API Details, struct rlimit, rlim_t & RLIM_INFINITY

 

36.2a — getrlimit() & setrlimit()
API Details, struct rlimit, rlim_t & RLIM_INFINITY | EmbeddedPathashala

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).

rlim_cur — Soft Limit

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.

rlim_max — 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

Q1. What are rlim_cur and rlim_max, and which one does the kernel check?

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.

Q2. What does RLIM_INFINITY mean?

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).

Q3. Why must you cast rlim_t to long long before printf?

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.

Q4. If getrlimit() fails, what is a typical reason?

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.

Leave a Reply

Your email address will not be published. Required fields are marked *