From af25453d9ad6f241e141025b9e5b26a4a5597967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20G=C3=B6rig?= Date: Thu, 16 Dec 2010 10:23:49 +0100 Subject: [PATCH] ps displays cgroup Author: Swann Perarnau Bug-Debian: http://bugs.debian.org/469669 Reviewed-by: Craig Small --- proc/readproc.c | 15 ++++++++++++++- proc/readproc.h | 4 +++- ps/display.c | 11 +++++++---- ps/output.c | 23 ++++++++++++++++++++++- ps/ps.1 | 4 ++++ 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/proc/readproc.c b/proc/readproc.c index 671d1e02..3e81c6ad 100644 --- a/proc/readproc.c +++ b/proc/readproc.c @@ -631,6 +631,17 @@ static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict cons p->environ = file2strvec(path, "environ"); else p->environ = NULL; + + if(linux_version_code>=LINUX_VERSION(2,6,24) && (flags & PROC_FILLCGROUP)) { + p->cgroup = file2strvec(path, "cgroup"); /* read /proc/#/cgroup */ + if(p->cgroup && *p->cgroup) { + int i = strlen(*p->cgroup); + if( (*p->cgroup)[i-1]=='\n' ) + (*p->cgroup)[i-1] = ' '; //little hack to remove trailing \n + } + } + else + p->cgroup = NULL; return p; next_proc: @@ -719,7 +730,7 @@ static proc_t* simple_readtask(PROCTAB *restrict const PT, const proc_t *restric t->cmdline = p->cmdline; // better not free these until done with all threads! t->environ = p->environ; #endif - + t->cgroup = p->cgroup; t->ppid = p->ppid; // ought to put the per-task ppid somewhere return t; @@ -929,6 +940,8 @@ void freeproc(proc_t* p) { free((void*)*p->cmdline); if (p->environ) free((void*)*p->environ); + if (p->cgroup) + free((void*)*p->cgroup); free(p); } diff --git a/proc/readproc.h b/proc/readproc.h index 4aab78ec..0b2c46a7 100644 --- a/proc/readproc.h +++ b/proc/readproc.h @@ -140,6 +140,7 @@ typedef struct proc_t { tpgid, // stat terminal process group id exit_signal, // stat might not be SIGCHLD processor; // stat current (or most recent?) CPU + char **cgroup; // cgroup current cgroup, looks like a classic filepath } proc_t; // PROCTAB: data structure holding the persistent information readproc needs @@ -237,8 +238,9 @@ extern proc_t * get_proc_stats(pid_t pid, proc_t *p); #define PROC_FILLSTAT 0x0040 // read stat -- currently unconditional #define PROC_FILLWCHAN 0x0080 // look up WCHAN name #define PROC_FILLARG 0x0100 // alloc and fill in `cmdline' +#define PROC_FILLCGROUP 0x0200 // alloc and fill in `cgroup` -#define PROC_LOOSE_TASKS 0x0200 // threat threads as if they were processes +#define PROC_LOOSE_TASKS 0x2000 // threat threads as if they were processes // Obsolete, consider only processes with one of the passed: #define PROC_PID 0x1000 // process id numbers ( 0 terminated) diff --git a/ps/display.c b/ps/display.c index 4574b9c8..3d6bbded 100644 --- a/ps/display.c +++ b/ps/display.c @@ -223,8 +223,7 @@ static unsigned task_format_needs; #define needs_for_format (proc_format_needs|task_format_needs) -#define PROC_ONLY_FLAGS (PROC_FILLENV|PROC_FILLARG|PROC_FILLCOM|PROC_FILLMEM) - +#define PROC_ONLY_FLAGS (PROC_FILLENV|PROC_FILLARG|PROC_FILLCOM|PROC_FILLMEM|PROC_FILLCGROUP) /***** munge lists and determine openproc() flags */ static void lists_and_needs(void){ check_headers(); @@ -342,6 +341,7 @@ static void simple_spew(void){ } if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse if(buf.environ) free((void*)*buf.environ); // ought to reuse + if(buf.cgroup) free((void*)*buf.cgroup); } break; case TF_show_proc|TF_loose_tasks: // H option @@ -354,6 +354,7 @@ static void simple_spew(void){ } if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse if(buf.environ) free((void*)*buf.environ); // ought to reuse + if(buf.cgroup) free((void*)*buf.cgroup); } break; case TF_show_proc|TF_show_task: // m and -m options @@ -366,7 +367,8 @@ static void simple_spew(void){ } if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse if(buf.environ) free((void*)*buf.environ); // ought to reuse - } + if(buf.cgroup) free((void*)*buf.cgroup); + } break; case TF_show_task: // -L and -T options while(readproc(ptp,&buf)){ @@ -377,7 +379,8 @@ static void simple_spew(void){ } if(buf.cmdline) free((void*)*buf.cmdline); // ought to reuse if(buf.environ) free((void*)*buf.environ); // ought to reuse - } + if(buf.cgroup) free((void*)*buf.cgroup); + } break; } closeproc(ptp); diff --git a/ps/output.c b/ps/output.c index adc558ac..b4905c2b 100644 --- a/ps/output.c +++ b/ps/output.c @@ -359,6 +359,26 @@ static int pr_args(char *restrict const outbuf, const proc_t *restrict const pp) return max_rightward-rightward; } +static int pr_cgroup(char *restrict const outbuf,const proc_t *restrict const pp) { + if(pp->cgroup && *pp->cgroup) { + char *endp = outbuf; + int rightward=max_rightward; + if(forest_prefix){ + int fh = forest_helper(outbuf); + endp += fh; + rightward -= fh; + } + if(rightward>1){ + *endp++ = ' '; + rightward--; + endp += escape_str(endp, *pp->cgroup, OUTBUF_SIZE, &rightward); + } + return max_rightward-rightward; + } + else + return pr_nop(outbuf,pp); +} + /* "ucomm" is the same thing: short unless -f */ static int pr_comm(char *restrict const outbuf, const proc_t *restrict const pp){ char *endp = outbuf; @@ -1257,7 +1277,7 @@ static int pr_t_left2(char *restrict const outbuf, const proc_t *restrict const #define GRP PROC_FILLGRP /* gid_t -> group names */ #define WCH PROC_FILLWCHAN /* do WCHAN lookup */ - +#define CGRP PROC_FILLCGROUP /* read cgroup */ /* TODO * pull out annoying BSD aliases into another table (to macro table?) * add sorting functions here (to unify names) @@ -1293,6 +1313,7 @@ static const format_struct format_array[] = { {"bsdtime", "TIME", pr_bsdtime, sr_nop, 6, 0, LNX, ET|RIGHT}, {"c", "C", pr_c, sr_pcpu, 2, 0, SUN, ET|RIGHT}, {"caught", "CAUGHT", pr_sigcatch, sr_nop, 9, 0, BSD, TO|SIGNAL}, /*sigcatch*/ +{"cgroup", "CGROUP", pr_cgroup, sr_nop, 27, CGRP, LNX, PO|UNLIMITED}, {"class", "CLS", pr_class, sr_sched, 3, 0, XXX, TO|LEFT}, {"cls", "CLS", pr_class, sr_sched, 3, 0, HPU, TO|RIGHT}, /*says HPUX or RT*/ {"cmaj_flt", "-", pr_nop, sr_cmaj_flt, 1, 0, LNX, AN|RIGHT}, diff --git a/ps/ps.1 b/ps/ps.1 index c0180dd3..715fb089 100644 --- a/ps/ps.1 +++ b/ps/ps.1 @@ -904,6 +904,10 @@ width of the field, a 32 or 64 bits mask in hexadecimal format is displayed. (alias\ \fBsig_catch\fR,\ \fBsigcatch\fR). T} +cgroup CGROUP T{ +display control groups to which the process belongs. +T} + class CLS T{ scheduling class of the process. (alias\ \fBpolicy\fR,\ \fBcls\fR). Field's possible values are: