====== std.ipc_sysv — SysV IPC (Shared Memory, Semaphore, Message Queues) ======
''import std.ipc_sysv;''
SysV IPC ist der klassische POSIX-Mechanismus für Inter-Prozess-Kommunikation: gemeinsamer Speicher (Shared Memory), Semaphore und Message Queues. Alle Objekte werden über Integer-Keys identifiziert, nicht über Pfade.
→ [[lyx_-_programmiersprache:units:ns|std.ns]] · [[lyx_-_programmiersprache:units:os|std.os]] · [[lyx_-_programmiersprache:sprache:handles-und-fd|Handles und Dateideskriptoren]]
----
===== Allgemeine Konstanten =====
^ Konstante ^ Wert ^ Bedeutung ^
| ''IPC_PRIVATE'' | 0 | Privater Key — nur für den erzeugenden Prozess und seine Kinder sichtbar |
| ''IPC_CREAT'' | 512 | Anlegen falls nicht vorhanden |
| ''IPC_EXCL'' | 1024 | Fehler wenn bereits vorhanden (nur mit IPC_CREAT sinnvoll) |
| ''IPC_RMID'' | 0 | Objekt löschen |
----
===== Shared Memory =====
==== Konstanten ====
^ Konstante ^ Wert ^ Bedeutung ^
| ''SHM_RDONLY'' | 4096 | Segment nur lesend mappen |
==== Funktionen ====
^ Funktion ^ Signatur ^ Beschreibung ^
| ''ShmCreate'' | ''(key: int64, size: int64, flags: int64): int64'' | Erzeugt oder öffnet ein Shared-Memory-Segment; gibt shmId zurück |
| ''ShmAttach'' | ''(shmId: int64, addr: int64, flags: int64): int64'' | Mappt Segment in den Prozess-Adressraum; ''addr=0'' → Kernel wählt |
| ''ShmDetach'' | ''(addr: int64): int64'' | Entfernt Mapping aus Adressraum (kein Löschen) |
| ''ShmDelete'' | ''(shmId: int64): int64'' | Löscht das Segment wenn kein Prozess mehr gemappt ist |
==== Verwendung ====
import std.ipc_sysv;
import std.io;
fn main(): int64 {
// Segment anlegen: IPC_PRIVATE + IPC_CREAT + Rechte 0o666
var shmId: int64 := ShmCreate(IPC_PRIVATE, 4096, IPC_CREAT | 438);
if (shmId < 0) { return shmId; }
// In Adressraum einblenden
var mem: int64 := ShmAttach(shmId, 0, 0);
if (mem < 0) { ShmDelete(shmId); return mem; }
// Daten schreiben/lesen
poke64(mem, 42);
var v: int64 := peek64(mem);
// Aufräumen
ShmDetach(mem);
ShmDelete(shmId);
return 0;
}
----
===== Semaphore =====
==== Konstanten ====
^ Konstante ^ Wert ^ Bedeutung ^
| ''SEMBUF_SIZE'' | 8 | Größe der sembuf-Struktur in Bytes |
| ''SEM_UNDO'' | 4096 | Undo-Operation bei Prozessende |
| ''IPC_NOWAIT'' | 2048 | Nicht blockieren |
| ''SEM_GETVAL'' | 12 | Wert einer Semaphore lesen |
| ''SEM_SETVAL'' | 16 | Wert einer Semaphore setzen |
==== Funktionen ====
^ Funktion ^ Signatur ^ Beschreibung ^
| ''SemCreate'' | ''(key: int64, nsems: int64, flags: int64): int64'' | Erzeugt/öffnet Semaphore-Gruppe mit ''nsems'' Semaphoren |
| ''SemSetVal'' | ''(semId: int64, semNum: int64, val: int64): int64'' | Setzt Wert von Semaphore Nr. ''semNum'' |
| ''SemGetVal'' | ''(semId: int64, semNum: int64): int64'' | Liest Wert von Semaphore Nr. ''semNum'' |
| ''SemWait'' | ''(semId: int64, semNum: int64): int64'' | P-Operation: dekrementiert um 1, blockiert wenn 0 |
| ''SemPost'' | ''(semId: int64, semNum: int64): int64'' | V-Operation: inkrementiert um 1 |
| ''SemDelete'' | ''(semId: int64): int64'' | Löscht die Semaphore-Gruppe |
==== Verwendung ====
import std.ipc_sysv;
fn main(): int64 {
// Mutex-Semaphore anlegen (1 Semaphore, Initialwert 1)
var semId: int64 := SemCreate(IPC_PRIVATE, 1, IPC_CREAT | 438);
if (semId < 0) { return semId; }
SemSetVal(semId, 0, 1); // Semaphore 0 auf Wert 1 setzen
// Kritischen Abschnitt schützen
SemWait(semId, 0); // Lock
// ... kritischer Abschnitt ...
SemPost(semId, 0); // Unlock
SemDelete(semId);
return 0;
}
----
===== Message Queues =====
==== Konstanten ====
^ Konstante ^ Wert ^ Bedeutung ^
| ''MSG_HDR_SIZE'' | 8 | Größe des mtype-Headers im msgbuf |
| ''MSG_NOERROR'' | 4096 | Nachricht abschneiden statt ''-E2BIG'' |
==== Funktionen ====
^ Funktion ^ Signatur ^ Beschreibung ^
| ''MsgQueueCreate'' | ''(key: int64, flags: int64): int64'' | Erzeugt/öffnet Message-Queue; gibt mqId zurück |
| ''MsgSend'' | ''(mqId: int64, buf: int64, size: int64, flags: int64): int64'' | Sendet Nachricht; ''buf'': erste 8 Bytes = mtype (> 0), dann Nutzdaten |
| ''MsgRecv'' | ''(mqId: int64, buf: int64, size: int64, msgType: int64, flags: int64): int64'' | Empfängt Nachricht; gibt Nutzdaten-Bytes zurück |
| ''MsgQueueDelete'' | ''(mqId: int64): int64'' | Löscht die Queue |
==== Verwendung ====
import std.ipc_sysv;
import std.alloc;
fn main(): int64 {
var mqId: int64 := MsgQueueCreate(IPC_PRIVATE, IPC_CREAT | 438);
if (mqId < 0) { return mqId; }
// Senden: 8 Bytes mtype-Header + 16 Bytes Nutzdaten
var sendBuf: int64 := alloc(24);
poke64(sendBuf, 1); // mtype = 1 (muss > 0)
poke64(sendBuf + 8, 0x1234); // Nutzdaten
poke64(sendBuf + 16, 0x5678);
MsgSend(mqId, sendBuf, 16, 0);
// Empfangen
var recvBuf: int64 := alloc(24);
var n: int64 := MsgRecv(mqId, recvBuf, 16, 1, 0);
// n = 16, recvBuf+8 = Nutzdaten
free(sendBuf, 24);
free(recvBuf, 24);
MsgQueueDelete(mqId);
return 0;
}
----
===== Hinweise =====
* **IPC_PRIVATE**: Erstellt ein Objekt das nicht über einen Integer-Key von anderen Prozessen gefunden werden kann — geeignet für Eltern-Kind-Kommunikation (vor dem ''fork()'').
* **Schlüssel-Konflikte**: Bei festem Key und ''IPC_CREAT'' ohne ''IPC_EXCL'' wird ein bestehendes Objekt geöffnet — kann zu unerwarteten Verbindungen mit anderen Prozessen führen.
* **msgbuf-Layout**: Die ersten 8 Bytes des Puffers sind immer der ''mtype'' (int64, muss > 0). Die ''size''-Parameter in ''MsgSend''/''MsgRecv'' zählen **ohne** diesen Header.
* **Persistenz**: SysV-IPC-Objekte überleben den Prozess — explizites ''ShmDelete''/''SemDelete''/''MsgQueueDelete'' ist nötig. Vergessene Objekte sichtbar mit: ''ipcs''.
* **Alternative**: Für moderne Anwendungen bevorzugt ''mmap'' + Datei oder POSIX-Semaphore (''sem_open'').
----
Letzte Aktualisierung: 2026-06-06