Details of Specific Resource Limits

 

36.3 — Details of Specific Resource Limits
Introduction + Table 36-1: All 15 Resource Constants | EmbeddedPathashala
15
Resource Constants
6
SUSv3 Standard
9
Linux / BSD Only

Section 36.3 — What This Section Covers

Section 36.3 of TLPI is the main body of Chapter 36. It covers each of the 15 resource limit constants individually — what resource each one controls, what happens when a process exceeds its soft limit, what signals or errors are generated, and which kernel version introduced each limit.

Before diving into each limit one by one, it is worth having the complete picture in one place. This file gives you the Section 36.3 introduction and the full Table 36-1 so you can orient yourself before reading the per-limit detail pages.

Think of resource limits like budget allocations in a company. Each department (process) has a budget (resource limit). The soft limit is the normal operating budget — go over it and you get a warning (a signal). The hard limit is the absolute ceiling — the CFO (kernel) terminates you if you go past it.

How Limits Get Set in Practice

There are three ways a process can have resource limits:

1. Shell — ulimit

In bash: ulimit -n 1024 sets RLIMIT_NOFILE. In C shell: limit. These limits are inherited by all child processes the shell spawns. This is the most common way to set limits for interactive users.

2. /proc/PID/limits

Since kernel 2.6.24, every process has a readable file at /proc/PID/limits showing all its current soft and hard limits. Owned by the real UID of the process; only that user (or root) can read it.

3. setrlimit() in Code

A process can call setrlimit() to change its own limits programmatically. Common in daemons, servers, or sandboxing tools that want to restrict a child process before exec()ing it.

Note on units: The shell commands (ulimit, limit) often use different units from getrlimit()/setrlimit(). For example, the shell typically expresses memory segment limits in kilobytes, while the system calls work in bytes. Always check which unit a tool is using.

Table 36-1: All 15 Resource Limit Constants

Constant Limits Unit Origin On Breach Detail Page
RLIMIT_AS Virtual address space size bytes SUSv3 ENOMEM on brk/mmap/shmat → RLIMIT_AS
RLIMIT_CORE Core dump file size bytes SUSv3 Core file truncated at limit → RLIMIT_CORE
RLIMIT_CPU CPU time seconds SUSv3 SIGXCPU (soft) → SIGKILL (hard) → RLIMIT_CPU
RLIMIT_DATA Data segment (.data + .bss + heap) bytes SUSv3 ENOMEM on sbrk/brk → RLIMIT_DATA
RLIMIT_FSIZE Maximum file size creatable bytes SUSv3 SIGXFSZ + EFBIG on write/truncate → RLIMIT_FSIZE
RLIMIT_MEMLOCK Locked (non-swappable) memory bytes BSD / Linux ENOMEM on mlock/mlockall → RLIMIT_MEMLOCK
RLIMIT_MSGQUEUE POSIX MQ bytes (per real UID) bytes Linux 2.6.8+ ENOMEM on mq_open → RLIMIT_MSGQUEUE
RLIMIT_NICE Nice value ceiling (20 − rlim_cur) value Linux 2.6.12+ EPERM on setpriority/nice → RLIMIT_NICE
RLIMIT_NOFILE Max file descriptor number + 1 count SUSv3 EMFILE on open/socket/dup → RLIMIT_NOFILE
RLIMIT_NPROC Process count for real UID count BSD / Linux EAGAIN on fork/vfork/clone → RLIMIT_NPROC
RLIMIT_RSS Resident set size (not enforced) pages BSD (no-op) No effect on modern Linux → RLIMIT_RSS
RLIMIT_RTPRIO Realtime scheduling priority ceiling priority Linux 2.6.12+ EPERM on sched_setscheduler → RLIMIT_RTPRIO
RLIMIT_RTTIME Realtime CPU time without sleeping microseconds Linux 2.6.25+ SIGXCPU → SIGKILL → RLIMIT_RTTIME
RLIMIT_SIGPENDING Queued signals for real UID count Linux 2.6.8+ EAGAIN on sigqueue() → RLIMIT_SIGPENDING
RLIMIT_STACK Stack segment size bytes SUSv3 SIGSEGV on stack overflow → RLIMIT_STACK

Grouping the Limits by Category

Memory Limits
RLIMIT_AS — virtual address space RLIMIT_DATA — heap + data segments RLIMIT_STACK — stack segment RLIMIT_MEMLOCK — locked memory RLIMIT_RSS — resident set (no-op)
CPU / Scheduling Limits
RLIMIT_CPU — CPU seconds RLIMIT_NICE — nice value ceiling RLIMIT_RTPRIO — RT priority ceiling RLIMIT_RTTIME — RT CPU microseconds
File / I/O Limits
RLIMIT_FSIZE — max file size RLIMIT_CORE — core dump size RLIMIT_NOFILE — max open FDs
Process / IPC Limits
RLIMIT_NPROC — process count RLIMIT_SIGPENDING — signal queue RLIMIT_MSGQUEUE — POSIX MQ bytes

What Happens When a Limit Is Exceeded?

The behaviour when a process exceeds a soft limit depends on the resource type. There are three patterns:

