====== 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