Frage

Weiß jemand, wie Bash mit dem Senden von Daten über Pipes umgeht?

cat file.txt | tail -20

Gibt dieser Befehl den gesamten Inhalt von file.txt in einen Puffer aus, der dann von tail gelesen wird?Oder gibt dieser Befehl beispielsweise den Inhalt von file.txt Zeile für Zeile aus und hält dann bei jeder Zeile an, damit tail ihn verarbeitet, und fragt dann nach weiteren Daten?

Der Grund, warum ich frage, ist, dass ich ein Programm auf einem eingebetteten Gerät schreibe, das im Grunde eine Folge von Operationen an einem Datenblock ausführt, wobei die Ausgabe einer Operation als Eingabe der nächsten Operation gesendet wird.Ich würde gerne wissen, wie Linux (Bash) damit umgeht, also geben Sie mir bitte eine allgemeine Antwort, nicht speziell, was passiert, wenn ich „cat file.txt | tail -20“ ausführe.

Vielen Dank im Voraus für Ihre Antworten!

BEARBEITEN:Shog9 hat auf einen relevanten Wikipedia-Artikel hingewiesen. Dies hat mich nicht direkt zu dem Artikel geführt, aber es hat mir dabei geholfen, Folgendes zu finden: http://en.wikipedia.org/wiki/Pipeline_%28Unix%29#Implementation welches die Informationen hatte, die ich suchte.


Es tut mir leid, dass ich mich nicht klar ausgedrückt habe.Natürlich verwenden Sie eine Pipe und natürlich verwenden Sie stdin und stdout der jeweiligen Teile des Befehls.Ich hatte angenommen, dass das zu offensichtlich sei, um es auszudrücken.

Was ich frage ist, wie das gehandhabt/umgesetzt wird.Wie werden Daten von stdin an stdout gesendet, da nicht beide Programme gleichzeitig ausgeführt werden können?Was passiert, wenn das erste Programm deutlich schneller Daten generiert als das zweite Programm?Führt das System einfach den ersten Befehl aus, bis er entweder beendet wird oder sein Standardausgabepuffer voll ist, und fährt dann mit dem nächsten Programm usw. in einer Schleife fort, bis keine Daten mehr verarbeitet werden müssen, oder gibt es einen komplizierteren Mechanismus? ?

War es hilfreich?

Lösung

Ich beschloss, eine etwas detailliertere Erklärung zu schreiben.

Die „Magie“ liegt hier im Betriebssystem.Beide Programme starten ungefähr zur gleichen Zeit und werden gleichzeitig (das Betriebssystem weist ihnen Zeitabschnitte auf dem Prozessor zur Ausführung zu) wie jeder andere gleichzeitig laufende Prozess auf Ihrem Computer ausgeführt (einschließlich der Terminalanwendung und des Kernels). .Bevor also Daten übergeben werden, führen die Prozesse die erforderliche Initialisierung durch.In Ihrem Beispiel analysiert tail das Argument „-20“ und cat analysiert das Argument „file.txt“ und öffnet die Datei.Irgendwann kommt tail an den Punkt, an dem es Eingaben benötigt, und teilt dem Betriebssystem mit, dass es auf Eingaben wartet.Zu einem anderen Zeitpunkt (entweder davor oder danach, es spielt keine Rolle) beginnt cat, Daten mithilfe von stdout an das Betriebssystem zu übergeben.Dies geht in einen Puffer im Betriebssystem.Wenn tail das nächste Mal eine Zeitscheibe auf dem Prozessor erhält, nachdem einige Daten von cat in den Puffer gelegt wurden, ruft es einen Teil dieser Daten (oder alle) ab, die den Puffer im Betriebssystem verlassen.Wenn der Puffer leer ist, muss tail irgendwann warten, bis cat weitere Daten ausgibt.Wenn cat Daten viel schneller ausgibt als tail sie verarbeitet, wird der Puffer erweitert.cat ist schließlich mit der Datenausgabe fertig, Tail wird jedoch weiterhin verarbeitet, sodass cat geschlossen wird und Tail alle verbleibenden Daten im Puffer verarbeitet.Das Betriebssystem signalisiert Tail, wenn keine Daten mehr mit einem EOF eingehen.Tail wird die restlichen Daten verarbeiten.In diesem Fall empfängt tail wahrscheinlich nur alle Daten in einem Ringpuffer mit 20 Zeilen, und wenn ihm vom Betriebssystem signalisiert wird, dass keine weiteren Daten mehr eingehen, speichert es die letzten zwanzig Zeilen in seinem eigenen Standardout wird einfach im Terminal angezeigt.Da tail ein viel einfacheres Programm als cat ist, wird es wahrscheinlich die meiste Zeit damit verbringen, darauf zu warten, dass cat Daten in den Puffer legt.

