From ce079fc58d6d30c3fe400a777934b4a4cce85761 Mon Sep 17 00:00:00 2001 From: Angelo Marletta Date: Thu, 21 Jun 2012 02:06:58 +0100 Subject: multiplatform refactoring. added more tests. works but there is a fd leak. --- src/list.c | 2 +- src/list.h | 2 +- src/process_group.c | 110 ++++++++++++-- src/process_group.h | 1 + src/process_iterator.c | 315 +---------------------------------------- src/process_iterator.h | 8 +- src/process_iterator_apple.c | 77 ++++++++++ src/process_iterator_freebsd.c | 92 ++++++++++++ src/process_iterator_linux.c | 142 +++++++++++++++++++ 9 files changed, 423 insertions(+), 326 deletions(-) create mode 100644 src/process_iterator_apple.c create mode 100644 src/process_iterator_freebsd.c create mode 100644 src/process_iterator_linux.c (limited to 'src') diff --git a/src/list.c b/src/list.c index 49f84ce..6fe1e06 100644 --- a/src/list.c +++ b/src/list.c @@ -127,7 +127,7 @@ void *locate_elem(struct list *l,void *elem) { return(xlocate_elem(l,elem,0,0)); } -void flush_list(struct list *l) { +void clear_list(struct list *l) { struct list_node *tmp; while(l->first!=EMPTYLIST) { tmp=l->first; diff --git a/src/list.h b/src/list.h index 387f79c..478635f 100644 --- a/src/list.h +++ b/src/list.h @@ -133,7 +133,7 @@ void *locate_elem(struct list *l,void *elem); /* * Delete all the elements in the list */ -void flush_list(struct list *l); +void clear_list(struct list *l); /* * Delete every element in the list, and free the memory pointed by all the node data diff --git a/src/process_group.c b/src/process_group.c index 2afef71..043ee69 100644 --- a/src/process_group.c +++ b/src/process_group.c @@ -2,6 +2,9 @@ #include #include #include +#include + +#include #include "process_iterator.h" #include "process_group.h" @@ -14,6 +17,8 @@ int init_process_group(struct process_group *pgroup, int target_pid, int include pgroup->target_pid = target_pid; pgroup->include_children = include_children; pgroup->proclist = (struct list*)malloc(sizeof(struct list)); + init_list(pgroup->proclist, 4); + memset(&pgroup->last_update, 0, sizeof(pgroup->last_update)); return 0; } @@ -29,40 +34,127 @@ int close_process_group(struct process_group *pgroup) pgroup->proctable[i] = NULL; } } + clear_list(pgroup->proclist); free(pgroup->proclist); pgroup->proclist = NULL; return 0; } +void remove_terminated_processes(struct process_group *pgroup) +{ + //TODO +} + +//return t1-t2 in microseconds (no overflow checks, so better watch out!) +static inline unsigned long timediff(const struct timeval *t1,const struct timeval *t2) +{ + return (t1->tv_sec - t2->tv_sec) * 1000000 + (t1->tv_usec - t2->tv_usec); +} + +//parameter in range 0-1 +#define ALFA 0.08 + +int process_monitor(struct process *proc) +{ + // int j = get_jiffies(proc); + // if (j<0) return -1; //error retrieving jiffies count (maybe the process is dead) + // struct timeval now; + // gettimeofday(&now, NULL); + // if (proc->last_jiffies==-1) { + // //store current time + // proc->last_sample = now; + // //store current jiffies + // proc->last_jiffies = j; + // //it's the first sample, cannot figure out the cpu usage + // proc->cpu_usage = -1; + // return 0; + // } + // //time from previous sample (in ns) + // long dt = timediff(&now, &(proc->last_sample)); + // //how many jiffies in dt? + // double max_jiffies = dt * HZ / 1000000.0; + // double sample = (j - proc->last_jiffies) / max_jiffies; + // if (proc->cpu_usage == -1) { + // //initialization + // proc->cpu_usage = sample; + // } + // else { + // //usage adjustment + // proc->cpu_usage = (1-ALFA) * proc->cpu_usage + ALFA * sample; + // } + // //store current time + // proc->last_sample = now; + // //store current jiffies + // proc->last_jiffies = j; + return 0; +} + void update_process_group(struct process_group *pgroup) { struct process_iterator it; - struct process process; + struct process tmp_process; struct process_filter filter; filter.pid = pgroup->target_pid; filter.include_children = pgroup->include_children; init_process_iterator(&it, &filter); - while (get_next_process(&it, &process) != -1) + clear_list(pgroup->proclist); + init_list(pgroup->proclist, 4); + struct timeval now; + gettimeofday(&now, NULL); + //time elapsed from previous sample (in ms) + long dt = timediff(&now, &pgroup->last_update) / 1000; + while (get_next_process(&it, &tmp_process) != -1) { - printf("Read process %d\n", process.pid); - printf("Parent %d\n", process.ppid); - printf("Starttime %d\n", process.starttime); - printf("CPU time %d\n", process.cputime); - int hashkey = pid_hashfn(process.pid + process.starttime); + // printf("Read process %d\n", tmp_process.pid); + // printf("Parent %d\n", tmp_process.ppid); + // printf("Starttime %d\n", tmp_process.starttime); + // printf("CPU time %d\n", tmp_process.cputime); + int hashkey = pid_hashfn(tmp_process.pid + tmp_process.starttime); if (pgroup->proctable[hashkey] == NULL) { //empty bucket pgroup->proctable[hashkey] = malloc(sizeof(struct list)); struct process *new_process = malloc(sizeof(struct process)); - memcpy(new_process, &process, sizeof(struct process)); + tmp_process.cpu_usage = -1; + memcpy(new_process, &tmp_process, sizeof(struct process)); init_list(pgroup->proctable[hashkey], 4); add_elem(pgroup->proctable[hashkey], new_process); + add_elem(pgroup->proclist, new_process); } else { //existing bucket - + struct process *p = (struct process*)locate_elem(pgroup->proctable[hashkey], &tmp_process); + if (p == NULL) + { + //process is new. add it + struct process *new_process = malloc(sizeof(struct process)); + tmp_process.cpu_usage = -1; + memcpy(new_process, &tmp_process, sizeof(struct process)); + add_elem(pgroup->proctable[hashkey], new_process); + add_elem(pgroup->proclist, new_process); + } + else + { + assert(tmp_process.pid == p->pid); + assert(tmp_process.ppid == p->ppid); + assert(tmp_process.starttime == p->starttime); + //process exists. update CPU usage + double sample = (tmp_process.cputime - p->cputime) / dt; + if (p->cpu_usage == -1) { + //initialization + p->cpu_usage = sample; + } + else { + //usage adjustment + p->cpu_usage = (1-ALFA) * p->cpu_usage + ALFA * sample; + } + p->cpu_usage = (1-ALFA) * p->cpu_usage + ALFA * sample; + p->cputime = tmp_process.cputime; + add_elem(pgroup->proclist, p); + } } } close_process_iterator(&it); + pgroup->last_update = now; } diff --git a/src/process_group.h b/src/process_group.h index 27c3352..f26d2cb 100644 --- a/src/process_group.h +++ b/src/process_group.h @@ -37,6 +37,7 @@ struct process_group struct list *proclist; pid_t target_pid; int include_children; + struct timeval last_update; }; int init_process_group(struct process_group *pgroup, int target_pid, int include_children); diff --git a/src/process_iterator.c b/src/process_iterator.c index e27ed4c..0e31c81 100644 --- a/src/process_iterator.c +++ b/src/process_iterator.c @@ -9,323 +9,18 @@ #ifdef __linux__ -static int get_boot_time() -{ - int uptime; - FILE *fp = fopen ("/proc/uptime", "r"); - if (fp != NULL) - { - char buf[BUFSIZ]; - char *b = fgets(buf, BUFSIZ, fp); - if (b == buf) - { - char *end_ptr; - double upsecs = strtod(buf, &end_ptr); - uptime = (int)upsecs; - } - fclose (fp); - } - time_t now = time(NULL); - return now - uptime; -} - -int init_process_iterator(struct process_iterator *it, struct process_filter *filter) -{ - //open a directory stream to /proc directory - if ((it->dip = opendir("/proc")) == NULL) - { - perror("opendir"); - return -1; - } - it->filter = filter; - it->boot_time = get_boot_time(); - return 0; -} - -static int read_process_info(pid_t pid, struct process *p) -{ - static char buffer[1024]; - static char statfile[32]; - static char exefile[1024]; - p->pid = pid; - //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->cputime = atoi(token) * 1000 / HZ; - token = strtok(NULL, " "); - p->cputime += atoi(token) * 1000 / HZ; - for (i=0; i<7; i++) - token = strtok(NULL, " "); - p->starttime = atoi(token) / sysconf(_SC_CLK_TCK); - //read command line - sprintf(exefile,"/proc/%d/cmdline", p->pid); - fd = fopen(statfile, "r"); - if (fgets(buffer, sizeof(buffer), fd)==NULL) { - fclose(fd); - return -1; - } - fclose(fd); - sscanf(buffer, "%s", (char*)&p->command); - return 0; -} - -static pid_t getppid_of(pid_t pid) -{ - char statfile[20]; - char buffer[1024]; - sprintf(statfile, "/proc/%d/stat", 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, " "); - return atoi(token); -} - -static int is_child_of(pid_t child_pid, pid_t parent_pid) -{ - int ppid = child_pid; - while(ppid > 1 && ppid != parent_pid) { - ppid = getppid_of(ppid); - } - return ppid == parent_pid; -} - -int get_next_process(struct process_iterator *it, struct process *p) -{ - if (it->dip == NULL) - { - //end of processes - return -1; - } - if (it->filter->pid > 0 && !it->filter->include_children) - { - read_process_info(it->filter->pid, p); - p->starttime += it->boot_time; - it->dip = NULL; - return 0; - } - struct dirent *dit; - //read in from /proc and seek for process dirs - while ((dit = readdir(it->dip)) != NULL) { - if(strtok(dit->d_name, "0123456789") != NULL) - continue; - p->pid = atoi(dit->d_name); - if (it->filter->pid > 0 && it->filter->pid != p->pid && !is_child_of(p->pid, it->filter->pid)) continue; - read_process_info(p->pid, p); - p->starttime += it->boot_time; - break; - } - if (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; - } - it->dip = NULL; - return 0; -} +#include "process_iterator_linux.c" #elif defined __FreeBSD__ -#include -#include -#include -#include - -int init_process_iterator(struct process_iterator *it, struct process_filter *filter) { - kvm_t *kd; - char errbuf[_POSIX2_LINE_MAX]; - it->i = 0; - /* Open the kvm interface, get a descriptor */ - if ((kd = kvm_openfiles(NULL, _PATH_DEVNULL, NULL, O_RDONLY, 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(kd, KERN_PROC_PROC, 0, &it->count)) == NULL) { - kvm_close(kd); - /* fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(kd)); */ - fprintf(stderr, "kvm_getprocs: %s", kvm_geterr(kd)); - return -1; - } - kvm_close(kd); - it->filter = filter; - return 0; -} - -static void kproc2proc(struct kinfo_proc *kproc, struct process *proc) -{ - proc->pid = kproc->ki_pid; - proc->ppid = kproc->ki_ppid; - proc->cputime = kproc->ki_runtime / 1000; - proc->starttime = kproc->ki_start.tv_sec; -} - -static int get_single_process(pid_t pid, struct process *process) -{ - kvm_t *kd; - int count; - char errbuf[_POSIX2_LINE_MAX]; - /* Open the kvm interface, get a descriptor */ - if ((kd = kvm_openfiles(NULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf)) == NULL) { - /* fprintf(stderr, "kvm_open: %s\n", errbuf); */ - fprintf(stderr, "kvm_open: %s", errbuf); - return -1; - } - struct kinfo_proc *kproc = kvm_getprocs(kd, KERN_PROC_PID, pid, &count); - kvm_close(kd); - if (count == 0 || kproc == NULL) - { - fprintf(stderr, "kvm_getprocs: %s", kvm_geterr(kd)); - return -1; - } - kproc2proc(kproc, process); - return 0; -} - -int get_next_process(struct process_iterator *it, struct process *p) { - if (it->i == it->count) - { - return -1; - } - if (it->filter->pid > 0 && !it->filter->include_children) - { - get_single_process(it->filter->pid, p); - it->i = it->count = 1; - return 0; - } - while (it->i < it->count) - { - if (it->filter->pid > 0 && it->filter->include_children) - { - kproc2proc(&(it->procs[it->i]), p); - it->i++; - if (p->pid != it->filter->pid && p->ppid != it->filter->pid) - continue; - return 0; - } - else if (it->filter->pid == 0) - { - kproc2proc(&(it->procs[it->i]), p); - it->i++; - return 0; - } - } - return -1; -} - -int close_process_iterator(struct process_iterator *it) { - return 0; -} +#include "process_iterator_freebsd.c" #elif defined __APPLE__ -int init_process_iterator(struct process_iterator *it) { - return 0; -} - -int get_next_process(struct process_iterator *it, struct process *p) { - return -1; -} - -int close_process_iterator(struct process_iterator *it) { - return 0; -} - - // int err; - // struct kinfo_proc *result = NULL; - // size_t length; - // int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; - - // /* We start by calling sysctl with result == NULL and length == 0. - // That will succeed, and set length to the appropriate length. - // We then allocate a buffer of that size and call sysctl again - // with that buffer. - // */ - // length = 0; - // err = sysctl(mib, 4, NULL, &length, NULL, 0); - // if (err == -1) { - // err = errno; - // } - // if (err == 0) { - // result = malloc(length); - // err = sysctl(mib, 4, result, &length, NULL, 0); - // if (err == -1) - // err = errno; - // if (err == ENOMEM) { - // free(result); /* clean up */ - // result = NULL; - // } - // } +#include "process_iterator_apple.c" - // i->proclist = result; - // i->count = err == 0 ? length / sizeof *result : 0; - // i->c = 0; +#else -// int get_proc_info(struct process *p, pid_t pid) { -// int err; -// struct kinfo_proc *result = NULL; -// size_t length; -// int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; - -// /* We start by calling sysctl with result == NULL and length == 0. -// That will succeed, and set length to the appropriate length. -// We then allocate a buffer of that size and call sysctl again -// with that buffer. -// */ -// length = 0; -// err = sysctl(mib, 4, NULL, &length, NULL, 0); -// if (err == -1) { -// err = errno; -// } -// if (err == 0) { -// result = malloc(length); -// err = sysctl(mib, 4, result, &length, NULL, 0); -// if (err == -1) -// err = errno; -// if (err == ENOMEM) { -// free(result); /* clean up */ -// result = NULL; -// } -// } - -// p->pid = result->kp_proc.p_pid; -// p->ppid = result->kp_eproc.e_ppid; -// p->starttime = result->kp_proc.p_starttime.tv_sec; -// p->last_jiffies = result->kp_proc.p_cpticks; -// //p_pctcpu - -// return 0; -// } - -#elif defined __APPLE__ +#error Platform not supported #endif diff --git a/src/process_iterator.h b/src/process_iterator.h index 1747644..39379b8 100644 --- a/src/process_iterator.h +++ b/src/process_iterator.h @@ -53,16 +53,14 @@ struct process { //pid of the process pid_t pid; - //pid of the process + //ppid of the process pid_t ppid; - //start time + //start time (unix timestamp) int starttime; - //cputime used by the process expressed in milliseconds + //cputime used by the process (in milliseconds) int cputime; //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]; }; diff --git a/src/process_iterator_apple.c b/src/process_iterator_apple.c new file mode 100644 index 0000000..ee574e7 --- /dev/null +++ b/src/process_iterator_apple.c @@ -0,0 +1,77 @@ +int init_process_iterator(struct process_iterator *it) { + return 0; +} + +int get_next_process(struct process_iterator *it, struct process *p) { + return -1; +} + +int close_process_iterator(struct process_iterator *it) { + return 0; +} + + // int err; + // struct kinfo_proc *result = NULL; + // size_t length; + // int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; + + // /* We start by calling sysctl with result == NULL and length == 0. + // That will succeed, and set length to the appropriate length. + // We then allocate a buffer of that size and call sysctl again + // with that buffer. + // */ + // length = 0; + // err = sysctl(mib, 4, NULL, &length, NULL, 0); + // if (err == -1) { + // err = errno; + // } + // if (err == 0) { + // result = malloc(length); + // err = sysctl(mib, 4, result, &length, NULL, 0); + // if (err == -1) + // err = errno; + // if (err == ENOMEM) { + // free(result); /* clean up */ + // result = NULL; + // } + // } + + // i->proclist = result; + // i->count = err == 0 ? length / sizeof *result : 0; + // i->c = 0; + +// int get_proc_info(struct process *p, pid_t pid) { +// int err; +// struct kinfo_proc *result = NULL; +// size_t length; +// int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + +// /* We start by calling sysctl with result == NULL and length == 0. +// That will succeed, and set length to the appropriate length. +// We then allocate a buffer of that size and call sysctl again +// with that buffer. +// */ +// length = 0; +// err = sysctl(mib, 4, NULL, &length, NULL, 0); +// if (err == -1) { +// err = errno; +// } +// if (err == 0) { +// result = malloc(length); +// err = sysctl(mib, 4, result, &length, NULL, 0); +// if (err == -1) +// err = errno; +// if (err == ENOMEM) { +// free(result); /* clean up */ +// result = NULL; +// } +// } + +// p->pid = result->kp_proc.p_pid; +// p->ppid = result->kp_eproc.e_ppid; +// p->starttime = result->kp_proc.p_starttime.tv_sec; +// p->last_jiffies = result->kp_proc.p_cpticks; +// //p_pctcpu + +// return 0; +// } diff --git a/src/process_iterator_freebsd.c b/src/process_iterator_freebsd.c new file mode 100644 index 0000000..fae671d --- /dev/null +++ b/src/process_iterator_freebsd.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include + +int init_process_iterator(struct process_iterator *it, struct process_filter *filter) { + kvm_t *kd; + char errbuf[_POSIX2_LINE_MAX]; + it->i = 0; + /* Open the kvm interface, get a descriptor */ + if ((kd = kvm_openfiles(NULL, _PATH_DEVNULL, NULL, O_RDONLY, 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(kd, KERN_PROC_PROC, 0, &it->count)) == NULL) { + kvm_close(kd); + /* fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(kd)); */ + fprintf(stderr, "kvm_getprocs: %s", kvm_geterr(kd)); + return -1; + } + kvm_close(kd); + it->filter = filter; + return 0; +} + +static void kproc2proc(struct kinfo_proc *kproc, struct process *proc) +{ + proc->pid = kproc->ki_pid; + proc->ppid = kproc->ki_ppid; + proc->cputime = kproc->ki_runtime / 1000; + proc->starttime = kproc->ki_start.tv_sec; +} + +static int get_single_process(pid_t pid, struct process *process) +{ + kvm_t *kd; + int count; + char errbuf[_POSIX2_LINE_MAX]; + /* Open the kvm interface, get a descriptor */ + if ((kd = kvm_openfiles(NULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf)) == NULL) { + /* fprintf(stderr, "kvm_open: %s\n", errbuf); */ + fprintf(stderr, "kvm_open: %s", errbuf); + return -1; + } + struct kinfo_proc *kproc = kvm_getprocs(kd, KERN_PROC_PID, pid, &count); + kvm_close(kd); + if (count == 0 || kproc == NULL) + { + fprintf(stderr, "kvm_getprocs: %s", kvm_geterr(kd)); + return -1; + } + kproc2proc(kproc, process); + return 0; +} + +int get_next_process(struct process_iterator *it, struct process *p) { + if (it->i == it->count) + { + return -1; + } + if (it->filter->pid > 0 && !it->filter->include_children) + { + get_single_process(it->filter->pid, p); + it->i = it->count = 1; + return 0; + } + while (it->i < it->count) + { + if (it->filter->pid > 0 && it->filter->include_children) + { + kproc2proc(&(it->procs[it->i]), p); + it->i++; + if (p->pid != it->filter->pid && p->ppid != it->filter->pid) + continue; + return 0; + } + else if (it->filter->pid == 0) + { + kproc2proc(&(it->procs[it->i]), p); + it->i++; + return 0; + } + } + return -1; +} + +int close_process_iterator(struct process_iterator *it) { + return 0; +} + diff --git a/src/process_iterator_linux.c b/src/process_iterator_linux.c new file mode 100644 index 0000000..34170e9 --- /dev/null +++ b/src/process_iterator_linux.c @@ -0,0 +1,142 @@ +static int get_boot_time() +{ + int uptime; + FILE *fp = fopen ("/proc/uptime", "r"); + if (fp != NULL) + { + char buf[BUFSIZ]; + char *b = fgets(buf, BUFSIZ, fp); + if (b == buf) + { + char *end_ptr; + double upsecs = strtod(buf, &end_ptr); + uptime = (int)upsecs; + } + fclose (fp); + } + time_t now = time(NULL); + return now - uptime; +} + +int init_process_iterator(struct process_iterator *it, struct process_filter *filter) +{ + //open a directory stream to /proc directory + if ((it->dip = opendir("/proc")) == NULL) + { + perror("opendir"); + return -1; + } + it->filter = filter; + it->boot_time = get_boot_time(); + return 0; +} + +static int read_process_info(pid_t pid, struct process *p) +{ + static char buffer[1024]; + static char statfile[32]; + static char exefile[1024]; + p->pid = pid; + //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->cputime = atoi(token) * 1000 / HZ; + token = strtok(NULL, " "); + p->cputime += atoi(token) * 1000 / HZ; + for (i=0; i<7; i++) + token = strtok(NULL, " "); + p->starttime = atoi(token) / sysconf(_SC_CLK_TCK); + //read command line + sprintf(exefile,"/proc/%d/cmdline", p->pid); + fd = fopen(statfile, "r"); + if (fgets(buffer, sizeof(buffer), fd)==NULL) { + fclose(fd); + return -1; + } + fclose(fd); + sscanf(buffer, "%s", (char*)&p->command); + return 0; +} + +static pid_t getppid_of(pid_t pid) +{ + char statfile[20]; + char buffer[1024]; + sprintf(statfile, "/proc/%d/stat", 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, " "); + return atoi(token); +} + +static int is_child_of(pid_t child_pid, pid_t parent_pid) +{ + int ppid = child_pid; + while(ppid > 1 && ppid != parent_pid) { + ppid = getppid_of(ppid); + } + return ppid == parent_pid; +} + +int get_next_process(struct process_iterator *it, struct process *p) +{ + if (it->dip == NULL) + { + //end of processes + return -1; + } + if (it->filter->pid > 0 && !it->filter->include_children) + { + read_process_info(it->filter->pid, p); + //p->starttime += it->boot_time; + it->dip = NULL; + return 0; + } + struct dirent *dit; + //read in from /proc and seek for process dirs + while ((dit = readdir(it->dip)) != NULL) { + if(strtok(dit->d_name, "0123456789") != NULL) + continue; + p->pid = atoi(dit->d_name); + if (it->filter->pid > 0 && it->filter->pid != p->pid && !is_child_of(p->pid, it->filter->pid)) continue; + read_process_info(p->pid, p); + //p->starttime += it->boot_time; + break; + } + if (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 != NULL && closedir(it->dip) == -1) { + perror("closedir"); + return 1; + } + it->dip = NULL; + return 0; +} -- cgit v1.2.3