Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/procps/top.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/procps/top.c
r3232 r3621 106 106 107 107 #include "libbb.h" 108 #include "common_bufsiz.h" 108 109 109 110 … … 184 185 }; //FIX_ALIASING; - large code growth 185 186 enum { LINE_BUF_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line_buf) }; 186 #define G (*(struct globals*)&bb_common_bufsiz1) 187 struct BUG_bad_size { 188 char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; 189 char BUG_line_buf_too_small[LINE_BUF_SIZE > 80 ? 1 : -1]; 190 }; 187 #define G (*(struct globals*)bb_common_bufsiz1) 191 188 #define top (G.top ) 192 189 #define ntop (G.ntop ) … … 205 202 #define total_pcpu (G.total_pcpu ) 206 203 #define line_buf (G.line_buf ) 207 #define INIT_G() do { } while (0) 204 #define INIT_G() do { \ 205 setup_common_bufsiz(); \ 206 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \ 207 BUILD_BUG_ON(LINE_BUF_SIZE <= 80); \ 208 } while (0) 208 209 209 210 enum { … … 265 266 { 266 267 #if !ENABLE_FEATURE_TOP_SMP_CPU 267 static const char fmt[] = "cpu %llu %llu %llu %llu %llu %llu %llu %llu";268 static const char fmt[] ALIGN1 = "cpu %llu %llu %llu %llu %llu %llu %llu %llu"; 268 269 #else 269 static const char fmt[] = "cp%*s %llu %llu %llu %llu %llu %llu %llu %llu";270 static const char fmt[] ALIGN1 = "cp%*s %llu %llu %llu %llu %llu %llu %llu %llu"; 270 271 #endif 271 272 int ret; … … 295 296 prev_jif = cur_jif; 296 297 if (read_cpu_jiffy(fp, &cur_jif) < 4) 297 bb_error_msg_and_die("can't read /proc/stat");298 bb_error_msg_and_die("can't read '%s'", "/proc/stat"); 298 299 299 300 #if !ENABLE_FEATURE_TOP_SMP_CPU … … 500 501 #endif 501 502 503 enum { 504 MI_MEMTOTAL, 505 MI_MEMFREE, 506 MI_MEMSHARED, 507 MI_SHMEM, 508 MI_BUFFERS, 509 MI_CACHED, 510 MI_SWAPTOTAL, 511 MI_SWAPFREE, 512 MI_DIRTY, 513 MI_WRITEBACK, 514 MI_ANONPAGES, 515 MI_MAPPED, 516 MI_SLAB, 517 MI_MAX 518 }; 519 520 static void parse_meminfo(unsigned long meminfo[MI_MAX]) 521 { 522 static const char fields[] ALIGN1 = 523 "MemTotal\0" 524 "MemFree\0" 525 "MemShared\0" 526 "Shmem\0" 527 "Buffers\0" 528 "Cached\0" 529 "SwapTotal\0" 530 "SwapFree\0" 531 "Dirty\0" 532 "Writeback\0" 533 "AnonPages\0" 534 "Mapped\0" 535 "Slab\0"; 536 char buf[60]; /* actual lines we expect are ~30 chars or less */ 537 FILE *f; 538 int i; 539 540 memset(meminfo, 0, sizeof(meminfo[0]) * MI_MAX); 541 f = xfopen_for_read("meminfo"); 542 while (fgets(buf, sizeof(buf), f) != NULL) { 543 char *c = strchr(buf, ':'); 544 if (!c) 545 continue; 546 *c = '\0'; 547 i = index_in_strings(fields, buf); 548 if (i >= 0) 549 meminfo[i] = strtoul(c+1, NULL, 10); 550 } 551 fclose(f); 552 } 553 502 554 static unsigned long display_header(int scr_width, int *lines_rem_p) 503 555 { 504 FILE *fp; 505 char buf[80]; 506 char scrbuf[80]; 507 unsigned long total, used, mfree, shared, buffers, cached; 508 509 /* read memory info */ 510 fp = xfopen_for_read("meminfo"); 511 512 /* 513 * Old kernels (such as 2.4.x) had a nice summary of memory info that 514 * we could parse, however this is gone entirely in 2.6. Try parsing 515 * the old way first, and if that fails, parse each field manually. 516 * 517 * First, we read in the first line. Old kernels will have bogus 518 * strings we don't care about, whereas new kernels will start right 519 * out with MemTotal: 520 * -- PFM. 521 */ 522 if (fscanf(fp, "MemTotal: %lu %s\n", &total, buf) != 2) { 523 fgets(buf, sizeof(buf), fp); /* skip first line */ 524 525 fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu", 526 &total, &used, &mfree, &shared, &buffers, &cached); 527 /* convert to kilobytes */ 528 used /= 1024; 529 mfree /= 1024; 530 shared /= 1024; 531 buffers /= 1024; 532 cached /= 1024; 533 total /= 1024; 534 } else { 535 /* 536 * Revert to manual parsing, which incidentally already has the 537 * sizes in kilobytes. This should be safe for both 2.4 and 538 * 2.6. 539 */ 540 fscanf(fp, "MemFree: %lu %s\n", &mfree, buf); 541 542 /* 543 * MemShared: is no longer present in 2.6. Report this as 0, 544 * to maintain consistent behavior with normal procps. 545 */ 546 if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2) 547 shared = 0; 548 549 fscanf(fp, "Buffers: %lu %s\n", &buffers, buf); 550 fscanf(fp, "Cached: %lu %s\n", &cached, buf); 551 552 used = total - mfree; 553 } 554 fclose(fp); 555 556 /* output memory info */ 556 char scrbuf[100]; /* [80] was a bit too low on 8Gb ram box */ 557 char *buf; 558 unsigned long meminfo[MI_MAX]; 559 560 parse_meminfo(meminfo); 561 562 /* Output memory info */ 557 563 if (scr_width > (int)sizeof(scrbuf)) 558 564 scr_width = sizeof(scrbuf); 559 565 snprintf(scrbuf, scr_width, 560 566 "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", 561 used, mfree, shared, buffers, cached); 562 /* go to top & clear to the end of screen */ 567 meminfo[MI_MEMTOTAL] - meminfo[MI_MEMFREE], 568 meminfo[MI_MEMFREE], 569 meminfo[MI_MEMSHARED] + meminfo[MI_SHMEM], 570 meminfo[MI_BUFFERS], 571 meminfo[MI_CACHED]); 572 /* Go to top & clear to the end of screen */ 563 573 printf(OPT_BATCH_MODE ? "%s\n" : "\033[H\033[J%s\n", scrbuf); 564 574 (*lines_rem_p)--; 565 575 566 /* Display CPU time split as percentage of total time 567 * This displays either a cumulative line or one line per CPU 576 /* Display CPU time split as percentage of total time. 577 * This displays either a cumulative line or one line per CPU. 568 578 */ 569 579 display_cpus(scr_width, scrbuf, lines_rem_p); 570 580 571 /* read load average as a string */ 572 buf[0] = '\0'; 573 open_read_close("loadavg", buf, sizeof(buf) - 1); 574 buf[sizeof(buf) - 1] = '\n'; 575 *strchr(buf, '\n') = '\0'; 576 snprintf(scrbuf, scr_width, "Load average: %s", buf); 581 /* Read load average as a string */ 582 buf = stpcpy(scrbuf, "Load average: "); 583 open_read_close("loadavg", buf, sizeof(scrbuf) - sizeof("Load average: ")); 584 scrbuf[scr_width - 1] = '\0'; 585 strchrnul(buf, '\n')[0] = '\0'; 577 586 puts(scrbuf); 578 587 (*lines_rem_p)--; 579 588 580 return total;589 return meminfo[MI_MEMTOTAL]; 581 590 } 582 591 … … 678 687 sprintf(vsz_str_buf, "%6ldm", s->vsz/1024); 679 688 else 680 sprintf(vsz_str_buf, "%7l d", s->vsz);689 sprintf(vsz_str_buf, "%7lu", s->vsz); 681 690 /* PID PPID USER STAT VSZ %VSZ [%CPU] COMMAND */ 682 691 col = snprintf(line_buf, scr_width, … … 782 791 static void display_topmem_header(int scr_width, int *lines_rem_p) 783 792 { 784 enum { 785 TOTAL = 0, MFREE, BUF, CACHE, 786 SWAPTOTAL, SWAPFREE, DIRTY, 787 MWRITE, ANON, MAP, SLAB, 788 NUM_FIELDS 789 }; 790 static const char match[NUM_FIELDS][12] = { 791 "\x09" "MemTotal:", // TOTAL 792 "\x08" "MemFree:", // MFREE 793 "\x08" "Buffers:", // BUF 794 "\x07" "Cached:", // CACHE 795 "\x0a" "SwapTotal:", // SWAPTOTAL 796 "\x09" "SwapFree:", // SWAPFREE 797 "\x06" "Dirty:", // DIRTY 798 "\x0a" "Writeback:", // MWRITE 799 "\x0a" "AnonPages:", // ANON 800 "\x07" "Mapped:", // MAP 801 "\x05" "Slab:", // SLAB 802 }; 803 char meminfo_buf[4 * 1024]; 804 const char *Z[NUM_FIELDS]; 805 unsigned i; 806 int sz; 807 808 for (i = 0; i < NUM_FIELDS; i++) 809 Z[i] = "?"; 810 811 /* read memory info */ 812 sz = open_read_close("meminfo", meminfo_buf, sizeof(meminfo_buf) - 1); 813 if (sz >= 0) { 814 char *p = meminfo_buf; 815 meminfo_buf[sz] = '\0'; 816 /* Note that fields always appear in the match[] order */ 817 for (i = 0; i < NUM_FIELDS; i++) { 818 char *found = strstr(p, match[i] + 1); 819 if (found) { 820 /* Cut "NNNN" out of " NNNN kb" */ 821 char *s = skip_whitespace(found + match[i][0]); 822 p = skip_non_whitespace(s); 823 *p++ = '\0'; 824 Z[i] = s; 825 } 826 } 827 } 793 unsigned long meminfo[MI_MAX]; 794 795 parse_meminfo(meminfo); 828 796 829 797 snprintf(line_buf, LINE_BUF_SIZE, 830 "Mem total:%s anon:%s map:%s free:%s", 831 Z[TOTAL], Z[ANON], Z[MAP], Z[MFREE]); 798 "Mem total:%lu anon:%lu map:%lu free:%lu", 799 meminfo[MI_MEMTOTAL], 800 meminfo[MI_ANONPAGES], 801 meminfo[MI_MAPPED], 802 meminfo[MI_MEMFREE]); 832 803 printf(OPT_BATCH_MODE ? "%.*s\n" : "\033[H\033[J%.*s\n", scr_width, line_buf); 833 804 834 805 snprintf(line_buf, LINE_BUF_SIZE, 835 " slab:%s buf:%s cache:%s dirty:%s write:%s", 836 Z[SLAB], Z[BUF], Z[CACHE], Z[DIRTY], Z[MWRITE]); 806 " slab:%lu buf:%lu cache:%lu dirty:%lu write:%lu", 807 meminfo[MI_SLAB], 808 meminfo[MI_BUFFERS], 809 meminfo[MI_CACHED], 810 meminfo[MI_DIRTY], 811 meminfo[MI_WRITEBACK]); 837 812 printf("%.*s\n", scr_width, line_buf); 838 813 839 814 snprintf(line_buf, LINE_BUF_SIZE, 840 "Swap total:%s free:%s", // TODO: % used? 841 Z[SWAPTOTAL], Z[SWAPFREE]); 815 "Swap total:%lu free:%lu", // TODO: % used? 816 meminfo[MI_SWAPTOTAL], 817 meminfo[MI_SWAPFREE]); 842 818 printf("%.*s\n", scr_width, line_buf); 843 819 … … 848 824 { 849 825 /* see http://en.wikipedia.org/wiki/Tera */ 850 smart_ulltoa5(ul, buf, " mgtpezy"); 851 buf[5] = ' '; 826 smart_ulltoa5(ul, buf, " mgtpezy")[0] = ' '; 852 827 } 853 828 … … 857 832 #define MIN_WIDTH sizeof(HDR_STR) 858 833 const topmem_status_t *s = topmem + G_scroll_ofs; 834 char *cp, ch; 859 835 860 836 display_topmem_header(scr_width, &lines_rem); 837 861 838 strcpy(line_buf, HDR_STR " COMMAND"); 862 line_buf[11 + sort_field * 6] = "^_"[inverted]; 839 /* Mark the ^FIELD^ we sort by */ 840 cp = &line_buf[5 + sort_field * 6]; 841 ch = "^_"[inverted]; 842 cp[6] = ch; 843 do *cp++ = ch; while (*cp == ' '); 844 863 845 printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf); 864 846 lines_rem--; … … 919 901 static unsigned handle_input(unsigned scan_mask, unsigned interval) 920 902 { 921 struct pollfd pfd[1];922 923 903 if (option_mask32 & OPT_EOF) { 924 904 /* EOF on stdin ("top </dev/null") */ … … 926 906 return scan_mask; 927 907 } 928 929 pfd[0].fd = 0;930 pfd[0].events = POLLIN;931 908 932 909 while (1) { … … 1205 1182 while ((p = procps_scan(p, scan_mask)) != NULL) { 1206 1183 int n; 1207 #if ENABLE_FEATURE_TOPMEM 1208 if (scan_mask != TOPMEM_MASK) 1209 #endif 1210 { 1184 1185 IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) { 1211 1186 n = ntop; 1212 1187 top = xrealloc_vector(top, 6, ntop++); … … 1248 1223 } 1249 1224 1250 if (scan_mask != TOPMEM_MASK) {1225 IF_FEATURE_TOPMEM(if (scan_mask != TOPMEM_MASK)) { 1251 1226 #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE 1252 1227 if (!prev_hist_count) { … … 1262 1237 qsort(top, ntop, sizeof(top_status_t), (void*)(sort_function[0])); 1263 1238 #endif 1239 display_process_list(G.lines, col); 1264 1240 } 1265 1241 #if ENABLE_FEATURE_TOPMEM 1266 1242 else { /* TOPMEM */ 1267 1243 qsort(topmem, ntop, sizeof(topmem_status_t), (void*)topmem_sort); 1268 }1269 #endif1270 if (scan_mask != TOPMEM_MASK)1271 display_process_list(G.lines, col);1272 #if ENABLE_FEATURE_TOPMEM1273 else1274 1244 display_topmem_process_list(G.lines, col); 1245 } 1275 1246 #endif 1276 1247 clearmems(); … … 1281 1252 #else 1282 1253 scan_mask = handle_input(scan_mask, interval); 1283 #endif /* FEATURE_USE_TERMIOS */1254 #endif 1284 1255 } /* end of "while (not Q)" */ 1285 1256
Note:
See TracChangeset
for help on using the changeset viewer.