Each process consumes system resources such as memory and CPU time. This chapter looks at resource-related system calls. We begin with the getrusage() system call, which allows a process to monitor the resources that it has used or that its children have used. We then look at the setrlimit() and getrlimit() system calls, which can be used to change and retrieve limits on the calling process’s consumption of various resources.
The getrusage() system call retrieves statistics about various system resources used by the calling process or by all of its children.
#include <sys/resource.h>
int getrusage
(int who, struct rusage *res_usage);
Returns 0 on success, or -1 on error
The who argument specifies the process(es) for which resource usage information is to be retrieved. It has one of the following values:
RUSAGE_SELF
Return information about the calling process.
RUSAGE_CHILDREN
Return information about all children of the calling process that have terminated and been waited for.
RUSAGE_THREAD
(since Linux 2.6.26)Return information about the calling thread. This value is Linux-specific.
The res_usage argument is a pointer to a structure of type rusage, defined as shown in Example 36-1.
Example 36-1. Definition of the rusage structure
struct rusage { struct timeval ru_utime; /* User CPU time used */ struct timeval ru_stime; /* System CPU time used */ long ru_maxrss; /* Maximum size of resident set (kilobytes) [used since Linux 2.6.32] */ long ru_ixrss; /* Integral (shared) text memory size (kilobyte-seconds) [unused] */ long ru_idrss; /* Integral (unshared) data memory used (kilobyte-seconds) [unused] */ long ru_isrss; /* Integral (unshared) stack memory used (kilobyte-seconds) [unused] */ long ru_minflt; /* Soft page faults (I/O not required) */ long ru_majflt; /* Hard page faults (I/O required) */ long ru_nswap; /* Swaps out of physical memory [unused] */ long ru_inblock; /* Block input operations via file system [used since Linux 2.6.22] */ long ru_oublock; /* Block output operations via file system [used since Linux 2.6.22] */ long ru_msgsnd; /* IPC messages sent [unused] */ long ru_msgrcv; /* IPC messages received [unused] */ long ru_nsignals; /* Signals received [unused] */ long ru_nvcsw; /* Voluntary context switches (process relinquished CPU before its time slice expired) [used since Linux 2.6] */ long ru_nivcsw; /* Involuntary context switches (higher priority process became runnable or time slice ran out) [used since Linux 2.6] */ };
As indicated in the comments in Example 36-1, on Linux, many of the fields in the rusage structure are not filled in by getrusage() (or wait3() and wait4()), or they are filled in only by more recent kernel versions. Some of the fields that are unused on Linux are used on other UNIX implementations. These fields are provided on Linux so that, if they are implemented at a future date, the rusage structure does not need to undergo a change that would break existing application binaries.
Although getrusage() appears on most UNIX implementations, it is only weakly specified in SUSv3 (which specifies only the fields ru_utime and ru_stime). In part, this is because the meaning of much of the information in the rusage structure is implementation-dependent.
The ru_utime and ru_stime fields are structures of type timeval (Calendar Time), which return the number of seconds and microseconds of CPU time consumed by a process in user mode and kernel mode, respectively. (Similar information is retrieved by the times() system call described in Section 10.7.)
The Linux-specific /proc/
PID/stat
files expose some resource usage information (CPU time and page faults) about all processes on the system. See the proc(5) manual page for further details.
The rusage structure returned by the getrusage() RUSAGE_CHILDREN
operation includes the resource usage statistics of all of the descendants of the calling process. For example, if we have three processes related as parent, child, and grandchild, then, when the child does a wait() on the grandchild, the resource usage values of the grandchild are added to the child’s RUSAGE_CHILDREN
values; when the parent performs a wait() for the child, the resource usage values of both the child and the grandchild are added to the parent’s RUSAGE_CHILDREN
values. Conversely, if the child does not wait() on the grandchild, then the grandchild’s resource usages are not recorded in the RUSAGE_CHILDREN
values of the parent.
For the RUSAGE_CHILDREN
operation, the ru_maxrss field returns the maximum resident set size among all of the descendants of the calling process (rather than a sum for all descendants).
SUSv3 specifies that if SIGCHLD
is being ignored (so that children are not turned into zombies that can be waited on), then the child statistics should not be added to the values returned by RUSAGE_CHILDREN
. However, as noted in Ignoring Dead Child Processes, in kernels before 2.6.9, Linux deviates from this requirement—if SIGCHLD
is ignored, then the resource usage values for dead children are included in the values returned for RUSAGE_CHILDREN
.