Rohre verstehen

21

Als ich gerade Pipe in Bash verwendet habe, habe ich nicht mehr darüber nachgedacht. Wenn ich jedoch ein C-Codebeispiel mit system call pipe () zusammen mit fork () lese, frage ich mich, wie ich Pipes verstehen kann, einschließlich anonymer Pipes und Named Pipes.

Es ist oft zu hören, dass "alles in Linux / Unix eine Datei ist". Ich frage mich, ob eine Pipe tatsächlich eine Datei ist, so dass ein Teil, den sie verbindet, in die Pipe-Datei schreibt und der andere Teil aus der Pipe-Datei liest. Wenn ja, wo wird die Pipe-Datei für eine anonyme Pipe erstellt? In / tmp, / dev oder ...?

Anhand von Beispielen für Named Pipes habe ich jedoch auch festgestellt, dass die Verwendung von Pipes gegenüber der expliziten Verwendung temporärer Dateien einen Raum- und Zeitvorteil hat, wahrscheinlich, weil keine Dateien an der Implementierung von Pipes beteiligt sind. Außerdem scheinen Pipes keine Daten wie Dateien zu speichern. Ich bezweifle also, dass eine Pipe tatsächlich eine Datei ist.

Tim
quelle

Antworten:

23

In Bezug auf Ihre Leistungsfrage sind Pipes effizienter als Dateien, da keine Datenträger-E / A-Vorgänge erforderlich sind. So cmd1 | cmd2ist effizienter als cmd1 > tmpfile; cmd2 < tmpfile(dies kann nicht wahr sein , wenn tmpfileauf einer RAM - Disk oder einem anderen Speichergerät als Named Pipe gesichert wird, aber wenn es sich um eine Named Pipe ist, cmd1sollte im Hintergrund ausgeführt werden , da sein Ausgang blockieren kann , wenn das Rohr voll ist ). Wenn Sie das Ergebnis von cmd1benötigen und dennoch seine Ausgabe an senden müssen cmd2, sollten Sie cmd1 | tee tmpfile | cmd2zulassen cmd1und cmd2parallel ausführen, um Festplattenlesevorgänge von zu vermeiden cmd2.

Named Pipes sind nützlich, wenn viele Prozesse dieselbe Pipe lesen / schreiben. Sie können auch nützlich sein, wenn ein Programm nicht für die Verwendung von stdin / stdout entwickelt wurde, da sein E / A Dateien verwenden muss . Ich habe Dateien kursiv geschrieben, weil Named Pipes aus Speichersicht keine Dateien sind, da sie sich im Speicher befinden und eine feste Puffergröße haben, auch wenn sie einen Dateisystemeintrag haben (zu Referenzzwecken). Andere Dinge in UNIX haben Dateisystemeinträge, ohne Dateien zu sein: man denke nur an /dev/nulloder andere Einträge in /devoder /proc.

Da Pipes (mit und ohne Namen) eine feste Puffergröße haben, können Lese- / Schreibvorgänge blockiert werden, wodurch der Lese- / Schreibvorgang in den IOWait-Status versetzt wird. Wann erhalten Sie eine EOF, wenn Sie aus einem Speicherpuffer lesen? Regeln zu diesem Verhalten sind gut definiert und können im Mann gefunden werden.

Eine Sache, die Sie mit Pipes (benannt und unbenannt) nicht machen können, ist das Zurücksuchen in den Daten. Da sie mit einem Speicherpuffer implementiert werden, ist dies verständlich.

Über "everything in Linux/Unix is a file"stimme ich nicht zu. Named Pipes haben Dateisystemeinträge, sind aber nicht genau Datei. Unbenannte Pipes haben keine Dateisystemeinträge (außer vielleicht in /proc). Die meisten E / A-Vorgänge unter UNIX werden jedoch mit der Lese- / Schreibfunktion ausgeführt, für die ein Dateideskriptor erforderlich ist , einschließlich einer unbenannten Pipe (und eines Sockets). Ich denke nicht, dass wir das sagen können "everything in Linux/Unix is a file", aber wir können das mit Sicherheit sagen "most IO in Linux/Unix is done using a file descriptor".

