The Two System Calls
getrlimit() reads the current soft and hard limits for a named resource. setrlimit() modifies them. Both live in <sys/resource.h> and return 0 on success or -1 on error.
Function Signatures
#include <sys/resource.h>
int getrlimit(int resource, struct rlimit *rlim);
int setrlimit(int resource, const struct rlimit *rlim);
/* Both return 0 on success, -1 on error (errno set) */
The resource argument is a constant naming which resource you are querying or changing — e.g. RLIMIT_CPU, RLIMIT_NOFILE, RLIMIT_STACK. The rlim pointer is an output for getrlimit() and an input for setrlimit().
struct rlimit — Two Fields
struct rlimit {
rlim_t rlim_cur; /* Soft limit — the actual enforced limit */
rlim_t rlim_max; /* Hard limit — ceiling for rlim_cur */
};
Every resource has exactly two numbers associated with it: a soft limit and a hard limit. Both are rlim_t (an integer type).
The kernel enforces this value at runtime. Think of it as the speed-limit sign — it is what is actively checked. A process can adjust the soft limit anywhere between 0 and the hard limit.
A ceiling that governs how high the soft limit can be raised. An unprivileged process can lower the hard limit (irreversibly), but cannot raise it. Only a privileged process (CAP_SYS_RESOURCE) can raise the hard limit.
RLIM_INFINITY — No Limit
When rlim_cur or rlim_max equals the constant RLIM_INFINITY, that component has no cap. getrlimit() returns RLIM_INFINITY for unlimited resources. setrlimit() accepts it to remove a limit (if privileged enough).
struct rlimit rl;
getrlimit(RLIMIT_AS, &rl);
if (rl.rlim_cur == RLIM_INFINITY)
printf("No virtual memory limit\n");
else
printf("VM soft limit: %lld bytes\n", (long long)rl.rlim_cur);
The rlim_t Data Type & Safe Printing
rlim_t is defined to be the same size as off_t. On 64-bit Linux this is 64 bits. On 32-bit with _FILE_OFFSET_BITS=64, the C library uses a 64-bit rlim_t but the kernel internally uses a 32-bit unsigned long. This mismatch can cause problems (covered in 36.2d).
Always cast to long long when printing:
printf("%lld", (long long)rl.rlim_cur); /* Correct — handles all architectures */
printf("%ld", rl.rlim_cur); /* WRONG — can truncate on 32-bit */
Code Example — getrlimit and setrlimit Together
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
int main(void)
{
struct rlimit rl;
/* 1. Read current RLIMIT_NOFILE limit */
if (getrlimit(RLIMIT_NOFILE, &rl) == -1) {
perror("getrlimit"); exit(1);
}
printf("Before change:\n");
printf(" Soft (enforced): %lld\n", (long long)rl.rlim_cur);
printf(" Hard (ceiling) : ");
if (rl.rlim_max == RLIM_INFINITY) printf("unlimited\n");
else printf("%lld\n", (long long)rl.rlim_max);
/* 2. Raise the soft limit to 2048 (if hard limit allows) */
if (rl.rlim_max == RLIM_INFINITY || rl.rlim_max >= 2048) {
rl.rlim_cur = 2048;
if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
perror("setrlimit"); exit(1);
}
printf("Soft limit raised to 2048\n");
}
/* 3. Verify */
getrlimit(RLIMIT_NOFILE, &rl);
printf("After change:\n");
printf(" Soft (enforced): %lld\n", (long long)rl.rlim_cur);
return 0;
}
/* Compile: gcc -o rl_api rl_api.c */
Interview Questions
rlim_cur is the soft limit — the kernel checks this at runtime. rlim_max is the hard limit — the ceiling for rlim_cur. The kernel enforces the soft limit; the hard limit only constrains how high the soft limit can be raised.
When rlim_cur or rlim_max equals RLIM_INFINITY, that component of the limit is uncapped — no limit is enforced or ceiling applied for that resource. It can be returned by getrlimit() and passed to setrlimit() (subject to privilege).
rlim_t is defined to be the same size as off_t, which can be 32 or 64 bits depending on the architecture and compilation flags. Using %lld with a (long long) cast is the safe approach that handles all sizes correctly across architectures.
The most common reason is EINVAL — the resource argument is not a recognised resource constant. EFAULT indicates a bad pointer for the rlim argument. In practice, getrlimit() rarely fails if you pass a valid resource constant and a valid pointer.
