Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/procps/top.c
- Timestamp:
- Nov 4, 2007, 3:16:40 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.5/mindi-busybox/procps/top.c
r821 r1765 29 29 */ 30 30 31 #include "busybox.h" 32 #include <sys/types.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <string.h> 37 #include <sys/ioctl.h> 38 39 //#define CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE /* + 2k */ 40 41 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 42 #include <time.h> 43 #include <fcntl.h> 44 #include <netinet/in.h> /* htons */ 45 #endif 46 47 48 typedef int (*cmp_t)(procps_status_t *P, procps_status_t *Q); 49 50 static procps_status_t *top; /* Hehe */ 51 static int ntop; 52 53 #ifdef CONFIG_FEATURE_USE_TERMIOS 54 static int pid_sort(procps_status_t *P, procps_status_t *Q) 55 { 31 #include "libbb.h" 32 33 34 typedef struct top_status_t { 35 unsigned long vsz; 36 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 37 unsigned long ticks; 38 unsigned pcpu; /* delta of ticks */ 39 #endif 40 unsigned pid, ppid; 41 unsigned uid; 42 char state[4]; 43 char comm[COMM_LEN]; 44 } top_status_t; 45 46 typedef struct jiffy_counts_t { 47 unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal; 48 unsigned long long total; 49 unsigned long long busy; 50 } jiffy_counts_t; 51 52 /* This structure stores some critical information from one frame to 53 the next. Used for finding deltas. */ 54 typedef struct save_hist { 55 unsigned long ticks; 56 unsigned pid; 57 } save_hist; 58 59 typedef int (*cmp_funcp)(top_status_t *P, top_status_t *Q); 60 61 enum { SORT_DEPTH = 3 }; 62 63 struct globals { 64 top_status_t *top; 65 int ntop; 66 #if ENABLE_FEATURE_USE_TERMIOS 67 struct termios initial_settings; 68 #endif 69 #if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 70 cmp_funcp sort_function; 71 #else 72 cmp_funcp sort_function[SORT_DEPTH]; 73 struct save_hist *prev_hist; 74 int prev_hist_count; 75 jiffy_counts_t jif, prev_jif; 76 /* int hist_iterations; */ 77 unsigned total_pcpu; 78 /* unsigned long total_vsz; */ 79 #endif 80 }; 81 #define G (*(struct globals*)&bb_common_bufsiz1) 82 #define top (G.top ) 83 #define ntop (G.ntop ) 84 #if ENABLE_FEATURE_USE_TERMIOS 85 #define initial_settings (G. initial_settings ) 86 #endif 87 #define sort_function (G.sort_function ) 88 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 89 #define prev_hist (G.prev_hist ) 90 #define prev_hist_count (G.prev_hist_count ) 91 #define jif (G.jif ) 92 #define prev_jif (G.prev_jif ) 93 #define total_pcpu (G.total_pcpu ) 94 #endif 95 96 #define OPT_BATCH_MODE (option_mask32 & 0x4) 97 98 99 #if ENABLE_FEATURE_USE_TERMIOS 100 static int pid_sort(top_status_t *P, top_status_t *Q) 101 { 102 /* Buggy wrt pids with high bit set */ 103 /* (linux pids are in [1..2^15-1]) */ 56 104 return (Q->pid - P->pid); 57 105 } 58 106 #endif 59 107 60 static int mem_sort(procps_status_t *P, procps_status_t *Q) 61 { 62 return (int)(Q->rss - P->rss); 63 } 64 65 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 66 67 #define sort_depth 3 68 static cmp_t sort_function[sort_depth]; 69 70 static int pcpu_sort(procps_status_t *P, procps_status_t *Q) 71 { 72 return (Q->pcpu - P->pcpu); 73 } 74 75 static int time_sort(procps_status_t *P, procps_status_t *Q) 76 { 77 return (int)((Q->stime + Q->utime) - (P->stime + P->utime)); 78 } 79 80 static int mult_lvl_cmp(void* a, void* b) { 108 static int mem_sort(top_status_t *P, top_status_t *Q) 109 { 110 /* We want to avoid unsigned->signed and truncation errors */ 111 if (Q->vsz < P->vsz) return -1; 112 return Q->vsz != P->vsz; /* 0 if ==, 1 if > */ 113 } 114 115 116 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 117 118 static int pcpu_sort(top_status_t *P, top_status_t *Q) 119 { 120 /* Buggy wrt ticks with high bit set */ 121 /* Affects only processes for which ticks overflow */ 122 return (int)Q->pcpu - (int)P->pcpu; 123 } 124 125 static int time_sort(top_status_t *P, top_status_t *Q) 126 { 127 /* We want to avoid unsigned->signed and truncation errors */ 128 if (Q->ticks < P->ticks) return -1; 129 return Q->ticks != P->ticks; /* 0 if ==, 1 if > */ 130 } 131 132 static int mult_lvl_cmp(void* a, void* b) 133 { 81 134 int i, cmp_val; 82 135 83 for (i = 0; i < sort_depth; i++) {136 for (i = 0; i < SORT_DEPTH; i++) { 84 137 cmp_val = (*sort_function[i])(a, b); 85 138 if (cmp_val != 0) … … 89 142 } 90 143 91 /* This structure stores some critical information from one frame to92 the next. mostly used for sorting. Added cumulative and resident fields. */93 struct save_hist {94 int ticks;95 int pid;96 };97 98 /*99 * Calculates percent cpu usage for each task.100 */101 102 static struct save_hist *prev_hist;103 static int prev_hist_count;104 /* static int hist_iterations; */105 106 107 static unsigned total_pcpu;108 /* static unsigned long total_rss; */109 110 struct jiffy_counts {111 unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal;112 unsigned long long total;113 unsigned long long busy;114 };115 static struct jiffy_counts jif, prev_jif;116 144 117 145 static void get_jiffy_counts(void) 118 146 { 119 FILE* fp = bb_xfopen("stat", "r");147 FILE* fp = xfopen("stat", "r"); 120 148 prev_jif = jif; 121 149 if (fscanf(fp, "cpu %lld %lld %lld %lld %lld %lld %lld %lld", 122 150 &jif.usr,&jif.nic,&jif.sys,&jif.idle, 123 151 &jif.iowait,&jif.irq,&jif.softirq,&jif.steal) < 4) { 124 bb_error_msg_and_die("failed to read 'stat'");152 bb_error_msg_and_die("failed to read /proc/stat"); 125 153 } 126 154 fclose(fp); … … 131 159 } 132 160 161 133 162 static void do_stats(void) 134 163 { 135 procps_status_t *cur; 136 int pid, total_time, i, last_i, n; 164 top_status_t *cur; 165 pid_t pid; 166 int i, last_i, n; 137 167 struct save_hist *new_hist; 138 168 139 169 get_jiffy_counts(); 140 170 total_pcpu = 0; 141 /* total_ rss= 0; */171 /* total_vsz = 0; */ 142 172 new_hist = xmalloc(sizeof(struct save_hist)*ntop); 143 173 /* … … 154 184 */ 155 185 pid = cur->pid; 156 total_time = cur->stime + cur->utime; 157 new_hist[n].ticks = total_time; 186 new_hist[n].ticks = cur->ticks; 158 187 new_hist[n].pid = pid; 159 188 … … 165 194 if (prev_hist_count) do { 166 195 if (prev_hist[i].pid == pid) { 167 cur->pcpu = total_time - prev_hist[i].ticks; 196 cur->pcpu = cur->ticks - prev_hist[i].ticks; 197 total_pcpu += cur->pcpu; 168 198 break; 169 199 } … … 171 201 /* hist_iterations++; */ 172 202 } while (i != last_i); 173 total_pcpu += cur->pcpu; 174 /* total_rss += cur->rss; */ 203 /* total_vsz += cur->vsz; */ 175 204 } 176 205 … … 182 211 prev_hist_count = ntop; 183 212 } 184 #else 185 static cmp_t sort_function; 186 #endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 213 #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 214 215 #if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS && ENABLE_FEATURE_TOP_DECIMALS 216 /* formats 7 char string (8 with terminating NUL) */ 217 static char *fmt_100percent_8(char pbuf[8], unsigned value, unsigned total) 218 { 219 unsigned t; 220 if (value >= total) { /* 100% ? */ 221 strcpy(pbuf, " 100% "); 222 return pbuf; 223 } 224 /* else generate " [N/space]N.N% " string */ 225 value = 1000 * value / total; 226 t = value / 100; 227 value = value % 100; 228 pbuf[0] = ' '; 229 pbuf[1] = t ? t + '0' : ' '; 230 pbuf[2] = '0' + (value / 10); 231 pbuf[3] = '.'; 232 pbuf[4] = '0' + (value % 10); 233 pbuf[5] = '%'; 234 pbuf[6] = ' '; 235 pbuf[7] = '\0'; 236 return pbuf; 237 } 238 #endif 187 239 188 240 /* display generic info (meminfo / loadavg) */ … … 192 244 char buf[80]; 193 245 char scrbuf[80]; 194 char *end;195 246 unsigned long total, used, mfree, shared, buffers, cached; 196 unsigned int needs_conversion = 1; 247 #if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS 248 unsigned total_diff; 249 #endif 197 250 198 251 /* read memory info */ 199 fp = bb_xfopen("meminfo", "r");252 fp = xfopen("meminfo", "r"); 200 253 201 254 /* … … 213 266 214 267 fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu", 215 &total, &used, &mfree, &shared, &buffers, &cached); 216 } else { 217 /* 218 * Revert to manual parsing, which incidentally already has the 219 * sizes in kilobytes. This should be safe for both 2.4 and 220 * 2.6. 221 */ 222 needs_conversion = 0; 223 224 fscanf(fp, "MemFree: %lu %s\n", &mfree, buf); 225 226 /* 227 * MemShared: is no longer present in 2.6. Report this as 0, 228 * to maintain consistent behavior with normal procps. 229 */ 230 if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2) 231 shared = 0; 232 233 fscanf(fp, "Buffers: %lu %s\n", &buffers, buf); 234 fscanf(fp, "Cached: %lu %s\n", &cached, buf); 235 236 used = total - mfree; 237 } 238 fclose(fp); 239 240 /* read load average as a string */ 241 fp = bb_xfopen("loadavg", "r"); 242 buf[0] = '\0'; 243 fgets(buf, sizeof(buf), fp); 244 end = strchr(buf, ' '); 245 if (end) end = strchr(end+1, ' '); 246 if (end) end = strchr(end+1, ' '); 247 if (end) *end = '\0'; 248 fclose(fp); 249 250 if (needs_conversion) { 268 &total, &used, &mfree, &shared, &buffers, &cached); 251 269 /* convert to kilobytes */ 252 270 used /= 1024; … … 256 274 cached /= 1024; 257 275 total /= 1024; 258 } 259 260 /* output memory info and load average */ 261 /* clear screen & go to top */ 276 } else { 277 /* 278 * Revert to manual parsing, which incidentally already has the 279 * sizes in kilobytes. This should be safe for both 2.4 and 280 * 2.6. 281 */ 282 283 fscanf(fp, "MemFree: %lu %s\n", &mfree, buf); 284 285 /* 286 * MemShared: is no longer present in 2.6. Report this as 0, 287 * to maintain consistent behavior with normal procps. 288 */ 289 if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2) 290 shared = 0; 291 292 fscanf(fp, "Buffers: %lu %s\n", &buffers, buf); 293 fscanf(fp, "Cached: %lu %s\n", &cached, buf); 294 295 used = total - mfree; 296 } 297 fclose(fp); 298 299 /* output memory info */ 262 300 if (scr_width > sizeof(scrbuf)) 263 301 scr_width = sizeof(scrbuf); 264 302 snprintf(scrbuf, scr_width, 265 "Mem: %l dK used, %ldK free, %ldK shrd, %ldK buff, %ldK cached",303 "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", 266 304 used, mfree, shared, buffers, cached); 267 printf("\e[H\e[J%s\n", scrbuf); 268 snprintf(scrbuf, scr_width, 269 "Load average: %s (Status: S=sleeping R=running, W=waiting)", buf); 270 printf("%s\n", scrbuf); 305 /* clear screen & go to top */ 306 printf(OPT_BATCH_MODE ? "%s\n" : "\e[H\e[J%s\n", scrbuf); 307 308 #if ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS 309 /* 310 * xxx% = (jif.xxx - prev_jif.xxx) / (jif.total - prev_jif.total) * 100% 311 */ 312 /* using (unsigned) casts to make operations cheaper */ 313 total_diff = ((unsigned)(jif.total - prev_jif.total) ? : 1); 314 #if ENABLE_FEATURE_TOP_DECIMALS 315 /* Generated code is approx +0.3k */ 316 #define CALC_STAT(xxx) char xxx[8] 317 #define SHOW_STAT(xxx) fmt_100percent_8(xxx, (unsigned)(jif.xxx - prev_jif.xxx), total_diff) 318 #define FMT "%s" 319 #else 320 #define CALC_STAT(xxx) unsigned xxx = 100 * (unsigned)(jif.xxx - prev_jif.xxx) / total_diff 321 #define SHOW_STAT(xxx) xxx 322 #define FMT "%4u%% " 323 #endif 324 { /* need block: CALC_STAT are declarations */ 325 CALC_STAT(usr); 326 CALC_STAT(sys); 327 CALC_STAT(nic); 328 CALC_STAT(idle); 329 CALC_STAT(iowait); 330 CALC_STAT(irq); 331 CALC_STAT(softirq); 332 //CALC_STAT(steal); 333 334 snprintf(scrbuf, scr_width, 335 /* Barely fits in 79 chars when in "decimals" mode. */ 336 "CPU:"FMT"usr"FMT"sys"FMT"nice"FMT"idle"FMT"io"FMT"irq"FMT"softirq", 337 SHOW_STAT(usr), SHOW_STAT(sys), SHOW_STAT(nic), SHOW_STAT(idle), 338 SHOW_STAT(iowait), SHOW_STAT(irq), SHOW_STAT(softirq) 339 //, SHOW_STAT(steal) - what is this 'steal' thing? 340 // I doubt anyone wants to know it 341 ); 342 } 343 puts(scrbuf); 344 #undef SHOW_STAT 345 #undef CALC_STAT 346 #undef FMT 347 #endif 348 349 /* read load average as a string */ 350 buf[0] = '\0'; 351 open_read_close("loadavg", buf, sizeof("N.NN N.NN N.NN")-1); 352 buf[sizeof("N.NN N.NN N.NN")-1] = '\0'; 353 snprintf(scrbuf, scr_width, "Load average: %s", buf); 354 puts(scrbuf); 271 355 272 356 return total; 273 357 } 274 275 358 276 359 /* display process statuses */ … … 278 361 { 279 362 enum { 280 bits_per_int= sizeof(int)*8363 BITS_PER_INT = sizeof(int)*8 281 364 }; 282 365 283 procps_status_t *s = top; 284 char rss_str_buf[8]; 285 unsigned long total_memory = display_generic(scr_width); /* or use total_rss? */ 286 unsigned pmem_shift, pmem_scale; 287 288 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 289 unsigned pcpu_shift, pcpu_scale; 366 top_status_t *s = top; 367 char vsz_str_buf[8]; 368 unsigned long total_memory = display_generic(scr_width); /* or use total_vsz? */ 369 /* xxx_shift and xxx_scale variables allow us to replace 370 * expensive divides with multiply and shift */ 371 unsigned pmem_shift, pmem_scale, pmem_half; 372 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 373 unsigned pcpu_shift, pcpu_scale, pcpu_half; 374 unsigned busy_jifs; 290 375 291 376 /* what info of the processes is shown */ 292 printf( "\e[7m%.*s\e[0m", scr_width,293 " PID USER STATUS RSS PPID %CPU %MEMCOMMAND");377 printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, 378 " PID PPID USER STAT VSZ %MEM %CPU COMMAND"); 294 379 #define MIN_WIDTH \ 295 sizeof( " PID USER STATUS RSS PPID %CPU %MEM C") 296 #else 297 printf("\e[7m%.*s\e[0m", scr_width, 298 " PID USER STATUS RSS PPID %MEM COMMAND"); 380 sizeof( " PID PPID USER STAT VSZ %MEM %CPU C") 381 #else 382 383 /* !CPU_USAGE_PERCENTAGE */ 384 printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, 385 " PID PPID USER STAT VSZ %MEM COMMAND"); 299 386 #define MIN_WIDTH \ 300 sizeof( " PID USER STATUS RSS PPID %MEM C") 301 #endif 302 387 sizeof( " PID PPID USER STAT VSZ %MEM C") 388 #endif 389 390 #if ENABLE_FEATURE_TOP_DECIMALS 391 #define UPSCALE 1000 392 #define CALC_STAT(name, val) div_t name = div((val), 10) 393 #define SHOW_STAT(name) name.quot, '0'+name.rem 394 #define FMT "%3u.%c" 395 #else 396 #define UPSCALE 100 397 #define CALC_STAT(name, val) unsigned name = (val) 398 #define SHOW_STAT(name) name 399 #define FMT "%4u%%" 400 #endif 303 401 /* 304 * MEM% = s-> rss/MemTotal402 * MEM% = s->vsz/MemTotal 305 403 */ 306 pmem_shift = bits_per_int-11;307 pmem_scale = 1000*(1U<<(bits_per_int-11)) / total_memory;308 /* s-> rss is in kb. we want (s->rss* pmem_scale) to never overflow */404 pmem_shift = BITS_PER_INT-11; 405 pmem_scale = UPSCALE*(1U<<(BITS_PER_INT-11)) / total_memory; 406 /* s->vsz is in kb. we want (s->vsz * pmem_scale) to never overflow */ 309 407 while (pmem_scale >= 512) { 310 408 pmem_scale /= 4; 311 409 pmem_shift -= 2; 312 410 } 313 #ifdef CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE 411 pmem_half = (1U << pmem_shift) / (ENABLE_FEATURE_TOP_DECIMALS? 20 : 2); 412 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 413 busy_jifs = jif.busy - prev_jif.busy; 414 /* This happens if there were lots of short-lived processes 415 * between two top updates (e.g. compilation) */ 416 if (total_pcpu < busy_jifs) total_pcpu = busy_jifs; 417 314 418 /* 315 419 * CPU% = s->pcpu/sum(s->pcpu) * busy_cpu_ticks/total_cpu_ticks … … 321 425 */ 322 426 pcpu_shift = 6; 323 pcpu_scale = ( 1000*64*(uint16_t)(jif.busy-prev_jif.busy)? : 1);324 while (pcpu_scale < (1U<<( bits_per_int-2))) {427 pcpu_scale = (UPSCALE*64*(uint16_t)busy_jifs ? : 1); 428 while (pcpu_scale < (1U<<(BITS_PER_INT-2))) { 325 429 pcpu_scale *= 4; 326 430 pcpu_shift += 2; … … 332 436 pcpu_shift -= 2; 333 437 } 438 pcpu_half = (1U << pcpu_shift) / (ENABLE_FEATURE_TOP_DECIMALS? 20 : 2); 334 439 /* printf(" pmem_scale=%u pcpu_scale=%u ", pmem_scale, pcpu_scale); */ 335 440 #endif 336 441 337 while (count--) { 338 div_t pmem = div( (s->rss*pmem_scale) >> pmem_shift, 10); 339 int col = scr_width+1; 340 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(div_t pcpu;) 341 342 if (s->rss >= 100*1024) 343 sprintf(rss_str_buf, "%6ldM", s->rss/1024); 442 /* Ok, all prelim data is ready, go thru the list */ 443 while (count-- > 0) { 444 int col = scr_width; 445 CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); 446 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 447 CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift); 448 #endif 449 450 if (s->vsz >= 100*1024) 451 sprintf(vsz_str_buf, "%6ldM", s->vsz/1024); 344 452 else 345 sprintf(rss_str_buf, "%7ld", s->rss); 346 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);) 347 col -= printf("\n%5d %-8s %s %s%6d%3u.%c" \ 348 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c") " ", 349 s->pid, s->user, s->state, rss_str_buf, s->ppid, 350 USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu.quot, '0'+pcpu.rem,) 351 pmem.quot, '0'+pmem.rem); 352 if (col>0) 353 printf("%.*s", col, s->short_cmd); 453 sprintf(vsz_str_buf, "%7ld", s->vsz); 454 // PID PPID USER STAT VSZ %MEM [%CPU] COMMAND 455 col -= printf("\n" "%5u%6u %-8.8s %s%s" FMT 456 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 457 FMT 458 #endif 459 " ", 460 s->pid, s->ppid, get_cached_username(s->uid), 461 s->state, vsz_str_buf, 462 SHOW_STAT(pmem) 463 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 464 , SHOW_STAT(pcpu) 465 #endif 466 ); 467 if (col > 0) { 468 char buf[col + 1]; 469 read_cmdline(buf, col, s->pid, s->comm); 470 fputs(buf, stdout); 471 } 354 472 /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, 355 473 jif.busy - prev_jif.busy, jif.total - prev_jif.total); */ … … 357 475 } 358 476 /* printf(" %d", hist_iterations); */ 359 putchar( '\r');477 putchar(OPT_BATCH_MODE ? '\n' : '\r'); 360 478 fflush(stdout); 361 479 } 480 #undef UPSCALE 481 #undef SHOW_STAT 482 #undef CALC_STAT 483 #undef FMT 484 362 485 363 486 static void clearmems(void) 364 487 { 488 clear_username_cache(); 365 489 free(top); 366 490 top = 0; … … 368 492 } 369 493 370 #ifdef CONFIG_FEATURE_USE_TERMIOS 494 495 #if ENABLE_FEATURE_USE_TERMIOS 371 496 #include <termios.h> 372 497 #include <signal.h> 373 498 374 375 static struct termios initial_settings;376 377 499 static void reset_term(void) 378 500 { 379 501 tcsetattr(0, TCSANOW, (void *) &initial_settings); 380 #if def CONFIG_FEATURE_CLEAN_UP502 #if ENABLE_FEATURE_CLEAN_UP 381 503 clearmems(); 382 #if def CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE504 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 383 505 free(prev_hist); 384 506 #endif 385 #endif /* CONFIG_FEATURE_CLEAN_UP */507 #endif /* FEATURE_CLEAN_UP */ 386 508 } 387 509 … … 391 513 exit(1); 392 514 } 393 #endif /* CONFIG_FEATURE_USE_TERMIOS */ 394 395 515 #endif /* FEATURE_USE_TERMIOS */ 516 517 518 int top_main(int argc, char **argv); 396 519 int top_main(int argc, char **argv) 397 520 { 398 int opt, interval, lines, col; 399 char *sinterval; 400 #ifdef CONFIG_FEATURE_USE_TERMIOS 521 int count, lines, col; 522 unsigned interval = 5; /* default update rate is 5 seconds */ 523 unsigned iterations = UINT_MAX; /* 2^32 iterations by default :) */ 524 char *sinterval, *siterations; 525 #if ENABLE_FEATURE_USE_TERMIOS 401 526 struct termios new_settings; 402 527 struct timeval tv; 403 528 fd_set readfds; 404 529 unsigned char c; 405 #endif /* CONFIG_FEATURE_USE_TERMIOS */ 530 #endif /* FEATURE_USE_TERMIOS */ 531 532 interval = 5; 406 533 407 534 /* do normal option parsing */ 408 opt = bb_getopt_ulflags(argc, argv, "d:", &sinterval); 409 if ((opt & 1)) { 410 interval = atoi(sinterval); 411 } else { 412 /* Default update rate is 5 seconds */ 413 interval = 5; 414 } 535 opt_complementary = "-"; 536 getopt32(argv, "d:n:b", &sinterval, &siterations); 537 if (option_mask32 & 0x1) interval = xatou(sinterval); // -d 538 if (option_mask32 & 0x2) iterations = xatou(siterations); // -n 539 //if (option_mask32 & 0x4) // -b 415 540 416 541 /* change to /proc */ 417 bb_xchdir("/proc");418 #if def CONFIG_FEATURE_USE_TERMIOS542 xchdir("/proc"); 543 #if ENABLE_FEATURE_USE_TERMIOS 419 544 tcgetattr(0, (void *) &initial_settings); 420 545 memcpy(&new_settings, &initial_settings, sizeof(struct termios)); 421 new_settings.c_lflag &= ~(ISIG | ICANON); /* unbuffered input */ 422 /* Turn off echoing */ 423 new_settings.c_lflag &= ~(ECHO | ECHONL); 546 /* unbuffered input, turn off echo */ 547 new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL); 424 548 425 549 signal(SIGTERM, sig_catcher); … … 427 551 tcsetattr(0, TCSANOW, (void *) &new_settings); 428 552 atexit(reset_term); 429 #endif /* CONFIG_FEATURE_USE_TERMIOS */430 431 #if def CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE553 #endif /* FEATURE_USE_TERMIOS */ 554 555 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 432 556 sort_function[0] = pcpu_sort; 433 557 sort_function[1] = mem_sort; … … 435 559 #else 436 560 sort_function = mem_sort; 437 #endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */561 #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 438 562 439 563 while (1) { 440 procps_status_t *p ;564 procps_status_t *p = NULL; 441 565 442 566 /* Default to 25 lines - 5 lines for status */ 443 lines = 24 - 3 ;567 lines = 24 - 3 USE_FEATURE_TOP_CPU_GLOBAL_PERCENTS( - 1); 444 568 col = 79; 445 #if def CONFIG_FEATURE_USE_TERMIOS569 #if ENABLE_FEATURE_USE_TERMIOS 446 570 get_terminal_width_height(0, &col, &lines); 447 571 if (lines < 5 || col < MIN_WIDTH) { … … 449 573 continue; 450 574 } 451 lines -= 3 ;452 #endif /* CONFIG_FEATURE_USE_TERMIOS */575 lines -= 3 USE_FEATURE_TOP_CPU_GLOBAL_PERCENTS( + 1); 576 #endif /* FEATURE_USE_TERMIOS */ 453 577 454 578 /* read process IDs & status for all the processes */ 455 while ((p = procps_scan(0)) != 0) { 579 while ((p = procps_scan(p, 0 580 | PSSCAN_PID 581 | PSSCAN_PPID 582 | PSSCAN_VSZ 583 | PSSCAN_STIME 584 | PSSCAN_UTIME 585 | PSSCAN_STATE 586 | PSSCAN_COMM 587 | PSSCAN_SID 588 | PSSCAN_UIDGID 589 ))) { 456 590 int n = ntop; 457 458 top = xrealloc(top, (++ntop)*sizeof(procps_status_t)); 459 memcpy(top + n, p, sizeof(procps_status_t)); 591 top = xrealloc(top, (++ntop) * sizeof(*top)); 592 top[n].pid = p->pid; 593 top[n].ppid = p->ppid; 594 top[n].vsz = p->vsz; 595 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 596 top[n].ticks = p->stime + p->utime; 597 #endif 598 top[n].uid = p->uid; 599 strcpy(top[n].state, p->state); 600 strcpy(top[n].comm, p->comm); 460 601 } 461 602 if (ntop == 0) { 462 bb_error_msg_and_die(" Can't findprocess info in /proc");603 bb_error_msg_and_die("no process info in /proc"); 463 604 } 464 #if def CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE605 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 465 606 if (!prev_hist_count) { 466 607 do_stats(); … … 470 611 } 471 612 do_stats(); 472 qsort(top, ntop, sizeof(procps_status_t), (void*)mult_lvl_cmp); 473 #else 474 qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function); 475 #endif /* CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 476 opt = lines; 477 if (opt > ntop) { 478 opt = ntop; 613 /* TODO: we don't need to sort all 10000 processes, we need to find top 24! */ 614 qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp); 615 #else 616 qsort(top, ntop, sizeof(top_status_t), (void*)sort_function); 617 #endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ 618 count = lines; 619 if (OPT_BATCH_MODE || count > ntop) { 620 count = ntop; 479 621 } 480 622 /* show status for each of the processes */ 481 display_status( opt, col);482 #if def CONFIG_FEATURE_USE_TERMIOS623 display_status(count, col); 624 #if ENABLE_FEATURE_USE_TERMIOS 483 625 tv.tv_sec = interval; 484 626 tv.tv_usec = 0; … … 493 635 break; 494 636 if (c == 'M') { 495 #if def CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE637 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 496 638 sort_function[0] = mem_sort; 497 639 sort_function[1] = pcpu_sort; … … 501 643 #endif 502 644 } 503 #if def CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE645 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 504 646 if (c == 'P') { 505 647 sort_function[0] = pcpu_sort; … … 514 656 #endif 515 657 if (c == 'N') { 516 #if def CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE658 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 517 659 sort_function[0] = pid_sort; 518 660 #else … … 521 663 } 522 664 } 665 if (!--iterations) 666 break; 523 667 #else 524 668 sleep(interval); 525 #endif /* CONFIG_FEATURE_USE_TERMIOS */669 #endif /* FEATURE_USE_TERMIOS */ 526 670 clearmems(); 527 671 }
Note:
See TracChangeset
for help on using the changeset viewer.