jfg956
quelle
Vielen Dank! Sind die beiden Befehle durch eine parallel verlaufende Pipe verbunden, anstatt dass die zweite nach dem ersten Ende ausgeführt wird?
Tim
Ja, die 2 Befehle werden parallel ausgeführt. Wenn sie nicht wären und der 1. Ausgang mehr als der Puffer wäre, wäre er gesperrt. Sie können es versuchen, indem Sie cmd1 > fifound cmd2 < fifoin 2 verschiedenen Shells ausführen und die Named Pipe mit erstellen mkfifo fifo.
jfg956
Ein weiterer Test, den Sie durchführen können, besteht darin, zu töten, cmd2während das Programm cmd1noch ausgeführt cmd1wird. Wahrscheinlich wird nicht mehr gemeldet, dass eine Rohrmitteilung gebrochen ist.
jfg956
Vielen Dank! was meinst du damit wäre gesperrt? Bedeutet dies, dass das Datum im Stream nach dem Block verloren geht?
Tim
2
Daten gehen nicht verloren. Wenn der Pipe-Puffer voll ist, wird cmd1das Schreiben in die Pipe nur zurückgegeben, wenn cmd2Daten aus der Pipe gelesen wurden. Auf die gleiche Weise wird cmd2das Lesen aus einer Pipe blockiert, wenn der Puffer leer ist, bis cmd1in die Pipe geschrieben wird.
jfg956
4

Zwei der grundlegenden Grundlagen der UNIX-Philosophie sind:

  1. Um kleine Programme zu erstellen, die eine Sache gut machen.
  2. und erwarten, dass die Ausgabe jedes Programms die Eingabe für ein anderes,
    noch unbekanntes Programm wird.

    Mithilfe von Pipes können Sie die Effekte dieser beiden Entwurfsgrundlagen nutzen
    , um äußerst leistungsfähige Befehlsketten zu erstellen, mit denen Sie das gewünschte Ergebnis erzielen.

    Die meisten Befehlszeilenprogramme, die mit Dateien arbeiten, können auch Standardeingaben (Eingaben über die Tastatur) und Standardausgaben (Drucken auf dem
    Bildschirm) akzeptieren .

    Einige Befehle können nur innerhalb einer Pipe ausgeführt werden und können nicht direkt auf Dateien angewendet werden.

    zum Beispiel trBefehl

  ls -C | tr 'a-z' 'A-Z'
    cmd1 | cmd2
  • Sendet STDOUT von cmd1 an STDIN von cmd2 anstelle des Bildschirms.

  • STDERR wird nicht über Pipes weitergeleitet.

    Kurz gesagt Pipes is character (|)kann Befehle verbinden.

    Jeder Befehl, der in STDOUT schreibt, kann auf der linken Seite der Pipe verwendet werden.

       ls - /etc | less 

    Jeder Befehl, der aus STDIN liest, kann auf der rechten Seite einer Pipe verwendet werden.

       echo "test print" | lpr 

    Eine herkömmliche Pipe ist "unbenannt", da sie anonym existiert und nur so lange besteht, wie der Prozess ausgeführt wird. Eine Named Pipe ist systempersistent und existiert über die Lebensdauer des Prozesses hinaus. Sie muss gelöscht werden, sobald sie nicht mehr verwendet wird. Prozesse werden im Allgemeinen an die Named Pipe angehängt (normalerweise als Datei), um die Interprozesskommunikation (IPC) durchzuführen.

Quelle: http://en.wikipedia.org/wiki/Named_pipe

mr_eclair
quelle
3

Ergänzend zu den anderen Antworten ...

stdin und stdout sind Dateideskriptoren und werden wie Dateien gelesen und geschrieben. Daher können Sie dies tun echo hi | grep hi, und es wird die Standardausgabe des Echos durch eine Pipe ersetzen und die Standardausgabe von grep an das andere Ende dieser Pipe setzen.

user606723
quelle
1

Alles ist eine Datei.

Wenn wir den Ausdruck zu wörtlich nehmen, erhalten wir die Bedeutung „wir haben nur Dateien und sonst nichts“. Dies ist nicht die richtige Interpretation, also was ist.

Wenn wir "Alles ist eine Datei" sagen, sagen wir nicht, dass alles auf einer Festplatte gespeichert ist. Wir sagen, dass alles wie eine Datei aussieht, gelesen und geschrieben werden kann.

Wenn unter Unix eine Datei oder eine Nicht-Datei geöffnet ist, kann sie wie eine Datei behandelt werden. Nicht alle Dateien unterstützen jedoch alle Operationen. Beispielsweise unterstützen einige Dateien (die keine Dateien sind) keine Suche: Sie müssen der Reihe nach gelesen / geschrieben werden (dies gilt für Pipes und Sockets).

Alles hat einen Dateinamen (auf einigen Systemen: zB Debian Gnu / Linux und vielen anderen Gnu / Linux).

  • Alle geöffneten Dateien erhalten einen Dateinamen. Sehen/proc/self/fd/…
  • Netzwerk-Sockets können mit einem Dateinamen geöffnet werden, siehe /dev/tcp
    zcat </dev/tcp/towel.blinkenlights.nl/23
Strg-Alt-Delor
quelle
Dieser letzte Teil gilt nur für Systeme mit einem /procDateisystem und für Systeme (oder Shells), die eine /dev/tcpDateistruktur bereitstellen .
Kusalananda