From 10c2915dd464de44047f182ecae9c8b34e24e772 Mon Sep 17 00:00:00 2001 From: Angelo Marletta Date: Thu, 7 Jun 2012 16:42:46 +0100 Subject: new cross-platform code to list processes. works on linux and freebsd --- src/Makefile | 5 +- src/process_iterator.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++ src/process_iterator.h | 72 +++++++++++++++++++++++++++++ src/procutils.c | 2 +- 4 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 src/process_iterator.c create mode 100644 src/process_iterator.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index bacec4b..57be683 100755 --- a/src/Makefile +++ b/src/Makefile @@ -9,11 +9,14 @@ ifeq ($(UNAME), FreeBSD) LIBS+=-lkvm endif -all:: $(TARGETS) +all:: $(TARGETS) process_iterator.o cpulimit: cpulimit.c $(LIBS) $(CC) -o cpulimit cpulimit.c $(LIBS) $(CFLAGS) +process_iterator.o: process_iterator.c process_iterator.h + $(CC) -c process_iterator.c $(CFLAGS) + process.o: process.c process.h $(CC) -c process.c $(CFLAGS) diff --git a/src/process_iterator.c b/src/process_iterator.c new file mode 100644 index 0000000..fd35952 --- /dev/null +++ b/src/process_iterator.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include + +#include "process_iterator.h" + +//TODO read this to port to other systems: http://www.steve.org.uk/Reference/Unix/faq_8.html#SEC85 + +#ifdef __linux__ + +int init_process_iterator(struct process_iterator *it) { + //open a directory stream to /proc directory + if ((it->dip = opendir("/proc")) == NULL) { + perror("opendir"); + return -1; + } + return 0; +} + +int read_next_process(struct process_iterator *it, struct process *p) { + char statfile[20]; + char buffer[1024]; + //read in from /proc and seek for process dirs + while ((it->dit = readdir(it->dip)) != NULL) { + if(strtok(it->dit->d_name, "0123456789") != NULL) + continue; + p->pid = atoi(it->dit->d_name); + //read stat file + sprintf(statfile, "/proc/%d/stat", p->pid); + FILE *fd = fopen(statfile, "r"); + if (fd==NULL) return -1; + if (fgets(buffer, sizeof(buffer), fd)==NULL) { + fclose(fd); + return -1; + } + fclose(fd); + char *token = strtok(buffer, " "); + int i; + for (i=0; i<3; i++) token = strtok(NULL, " "); + p->ppid = atoi(token); + for (i=0; i<10; i++) + token = strtok(NULL, " "); + p->last_jiffies = atoi(token); + token = strtok(NULL, " "); + p->last_jiffies += atoi(token); + for (i=0; i<7; i++) + token = strtok(NULL, " "); + p->starttime = atoi(token); + break; + //read command line + char exefile[20]; + sprintf(exefile,"/proc/%d/cmdline", p->pid); + fd = fopen(statfile, "r"); + char buffer[1024]; + if (fgets(buffer, sizeof(buffer), fd)==NULL) { + fclose(fd); + return -1; + } + fclose(fd); + sscanf(buffer, "%s", (char*)&p->command); + } + if (it->dit == NULL) + { + //end of processes + closedir(it->dip); + it->dip = NULL; + return -1; + } + return 0; +} + +int close_process_iterator(struct process_iterator *it) { + if (it->dip != 0 && closedir(it->dip) == -1) { + perror("closedir"); + return 1; + } + return 0; +} + +#elif defined __APPLE__ + +#elif defined __FreeBSD__ + +#include +#include + +int init_process_iterator(struct process_iterator *it) { + char errbuf[_POSIX2_LINE_MAX]; + /* Open the kvm interface, get a descriptor */ + if ((it->kd = kvm_open(NULL, NULL, NULL, 0, errbuf)) == NULL) { + /* fprintf(stderr, "kvm_open: %s\n", errbuf); */ + fprintf(stderr, "kvm_open: %s", errbuf); + return -1; + } + /* Get the list of processes. */ + if ((it->procs = kvm_getprocs(it->kd, KERN_PROC_PROC, 0, &it->count)) == NULL) { + kvm_close(it->kd); + /* fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(kd)); */ + fprintf(stderr, "kvm_getprocs: %s", kvm_geterr(it->kd)); + return -1; + } + kvm_close(it->kd); + it->i = 0; + return 0; +} + +int read_next_process(struct process_iterator *it, struct process *p) { + if (it->i == it->count) return -1; + p->pid = it->procs[it->i].ki_pid; + p->ppid = it->procs[it->i].ki_ppid; + p->last_jiffies = it->procs[it->i].ki_runtime / 1000; + it->i++; + return 0; +} + +int close_process_iterator(struct process_iterator *it) { + return 0; +} + +#endif diff --git a/src/process_iterator.h b/src/process_iterator.h new file mode 100644 index 0000000..fc559d3 --- /dev/null +++ b/src/process_iterator.h @@ -0,0 +1,72 @@ +/** + * + * cpulimit - a cpu limiter for Linux + * + * Copyright (C) 2005-2012, by: Angelo Marletta + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __PROCESS_ITERATOR_H + +#define __PROCESS_ITERATOR_H + +#include +#include +#include + +#ifdef __FreeBSD__ +#include +#endif + +// process descriptor +struct process { + //pid of the process + pid_t pid; + //pid of the process + pid_t ppid; + //start time + int starttime; + //total number of jiffies used by the process at time last_sample + int last_jiffies; + //actual cpu usage estimation (value in range 0-1) + double cpu_usage; + //1 if the process is zombie + int is_zombie; + //absolute path of the executable file + char command[PATH_MAX+1]; +}; + +struct process_iterator { +#ifdef __linux__ + DIR *dip; + struct dirent *dit; +#elif defined __APPLE__ + struct kinfo_proc *procList; +#elif defined __FreeBSD__ + kvm_t *kd; + struct kinfo_proc *procs; + int count; + int i; +#endif +}; + +int init_process_iterator(struct process_iterator *i); + +int read_next_process(struct process_iterator *i, struct process *p); + +int close_process_iterator(struct process_iterator *i); + +#endif diff --git a/src/procutils.c b/src/procutils.c index 19b7054..7367196 100644 --- a/src/procutils.c +++ b/src/procutils.c @@ -69,7 +69,7 @@ static pid_t getppid_of(pid_t pid) get_proc_info(&p, pid); return p.ppid; #elif defined __FreeBSD__ - + #endif } -- cgit v1.2.3