10 #include <sys/resource.h>
14 #include <sys/sysctl.h>
22 static void getsysctl(char *, void *, size_t);
25 char *cpustatenames[] = {
26 "user", "nice", "system", "idle", "interrupt", NULL
33 char *cpustatenames[] = {
34 "user", "nice", "system", "idle", NULL
42 * user - nice - system - idle - iowait - irq - soft irq */
43 char *cpustatenames[] = {
44 "user", "nice", "system", "idle", "iowait", "irq", "softirq", NULL
50 static const char usage[] =
51 "\n usage: cpusage [ -hos ] [ -a | -l limit ] [ -c CPU ]\n";
55 static float cpu_perc[CPUSTATES];
56 static float cpu_max[CPUSTATES];
57 static float cpu_min[CPUSTATES];
59 int cpunum; /* -1 all, 0-n CPU/Core 0-n */
65 /* returns 1-n yielding the number of CPU's/Cores */
76 fd = open("/proc/stat", O_RDONLY);
78 fprintf(stderr, "%s: cannot open /proc/stat \n", appname);
80 len = read(fd, buffer, sizeof(buffer)-1);
86 test = strstr(buffer, "cpu");
88 test += sizeof("cpu");
89 test = strstr(test, "cpu");
92 while ( test != NULL ) {
93 test += sizeof("cpu");
94 /* fprintf(stderr, "%s: DEBUG: %s\n", appname, test); */
96 test = strstr(test, "cpu");
103 static void getsysctl (char *name, void *ptr, size_t len) {
107 if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
108 fprintf(stderr, "%s: sysctl(%s...) failed: %s\n",
109 appname, name, strerror(errno));
113 fprintf(stderr, "%s: sysctl(%s...) expected %lu, got %lu\n",
114 appname, name, (unsigned long)len, (unsigned long)nlen);
118 /* swapping idle and interrupt to look like linux */
119 save = ((long*) ptr)[4];
120 ((long*) ptr)[4] = ((long*) ptr)[3];
121 ((long*) ptr)[3] = save;
124 void getSysinfo(unsigned long *ptr, size_t size)
131 for (j = 0; j<size; j++)
134 fd = open("/proc/stat", O_RDONLY);
136 fprintf(stderr, "%s: cannot open /proc/stat\n", appname );
138 len = read(fd, buffer, sizeof(buffer)-1);
143 strcpy(match, "cpu ");
145 if ( cpunum != -1 ) {
146 sprintf(match, "cpu%d ", cpunum);
147 start = strstr(buffer, match);
151 strcat(match, "%ld %ld %ld %ld %ld %ld %ld");
152 if ( sscanf(start, match, &ptr[0],
153 &ptr[1], &ptr[2], &ptr[3], &ptr[4], &ptr[5], &ptr[6]) != 7 ) {
154 fprintf(stderr, "%s: wrong /proc/stat format\n", appname);
157 strcat(match, "%ld %ld %ld %ld");
158 if ( sscanf(start, match,
159 &ptr[0], &ptr[1], &ptr[2], &ptr[3]) != 4) {
160 fprintf(stderr, "%s: wrong /proc/stat format\n", appname);
167 long perc(int cpustates, long *cp_time, long *cp_old, long *cp_diff) {
172 for ( i = 0; i < cpustates; i++ ) {
173 cp_diff[i] = cp_time[i] - cp_old[i];
177 for ( i = 0; i < cpustates; i++) {
178 cpu_perc[i] = ((float)cp_diff[i]*100.0 / total);
180 if ( cpu_perc[i] > cpu_max[i] )
181 cpu_max[i] = cpu_perc[i];
183 if ( cpu_perc[i] < cpu_min[i] )
184 cpu_min[i] = cpu_perc[i];
190 void print_perc(float *perc, const char *head){
196 if ( (output == 0) && (head != ""))
197 printf("%s: ", head);
199 /* machine readable */
200 if ( (output == 1) && (head != ""))
205 now = localtime(&Zeitstempel);
207 printf("timestamp: %04d-%02d-%02d %02d.%02d.%02d, ", now->tm_year+1900, now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
209 printf("%04d-%02d-%02d;%02d:%02d:%02d;", now->tm_year+1900, now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
212 printf("%s: %5.1f%%, ", cpustatenames[0], perc[0]);
214 printf("%.1f", perc[0]);
216 /* print out calculated information in percentages */
217 for ( i = 1; i < CPUSTATES; i++) {
219 printf("%s: %5.1f%%, ", cpustatenames[i], perc[i]);
221 printf(";%.1f", perc[i]);
226 /* to catch Strg+C when looping */
227 void loop_term_handler (int signum) {
231 int main(int argc, char** argv) {
236 int runonce; /* run just once and exit */
237 int avg; /* is avg measurement allready running */
238 int avg_run; /* did we allready had an avg measurement */
239 static long cp_time1[CPUSTATES];
240 static long cp_time2[CPUSTATES];
241 static long cp_avg_start[CPUSTATES];
242 static long cp_avg_stop[CPUSTATES];
243 static long cp_diff[CPUSTATES];
245 struct sigaction sigold, signew;
247 long *old = cp_time2;
248 long *new = cp_time1;
252 output = 0; /* 0: human readable; 1: machine readable */
253 runonce = 0; /* 0: run continuesly; 1: run once */
255 cpunum = -1; /* -1: all CPUs/Cores, 0-n: special CPU/Core */
257 /* reading commandline options */
259 c = getopt(argc, argv, "saohl:c:");
266 /*run once and exit */
270 /* use avg from begin to end -> same as "-l 100" */
275 output = 1; /* machine readable */
276 // header for CSV output
277 printf("date;time;user;nice;system;idle;iowait;irq;softirq\n");
281 fprintf(stderr, "%s: %s", appname, usage);
286 if ( !(sscanf(optarg, "%d", &limit) == 1) ) {
287 fprintf(stderr, "%s: option for -l should be integer (is %s)\n",
292 /* select CPU/Core */
294 if ( !(sscanf(optarg, "%d", &cpunum) == 1) ) {
295 fprintf(stderr, "%s: option for -c should be integer (is %s)\n",
306 fprintf(stderr, "%s: No CPU/Core selection available for FreeBSD\n",
310 int numcpu = getNumCPU();
311 if ( cpunum < numcpu ) {
312 printf("-- Selected CPU %d\n", cpunum );
315 fprintf(stderr, "%s: CPU %d not available (found %d CPU: [0])\n",
316 appname, cpunum, numcpu );
318 fprintf(stderr, "%s: CPU %d not available (found %d CPU's: [0]-[%d])\n ",
319 appname, cpunum, numcpu, numcpu - 1 );
329 for (i=0; i < CPUSTATES; i++){
334 /* get information */
336 getsysctl("kern.cp_time", new, sizeof(cp_time1));
338 getSysinfo((unsigned long*)new, CPUSTATES);
341 /* catch Strg+C when capturing to call pcap_breakloop() */
342 memset(&signew, 0, sizeof(signew));
343 signew.sa_handler = loop_term_handler;
344 if (sigaction(SIGINT, &signew, &sigold) < 0 ){
345 fprintf(stderr, "Could not set signal handler -> exiting");
358 if ( new == cp_time1 ) {
366 /* get information again */
368 getsysctl("kern.cp_time", new, sizeof(cp_time1));
370 getSysinfo((unsigned long*)new, CPUSTATES);
373 /* convert cp_time counts to percentages */
374 total = perc(CPUSTATES, new, old, cp_diff);
376 /* check for avg measurement start */
377 if ( !avg_run && !avg && (cpu_perc[IDLEI] <= limit) ){
379 for ( i = 0; i < CPUSTATES; i++ )
380 cp_avg_start[i] = new[i];
383 /* check for avg measurement stop */
384 if ( !avg_run && avg && (cpu_perc[IDLEI] > limit) ){
386 for ( i = 0; i < CPUSTATES; i++ )
387 cp_avg_stop[i] = new[i];
391 print_perc(cpu_perc, "");
396 for ( i = 0; i < CPUSTATES; i++ )
397 cp_avg_stop[i] = new[i];
403 /* Set default behaviour when loop is done */
404 if (sigaction(SIGINT, &sigold, &signew) < 0 ){
405 fprintf(stderr, "%s: Could not restore signal handler -> exiting", appname);
408 if ( ! runonce && output == 0) {
409 // print avg only when not making a one-shot msg and
410 // when not writing CSV output
411 printf("---Summary----\n");
413 print_perc(cpu_min, "Min");
415 print_perc(cpu_max, "Max");
417 perc(CPUSTATES, cp_avg_start, cp_avg_stop, cp_diff);
419 print_perc(cpu_perc, "Avg");