diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-30 14:47:41 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-06-30 14:47:41 +0000 |
commit | 98ebab8b768d4651d8db2f46a0cd6bd53012c8e6 (patch) | |
tree | 2f491e67f1f49a31b0cfeeaabb032b646b8d808c | |
parent | 8b1409896d3224fec477bc372c4dceaebe6d6351 (diff) | |
download | busybox-w32-98ebab8b768d4651d8db2f46a0cd6bd53012c8e6.tar.gz busybox-w32-98ebab8b768d4651d8db2f46a0cd6bd53012c8e6.tar.bz2 busybox-w32-98ebab8b768d4651d8db2f46a0cd6bd53012c8e6.zip |
top,ps: improve /proc/PID/cmdinfo reading code
function old new delta
display_status - 1231 +1231
read_cmdline - 101 +101
parse_conf 1284 1303 +19
arith 2033 2042 +9
collect_blk 467 474 +7
fsck_main 1909 1911 +2
dhcprelay_main 1125 1122 -3
singlemount 4555 4547 -8
read_close 50 36 -14
get_lcm 123 105 -18
ed_main 3111 3084 -27
func_args 73 28 -45
procps_scan 732 658 -74
top_main 2187 899 -1288
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 4/8 up/down: 1369/-1477) Total: -108 bytes
text data bss dec hex filename
676048 2744 13968 692760 a9218 busybox_old
675940 2744 13968 692652 a91ac busybox_unstripped
-rw-r--r-- | include/libbb.h | 13 | ||||
-rw-r--r-- | libbb/procps.c | 35 | ||||
-rw-r--r-- | libbb/read.c | 6 | ||||
-rw-r--r-- | procps/ps.c | 63 | ||||
-rw-r--r-- | procps/top.c | 22 |
5 files changed, 80 insertions, 59 deletions
diff --git a/include/libbb.h b/include/libbb.h index 6a699a7e6..a95de848b 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -836,7 +836,7 @@ enum { COMM_LEN = 16 }; | |||
836 | typedef struct { | 836 | typedef struct { |
837 | DIR *dir; | 837 | DIR *dir; |
838 | /* Fields are set to 0/NULL if failed to determine (or not requested) */ | 838 | /* Fields are set to 0/NULL if failed to determine (or not requested) */ |
839 | char *cmd; | 839 | /*char *cmd;*/ |
840 | char *argv0; | 840 | char *argv0; |
841 | /*char *exe;*/ | 841 | /*char *exe;*/ |
842 | USE_SELINUX(char *context;) | 842 | USE_SELINUX(char *context;) |
@@ -852,7 +852,9 @@ typedef struct { | |||
852 | unsigned gid; | 852 | unsigned gid; |
853 | unsigned tty_major,tty_minor; | 853 | unsigned tty_major,tty_minor; |
854 | char state[4]; | 854 | char state[4]; |
855 | /* basename of executable in exec(2), read from /proc/N/stat */ | 855 | /* basename of executable in exec(2), read from /proc/N/stat |
856 | * (if executable is symlink or script, it is NOT replaced | ||
857 | * by link target or interpreter name) */ | ||
856 | char comm[COMM_LEN]; | 858 | char comm[COMM_LEN]; |
857 | /* user/group? - use passwd/group parsing functions */ | 859 | /* user/group? - use passwd/group parsing functions */ |
858 | } procps_status_t; | 860 | } procps_status_t; |
@@ -863,9 +865,9 @@ enum { | |||
863 | PSSCAN_SID = 1 << 3, | 865 | PSSCAN_SID = 1 << 3, |
864 | PSSCAN_UIDGID = 1 << 4, | 866 | PSSCAN_UIDGID = 1 << 4, |
865 | PSSCAN_COMM = 1 << 5, | 867 | PSSCAN_COMM = 1 << 5, |
866 | PSSCAN_CMD = 1 << 6, | 868 | /* PSSCAN_CMD = 1 << 6, - use read_cmdline instead */ |
867 | PSSCAN_ARGV0 = 1 << 7, | 869 | PSSCAN_ARGV0 = 1 << 7, |
868 | PSSCAN_EXE = 1 << 8, /* not implemented yet */ | 870 | /* PSSCAN_EXE = 1 << 8, - not implemented */ |
869 | PSSCAN_STATE = 1 << 9, | 871 | PSSCAN_STATE = 1 << 9, |
870 | PSSCAN_VSZ = 1 << 10, | 872 | PSSCAN_VSZ = 1 << 10, |
871 | PSSCAN_RSS = 1 << 11, | 873 | PSSCAN_RSS = 1 << 11, |
@@ -883,6 +885,9 @@ enum { | |||
883 | procps_status_t* alloc_procps_scan(int flags); | 885 | procps_status_t* alloc_procps_scan(int flags); |
884 | void free_procps_scan(procps_status_t* sp); | 886 | void free_procps_scan(procps_status_t* sp); |
885 | procps_status_t* procps_scan(procps_status_t* sp, int flags); | 887 | procps_status_t* procps_scan(procps_status_t* sp, int flags); |
888 | /* Format cmdline (up to col chars) into char buf[col+1] */ | ||
889 | /* Puts [comm] if cmdline is empty (-> process is a kernel thread) */ | ||
890 | void read_cmdline(char *buf, int col, unsigned pid, const char *comm); | ||
886 | pid_t *find_pid_by_name(const char* procName); | 891 | pid_t *find_pid_by_name(const char* procName); |
887 | pid_t *pidlist_reverse(pid_t *pidList); | 892 | pid_t *pidlist_reverse(pid_t *pidList); |
888 | 893 | ||
diff --git a/libbb/procps.c b/libbb/procps.c index 8413ce8a1..1987e98fd 100644 --- a/libbb/procps.c +++ b/libbb/procps.c | |||
@@ -102,7 +102,7 @@ procps_status_t *alloc_procps_scan(int flags) | |||
102 | void free_procps_scan(procps_status_t* sp) | 102 | void free_procps_scan(procps_status_t* sp) |
103 | { | 103 | { |
104 | closedir(sp->dir); | 104 | closedir(sp->dir); |
105 | free(sp->cmd); | 105 | free(sp->argv0); |
106 | USE_SELINUX(free(sp->context);) | 106 | USE_SELINUX(free(sp->context);) |
107 | free(sp); | 107 | free(sp); |
108 | } | 108 | } |
@@ -266,6 +266,7 @@ procps_status_t *procps_scan(procps_status_t* sp, int flags) | |||
266 | 266 | ||
267 | } | 267 | } |
268 | 268 | ||
269 | #if 0 /* PSSCAN_CMD is not used */ | ||
269 | if (flags & (PSSCAN_CMD|PSSCAN_ARGV0)) { | 270 | if (flags & (PSSCAN_CMD|PSSCAN_ARGV0)) { |
270 | if (sp->argv0) { | 271 | if (sp->argv0) { |
271 | free(sp->argv0); | 272 | free(sp->argv0); |
@@ -292,10 +293,42 @@ procps_status_t *procps_scan(procps_status_t* sp, int flags) | |||
292 | sp->cmd = xstrdup(buf); | 293 | sp->cmd = xstrdup(buf); |
293 | } | 294 | } |
294 | } | 295 | } |
296 | #else | ||
297 | if (flags & PSSCAN_ARGV0) { | ||
298 | if (sp->argv0) { | ||
299 | free(sp->argv0); | ||
300 | sp->argv0 = NULL; | ||
301 | } | ||
302 | strcpy(filename_tail, "/cmdline"); | ||
303 | n = read_to_buf(filename, buf); | ||
304 | if (n <= 0) | ||
305 | break; | ||
306 | if (flags & PSSCAN_ARGV0) | ||
307 | sp->argv0 = xstrdup(buf); | ||
308 | } | ||
309 | #endif | ||
295 | break; | 310 | break; |
296 | } | 311 | } |
297 | return sp; | 312 | return sp; |
298 | } | 313 | } |
314 | |||
315 | void read_cmdline(char *buf, int col, unsigned pid, const char *comm) | ||
316 | { | ||
317 | ssize_t sz; | ||
318 | char filename[sizeof("/proc//cmdline") + sizeof(int)*3]; | ||
319 | |||
320 | sprintf(filename, "/proc/%u/cmdline", pid); | ||
321 | sz = open_read_close(filename, buf, col); | ||
322 | if (sz > 0) { | ||
323 | buf[sz] = '\0'; | ||
324 | while (--sz >= 0) | ||
325 | if ((unsigned char)(buf[sz]) < ' ') | ||
326 | buf[sz] = ' '; | ||
327 | } else { | ||
328 | snprintf(buf, col, "[%s]", comm); | ||
329 | } | ||
330 | } | ||
331 | |||
299 | /* from kernel: | 332 | /* from kernel: |
300 | // pid comm S ppid pgid sid tty_nr tty_pgrp flg | 333 | // pid comm S ppid pgid sid tty_nr tty_pgrp flg |
301 | sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ | 334 | sprintf(buffer,"%d (%s) %c %d %d %d %d %d %lu %lu \ |
diff --git a/libbb/read.c b/libbb/read.c index 05bf754e0..502d407c4 100644 --- a/libbb/read.c +++ b/libbb/read.c | |||
@@ -124,11 +124,11 @@ char *xmalloc_reads(int fd, char *buf) | |||
124 | 124 | ||
125 | ssize_t read_close(int fd, void *buf, size_t size) | 125 | ssize_t read_close(int fd, void *buf, size_t size) |
126 | { | 126 | { |
127 | int e; | 127 | /*int e;*/ |
128 | size = full_read(fd, buf, size); | 128 | size = full_read(fd, buf, size); |
129 | e = errno; | 129 | /*e = errno;*/ |
130 | close(fd); | 130 | close(fd); |
131 | errno = e; | 131 | /*errno = e;*/ |
132 | return size; | 132 | return size; |
133 | } | 133 | } |
134 | 134 | ||
diff --git a/procps/ps.c b/procps/ps.c index 003e8eacd..c6bffc60d 100644 --- a/procps/ps.c +++ b/procps/ps.c | |||
@@ -27,11 +27,7 @@ static void func_comm(char *buf, int size, const procps_status_t *ps) | |||
27 | 27 | ||
28 | static void func_args(char *buf, int size, const procps_status_t *ps) | 28 | static void func_args(char *buf, int size, const procps_status_t *ps) |
29 | { | 29 | { |
30 | buf[0] = '\0'; | 30 | read_cmdline(buf, size, ps->pid, ps->comm); |
31 | if (ps->cmd) | ||
32 | safe_strncpy(buf, ps->cmd, size+1); | ||
33 | else if (size >= 2) | ||
34 | sprintf(buf, "[%.*s]", size-2, ps->comm); | ||
35 | } | 31 | } |
36 | 32 | ||
37 | static void func_pid(char *buf, int size, const procps_status_t *ps) | 33 | static void func_pid(char *buf, int size, const procps_status_t *ps) |
@@ -112,25 +108,25 @@ typedef struct { | |||
112 | 108 | ||
113 | static const ps_out_t out_spec[] = { | 109 | static const ps_out_t out_spec[] = { |
114 | // Mandated by POSIX: | 110 | // Mandated by POSIX: |
115 | { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID }, | 111 | { 8 , "user" ,"USER" ,func_user ,PSSCAN_UIDGID }, |
116 | { 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM }, | 112 | { 16 , "comm" ,"COMMAND",func_comm ,PSSCAN_COMM }, |
117 | { 256 , "args" ,"COMMAND",func_args ,PSSCAN_CMD|PSSCAN_COMM }, | 113 | { 256 , "args" ,"COMMAND",func_args ,PSSCAN_COMM }, |
118 | { 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID }, | 114 | { 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID }, |
119 | { 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID }, | 115 | { 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID }, |
120 | { 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID }, | 116 | { 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID }, |
121 | // { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_ }, | 117 | // { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_ }, |
122 | // { sizeof("GROUP" )-1, "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID }, | 118 | // { sizeof("GROUP" )-1, "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID }, |
123 | // { sizeof("NI" )-1, "nice" ,"NI" ,func_nice ,PSSCAN_ }, | 119 | // { sizeof("NI" )-1, "nice" ,"NI" ,func_nice ,PSSCAN_ }, |
124 | // { sizeof("%CPU" )-1, "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ }, | 120 | // { sizeof("%CPU" )-1, "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ }, |
125 | // { sizeof("RGROUP" )-1, "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID }, | 121 | // { sizeof("RGROUP" )-1, "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID }, |
126 | // { sizeof("RUSER" )-1, "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID }, | 122 | // { sizeof("RUSER" )-1, "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID }, |
127 | // { sizeof("TIME" )-1, "time" ,"TIME" ,func_time ,PSSCAN_ }, | 123 | // { sizeof("TIME" )-1, "time" ,"TIME" ,func_time ,PSSCAN_ }, |
128 | { 6 , "tty" ,"TT" ,func_tty ,PSSCAN_TTY }, | 124 | { 6 , "tty" ,"TT" ,func_tty ,PSSCAN_TTY }, |
129 | { 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ }, | 125 | { 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ }, |
130 | // Not mandated by POSIX, but useful: | 126 | // Not mandated by POSIX, but useful: |
131 | { 4 , "rss" ,"RSS" ,func_rss ,PSSCAN_RSS }, | 127 | { 4 , "rss" ,"RSS" ,func_rss ,PSSCAN_RSS }, |
132 | #if ENABLE_SELINUX | 128 | #if ENABLE_SELINUX |
133 | { 35 , "label" ,"LABEL" ,func_label ,PSSCAN_CONTEXT }, | 129 | { 35 , "label" ,"LABEL" ,func_label ,PSSCAN_CONTEXT }, |
134 | #endif | 130 | #endif |
135 | }; | 131 | }; |
136 | 132 | ||
@@ -386,10 +382,9 @@ int ps_main(int argc, char **argv) | |||
386 | | PSSCAN_UIDGID | 382 | | PSSCAN_UIDGID |
387 | | PSSCAN_STATE | 383 | | PSSCAN_STATE |
388 | | PSSCAN_VSZ | 384 | | PSSCAN_VSZ |
389 | | PSSCAN_CMD | 385 | | PSSCAN_COMM |
390 | | use_selinux | 386 | | use_selinux |
391 | ))) { | 387 | ))) { |
392 | char *namecmd = p->cmd; | ||
393 | #if ENABLE_SELINUX | 388 | #if ENABLE_SELINUX |
394 | if (use_selinux) { | 389 | if (use_selinux) { |
395 | len = printf("%5u %-32s %s ", | 390 | len = printf("%5u %-32s %s ", |
@@ -408,21 +403,11 @@ int ps_main(int argc, char **argv) | |||
408 | p->pid, user, p->vsz, p->state); | 403 | p->pid, user, p->vsz, p->state); |
409 | } | 404 | } |
410 | 405 | ||
411 | i = terminal_width-len; | 406 | { |
412 | 407 | char sz = terminal_width - len; | |
413 | if (namecmd && namecmd[0]) { | 408 | char buf[sz + 1]; |
414 | if (i < 0) | 409 | read_cmdline(buf, sz, p->pid, p->comm); |
415 | i = 0; | 410 | puts(buf); |
416 | if (strlen(namecmd) > (size_t)i) | ||
417 | namecmd[i] = '\0'; | ||
418 | puts(namecmd); | ||
419 | } else { | ||
420 | namecmd = p->comm; | ||
421 | if (i < 2) | ||
422 | i = 2; | ||
423 | if (strlen(namecmd) > ((size_t)i-2)) | ||
424 | namecmd[i-2] = '\0'; | ||
425 | printf("[%s]\n", namecmd); | ||
426 | } | 411 | } |
427 | } | 412 | } |
428 | if (ENABLE_FEATURE_CLEAN_UP) | 413 | if (ENABLE_FEATURE_CLEAN_UP) |
diff --git a/procps/top.c b/procps/top.c index 136f1404a..a37a0d07f 100644 --- a/procps/top.c +++ b/procps/top.c | |||
@@ -40,11 +40,10 @@ typedef struct top_status_t { | |||
40 | unsigned pid, ppid; | 40 | unsigned pid, ppid; |
41 | unsigned uid; | 41 | unsigned uid; |
42 | char state[4]; | 42 | char state[4]; |
43 | /* TODO: read /proc/$PID/cmdline only for processes which are displayed */ | 43 | char comm[COMM_LEN]; |
44 | char cmd[64]; | ||
45 | } top_status_t; | 44 | } top_status_t; |
46 | 45 | ||
47 | typedef struct jiffy_counts_t{ | 46 | typedef struct jiffy_counts_t { |
48 | unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal; | 47 | unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal; |
49 | unsigned long long total; | 48 | unsigned long long total; |
50 | unsigned long long busy; | 49 | unsigned long long busy; |
@@ -421,7 +420,7 @@ static void display_status(int count, int scr_width) | |||
421 | 420 | ||
422 | /* Ok, all prelim data is ready, go thru the list */ | 421 | /* Ok, all prelim data is ready, go thru the list */ |
423 | while (count-- > 0) { | 422 | while (count-- > 0) { |
424 | int col = scr_width+1; | 423 | int col = scr_width; |
425 | CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); | 424 | CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); |
426 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE | 425 | #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE |
427 | CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift); | 426 | CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift); |
@@ -444,8 +443,11 @@ static void display_status(int count, int scr_width) | |||
444 | , SHOW_STAT(pcpu) | 443 | , SHOW_STAT(pcpu) |
445 | #endif | 444 | #endif |
446 | ); | 445 | ); |
447 | if (col > 0) | 446 | if (col > 0) { |
448 | printf("%.*s", col, s->cmd); | 447 | char buf[col + 1]; |
448 | read_cmdline(buf, col, s->pid, s->comm); | ||
449 | fputs(buf, stdout); | ||
450 | } | ||
449 | /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, | 451 | /* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu, |
450 | jif.busy - prev_jif.busy, jif.total - prev_jif.total); */ | 452 | jif.busy - prev_jif.busy, jif.total - prev_jif.total); */ |
451 | s++; | 453 | s++; |
@@ -560,12 +562,11 @@ int top_main(int argc, char **argv) | |||
560 | | PSSCAN_UTIME | 562 | | PSSCAN_UTIME |
561 | | PSSCAN_STATE | 563 | | PSSCAN_STATE |
562 | | PSSCAN_COMM | 564 | | PSSCAN_COMM |
563 | | PSSCAN_CMD | ||
564 | | PSSCAN_SID | 565 | | PSSCAN_SID |
565 | | PSSCAN_UIDGID | 566 | | PSSCAN_UIDGID |
566 | ))) { | 567 | ))) { |
567 | int n = ntop; | 568 | int n = ntop; |
568 | top = xrealloc(top, (++ntop)*sizeof(top_status_t)); | 569 | top = xrealloc(top, (++ntop) * sizeof(*top)); |
569 | top[n].pid = p->pid; | 570 | top[n].pid = p->pid; |
570 | top[n].ppid = p->ppid; | 571 | top[n].ppid = p->ppid; |
571 | top[n].vsz = p->vsz; | 572 | top[n].vsz = p->vsz; |
@@ -574,10 +575,7 @@ int top_main(int argc, char **argv) | |||
574 | #endif | 575 | #endif |
575 | top[n].uid = p->uid; | 576 | top[n].uid = p->uid; |
576 | strcpy(top[n].state, p->state); | 577 | strcpy(top[n].state, p->state); |
577 | if (p->cmd) | 578 | strcpy(top[n].comm, p->comm); |
578 | safe_strncpy(top[n].cmd, p->cmd, sizeof(top[n].cmd)); | ||
579 | else /* mimic ps */ | ||
580 | sprintf(top[n].cmd, "[%s]", p->comm); | ||
581 | } | 579 | } |
582 | if (ntop == 0) { | 580 | if (ntop == 0) { |
583 | bb_error_msg_and_die("no process info in /proc"); | 581 | bb_error_msg_and_die("no process info in /proc"); |