top: add -m ("memory") option

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2009-09-11 23:26:42 +02:00
parent 56573cb4f7
commit 0052882200
4 changed files with 86 additions and 57 deletions

23
TODO
View File

@ -320,6 +320,29 @@ vdprintf() -> similar sized functionality
Unicode work needed: Unicode work needed:
Unicode support uses libc multibyte functions if LOCALE_SUPPORT is on
(in this case, the code will also support many more encodings),
or uses a limited subset of re-implemented multibyte functions
which only understand "one byte == one char" and unicode.
This is useful if you build against uclibc with locale support disabled.
Unicode-dependent applets must call check_unicode_in_env() when they
begin executing.
Applet code may conditionalize on FEATURE_ASSUME_UNICODE
in order to use more efficient code if unicode support is not requested.
Available functions (if you need more, implement them in libbb/unicode.c
so that they work without LOCALE_SUPPORT too):
int bb_mbstrlen(str) - multibyte-aware strlen
size_t mbstowcs(wdest, src, n)
size_t wcstombs(dest, wsrc, n)
size_t wcrtomb(str, wc, wstate)
int iswspace(wc)
int iswalnum(wc)
int iswpunct(wc)
Applets which only need to align columns on screen correctly: Applets which only need to align columns on screen correctly:
ls - already done, use source as an example ls - already done, use source as an example

View File

@ -4566,7 +4566,7 @@
"Defaults: SECS: 10, SIG: TERM." \ "Defaults: SECS: 10, SIG: TERM." \
#define top_trivial_usage \ #define top_trivial_usage \
"[-b] [-nCOUNT] [-dSECONDS]" "[-b] [-nCOUNT] [-dSECONDS]" IF_FEATURE_TOPMEM(" [-m]")
#define top_full_usage "\n\n" \ #define top_full_usage "\n\n" \
"Provide a view of process activity in real time.\n" \ "Provide a view of process activity in real time.\n" \
"Read the status of all processes from /proc each SECONDS\n" \ "Read the status of all processes from /proc each SECONDS\n" \

View File

@ -147,15 +147,15 @@ const char *opt_complementary
Special characters: Special characters:
"-" A dash as the first char in a opt_complementary group forces "-" A group consisting of just a dash forces all arguments
all arguments to be treated as options, even if they have to be treated as options, even if they have no leading dashes.
no leading dashes. Next char in this case can't be a digit (0-9), Next char in this case can't be a digit (0-9), use ':' or end of line.
use ':' or end of line. For example: Example:
opt_complementary = "-:w-x:x-w"; opt_complementary = "-:w-x:x-w"; // "-w-x:x-w" would also work,
getopt32(argv, "wx"); getopt32(argv, "wx"); // but is less readable
Allows any arguments to be given without a dash (./program w x) This makes it possible to use options without a dash (./program w x)
as well as with a dash (./program -x). as well as with a dash (./program -x).
NB: getopt32() will leak a small amount of memory if you use NB: getopt32() will leak a small amount of memory if you use

View File

