Part 1 — Resource Usage Monitoring (getrusage)
The getrusage() system call lets a process read the resource statistics the kernel has accumulated for it. The who argument selects the target: RUSAGE_SELF for the calling process, RUSAGE_CHILDREN for terminated-and-waited-for descendants, or RUSAGE_THREAD for the calling thread (Linux 2.6.26+, non-portable).
The returned struct rusage has 17 fields. On Linux, 9 are actually populated: ru_utime and ru_stime (CPU time in user and kernel mode), ru_maxrss (peak resident set size, since 2.6.32), ru_minflt and ru_majflt (minor and major page faults), ru_inblock and ru_oublock (block I/O ops, since 2.6.22), and ru_nvcsw and ru_nivcsw (voluntary and involuntary context switches, since 2.6).
RUSAGE_CHILDREN stats are only transferred to the parent when the parent calls wait(). If a child does not wait for its own grandchildren before the parent waits for the child, the grandchild’s stats are permanently lost. For RUSAGE_CHILDREN, ru_maxrss gives the peak RSS across all descendants (maximum, not sum).
Part 2 — Resource Limits (getrlimit / setrlimit)
The getrlimit() and setrlimit() system calls read and modify process resource limits. Each resource has two values in a struct rlimit:
- rlim_cur (soft limit) — what the kernel enforces at runtime
- rlim_max (hard limit) — the ceiling for rlim_cur
Privilege rules: An unprivileged process can raise the soft limit up to the hard limit, and can lower the hard limit (irreversibly). Only a privileged process (CAP_SYS_RESOURCE) can raise the hard limit. Both limits are inherited by child processes via fork() and preserved across exec().
RLIM_INFINITY in either field means no limit. The value RLIM_SAVED_CUR/MAX indicates an unrepresentable limit on 32-bit systems with large-file compilation. Always print rlim_t values by casting to long long and using %lld.
