Sind Linux-Dienstprogramme bei der Ausführung von Pipe-Befehlen intelligent?

23

Ich habe gerade ein paar Befehle in einem Terminal ausgeführt und mich gefragt, ob Unix / Linux beim Ausführen von Pipe-Befehlen Verknüpfungen verwendet.

Nehmen wir zum Beispiel an, ich habe eine Datei mit einer Million Zeilen, von denen die ersten 10 enthalten hello world. Wenn Sie den Befehl ausführen, grep "hello world" file | headstoppt der erste Befehl, sobald er 10 Zeilen findet, oder durchsucht er zuerst die gesamte Datei?

Verärgerte Ziege
quelle
2
Deshalb hat Gnu Grep das -mArgument.
Paul Tomblin
3
Das Terminal hat nichts damit zu tun. Weitergeleitete Befehle werden von der Shell verwaltet.
Keith Thompson
@KeithThompson Entschuldigen Sie meine Unwissenheit, ich bin mir nicht ganz sicher, ob ich es Terminal, Shell oder Kommandozeile nennen soll. Fühlen Sie sich frei, Änderungen an meiner Frage vorzuschlagen :)
DisgruntledGoat

Antworten:

30

Art von. Die Shell hat keine Ahnung, was die von Ihnen ausgeführten Befehle bewirken, sie verbindet lediglich den Ausgang des einen mit dem Eingang des anderen.

Wenn grepmehr als 10 Zeilen mit der Aufschrift "Hallo Welt" gefunden headwerden, werden alle 10 gewünschten Zeilen angezeigt, und die Pipe wird geschlossen. Dadurch wird grepSIGPIPE beendet, sodass keine sehr großen Dateien weiter gescannt werden müssen.

Psusi
quelle
2
Also denke ich, dass grep aufgrund der Rennbedingungen vielleicht schon das 11. oder 12. Muster gelesen hat, aber wahrscheinlich nicht das 100 Tausendste?
Benutzer unbekannt
3
Dies hängt zum Teil von der Länge der Zeilen und der Größe des Pipe-Puffers ab, aber die kurze Antwort lautet, dass grep eine einigermaßen begrenzte Menge zusätzlicher Daten liest, bevor es getötet wird.
dmckee
1
@userunknown, genau.
Psusi
Cool, ich wusste nicht, dass das passiert ist. Ich dachte, ich grepwürde weiterhin Ausgaben in eine Leere senden, ähnlich wie/dev/null
Izkata
15

Wenn ein Programm versucht, in eine Pipe zu schreiben und kein Prozess aus dieser Pipe gelesen wird, empfängt das Schreibprogramm ein SIGPIPE- Signal. Die Standardaktion beim Empfang von SIGPIPE ist das Beenden des Programms. Ein Programm kann das SIGPIPE-Signal ignorieren. In diesem Fall gibt der Schreibvorgang einen Fehler zurück ( EPIPE).

In Ihrem Beispiel sehen Sie in der folgenden Zeitleiste, was passiert:

  • Die Befehle grepund headwerden parallel gestartet.
  • grep Liest eine Eingabe und beginnt sie zu verarbeiten.
  • grepProduziert irgendwann einen ersten Teil der Ausgabe.
  • head liest den ersten Block und schreibt ihn aus.
  • Vorausgesetzt, dass nach den ersten 10 Übereinstimmungen genügend Zeilen vorhanden sind (andernfalls wird grepmöglicherweise zuerst Schluss gemacht), headwird möglicherweise die gewünschte Anzahl von Zeilen ausgedruckt. An dieser Stelle wird beendet head.
  • Abhängig von der relativen Geschwindigkeit des grepund head-Vorgangs grephaben sich möglicherweise einige Daten angesammelt und wurden noch nicht ausgedruckt. Beim headBeenden werden grepmöglicherweise Eingaben gelesen oder es wird eine interne Verarbeitung durchgeführt. In diesem Fall wird die Verarbeitung fortgesetzt.
  • Bald grepwerden die Daten, die es verarbeitet, ausgeschrieben. An diesem Punkt erhält es ein SIEGEL und stirbt.

