From b8bc055ee5131c333af3422569bde24bb760ac65 Mon Sep 17 00:00:00 2001 From: Angelo Marletta Date: Sat, 23 Jun 2012 12:57:42 +0100 Subject: full command line is detected on freebsd. deleted old files. all tests pass on linux and freebsd --- src/process.c | 265 ----------------------------------------- src/process.h | 88 -------------- src/process_iterator.h | 1 + src/process_iterator_freebsd.c | 54 +++++---- 4 files changed, 29 insertions(+), 379 deletions(-) delete mode 100644 src/process.c delete mode 100644 src/process.h (limited to 'src') diff --git a/src/process.c b/src/process.c deleted file mode 100644 index 53226a7..0000000 --- a/src/process.c +++ /dev/null @@ -1,265 +0,0 @@ -/** - * - * cpulimit - a cpu limiter for Linux - * - * Copyright (C) 2005-2008, 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. - */ - -//TODO: add documentation to public functions - -#include -#include -#include -#include -#include -#include -#include - -#include "process.h" - -#ifdef __APPLE__ -#include -#include -#endif - -#ifdef __FreeBSD__ -#include -#include -#include -#include -#include -#include -#include -#endif - -#ifdef __linux__ -int get_proc_info(struct process *p, pid_t pid) { -/* static char statfile[20]; - static char buffer[64]; - int ret; - sprintf(statfile, "/proc/%d/stat", pid); - FILE *fd = fopen(statfile, "r"); - if (fd==NULL) return -1; - fgets(buffer, sizeof(buffer), fd); - fclose(fd); - - char state; - - int n = sscanf(buffer, "%d %s %c %d %d %d %d %d " - "%lu %lu %lu %lu %lu %lu %lu " - "%ld %ld %ld %ld %ld %ld " - "%lu ", - &p->pid, - &p->command, - &state, - NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, - &utime,&stime,&cutime,&cstime, - NULL,NULL,NULL,NULL, - &starttime, - );*/ - return 0; -} -#elif defined __APPLE__ -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; -} -#endif - -// returns the start time of a process (used with pid to identify a process) -static int get_starttime(pid_t pid) -{ -#ifdef __linux__ - char file[20]; - char buffer[1024]; - sprintf(file, "/proc/%d/stat", pid); - FILE *fd = fopen(file, "r"); - if (fd==NULL) return -1; - if (fgets(buffer, sizeof(buffer), fd) == NULL) return -1; - fclose(fd); - char *p = buffer; - p = memchr(p+1,')', sizeof(buffer) - (p-buffer)); - int sp = 20; - while (sp--) - p = memchr(p+1,' ',sizeof(buffer) - (p-buffer)); - //start time of the process - int time = atoi(p+1); - return time; -#elif defined __APPLE__ - struct process proc; - get_proc_info(&proc, pid); - return proc.starttime; -#elif defined __FreeBSD__ - return -1; -#endif -} - -static int get_jiffies(struct process *proc) { -#ifdef __linux__ - FILE *f = fopen(proc->stat_file, "r"); - if (f==NULL) return -1; - if (fgets(proc->buffer, sizeof(proc->buffer),f) == NULL) return -1; - fclose(f); - char *p = proc->buffer; - p = memchr(p+1,')', sizeof(proc->buffer) - (p-proc->buffer)); - int sp = 12; - while (sp--) - p = memchr(p+1,' ',sizeof(proc->buffer) - (p-proc->buffer)); - //user mode jiffies - int utime = atoi(p+1); - p = memchr(p+1,' ',sizeof(proc->buffer) - (p-proc->buffer)); - //kernel mode jiffies - int ktime = atoi(p+1); - return utime+ktime; -#elif defined __APPLE__ - struct process proc2; - get_proc_info(&proc2, proc->pid); - return proc2.last_jiffies; -#elif defined __FreeBSD__ - kvm_t *my_kernel = NULL; - struct kinfo_proc *process_data = NULL; - int processes; - int my_jiffies = -1; - my_kernel = kvm_open(0, 0, 0, O_RDONLY, "kvm_open"); - if (! my_kernel) - { - printf("Error opening kernel vm. You should be running as root.\n"); - return -1; - } - - process_data = kvm_getprocs(my_kernel, KERN_PROC_PID, proc->pid, &processes); - if ( (process_data) && (processes >= 1) ) - my_jiffies = process_data->ki_runtime; - - kvm_close(my_kernel); - if (my_jiffies >= 0) - my_jiffies /= 1000; - return my_jiffies; -#endif -} - -//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); -} - -/*static int*/ int process_update(struct process *proc) { - //TODO: get any process statistic here - //check that starttime is not changed(?), update jiffies, parent, zombie status - return 0; -} - -int process_init(struct process *proc, int pid) -{ - //general members - proc->pid = pid; - proc->starttime = get_starttime(pid); - proc->cpu_usage = 0; - memset(&(proc->last_sample), 0, sizeof(struct timeval)); - proc->last_jiffies = -1; - //system dependent members -#ifdef __linux__ -//TODO: delete these members for the sake of portability? - //test /proc file descriptor for reading - sprintf(proc->stat_file, "/proc/%d/stat", pid); - FILE *fd = fopen(proc->stat_file, "r"); - if (fd == NULL) return 1; - fclose(fd); -#endif - return 0; -} - -//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; -} - -int process_close(struct process *proc) -{ - if (kill(proc->pid,SIGCONT)!=0) { - fprintf(stderr,"Process %d is already dead!\n", proc->pid); - } - proc->pid = 0; - return 0; -} diff --git a/src/process.h b/src/process.h deleted file mode 100644 index 0280ad6..0000000 --- a/src/process.h +++ /dev/null @@ -1,88 +0,0 @@ -/** - * - * cpulimit - a cpu limiter for Linux - * - * Copyright (C) 2005-2008, 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_H - -#define __PROCESS_H - -#include -#include -#include - -//USER_HZ detection, from openssl code -#ifndef HZ -# if defined(_SC_CLK_TCK) \ - && (!defined(OPENSSL_SYS_VMS) || __CTRL_VER >= 70000000) -# define HZ ((double)sysconf(_SC_CLK_TCK)) -# else -# ifndef CLK_TCK -# ifndef _BSD_CLK_TCK_ /* FreeBSD hack */ -# define HZ 100.0 -# else /* _BSD_CLK_TCK_ */ -# define HZ ((double)_BSD_CLK_TCK_) -# endif -# else /* CLK_TCK */ -# define HZ ((double)CLK_TCK) -# endif -# endif -#endif - -// process descriptor -struct process { - //pid of the process - pid_t pid; - //pid of the process - pid_t ppid; - //start time - int starttime; - //is member of the family? - int member; //TODO: delete this field - //total number of jiffies used by the process at time last_sample - int last_jiffies; - //timestamp when last_jiffies and cpu_usage was calculated - struct timeval last_sample; - //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]; - - //system-dependent members -//TODO: delete these members for the sake of portability? -#ifdef __linux__ - //preallocate buffers for performance - //name of /proc/PID/stat file - char stat_file[20]; - //read buffer for /proc filesystem - char buffer[1024]; -#endif -}; - -int get_proc_info(struct process *p, pid_t pid); - -int process_init(struct process *proc, pid_t pid); - -int process_monitor(struct process *proc); - -int process_close(struct process *proc); - -#endif diff --git a/src/process_iterator.h b/src/process_iterator.h index 39379b8..82fadac 100644 --- a/src/process_iterator.h +++ b/src/process_iterator.h @@ -76,6 +76,7 @@ struct process_iterator { DIR *dip; int boot_time; #elif defined __FreeBSD__ + kvm_t *kd; struct kinfo_proc *procs; int count; int i; diff --git a/src/process_iterator_freebsd.c b/src/process_iterator_freebsd.c index e840968..eb6cfaa 100644 --- a/src/process_iterator_freebsd.c +++ b/src/process_iterator_freebsd.c @@ -4,55 +4,46 @@ #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); + if ((it->kd = kvm_openfiles(NULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf)) == NULL) { + fprintf(stderr, "kvm_open: %s\n", 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)); + 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(it->kd)); return -1; } - kvm_close(kd); it->filter = filter; return 0; } -static void kproc2proc(struct kinfo_proc *kproc, struct process *proc) +static void kproc2proc(kvm_t *kd, 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; - memcpy(proc->command, kproc->ki_comm, strlen(kproc->ki_comm)); + char **args = kvm_getargv(kd, kproc, sizeof(proc->command)); + if (args != NULL) + { + memcpy(proc->command, args[0], strlen(args[0]) + 1); + } } -static int get_single_process(pid_t pid, struct process *process) +static int get_single_process(kvm_t *kd, 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)); + fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(kd)); return -1; } - kproc2proc(kproc, process); + kproc2proc(kd, kproc, process); return 0; } @@ -63,15 +54,22 @@ int get_next_process(struct process_iterator *it, struct process *p) { } if (it->filter->pid > 0 && !it->filter->include_children) { - get_single_process(it->filter->pid, p); + get_single_process(it->kd, it->filter->pid, p); it->i = it->count = 1; return 0; } while (it->i < it->count) { + struct kinfo_proc *kproc = &(it->procs[it->i]); + if (kproc->ki_flag & P_SYSTEM) + { + // skip system processes + it->i++; + continue; + } if (it->filter->pid > 0 && it->filter->include_children) { - kproc2proc(&(it->procs[it->i]), p); + kproc2proc(it->kd, kproc, p); it->i++; if (p->pid != it->filter->pid && p->ppid != it->filter->pid) continue; @@ -79,7 +77,7 @@ int get_next_process(struct process_iterator *it, struct process *p) { } else if (it->filter->pid == 0) { - kproc2proc(&(it->procs[it->i]), p); + kproc2proc(it->kd, kproc, p); it->i++; return 0; } @@ -88,6 +86,10 @@ int get_next_process(struct process_iterator *it, struct process *p) { } int close_process_iterator(struct process_iterator *it) { + if (kvm_close(it->kd) == -1) { + fprintf(stderr, "kvm_getprocs: %s\n", kvm_geterr(it->kd)); + return -1; + } return 0; } -- cgit v1.2.3