Auf einem System mit mehreren Prozessoren teilen sich die beiden Programme nicht nur abwechselnde Zeitabschnitte auf demselben Prozessorkern, sondern laufen wahrscheinlich gleichzeitig auf separaten Kernen.

Um etwas detaillierter zu sein: Wenn Sie eine Art Prozessmonitor (betriebssystemspezifisch) wie „top“ unter Linux öffnen, sehen Sie eine ganze Liste laufender Prozesse, von denen die meisten effektiv 0 % des Prozessors verbrauchen.Die meisten Anwendungen verbringen die meiste Zeit damit, nichts zu tun, es sei denn, sie verarbeiten Daten.Das ist gut, denn so können andere Prozesse je nach Bedarf ungehinderten Zugriff auf den Prozessor haben.Dies wird grundsätzlich auf drei Arten erreicht.Ein Prozess könnte zu einer Anweisung im Sleep(n)-Stil gelangen, bei der er den Kernel grundsätzlich anweist, n Millisekunden zu warten, bevor er ihm eine weitere Zeitscheibe zum Arbeiten gibt.Am häufigsten muss ein Programm auf etwas von einem anderen Programm warten, z. B. darauf, dass „tail“ darauf wartet, dass weitere Daten in den Puffer gelangen.In diesem Fall wird das Betriebssystem den Prozess aktivieren, wenn mehr Daten verfügbar sind.Schließlich kann der Kernel einen Prozess mitten in der Ausführung vorwegnehmen und so anderen Prozessen einige Zeitscheiben des Prozessors zur Verfügung stellen.„cat“ und „tail“ sind einfache Programme.In diesem Beispiel verbringt tail die meiste Zeit damit, auf weitere Daten im Puffer zu warten, und cat verbringt die meiste Zeit damit, darauf zu warten, dass das Betriebssystem Daten von der Festplatte abruft.Der Engpass ist die Geschwindigkeit (oder Langsamkeit) des physischen Mediums, auf dem die Datei gespeichert ist.Die spürbare Verzögerung, die Sie möglicherweise feststellen, wenn Sie diesen Befehl zum ersten Mal ausführen, ist die Zeit, die die Leseköpfe auf dem Festplattenlaufwerk benötigen, um die Position auf der Festplatte zu finden, an der sich „file.txt“ befindet.Wenn Sie den Befehl ein zweites Mal ausführen, wird das Betriebssystem wahrscheinlich den Inhalt von „file.txt“ im Speicher zwischenspeichern, und Sie werden wahrscheinlich keine wahrnehmbare Verzögerung feststellen (es sei denn, „file.txt“ ist sehr groß oder die Datei wird nicht mehr zwischengespeichert). .)

Die meisten Vorgänge, die Sie auf Ihrem Computer ausführen, sind E/A-gebunden, das heißt, Sie warten normalerweise darauf, dass Daten von Ihrer Festplatte, einem Netzwerkgerät usw. kommen.

Andere Tipps

Shog9 hat bereits auf den Wikipedia-Artikel verwiesen, aber der Abschnitt zur Umsetzung hat die Details, die Sie wollen.Die grundlegende Implementierung ist ein begrenzter Puffer.

cat gibt die Daten einfach an den Standardausgang aus, der zufällig an den Standardeingang von tail umgeleitet wird.Dies ist in der Manpage von Bash zu sehen.

Mit anderen Worten, es wird nicht pausiert, tail liest nur vom Standardeingang und cat schreibt nur vom Standardausgang.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top