CPU user/kernel time given the PID
Dan Nelson
dnelson at allantgroup.com
Sun Mar 8 18:21:41 PDT 2009
In the last episode (Mar 08), Jay Loden said:
> Oliver Fromme wrote:
> > ps(1) and top(1) both use ki_pctcpu, see the getpcpu() function in
> > src/bin/ps/print.c and format_next_process() in
> > src/usr.bin/top/machine.c
>
> Hi Oliver, thanks for the reply. I noticed the same after some digging
> through the source code for ps and top. While CPU usage % is a useful
> number also, I was hoping to be able to get CPU time(s). Possibly that
> information simply isn't available on FreeBSD like it is for other OSes.
I was wondering why you were having so much trouble finding what you were
looking for, and then I realized I have a patch that I have never submitted
a PR for: the addition of "systime" and "usertime" ps keywords :) It simply
reads the rusage struct, and returns the same values that getrusage() does.
--
Dan Nelson
dnelson at allantgroup.com
-------------- next part --------------
Index: extern.h
===================================================================
RCS file: /home/ncvs/src/bin/ps/extern.h,v
retrieving revision 1.37
diff -u -p -r1.37 extern.h
--- extern.h 23 Jun 2004 23:48:09 -0000 1.37
+++ extern.h 7 Jan 2005 06:46:15 -0000
@@ -78,11 +78,13 @@ int s_uname(KINFO *);
void showkey(void);
void started(KINFO *, VARENT *);
void state(KINFO *, VARENT *);
+void systime(KINFO *, VARENT *);
void tdev(KINFO *, VARENT *);
void tname(KINFO *, VARENT *);
void ucomm(KINFO *, VARENT *);
void uname(KINFO *, VARENT *);
void upr(KINFO *, VARENT *);
+void usertime(KINFO *, VARENT *);
void vsize(KINFO *, VARENT *);
void wchan(KINFO *, VARENT *);
__END_DECLS
Index: keyword.c
===================================================================
RCS file: /home/ncvs/src/bin/ps/keyword.c,v
retrieving revision 1.76
diff -u -p -r1.76 keyword.c
--- keyword.c 6 Apr 2006 03:24:31 -0000 1.76
+++ keyword.c 2 Mar 2007 17:23:10 -0000
@@ -185,6 +185,7 @@ static VAR var[] = {
UINT, UIDFMT, 0},
{"svuid", "SVUID", NULL, 0, kvar, NULL, UIDLEN, KOFF(ki_svuid),
UINT, UIDFMT, 0},
+ {"systime", "SYSTIME", NULL, USER, systime, NULL, 9, 0, CHAR, NULL, 0},
{"tdev", "TDEV", NULL, 0, tdev, NULL, 4, 0, CHAR, NULL, 0},
{"time", "TIME", NULL, USER, cputime, NULL, 9, 0, CHAR, NULL, 0},
{"tpgid", "TPGID", NULL, 0, kvar, NULL, 4, KOFF(ki_tpgid), UINT,
@@ -203,6 +204,7 @@ static VAR var[] = {
"lx", 0},
{"user", "USER", NULL, LJUST|DSIZ, uname, s_uname, USERLEN, 0, CHAR,
NULL, 0},
+ {"usertime", "USERTIME", NULL, USER, usertime, NULL, 9, 0, CHAR, NULL, 0},
{"usrpri", "", "upr", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"vsize", "", "vsz", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"vsz", "VSZ", NULL, 0, vsize, NULL, 5, 0, CHAR, NULL, 0},
Index: print.c
===================================================================
RCS file: /home/ncvs/src/bin/ps/print.c,v
retrieving revision 1.95
diff -u -p -r1.95 print.c
--- print.c 17 Sep 2007 05:27:18 -0000 1.95
+++ print.c 11 Oct 2007 19:54:02 -0000
@@ -551,6 +551,79 @@ cputime(KINFO *k, VARENT *ve)
}
void
+systime(KINFO *k, VARENT *ve)
+{
+ VAR *v;
+ long secs;
+ long psecs; /* "parts" of a second. first micro, then centi */
+ char obuff[128];
+ static char decimal_point;
+
+ if (decimal_point == '\0')
+ decimal_point = localeconv()->decimal_point[0];
+ v = ve->var;
+ if (!k->ki_valid) {
+ secs = 0;
+ psecs = 0;
+ } else {
+ /*
+ * This counts time spent handling interrupts. We could
+ * fix this, but it is not 100% trivial (and interrupt
+ * time fractions only work on the sparc anyway). XXX
+ */
+ secs = k->ki_p->ki_rusage.ru_stime.tv_sec;
+ psecs = k->ki_p->ki_rusage.ru_stime.tv_usec;
+ if (sumrusage) {
+ secs += k->ki_p->ki_childstime.tv_sec;
+ psecs += k->ki_p->ki_childstime.tv_usec;
+ }
+ /*
+ * round and scale to 100's
+ */
+ psecs = (psecs + 5000) / 10000;
+ secs += psecs / 100;
+ psecs = psecs % 100;
+ }
+ (void)snprintf(obuff, sizeof(obuff), "%3ld:%02ld%c%02ld",
+ secs / 60, secs % 60, decimal_point, psecs);
+ (void)printf("%*s", v->width, obuff);
+}
+
+void
+usertime(KINFO *k, VARENT *ve)
+{
+ VAR *v;
+ long secs;
+ long psecs; /* "parts" of a second. first micro, then centi */
+ char obuff[128];
+ static char decimal_point;
+
+ if (decimal_point == '\0')
+ decimal_point = localeconv()->decimal_point[0];
+ v = ve->var;
+ if (!k->ki_valid) {
+ secs = 0;
+ psecs = 0;
+ } else {
+ secs = k->ki_p->ki_rusage.ru_utime.tv_sec;
+ psecs = k->ki_p->ki_rusage.ru_utime.tv_usec;
+ if (sumrusage) {
+ secs += k->ki_p->ki_childutime.tv_sec;
+ psecs += k->ki_p->ki_childutime.tv_usec;
+ }
+ /*
+ * round and scale to 100's
+ */
+ psecs = (psecs + 5000) / 10000;
+ secs += psecs / 100;
+ psecs = psecs % 100;
+ }
+ (void)snprintf(obuff, sizeof(obuff), "%3ld:%02ld%c%02ld",
+ secs / 60, secs % 60, decimal_point, psecs);
+ (void)printf("%*s", v->width, obuff);
+}
+
+void
elapsed(KINFO *k, VARENT *ve)
{
VAR *v;
Index: ps.1
===================================================================
RCS file: /home/ncvs/src/bin/ps/ps.1,v
retrieving revision 1.89
diff -u -p -r1.89 ps.1
--- ps.1 17 Sep 2006 17:40:06 -0000 1.89
+++ ps.1 2 Mar 2007 17:23:11 -0000
@@ -571,6 +571,8 @@ symbolic process state (alias
saved gid from a setgid executable
.It Cm svuid
saved UID from a setuid executable
+.It Cm systime
+accumulated system CPU time
.It Cm tdev
control terminal device number
.It Cm time
@@ -599,6 +601,8 @@ scheduling priority on return from syste
.Cm usrpri )
.It Cm user
user name (from UID)
+.It Cm usertime
+accumulated user CPU time
.It Cm vsz
virtual size in Kbytes (alias
.Cm vsize )
More information about the freebsd-hackers
mailing list