aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAngelo Marletta <angelo.marletta@gmail.com>2012-06-15 03:18:03 +0100
committerAngelo Marletta <angelo.marletta@gmail.com>2012-06-15 03:18:03 +0100
commit5544c90d488caf7d19ee3d6c828cf0490e60a3a5 (patch)
tree81cf2fadbd31cf5fac385eb14d00d88697e48d5f /src
parentb774ed89bfeaf96905aaa85946771082302fc848 (diff)
downloadcpulimit-5544c90d488caf7d19ee3d6c828cf0490e60a3a5.tar.gz
added filter to process_iterator. process_group and everything else broken
Diffstat (limited to 'src')
-rw-r--r--src/Makefile17
-rw-r--r--src/process_group.c72
-rw-r--r--src/process_group.h47
-rw-r--r--src/process_iterator.c234
-rw-r--r--src/process_iterator.h38
5 files changed, 344 insertions, 64 deletions
diff --git a/src/Makefile b/src/Makefile
index 57be683..f7a71ed 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,7 +1,7 @@
CC?=gcc
-CFLAGS?=-Wall -O2 -D_GNU_SOURCE
+CFLAGS?=-Wall -g -D_GNU_SOURCE
TARGETS=cpulimit
-LIBS=process.o procutils.o list.o
+LIBS=procutils.o list.o process_iterator.o
UNAME := $(shell uname)
@@ -17,15 +17,18 @@ cpulimit: cpulimit.c $(LIBS)
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)
+list.o: list.c list.h
+ $(CC) -c list.c $(CFLAGS)
+
+process_group.o: process_group.c process_group.h process_iterator.o list.o
+ $(CC) -c process_group.c $(CFLAGS)
+
+#process.o: process.c process.h
+# $(CC) -c process.c $(CFLAGS)
procutils.o: procutils.c procutils.h
$(CC) -c procutils.c $(CFLAGS)
-list.o: list.c list.h
- $(CC) -c list.c $(CFLAGS)
-
clean:
rm -f *~ *.o $(TARGETS)
diff --git a/src/process_group.c b/src/process_group.c
new file mode 100644
index 0000000..b8b1155
--- /dev/null
+++ b/src/process_group.c
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+#include "process_group.h"
+#include "list.h"
+
+int init_process_monitor(struct process_monitor *monitor, int target_pid, int ignore_children)
+{
+ //hashtable initialization
+ memset(&monitor->proctable, 0, sizeof(monitor->proctable));
+ monitor->target_pid = target_pid;
+ monitor->ignore_children = ignore_children;
+ return 0;
+}
+
+struct list* get_process_list(struct process_monitor *monitor)
+{
+ struct process_iterator it;
+ struct process process;
+ init_process_iterator(&it);
+ while (read_next_process(&it, &process) != -1)
+ {
+ if (monitor->ignore_children && process.pid != monitor->target_pid) continue;
+ 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);
+ if (monitor->proctable[hashkey] == NULL)
+ {
+
+ if (is_ancestor(pid, ppid))
+ struct process *ancestor = NULL;
+ while((ancestor=seek_process(f, ppid))==NULL) {
+ ppid = getppid_of(ppid);
+ }
+
+
+ //empty bucket
+ monitor->proctable[hashkey] = malloc(sizeof(struct list));
+ struct process *new_process = malloc(sizeof(struct process));
+ memcpy(new_process, &process, sizeof(struct process));
+ init_list(monitor->proctable[hashkey], 4);
+ add_elem(monitor->proctable[hashkey], new_process);
+ }
+ else
+ {
+
+ }
+ }
+ close_process_iterator(&it);
+
+ return NULL;
+}
+
+int close_process_monitor(struct process_monitor *monitor)
+{
+ int i;
+ int size = sizeof(monitor->proctable) / sizeof(struct process*);
+ for (i=0; i<size; i++) {
+ if (monitor->proctable[i] != NULL) {
+ //free() history for each process
+ destroy_list(monitor->proctable[i]);
+ free(monitor->proctable[i]);
+ monitor->proctable[i] = NULL;
+ }
+ }
+ monitor->target_pid = 0;
+ return 0;
+} \ No newline at end of file
diff --git a/src/process_group.h b/src/process_group.h
new file mode 100644
index 0000000..eb4c5d8
--- /dev/null
+++ b/src/process_group.h
@@ -0,0 +1,47 @@
+/**
+ *
+ * cpulimit - a cpu limiter for Linux
+ *
+ * Copyright (C) 2005-2012, by: Angelo Marletta <marlonx80@hotmail.com>
+ *
+ * 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_MONITOR_H
+
+#define __PROCESS_MONITOR_H
+
+#include "process_iterator.h"
+
+#include "list.h"
+
+#define PIDHASH_SZ 1024
+#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
+
+struct process_monitor
+{
+ //hashtable with all the processes (array of struct list of struct process)
+ struct list *proctable[PIDHASH_SZ];
+ pid_t target_pid;
+ int ignore_children;
+};
+
+int init_process_monitor(struct process_monitor *monitor, int target_pid, int ignore_children);
+
+struct list* get_process_list(struct process_monitor *monitor);
+
+int close_process_monitor(struct process_monitor *monitor);
+
+#endif \ No newline at end of file
diff --git a/src/process_iterator.c b/src/process_iterator.c
index f0cee92..bacf914 100644
--- a/src/process_iterator.c
+++ b/src/process_iterator.c
@@ -5,62 +5,106 @@
#include "process_iterator.h"
-//TODO read this to port to other systems: http://www.steve.org.uk/Reference/Unix/faq_8.html#SEC85
+//See this link 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) {
+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) {
+ if ((it->dip = opendir("/proc")) == NULL)
+ {
perror("opendir");
return -1;
}
+ it->filter = filter;
return 0;
}
-int read_next_process(struct process_iterator *it, struct process *p) {
+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) * HZ;
+ token = strtok(NULL, " ");
+ p->cputime += atoi(token) * 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 read_next_process(struct process_iterator *it, struct process *p)
+{
+ if (it->filter->pid > 0 && !it->filter->include_children)
+ {
+ read_process_info(it->filter->pid, p);
+ return -1;
+ }
+ struct dirent *dit;
//read in from /proc and seek for process dirs
- while ((it->dit = readdir(it->dip)) != NULL) {
- if(strtok(it->dit->d_name, "0123456789") != NULL)
+ while ((dit = readdir(it->dip)) != NULL) {
+ if(strtok(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);
+ 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);
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)
+ if (dit == NULL)
{
//end of processes
closedir(it->dip);
@@ -75,11 +119,10 @@ int close_process_iterator(struct process_iterator *it) {
perror("closedir");
return 1;
}
+ it->dip = NULL;
return 0;
}
-#elif defined __APPLE__
-
#elif defined __FreeBSD__
#include <sys/sysctl.h>
@@ -87,23 +130,30 @@ int close_process_iterator(struct process_iterator *it) {
#include <fcntl.h>
#include <paths.h>
-int init_process_iterator(struct process_iterator *it) {
+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 ((it->kd = kvm_openfiles(NULL, _PATH_DEVNULL, NULL, O_RDONLY, errbuf)) == NULL) {
+ 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(it->kd, KERN_PROC_PROC, 0, &it->count)) == NULL) {
- kvm_close(it->kd);
+ 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(it->kd));
+ fprintf(stderr, "kvm_getprocs: %s", kvm_geterr(kd));
return -1;
}
- kvm_close(it->kd);
- it->i = 0;
+ kvm_close(kd);
+ static int request[2] = { CTL_KERN, KERN_BOOTTIME };
+ struct timeval result;
+ size_t result_len = sizeof result;
+ if (sysctl (request, 2, &result, &result_len, NULL, 0) < 0) return -1;
+ it->boot_time = result.tv_sec;
+ it->filter = filter;
return 0;
}
@@ -111,13 +161,97 @@ 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;
+ p->cputime = it->procs[it->i].ki_runtime / 1000;
+ p->starttime = it->procs[it->i].ki_start.tv_sec - it->boot_time;
it->i++;
+ if (it->i == it->count) return -1;
+ return 0;
+}
+
+int close_process_iterator(struct process_iterator *it) {
+ return 0;
+}
+
+#elif defined __APPLE__
+
+int init_process_iterator(struct process_iterator *it) {
return 0;
}
+int read_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;
+// }
+
+#elif defined __APPLE__
+
#endif
diff --git a/src/process_iterator.h b/src/process_iterator.h
index fc559d3..23af7ed 100644
--- a/src/process_iterator.h
+++ b/src/process_iterator.h
@@ -27,6 +27,24 @@
#include <limits.h>
#include <dirent.h>
+//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
+
#ifdef __FreeBSD__
#include <kvm.h>
#endif
@@ -39,8 +57,8 @@ struct process {
pid_t ppid;
//start time
int starttime;
- //total number of jiffies used by the process at time last_sample
- int last_jiffies;
+ //cputime used by the process expressed in milliseconds
+ int cputime;
//actual cpu usage estimation (value in range 0-1)
double cpu_usage;
//1 if the process is zombie
@@ -49,21 +67,27 @@ struct process {
char command[PATH_MAX+1];
};
+struct process_filter {
+ int pid;
+ int include_children;
+ char program_name[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;
+ int boot_time;
struct kinfo_proc *procs;
int count;
int i;
+#elif defined __APPLE__
+ struct kinfo_proc *procList;
#endif
+ struct process_filter *filter;
};
-int init_process_iterator(struct process_iterator *i);
+int init_process_iterator(struct process_iterator *i, struct process_filter *filter);
int read_next_process(struct process_iterator *i, struct process *p);
Un proyecto texto-plano.xyz