Kernel Filesystem Interface & Resource Limits /proc/sysvipc & IPC Limits

 

/proc/sysvipc & IPC Limits
Chapter 45, Sections 45.7–45.8 | Kernel Filesystem Interface & Resource Limits
/proc/sysvipc
Kernel IPC files
/proc/sys/kernel
Limit controls
All objects
No permission filter
Key Terms
/proc/sysvipc/msg /proc/sysvipc/sem /proc/sysvipc/shm /proc/sys/kernel/msgmni SEMMNI SHMMNI MSGMNI sysctl

The /proc/sysvipc Directory

Linux provides a non-standard but powerful method to list all System V IPC objects on the system: three read-only files in the /proc/sysvipc/ directory.

Unlike ipcs, these files show all objects of the corresponding type — regardless of whether you have read permission on them. This makes them more comprehensive for system monitoring.

The Three /proc/sysvipc Files
/proc/sysvipc — Three Virtual Files
/proc/sysvipc/msg
Lists all message queues with their attributes: key, msqid, perms, cbytes, qnum, lspid, lrpid, uid, gid, cuid, cgid, stime, rtime, ctime
/proc/sysvipc/sem
Lists all semaphore sets: key, semid, perms, nsems, uid, gid, cuid, cgid, otime, ctime
/proc/sysvipc/shm
Lists all shared memory segments: key, shmid, perms, size, cpid, lpid, nattch, uid, gid, cuid, cgid, atime, dtime, ctime

Sample /proc/sysvipc/sem Output
$ cat /proc/sysvipc/sem
key         semid  perms  nsems uid  gid  cuid cgid  otime      ctime
0 16646144 600    4     1000 100  1000 100   0          1010166460
Key difference vs ipcs: ipcs filters by read permission. /proc/sysvipc files show all objects unconditionally. This makes them more useful for root-level system monitoring and scripting.

Coding Example 1 — Parsing /proc/sysvipc/sem in C
/* read_proc_sysvipc.c — parse /proc/sysvipc/sem to list all semaphore sets */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct sem_entry {
    int key;
    int semid;
    int perms;
    int nsems;
    int uid;
    int gid;
};

int main(void) {
    FILE *f = fopen("/proc/sysvipc/sem", "r");
    if (!f) {
        perror("/proc/sysvipc/sem");
        exit(EXIT_FAILURE);
    }

    char line[512];
    int count = 0;

    printf("=== All Semaphore Sets on This System ===\n");
    printf("%-12s %-10s %-8s %-6s %-6s %-6s\n",
           "Key", "SemID", "Perms", "NSems", "UID", "GID");
    printf("%-12s %-10s %-8s %-6s %-6s %-6s\n",
           "----------", "--------", "------", "-----", "-----", "-----");

    /* Skip the header line */
    fgets(line, sizeof(line), f);

    struct sem_entry e;
    /* Fields: key semid perms nsems uid gid cuid cgid otime ctime */
    while (fscanf(f, "%d %d %d %d %d %d %*d %*d %*d %*d",
                  &e.key, &e.semid, &e.perms, &e.nsems, &e.uid, &e.gid) == 6) {
        printf("0x%-10x %-10d 0%-7o %-6d %-6d %-6d\n",
               e.key, e.semid, e.perms, e.nsems, e.uid, e.gid);
        count++;
    }

    if (count == 0)
        printf("(no semaphore sets found)\n");
    else
        printf("\nTotal: %d semaphore set(s)\n", count);

    fclose(f);
    return 0;
}

45.8 — IPC Limits

Because IPC objects consume kernel resources (memory, entries in kernel tables), Linux places limits on how many objects of each type can exist. These limits prevent resource exhaustion.

The limits are viewed and modified via files under /proc/sys/kernel/. They can also be changed temporarily using sysctl or permanently in /etc/sysctl.conf.

