ps,top: add an option to show threads. +260 bytes of code
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
f00cfdfae5
commit
b410d4ada7
@ -1275,6 +1275,7 @@ enum { COMM_LEN = 16 };
|
||||
#endif
|
||||
typedef struct procps_status_t {
|
||||
DIR *dir;
|
||||
IF_FEATURE_SHOW_THREADS(DIR *task_dir;)
|
||||
uint8_t shift_pages_to_bytes;
|
||||
uint8_t shift_pages_to_kb;
|
||||
/* Fields are set to 0/NULL if failed to determine (or not requested) */
|
||||
@ -1348,6 +1349,7 @@ enum {
|
||||
PSSCAN_CPU = (1 << 19) * ENABLE_FEATURE_TOP_SMP_PROCESS,
|
||||
PSSCAN_NICE = (1 << 20) * ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS,
|
||||
PSSCAN_RUIDGID = (1 << 21) * ENABLE_FEATURE_PS_ADDITIONAL_COLUMNS,
|
||||
PSSCAN_TASKS = (1 << 22) * ENABLE_FEATURE_SHOW_THREADS,
|
||||
/* These are all retrieved from proc/NN/stat in one go: */
|
||||
PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID
|
||||
/**/ | PSSCAN_COMM | PSSCAN_STATE
|
||||
|
@ -110,6 +110,10 @@ static procps_status_t* FAST_FUNC alloc_procps_scan(void)
|
||||
void FAST_FUNC free_procps_scan(procps_status_t* sp)
|
||||
{
|
||||
closedir(sp->dir);
|
||||
#if ENABLE_FEATURE_SHOW_THREADS
|
||||
if (sp->task_dir)
|
||||
closedir(sp->task_dir);
|
||||
#endif
|
||||
free(sp->argv0);
|
||||
free(sp->exe);
|
||||
IF_SELINUX(free(sp->context);)
|
||||
@ -189,14 +193,35 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
|
||||
sp = alloc_procps_scan();
|
||||
|
||||
for (;;) {
|
||||
#if ENABLE_FEATURE_SHOW_THREADS
|
||||
if ((flags & PSSCAN_TASKS) && sp->task_dir) {
|
||||
entry = readdir(sp->task_dir);
|
||||
if (entry)
|
||||
goto got_entry;
|
||||
closedir(sp->task_dir);
|
||||
sp->task_dir = NULL;
|
||||
}
|
||||
#endif
|
||||
entry = readdir(sp->dir);
|
||||
if (entry == NULL) {
|
||||
free_procps_scan(sp);
|
||||
return NULL;
|
||||
}
|
||||
IF_FEATURE_SHOW_THREADS(got_entry:)
|
||||
pid = bb_strtou(entry->d_name, NULL, 10);
|
||||
if (errno)
|
||||
continue;
|
||||
#if ENABLE_FEATURE_SHOW_THREADS
|
||||
if ((flags & PSSCAN_TASKS) && !sp->task_dir) {
|
||||
/* We found another /proc/PID. Do not use it,
|
||||
* there will be /proc/PID/task/PID (same PID!),
|
||||
* so just go ahead and dive into /proc/PID/task. */
|
||||
char task_dir[sizeof("/proc/%u/task") + sizeof(int)*3];
|
||||
sprintf(task_dir, "/proc/%u/task", pid);
|
||||
sp->task_dir = xopendir(task_dir);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* After this point we have to break, not continue
|
||||
* ("continue" would mean that current /proc/NNN
|
||||
|
@ -188,6 +188,13 @@ config FEATURE_TOPMEM
|
||||
help
|
||||
Enable 's' in top (gives lots of memory info).
|
||||
|
||||
config FEATURE_SHOW_THREADS
|
||||
bool "Support for showing threads in ps/top"
|
||||
default n
|
||||
depends on PS || TOP
|
||||
help
|
||||
Enables ps -T option and 'h' command in top
|
||||
|
||||
config UPTIME
|
||||
bool "uptime"
|
||||
default n
|
||||
@ -203,5 +210,4 @@ config WATCH
|
||||
watch is used to execute a program periodically, showing
|
||||
output to the screen.
|
||||
|
||||
|
||||
endmenu
|
||||
|
31
procps/ps.c
31
procps/ps.c
@ -17,7 +17,6 @@ enum { MAX_WIDTH = 2*1024 };
|
||||
#if ENABLE_DESKTOP
|
||||
|
||||
#include <sys/times.h> /* for times() */
|
||||
//#include <sys/sysinfo.h> /* for sysinfo() */
|
||||
#ifndef AT_CLKTCK
|
||||
#define AT_CLKTCK 17
|
||||
#endif
|
||||
@ -61,6 +60,7 @@ struct globals {
|
||||
#define kernel_HZ (G.kernel_HZ )
|
||||
#define seconds_since_boot (G.seconds_since_boot)
|
||||
#define default_o (G.default_o )
|
||||
#define INIT_G() do { } while (0)
|
||||
|
||||
#if ENABLE_FEATURE_PS_TIME
|
||||
/* for ELF executables, notes are pushed before environment and args */
|
||||
@ -452,21 +452,34 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
|
||||
{
|
||||
procps_status_t *p;
|
||||
llist_t* opt_o = NULL;
|
||||
IF_SELINUX(int opt;)
|
||||
int opt;
|
||||
enum {
|
||||
OPT_Z = (1 << 0),
|
||||
OPT_o = (1 << 1),
|
||||
OPT_a = (1 << 2),
|
||||
OPT_A = (1 << 3),
|
||||
OPT_d = (1 << 4),
|
||||
OPT_e = (1 << 5),
|
||||
OPT_f = (1 << 6),
|
||||
OPT_l = (1 << 7),
|
||||
OPT_T = (1 << 8) * ENABLE_FEATURE_SHOW_THREADS,
|
||||
};
|
||||
|
||||
INIT_G();
|
||||
|
||||
// POSIX:
|
||||
// -a Write information for all processes associated with terminals
|
||||
// Implementations may omit session leaders from this list
|
||||
// -A Write information for all processes
|
||||
// -d Write information for all processes, except session leaders
|
||||
// -e Write information for all processes (equivalent to -A.)
|
||||
// -e Write information for all processes (equivalent to -A)
|
||||
// -f Generate a full listing
|
||||
// -l Generate a long listing
|
||||
// -o col1,col2,col3=header
|
||||
// Select which columns to display
|
||||
/* We allow (and ignore) most of the above. FIXME */
|
||||
opt_complementary = "o::";
|
||||
IF_SELINUX(opt =) getopt32(argv, "Zo:aAdefl", &opt_o);
|
||||
opt = getopt32(argv, "Zo:aAdefl" IF_FEATURE_SHOW_THREADS("T"), &opt_o);
|
||||
if (opt_o) {
|
||||
do {
|
||||
parse_o(llist_pop(&opt_o));
|
||||
@ -474,7 +487,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
|
||||
} else {
|
||||
/* Below: parse_o() needs char*, NOT const char*... */
|
||||
#if ENABLE_SELINUX
|
||||
if (!(opt & 1) || !is_selinux_enabled()) {
|
||||
if (!(opt & OPT_Z) || !is_selinux_enabled()) {
|
||||
/* no -Z or no SELinux: do not show LABEL */
|
||||
strcpy(default_o, DEFAULT_O_STR + sizeof(SELINUX_O_PREFIX)-1);
|
||||
} else
|
||||
@ -485,6 +498,10 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
|
||||
parse_o(default_o);
|
||||
}
|
||||
post_process();
|
||||
#if ENABLE_FEATURE_SHOW_THREADS
|
||||
if (opt & OPT_T)
|
||||
need_flags |= PSSCAN_TASKS;
|
||||
#endif
|
||||
|
||||
/* Was INT_MAX, but some libc's go belly up with printf("%.*s")
|
||||
* and such large widths */
|
||||
@ -497,7 +514,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv)
|
||||
format_header();
|
||||
|
||||
p = NULL;
|
||||
while ((p = procps_scan(p, need_flags))) {
|
||||
while ((p = procps_scan(p, need_flags)) != NULL) {
|
||||
format_process(p);
|
||||
}
|
||||
|
||||
@ -558,7 +575,7 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
|
||||
| PSSCAN_VSZ
|
||||
| PSSCAN_COMM
|
||||
| use_selinux
|
||||
))) {
|
||||
)) != NULL) {
|
||||
#if ENABLE_SELINUX
|
||||
if (use_selinux) {
|
||||
len = printf("%5u %-32.32s %s ",
|
||||
|
21
procps/top.c
21
procps/top.c
@ -976,7 +976,10 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
||||
/* read process IDs & status for all the processes */
|
||||
while ((p = procps_scan(p, scan_mask)) != NULL) {
|
||||
int n;
|
||||
if (scan_mask == TOP_MASK) {
|
||||
#if ENABLE_FEATURE_TOPMEM
|
||||
if (scan_mask != TOPMEM_MASK)
|
||||
#endif
|
||||
{
|
||||
n = ntop;
|
||||
top = xrealloc_vector(top, 6, ntop++);
|
||||
top[n].pid = p->pid;
|
||||
@ -991,8 +994,9 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
||||
#if ENABLE_FEATURE_TOP_SMP_PROCESS
|
||||
top[n].last_seen_on_cpu = p->last_seen_on_cpu;
|
||||
#endif
|
||||
} else { /* TOPMEM */
|
||||
}
|
||||
#if ENABLE_FEATURE_TOPMEM
|
||||
else { /* TOPMEM */
|
||||
if (!(p->mapped_ro | p->mapped_rw))
|
||||
continue; /* kernel threads are ignored */
|
||||
n = ntop;
|
||||
@ -1007,15 +1011,15 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
||||
topmem[n].dirty = p->private_dirty + p->shared_dirty;
|
||||
topmem[n].dirty_sh = p->shared_dirty;
|
||||
topmem[n].stack = p->stack;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} /* end of "while we read /proc" */
|
||||
if (ntop == 0) {
|
||||
bb_error_msg("no process info in /proc");
|
||||
break;
|
||||
}
|
||||
|
||||
if (scan_mask == TOP_MASK) {
|
||||
if (scan_mask != TOPMEM_MASK) {
|
||||
#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
|
||||
if (!prev_hist_count) {
|
||||
do_stats();
|
||||
@ -1039,7 +1043,7 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
||||
if (OPT_BATCH_MODE) {
|
||||
lines_rem = INT_MAX;
|
||||
}
|
||||
if (scan_mask == TOP_MASK)
|
||||
if (scan_mask != TOPMEM_MASK)
|
||||
display_process_list(lines_rem, col);
|
||||
#if ENABLE_FEATURE_TOPMEM
|
||||
else
|
||||
@ -1076,6 +1080,13 @@ int top_main(int argc UNUSED_PARAM, char **argv)
|
||||
sort_function[2] = time_sort;
|
||||
# endif
|
||||
}
|
||||
#if ENABLE_FEATURE_SHOW_THREADS
|
||||
if (c == 'h'
|
||||
IF_FEATURE_TOPMEM(&& scan_mask != TOPMEM_MASK)
|
||||
) {
|
||||
scan_mask ^= PSSCAN_TASKS;
|
||||
}
|
||||
#endif
|
||||
# if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
|
||||
if (c == 'p') {
|
||||
IF_FEATURE_TOPMEM(scan_mask = TOP_MASK;)
|
||||
|
Loading…
Reference in New Issue
Block a user