SysV IPC

semget#

Create or look up a System V semaphore set and return its identifier.

semget is the entry point into the SysV semaphore API. It wraps the semget(2) system call: given a numeric KEY that names the set, the number of semaphores NSEMS in the set, and a FLAGS word combining permission bits with creation flags, the kernel either returns the id of a matching existing set or, if IPC_CREAT is in FLAGS, creates a new set and returns its id. The returned id is the handle every other semaphore call (semop, semctl) expects.

Synopsis#

semget KEY, NSEMS, FLAGS

What you get back#

The semaphore set identifier (a non-negative integer) on success, or undef on failure with $! set to the errno from the underlying semget(2) call. The id is not a file descriptor — it is a kernel-wide SysV IPC handle that outlives your process and persists until explicitly removed with semctl($id, 0, IPC_RMID, 0).

use IPC::SysV qw(IPC_CREAT IPC_PRIVATE);

my $semid = semget(IPC_PRIVATE, 3, IPC_CREAT | 0600)
    // die "semget: $!";

Global state it touches#

  • $! — set to the errno value from semget(2) on failure (EACCES, EEXIST, ENOENT, ENOSPC, EINVAL, ENOMEM).

The KEY argument#

KEY is an integer that names the semaphore set system-wide. Three conventions matter:

  • IPC_PRIVATE (imported from IPC::SysV) — the kernel allocates a fresh key unused by any other set. The resulting id is known only to this process and anyone it passes the id to, typically children after fork. Use this when the set is an implementation detail of one process tree.

  • A fixed integer literal — every cooperating process hard-codes the same number. Fragile across unrelated programs that might pick the same integer.

  • A key derived from ftok(3)IPC::SysV::ftok($path, $proj_id) turns a filesystem path plus a project byte into a numeric key. The standard recipe for unrelated processes that need to agree on a key without hard-coding a magic number.

The FLAGS argument#

FLAGS combines permission bits (low 9 bits, like a chmod mode: 0600, 0660, 0666) with creation flags from IPC::SysV:

  • IPC_CREAT — create the set if it does not already exist. Without this flag, semget only looks up an existing set with the given key.

  • IPC_CREAT | IPC_EXCL — create the set, but fail with EEXIST if one already exists for KEY. The SysV analogue of O_CREAT | O_EXCL in open.

Permission bits are checked by the kernel on every subsequent semop and semctl call against the invoking process’s uid/gid.

Examples#

Create a private set of three semaphores usable by this process and its children:

use IPC::SysV qw(IPC_PRIVATE IPC_CREAT);
my $semid = semget(IPC_PRIVATE, 3, IPC_CREAT | 0600)
    // die "semget: $!";

Look up an existing, named set without creating it. NSEMS must match the size the set was created with, or can be 0 if you do not care:

use IPC::SysV qw(ftok);
my $key   = ftok("/var/run/myapp.pid", ord('M'));
my $semid = semget($key, 0, 0) // die "no set for key $key: $!";

Create-or-open idiom — try exclusive create, fall back to lookup. The first process through initialises the set; later ones just attach:

use IPC::SysV qw(ftok IPC_CREAT IPC_EXCL);

my $key = ftok("/var/run/myapp.pid", ord('M'));
my $semid = semget($key, 4, IPC_CREAT | IPC_EXCL | 0660);
if (defined $semid) {
    # We created it — initialise every semaphore to 1.
    semctl($semid, 0, SETALL, pack("s!*", (1) x 4))
        or die "SETALL: $!";
} else {
    $semid = semget($key, 4, 0) // die "semget lookup: $!";
}

Remove a set when you are done with it. SysV sets leak across process exit — nothing cleans them up for you:

use IPC::SysV qw(IPC_RMID);
semctl($semid, 0, IPC_RMID, 0) or warn "semctl RMID: $!";

Edge cases#

  • NSEMS on lookup: when looking up an existing set (no IPC_CREAT), NSEMS of 0 means “any size”; a positive value must be less than or equal to the set’s actual size or semget fails with EINVAL.

  • IPC_PRIVATE still obeys FLAGS: permission bits apply. A set created with 0400 is read-only even to the creating process for semop calls that modify it.

  • Kernel limits: semget can fail with ENOSPC when the system-wide semaphore-set limit is reached, or EINVAL when NSEMS exceeds the per-set maximum. See ipcs -sl for the current limits on Linux.

  • Leaked sets: a set persists until IPC_RMID or reboot. Long- running daemons that forget to remove their sets accumulate them; ipcs -s lists the survivors, ipcrm -s $id removes one.

  • Key collisions: two unrelated programs picking the same hard- coded KEY will see each other’s set — hence the ftok(3) idiom.

  • Not a filehandle: $semid is an integer, not a handle. Do not pass it to close, fcntl, or any filehandle operation.

  • Forks inherit ids, not ownership: a child sees the same $semid value as the parent and can use it, but the set itself is owned by the uid that created it, not by any particular process.

  • Numeric context: the id is a plain integer, safe to print, compare, and store in a file for another process to pick up.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • semop — perform wait/signal operations on the set returned by semget

  • semctl — control operations on the set: initialise values (SETALL, SETVAL), read them (GETALL, GETVAL), and remove the set (IPC_RMID)

  • msgget — the message-queue counterpart, same KEY, FLAGS conventions

  • shmget — the shared-memory counterpart, same KEY, FLAGS conventions

  • IPC::SysV — imports IPC_CREAT, IPC_EXCL, IPC_PRIVATE, IPC_RMID, SETALL, GETALL, and the ftok helper

  • IPC::Semaphore — object wrapper around the raw sem* built-ins when you would rather not pack structs by hand