Wie funktioniert Pipe in Bash-Befehlen?

Wie funktioniert Pipe in Bash-Befehlen?

Passiert irgendetwas Symbolisches, wenn ich Bash-Befehle über eine Pipe verkette, oder läuft alles nach dem Prinzip „Berechnen-Weitergeben-Berechnen-Weitergeben“ ab?

Beispielsweise head t.txt -n 5 | tail -n 2wird in head t.txt -n 5berechnet und dann tail -n 2darüber ausgeführt. Oder gibt es zuerst eine Abstraktion, um der Shell mitzuteilen, dass die Zeilen 3 bis 5 gelesen werden sollen? In diesem Beispiel macht das vielleicht keinen Unterschied, aber ich denke, in anderen Szenarien kann das der Fall sein.

Antwort1

Die Shell verwendet den pipe(2)Systemaufruf, um im Kernel einen begrenzten Puffer mit zwei Dateideskriptoren zu erstellen, von denen einer es Prozessen ermöglicht, in den Puffer zu schreiben, und der andere es Prozessen ermöglicht, aus dem Puffer zu lesen.

Betrachten Sie einen einfachen Fall:

$ p1 | p2

In diesem Fall erstellt die Shell konzeptionell die oben erwähnte Pipe, fork()s, das Kind verbindet seinen Standardausgabestrom mit dem Schreibende der Pipe, dann das Kind exec()s p1. Als nächstes fork()s die Shell wieder, das Kind verbindet seinen Standardeingabestrom mit dem Lesende der Pipe, dann das Kind exec()s p2. (Ich sagekonzeptionellweil Shells die Dinge zwar in unterschiedlicher Reihenfolge erledigen, die Idee aber dieselbe ist.)

An diesem Punkt werden p1und p2gleichzeitig ausgeführt. p1schreibt in die Pipe und der Kernel kopiert die geschriebenen Daten in den Puffer. p2liest aus der Pipe und der Kernel kopiert die gelesenen Daten aus dem Puffer. Wenn die Pipe voll ist, blockiert der Kernel p1seinen Aufruf von write(), bis p2etwas aus der Pipe gelesen wird und so Speicherplatz frei wird. Wenn die Pipe leer ist, blockiert der Kernel p2seinen Aufruf von , read()bis p1weitere Daten in die Pipe geschrieben werden.

Antwort2

Von den beiden Modellen, die Sie vorschlagen, kommt compute-pass-compute-pass dem am nächsten. Die Shell verbindet lediglich die Prozesse. Sie weiß nicht, was sie tun.

Außer, Die Reihenfolge der Ausführung ist nicht definiert. Sie werden effektiv gleichzeitig ausgeführt. Allerdings muss der linke Befehl Bytes ausgeben, bevor der rechte sie eingibt. Daten fließen von links nach rechts. Daten fließen vom ersten Befehl aus seinem Standardausgang, dann fließen sie in den Standardeingang des nächsten Prozesses, wo sie verarbeitet werden, dann kommen sie aus ihrem Standardausgang heraus, wo sie an einen anderen Prozess weitergeleitet werden können, usw., usw., usw.

Wenn keine Umleitung >, <, usw. erfolgt oder aus einer Datei gelesen wird, sieht es so aus.

         ┌───────────┐ ┌───────────┐ ┌─────────────┐
Terminal⇨│Process one│⇨│Process two│⇨│Process Three│⇨Terminal
         └───────────┘ └───────────┘ └─────────────┘

verwandte Informationen