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