I recently had to work on functionality to look through /proc/<pid> for information about processes, which would have entailed an annoying amount of file schlepping and string parsing. Fortunately there is procps, a very nice library to makes /proc access work very much like directory access via opendir(). It normalizes the procfs implementations of a number of OSes like Linux and Solaris, so you work with a common data structure and don't have to maintain a bunch of parsing code. However it doesn't abstract /proc very much: you still need to know what it is and what information is in each /proc file to make good use of the facility.
You start with a call to openproc(), which creates a PROCTAB* structure to iterate through running processes.
#include <proc/readproc.h> int main(int argc, char** argv) { PROCTAB* proc = openproc(PROC_FILLMEM | PROC_FILLSTAT | PROC_FILLSTATUS);
A flag argument to openproc() tell it what kind of information you want. The library will skip processing files in /proc if it can.
PROC_FILLMEM | read /proc/<pid>/statm |
PROC_FILLCOM | allocate and populate `cmdline' |
PROC_FILLENV | allocate and populate `environ' |
PROC_FILLUSR | look up user id number, fill in user name |
PROC_FILLGRP | look up group id number, fill in group name |
PROC_FILLSTATUS | read /proc/<pid>/status |
PROC_FILLSTAT | read /proc/<pid>/status |
PROC_FILLWCHAN | read function name from /proc/<pid>/statm |
PROC_FILLARG | handled identically to PROC_FILLCOM |
The PROCTAB is repeatedly passed to readproc(), which populates a proc_t for each running process.
proc_t proc_info; memset(&proc_info, 0, sizeof(proc_info)); while (readproc(proc, &proc_info) != NULL) { printf("%20s:\t%5ld\t%5lld\t%5lld\n", proc_info.cmd, proc_info.resident, proc_info.utime, proc_info.stime); }
When done, call closeproc() to release resources.
closeproc(proc);
Some sample output from my system:
process: pages utime stime xinetd: 139 1 0 sshd: 866 10 21 bash: 1377 28 16 ssh-agent: 208 11 3 portmap: 158 1 4 rpc.statd: 208 1 0
proc_t
The proc_t contains a great deal of information about the process.
typedef struct proc_t { int tid, // (special) task id, the POSIX thread ID (see also: tgid) ppid; // stat,status pid of parent process unsigned long long utime, // stat user-mode CPU time accumulated by process stime, // stat kernel-mode CPU time accumulated by process cutime, // stat cumulative utime of process and reaped children cstime, // stat cumulative stime of process and reaped children start_time; // stat start time of process -- seconds since 1-1-70 long priority, // stat kernel scheduling priority nice, // stat standard unix nice level of process rss, // stat resident set size from /proc/#/stat (pages) ...etc...
The proc_t also contains this maddening little member variable:
unsigned pcpu; // stat %CPU usage (is not filled in by readproc)
Instantaneous CPU percentage is commonly desired, but is not tracked by the kernel and is therefore not available anywhere procps can read. Tracking a percentage has to be implemented in the application by taking a snapshot, waiting a little while, and taking another snapshot to learn the utime+stime spent during the interval. This is the reason why top shows all CPU percentages as 0.0% when it starts, and corrects them on the next interval. procps provides a convenient place to store the CPU percentage, but does not implement it in the library.