summaryrefslogtreecommitdiffhomepage
path: root/procps/top.c
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2003-10-11 18:47:20 +0000
committerEric Andersen <andersen@codepoet.org>2003-10-11 18:47:20 +0000
commit7857c038087a94345e768bc010134d8ff2586809 (patch)
treee4a246f2267a80f39138920b283aa28d56011e5a /procps/top.c
parentd12061b299a096359b998e0e4415ebe77b45c96b (diff)
Paul Mundt (lethal) writes:
Erik, The format for /proc/meminfo has changed between 2.4 and 2.6, quite considerably. In addition to the removal of the two-line summary that was present in 2.4, MemShared was also removed. Presently (at least in busybox CVS HEAD), top fails to parse this correctly and spews forth a: top: failed to read 'meminfo' message. This patch switches around some of the semantics a little to do sane parsing for both 2.4 and 2.6. Also, in the event that the summary gets yanked from 2.4, this patch will deal with that as well. With this patch, I'm able to run top correctly on 2.6.0-test7 (tested on sh). Please apply. procps/top.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 48 insertions(+), 12 deletions(-)
Diffstat (limited to 'procps/top.c')
-rw-r--r--procps/top.c60
1 files changed, 48 insertions, 12 deletions
diff --git a/procps/top.c b/procps/top.c
index cee1b52c1..9944598c2 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -311,14 +311,47 @@ static unsigned long display_generic(void)
char buf[80];
float avg1, avg2, avg3;
unsigned long total, used, mfree, shared, buffers, cached;
+ unsigned int needs_conversion = 1;
/* read memory info */
fp = bb_xfopen("meminfo", "r");
- fgets(buf, sizeof(buf), fp); /* skip first line */
- if (fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu",
- &total, &used, &mfree, &shared, &buffers, &cached) != 6) {
- bb_error_msg_and_die("failed to read '%s'", "meminfo");
+ /*
+ * 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);
+ } else {
+ /*
+ * Revert to manual parsing, which incidentally already has the
+ * sizes in kilobytes. This should be safe for both 2.4 and
+ * 2.6.
+ */
+ needs_conversion = 0;
+
+ fscanf(fp, "MemFree: %lu %s\n", &mfree, buf);
+
+ /*
+ * 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);
+
+ used = total - mfree;
}
fclose(fp);
@@ -329,13 +362,16 @@ static unsigned long display_generic(void)
}
fclose(fp);
- /* convert to kilobytes */
- used /= 1024;
- mfree /= 1024;
- shared /= 1024;
- buffers /= 1024;
- cached /= 1024;
-
+ if (needs_conversion) {
+ /* convert to kilobytes */
+ used /= 1024;
+ mfree /= 1024;
+ shared /= 1024;
+ buffers /= 1024;
+ cached /= 1024;
+ total /= 1024;
+ }
+
/* output memory info and load average */
/* clear screen & go to top */
printf("\e[H\e[J" "Mem: "
@@ -344,7 +380,7 @@ static unsigned long display_generic(void)
printf("Load average: %.2f, %.2f, %.2f "
"(State: S=sleeping R=running, W=waiting)\n",
avg1, avg2, avg3);
- return total / 1024;
+ return total;
}