Hello, the attached patch adds 'time' and 'etime' for ps. It adds more than 2k (but only for CONFIG_DESKTOP) because of the expensive computation of HZ. If we omit support for pre-2.4 Linux, the space addition would go way done.
Detlef -- Detlef Vollmann vollmann engineering gmbh Linux and C++ for Embedded Systems http://www.vollmann.ch/
diff -Nupr busybox-1.9.0-orig/include/libbb.h busybox-1.9.0/include/libbb.h --- busybox-1.9.0-orig/include/libbb.h Fri Dec 21 23:00:31 2007 +++ busybox-1.9.0/include/libbb.h Thu Jan 3 21:59:37 2008 @@ -982,6 +982,7 @@ typedef struct procps_status_t { * it is memset(0) for each process in procps_scan() */ unsigned long vsz, rss; /* we round it to kbytes */ unsigned long stime, utime; + unsigned long start_time; unsigned pid; unsigned ppid; unsigned pgid; @@ -1024,11 +1025,12 @@ enum { PSSCAN_SMAPS = (1 << 15) * ENABLE_FEATURE_TOPMEM, PSSCAN_ARGVN = (1 << 16) * (ENABLE_PGREP | ENABLE_PKILL), USE_SELINUX(PSSCAN_CONTEXT = 1 << 17,) + PSSCAN_START_TIME = 1 << 18, /* These are all retrieved from proc/NN/stat in one go: */ PSSCAN_STAT = PSSCAN_PPID | PSSCAN_PGID | PSSCAN_SID | PSSCAN_COMM | PSSCAN_STATE | PSSCAN_VSZ | PSSCAN_RSS - | PSSCAN_STIME | PSSCAN_UTIME + | PSSCAN_STIME | PSSCAN_UTIME | PSSCAN_START_TIME | PSSCAN_TTY, }; procps_status_t* alloc_procps_scan(int flags); @@ -1040,6 +1042,11 @@ void read_cmdline(char *buf, int col, un pid_t *find_pid_by_name(const char* procName); pid_t *pidlist_reverse(pid_t *pidList); +#if ENABLE_DESKTOP +extern unsigned long Hertz; +extern unsigned long seconds_since_boot; +void init_hertz(void); +#endif extern const char bb_uuenc_tbl_base64[]; extern const char bb_uuenc_tbl_std[]; diff -Nupr busybox-1.9.0-orig/libbb/procps.c busybox-1.9.0/libbb/procps.c --- busybox-1.9.0-orig/libbb/procps.c Fri Dec 21 23:00:29 2007 +++ busybox-1.9.0/libbb/procps.c Thu Jan 3 22:52:59 2008 @@ -243,7 +243,8 @@ procps_status_t *procps_scan(procps_stat "%lu %lu " /* utime, stime */ "%*s %*s %*s " /* cutime, cstime, priority */ "%ld " /* nice */ - "%*s %*s %*s " /* timeout, it_real_value, start_time */ + "%*s %*s " /* timeout, it_real_value */ + "%lu " /* start_time */ "%lu " /* vsize */ "%lu " /* rss */ /* "%lu %lu %lu %lu %lu %lu " rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */ @@ -254,6 +255,7 @@ procps_status_t *procps_scan(procps_stat &sp->pgid, &sp->sid, &tty, &sp->utime, &sp->stime, &tasknice, + &sp->start_time, &vsz, &rss); if (n != 10) @@ -280,7 +282,8 @@ procps_status_t *procps_scan(procps_stat sp->stime = fast_strtoul_10(&cp); cp = skip_fields(cp, 3); /* cutime, cstime, priority */ tasknice = fast_strtoul_10(&cp); - cp = skip_fields(cp, 3); /* timeout, it_real_value, start_time */ + cp = skip_fields(cp, 2); /* timeout, it_real_value */ + sp->start_time = fast_strtoul_10(&cp); /* vsz is in bytes and we want kb */ sp->vsz = fast_strtoul_10(&cp) >> 10; /* vsz is in bytes but rss is in *PAGES*! Can you believe that? */ diff -Nupr busybox-1.9.0-orig/procps/Kbuild busybox-1.9.0/procps/Kbuild --- busybox-1.9.0-orig/procps/Kbuild Fri Dec 21 23:00:32 2007 +++ busybox-1.9.0/procps/Kbuild Thu Jan 3 15:58:11 2008 @@ -14,6 +14,7 @@ lib-$(CONFIG_PGREP) += pgrep.o lib-$(CONFIG_PKILL) += pgrep.o lib-$(CONFIG_PIDOF) += pidof.o lib-$(CONFIG_PS) += ps.o +lib-$(CONFIG_PS) += sysinfo.o lib-$(CONFIG_RENICE) += renice.o lib-$(CONFIG_BB_SYSCTL) += sysctl.o lib-$(CONFIG_TOP) += top.o diff -Nupr busybox-1.9.0-orig/procps/ps.c busybox-1.9.0/procps/ps.c --- busybox-1.9.0-orig/procps/ps.c Fri Dec 21 23:00:32 2007 +++ busybox-1.9.0/procps/ps.c Thu Jan 3 22:54:16 2008 @@ -73,6 +73,30 @@ static void func_tty(char *buf, int size snprintf(buf, size+1, "%u,%u", ps->tty_major, ps->tty_minor); } +static void func_etime(char *buf, int size, const procps_status_t *ps) +{ + /* elapsed time [[dd-]hh:]mm:ss; here only mm:ss */ + unsigned long mm; + unsigned ss; + + mm = seconds_since_boot - (unsigned long)(ps->start_time / Hertz); + ss = mm % 60; + mm /= 60; + snprintf(buf, size+1, "%3lu:%02u", mm, ss); +} + +static void func_time(char *buf, int size, const procps_status_t *ps) +{ + /* cumulative time [[dd-]hh:]mm:ss; here only mm:ss */ + unsigned long mm; + unsigned ss; + + mm = (ps->utime + ps->stime) / Hertz; + ss = mm % 60; + mm /= 60; + snprintf(buf, size+1, "%3lu:%02u", mm, ss); +} + #if ENABLE_SELINUX static void func_label(char *buf, int size, const procps_status_t *ps) { @@ -86,16 +110,6 @@ static void func_nice(char *buf, int siz ps->??? } -static void func_etime(char *buf, int size, const procps_status_t *ps) -{ - elapled time [[dd-]hh:]mm:ss -} - -static void func_time(char *buf, int size, const procps_status_t *ps) -{ - cumulative time [[dd-]hh:]mm:ss -} - static void func_pcpu(char *buf, int size, const procps_status_t *ps) { } @@ -117,13 +131,13 @@ static const ps_out_t out_spec[] = { { 5 , "pid" ,"PID" ,func_pid ,PSSCAN_PID }, { 5 , "ppid" ,"PPID" ,func_ppid ,PSSCAN_PPID }, { 5 , "pgid" ,"PGID" ,func_pgid ,PSSCAN_PGID }, -// { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_ }, + { sizeof("ELAPSED")-1, "etime" ,"ELAPSED",func_etime ,PSSCAN_START_TIME }, // { sizeof("GROUP" )-1, "group" ,"GROUP" ,func_group ,PSSCAN_UIDGID }, // { sizeof("NI" )-1, "nice" ,"NI" ,func_nice ,PSSCAN_ }, // { sizeof("%CPU" )-1, "pcpu" ,"%CPU" ,func_pcpu ,PSSCAN_ }, // { sizeof("RGROUP" )-1, "rgroup","RGROUP" ,func_rgroup,PSSCAN_UIDGID }, // { sizeof("RUSER" )-1, "ruser" ,"RUSER" ,func_ruser ,PSSCAN_UIDGID }, -// { sizeof("TIME" )-1, "time" ,"TIME" ,func_time ,PSSCAN_ }, + { 6 , "time" ,"TIME" ,func_time ,PSSCAN_STIME | PSSCAN_UTIME }, { 6 , "tty" ,"TT" ,func_tty ,PSSCAN_TTY }, { 4 , "vsz" ,"VSZ" ,func_vsz ,PSSCAN_VSZ }, // Not mandated by POSIX, but useful: @@ -137,7 +151,7 @@ static const ps_out_t out_spec[] = { #define SELINIX_O_PREFIX "label," #define DEFAULT_O_STR SELINIX_O_PREFIX "pid,user" /* TODO: ,vsz,stat */ ",args" #else -#define DEFAULT_O_STR "pid,user" /* TODO: ,vsz,stat */ ",args" +#define DEFAULT_O_STR "pid,user,time" /* TODO: ,vsz,stat */ ",args" #endif struct globals { @@ -317,6 +331,7 @@ int ps_main(int argc, char **argv) parse_o(default_o); } post_process(); + init_hertz(); /* Was INT_MAX, but some libc's go belly up with printf("%.*s") * and such large widths */ diff -Nupr busybox-1.9.0-orig/procps/sysinfo.c busybox-1.9.0/procps/sysinfo.c --- busybox-1.9.0-orig/procps/sysinfo.c Thu Jan 1 01:00:00 1970 +++ busybox-1.9.0/procps/sysinfo.c Fri Jan 4 15:04:46 2008 @@ -0,0 +1,247 @@ +// sysinfo.c - compute the Hertz value (HZ inside the kernel) +// taken from procps-3.2.7 +// +// adaption for busybox by Detlef Vollmann, Siemens, January 2008 +// original copyright notices: +// Copyright (C) 1992-1998 by Michael K. Johnson, [EMAIL PROTECTED] +// Copyright 1998-2003 Albert Cahalan +// +// This file is placed under the conditions of the GNU Library +// General Public License, version 2, or any later version. +// See file COPYING for information on distribution conditions. +// + +#if ENABLE_DESKTOP +#include "libbb.h" + +#ifndef HZ +#include <netinet/in.h> /* htons */ +#endif + +#define BAD_OPEN_MESSAGE "Error: /proc must be mounted\n" + +#define STAT_FILE "/proc/stat" +#define UPTIME_FILE "/proc/uptime" + +#define PROCPS_BUF_SIZE 1024 + + +/************** this part taken from version.c of procps-3.2.7 ********* + * Linux kernel version information for procps utilities + * Copyright (c) 1996 Charles Blake <[EMAIL PROTECTED]> + */ +#include <sys/utsname.h> + +#define LINUX_VERSION(x,y,z) (0x10000*(x) + 0x100*(y) + z) + +static int linux_version_code; + +static void init_Linux_version(void) +{ + static struct utsname uts; + int x = 0, y = 0, z = 0; /* cleared in case sscanf() < 3 */ + + if (uname(&uts) == -1) { /* failure implies impending death */ + exit(1); + } + if (sscanf(uts.release, "%d.%d.%d", &x, &y, &z) < 3) { + fprintf(stderr, /* *very* unlikely to happen by accident */ + "Non-standard uts for running kernel:\n" + "release %s=%d.%d.%d gives version code %d\n", + uts.release, x, y, z, LINUX_VERSION(x, y, z)); + } + linux_version_code = LINUX_VERSION(x, y, z); +} + +/*********************** end version.c part ****************************/ + +/*********************************************************************** + * Some values in /proc are expressed in units of 1/HZ seconds, where HZ + * is the kernel clock tick rate. One of these units is called a jiffy. + * The HZ value used in the kernel may vary according to hacker desire. + * According to Linus Torvalds, this is not true. He considers the values + * in /proc as being in architecture-dependant units that have no relation + * to the kernel clock tick rate. Examination of the kernel source code + * reveals that opinion as wishful thinking. + * + * In any case, we need the HZ constant as used in /proc. (the real HZ value + * may differ, but we don't care) There are several ways we could get HZ: + * + * 1. Include the kernel header file. If it changes, recompile this library. + * 2. Use the sysconf() function. When HZ changes, recompile the C library! + * 3. Ask the kernel. This is obviously correct... + * + * Linus Torvalds won't let us ask the kernel, because he thinks we should + * not know the HZ value. Oh well, we don't have to listen to him. + * Someone smuggled out the HZ value. :-) + * + * This code should work fine, even if Linus fixes the kernel to match his + * stated behavior. The code only fails in case of a partial conversion. + * + * Recent update: on some architectures, the 2.4 kernel provides an + * ELF note to indicate HZ. This may be for ARM or user-mode Linux + * support. This ought to be investigated. Note that sysconf() is still + * unreliable, because it doesn't return an error code when it is + * used with a kernel that doesn't support the ELF note. On some other + * architectures there may be a system call or sysctl() that will work. + */ + +unsigned long Hertz = 0; +unsigned long seconds_since_boot = 0; +static long smp_num_cpus = 0; + +static inline void file_to_buf(char const *filename, char *buf) +{ + if (open_read_close(filename, buf, sizeof(buf)) < 0) { + bb_error_msg_and_die(BAD_OPEN_MESSAGE); + } +} + +static void old_Hertz_hack(void) +{ + char buf[PROCPS_BUF_SIZE]; + unsigned long long user_j, nice_j, sys_j, other_j; /* jiffies (clock ticks) */ + double up_1, up_2, seconds; + unsigned long long jiffies; + unsigned h; + + if (smp_num_cpus == 0) { + smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN); + if (smp_num_cpus < 1) { + smp_num_cpus = 1; /* SPARC glibc is buggy */ + } + } +#if ENABLE_LOCALE_SUPPORT + char *restrict savelocale; + + savelocale = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "C"); +#endif + do { + file_to_buf(UPTIME_FILE, buf); + sscanf(buf, "%lf", &up_1); + file_to_buf(STAT_FILE, buf); + sscanf(buf, "cpu %Lu %Lu %Lu %Lu", &user_j, &nice_j, &sys_j, + &other_j); + file_to_buf(UPTIME_FILE, buf); + sscanf(buf, "%lf", &up_2); + } while ((long long) ((up_2 - up_1) * 1000.0 / up_1)); /* want under 0.1% error */ +#if ENABLE_LOCALE_SUPPORT + setlocale(LC_NUMERIC, savelocale); +#endif + jiffies = user_j + nice_j + sys_j + other_j; + seconds = (up_1 + up_2) / 2; + h = (unsigned) ((double) jiffies / seconds / smp_num_cpus); + /* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */ + switch (h) { + case 9 ... 11: + Hertz = 10; /* S/390 (sometimes) */ + break; + case 18 ... 22: + Hertz = 20; /* user-mode Linux */ + break; + case 30 ... 34: + Hertz = 32; /* ia64 emulator */ + break; + case 48 ... 52: + Hertz = 50; + break; + case 58 ... 61: + Hertz = 60; + break; + case 62 ... 65: + Hertz = 64; /* StrongARM /Shark */ + break; + case 95 ... 105: + Hertz = 100; /* normal Linux */ + break; + case 124 ... 132: + Hertz = 128; /* MIPS, ARM */ + break; + case 195 ... 204: + Hertz = 200; /* normal << 1 */ + break; + case 253 ... 260: + Hertz = 256; + break; + case 393 ... 408: + Hertz = 400; /* normal << 2 */ + break; + case 790 ... 808: + Hertz = 800; /* normal << 3 */ + break; + case 990 ... 1010: + Hertz = 1000; /* ARM */ + break; + case 1015 ... 1035: + Hertz = 1024; /* Alpha, ia64 */ + break; + case 1180 ... 1220: + Hertz = 1200; /* Alpha */ + break; + default: +#ifdef HZ + Hertz = (unsigned long long) HZ; /* <asm/param.h> */ +#else + /* If 32-bit or big-endian (not Alpha or ia64), assume HZ is 100. */ + Hertz = (sizeof(long) == sizeof(int) + || htons(999) == 999) ? 100UL : 1024UL; +#endif + fprintf(stderr, "Unknown HZ value! (%d) Assume %ld.\n", h, Hertz); + } + seconds_since_boot = seconds; +} + +static void get_uptime(void) +{ + char buf[PROCPS_BUF_SIZE]; + +#if ENABLE_LOCALE_SUPPORT + char *restrict savelocale; + + savelocale = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "C"); +#endif + + file_to_buf(UPTIME_FILE, buf); + sscanf(buf, "%lu", &seconds_since_boot); + +#if ENABLE_LOCALE_SUPPORT + setlocale(LC_NUMERIC, savelocale); +#endif +} + +#ifndef AT_CLKTCK +#define AT_CLKTCK 17 // frequency of times() +#endif +#define NOTE_NOT_FOUND 42 + +/* for ELF executables, notes are pushed before environment and args */ +static unsigned long find_elf_note(unsigned long findme) +{ + unsigned long *ep = (unsigned long *) environ; + + while (*ep++); + while (*ep) { + if (ep[0] == findme) { + return ep[1]; + } + ep += 2; + } + return NOTE_NOT_FOUND; +} + +void init_hertz(void) +{ + init_Linux_version(); + if (linux_version_code > LINUX_VERSION(2, 4, 0)) { + Hertz = find_elf_note(AT_CLKTCK); + if (Hertz != NOTE_NOT_FOUND) { + get_uptime(); + return; + } + fputs("2.4+ kernel w/o ELF notes? -- report this\n", stderr); + } + old_Hertz_hack(); +} +#endif /* ENABLE_DESKTOP */
_______________________________________________ busybox mailing list busybox@busybox.net http://busybox.net/cgi-bin/mailman/listinfo/busybox