diff options
author | bhackerozzo <bhackerozzo@3b445381-d045-0410-9223-e17ecdb95f4b> | 2008-09-06 19:04:45 +0000 |
---|---|---|
committer | bhackerozzo <bhackerozzo@3b445381-d045-0410-9223-e17ecdb95f4b> | 2008-09-06 19:04:45 +0000 |
commit | a1f006a43cdc6d73579321845752b6afcfbd8b0e (patch) | |
tree | 5441328842631f8d889462c07393a2dfdb355531 | |
parent | c7534b4eacfbc642f986d0039de7f757f6b5bcca (diff) | |
download | cpulimit-a1f006a43cdc6d73579321845752b6afcfbd8b0e.tar.gz |
process_history deleted, macosx code updated
-rw-r--r-- | cpulimit.c | 96 | ||||
-rw-r--r-- | process.c | 79 | ||||
-rw-r--r-- | process.h | 31 | ||||
-rw-r--r-- | procutils.c | 98 | ||||
-rw-r--r-- | procutils.h | 21 | ||||
-rw-r--r-- | tools/jiffy.c | 69 | ||||
-rw-r--r-- | tools/loop.c | 3 | ||||
-rw-r--r-- | tools/ptest.c | 58 |
8 files changed, 164 insertions, 291 deletions
@@ -32,7 +32,7 @@ * - cpu count detection, i.e. if you have 4 cpu, it is possible to limit up to 400% * - in order to avoid deadlocks, cpulimit now prevents to limit itself * - option --path eliminated, use --exe instead both for absolute path and file name - * - call setpriority() just once + * - call setpriority() just once in limit_process() * - no more segmentation fault when processes exit * - no more memory corruption when processes exit * - cpulimit exits if --lazy option is specified and the process terminates @@ -81,6 +81,9 @@ #define MAX_PRIORITY -10 +//how many cpu do we have? +#define NCPU (sysconf(_SC_NPROCESSORS_ONLN)) + /* GLOBAL VARIABLES */ //the "family" @@ -97,7 +100,7 @@ int verbose = 0; //lazy mode (exits if there is no process) int lazy = 0; -void *memrchr(const void *s, int c, size_t n) +static void *memrchr(const void *s, int c, size_t n) { const unsigned char *start=s,*end=s; @@ -113,44 +116,35 @@ void *memrchr(const void *s, int c, size_t n) return NULL; } -//how many cpu do we have? -int get_cpu_count() -{ - return sysconf(_SC_NPROCESSORS_ONLN); -} - -//return t1-t2 in microseconds (no overflow checks, so better watch out!) -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); -} - -//returns t1-t2 in microseconds -inline unsigned long long tv_diff(struct timeval *t1, struct timeval *t2) -{ - return ((unsigned long long)(t1->tv_sec - t2->tv_sec)) * 1000000ULL + t1->tv_usec - t2->tv_usec; -} - //SIGINT and SIGTERM signal handler -void quit(int sig) +static void quit(int sig) { //let all the processes continue if stopped struct list_node *node = NULL; for (node=pf.members.first; node!= NULL; node=node->next) { struct process *p = (struct process*)(node->data); - process_close(p->history); kill(p->pid, SIGCONT); + process_close(p); } //free all the memory cleanup_process_family(&pf); + //fix ^C little problem + printf("\r"); + fflush(stdout); exit(0); } -void print_usage(FILE *stream, int exit_code) +//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 void print_usage(FILE *stream, int exit_code) { fprintf(stream, "Usage: %s [OPTIONS...] TARGET\n", program_name); fprintf(stream, " OPTIONS\n"); - fprintf(stream, " -l, --limit=N percentage of cpu allowed from 0 to %d (required)\n", 100*get_cpu_count()); + fprintf(stream, " -l, --limit=N percentage of cpu allowed from 0 to %ld (required)\n", 100*NCPU); fprintf(stream, " -v, --verbose show control statistics\n"); fprintf(stream, " -z, --lazy exit if there is no target process, or if it dies\n"); fprintf(stream, " -i, --ignore-children don't limit children processes\n"); @@ -163,6 +157,21 @@ void print_usage(FILE *stream, int exit_code) exit(exit_code); } +static void increase_priority() { + //find the best available nice value + int old_priority = getpriority(PRIO_PROCESS, 0); + int priority = old_priority; + while (setpriority(PRIO_PROCESS, 0, priority-1) == 0 && priority>MAX_PRIORITY) { + priority--; + } + if (priority != old_priority) { + if (verbose) printf("Priority changed to %d\n", priority); + } + else { + if (verbose) printf("Warning: Cannot change priority. Run as root or renice for best results.\n"); + } +} + void limit_process(pid_t pid, double limit, int ignore_children) { //slice of the slot in which the process is allowed to run @@ -185,6 +194,9 @@ void limit_process(pid_t pid, double limit, int ignore_children) //counter int c = 0; + //get a better priority + increase_priority(); + //build the family create_process_family(&pf, pid); if (ignore_children) { @@ -201,9 +213,7 @@ void limit_process(pid_t pid, double limit, int ignore_children) //rate at which we are keeping active the processes (range 0-1) //1 means that the process are using all the twork slice double workingrate = -1; - while(1) { - if (!ignore_children && c%10==0) { //update the process family (checks only for new members) int new_children = update_process_family(&pf); @@ -228,21 +238,27 @@ void limit_process(pid_t pid, double limit, int ignore_children) //total cpu actual usage (range 0-1) //1 means that the processes are using 100% cpu double pcpu = -1; - + //estimate how much the controlled processes are using the cpu in the working interval for (node=pf.members.first; node!=NULL; node=node->next) { struct process *proc = (struct process*)(node->data); - if (process_monitor(proc->history)==-1) { + if (proc->is_zombie) { + //process is zombie, remove it from family + fprintf(stderr,"Process %d is zombie!\n", proc->pid); + remove_process_from_family(&pf, proc->pid); + continue; + } + if (process_monitor(proc) != 0) { //process is dead, remove it from family fprintf(stderr,"Process %d dead!\n", proc->pid); remove_process_from_family(&pf, proc->pid); continue; } - if (proc->history->cpu_usage<0) { + if (proc->cpu_usage<0) { continue; } if (pcpu<0) pcpu = 0; - pcpu += proc->history->cpu_usage; + pcpu += proc->cpu_usage; } //adjust work and sleep time slices @@ -390,9 +406,8 @@ int main(int argc, char **argv) { exit(1); } double limit = perclimit/100.0; - int cpu_count = get_cpu_count(); - if (limit<0 || limit >cpu_count) { - fprintf(stderr,"Error: limit must be in the range 0-%d00\n", cpu_count); + if (limit<0 || limit >NCPU) { + fprintf(stderr,"Error: limit must be in the range 0-%ld00\n", NCPU); print_usage(stderr, 1); exit(1); } @@ -415,21 +430,8 @@ int main(int argc, char **argv) { signal(SIGTERM, quit); //print the number of available cpu - if (verbose) printf("%d cpu detected\n", cpu_count); + if (verbose) printf("%ld cpu detected\n", NCPU); - //try to renice for a higher priority - int old_priority = getpriority(PRIO_PROCESS, 0); - int priority = old_priority; - while (setpriority(PRIO_PROCESS, 0, priority-1) == 0 && priority>MAX_PRIORITY) { - priority--; - } - if (priority != old_priority) { - if (verbose) printf("Priority changed to %d\n", priority); - } - else { - if (verbose) printf("Warning: Cannot change priority. Run as root or renice for best results.\n"); - } - if (command_mode) { int i; //executable file @@ -27,30 +27,37 @@ #include <Carbon/Carbon.h> #endif -int process_init(struct process_history *proc, int pid) +// returns the start time of a process (used with pid to identify a process) +static int get_starttime(pid_t pid) { #ifdef __linux__ - //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; + char file[20]; + char buffer[1024]; + sprintf(file, "/proc/%d/stat", pid); + FILE *fd = fopen(file, "r"); + if (fd==NULL) return -1; + fgets(buffer, sizeof(buffer), fd); 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__ + ProcessSerialNumber psn; + ProcessInfoRec info; + memset(&info, 0, sizeof(ProcessInfoRec)); + info.processInfoLength = sizeof(ProcessInfoRec); + if (GetProcessForPID(pid, &psn)) return -1; + if (GetProcessInformation(&psn, &info)) return -1; + return info.processLaunchDate; #endif - //init properties - proc->pid = pid; - proc->cpu_usage = 0; - memset(&(proc->last_sample), 0, sizeof(struct timeval)); - proc->last_jiffies = -1; - return 0; } -//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 get_jiffies(struct process_history *proc) { +static int get_jiffies(struct process *proc) { #ifdef __linux__ FILE *f = fopen(proc->stat_file, "r"); if (f==NULL) return -1; @@ -76,10 +83,42 @@ static int get_jiffies(struct process_history *proc) { #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_history *proc) +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) @@ -116,7 +155,7 @@ int process_monitor(struct process_history *proc) return 0; } -int process_close(struct process_history *proc) +int process_close(struct process *proc) { if (kill(proc->pid,SIGCONT)!=0) { fprintf(stderr,"Process %d is already dead!\n", proc->pid); @@ -53,30 +53,39 @@ # endif #endif - -//process descriptor -struct process_history { - //the PID of the process +// process descriptor +struct process { + //pid of the process pid_t pid; - //timestamp when last_j and cpu_usage was calculated - struct timeval last_sample; + //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; - //cpu usage estimation (value in range 0-1) + //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; + + //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 +#endif }; -int process_init(struct process_history *proc, pid_t pid); -int process_monitor(struct process_history *proc); +int process_init(struct process *proc, pid_t pid); + +int process_monitor(struct process *proc); -int process_close(struct process_history *proc); +int process_close(struct process *proc); #endif diff --git a/procutils.c b/procutils.c index 6ad6517..3e17628 100644 --- a/procutils.c +++ b/procutils.c @@ -56,36 +56,6 @@ static pid_t getppid_of(pid_t pid) #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; - fgets(buffer, sizeof(buffer), fd); - 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__ - ProcessSerialNumber psn; - ProcessInfoRec info; - memset(&info, 0, sizeof(ProcessInfoRec)); - info.processInfoLength = sizeof(ProcessInfoRec); - if (GetProcessForPID(pid, &psn)) return -1; - if (GetProcessInformation(&psn, &info)) return -1; - return info.processLaunchDate; -#endif -} - // detects whether a process is a kernel thread or not static int is_kernel_thread(pid_t pid) { @@ -129,7 +99,7 @@ static int process_exists(pid_t pid) { static int hash_process(struct process_family *f, struct process *p) { int ret; - struct list **l = &(f->hashtable[pid_hashfn(p->pid)]); + struct list **l = &(f->proctable[pid_hashfn(p->pid)]); if (*l == NULL) { //there is no process in this hashtable item //allocate the list @@ -161,7 +131,7 @@ static int hash_process(struct process_family *f, struct process *p) static void unhash_process(struct process_family *f, pid_t pid) { //remove process from hashtable - struct list **l = &(f->hashtable[pid_hashfn(pid)]); + struct list **l = &(f->proctable[pid_hashfn(pid)]); if (*l == NULL) return; //nothing done struct list_node *node = locate_node(*l, &pid); @@ -172,17 +142,10 @@ static void unhash_process(struct process_family *f, pid_t pid) { static struct process *seek_process(struct process_family *f, pid_t pid) { - struct list **l = &(f->hashtable[pid_hashfn(pid)]); + struct list **l = &(f->proctable[pid_hashfn(pid)]); return (*l != NULL) ? (struct process*)locate_elem(*l, &pid) : NULL; } -/* -static int is_member(struct process_family *f, pid_t pid) { - struct process *p = seek_process(f, pid); - return (p!=NULL && p->member); -} -*/ - /* PROCESS ITERATOR STUFF */ // creates an object that browse all running processes @@ -202,14 +165,16 @@ static int init_process_iterator(struct process_iterator *i) { // reads the next user process from /process // automatic closing if the end of the list is reached -static int read_next_process(struct process_iterator *i) { +static pid_t read_next_process(struct process_iterator *i) { pid_t pid = 0; #ifdef __linux__ //TODO read this to port to other systems: http://www.steve.org.uk/Reference/Unix/faq_8.html#SEC85 //read in from /proc and seek for process dirs while ((i->dit = readdir(i->dip)) != NULL) { + if( strtok(i->dit->d_name, "0123456789") != NULL ) + continue; pid = atoi(i->dit->d_name); - if (pid<=0 || is_kernel_thread(pid)) + if (is_kernel_thread(pid)) continue; //return the first found process break; @@ -230,14 +195,14 @@ static int read_next_process(struct process_iterator *i) { /* PUBLIC FUNCTIONS */ -// searches for all the processes derived from father and stores them +// search for all the processes derived from father and stores them // in the process family struct int create_process_family(struct process_family *f, pid_t father) { //process list initialization (4 bytes key) init_list(&(f->members), 4); //hashtable initialization - memset(&(f->hashtable), 0, sizeof(f->hashtable)); + memset(&(f->proctable), 0, sizeof(f->proctable)); f->count = 0; f->father = father; //process iterator @@ -251,10 +216,10 @@ int create_process_family(struct process_family *f, pid_t father) while(ppid!=1 && ppid!=father) { ppid = getppid_of(ppid); } - //allocate and insert the process + //allocate process descriptor struct process *p = malloc(sizeof(struct process)); - p->pid = pid; - p->starttime = get_starttime(pid); + //init process + process_init(p, pid); if (ppid==1) { //the init process p->member = 0; @@ -264,9 +229,6 @@ int create_process_family(struct process_family *f, pid_t father) p->member = 1; add_elem(&(f->members), p); } - //init history - p->history = malloc(sizeof(struct process_history)); - process_init(p->history, pid); //add to hashtable hash_process(f, p); } @@ -300,8 +262,8 @@ int update_process_family(struct process_family *f) } //allocate and insert the process struct process *p = malloc(sizeof(struct process)); - p->pid = pid; - p->starttime = get_starttime(pid); + //init process + process_init(p, pid); if (ancestor->member) { //add to members p->member = 1; @@ -312,9 +274,6 @@ int update_process_family(struct process_family *f) //not a member p->member = 0; } - //init history - p->history = malloc(sizeof(struct process_history)); - process_init(p->history, pid); //add to hashtable hash_process(f, p); } @@ -326,9 +285,9 @@ void remove_process_from_family(struct process_family *f, pid_t pid) { struct list_node *node = locate_node(&(f->members), &pid); if (node != NULL) { - struct process *p = (struct process*)(node->data); - free(p->history); - p->history = NULL; +// struct process *p = (struct process*)(node->data); +// free(p->history); +// p->history = NULL; delete_node(&(f->members), node); } unhash_process(f, pid); @@ -338,19 +297,19 @@ void remove_process_from_family(struct process_family *f, pid_t pid) void cleanup_process_family(struct process_family *f) { int i; - int size = sizeof(f->hashtable) / sizeof(struct process*); + int size = sizeof(f->proctable) / sizeof(struct process*); for (i=0; i<size; i++) { - if (f->hashtable[i] != NULL) { + if (f->proctable[i] != NULL) { //free() history for each process struct list_node *node = NULL; - for (node=f->hashtable[i]->first; node!=NULL; node=node->next) { - struct process *p = (struct process*)(node->data); - free(p->history); - p->history = NULL; + for (node=f->proctable[i]->first; node!=NULL; node=node->next) { +// struct process *p = (struct process*)(node->data); +// free(p->history); +// p->history = NULL; } - destroy_list(f->hashtable[i]); - free(f->hashtable[i]); - f->hashtable[i] = NULL; + destroy_list(f->proctable[i]); + free(f->proctable[i]); + f->proctable[i] = NULL; } } flush_list(&(f->members)); @@ -399,16 +358,17 @@ int look_for_process_by_name(const char *process_name) info.processName = (char*)malloc(64*sizeof(char)); #endif while ((pid = read_next_process(&iter))) { + int size = 0; #ifdef __linux__ //read the executable link sprintf(exelink,"/proc/%d/exe",pid); - int size = readlink(exelink, exepath, sizeof(exepath)); + size = readlink(exelink, exepath, sizeof(exepath)); exepath[size] = '\0'; #elif defined __APPLE__ //get the executable file name if (GetProcessForPID(pid, &psn)) return -1; if (GetProcessInformation(&psn, &info)) return -1; - int size = strlen(info.processName); + size = strlen(info.processName); strcpy(exepath, info.processName); #endif if (size>0) { diff --git a/procutils.h b/procutils.h index c285e15..720b09b 100644 --- a/procutils.h +++ b/procutils.h @@ -31,6 +31,7 @@ #include <dirent.h> #include <string.h> #include <limits.h> + #include "list.h" #include "process.h" @@ -38,10 +39,6 @@ #include <Carbon/Carbon.h> #endif -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif - #define PIDHASH_SZ 1024 #define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1)) @@ -54,20 +51,16 @@ struct process_family { struct list members; //non-members list //hashtable with all the processes (array of struct list of struct process) - struct list *hashtable[PIDHASH_SZ]; + struct list *proctable[PIDHASH_SZ]; //total process count int count; }; -// process descriptor -struct process { - //pid of the process - pid_t pid; - //start time - int starttime; - //is member of the family? +//TODO: use this object in proctable and delete member in struct process +struct table_item { + struct process *proc; + //1 if the process is a member of the family int member; - struct process_history *history; }; // object to enumerate running processes @@ -97,7 +90,7 @@ void cleanup_process_family(struct process_family *f); // searches a process given the name of the executable file, or its absolute path // returns the pid, or 0 if it's not found -int look_for_process_by_name(const char *process); +int look_for_process_by_name(const char *process_name); // searches a process given its pid // returns the pid, or 0 if it's not found diff --git a/tools/jiffy.c b/tools/jiffy.c deleted file mode 100644 index 298f300..0000000 --- a/tools/jiffy.c +++ /dev/null @@ -1,69 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <sys/time.h> -#include <string.h> -#include <unistd.h> - -#ifdef __APPLE__ -#include <Carbon/Carbon.h> -#endif - -static int get_jiffies(pid_t pid) { -#ifdef __GNUC__ - char buffer[1024]; - char stat_file[32]; - sprintf(stat_file, "/proc/%d/stat", pid); - FILE *f = fopen(stat_file, "r"); - if (f==NULL) return -1; - fgets(buffer, sizeof(buffer),f); - fclose(f); - char *p = buffer; - p = memchr(p+1,')', sizeof(buffer) - (p-buffer)); - int sp = 12; - while (sp--) - p = memchr(p+1,' ',sizeof(buffer) - (p-buffer)); - //user mode jiffies - int utime = atoi(p+1); - p = memchr(p+1,' ',sizeof(buffer) - (p-buffer)); - //kernel mode jiffies - int ktime = atoi(p+1); - return utime+ktime; -#elif defined __APPLE__ - ProcessSerialNumber psn; - ProcessInfoRec info; - if (GetProcessForPID(pid, &psn)) return -1; - if (GetProcessInformation(&psn, &info)) return -1; - return info.processActiveTime; -#endif -} - -struct timeval timeval_diff(struct timeval *tv1, struct timeval *tv2) -{ - struct timeval diff; - diff.tv_sec = tv2->tv_sec - tv1->tv_sec; - diff.tv_usec = tv2->tv_usec - tv1->tv_usec; - if (diff.tv_usec < 0) { - diff.tv_sec--; - diff.tv_usec += 1000000; - } - return diff; -} - -int main() { - struct timeval start, now, diff; - int i,j; - int pid = getpid(); - gettimeofday(&start, NULL); - printf("time j HZ jiffy time\n"); - while(1) { - for(i=0;i<100000;i++) - for(j=0;j<10000;j++); - int j = get_jiffies(pid); - if (j<0) exit(-1); - gettimeofday(&now, NULL); - diff = timeval_diff(&start, &now); - double d = diff.tv_sec + diff.tv_usec * 1e-6; - printf("%lf %d %lf %lf ms\n", d, j, j/d, 1000*d/j); - } - exit(0); -} diff --git a/tools/loop.c b/tools/loop.c deleted file mode 100644 index c9280d2..0000000 --- a/tools/loop.c +++ /dev/null @@ -1,3 +0,0 @@ -int main() { - while(1); -} diff --git a/tools/ptest.c b/tools/ptest.c deleted file mode 100644 index 68d1fc2..0000000 --- a/tools/ptest.c +++ /dev/null @@ -1,58 +0,0 @@ -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/time.h> -#include <stdlib.h> -#include <unistd.h> - -#define N 10 - -//simple program to test cpulimit -int main() -{ - printf("Parent: PID %d\n", getpid()); - getchar(); - sleep(1); - int i; - int children[N]; - for (i=0;i<N;i++) { - int pid = fork(); - if (pid>0) { - //parent code - children[i] = pid; - printf("Child %d created\n", pid); - } - else if (pid==0) { - while(1); - //child code -// while(1) { - //random generator initialization - struct timeval t; - gettimeofday(&t, NULL); - srandom(t.tv_sec + t.tv_usec + getpid()); - int loop = random() % 1000000; - printf("start\n"); - int i,j; - for (i=0;i<1000;i++) - for (j=0;j<loop;j++); - printf("stop\n"); - int time = random() % 10000000; - // printf("Child %d wait %d\n", getpid(), time); - usleep(time); - printf("Child %d terminated\n", getpid()); -// } - exit(0); - } - else { - fprintf(stderr, "fork() failed!\n"); - } - } - for (i=0;i<N;i++) { - int status; - waitpid(children[i], &status, 0); - } - sleep(1); - return 0; -} |