top: implement scrolling up/down (_very_ useful)
function old new delta handle_input 494 564 +70 top_main 928 947 +19 display_topmem_process_list 363 381 +18 display_process_list 1442 1453 +11 clearmems 38 28 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 118/-10) Total: 108 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
3c62bbae94
commit
2fb8d0dee9
@ -140,60 +140,6 @@ config BB_SYSCTL
|
|||||||
help
|
help
|
||||||
Configure kernel parameters at runtime.
|
Configure kernel parameters at runtime.
|
||||||
|
|
||||||
config TOP
|
|
||||||
bool "top"
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
The top program provides a dynamic real-time view of a running
|
|
||||||
system.
|
|
||||||
|
|
||||||
config FEATURE_TOP_CPU_USAGE_PERCENTAGE
|
|
||||||
bool "Show CPU per-process usage percentage"
|
|
||||||
default y
|
|
||||||
depends on TOP
|
|
||||||
help
|
|
||||||
Make top display CPU usage for each process.
|
|
||||||
This adds about 2k.
|
|
||||||
|
|
||||||
config FEATURE_TOP_CPU_GLOBAL_PERCENTS
|
|
||||||
bool "Show CPU global usage percentage"
|
|
||||||
default y
|
|
||||||
depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
|
|
||||||
help
|
|
||||||
Makes top display "CPU: NN% usr NN% sys..." line.
|
|
||||||
This adds about 0.5k.
|
|
||||||
|
|
||||||
config FEATURE_TOP_SMP_CPU
|
|
||||||
bool "SMP CPU usage display ('c' key)"
|
|
||||||
default y
|
|
||||||
depends on FEATURE_TOP_CPU_GLOBAL_PERCENTS
|
|
||||||
help
|
|
||||||
Allow 'c' key to switch between individual/cumulative CPU stats
|
|
||||||
This adds about 0.5k.
|
|
||||||
|
|
||||||
config FEATURE_TOP_DECIMALS
|
|
||||||
bool "Show 1/10th of a percent in CPU/mem statistics"
|
|
||||||
default y
|
|
||||||
depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
|
|
||||||
help
|
|
||||||
Show 1/10th of a percent in CPU/mem statistics.
|
|
||||||
This adds about 0.3k.
|
|
||||||
|
|
||||||
config FEATURE_TOP_SMP_PROCESS
|
|
||||||
bool "Show CPU process runs on ('j' field)"
|
|
||||||
default y
|
|
||||||
depends on TOP
|
|
||||||
help
|
|
||||||
Show CPU where process was last found running on.
|
|
||||||
This is the 'j' field.
|
|
||||||
|
|
||||||
config FEATURE_TOPMEM
|
|
||||||
bool "Topmem command ('s' key)"
|
|
||||||
default y
|
|
||||||
depends on TOP
|
|
||||||
help
|
|
||||||
Enable 's' in top (gives lots of memory info).
|
|
||||||
|
|
||||||
config FEATURE_SHOW_THREADS
|
config FEATURE_SHOW_THREADS
|
||||||
bool "Support for showing threads in ps/pstree/top"
|
bool "Support for showing threads in ps/pstree/top"
|
||||||
default y
|
default y
|
||||||
|
130
procps/top.c
130
procps/top.c
@ -50,6 +50,60 @@
|
|||||||
* chroot . ./top -bn1 >top1.out
|
* chroot . ./top -bn1 >top1.out
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//config:config TOP
|
||||||
|
//config: bool "top"
|
||||||
|
//config: default y
|
||||||
|
//config: help
|
||||||
|
//config: The top program provides a dynamic real-time view of a running
|
||||||
|
//config: system.
|
||||||
|
//config:
|
||||||
|
//config:config FEATURE_TOP_CPU_USAGE_PERCENTAGE
|
||||||
|
//config: bool "Show CPU per-process usage percentage"
|
||||||
|
//config: default y
|
||||||
|
//config: depends on TOP
|
||||||
|
//config: help
|
||||||
|
//config: Make top display CPU usage for each process.
|
||||||
|
//config: This adds about 2k.
|
||||||
|
//config:
|
||||||
|
//config:config FEATURE_TOP_CPU_GLOBAL_PERCENTS
|
||||||
|
//config: bool "Show CPU global usage percentage"
|
||||||
|
//config: default y
|
||||||
|
//config: depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
|
||||||
|
//config: help
|
||||||
|
//config: Makes top display "CPU: NN% usr NN% sys..." line.
|
||||||
|
//config: This adds about 0.5k.
|
||||||
|
//config:
|
||||||
|
//config:config FEATURE_TOP_SMP_CPU
|
||||||
|
//config: bool "SMP CPU usage display ('c' key)"
|
||||||
|
//config: default y
|
||||||
|
//config: depends on FEATURE_TOP_CPU_GLOBAL_PERCENTS
|
||||||
|
//config: help
|
||||||
|
//config: Allow 'c' key to switch between individual/cumulative CPU stats
|
||||||
|
//config: This adds about 0.5k.
|
||||||
|
//config:
|
||||||
|
//config:config FEATURE_TOP_DECIMALS
|
||||||
|
//config: bool "Show 1/10th of a percent in CPU/mem statistics"
|
||||||
|
//config: default y
|
||||||
|
//config: depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE
|
||||||
|
//config: help
|
||||||
|
//config: Show 1/10th of a percent in CPU/mem statistics.
|
||||||
|
//config: This adds about 0.3k.
|
||||||
|
//config:
|
||||||
|
//config:config FEATURE_TOP_SMP_PROCESS
|
||||||
|
//config: bool "Show CPU process runs on ('j' field)"
|
||||||
|
//config: default y
|
||||||
|
//config: depends on TOP
|
||||||
|
//config: help
|
||||||
|
//config: Show CPU where process was last found running on.
|
||||||
|
//config: This is the 'j' field.
|
||||||
|
//config:
|
||||||
|
//config:config FEATURE_TOPMEM
|
||||||
|
//config: bool "Topmem command ('s' key)"
|
||||||
|
//config: default y
|
||||||
|
//config: depends on TOP
|
||||||
|
//config: help
|
||||||
|
//config: Enable 's' in top (gives lots of memory info).
|
||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
|
||||||
|
|
||||||
@ -101,6 +155,8 @@ struct globals {
|
|||||||
#endif
|
#endif
|
||||||
#if ENABLE_FEATURE_USE_TERMIOS
|
#if ENABLE_FEATURE_USE_TERMIOS
|
||||||
struct termios initial_settings;
|
struct termios initial_settings;
|
||||||
|
unsigned lines; /* screen height */
|
||||||
|
int scroll_ofs;
|
||||||
#endif
|
#endif
|
||||||
#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
|
#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
|
||||||
cmp_funcp sort_function[1];
|
cmp_funcp sort_function[1];
|
||||||
@ -117,6 +173,9 @@ struct globals {
|
|||||||
/* Per CPU samples: current and last */
|
/* Per CPU samples: current and last */
|
||||||
jiffy_counts_t *cpu_jif, *cpu_prev_jif;
|
jiffy_counts_t *cpu_jif, *cpu_prev_jif;
|
||||||
int num_cpus;
|
int num_cpus;
|
||||||
|
#endif
|
||||||
|
#if ENABLE_FEATURE_USE_TERMIOS
|
||||||
|
char kbd_input[KEYCODE_BUFFER_SIZE];
|
||||||
#endif
|
#endif
|
||||||
char line_buf[80];
|
char line_buf[80];
|
||||||
}; //FIX_ALIASING; - large code growth
|
}; //FIX_ALIASING; - large code growth
|
||||||
@ -602,9 +661,9 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width)
|
|||||||
|
|
||||||
/* Ok, all preliminary data is ready, go through the list */
|
/* Ok, all preliminary data is ready, go through the list */
|
||||||
scr_width += 2; /* account for leading '\n' and trailing NUL */
|
scr_width += 2; /* account for leading '\n' and trailing NUL */
|
||||||
if (lines_rem > ntop)
|
if (lines_rem > ntop - G.scroll_ofs)
|
||||||
lines_rem = ntop;
|
lines_rem = ntop - G.scroll_ofs;
|
||||||
s = top;
|
s = top + G.scroll_ofs;
|
||||||
while (--lines_rem >= 0) {
|
while (--lines_rem >= 0) {
|
||||||
unsigned col;
|
unsigned col;
|
||||||
CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift);
|
CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift);
|
||||||
@ -649,7 +708,6 @@ static void clearmems(void)
|
|||||||
clear_username_cache();
|
clear_username_cache();
|
||||||
free(top);
|
free(top);
|
||||||
top = NULL;
|
top = NULL;
|
||||||
ntop = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_FEATURE_USE_TERMIOS
|
#if ENABLE_FEATURE_USE_TERMIOS
|
||||||
@ -793,7 +851,7 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width)
|
|||||||
{
|
{
|
||||||
#define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK"
|
#define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK"
|
||||||
#define MIN_WIDTH sizeof(HDR_STR)
|
#define MIN_WIDTH sizeof(HDR_STR)
|
||||||
const topmem_status_t *s = topmem;
|
const topmem_status_t *s = topmem + G.scroll_ofs;
|
||||||
|
|
||||||
display_topmem_header(scr_width, &lines_rem);
|
display_topmem_header(scr_width, &lines_rem);
|
||||||
strcpy(line_buf, HDR_STR " COMMAND");
|
strcpy(line_buf, HDR_STR " COMMAND");
|
||||||
@ -801,8 +859,8 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width)
|
|||||||
printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf);
|
printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf);
|
||||||
lines_rem--;
|
lines_rem--;
|
||||||
|
|
||||||
if (lines_rem > ntop)
|
if (lines_rem > ntop - G.scroll_ofs)
|
||||||
lines_rem = ntop;
|
lines_rem = ntop - G.scroll_ofs;
|
||||||
while (--lines_rem >= 0) {
|
while (--lines_rem >= 0) {
|
||||||
/* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */
|
/* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */
|
||||||
ulltoa6_and_space(s->pid , &line_buf[0*6]);
|
ulltoa6_and_space(s->pid , &line_buf[0*6]);
|
||||||
@ -856,26 +914,57 @@ enum {
|
|||||||
#if ENABLE_FEATURE_USE_TERMIOS
|
#if ENABLE_FEATURE_USE_TERMIOS
|
||||||
static unsigned handle_input(unsigned scan_mask, unsigned interval)
|
static unsigned handle_input(unsigned scan_mask, unsigned interval)
|
||||||
{
|
{
|
||||||
unsigned char c;
|
|
||||||
struct pollfd pfd[1];
|
struct pollfd pfd[1];
|
||||||
|
|
||||||
pfd[0].fd = 0;
|
pfd[0].fd = 0;
|
||||||
pfd[0].events = POLLIN;
|
pfd[0].events = POLLIN;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (safe_poll(pfd, 1, interval * 1000) <= 0)
|
int32_t c;
|
||||||
return scan_mask;
|
|
||||||
interval = 0;
|
|
||||||
|
|
||||||
if (safe_read(STDIN_FILENO, &c, 1) != 1) { /* error/EOF? */
|
c = read_key(STDIN_FILENO, G.kbd_input, interval * 1000);
|
||||||
|
if (c == -1 && errno != EAGAIN) {
|
||||||
|
/* error/EOF */
|
||||||
option_mask32 |= OPT_EOF;
|
option_mask32 |= OPT_EOF;
|
||||||
return scan_mask;
|
break;
|
||||||
}
|
}
|
||||||
|
interval = 0;
|
||||||
|
|
||||||
if (c == initial_settings.c_cc[VINTR])
|
if (c == initial_settings.c_cc[VINTR])
|
||||||
return EXIT_MASK;
|
return EXIT_MASK;
|
||||||
if (c == initial_settings.c_cc[VEOF])
|
if (c == initial_settings.c_cc[VEOF])
|
||||||
return EXIT_MASK;
|
return EXIT_MASK;
|
||||||
|
|
||||||
|
if (c == KEYCODE_UP) {
|
||||||
|
G.scroll_ofs--;
|
||||||
|
goto normalize_ofs;
|
||||||
|
}
|
||||||
|
if (c == KEYCODE_DOWN) {
|
||||||
|
G.scroll_ofs++;
|
||||||
|
goto normalize_ofs;
|
||||||
|
}
|
||||||
|
if (c == KEYCODE_HOME) {
|
||||||
|
G.scroll_ofs = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (c == KEYCODE_END) {
|
||||||
|
G.scroll_ofs = ntop - G.lines / 2;
|
||||||
|
goto normalize_ofs;
|
||||||
|
}
|
||||||
|
if (c == KEYCODE_PAGEUP) {
|
||||||
|
G.scroll_ofs -= G.lines / 2;
|
||||||
|
goto normalize_ofs;
|
||||||
|
}
|
||||||
|
if (c == KEYCODE_PAGEDOWN) {
|
||||||
|
G.scroll_ofs += G.lines / 2;
|
||||||
|
normalize_ofs:
|
||||||
|
if (G.scroll_ofs >= ntop)
|
||||||
|
G.scroll_ofs = ntop - 1;
|
||||||
|
if (G.scroll_ofs < 0)
|
||||||
|
G.scroll_ofs = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
c |= 0x20; /* lowercase */
|
c |= 0x20; /* lowercase */
|
||||||
if (c == 'q')
|
if (c == 'q')
|
||||||
return EXIT_MASK;
|
return EXIT_MASK;
|
||||||
@ -1011,7 +1100,7 @@ int top_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
|||||||
int top_main(int argc UNUSED_PARAM, char **argv)
|
int top_main(int argc UNUSED_PARAM, char **argv)
|
||||||
{
|
{
|
||||||
int iterations;
|
int iterations;
|
||||||
unsigned lines, col;
|
unsigned col;
|
||||||
unsigned interval;
|
unsigned interval;
|
||||||
char *str_interval, *str_iterations;
|
char *str_interval, *str_iterations;
|
||||||
unsigned scan_mask = TOP_MASK;
|
unsigned scan_mask = TOP_MASK;
|
||||||
@ -1081,15 +1170,15 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
procps_status_t *p = NULL;
|
procps_status_t *p = NULL;
|
||||||
|
|
||||||
if (OPT_BATCH_MODE) {
|
if (OPT_BATCH_MODE) {
|
||||||
lines = INT_MAX;
|
G.lines = INT_MAX;
|
||||||
col = LINE_BUF_SIZE - 2; /* +2 bytes for '\n', NUL */
|
col = LINE_BUF_SIZE - 2; /* +2 bytes for '\n', NUL */
|
||||||
} else {
|
} else {
|
||||||
lines = 24; /* default */
|
G.lines = 24; /* default */
|
||||||
col = 79;
|
col = 79;
|
||||||
#if ENABLE_FEATURE_USE_TERMIOS
|
#if ENABLE_FEATURE_USE_TERMIOS
|
||||||
/* We output to stdout, we need size of stdout (not stdin)! */
|
/* We output to stdout, we need size of stdout (not stdin)! */
|
||||||
get_terminal_width_height(STDOUT_FILENO, &col, &lines);
|
get_terminal_width_height(STDOUT_FILENO, &col, &G.lines);
|
||||||
if (lines < 5 || col < 10) {
|
if (G.lines < 5 || col < 10) {
|
||||||
sleep(interval);
|
sleep(interval);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1099,6 +1188,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* read process IDs & status for all the processes */
|
/* read process IDs & status for all the processes */
|
||||||
|
ntop = 0;
|
||||||
while ((p = procps_scan(p, scan_mask)) != NULL) {
|
while ((p = procps_scan(p, scan_mask)) != NULL) {
|
||||||
int n;
|
int n;
|
||||||
#if ENABLE_FEATURE_TOPMEM
|
#if ENABLE_FEATURE_TOPMEM
|
||||||
@ -1165,10 +1255,10 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (scan_mask != TOPMEM_MASK)
|
if (scan_mask != TOPMEM_MASK)
|
||||||
display_process_list(lines, col);
|
display_process_list(G.lines, col);
|
||||||
#if ENABLE_FEATURE_TOPMEM
|
#if ENABLE_FEATURE_TOPMEM
|
||||||
else
|
else
|
||||||
display_topmem_process_list(lines, col);
|
display_topmem_process_list(G.lines, col);
|
||||||
#endif
|
#endif
|
||||||
clearmems();
|
clearmems();
|
||||||
if (iterations >= 0 && !--iterations)
|
if (iterations >= 0 && !--iterations)
|
||||||
|
Loading…
Reference in New Issue
Block a user