====== std.pipe ====== Pipes & fd-Duplikation (WP-2): Erstellt unidirektionale anonyme Pipes für die Prozesskommunikation und dupliziert Dateideskriptoren (''dup''/''dup2''/''dup3''). Typischer Einsatz: Eltern-Kind-Kommunikation nach ''fork'', Stdout/Stderr-Umleitung und Pipe-Kaskaden. → [[lyx_-_programmiersprache:units|Standard Library]] · [[lyx_-_programmiersprache:units:process|std.process]] · [[lyx_-_programmiersprache:units:mqueue|std.mqueue]] ---- ===== Konstanten ===== ^ Konstante ^ Wert ^ Beschreibung ^ | ''O_CLOEXEC'' | 524288 | fd bei ''exec()'' schließen (''0x80000'') | | ''O_NONBLOCK'' | 2048 | Pipe-fds nicht-blockierend (''0x800'') | ---- ===== Funktionen ===== ==== Pipe erstellen ==== ^ Signatur ^ Beschreibung ^ | ''PipeCreate(readFdOut: int64, writeFdOut: int64): int64'' | Erstellt ein Pipe-Paar. ''readFdOut'' und ''writeFdOut'' sind je ''alloc(8)''-Buffer; nach Aufruf via ''peek64'' lesen. Gibt 0 bei Erfolg zurück | | ''Pipe2(readFdOut: int64, writeFdOut: int64, flags: int64): int64'' | Wie ''PipeCreate'', aber mit Flags (''O_CLOEXEC'', ''O_NONBLOCK'' oder Kombination) | ==== fd-Duplikation ==== ^ Signatur ^ Beschreibung ^ | ''FdDup(oldFd: int64): int64'' | Dupliziert ''oldFd'' auf den nächst-freien fd. Gibt den neuen fd zurück | | ''FdDup2(oldFd: int64, newFd: int64): int64'' | Dupliziert ''oldFd'' auf ''newFd'' (schließt ''newFd'' falls bereits offen). Gibt ''newFd'' zurück | | ''FdDup3(oldFd: int64, newFd: int64, flags: int64): int64'' | Wie ''FdDup2'', aber mit Flags (z. B. ''O_CLOEXEC'') | ---- ===== Verwendung ===== ==== Eltern-Kind-Kommunikation ==== import std.pipe; import std.process; import std.alloc; import std.io; fn Main(): void { var rBuf: int64 := alloc(8); var wBuf: int64 := alloc(8); PipeCreate(rBuf, wBuf); var rFd := peek64(rBuf); var wFd := peek64(wBuf); free(rBuf, 8); free(wBuf, 8); var pid := Fork(); if (pid == 0) { // Kindprozess: liest von der Pipe close(wFd); var buf: int64 := alloc(64); var n := read(rFd, buf, 64); PrintLn("Kind empfing: " + buf as pchar); free(buf, 64); close(rFd); } else { // Elternprozess: schreibt in die Pipe close(rFd); var msg: pchar := "Hallo Kind"; write(wFd, msg as int64, 11); close(wFd); Wait(pid); } } ==== Stdout auf Pipe umleiten (FdDup2) ==== import std.pipe; import std.alloc; fn RedirectStdout(): int64 { var rBuf: int64 := alloc(8); var wBuf: int64 := alloc(8); Pipe2(rBuf, wBuf, O_CLOEXEC); var rFd := peek64(rBuf); var wFd := peek64(wBuf); free(rBuf, 8); free(wBuf, 8); // fd 1 (stdout) auf Schreib-Ende der Pipe umleiten FdDup2(wFd, 1); close(wFd); // Alles was jetzt über fd 1 geschrieben wird, landet in der Pipe. // Lese-Ende (rFd) zurückgeben. return rFd; } ==== Nicht-blockierende Pipe ==== import std.pipe; import std.alloc; import std.io; fn TryRead(pipeFd: int64): bool { var buf: int64 := alloc(256); var n := read(pipeFd, buf, 256); free(buf, 256); if (n < 0) { // n == -11 bedeutet EAGAIN — keine Daten vorhanden return false; } return true; } fn SetupNonblocking(): int64 { var rBuf: int64 := alloc(8); var wBuf: int64 := alloc(8); Pipe2(rBuf, wBuf, O_NONBLOCK | O_CLOEXEC); var rFd := peek64(rBuf); free(rBuf, 8); free(wBuf, 8); return rFd; } ---- ===== Hinweise ===== * Eine Pipe ist unidirektional: Das Schreib-Ende (''wFd'') und Lese-Ende (''rFd'') müssen nach ''fork()'' im jeweils nicht-verwendenden Prozess geschlossen werden — sonst blockiert ''read'' auf ''rFd'' ewig (Schreib-Ende noch offen). * Pipes haben einen Kernel-Puffer (typisch 64 KB). ''write'' auf eine volle Pipe blockiert; ''read'' auf eine leere Pipe blockiert. * Mit ''O_NONBLOCK'' geben ''read''/''write'' sofort zurück: ''−11'' (''EAGAIN'') wenn nicht bereit. * ''FdDup2(wFd, 1)'' ist der Standardweg um den Stdout eines Kindprozesses abzufangen (vor ''exec''). * ''O_CLOEXEC'' auf der Pipe verhindert, dass der fd nach ''exec()'' versehentlich geerbt wird. ---- ===== Verwandte Units ===== * ''[[lyx_-_programmiersprache:units:process|std.process]]'' — fork, exec, waitpid * ''[[lyx_-_programmiersprache:units:mqueue|std.mqueue]]'' — Message Queues (prioritätsbasiertes IPC) * ''[[lyx_-_programmiersprache:units:signals|std.signals]]'' — Signal-basierte Prozesskommunikation * ''[[lyx_-_programmiersprache:units:net:epoll|std.net.epoll]]'' — Pipe-fds lassen sich in epoll einbinden Letzte Aktualisierung: 2026-06-05