🚨
Signal + Error (most aggressive) — used by RLIMIT_CPU and RLIMIT_FSIZE
The process receives a signal (SIGXCPU or SIGXFSZ) AND the system call returns an error (SIGKILL eventually for RLIMIT_CPU). The signal gives the process a chance to clean up before being killed.
⚠️
Error only — syscall fails — used by RLIMIT_AS, RLIMIT_DATA, RLIMIT_NOFILE, RLIMIT_NPROC, RLIMIT_MEMLOCK, RLIMIT_MSGQUEUE, RLIMIT_SIGPENDING
The system call that would exceed the limit simply fails with an appropriate errno (ENOMEM, EMFILE, EAGAIN, etc.). No signal is sent.
🛑
Signal only — stack overflow → SIGSEGV — used by RLIMIT_STACK
Growing the stack beyond the limit generates a SIGSEGV. Since the stack itself is exhausted, you need an alternate signal stack to catch it at all.

Code Example — Checking All Resource Limits

This helper loops through all 15 constants and prints their current soft and hard limits. Useful as a diagnostic tool:

#include <stdio.h>
#include <sys/resource.h>

static void print_limit(const char *name, int resource)
{
    struct rlimit rl;
    if (getrlimit(resource, &rl) == -1) {
        perror(name);
        return;
    }

    printf("%-22s soft=", name);
    if (rl.rlim_cur == RLIM_INFINITY)
        printf("unlimited");
    else
        printf("%lld", (long long)rl.rlim_cur);

    printf("  hard=");
    if (rl.rlim_max == RLIM_INFINITY)
        printf("unlimited\n");
    else
        printf("%lld\n", (long long)rl.rlim_max);
}

int main(void)
{
    printf("Resource Limit Summary\n");
    printf("======================\n");
    print_limit("RLIMIT_AS",          RLIMIT_AS);
    print_limit("RLIMIT_CORE",        RLIMIT_CORE);
    print_limit("RLIMIT_CPU",         RLIMIT_CPU);
    print_limit("RLIMIT_DATA",        RLIMIT_DATA);
    print_limit("RLIMIT_FSIZE",       RLIMIT_FSIZE);
    print_limit("RLIMIT_MEMLOCK",     RLIMIT_MEMLOCK);
    print_limit("RLIMIT_MSGQUEUE",    RLIMIT_MSGQUEUE);
    print_limit("RLIMIT_NICE",        RLIMIT_NICE);
    print_limit("RLIMIT_NOFILE",      RLIMIT_NOFILE);
    print_limit("RLIMIT_NPROC",       RLIMIT_NPROC);
    print_limit("RLIMIT_RSS",         RLIMIT_RSS);
    print_limit("RLIMIT_RTPRIO",      RLIMIT_RTPRIO);
    print_limit("RLIMIT_RTTIME",      RLIMIT_RTTIME);
    print_limit("RLIMIT_SIGPENDING",  RLIMIT_SIGPENDING);
    print_limit("RLIMIT_STACK",       RLIMIT_STACK);
    return 0;
}

/* Compare against: ulimit -a (bash) or cat /proc/self/limits */

Interview Questions

Q1. How many resource limit constants does Linux define, and where is the full list documented?

Linux defines 15 resource limit constants as of kernel 2.6.25 (when RLIMIT_RTTIME was added). They are listed in Table 36-1 of TLPI and fully documented in the getrlimit(2) man page. The header <sys/resource.h> defines all the RLIMIT_* constants.

Q2. Which resource limits are standardized by SUSv3 (POSIX)?

Six of the 15 limits are in SUSv3: RLIMIT_AS, RLIMIT_CORE, RLIMIT_CPU, RLIMIT_DATA, RLIMIT_FSIZE, RLIMIT_NOFILE, and RLIMIT_STACK. The rest are Linux-specific or BSD-derived extensions.

Q3. Since which kernel version can you read all resource limits of a process without code?

Since kernel 2.6.24, the file /proc/PID/limits displays all soft and hard resource limits of any process. This file is readable by the process’s real user ID or by root. The equivalent shell command is ulimit -a for your own shell’s limits.

Q4. Why do shell commands like ulimit use different units from getrlimit()?

Historical convention. Shell commands typically display memory limits in kilobytes for human readability, while the kernel system calls work in bytes for precision. For example, ulimit -s shows stack size in KB, but RLIMIT_STACK via getrlimit() returns bytes. Always verify which unit a tool uses before interpreting values.

Q5. Which resource limit is present in the kernel but has absolutely no effect on modern Linux?

RLIMIT_RSS — the resident set size limit. It was inherited from BSD but has never been enforced by the Linux kernel. Processes can set it, and getrlimit() will return it, but the kernel never actually limits the process’s physical memory based on this value.

Q6. What are three different ways a process can receive or set its resource limits?

First, through the shell using ulimit (bash/ksh) or limit (csh) before running a program — these limits are inherited. Second, programmatically using setrlimit() to change the process’s own limits at runtime. Third, by reading /proc/PID/limits to inspect any process’s current limits (since kernel 2.6.24).

Leave a Reply

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