-/* free.c - a /proc implementation of free */
-/* Dec14/92 by Brian Edmonds */
-/* Thanks to Rafal Maszkowski for the Total line */
+// free.c - free(1)
+// procps utility to display free memory information
+//
+// All new, Robert Love <rml@tech9.net> 18 Nov 2002
+// Original by Brian Edmonds and Rafal Maszkowski 14 Dec 1992
+//
+// This program is licensed under the GNU Library General Public License, v2
+//
+// Copyright 2003 Robert Love
+// Copyright 2004 Albert Cahalan
#include "proc/sysinfo.h"
#include "proc/version.h"
+//#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <fcntl.h>
-#include <getopt.h>
-#define S(X) ( ((unsigned long long)(X) << 10) >> byteshift)
+#define S(X) ( ((unsigned long long)(X) << 10) >> shift)
-static int byteshift = 10;
-static int total = 0;
+const char help_message[] =
+"usage: free [-b|-k|-m|-g] [-l] [-o] [-t] [-s delay] [-c count] [-V]\n"
+" -b,-k,-m,-g show output in bytes, KB, MB, or GB\n"
+" -l show detailed low and high memory statistics\n"
+" -o use old format (no -/+buffers/cache line)\n"
+" -t display total for RAM + swap\n"
+" -s update every [delay] seconds\n"
+" -c update [count] times\n"
+" -V display version information and exit\n"
+;
int main(int argc, char *argv[]){
int i;
+ int count = 0;
+ int shift = 10;
+ int pause_length = 0;
+ int show_high = 0;
+ int show_total = 0;
int old_fmt = 0;
- int rtime = 0;
/* check startup flags */
- while( (i = getopt(argc, argv, "bkmos:tV") ) != -1 )
+ while( (i = getopt(argc, argv, "bkmglotc:s:V") ) != -1 )
switch (i) {
- case 'b': byteshift = 0; break;
- case 'k': byteshift = 10; break;
- case 'm': byteshift = 20; break;
+ case 'b': shift = 0; break;
+ case 'k': shift = 10; break;
+ case 'm': shift = 20; break;
+ case 'g': shift = 30; break;
+ case 'l': show_high = 1; break;
case 'o': old_fmt = 1; break;
- case 's': rtime = 1000000 * atof(optarg); break;
- case 't': total = 1; break;
+ case 't': show_total = 1; break;
+ case 's': pause_length = 1000000 * atof(optarg); break;
+ case 'c': count = strtoul(optarg, NULL, 10); break;
case 'V': display_version(); exit(0);
default:
- fprintf(stderr, "usage: %s [-b|-k|-m] [-o] [-s delay] [-t] [-V]\n", argv[0]);
- return 1;
+ fwrite(help_message,1,strlen(help_message),stderr);
+ return 1;
}
do {
meminfo();
printf(" total used free shared buffers cached\n");
printf(
- "%-7s %10Ld %10Ld %10Ld %10Ld %10Ld %10Ld\n", "Mem:",
+ "%-7s %10Lu %10Lu %10Lu %10Lu %10Lu %10Lu\n", "Mem:",
S(kb_main_total),
S(kb_main_used),
S(kb_main_free),
S(kb_main_buffers),
S(kb_main_cached)
);
+ // Print low vs. high information, if the user requested it.
+ // Note we check if low_total==0: if so, then this kernel does
+ // not export the low and high stats. Note we still want to
+ // print the high info, even if it is zero.
+ if (show_high) {
+ printf(
+ "%-7s %10Lu %10Lu %10Lu\n", "Low:",
+ S(kb_low_total),
+ S(kb_low_total - kb_low_free),
+ S(kb_low_free)
+ );
+ printf(
+ "%-7s %10Lu %10Lu %10Lu\n", "High:",
+ S(kb_high_total),
+ S(kb_high_total - kb_high_free),
+ S(kb_high_free)
+ );
+ }
if(!old_fmt){
+ unsigned KLONG buffers_plus_cached = kb_main_buffers + kb_main_cached;
printf(
- "-/+ buffers/cache: %10Ld %10Ld\n",
- S(kb_main_used-kb_main_buffers-kb_main_cached),
- S(kb_main_free+kb_main_buffers+kb_main_cached)
+ "-/+ buffers/cache: %10Lu %10Lu\n",
+ S(kb_main_used - buffers_plus_cached),
+ S(kb_main_free + buffers_plus_cached)
);
}
printf(
- "%-7s %10Ld %10Ld %10Ld\n", "Swap:",
+ "%-7s %10Lu %10Lu %10Lu\n", "Swap:",
S(kb_swap_total),
S(kb_swap_used),
S(kb_swap_free)
);
- if(total == 1){
+ if(show_total){
printf(
- "%-7s %10Ld %10Ld %10Ld\n", "Total:",
+ "%-7s %10Lu %10Lu %10Lu\n", "Total:",
S(kb_main_total + kb_swap_total),
S(kb_main_used + kb_swap_used),
S(kb_main_free + kb_swap_free)
);
}
- if(rtime){
+ if(pause_length){
fputc('\n', stdout);
fflush(stdout);
- usleep(rtime);
+ if (count != 1) usleep(pause_length);
}
- } while(rtime);
+ } while(pause_length && --count);
return 0;
}