aboutsummaryrefslogtreecommitdiff
path: root/procps
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2014-10-06 12:50:22 +0100
committerRon Yorston <rmy@pobox.com>2014-10-06 12:50:22 +0100
commitb04d11dcbadda2620743a1dd923938f2f3043a38 (patch)
tree971afe425a81304b79e44122e220c7a69efe2616 /procps
parent124bbf02948b7ac0babb4ead04acd1559db182d3 (diff)
parent760d035699c4a878f9109544c1d35ea0d5f6b76c (diff)
downloadbusybox-w32-b04d11dcbadda2620743a1dd923938f2f3043a38.tar.gz
busybox-w32-b04d11dcbadda2620743a1dd923938f2f3043a38.tar.bz2
busybox-w32-b04d11dcbadda2620743a1dd923938f2f3043a38.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'procps')
-rw-r--r--procps/top.c197
1 files changed, 86 insertions, 111 deletions
diff --git a/procps/top.c b/procps/top.c
index 530f45fa1..3d67c3cfd 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -499,85 +499,93 @@ static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p)
499# define display_cpus(scr_width, scrbuf, lines_rem) ((void)0) 499# define display_cpus(scr_width, scrbuf, lines_rem) ((void)0)
500#endif 500#endif
501 501
502static unsigned long display_header(int scr_width, int *lines_rem_p) 502enum {
503{ 503 MI_MEMTOTAL,
504 FILE *fp; 504 MI_MEMFREE,
505 char buf[80]; 505 MI_MEMSHARED,
506 char scrbuf[80]; 506 MI_SHMEM,
507 unsigned long total, used, mfree, shared, buffers, cached; 507 MI_BUFFERS,
508 508 MI_CACHED,
509 /* read memory info */ 509 MI_SWAPTOTAL,
510 fp = xfopen_for_read("meminfo"); 510 MI_SWAPFREE,
511 MI_DIRTY,
512 MI_WRITEBACK,
513 MI_ANONPAGES,
514 MI_MAPPED,
515 MI_SLAB,
516 MI_MAX
517};
511 518
512 /* 519static void parse_meminfo(unsigned long meminfo[MI_MAX])
513 * Old kernels (such as 2.4.x) had a nice summary of memory info that 520{
514 * we could parse, however this is gone entirely in 2.6. Try parsing 521 static const char fields[] =
515 * the old way first, and if that fails, parse each field manually. 522 "MemTotal\0"
516 * 523 "MemFree\0"
517 * First, we read in the first line. Old kernels will have bogus 524 "MemShared\0"
518 * strings we don't care about, whereas new kernels will start right 525 "Shmem\0"
519 * out with MemTotal: 526 "Buffers\0"
520 * -- PFM. 527 "Cached\0"
521 */ 528 "SwapTotal\0"
522 if (fscanf(fp, "MemTotal: %lu %s\n", &total, buf) != 2) { 529 "SwapFree\0"
523 fgets(buf, sizeof(buf), fp); /* skip first line */ 530 "Dirty\0"
524 531 "Writeback\0"
525 fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu", 532 "AnonPages\0"
526 &total, &used, &mfree, &shared, &buffers, &cached); 533 "Mapped\0"
527 /* convert to kilobytes */ 534 "Slab\0";
528 used /= 1024; 535 char buf[60]; /* actual lines we expect are ~30 chars or less */
529 mfree /= 1024; 536 FILE *f;
530 shared /= 1024; 537 int i;
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 538
542 /* 539 memset(meminfo, 0, sizeof(meminfo[0]) * MI_MAX);
543 * MemShared: is no longer present in 2.6. Report this as 0, 540 f = xfopen_for_read("meminfo");
544 * to maintain consistent behavior with normal procps. 541 while (fgets(buf, sizeof(buf), f) != NULL) {
545 */ 542 char *c = strchr(buf, ':');
546 if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2) 543 if (!c)
547 shared = 0; 544 continue;
545 *c = '\0';
546 i = index_in_strings(fields, buf);
547 if (i >= 0)
548 meminfo[i] = strtoul(c+1, NULL, 10);
549 }
550 fclose(f);
551}
548 552
549 fscanf(fp, "Buffers: %lu %s\n", &buffers, buf); 553static unsigned long display_header(int scr_width, int *lines_rem_p)
550 fscanf(fp, "Cached: %lu %s\n", &cached, buf); 554{
555 char scrbuf[100]; /* [80] was a bit too low on 8Gb ram box */
556 char *buf;
557 unsigned long meminfo[MI_MAX];
551 558
552 used = total - mfree; 559 parse_meminfo(meminfo);
553 }
554 fclose(fp);
555 560
556 /* output memory info */ 561 /* Output memory info */
557 if (scr_width > (int)sizeof(scrbuf)) 562 if (scr_width > (int)sizeof(scrbuf))
558 scr_width = sizeof(scrbuf); 563 scr_width = sizeof(scrbuf);
559 snprintf(scrbuf, scr_width, 564 snprintf(scrbuf, scr_width,
560 "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", 565 "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached",
561 used, mfree, shared, buffers, cached); 566 meminfo[MI_MEMTOTAL] - meminfo[MI_MEMFREE],
562 /* go to top & clear to the end of screen */ 567 meminfo[MI_MEMFREE],
568 meminfo[MI_MEMSHARED] + meminfo[MI_SHMEM],
569 meminfo[MI_BUFFERS],
570 meminfo[MI_CACHED]);
571 /* Go to top & clear to the end of screen */
563 printf(OPT_BATCH_MODE ? "%s\n" : "\033[H\033[J%s\n", scrbuf); 572 printf(OPT_BATCH_MODE ? "%s\n" : "\033[H\033[J%s\n", scrbuf);
564 (*lines_rem_p)--; 573 (*lines_rem_p)--;
565 574
566 /* Display CPU time split as percentage of total time 575 /* Display CPU time split as percentage of total time.
567 * This displays either a cumulative line or one line per CPU 576 * This displays either a cumulative line or one line per CPU.
568 */ 577 */
569 display_cpus(scr_width, scrbuf, lines_rem_p); 578 display_cpus(scr_width, scrbuf, lines_rem_p);
570 579
571 /* read load average as a string */ 580 /* Read load average as a string */
572 buf[0] = '\0'; 581 buf = stpcpy(scrbuf, "Load average: ");
573 open_read_close("loadavg", buf, sizeof(buf) - 1); 582 open_read_close("loadavg", buf, sizeof(scrbuf) - sizeof("Load average: "));
574 buf[sizeof(buf) - 1] = '\n'; 583 scrbuf[scr_width - 1] = '\0';
575 *strchr(buf, '\n') = '\0'; 584 strchrnul(buf, '\n')[0] = '\0';
576 snprintf(scrbuf, scr_width, "Load average: %s", buf);
577 puts(scrbuf); 585 puts(scrbuf);
578 (*lines_rem_p)--; 586 (*lines_rem_p)--;
579 587
580 return total; 588 return meminfo[MI_MEMTOTAL];
581} 589}
582 590
583static NOINLINE void display_process_list(int lines_rem, int scr_width) 591static NOINLINE void display_process_list(int lines_rem, int scr_width)
@@ -781,64 +789,31 @@ static int topmem_sort(char *a, char *b)
781/* display header info (meminfo / loadavg) */ 789/* display header info (meminfo / loadavg) */
782static void display_topmem_header(int scr_width, int *lines_rem_p) 790static void display_topmem_header(int scr_width, int *lines_rem_p)
783{ 791{
784 enum { 792 unsigned long meminfo[MI_MAX];
785 TOTAL = 0, MFREE, BUF, CACHE, 793
786 SWAPTOTAL, SWAPFREE, DIRTY, 794 parse_meminfo(meminfo);
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 }
828 795
829 snprintf(line_buf, LINE_BUF_SIZE, 796 snprintf(line_buf, LINE_BUF_SIZE,
830 "Mem total:%s anon:%s map:%s free:%s", 797 "Mem total:%lu anon:%lu map:%lu free:%lu",
831 Z[TOTAL], Z[ANON], Z[MAP], Z[MFREE]); 798 meminfo[MI_MEMTOTAL],
799 meminfo[MI_ANONPAGES],
800 meminfo[MI_MAPPED],
801 meminfo[MI_MEMFREE]);
832 printf(OPT_BATCH_MODE ? "%.*s\n" : "\033[H\033[J%.*s\n", scr_width, line_buf); 802 printf(OPT_BATCH_MODE ? "%.*s\n" : "\033[H\033[J%.*s\n", scr_width, line_buf);
833 803
834 snprintf(line_buf, LINE_BUF_SIZE, 804 snprintf(line_buf, LINE_BUF_SIZE,
835 " slab:%s buf:%s cache:%s dirty:%s write:%s", 805 " slab:%lu buf:%lu cache:%lu dirty:%lu write:%lu",
836 Z[SLAB], Z[BUF], Z[CACHE], Z[DIRTY], Z[MWRITE]); 806 meminfo[MI_SLAB],
807 meminfo[MI_BUFFERS],
808 meminfo[MI_CACHED],
809 meminfo[MI_DIRTY],
810 meminfo[MI_WRITEBACK]);
837 printf("%.*s\n", scr_width, line_buf); 811 printf("%.*s\n", scr_width, line_buf);
838 812
839 snprintf(line_buf, LINE_BUF_SIZE, 813 snprintf(line_buf, LINE_BUF_SIZE,
840 "Swap total:%s free:%s", // TODO: % used? 814 "Swap total:%lu free:%lu", // TODO: % used?
841 Z[SWAPTOTAL], Z[SWAPFREE]); 815 meminfo[MI_SWAPTOTAL],
816 meminfo[MI_SWAPFREE]);
842 printf("%.*s\n", scr_width, line_buf); 817 printf("%.*s\n", scr_width, line_buf);
843 818
844 (*lines_rem_p) -= 3; 819 (*lines_rem_p) -= 3;