aboutsummaryrefslogtreecommitdiff
path: root/procps
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-11-05 00:43:51 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-11-05 00:43:51 +0000
commit459e4d6cf77940977a064edab60c7162731554fb (patch)
tree5deb7d2b82c280440761cceb4281738867d5631a /procps
parentfa07680091d20f9da1f8fa2c145dd92b5d62ae09 (diff)
downloadbusybox-459e4d6cf77940977a064edab60c7162731554fb.tar.gz
replace /proc scanning code by more versatile one.
Use it where appropriate. Stop scanning /etc/passwd *for every process*!!! (uid->username) top: reduce memory usage - we won't save unneeded fields from /proc info anymore. Downside: ~+250 bytes of code
Diffstat (limited to 'procps')
-rw-r--r--procps/kill.c6
-rw-r--r--procps/ps.c28
-rw-r--r--procps/top.c144
3 files changed, 115 insertions, 63 deletions
diff --git a/procps/kill.c b/procps/kill.c
index 9b96b4c1a..18121f06f 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -82,7 +82,7 @@ do_it_now:
if (killall5) {
pid_t sid;
- procps_status_t* p;
+ procps_status_t* p = NULL;
// Cannot happen anyway? We don't TERM ourself, we STOP
// /* kill(-1, sig) on Linux (at least 2.1.x)
@@ -94,8 +94,8 @@ do_it_now:
pid = getpid();
sid = getsid(pid);
/* Now kill all processes except our session */
- while ((p = procps_scan(0))!=0) {
- if (getsid(p->pid)!=sid && p->pid!=pid && p->pid!=1)
+ while ((p = procps_scan(p, PSSCAN_PID|PSSCAN_SID))) {
+ if (p->sid != sid && p->pid != pid && p->pid != 1)
kill(p->pid, signo);
}
/* And let them continue */
diff --git a/procps/ps.c b/procps/ps.c
index 9d6e42d79..2ff6e77d4 100644
--- a/procps/ps.c
+++ b/procps/ps.c
@@ -11,7 +11,7 @@
int ps_main(int argc, char **argv)
{
- procps_status_t * p;
+ procps_status_t *p = NULL;
int i, len;
SKIP_SELINUX(const) int use_selinux = 0;
USE_SELINUX(security_context_t sid = NULL;)
@@ -50,7 +50,13 @@ int ps_main(int argc, char **argv)
else
puts(" PID Uid VmSize Stat Command");
- while ((p = procps_scan(1)) != 0) {
+ while ((p = procps_scan(p, 0
+ | PSSCAN_PID
+ | PSSCAN_UIDGID
+ | PSSCAN_STATE
+ | PSSCAN_RSS
+ | PSSCAN_CMD
+ ))) {
char *namecmd = p->cmd;
#if ENABLE_SELINUX
if (use_selinux) {
@@ -71,13 +77,18 @@ int ps_main(int argc, char **argv)
} else {
safe_strncpy(sbuf, "unknown", 7);
}
- len = printf("%5u %-32s %s ", (unsigned)p->pid, sbuf, p->state);
+ len = printf("%5u %-32s %s ", p->pid, sbuf, p->state);
} else
#endif
+ {
+ const char *user = get_cached_username(p->uid);
if (p->rss == 0)
- len = printf("%5u %-8s %s ", (unsigned)p->pid, p->user, p->state);
+ len = printf("%5u %-8s %s ",
+ p->pid, user, p->state);
else
- len = printf("%5u %-8s %6ld %s ", (unsigned)p->pid, p->user, p->rss, p->state);
+ len = printf("%5u %-8s %6ld %s ",
+ p->pid, user, p->rss, p->state);
+ }
i = terminal_width-len;
@@ -88,16 +99,15 @@ int ps_main(int argc, char **argv)
namecmd[i] = 0;
puts(namecmd);
} else {
- namecmd = p->short_cmd;
+ namecmd = p->comm;
if (i < 2)
i = 2;
if (strlen(namecmd) > ((size_t)i-2))
namecmd[i-2] = 0;
printf("[%s]\n", namecmd);
}
- /* no check needed, but to make valgrind happy.. */
- if (ENABLE_FEATURE_CLEAN_UP && p->cmd)
- free(p->cmd);
}
+ if (ENABLE_FEATURE_CLEAN_UP)
+ clear_username_cache();
return EXIT_SUCCESS;
}
diff --git a/procps/top.c b/procps/top.c
index c76fdc312..8d732d4b2 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -30,37 +30,76 @@
#include "busybox.h"
-typedef int (*cmp_t)(procps_status_t *P, procps_status_t *Q);
-static procps_status_t *top; /* Hehe */
+typedef struct {
+ unsigned long rss;
+#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+ unsigned long ticks;
+ unsigned pcpu; /* delta of ticks */
+#endif
+ unsigned pid, ppid;
+ unsigned uid;
+ char state[4];
+ char comm[COMM_LEN];
+} top_status_t;
+static top_status_t *top;
static int ntop;
+/* This structure stores some critical information from one frame to
+ the next. Used for finding deltas. */
+struct save_hist {
+ unsigned long ticks;
+ unsigned pid;
+};
+static struct save_hist *prev_hist;
+static int prev_hist_count;
+/* static int hist_iterations; */
+static unsigned total_pcpu;
+/* static unsigned long total_rss; */
+
+
#define OPT_BATCH_MODE (option_mask32 & 0x4)
#if ENABLE_FEATURE_USE_TERMIOS
-static int pid_sort(procps_status_t *P, procps_status_t *Q)
+static int pid_sort(top_status_t *P, top_status_t *Q)
{
+ /* Buggy wrt pids with high bit set */
+ /* (linux pids are in [1..2^15-1]) */
return (Q->pid - P->pid);
}
#endif
-static int mem_sort(procps_status_t *P, procps_status_t *Q)
+static int mem_sort(top_status_t *P, top_status_t *Q)
{
- return (int)(Q->rss - P->rss);
+ /* We want to avoid unsigned->signed and truncation errors */
+ if (Q->rss < P->rss) return -1;
+ return Q->rss != P->rss; /* 0 if ==, 1 if > */
}
-#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+
+typedef int (*cmp_funcp)(top_status_t *P, top_status_t *Q);
+
+#if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
+
+static cmp_funcp sort_function;
+
+#else
enum { SORT_DEPTH = 3 };
-static cmp_t sort_function[SORT_DEPTH];
-static int pcpu_sort(procps_status_t *P, procps_status_t *Q)
+static cmp_funcp sort_function[SORT_DEPTH];
+
+static int pcpu_sort(top_status_t *P, top_status_t *Q)
{
- return (Q->pcpu - P->pcpu);
+ /* Buggy wrt ticks with high bit set */
+ /* Affects only processes for which ticks overflow */
+ return (int)Q->pcpu - (int)P->pcpu;
}
-static int time_sort(procps_status_t *P, procps_status_t *Q)
+static int time_sort(top_status_t *P, top_status_t *Q)
{
- return (int)((Q->stime + Q->utime) - (P->stime + P->utime));
+ /* We want to avoid unsigned->signed and truncation errors */
+ if (Q->ticks < P->ticks) return -1;
+ return Q->ticks != P->ticks; /* 0 if ==, 1 if > */
}
static int mult_lvl_cmp(void* a, void* b) {
@@ -74,24 +113,6 @@ static int mult_lvl_cmp(void* a, void* b) {
return 0;
}
-/* This structure stores some critical information from one frame to
- the next. Mostly used for sorting. */
-struct save_hist {
- int ticks;
- pid_t pid;
-};
-
-/*
- * Calculates percent cpu usage for each task.
- */
-
-static struct save_hist *prev_hist;
-static int prev_hist_count;
-/* static int hist_iterations; */
-
-
-static unsigned total_pcpu;
-/* static unsigned long total_rss; */
typedef struct {
unsigned long long usr,nic,sys,idle,iowait,irq,softirq,steal;
@@ -115,11 +136,12 @@ static void get_jiffy_counts(void)
jif.busy = jif.total - jif.idle - jif.iowait;
}
+
static void do_stats(void)
{
- procps_status_t *cur;
+ top_status_t *cur;
pid_t pid;
- int total_time, i, last_i, n;
+ int i, last_i, n;
struct save_hist *new_hist;
get_jiffy_counts();
@@ -139,8 +161,7 @@ static void do_stats(void)
* and system time
*/
pid = cur->pid;
- total_time = cur->stime + cur->utime;
- new_hist[n].ticks = total_time;
+ new_hist[n].ticks = cur->ticks;
new_hist[n].pid = pid;
/* find matching entry from previous pass */
@@ -150,13 +171,13 @@ static void do_stats(void)
last_i = i;
if (prev_hist_count) do {
if (prev_hist[i].pid == pid) {
- cur->pcpu = total_time - prev_hist[i].ticks;
+ cur->pcpu = cur->ticks - prev_hist[i].ticks;
+ total_pcpu += cur->pcpu;
break;
}
i = (i+1) % prev_hist_count;
/* hist_iterations++; */
} while (i != last_i);
- total_pcpu += cur->pcpu;
/* total_rss += cur->rss; */
}
@@ -167,10 +188,9 @@ static void do_stats(void)
prev_hist = new_hist;
prev_hist_count = ntop;
}
-#else
-static cmp_t sort_function;
#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
+
/* display generic info (meminfo / loadavg) */
static unsigned long display_generic(int scr_width)
{
@@ -265,7 +285,7 @@ static void display_status(int count, int scr_width)
bits_per_int = sizeof(int)*8
};
- procps_status_t *s = top;
+ top_status_t *s = top;
char rss_str_buf[8];
unsigned long total_memory = display_generic(scr_width); /* or use total_rss? */
unsigned pmem_shift, pmem_scale;
@@ -333,14 +353,19 @@ static void display_status(int count, int scr_width)
sprintf(rss_str_buf, "%6ldM", s->rss/1024);
else
sprintf(rss_str_buf, "%7ld", s->rss);
- USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);)
- col -= printf("\n%5u %-8s %s %s%6u%3u.%c" \
- USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c") " ",
- (unsigned)s->pid, s->user, s->state, rss_str_buf, (unsigned)s->ppid,
+ USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(
+ pcpu = div((s->pcpu*pcpu_scale) >> pcpu_shift, 10);
+ )
+ col -= printf("\n%5u %-8s %s "
+ "%s%6u"
+ USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE("%3u.%c")
+ "%3u.%c ",
+ s->pid, get_cached_username(s->uid), s->state,
+ rss_str_buf, s->ppid,
USE_FEATURE_TOP_CPU_USAGE_PERCENTAGE(pcpu.quot, '0'+pcpu.rem,)
pmem.quot, '0'+pmem.rem);
if (col > 0)
- printf("%.*s", col, s->short_cmd);
+ printf("%.*s", col, s->comm);
/* printf(" %d/%d %lld/%lld", s->pcpu, total_pcpu,
jif.busy - prev_jif.busy, jif.total - prev_jif.total); */
s++;
@@ -350,18 +375,20 @@ static void display_status(int count, int scr_width)
fflush(stdout);
}
+
static void clearmems(void)
{
+ clear_username_cache();
free(top);
top = 0;
ntop = 0;
}
+
#if ENABLE_FEATURE_USE_TERMIOS
#include <termios.h>
#include <signal.h>
-
static struct termios initial_settings;
static void reset_term(void)
@@ -427,7 +454,7 @@ int top_main(int argc, char **argv)
#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
while (1) {
- procps_status_t *p;
+ procps_status_t *p = NULL;
/* Default to 25 lines - 5 lines for status */
lines = 24 - 3;
@@ -442,11 +469,26 @@ int top_main(int argc, char **argv)
#endif /* FEATURE_USE_TERMIOS */
/* read process IDs & status for all the processes */
- while ((p = procps_scan(0)) != 0) {
+ while ((p = procps_scan(p, 0
+ | PSSCAN_PID
+ | PSSCAN_PPID
+ | PSSCAN_RSS
+ | PSSCAN_STIME
+ | PSSCAN_UTIME
+ | PSSCAN_STATE
+ | PSSCAN_COMM
+ | PSSCAN_SID
+ | PSSCAN_UIDGID
+ ))) {
int n = ntop;
-
- top = xrealloc(top, (++ntop)*sizeof(procps_status_t));
- memcpy(top + n, p, sizeof(procps_status_t));
+ top = xrealloc(top, (++ntop)*sizeof(top_status_t));
+ top[n].pid = p->pid;
+ top[n].ppid = p->ppid;
+ top[n].rss = p->rss;
+ top[n].ticks = p->stime + p->utime;
+ top[n].uid = p->uid;
+ strcpy(top[n].state, p->state);
+ strcpy(top[n].comm, p->comm);
}
if (ntop == 0) {
bb_error_msg_and_die("can't find process info in /proc");
@@ -459,9 +501,9 @@ int top_main(int argc, char **argv)
continue;
}
do_stats();
- qsort(top, ntop, sizeof(procps_status_t), (void*)mult_lvl_cmp);
+ qsort(top, ntop, sizeof(top_status_t), (void*)mult_lvl_cmp);
#else
- qsort(top, ntop, sizeof(procps_status_t), (void*)sort_function);
+ qsort(top, ntop, sizeof(top_status_t), (void*)sort_function);
#endif /* FEATURE_TOP_CPU_USAGE_PERCENTAGE */
count = lines;
if (OPT_BATCH_MODE || count > ntop) {