@ -131,7 +131,8 @@ enum {
OPT_d = (1 << 0), OPT_d = (1 << 0),
OPT_n = (1 << 1), OPT_n = (1 << 1),
OPT_b = (1 << 2), OPT_b = (1 << 2),
OPT_EOF = (1 << 3), /* pseudo: "we saw EOF in stdin" */ OPT_m = (1 << 3),
OPT_EOF = (1 << 4), /* pseudo: "we saw EOF in stdin" */
}; };
#define OPT_BATCH_MODE (option_mask32 & OPT_b) #define OPT_BATCH_MODE (option_mask32 & OPT_b)
@ -348,29 +349,29 @@ static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p)
jiffy_counts_t *p_jif, *p_prev_jif; jiffy_counts_t *p_jif, *p_prev_jif;
int i; int i;
#if ENABLE_FEATURE_TOP_SMP_CPU # if ENABLE_FEATURE_TOP_SMP_CPU
int n_cpu_lines; int n_cpu_lines;
#endif # endif
/* using (unsigned) casts to make operations cheaper */ /* using (unsigned) casts to make operations cheaper */
#define CALC_TOT_DIFF ((unsigned)(p_jif->total - p_prev_jif->total) ? : 1) # define CALC_TOT_DIFF ((unsigned)(p_jif->total - p_prev_jif->total) ? : 1)
#if ENABLE_FEATURE_TOP_DECIMALS # if ENABLE_FEATURE_TOP_DECIMALS
#define CALC_STAT(xxx) char xxx[8] # define CALC_STAT(xxx) char xxx[8]
#define SHOW_STAT(xxx) fmt_100percent_8(xxx, (unsigned)(p_jif->xxx - p_prev_jif->xxx), total_diff) # define SHOW_STAT(xxx) fmt_100percent_8(xxx, (unsigned)(p_jif->xxx - p_prev_jif->xxx), total_diff)
#define FMT "%s" # define FMT "%s"
#else # else
#define CALC_STAT(xxx) unsigned xxx = 100 * (unsigned)(p_jif->xxx - p_prev_jif->xxx) / total_diff # define CALC_STAT(xxx) unsigned xxx = 100 * (unsigned)(p_jif->xxx - p_prev_jif->xxx) / total_diff
#define SHOW_STAT(xxx) xxx # define SHOW_STAT(xxx) xxx
#define FMT "%4u%% " # define FMT "%4u%% "
#endif # endif
#if !ENABLE_FEATURE_TOP_SMP_CPU # if !ENABLE_FEATURE_TOP_SMP_CPU
{ {
i = 1; i = 1;
p_jif = &cur_jif; p_jif = &cur_jif;
p_prev_jif = &prev_jif; p_prev_jif = &prev_jif;
#else # else
/* Loop thru CPU(s) */ /* Loop thru CPU(s) */
n_cpu_lines = smp_cpu_info ? num_cpus : 1; n_cpu_lines = smp_cpu_info ? num_cpus : 1;
if (n_cpu_lines > *lines_rem_p) if (n_cpu_lines > *lines_rem_p)
@ -379,7 +380,7 @@ static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p)
for (i = 0; i < n_cpu_lines; i++) { for (i = 0; i < n_cpu_lines; i++) {
p_jif = &cpu_jif[i]; p_jif = &cpu_jif[i];
p_prev_jif = &cpu_prev_jif[i]; p_prev_jif = &cpu_prev_jif[i];
#endif # endif
total_diff = CALC_TOT_DIFF; total_diff = CALC_TOT_DIFF;
{ /* Need a block: CALC_STAT are declarations */ { /* Need a block: CALC_STAT are declarations */
@ -394,12 +395,12 @@ static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p)
snprintf(scrbuf, scr_width, snprintf(scrbuf, scr_width,
/* Barely fits in 79 chars when in "decimals" mode. */ /* Barely fits in 79 chars when in "decimals" mode. */
#if ENABLE_FEATURE_TOP_SMP_CPU # if ENABLE_FEATURE_TOP_SMP_CPU
"CPU%s:"FMT"usr"FMT"sys"FMT"nic"FMT"idle"FMT"io"FMT"irq"FMT"sirq", "CPU%s:"FMT"usr"FMT"sys"FMT"nic"FMT"idle"FMT"io"FMT"irq"FMT"sirq",
(smp_cpu_info ? utoa(i) : ""), (smp_cpu_info ? utoa(i) : ""),
#else # else
"CPU:"FMT"usr"FMT"sys"FMT"nic"FMT"idle"FMT"io"FMT"irq"FMT"sirq", "CPU:"FMT"usr"FMT"sys"FMT"nic"FMT"idle"FMT"io"FMT"irq"FMT"sirq",
#endif # endif
SHOW_STAT(usr), SHOW_STAT(sys), SHOW_STAT(nic), SHOW_STAT(idle), SHOW_STAT(usr), SHOW_STAT(sys), SHOW_STAT(nic), SHOW_STAT(idle),
SHOW_STAT(iowait), SHOW_STAT(irq), SHOW_STAT(softirq) SHOW_STAT(iowait), SHOW_STAT(irq), SHOW_STAT(softirq)
/*, SHOW_STAT(steal) - what is this 'steal' thing? */ /*, SHOW_STAT(steal) - what is this 'steal' thing? */
@ -408,13 +409,13 @@ static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p)
puts(scrbuf); puts(scrbuf);
} }
} }
#undef SHOW_STAT # undef SHOW_STAT
#undef CALC_STAT # undef CALC_STAT
#undef FMT # undef FMT
*lines_rem_p -= i; *lines_rem_p -= i;
} }
#else /* !ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS */ #else /* !ENABLE_FEATURE_TOP_CPU_GLOBAL_PERCENTS */
#define display_cpus(scr_width, scrbuf, lines_rem) ((void)0) # define display_cpus(scr_width, scrbuf, lines_rem) ((void)0)
#endif #endif
static unsigned long display_header(int scr_width, int *lines_rem_p) static unsigned long display_header(int scr_width, int *lines_rem_p)
@ -528,15 +529,15 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width)
lines_rem--; lines_rem--;
#if ENABLE_FEATURE_TOP_DECIMALS #if ENABLE_FEATURE_TOP_DECIMALS
#define UPSCALE 1000 # define UPSCALE 1000
#define CALC_STAT(name, val) div_t name = div((val), 10) # define CALC_STAT(name, val) div_t name = div((val), 10)
#define SHOW_STAT(name) name.quot, '0'+name.rem # define SHOW_STAT(name) name.quot, '0'+name.rem
#define FMT "%3u.%c" # define FMT "%3u.%c"
#else #else
#define UPSCALE 100 # define UPSCALE 100
#define CALC_STAT(name, val) unsigned name = (val) # define CALC_STAT(name, val) unsigned name = (val)
#define SHOW_STAT(name) name # define SHOW_STAT(name) name
#define FMT "%4u%%" # define FMT "%4u%%"
#endif #endif
/* /*
* MEM% = s->vsz/MemTotal * MEM% = s->vsz/MemTotal
@ -646,9 +647,9 @@ static void reset_term(void)
tcsetattr_stdin_TCSANOW(&initial_settings); tcsetattr_stdin_TCSANOW(&initial_settings);
if (ENABLE_FEATURE_CLEAN_UP) { if (ENABLE_FEATURE_CLEAN_UP) {
clearmems(); clearmems();
#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE # if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
free(prev_hist); free(prev_hist);
#endif # endif
} }
} }
@ -895,7 +896,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
pfd[0].fd = 0; pfd[0].fd = 0;
pfd[0].events = POLLIN; pfd[0].events = POLLIN;
#endif /* FEATURE_USE_TERMIOS */ #endif
INIT_G(); INIT_G();
@ -909,10 +910,15 @@ int top_main(int argc UNUSED_PARAM, char **argv)
#endif #endif
/* all args are options; -n NUM */ /* all args are options; -n NUM */
opt_complementary = "-"; opt_complementary = "-"; /* options can be specified w/o dash */
col = getopt32(argv, "d:n:b", &str_interval, &str_iterations); col = getopt32(argv, "d:n:b"IF_FEATURE_TOPMEM("m"), &str_interval, &str_iterations);
#if ENABLE_FEATURE_TOPMEM
if (col & OPT_m) /* -m (busybox specific) */
scan_mask = TOPMEM_MASK;
#endif
if (col & OPT_d) { if (col & OPT_d) {
/* work around for "-d 1" -> "-d -1" done by getopt32 */ /* work around for "-d 1" -> "-d -1" done by getopt32
* (opt_complementary == "-" does this) */
if (str_interval[0] == '-') if (str_interval[0] == '-')
str_interval++; str_interval++;
/* Need to limit it to not overflow poll timeout */ /* Need to limit it to not overflow poll timeout */
@ -934,7 +940,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
bb_signals(BB_FATAL_SIGS, sig_catcher); bb_signals(BB_FATAL_SIGS, sig_catcher);
tcsetattr_stdin_TCSANOW(&new_settings); tcsetattr_stdin_TCSANOW(&new_settings);
#endif /* FEATURE_USE_TERMIOS */ #endif
#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
sort_function[0] = pcpu_sort; sort_function[0] = pcpu_sort;
@ -942,7 +948,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
sort_function[2] = time_sort; sort_function[2] = time_sort;
#else #else
sort_function[0] = mem_sort; sort_function[0] = mem_sort;
#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ #endif
while (1) { while (1) {
procps_status_t *p = NULL; procps_status_t *p = NULL;
@ -956,7 +962,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
sleep(interval); sleep(interval);
continue; continue;
} }
#endif /* FEATURE_USE_TERMIOS */ #endif
if (col > LINE_BUF_SIZE-2) /* +2 bytes for '\n', NUL, */ if (col > LINE_BUF_SIZE-2) /* +2 bytes for '\n', NUL, */
col = LINE_BUF_SIZE-2; col = LINE_BUF_SIZE-2;
@ -1015,7 +1021,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp); qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp);
#else #else
qsort(top, ntop, sizeof(top_status_t), (void*)(sort_function[0])); qsort(top, ntop, sizeof(top_status_t), (void*)(sort_function[0]));
#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */ #endif
} }
#if ENABLE_FEATURE_TOPMEM #if ENABLE_FEATURE_TOPMEM
else { /* TOPMEM */ else { /* TOPMEM */
@ -1058,12 +1064,12 @@ int top_main(int argc UNUSED_PARAM, char **argv)
if (c == 'm') { if (c == 'm') {
IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;) IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
sort_function[0] = mem_sort; sort_function[0] = mem_sort;
#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE # if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
sort_function[1] = pcpu_sort; sort_function[1] = pcpu_sort;
sort_function[2] = time_sort; sort_function[2] = time_sort;
#endif # endif
} }
#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE # if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
if (c == 'p') { if (c == 'p') {
IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;) IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
sort_function[0] = pcpu_sort; sort_function[0] = pcpu_sort;
@ -1076,7 +1082,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
sort_function[1] = mem_sort; sort_function[1] = mem_sort;
sort_function[2] = pcpu_sort; sort_function[2] = pcpu_sort;
} }
#if ENABLE_FEATURE_TOPMEM # if ENABLE_FEATURE_TOPMEM
if (c == 's') { if (c == 's') {
scan_mask = TOPMEM_MASK; scan_mask = TOPMEM_MASK;
free(prev_hist); free(prev_hist);
@ -1086,8 +1092,8 @@ int top_main(int argc UNUSED_PARAM, char **argv)
} }
if (c == 'r') if (c == 'r')
inverted ^= 1; inverted ^= 1;
#endif # endif
#if ENABLE_FEATURE_TOP_SMP_CPU # if ENABLE_FEATURE_TOP_SMP_CPU
/* procps-2.0.18 uses 'C', 3.2.7 uses '1' */ /* procps-2.0.18 uses 'C', 3.2.7 uses '1' */
if (c == 'c' || c == '1') { if (c == 'c' || c == '1') {
/* User wants to toggle per cpu <> aggregate */ /* User wants to toggle per cpu <> aggregate */
@ -1104,8 +1110,8 @@ int top_main(int argc UNUSED_PARAM, char **argv)
smp_cpu_info = !smp_cpu_info; smp_cpu_info = !smp_cpu_info;
get_jiffy_counts(); get_jiffy_counts();
} }
#endif # endif
#endif # endif
} }
#endif /* FEATURE_USE_TERMIOS */ #endif /* FEATURE_USE_TERMIOS */
} /* end of "while (1)" */ } /* end of "while (1)" */