IPC Limits — /proc/sys/kernel Files
File Controls Meaning
/proc/sys/kernel/msgmni MSGMNI Max number of message queues system-wide
/proc/sys/kernel/msgmax MSGMAX Max size of a single message (bytes)
/proc/sys/kernel/msgmnb MSGMNB Max total bytes in a single message queue
/proc/sys/kernel/sem SEMMSL SEMMNS SEMOPM SEMMNI Four semaphore limits (one file, four values)
/proc/sys/kernel/shmmni SHMMNI Max number of shared memory segments
/proc/sys/kernel/shmmax SHMMAX Max size of a single shared memory segment
/proc/sys/kernel/shmall SHMALL Max total pages of shared memory system-wide

The Semaphore Limits File: /proc/sys/kernel/sem

The semaphore limits file contains four space-separated values in this order:

$ cat /proc/sys/kernel/sem
32000   1024000000   500   32000
SEMMSL  SEMMNS       SEMOPM SEMMNI
Name Description
SEMMSL Max semaphores per semaphore set (array)
SEMMNS Max semaphores across all sets system-wide
SEMOPM Max number of operations per semop() call
SEMMNI Max number of semaphore sets (identifiers)

Coding Example 2 — Display All IPC Limits
/* ipc_limits.c — display current System V IPC limits */
#include <stdio.h>
#include <stdlib.h>

void read_int_limit(const char *path, const char *name) {
    FILE *f = fopen(path, "r");
    if (!f) { printf("  %-30s: (cannot read)\n", name); return; }
    int val;
    fscanf(f, "%d", &val);
    printf("  %-30s: %d\n", name, val);
    fclose(f);
}

void read_long_limit(const char *path, const char *name) {
    FILE *f = fopen(path, "r");
    if (!f) { printf("  %-30s: (cannot read)\n", name); return; }
    long val;
    fscanf(f, "%ld", &val);
    printf("  %-30s: %ld\n", name, val);
    fclose(f);
}

int main(void) {
    printf("=== System V IPC Limits ===\n\n");

    printf("Message Queue Limits:\n");
    read_int_limit("/proc/sys/kernel/msgmni", "MSGMNI (max queues)");
    read_int_limit("/proc/sys/kernel/msgmax", "MSGMAX (max msg size, bytes)");
    read_int_limit("/proc/sys/kernel/msgmnb", "MSGMNB (max queue capacity, bytes)");

    printf("\nSemaphore Limits (from /proc/sys/kernel/sem):\n");
    FILE *f = fopen("/proc/sys/kernel/sem", "r");
    if (f) {
        int semmsl, semmns, semopm, semmni;
        fscanf(f, "%d %d %d %d", &semmsl, &semmns, &semopm, &semmni);
        printf("  %-30s: %d\n", "SEMMSL (max sems per set)", semmsl);
        printf("  %-30s: %d\n", "SEMMNS (max sems system-wide)", semmns);
        printf("  %-30s: %d\n", "SEMOPM (max ops per semop())", semopm);
        printf("  %-30s: %d\n", "SEMMNI (max sem sets)", semmni);
        fclose(f);
    }

    printf("\nShared Memory Limits:\n");
    read_int_limit("/proc/sys/kernel/shmmni",  "SHMMNI (max segments)");
    read_long_limit("/proc/sys/kernel/shmmax", "SHMMAX (max segment size, bytes)");
    read_long_limit("/proc/sys/kernel/shmall", "SHMALL (max total pages)");

    return 0;
}

Coding Example 3 — Changing IPC Limits (sysctl)

You can temporarily change IPC limits using sysctl or by writing to the /proc files. These changes are lost on reboot. To make permanent changes, edit /etc/sysctl.conf.

/* --- Shell commands to change IPC limits (run as root) ---

# View current message queue limit
$ sysctl kernel.msgmni

# Temporarily increase max message queues to 1024
$ sysctl -w kernel.msgmni=1024

# Or write directly to /proc:
$ echo 1024 > /proc/sys/kernel/msgmni

# Change semaphore limits (all 4 values in one write):
# format: SEMMSL SEMMNS SEMOPM SEMMNI
$ sysctl -w kernel.sem="32000 1024000000 500 32000"

# Make permanent: add to /etc/sysctl.conf
$ echo "kernel.msgmni = 1024" >> /etc/sysctl.conf
$ echo "kernel.shmmni = 4096" >> /etc/sysctl.conf
$ sysctl -p   # reload from sysctl.conf
*/

