RLIMIT_NOFILE Max File Descriptors: EMFILE, NR_OPEN, nr_open, file-max

 

36.3 — RLIMIT_NOFILE
Max File Descriptors: EMFILE, NR_OPEN, nr_open, file-max | EmbeddedPathashala

What is RLIMIT_NOFILE?

RLIMIT_NOFILE specifies a number one greater than the maximum file descriptor number a process may allocate. If the limit is 1024, then file descriptors 0 through 1023 are allowed — descriptor 1024 would not be allocated. This is one of the most commonly hit limits in network servers, BLE daemons, and any application that handles many simultaneous connections.

What Fails When the Limit Is Hit

Any call that allocates a new file descriptor fails when it would assign a descriptor number equal to or greater than RLIMIT_NOFILE:

System Call Error When Limit Hit
open(), pipe(), socket(), accept(), shm_open(), epoll_create() EMFILE
dup2(fd, newfd) — newfd ≥ limit EBADF
fcntl(fd, F_DUPFD, newfd) — newfd ≥ limit EINVAL

Changes to RLIMIT_NOFILE are also reflected in sysconf(_SC_OPEN_MAX) on Linux — this function queries the current soft RLIMIT_NOFILE value.

Three Layers of File Descriptor Limits on Linux

Linux has three separate limits on file descriptors, operating at different scopes:

1. RLIMIT_NOFILE — Per-process limit
The per-process maximum descriptor number + 1. Default typically 1024 (soft) / 4096 (hard) on most Linux distributions. Raise with setrlimit() or ulimit -n.
2. /proc/sys/fs/nr_open — Per-process kernel ceiling (Linux 2.6.25+)
The maximum value RLIMIT_NOFILE can be raised to. Default 1,048,576. Can be changed by root. Before 2.6.25, this was a hard-coded constant NR_OPEN (also 1,048,576). Attempting to set RLIMIT_NOFILE above nr_open fails with EPERM.
3. /proc/sys/fs/file-max — System-wide limit
Maximum number of open file descriptions across all processes on the system. Only privileged (CAP_SYS_ADMIN) processes can exceed this. An unprivileged process whose call hits the system-wide file-max gets ENFILE (not EMFILE).

Code Example — Raising RLIMIT_NOFILE for a High-FD Server

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

/* Raise RLIMIT_NOFILE to its maximum allowed value */
int maximize_open_files(void)
{
    struct rlimit rl;

    /* Read current limits */
    if (getrlimit(RLIMIT_NOFILE, &rl) == -1) {
        perror("getrlimit"); return -1;
    }
    printf("Current: soft=%lld hard=%lld\n",
           (long long)rl.rlim_cur, (long long)rl.rlim_max);

    /* Raise soft limit to match hard limit */
    if (rl.rlim_cur < rl.rlim_max) {
        rl.rlim_cur = rl.rlim_max;   /* or RLIM_INFINITY if hard is infinite */
        if (setrlimit(RLIMIT_NOFILE, &rl) == -1) {
            if (errno == EPERM) {
                /* Hard limit already at ceiling; use current soft */
                getrlimit(RLIMIT_NOFILE, &rl);
                printf("Cannot raise; using soft=%lld\n",
                       (long long)rl.rlim_cur);
                return 0;
            }
            perror("setrlimit"); return -1;
        }
    }
    getrlimit(RLIMIT_NOFILE, &rl);
    printf("After raise: soft=%lld hard=%lld\n",
           (long long)rl.rlim_cur, (long long)rl.rlim_max);
    return 0;
}

int main(void)
{
    maximize_open_files();

    /* Check what sysconf says (reflects the soft RLIMIT_NOFILE) */
    printf("sysconf(_SC_OPEN_MAX) = %ld\n", sysconf(_SC_OPEN_MAX));

    /* Check how many FDs this process currently has open */
    printf("Check /proc/self/fd to see open descriptors:\n");
    system("ls /proc/self/fd | wc -l");

    return 0;
}
/* Compile: gcc -o nofile_demo nofile_demo.c
   For servers: call maximize_open_files() at startup.
   For root: you can also set rl.rlim_cur = rl.rlim_max = 65536 etc. */

Interview Questions

Q1. RLIMIT_NOFILE is “one greater than the maximum FD number” — what does this mean in practice?

If RLIMIT_NOFILE is 1024, then the maximum valid file descriptor number is 1023 (because FDs start at 0). The kernel will not allocate FD 1024 or above. The “plus one” convention makes it easy to use the value as a loop bound: for (fd = 0; fd < (int)rl.rlim_cur; fd++).

Q2. What is the difference between EMFILE and ENFILE?

EMFILE (Too many open files) is returned when a process-level limit is hit — the process has used all its allowed file descriptors (RLIMIT_NOFILE). ENFILE (File table overflow) is returned when the system-wide limit is hit — the total number of open file descriptions across all processes has reached the kernel’s file-max limit.

Q3. How do you check how many file descriptors a process currently has open on Linux?

Read the /proc/PID/fd directory — it contains a symbolic link for each open file descriptor. Count the entries: ls /proc/self/fd | wc -l. You can also use ls -la /proc/self/fd to see where each descriptor points.

Q4. What is /proc/sys/fs/nr_open and how does it relate to RLIMIT_NOFILE?

nr_open is the kernel ceiling on the maximum value that RLIMIT_NOFILE can be set to (since Linux 2.6.25). Default is 1,048,576. If you try to set RLIMIT_NOFILE higher than nr_open, setrlimit() fails with EPERM. Root can raise nr_open itself to allow higher RLIMIT_NOFILE values.

Leave a Reply

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