diff options
author | Guillermo Rodriguez <guille.rodriguez@gmail.com> | 2018-10-30 13:49:51 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-10-30 13:49:51 +0100 |
commit | c8e3922ad838751e45bf4b3cb8608b228ee83c71 (patch) | |
tree | 0e08b1016bb276e800b85bb1e98fbc7435cc6233 | |
parent | 47839ae6797bcded0178893cb950d2e2f8be1f6f (diff) | |
download | busybox-w32-c8e3922ad838751e45bf4b3cb8608b228ee83c71.tar.gz busybox-w32-c8e3922ad838751e45bf4b3cb8608b228ee83c71.tar.bz2 busybox-w32-c8e3922ad838751e45bf4b3cb8608b228ee83c71.zip |
free: add 'available' memory if provided by the kernel
Show estimated available memory if this is provided by the
kernel. See [1] for the full story.
[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
function old new delta
free_main 537 633 +96
parse_cached_kb 85 - -85
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 1/0 up/down: 96/-85) Total: 11 bytes
Signed-off-by: Guillermo Rodriguez <guille.rodriguez@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | procps/free.c | 59 |
1 files changed, 36 insertions, 23 deletions
diff --git a/procps/free.c b/procps/free.c index 48139c4a3..e41601e08 100644 --- a/procps/free.c +++ b/procps/free.c | |||
@@ -53,21 +53,27 @@ static unsigned long long scale(struct globals *g, unsigned long d) | |||
53 | } | 53 | } |
54 | 54 | ||
55 | /* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */ | 55 | /* NOINLINE reduces main() stack usage, which makes code smaller (on x86 at least) */ |
56 | static NOINLINE unsigned long parse_cached_kb(void) | 56 | static NOINLINE unsigned int parse_meminfo(unsigned long *cached_kb, unsigned long *available_kb) |
57 | { | 57 | { |
58 | char buf[60]; /* actual lines we expect are ~30 chars or less */ | 58 | char buf[60]; /* actual lines we expect are ~30 chars or less */ |
59 | FILE *fp; | 59 | FILE *fp; |
60 | unsigned long cached = 0; | 60 | int seen_cached_and_available; |
61 | 61 | ||
62 | fp = xfopen_for_read("/proc/meminfo"); | 62 | fp = xfopen_for_read("/proc/meminfo"); |
63 | while (fgets(buf, sizeof(buf), fp) != NULL) { | 63 | *cached_kb = *available_kb = 0; |
64 | if (sscanf(buf, "Cached: %lu %*s\n", &cached) == 1) | 64 | seen_cached_and_available = 2; |
65 | break; | 65 | while (fgets(buf, sizeof(buf), fp)) { |
66 | if (sscanf(buf, "Cached: %lu %*s\n", cached_kb) == 1) | ||
67 | if (--seen_cached_and_available == 0) | ||
68 | break; | ||
69 | if (sscanf(buf, "MemAvailable: %lu %*s\n", available_kb) == 1) | ||
70 | if (--seen_cached_and_available == 0) | ||
71 | break; | ||
66 | } | 72 | } |
67 | /* Have to close because of NOFORK */ | 73 | /* Have to close because of NOFORK */ |
68 | fclose(fp); | 74 | fclose(fp); |
69 | 75 | ||
70 | return cached; | 76 | return seen_cached_and_available == 0; |
71 | } | 77 | } |
72 | 78 | ||
73 | int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 79 | int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
@@ -75,7 +81,9 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | |||
75 | { | 81 | { |
76 | struct globals G; | 82 | struct globals G; |
77 | struct sysinfo info; | 83 | struct sysinfo info; |
78 | unsigned long long cached; | 84 | unsigned long long cached, cached_plus_free, available; |
85 | unsigned long cached_kb, available_kb; | ||
86 | int seen_available; | ||
79 | 87 | ||
80 | #if ENABLE_DESKTOP | 88 | #if ENABLE_DESKTOP |
81 | G.unit_steps = 10; | 89 | G.unit_steps = 10; |
@@ -98,41 +106,46 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) | |||
98 | } | 106 | } |
99 | } | 107 | } |
100 | #endif | 108 | #endif |
101 | printf(" %11s%11s%11s%11s%11s%11s\n" | 109 | printf(" %12s%12s%12s%12s%12s%12s\n" |
102 | "Mem: ", | 110 | "Mem: ", |
103 | "total", | 111 | "total", |
104 | "used", | 112 | "used", |
105 | "free", | 113 | "free", |
106 | "shared", "buffers", "cached" /* swap and total don't have these columns */ | 114 | "shared", "buff/cache", "available" /* swap and total don't have these columns */ |
107 | ); | 115 | ); |
108 | 116 | ||
109 | sysinfo(&info); | 117 | sysinfo(&info); |
110 | /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ | 118 | /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ |
111 | G.mem_unit = (info.mem_unit ? info.mem_unit : 1); | 119 | G.mem_unit = (info.mem_unit ? info.mem_unit : 1); |
112 | /* Extract cached from /proc/meminfo and convert to mem_units */ | 120 | /* Extract cached and memavailable from /proc/meminfo and convert to mem_units */ |
113 | cached = ((unsigned long long) parse_cached_kb() * 1024) / G.mem_unit; | 121 | seen_available = parse_meminfo(&cached_kb, &available_kb); |
122 | available = ((unsigned long long) available_kb * 1024) / G.mem_unit; | ||
123 | cached = ((unsigned long long) cached_kb * 1024) / G.mem_unit; | ||
124 | cached += info.bufferram; | ||
125 | cached_plus_free = cached + info.freeram; | ||
114 | 126 | ||
115 | #define FIELDS_6 "%11llu%11llu%11llu%11llu%11llu%11llu\n" | 127 | #define FIELDS_6 "%12llu%12llu%12llu%12llu%12llu%12llu\n" |
116 | #define FIELDS_3 (FIELDS_6 + 3*6) | 128 | #define FIELDS_3 (FIELDS_6 + 3*6) |
117 | #define FIELDS_2 (FIELDS_6 + 4*6) | 129 | #define FIELDS_2 (FIELDS_6 + 4*6) |
118 | 130 | ||
119 | printf(FIELDS_6, | 131 | printf(FIELDS_6, |
120 | scale(&G, info.totalram), //total | 132 | scale(&G, info.totalram), //total |
121 | scale(&G, info.totalram - info.freeram), //used | 133 | scale(&G, info.totalram - cached_plus_free), //used |
122 | scale(&G, info.freeram), //free | 134 | scale(&G, info.freeram), //free |
123 | scale(&G, info.sharedram), //shared | 135 | scale(&G, info.sharedram), //shared |
124 | scale(&G, info.bufferram), //buffers | 136 | scale(&G, cached), //buff/cache |
125 | scale(&G, cached) //cached | 137 | scale(&G, available) //available |
126 | ); | 138 | ); |
127 | /* Show alternate, more meaningful busy/free numbers by counting | 139 | /* On kernels < 3.14, MemAvailable is not provided. |
140 | * Show alternate, more meaningful busy/free numbers by counting | ||
128 | * buffer cache as free memory. */ | 141 | * buffer cache as free memory. */ |
129 | printf("-/+ buffers/cache:"); | 142 | if (!seen_available) { |
130 | cached += info.freeram; | 143 | printf("-/+ buffers/cache: "); |
131 | cached += info.bufferram; | 144 | printf(FIELDS_2, |
132 | printf(FIELDS_2, | 145 | scale(&G, info.totalram - cached_plus_free), //used |
133 | scale(&G, info.totalram - cached), //used | 146 | scale(&G, cached_plus_free) //free |
134 | scale(&G, cached) //free | 147 | ); |
135 | ); | 148 | } |
136 | #if BB_MMU | 149 | #if BB_MMU |
137 | printf("Swap: "); | 150 | printf("Swap: "); |
138 | printf(FIELDS_3, | 151 | printf(FIELDS_3, |