Es ist wahrscheinlich, dass grepein wenig mehr Eingaben verarbeitet werden als unbedingt erforderlich, normalerweise jedoch nur ein paar Kilobyte:

  • headLiest normalerweise Blöcke von einigen Kilobyte ein (da dies effizienter ist als das Ausgeben eines readSystemaufrufs für jedes Byte - dieses Verhalten wird als Pufferung bezeichnet), sodass der Rest des letzten Blocks nach der gewünschten letzten Zeile verworfen wird.
  • Möglicherweise werden einige Daten übertragen, da Pipes über einen vom Kernel verwalteten Puffer verfügen (häufig 512 Byte). Diese Daten werden verworfen.
  • grepMöglicherweise haben sich einige Daten angesammelt, die bereit sind, ein Ausgabeabschnitt zu werden (erneutes Puffern). Es wird SIGPIPE empfangen, wenn es versucht, seinen Ausgabepuffer zu leeren.

Alles in allem ist das System präzise ausgelegt, damit sich Filterdienstprogramme auf natürliche Weise effizient verhalten. Programme, die weiterarbeiten müssen, wenn ihr Ausgangskanal ausfällt, müssen das SIGPIPE-Signal ignorieren.

Gilles 'SO - hör auf böse zu sein'
quelle
3

Die Pipeline funktioniert folgendermaßen: Sie führt zuerst den ersten Befehl und dann in Ihrem Fall den zweiten Befehl aus.

Das heißt, lassen Sie uns A|Bden Befehl geben. Dann ist es ungewiss, ob Aoder ob Berst begonnen wird. Sie starten möglicherweise genau zur gleichen Zeit, wenn mehrere CPUs vorhanden sind. Eine Pipe kann eine undefinierte, aber begrenzte Datenmenge enthalten.

Wenn B versucht, aus der Pipe zu lesen, aber keine Daten verfügbar sind, Bwird gewartet, bis die Daten eingehen. Wenn Sie Bvon Beiner Festplatte gelesen haben , besteht möglicherweise dasselbe Problem und Sie müssen warten, bis der Lesevorgang für die Festplatte abgeschlossen ist . Eine nähere Analogie wäre das Lesen von einer Tastatur. Dort Bmüsste man warten, bis ein Benutzer eingibt. In all diesen Fällen hat B eine "Lese" -Operation gestartet und muss warten, bis sie beendet ist. Wenn Bjedoch ein Befehl so ist, dass er nur eine Teilausgabe benötigt, wird dieser Anach einem bestimmten Punkt, an dem der BEingangspegel erreicht ist A, von SIGPIPE beendet

Wenn Aversucht wird, in die Pipe zu schreiben, und die Pipe voll ist, Amuss abgewartet werden, bis etwas Platz in der Pipe frei wird. Akönnte das gleiche Problem haben, wenn es in ein Terminal schreibt. Ein Terminal verfügt über eine Flusskontrolle und kann das Datentempo verringern. In jedem Fall hat to Aeine "Schreib" -Operation gestartet und wartet, bis die Schreiboperation beendet ist.

Aund Bverhalten sich wie Co-Prozesse, obwohl nicht alle Co-Prozesse mit einer Pipe kommunizieren. Keiner hat die volle Kontrolle über den anderen.

harish.venkat
quelle
1
Die Frage ist: "Was würde A tun, wenn B seine Seite des Rohrs schließt?"
Enzotib
2
Wäre das nicht eine "kaputte Pfeife"?
Patkos Csaba
1
Wenn ein Programm versucht, von einer geschlossenen Pipe zu lesen / zu schreiben (z. B. zu headbeenden), tritt im Programm ein SIGPIPE-Signal auf, und das Standardverhalten ist das Beenden.
Lekensteyn
Wie genau beantwortet dies die Frage? Es scheint, dass die Antwort von Psusi kürzer und auf den Punkt gebracht ist.
jw013,
1

grephat keine direkte Kontrolle über die Pipe (sie empfängt nur Daten) und die Pipe hat keine direkte Kontrolle über grep(sie sendet nur Daten) ...

Was grepoder ein anderes Programm tut, hängt ganz von der internen Logik dieses Programms ab. Wenn Sie sagen , grepüber Kommandozeilenoptionen einen früher machen austritt wenn gefunden , dann wird es, sonst wird es zu sehr tuckert auf der Datei für das Muster am Ende der Suche ...

Das Terminal ist ebenfalls ziemlich unabhängig von den internen Abläufen grepund den shellLeitungsaktionen des Terminals. Das Terminal ist im Grunde genommen nur eine Startrampe und eine Ausgabeanzeige.

Peter.O
quelle