Wikipedia · einfach zusammengefasst · Stand
Pipe (Informatik)
Eine Pipe oder Pipeline (englisch Rohrleitung) ist ein Datenstrom zwischen zwei Prozessen durch einen Puffer mit dem Prinzip First In – First Out (FIFO).
Inhalt6 Abschnitte
Grundidee und Bedeutung
Eine Pipe oder Pipeline ist ein Datenstrom zwischen zwei Prozessen, der über einen Puffer nach dem Prinzip First In – First Out (FIFO) läuft: Die zuerst hineingeschriebenen Daten werden zuerst wieder gelesen. Dadurch kann die Ausgabe eines Programms unmittelbar als Eingabe eines anderen Programms dienen.
Pipes sind besonders wichtig für die Unix-Philosophie. Statt ein einziges Programm mit sehr vielen Funktionen auszustatten, werden spezialisierte Programme miteinander verbunden. Jedes löst eine Teilaufgabe, während die Pipe die Daten zwischen ihnen weiterleitet. Auf diese Weise lassen sich mehrere Verarbeitungsschritte zu einer Befehlsfolge kombinieren.
Douglas McIlroy erfand Pipes 1972/73 für Unix; als Einführungsjahr wird auch 1973 genannt. Bereits 1964 hatte er zu Beginn des Multics-Projekts vorgeschlagen, Programme ähnlich wie Abschnitte eines Gartenschlauchs miteinander zu verbinden.
Erzeugung und Lebensdauer
Unter den meisten Betriebssystemen und in vielen Programmiersprachen wird eine Pipe durch den Systemaufruf pipe() angefordert. Das Betriebssystem liefert zwei Zugriffskennungen, sogenannte Handles beziehungsweise unter Unix Filedeskriptoren: eine zum Lesen und eine zum Schreiben.
Kindprozesse erben gewöhnlich den Zugriff auf diese Kennungen. Dadurch können ein Elternprozess und seine durch fork() erzeugten Kindprozesse Daten über die Pipe austauschen. Sobald der letzte Prozess, der noch Zugriff auf eine aktive Pipe besitzt, beendet wird, beendet das Betriebssystem auch die Pipe.
Anonyme und benannte Pipes
Anonyme Pipes besitzen keinen dauerhaften Namen. Sie haben drei wesentliche Einschränkungen:
- Sie arbeiten nur in eine Richtung: Ein Prozess schreibt, der andere liest.
- Sie dienen nur der Kommunikation zwischen eng verwandten Prozessen, beispielsweise Prozessen mit demselben Elternprozess.
- Die Datenmenge, die ihr Puffer gleichzeitig aufnehmen kann, ist relativ klein.
Benannte Pipes, auch Named Pipes oder FIFOs genannt, werden dagegen über einen Namen angesprochen. Jeder entsprechend berechtigte Prozess, der diesen Namen kennt, kann eine Verbindung herstellen. Die Prozesse müssen nicht miteinander verwandt sein und dürfen sich auch auf unterschiedlichen Rechnern eines Netzwerks befinden.
Benannte Pipes sind flexibler, eignen sich für Client-Server-Anwendungen und können auch für Remote Procedure Calls (RPCs), also entfernte Prozeduraufrufe, verwendet werden. Sie erlauben eine gleichzeitige Datenübertragung in beide Richtungen. Dieser Betrieb heißt Vollduplexbetrieb.
Verwendung unter Unix
Unter Unix und unixoiden Betriebssystemen ermöglichen Pipes die aufeinanderfolgende Verarbeitung eines Datenbestands durch mehrere Befehle. In einer Shell kennzeichnet das Zeichen | eine anonyme Pipe. Die Shell erzeugt die beteiligten Prozesse automatisch durch Forks und ist deren gemeinsamer Elternprozess.
Ein typisches Beispiel lautet:
ls -R ./Bilder | grep -ic '.jpg$'
ls listet das Verzeichnis ./Bilder samt Unterverzeichnissen, weil der Schalter R gesetzt ist. Diese Textausgabe gelangt durch die Pipe zu grep. grep sucht nach Dateinamen mit der Endung .jpg; der Backslash maskiert den Punkt. Der Schalter i lässt Groß- und Kleinschreibung unberücksichtigt, sodass auch JPG gefunden wird. Der Schalter c gibt nur die Anzahl der Treffer aus. Das Gesamtergebnis ist somit die Anzahl der JPG-Bilder unterhalb von ./Bilder.
In einer längeren Pipeline durchsucht
grep '.sshd.*Invalid user' /var/log/messages | awk '{print $NF}' | sort -u
die System-Logdatei nach Zeilen, in denen auf „sshd“ der Text „Invalid user“ folgt. awk entnimmt jeweils das letzte Feld, hier die IP-Adresse des Rechners, von dem der SSH-Zugriff ausging. sort -u sortiert die Adressen und entfernt Mehrfachnennungen.
Bis auf das erste Programm lesen die beteiligten Programme von der Standardeingabe; bis auf das letzte schreiben sie auf die Standardausgabe. Bei manchen Anwendungen kann ein Minuszeichen anstelle eines Dateinamens festlegen, dass die Standardausgabe beziehungsweise Standardeingabe verwendet wird. So packt
tar cf - /home/user/ogg/mycolouringbook | ssh -l user server "cd /var/ogg && tar xvf -"
ein Verzeichnis in ein Archiv, überträgt es über SSH zu einem anderen Rechner und entpackt es dort.
Eine benannte Unix-Pipe wird beispielsweise mit mkfifo erzeugt und anschließend über ihren Dateinamen geöffnet. Sie gehört zum Dateisystem und überdauert daher die Prozesse, die sie verwenden. Solange kein Prozess sie geöffnet hat, kann sie jedoch keinen Inhalt speichern. Schließt der schreibende Prozess sein Ende, bevor ein lesender Prozess das andere Ende geöffnet hat, geht der gepufferte Inhalt verloren.
Programmierung anonymer Pipes in C
In C nimmt ein Feld wie fd[2] die beiden Filedeskriptoren einer Pipe auf. Nach pipe(fd) bezeichnet fd[0] das Leseende und fd[1] das Schreibende. Mit fork() entsteht ein Kindprozess, der zunächst beide Enden erbt. Jeder Prozess muss deshalb das Ende schließen, das er nicht benötigt.
Für die Wirkung von who | sort kann ein erster Kindprozess sein Schreibende mithilfe von dup2 mit der Standardausgabe verbinden und anschließend who ausführen. Ein zweiter Kindprozess verbindet das Leseende mit der Standardeingabe und führt sort aus. Bleibt ein unnötiges Schreibende geöffnet, erkennt der lesende Prozess nicht, dass keine weiteren Daten kommen, und wartet weiter. Auch unnötige Lesezugriffe können zu fehlerhaftem Warten führen.
Ein weiteres C-Beispiel begrenzt die Eingabe mit MAX_ZEICHEN auf 2048 Bytes. Der Elternprozess schließt das Leseende, liest mit fgets eine Benutzereingabe ein und sendet sie mit write durch die Pipe. Danach wartet er mit waitpid auf das Kind. Der Kindprozess schließt das Schreibende, liest die Daten mit read, wandelt jedes Zeichen mit toupper in einen Großbuchstaben um und gibt das Ergebnis über STDOUT_FILENO aus. Fehler beim Erzeugen der Pipe oder beim Warten werden über Fehlermeldungen behandelt.
Unterstützung in Windows und OS/2
Windows unterstützt anonyme und benannte Pipes. Eine benannte Pipe lässt sich über das Pipe-API ähnlich wie eine SMB-Freigabe unter \ServerName\pipe\PipeName ansprechen. In der Windows-Eingabeaufforderung können anonyme Pipes Ausgaben filtern. Der Befehl
dir *.java /s | find "Render"
sucht in der rekursiven Ausgabe von dir nach „Render“. Er liefert Unterverzeichnisse mit enthaltenen .java-Dateien, wenn ihr Pfad dieses Wort enthält, sowie .java-Dateien, deren Dateiname „Render“ enthält.
Auch OS/2 besitzt anonyme und benannte Pipes. Benannte Pipes zählen dort zu den leistungsfähigsten Verfahren der Interprozesskommunikation (IPC). Ein Server-Prozess kann mehrere Instanzen einer Pipe erzeugen, die alle denselben Namen tragen. Im Multiplexbetrieb kann dadurch ein einzelner Server-Prozess mehrere Clients gleichzeitig bedienen.