--- name: shmget signature: 'shmget KEY, SIZE, FLAGS' since: 5.0 status: documented categories: ["SysV IPC"] --- ```{index} single: shmget; Perl built-in ``` *[SysV IPC](../perlfunc-by-category)* # shmget Create or look up a System V shared memory segment and return its identifier. `shmget` is the allocation step for SysV shared memory. Given a numeric `KEY` (either `IPC_PRIVATE` for a fresh anonymous segment or a well-known number agreed with other processes), a requested `SIZE` in bytes, and a bit-mask of `FLAGS` (creation flags OR'd with a 9-bit mode), it returns a kernel-assigned integer identifier. That identifier — the `shmid` — is what every subsequent call ([`shmctl`](shmctl), [`shmread`](shmread), [`shmwrite`](shmwrite)) uses to refer to the segment. The segment persists in the kernel until it is explicitly removed with `shmctl($shmid, IPC_RMID, 0)` or the system reboots; closing the creating process does **not** release it. ## Synopsis ```perl shmget KEY, SIZE, FLAGS ``` ## What you get back An integer shared-memory identifier (`shmid`) on success, suitable for passing to [`shmctl`](shmctl), [`shmread`](shmread), and [`shmwrite`](shmwrite). On failure returns a false value and sets [`$!`](../perlvar) to the underlying `errno`. ```perl use IPC::SysV qw(IPC_PRIVATE IPC_CREAT S_IRUSR S_IWUSR); my $shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT | S_IRUSR | S_IWUSR) or die "shmget: $!"; ``` The returned identifier is an opaque small integer. Do not do arithmetic on it, do not compare it to `0` for truth — the identifier `0` is a legitimate value on some systems. Always check the return against the documented failure sentinel (see *Differences from upstream*). ## Global state it touches - [`$!`](../perlvar) — set on failure to the underlying `errno`: `EACCES` (permissions), `EEXIST` (segment for that key already exists and both `IPC_CREAT` and `IPC_EXCL` were given), `EINVAL` (`SIZE` below `SHMMIN` or above `SHMMAX`, or `SIZE` differs from the existing segment when looking one up), `ENFILE` / `ENOSPC` (kernel segment-table full), `ENOENT` (no segment for that key and `IPC_CREAT` was not given), `ENOMEM` (insufficient memory). The function is otherwise pure with respect to Perl-visible state: no special variables beyond [`$!`](../perlvar) are touched, [`$_`](../perlvar) is not read. ## Examples Create a fresh private segment — the usual pattern when parent and children share memory via `fork`: ```perl use IPC::SysV qw(IPC_PRIVATE IPC_CREAT S_IRUSR S_IWUSR); my $size = 4096; my $shmid = shmget(IPC_PRIVATE, $size, IPC_CREAT | S_IRUSR | S_IWUSR) or die "shmget: $!"; # children inherit $shmid across fork and attach via shmread/shmwrite ``` Attach to a pre-existing segment by its well-known key. `SIZE` and mode bits are ignored in this form; pass `0` for both: ```perl my $key = 0xDEADBEEF; my $shmid = shmget($key, 0, 0) or die "shmget: $!"; ``` Create-or-open with `IPC_CREAT`. If the key already exists the existing `shmid` is returned; otherwise a new segment of `SIZE` bytes is created with the given mode: ```perl use IPC::SysV qw(IPC_CREAT S_IRUSR S_IWUSR S_IRGRP); my $shmid = shmget(0x1234, 8192, IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP) or die "shmget: $!"; ``` Fail if a segment already exists, using `IPC_EXCL`. This is the safe pattern for a process that wants to be the unique creator: ```perl use IPC::SysV qw(IPC_CREAT IPC_EXCL S_IRUSR S_IWUSR); use Errno qw(EEXIST); my $shmid = shmget(0x1234, 4096, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); if (!$shmid) { die "shmget: $!" unless $! == EEXIST; # another process won the race; fall back to plain lookup $shmid = shmget(0x1234, 0, 0) or die "shmget (lookup): $!"; } ``` Full create-use-destroy cycle with guaranteed cleanup via `END`: ```perl use IPC::SysV qw(IPC_PRIVATE IPC_CREAT IPC_RMID S_IRUSR S_IWUSR); my $shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | S_IRUSR | S_IWUSR) or die "shmget: $!"; END { shmctl($shmid, IPC_RMID, 0) if defined $shmid; } shmwrite($shmid, "hello", 0, 5) or die "shmwrite: $!"; shmread($shmid, my $buf, 0, 5) or die "shmread: $!"; ``` ## Edge cases - **`use IPC::SysV` is effectively mandatory.** The flag constants (`IPC_PRIVATE`, `IPC_CREAT`, `IPC_EXCL`, `IPC_RMID`) and mode bits (`S_IRUSR`, `S_IWUSR`, `S_IRGRP`, ...) are not built-ins. Without the import you end up passing bare barewords that stringify to `0` and silently do the wrong thing. - **Key `0` is not `IPC_PRIVATE`.** `IPC_PRIVATE` is defined as `0` on Linux, but passing a literal `0` with no `IPC_CREAT` asks the kernel for the segment at key `0`, which is the `IPC_PRIVATE` sentinel and yields `EINVAL`. Import the constant by name and use it. - **`SIZE` is rounded up to a page boundary** by the kernel; the returned segment may be larger than requested. Ask the kernel for the effective size with `shmctl($shmid, IPC_STAT, $ds)` and unpack the `shmid_ds` structure if you need the real number. - **Segment persists beyond process exit.** A crashed or killed creator leaves the segment in the kernel. Use `ipcs -m` to list orphaned segments and `ipcrm -m ` to remove them. Install an `END` block or a signal handler to call `shmctl IPC_RMID` on shutdown. - **`IPC_RMID` is deferred, not immediate.** It marks the segment for destruction; actual removal happens once the attach count drops to zero. Safe to call right after `shmget` if you know no one else will attach. - **Kernel limits.** `SHMMNI` caps the total number of segments system-wide (`/proc/sys/kernel/shmmni`). `SHMMAX` caps the size of one segment (`/proc/sys/kernel/shmmax`). On a shared host these are easy to hit; treat `ENOSPC` and `EINVAL`-from-large-size as configuration issues, not bugs. - **SysV IPC is not available on every platform.** Upstream Perl built on a system without `HAS_SHM` dies with `"System V IPC is not implemented on this machine"`. pperl targets Linux only, where SysV IPC is always present, so the call is always dispatched. ## Differences from upstream - Returns `-1` rather than [`undef`](undef) on failure. Both values are false under Perl's truth rules, so the idiomatic `shmget(...) or die "$!"` works unchanged, but code that distinguishes "not an identifier" via `defined $shmid` will read `-1` as defined. Prefer checking for truth, or compare against `-1` explicitly when you want to branch on the failure sentinel. The `-1` is the raw `shmget(2)` return value, which is the documented error sentinel for that syscall. ## See also - [`shmctl`](shmctl) — control operations on the segment `shmget` returned; use `IPC_RMID` to delete it, `IPC_STAT` to inspect size and permissions - [`shmread`](shmread) — read `SIZE` bytes from the segment into a Perl scalar - [`shmwrite`](shmwrite) — write a Perl scalar into the segment at an offset - [`msgget`](msgget) — the equivalent allocation step for SysV message queues when you want a queue, not a flat buffer - [`semget`](semget) — the equivalent for SysV semaphores when the goal is synchronisation rather than shared data - `IPC::SysV` — source of the `IPC_*` and `S_*` flag constants `shmget` requires; no local reference page, see upstream POD