Kernel IPC files
Limit controls
No permission filter
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.
key semid perms nsems uid gid cuid cgid otime ctime
0 16646144 600 4 1000 100 1000 100 0 1010166460
/* 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;
}
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.
| 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 contains four space-separated values in this order:
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) |
/* 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;
}
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;
}
| 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 |
