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 Signed-off-by: Guillermo Rodriguez <[email protected]> --- procps/free.c | 54 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/procps/free.c b/procps/free.c index 0991713..e7ba974 100644 --- a/procps/free.c +++ b/procps/free.c @@ -44,27 +44,36 @@ static unsigned long long scale(unsigned long d) return ((unsigned long long)d * G.mem_unit) >> G_unit_steps; } -static unsigned long parse_cached_kb(void) +static unsigned int parse_meminfo(unsigned long *cached_kb, unsigned long *available_kb) { char buf[60]; /* actual lines we expect are ~30 chars or less */ FILE *f; - unsigned long cached = 0; + int seen_cached = 0; + int seen_available = 0; + + *cached_kb = *available_kb = 0; f = xfopen_for_read("/proc/meminfo"); - while (fgets(buf, sizeof(buf), f) != NULL) { - if (sscanf(buf, "Cached: %lu %*s\n", &cached) == 1) - break; + while (fgets(buf, sizeof(buf), f) != NULL && !(seen_cached && seen_available)) { + if (!seen_cached && sscanf(buf, "Cached: %lu %*s\n", cached_kb) == 1) { + seen_cached = 1; + } + else if (!seen_available && sscanf(buf, "MemAvailable: %lu %*s\n", available_kb) == 1) { + seen_available = 1; + } } fclose(f); - return cached; + return seen_available; } int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) { struct sysinfo info; - unsigned long long cached; + unsigned long long cached, available; + unsigned long cached_kb, available_kb; + int seen_available; INIT_G(); @@ -95,17 +104,19 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) /* Kernels prior to 2.4.x will return info.mem_unit==0, so cope... */ G.mem_unit = (info.mem_unit ? info.mem_unit : 1); - /* Extract cached from /proc/meminfo and convert to mem_units */ - cached = ((unsigned long long) parse_cached_kb() * 1024) / G.mem_unit; + /* Extract cached and memavailable from /proc/meminfo and convert to mem_units */ + seen_available = parse_meminfo(&cached_kb, &available_kb); + cached = ((unsigned long long) cached_kb * 1024) / G.mem_unit; + available = ((unsigned long long) available_kb * 1024) / G.mem_unit; - printf(" %11s%11s%11s%11s%11s%11s\n", + printf(" %12s%12s%12s%12s%12s%12s\n", "total", "used", "free", - "shared", "buffers", "cached" /* swap and total don't have these columns */ + "shared", "buff/cache", "available" /* swap and total don't have these columns */ ); -#define FIELDS_6 "%11llu%11llu%11llu%11llu%11llu%11llu\n" +#define FIELDS_6 "%12llu%12llu%12llu%12llu%12llu%12llu\n" #define FIELDS_3 (FIELDS_6 + 3*6) #define FIELDS_2 (FIELDS_6 + 4*6) @@ -115,16 +126,19 @@ int free_main(int argc UNUSED_PARAM, char **argv IF_NOT_DESKTOP(UNUSED_PARAM)) scale(info.totalram - info.freeram), scale(info.freeram), scale(info.sharedram), - scale(info.bufferram), - scale(cached) + scale(info.bufferram) + scale(cached), + scale(available) ); - /* Show alternate, more meaningful busy/free numbers by counting + /* On kernels < 3.14, MemAvailable is not provided. + * Show alternate, more meaningful busy/free numbers by counting * buffer cache as free memory. */ - printf("-/+ buffers/cache:"); - printf(FIELDS_2, - scale(info.totalram - info.freeram - info.bufferram - cached), - scale(info.freeram + info.bufferram + cached) - ); + if (!seen_available) { + printf("-/+ buffers/cache:"); + printf(FIELDS_2, + scale(info.totalram - info.freeram - info.bufferram - cached), + scale(info.freeram + info.bufferram + cached) + ); + } #if BB_MMU printf("Swap: "); printf(FIELDS_3, -- 1.9.1 _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
