--- name: semget signature: 'semget KEY, NSEMS, FLAGS' since: 5.0 status: documented categories: ["SysV IPC"] --- ```{index} single: semget; Perl built-in ``` *[SysV IPC](../perlfunc-by-category)* # 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`](semop), [`semctl`](semctl)) expects. ## Synopsis ```perl semget KEY, NSEMS, FLAGS ``` ## What you get back The semaphore set identifier (a non-negative integer) on success, or [`undef`](undef) on failure with [`$!`](../perlvar) 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)`. ```perl use IPC::SysV qw(IPC_CREAT IPC_PRIVATE); my $semid = semget(IPC_PRIVATE, 3, IPC_CREAT | 0600) // die "semget: $!"; ``` ## Global state it touches - [`$!`](../perlvar) — 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`](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`](open). Permission bits are checked by the kernel on every subsequent [`semop`](semop) and [`semctl`](semctl) call against the invoking process's uid/gid. ## Examples Create a private set of three semaphores usable by this process and its children: ```perl 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: ```perl 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: ```perl 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: ```perl 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`](close), [`fcntl`](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`](semop) — perform wait/signal operations on the set returned by `semget` - [`semctl`](semctl) — control operations on the set: initialise values (`SETALL`, `SETVAL`), read them (`GETALL`, `GETVAL`), and remove the set (`IPC_RMID`) - [`msgget`](msgget) — the message-queue counterpart, same `KEY, FLAGS` conventions - [`shmget`](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