free: Use IEC units
Free always used 1024 based units but used the confusing old style kilo,mega etc. This change changes the names to kibi,mebi for 1024 based divisors and kilo,mega for 1000 based divisors or IEC units. It also checks if you try to set two units, e.g free -k -m Petabyte and Pebibyte have been added. If you used to use the long options such as --mega these will now actually print megabytes (they previously printed mebibytes). The short options are being used on the IEC units References: https://www.gitorious.org/procps/procps/merge_requests/38 Signed-off-by: Craig Small <csmall@enc.com.au>
This commit is contained in:
parent
6ed8cf3444
commit
f8e98b65ae
50
free.1
50
free.1
@ -2,7 +2,7 @@
|
|||||||
.\" This page Copyright (C) 1993 Matt Welsh, mdw@sunsite.unc.edu.
|
.\" This page Copyright (C) 1993 Matt Welsh, mdw@sunsite.unc.edu.
|
||||||
.\" Long options where added at April 15th, 2011.
|
.\" Long options where added at April 15th, 2011.
|
||||||
.\" Freely distributable under the terms of the GPL
|
.\" Freely distributable under the terms of the GPL
|
||||||
.TH FREE 1 "July 2014" "procps-ng" "User Commands"
|
.TH FREE 1 "Apr 2015" "procps-ng" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
free \- Display amount of free and used memory in the system
|
free \- Display amount of free and used memory in the system
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -50,17 +50,35 @@ kernels 3.14, emulated on kernels 2.6.27+, otherwise the same as \fBfree\fR)
|
|||||||
\fB\-b\fR, \fB\-\-bytes\fR
|
\fB\-b\fR, \fB\-\-bytes\fR
|
||||||
Display the amount of memory in bytes.
|
Display the amount of memory in bytes.
|
||||||
.TP
|
.TP
|
||||||
\fB\-k\fR, \fB\-\-kilo\fR
|
\fB\-k\fR, \fB\-\-kibi\fR
|
||||||
Display the amount of memory in kilobytes. This is the default.
|
Display the amount of memory in kibibytes. This is the default.
|
||||||
.TP
|
.TP
|
||||||
\fB\-m\fR, \fB\-\-mega\fR
|
\fB\-m\fR, \fB\-\-mebi\fR
|
||||||
Display the amount of memory in megabytes.
|
Display the amount of memory in mebibytes.
|
||||||
.TP
|
.TP
|
||||||
\fB\-g\fR, \fB\-\-giga\fR
|
\fB\-g\fR, \fB\-\-gibi\fR
|
||||||
Display the amount of memory in gigabytes.
|
Display the amount of memory in gibibytes.
|
||||||
|
.TP
|
||||||
|
\fB\-\-tebi\fR
|
||||||
|
Display the amount of memory in tebibytes.
|
||||||
|
.TP
|
||||||
|
\fB\-\-pebi\fR
|
||||||
|
Display the amount of memory in pebibytes.
|
||||||
|
.TP
|
||||||
|
\fB\-\-kilo\fR
|
||||||
|
Display the amount of memory in kilobytes. Implies --si.
|
||||||
|
.TP
|
||||||
|
\fB\-\-mega\fR
|
||||||
|
Display the amount of memory in megabytes. Implies --si.
|
||||||
|
.TP
|
||||||
|
\fB\-\-giga\fR
|
||||||
|
Display the amount of memory in gigabytes. Implies --si.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-tera\fR
|
\fB\-\-tera\fR
|
||||||
Display the amount of memory in terabytes.
|
Display the amount of memory in terabytes. Implies --si.
|
||||||
|
.TP
|
||||||
|
\fB\-\-peta\fR
|
||||||
|
Display the amount of memory in petabytes. Implies --si.
|
||||||
.TP
|
.TP
|
||||||
\fB\-h\fR, \fB\-\-human\fP
|
\fB\-h\fR, \fB\-\-human\fP
|
||||||
Show all output fields automatically scaled to shortest three digit unit and
|
Show all output fields automatically scaled to shortest three digit unit and
|
||||||
@ -68,14 +86,15 @@ display the units of print out. Following units are used.
|
|||||||
.sp
|
.sp
|
||||||
.nf
|
.nf
|
||||||
B = bytes
|
B = bytes
|
||||||
K = kilos
|
K = kibibyte
|
||||||
M = megas
|
M = mebibyte
|
||||||
G = gigas
|
G = gibibyte
|
||||||
T = teras
|
T = tebibyte
|
||||||
|
P = pebibyte
|
||||||
.fi
|
.fi
|
||||||
.sp
|
.sp
|
||||||
If unit is missing, and you have petabyte of RAM or swap, the number is in
|
If unit is missing, and you have exbibyte of RAM or swap, the number is in
|
||||||
terabytes and columns might not be aligned with header.
|
tebibytes and columns might not be aligned with header.
|
||||||
.TP
|
.TP
|
||||||
\fB\-w\fR, \fB\-\-wide\fR
|
\fB\-w\fR, \fB\-\-wide\fR
|
||||||
Switch to the wide mode. The wide mode produces lines longer
|
Switch to the wide mode. The wide mode produces lines longer
|
||||||
@ -101,7 +120,8 @@ apart. You may actually specify any floating point number for
|
|||||||
is used for microsecond resolution delay times.
|
is used for microsecond resolution delay times.
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-si\fR
|
\fB\-\-si\fR
|
||||||
Use power of 1000 not 1024.
|
Use kilo, mega, giga etc (power of 1000) instead of kibi, mebi, gibi (power
|
||||||
|
of 1024).
|
||||||
.TP
|
.TP
|
||||||
\fB\-t\fR, \fB\-\-total\fR
|
\fB\-t\fR, \fB\-\-total\fR
|
||||||
Display a line showing the column totals.
|
Display a line showing the column totals.
|
||||||
|
85
free.c
85
free.c
@ -74,10 +74,16 @@ static void __attribute__ ((__noreturn__))
|
|||||||
_(" %s [options]\n"), program_invocation_short_name);
|
_(" %s [options]\n"), program_invocation_short_name);
|
||||||
fputs(USAGE_OPTIONS, out);
|
fputs(USAGE_OPTIONS, out);
|
||||||
fputs(_(" -b, --bytes show output in bytes\n"), out);
|
fputs(_(" -b, --bytes show output in bytes\n"), out);
|
||||||
fputs(_(" -k, --kilo show output in kilobytes\n"), out);
|
fputs(_(" --kilo show output in kilobytes\n"), out);
|
||||||
fputs(_(" -m, --mega show output in megabytes\n"), out);
|
fputs(_(" --mega show output in megabytes\n"), out);
|
||||||
fputs(_(" -g, --giga show output in gigabytes\n"), out);
|
fputs(_(" --giga show output in gigabytes\n"), out);
|
||||||
fputs(_(" --tera show output in terabytes\n"), out);
|
fputs(_(" --tera show output in terabytes\n"), out);
|
||||||
|
fputs(_(" --peta show output in petabytes\n"), out);
|
||||||
|
fputs(_(" -k, --kibi show output in kibibytes\n"), out);
|
||||||
|
fputs(_(" -m, --mebi show output in mebibytes\n"), out);
|
||||||
|
fputs(_(" -g, --gibi show output in gibibytes\n"), out);
|
||||||
|
fputs(_(" --tebi show output in tebibytes\n"), out);
|
||||||
|
fputs(_(" --pebi show output in pebibytes\n"), out);
|
||||||
fputs(_(" -h, --human show human-readable output\n"), out);
|
fputs(_(" -h, --human show human-readable output\n"), out);
|
||||||
fputs(_(" --si use powers of 1000 not 1024\n"), out);
|
fputs(_(" --si use powers of 1000 not 1024\n"), out);
|
||||||
fputs(_(" -l, --lohi show detailed low and high memory statistics\n"), out);
|
fputs(_(" -l, --lohi show detailed low and high memory statistics\n"), out);
|
||||||
@ -101,7 +107,7 @@ double power(unsigned int base, unsigned int expo)
|
|||||||
/* idea of this function is copied from top size scaling */
|
/* idea of this function is copied from top size scaling */
|
||||||
static const char *scale_size(unsigned long size, int flags, struct commandline_arguments args)
|
static const char *scale_size(unsigned long size, int flags, struct commandline_arguments args)
|
||||||
{
|
{
|
||||||
static char nextup[] = { 'B', 'K', 'M', 'G', 'T', 0 };
|
static char nextup[] = { 'B', 'K', 'M', 'G', 'T', 'P', 0 };
|
||||||
static char buf[BUFSIZ];
|
static char buf[BUFSIZ];
|
||||||
int i;
|
int i;
|
||||||
char *up;
|
char *up;
|
||||||
@ -163,6 +169,7 @@ static const char *scale_size(unsigned long size, int flags, struct commandline_
|
|||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
case 5:
|
case 5:
|
||||||
|
case 6:
|
||||||
if (4 >=
|
if (4 >=
|
||||||
snprintf(buf, sizeof(buf), "%.1f%c",
|
snprintf(buf, sizeof(buf), "%.1f%c",
|
||||||
(float)(size / power(base, i - 2)), *up))
|
(float)(size / power(base, i - 2)), *up))
|
||||||
@ -172,21 +179,29 @@ static const char *scale_size(unsigned long size, int flags, struct commandline_
|
|||||||
(long)(size / power(base, i - 2)), *up))
|
(long)(size / power(base, i - 2)), *up))
|
||||||
return buf;
|
return buf;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 7:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* On system where there is more than petabyte of memory or swap the
|
* On system where there is more than exbibyte of memory or swap the
|
||||||
* output does not fit to column. For incoming few years this should
|
* output does not fit to column. For incoming few years this should
|
||||||
* not be a big problem (wrote at Apr, 2011).
|
* not be a big problem (wrote at Apr, 2015).
|
||||||
*/
|
*/
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void check_unit_set(int *unit_set)
|
||||||
|
{
|
||||||
|
if (*unit_set)
|
||||||
|
xerrx(EXIT_FAILURE,
|
||||||
|
_("Multiple unit options doesn't make sense."));
|
||||||
|
*unit_set = 1;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int c, flags = 0;
|
int c, flags = 0, unit_set = 0;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
struct commandline_arguments args;
|
struct commandline_arguments args;
|
||||||
|
|
||||||
@ -196,16 +211,28 @@ int main(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
SI_OPTION = CHAR_MAX + 1,
|
SI_OPTION = CHAR_MAX + 1,
|
||||||
|
KILO_OPTION,
|
||||||
|
MEGA_OPTION,
|
||||||
|
GIGA_OPTION,
|
||||||
TERA_OPTION,
|
TERA_OPTION,
|
||||||
|
PETA_OPTION,
|
||||||
|
TEBI_OPTION,
|
||||||
|
PEBI_OPTION,
|
||||||
HELP_OPTION
|
HELP_OPTION
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option longopts[] = {
|
static const struct option longopts[] = {
|
||||||
{ "bytes", no_argument, NULL, 'b' },
|
{ "bytes", no_argument, NULL, 'b' },
|
||||||
{ "kilo", no_argument, NULL, 'k' },
|
{ "kilo", no_argument, NULL, KILO_OPTION },
|
||||||
{ "mega", no_argument, NULL, 'm' },
|
{ "mega", no_argument, NULL, MEGA_OPTION },
|
||||||
{ "giga", no_argument, NULL, 'g' },
|
{ "giga", no_argument, NULL, GIGA_OPTION },
|
||||||
{ "tera", no_argument, NULL, TERA_OPTION },
|
{ "tera", no_argument, NULL, TERA_OPTION },
|
||||||
|
{ "peta", no_argument, NULL, PETA_OPTION },
|
||||||
|
{ "kibi", no_argument, NULL, 'k' },
|
||||||
|
{ "mebi", no_argument, NULL, 'm' },
|
||||||
|
{ "gibi", no_argument, NULL, 'g' },
|
||||||
|
{ "tebi", no_argument, NULL, TEBI_OPTION },
|
||||||
|
{ "pebi", no_argument, NULL, PEBI_OPTION },
|
||||||
{ "human", no_argument, NULL, 'h' },
|
{ "human", no_argument, NULL, 'h' },
|
||||||
{ "si", no_argument, NULL, SI_OPTION },
|
{ "si", no_argument, NULL, SI_OPTION },
|
||||||
{ "lohi", no_argument, NULL, 'l' },
|
{ "lohi", no_argument, NULL, 'l' },
|
||||||
@ -234,20 +261,54 @@ int main(int argc, char **argv)
|
|||||||
while ((c = getopt_long(argc, argv, "bkmghltc:ws:V", longopts, NULL)) != -1)
|
while ((c = getopt_long(argc, argv, "bkmghltc:ws:V", longopts, NULL)) != -1)
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
|
check_unit_set(&unit_set);
|
||||||
args.exponent = 1;
|
args.exponent = 1;
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
|
check_unit_set(&unit_set);
|
||||||
args.exponent = 2;
|
args.exponent = 2;
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
|
check_unit_set(&unit_set);
|
||||||
args.exponent = 3;
|
args.exponent = 3;
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
|
check_unit_set(&unit_set);
|
||||||
args.exponent = 4;
|
args.exponent = 4;
|
||||||
break;
|
break;
|
||||||
case TERA_OPTION:
|
case TEBI_OPTION:
|
||||||
|
check_unit_set(&unit_set);
|
||||||
args.exponent = 5;
|
args.exponent = 5;
|
||||||
break;
|
break;
|
||||||
|
case PEBI_OPTION:
|
||||||
|
check_unit_set(&unit_set);
|
||||||
|
args.exponent = 6;
|
||||||
|
break;
|
||||||
|
case KILO_OPTION:
|
||||||
|
check_unit_set(&unit_set);
|
||||||
|
args.exponent = 2;
|
||||||
|
flags |= FREE_SI;
|
||||||
|
break;
|
||||||
|
case MEGA_OPTION:
|
||||||
|
check_unit_set(&unit_set);
|
||||||
|
args.exponent = 3;
|
||||||
|
flags |= FREE_SI;
|
||||||
|
break;
|
||||||
|
case GIGA_OPTION:
|
||||||
|
check_unit_set(&unit_set);
|
||||||
|
args.exponent = 4;
|
||||||
|
flags |= FREE_SI;
|
||||||
|
break;
|
||||||
|
case TERA_OPTION:
|
||||||
|
check_unit_set(&unit_set);
|
||||||
|
args.exponent = 5;
|
||||||
|
flags |= FREE_SI;
|
||||||
|
break;
|
||||||
|
case PETA_OPTION:
|
||||||
|
check_unit_set(&unit_set);
|
||||||
|
args.exponent = 6;
|
||||||
|
flags |= FREE_SI;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
flags |= FREE_HUMANREADABLE;
|
flags |= FREE_HUMANREADABLE;
|
||||||
break;
|
break;
|
||||||
|
@ -19,7 +19,7 @@ set swaptotal [ expr { $swaptotal_kb * 1024 } ]
|
|||||||
spawn $free -b
|
spawn $free -b
|
||||||
expect_pass "$test" "^${free_header}Mem:\\s+${memtotal}\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s*Swap:\\s+${swaptotal}\\s+\\d+\\s+\\d+\\s*"
|
expect_pass "$test" "^${free_header}Mem:\\s+${memtotal}\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s*Swap:\\s+${swaptotal}\\s+\\d+\\s+\\d+\\s*"
|
||||||
|
|
||||||
foreach {arg divisor } {-k 1 -m 1024 -g 1048576 } {
|
foreach {arg divisor } {-k 1 -m 1024 -g 1048576 --mega 1000 --giga 1000000 } {
|
||||||
set test "free with $arg argument"
|
set test "free with $arg argument"
|
||||||
set memtotal [ expr { $memtotal_kb / $divisor } ]
|
set memtotal [ expr { $memtotal_kb / $divisor } ]
|
||||||
set swaptotal [ expr { $swaptotal_kb / $divisor } ]
|
set swaptotal [ expr { $swaptotal_kb / $divisor } ]
|
||||||
|
Loading…
Reference in New Issue
Block a user