/* C code: check if semaphore creation would exceed limits */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(void) {
    int semmni = 0;
    FILE *f = fopen("/proc/sys/kernel/sem", "r");
    if (f) { int a,b,c; fscanf(f, "%d %d %d %d", &a,&b,&c,&semmni); fclose(f); }

    printf("Max semaphore sets (SEMMNI) = %d\n", semmni);
    printf("Attempting to create a semaphore set...\n");

    int id = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
    if (id == -1) {
        if (errno == ENOSPC)
            printf("ENOSPC: System limit reached! Too many semaphore sets.\n");
        else
            perror("semget");
        exit(EXIT_FAILURE);
    }

    printf("Created semaphore set ID = %d\n", id);
    semctl(id, 0, IPC_RMID);
    return 0;
}
ENOSPC error: When you hit the system limit for a particular IPC type (e.g., too many semaphore sets), the get call returns -1 with errno set to ENOSPC. This is why cleaning up unused IPC objects is important in production systems.

ipcs vs /proc/sysvipc — When to Use Which
Feature ipcs command /proc/sysvipc files
Shows all objects? No — filtered by read permission Yes — all objects regardless of permissions
Portability Available on all POSIX systems Linux-specific
Use in scripts Needs text parsing of ipcs output Direct file read, more reliable format
Programmatic access Via popen() or system() Direct fopen()/fread()
Available to non-root? Yes (shows permitted objects) Yes (shows all)
Portable approach? Most portable (parse ipcs output) Not portable — Linux only
TLPI recommendation: For portability, parse the output of ipcs(1). For Linux-specific programs that need to walk all IPC objects (including those without read permission), use the /proc/sysvipc files.

🎯 Interview Questions — /proc/sysvipc & Limits

Q1. What are the three files in /proc/sysvipc and what does each contain?
A: /proc/sysvipc/msg (all message queues), /proc/sysvipc/sem (all semaphore sets), /proc/sysvipc/shm (all shared memory segments). Each provides the same information as ipcs but for all objects regardless of read permission.
Q2. What is the key advantage of /proc/sysvipc over the ipcs command?
A: The /proc/sysvipc files show ALL IPC objects on the system regardless of read permission. ipcs only shows objects for which the current user has read permission. This makes /proc/sysvipc more useful for root-level monitoring and scripts that need a complete picture.
Q3. Where are System V IPC limits stored on Linux?
A: Under /proc/sys/kernel/. For message queues: msgmni, msgmax, msgmnb. For semaphores: /proc/sys/kernel/sem (contains SEMMSL, SEMMNS, SEMOPM, SEMMNI). For shared memory: shmmni, shmmax, shmall.
Q4. What do the four values in /proc/sys/kernel/sem mean?
A: SEMMSL (max semaphores per set), SEMMNS (max semaphores system-wide across all sets), SEMOPM (max operations per single semop() call), SEMMNI (max number of semaphore sets/identifiers).
Q5. What error is returned by a get call when a system IPC limit is reached?
A: ENOSPC (“no space left on device” — but in this context means “IPC resource limit reached”). The call returns -1 and errno is set to ENOSPC.
Q6. How do you make an IPC limit change permanent across reboots?
A: Add the limit to /etc/sysctl.conf (e.g., kernel.msgmni = 1024) and run sysctl -p to reload. Changes made directly to /proc/sys/kernel/* or via sysctl -w are temporary and lost on reboot.
Q7. What is the most portable way to programmatically list all IPC objects of a given type?
A: Parse the output of ipcs(1). The /proc/sysvipc files are Linux-specific. Some other UNIX implementations provide their own non-standard methods (e.g., Solaris has msgids(), semids(), shmids() system calls).
Q8. Why do IPC limits exist? What problem would occur without them?
A: Without limits, processes could create an unlimited number of IPC objects, exhausting kernel memory and data structures. Limits ensure fair resource usage and prevent denial-of-service through resource exhaustion.

Leave a Reply

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