diff options
-rw-r--r-- | procps/top.c | 196 |
1 files changed, 86 insertions, 110 deletions
diff --git a/procps/top.c b/procps/top.c index 530f45f..62f9421 100644 --- a/procps/top.c +++ b/procps/top.c @@ -499,85 +499,94 @@ static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p) # define display_cpus(scr_width, scrbuf, lines_rem) ((void)0) #endif -static unsigned long display_header(int scr_width, int *lines_rem_p) -{ - FILE *fp; - char buf[80]; - char scrbuf[80]; - unsigned long total, used, mfree, shared, buffers, cached; +enum { + MI_MEMTOTAL, + MI_MEMFREE, + MI_MEMSHARED, + MI_SHMEM, + MI_BUFFERS, + MI_CACHED, + MI_SWAPTOTAL, + MI_SWAPFREE, + MI_DIRTY, + MI_WRITEBACK, + MI_ANONPAGES, + MI_MAPPED, + MI_SLAB, + MI_MAX +}; - /* read memory info */ - fp = xfopen_for_read("meminfo"); +static void parse_meminfo(unsigned long meminfo[MI_MAX]) +{ + static const char fields[] = + "MemTotal\0" + "MemFree\0" + "MemShared\0" + "Shmem\0" + "Buffers\0" + "Cached\0" + "SwapTotal\0" + "SwapFree\0" + "Dirty\0" + "Writeback\0" + "AnonPages\0" + "Mapped\0" + "Slab\0"; + char buf[60]; /* actual lines we expect are ~30 chars or less */ + FILE *f; + int i; - /* - * Old kernels (such as 2.4.x) had a nice summary of memory info that - * we could parse, however this is gone entirely in 2.6. Try parsing - * the old way first, and if that fails, parse each field manually. - * - * First, we read in the first line. Old kernels will have bogus - * strings we don't care about, whereas new kernels will start right - * out with MemTotal: - * -- PFM. - */ - if (fscanf(fp, "MemTotal: %lu %s\n", &total, buf) != 2) { - fgets(buf, sizeof(buf), fp); /* skip first line */ - - fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu", - &total, &used, &mfree, &shared, &buffers, &cached); - /* convert to kilobytes */ - used /= 1024; - mfree /= 1024; - shared /= 1024; - buffers /= 1024; - cached /= 1024; - total /= 1024; - } else { - /* - * Revert to manual parsing, which incidentally already has the - * sizes in kilobytes. This should be safe for both 2.4 and - * 2.6. - */ - fscanf(fp, "MemFree: %lu %s\n", &mfree, buf); + memset(meminfo, 0, sizeof(meminfo)); + f = xfopen_for_read("meminfo"); + while (fgets(buf, sizeof(buf), f) != NULL) { + char *c = strchr(buf, ':'); + if (!c) + continue; + *c = '\0'; + i = index_in_strings(fields, buf); + if (i >= 0) + meminfo[i] = strtoul(c+1, NULL, 10); + } + fclose(f); +} - /* - * MemShared: is no longer present in 2.6. Report this as 0, - * to maintain consistent behavior with normal procps. - */ - if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2) - shared = 0; - fscanf(fp, "Buffers: %lu %s\n", &buffers, buf); - fscanf(fp, "Cached: %lu %s\n", &cached, buf); +static unsigned long display_header(int scr_width, int *lines_rem_p) +{ + char scrbuf[100]; /* [80] was a bit too low on 8Gb ram box */ + char *buf; + unsigned long meminfo[MI_MAX]; - used = total - mfree; - } - fclose(fp); + parse_meminfo(meminfo); - /* output memory info */ + /* Output memory info */ if (scr_width > (int)sizeof(scrbuf)) scr_width = sizeof(scrbuf); snprintf(scrbuf, scr_width, "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", - used, mfree, shared, buffers, cached); - /* go to top & clear to the end of screen */ + meminfo[MI_MEMTOTAL] - meminfo[MI_MEMFREE], + meminfo[MI_MEMFREE], + meminfo[MI_MEMSHARED] + meminfo[MI_SHMEM], + meminfo[MI_BUFFERS], + meminfo[MI_CACHED]); + /* Go to top & clear to the end of screen */ printf(OPT_BATCH_MODE ? "%s\n" : "\033[H\033[J%s\n", scrbuf); (*lines_rem_p)--; - /* Display CPU time split as percentage of total time - * This displays either a cumulative line or one line per CPU + /* Display CPU time split as percentage of total time. + * This displays either a cumulative line or one line per CPU. */ display_cpus(scr_width, scrbuf, lines_rem_p); - /* read load average as a string */ - buf[0] = '\0'; - open_read_close("loadavg", buf, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = '\n'; - *strchr(buf, '\n') = '\0'; - snprintf(scrbuf, scr_width, "Load average: %s", buf); + /* Read load average as a string */ + buf = stpcpy(scrbuf, "Load average: "); + open_read_close("loadavg", buf, sizeof(scrbuf) - sizeof("Load average: ")); + scrbuf[scr_width - 1] = '\0'; + strchrnul(buf, '\n')[0] = '\0'; puts(scrbuf); (*lines_rem_p)--; - return total; + return meminfo[MI_MEMTOTAL]; } static NOINLINE void display_process_list(int lines_rem, int scr_width) @@ -781,64 +790,31 @@ static int topmem_sort(char *a, char *b) /* display header info (meminfo / loadavg) */ static void display_topmem_header(int scr_width, int *lines_rem_p) { - enum { - TOTAL = 0, MFREE, BUF, CACHE, - SWAPTOTAL, SWAPFREE, DIRTY, - MWRITE, ANON, MAP, SLAB, - NUM_FIELDS - }; - static const char match[NUM_FIELDS][12] = { - "\x09" "MemTotal:", // TOTAL - "\x08" "MemFree:", // MFREE - "\x08" "Buffers:", // BUF - "\x07" "Cached:", // CACHE - "\x0a" "SwapTotal:", // SWAPTOTAL - "\x09" "SwapFree:", // SWAPFREE - "\x06" "Dirty:", // DIRTY - "\x0a" "Writeback:", // MWRITE - "\x0a" "AnonPages:", // ANON - "\x07" "Mapped:", // MAP - "\x05" "Slab:", // SLAB - }; - char meminfo_buf[4 * 1024]; - const char *Z[NUM_FIELDS]; - unsigned i; - int sz; - - for (i = 0; i < NUM_FIELDS; i++) - Z[i] = "?"; - - /* read memory info */ - sz = open_read_close("meminfo", meminfo_buf, sizeof(meminfo_buf) - 1); - if (sz >= 0) { - char *p = meminfo_buf; - meminfo_buf[sz] = '\0'; - /* Note that fields always appear in the match[] order */ - for (i = 0; i < NUM_FIELDS; i++) { - char *found = strstr(p, match[i] + 1); - if (found) { - /* Cut "NNNN" out of " NNNN kb" */ - char *s = skip_whitespace(found + match[i][0]); - p = skip_non_whitespace(s); - *p++ = '\0'; - Z[i] = s; - } - } - } + unsigned long meminfo[MI_MAX]; + + parse_meminfo(meminfo); snprintf(line_buf, LINE_BUF_SIZE, - "Mem total:%s anon:%s map:%s free:%s", - Z[TOTAL], Z[ANON], Z[MAP], Z[MFREE]); + "Mem total:%lu anon:%lu map:%lu free:%lu", + meminfo[MI_MEMTOTAL], + meminfo[MI_ANONPAGES], + meminfo[MI_MAPPED], + meminfo[MI_MEMFREE]); printf(OPT_BATCH_MODE ? "%.*s\n" : "\033[H\033[J%.*s\n", scr_width, line_buf); snprintf(line_buf, LINE_BUF_SIZE, - " slab:%s buf:%s cache:%s dirty:%s write:%s", - Z[SLAB], Z[BUF], Z[CACHE], Z[DIRTY], Z[MWRITE]); + " slab:%lu buf:%lu cache:%lu dirty:%lu write:%lu", + meminfo[MI_SLAB], + meminfo[MI_BUFFERS], + meminfo[MI_CACHED], + meminfo[MI_DIRTY], + meminfo[MI_WRITEBACK]); printf("%.*s\n", scr_width, line_buf); snprintf(line_buf, LINE_BUF_SIZE, - "Swap total:%s free:%s", // TODO: % used? - Z[SWAPTOTAL], Z[SWAPFREE]); + "Swap total:%lu free:%lu", // TODO: % used? + meminfo[MI_SWAPTOTAL], + meminfo[MI_SWAPFREE]); printf("%.*s\n", scr_width, line_buf); (*lines_rem_p) -= 3; |