--- name: shmwrite signature: 'shmwrite ID, STRING, POS, SIZE' since: 5.0 status: documented categories: ["SysV IPC"] --- ```{index} single: shmwrite; Perl built-in ``` *[SysV IPC](../perlfunc-by-category)* # shmwrite Copy bytes into a System V shared memory segment. `shmwrite` attaches to the shared memory segment identified by `ID`, copies up to `SIZE` bytes from `STRING` starting at byte offset `POS` inside the segment, and detaches. If `STRING` is longer than `SIZE`, only the first `SIZE` bytes are written; if it is shorter, the remainder of the `SIZE`-byte window is zero-filled with NUL bytes. The segment `ID` is the value returned by an earlier [`shmget`](shmget) call (or obtained from another process via some out-of-band channel). ## Synopsis ```perl shmwrite ID, STRING, POS, SIZE ``` ## What you get back True on success, false on error, with [`$!`](../perlvar) set to the reason (typically `EINVAL`, `EACCES`, or `EIDRM`). Unlike most I/O built-ins the return value is a plain boolean — there is no byte-count variant, because the count is always exactly `SIZE` when the call succeeds. ```perl shmwrite($id, $payload, 0, 4096) or die "shmwrite($id) failed: $!"; ``` ## Global state it touches - [`$!`](../perlvar) is set on failure to the underlying `shmat` / `memcpy` / `shmdt` errno. - No other special variables are read or written. Unlike [`shmread`](shmread), `shmwrite` does not taint anything — it is the *source* of bytes, not a sink. ## Examples Publish a fixed-size record at the start of a segment: ```perl use IPC::SysV qw(IPC_PRIVATE S_IRUSR S_IWUSR); my $id = shmget(IPC_PRIVATE, 4096, S_IRUSR | S_IWUSR) or die "shmget: $!"; shmwrite($id, "hello, world", 0, 4096) or die "shmwrite: $!"; ``` A `STRING` shorter than `SIZE` is NUL-padded to fill the window — useful for clearing stale trailing bytes from a previous writer: ```perl shmwrite($id, "short", 0, 64); # 5 bytes of "short", then 59 NULs ``` A `STRING` longer than `SIZE` is truncated; the tail is silently discarded, so size your window to the largest record you ever intend to publish: ```perl shmwrite($id, "x" x 10_000, 0, 128); # only the first 128 x's land ``` Writing to a non-zero offset lets multiple fixed-size records share one segment. Pair it with a matching [`shmread`](shmread) on the reader side: ```perl my $slot = 3; my $len = 64; shmwrite($id, $record, $slot * $len, $len) or die "shmwrite slot $slot: $!"; ``` Check the return value — a segment that has been marked for deletion with `IPC_RMID` continues to accept writes from processes already attached, but fails for new `shmwrite` calls with `EIDRM`: ```perl unless (shmwrite($id, $msg, 0, $SIZE)) { warn "segment $id gone: $!"; # reacquire via shmget() and retry } ``` ## Edge cases - **Kernel must be built with SysV IPC.** On systems without SysV shared memory `shmwrite` croaks with `shmwrite not implemented`. This is a compile-time property of the kernel / libc, not a runtime condition you can probe for. - **`SIZE` of `0`** is accepted by the kernel and writes nothing; `shmwrite` returns true. Use it only when you genuinely mean "no-op", not as an error signal. - **`POS + SIZE` must fit inside the segment.** Overrunning the segment boundary fails with `EINVAL` and leaves the segment untouched — the copy is not partial. - **Binary payloads are fine.** `STRING` is treated as a byte string; embedded NULs are written literally. If the string carries the UTF-8 flag, the raw internal bytes are what hits the segment — use [`pack`](pack) or `Encode::encode` first if you need a specific encoding on the wire. - **No locking.** The kernel guarantees that each `shmwrite` call is atomic with respect to `shmat` / `shmdt`, but two concurrent writers can still interleave byte ranges within the segment. Coordinate with [`semop`](semop) or a user-space lock if multiple processes write the same region. - **Permissions** come from the segment's mode at [`shmget`](shmget) time. Attaching read-only and calling `shmwrite` fails with `EACCES`. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`shmread`](shmread) — inverse operation; copy bytes *out* of a segment into a Perl scalar - [`shmget`](shmget) — obtain the `ID` that `shmwrite` writes into - [`shmctl`](shmctl) — inspect segment attributes, change permissions, or mark a segment for deletion - [`semop`](semop) — the usual companion primitive for serialising access to a shared segment - [`pack`](pack) — build the fixed-layout byte string you hand to `shmwrite` when the segment holds structured records - `IPC::SysV` — constants (`IPC_PRIVATE`, `S_IRUSR`, `IPC_RMID`) used to construct the arguments to `shmget` and `shmctl`