Sind FIFO, Pipe & Unix Domain Socket im Linux-Kernel dasselbe?

30

Ich habe gehört, dass FIFOs Pipes heißen. Und sie haben genau die gleiche Semantik. Auf der anderen Seite denke ich, dass Unix Domain Socket Pipe ziemlich ähnlich ist (obwohl ich es nie benutzt habe). Ich frage mich also, ob sich alle auf dieselbe Implementierung im Linux-Kernel beziehen. Irgendeine Idee?

Justin
quelle
Durch die Antwort unten wurde mir klar, dass meine Frage mehrdeutig ist und schwer zu beantworten ist. Es ist wahrscheinlich, dass niemand so viele Details des Implementierungsmaterials im Kernel kennen kann (selbst für Kernelentwickler). Wenn jemand bestätigen kann, dass Unix-Domain-Socket, -Pipe und -FIFO alle die Daten puffern, die unter Linux im gemeinsamen Speicher gesendet werden, ist meine Frage gelöst. Nun ... teilweise gelöst.
Justin
FIFO = Named Pipes! = Pipes. FIFOs können wie ein Socket-Paar bidirektional sein. Normale Pipes sind unidirektional. Alle haben die Dateischnittstelle und Dateisemantik. Warum ist die Implementierung für Sie wichtig?
PSkocik
Ich weiß, dass Pipes kreisförmige Puffer sind und dass diese beim STREAMS-System eine gemeinsame Implementierung haben können, Linux verwendet jedoch standardmäßig keine STREAMS. Ich glaube, Linux codiert diese IPC-Kanäle hart. Ich habe aber keine Lust, nachzusehen. : D Warum gehst du nicht? Der Code ist öffentlich verfügbar.
PSkocik
Wenn alle dieselbe Implementierung verwenden, sollte ihre Effizienz nahe beieinander liegen. Und für mich ist der Kernel-Code zu schwer zu verstehen.
Justin

Antworten:

35

UNIX-Domain-Sockets und FIFO können einen Teil ihrer Implementierung gemeinsam nutzen, sind jedoch konzeptionell sehr unterschiedlich. FIFO arbeitet auf sehr niedrigem Niveau. Ein Prozess schreibt Bytes in die Pipe und ein anderer liest daraus. Ein UNIX-Domain-Socket hat dasselbe Verhalten wie ein TCP / IP-Socket.

Ein Socket ist bidirektional und kann von vielen Prozessen gleichzeitig verwendet werden. Ein Prozess kann viele Verbindungen auf demselben Socket akzeptieren und mehrere Clients gleichzeitig bedienen. Der Kernel liefert jedes Mal einen neuen Dateideskriptor connect(2)oder accept(2)wird auf dem Socket aufgerufen. Die Pakete gehen immer zum richtigen Prozess.
Bei einem FIFO wäre dies unmöglich. Für die bidirektionale Kommunikation benötigen Sie zwei FIFOs und für jeden Ihrer Clients ein FIFO-Paar. Es gibt keine Möglichkeit, selektiv zu schreiben oder zu lesen, da sie eine viel primitivere Art der Kommunikation darstellen.

Anonyme Pipes und FIFOs sind sehr ähnlich. Der Unterschied besteht darin, dass anonyme Pipes nicht als Dateien im Dateisystem vorhanden sind und daher von keinem Prozess verarbeitet werden können open(2). Sie werden von Prozessen verwendet, die sie mit einer anderen Methode gemeinsam nutzen. Wenn ein Prozess ein FIFO öffnet und dann beispielsweise ein ausführt, fork(2)erbt sein untergeordnetes Element seine Dateideskriptoren und unter anderem die Pipe.

Die UNIX-Domänensockets, anonymen Pipes und FIFOs sind ähnlich, da sie gemeinsam genutzte Speichersegmente verwenden. Die Details der Implementierung können von einem System zum anderen variieren, aber die Idee ist immer die gleiche: Fügen Sie denselben Teil des Speichers in zwei unterschiedliche Prozesse ein, um die gemeinsame Nutzung von Daten zu ermöglichen
( Bearbeiten: Dies wäre eine naheliegende Möglichkeit, dies zu implementieren, aber das ist nicht, wie es tatsächlich in Linux gemacht wird, das einfach den Kernel-Speicher für die Puffer verwendet (siehe Antwort von @ tjb63 unten).
Der Kernel verarbeitet dann die Systemaufrufe und abstrahiert den Mechanismus.

lgeorget
quelle
"UNIX-Domain-Sockets und FIFO haben möglicherweise einen Teil ihrer Implementierung gemeinsam" ... der Punkt ist "ein Teil von" ... Ich habe gerade festgestellt, dass meine Frage mehrdeutig und schwer zu beantworten ist. Es ist wahrscheinlich, dass niemand so viele Details darüber wissen kann, welche Teile sie im Kernel gemeinsam haben (selbst für Kernelentwickler). Dennoch ... kann jemand bestätigen, dass Unix-Domain-Socket, -Pipe und -FIFO alle die Daten puffern, die unter Linux im gemeinsamen Speicher gesendet werden? Wenn es bestätigt ist, ist meine Frage gelöst. Nun ... teilweise gelöst.
Justin
Ja, es gibt einen Puffer, der vom Kernel verwaltet wird. Zum Beispiel können Sie mit FIFOs den Schreiber töten und der Leser kann immer noch, was vor dem Tod des Schreibers in die Pipe geschickt wurde. Bei Sockets ist dies etwas komplizierter, da sie mit einem verbundenen Protokoll funktionieren. Wenn Sie jedoch beispielsweise ein int an den Socket senden und dann den Gültigkeitsbereich verlassen, sodass das int vom Senderstapel gelöscht wird, kann der Empfänger es weiterhin lesen. Es gibt also eindeutig irgendwo einen Puffer.
Dienstag,
Ich lese den Kommentar noch einmal und bin mir nicht sicher, ob ich hier klar bin. Lassen Sie es mich wissen, wenn noch etwas unklar ist.
Lgeorget
Ihr Kommentar ist mir klar.
Justin
7

Hier gibt es eine gute Diskussion darüber: http://www.slideshare.net/divyekapoor/linux-kernel-implementation-of-pipes-and-fifos

Soweit ich sehen kann, sind sowohl die Präsentationsfolien als auch die Quelle @ http://lxr.free-electrons.com/source/fs/pipe.c - fifos als Wrapper um Pipes implementiert, und die Pipes selbst sind implementiert über das virtuelle Dateisystem pipefs.

@lgeorget - Die Pipes scheinen den Kernel-Speicher für Puffer zwischen den Readern und den Writern zu verwenden. Sie verwenden nicht den 'Shared Memory' als solchen und kopieren den Speicher zwischen Benutzer- und Kernel-Adressräumen (z. B. pipe_readAufrufe pipe_iov_copy_to_user, die aufrufen __copy_to_user_inatomic(oder copy_to_user)). . __copy_to_user_inatomicAnrufe copy_user_generic, die auf mehrere ASM - Implementierungen sind.

tjb63
quelle
4

Ein "FIFO" und eine " Named Pipe" sind dasselbe - obwohl sie sich stark davon unterscheiden, wie eine Shell eine "Pipe" (|) zwischen zwei Befehlen in der Befehlszeile behandelt.

Eine Named Pipe (FIFO) ist eine einzelne "Datei", die von zwei Programmen gemeinsam genutzt wird, wobei einer darauf schreibt und der andere daraus liest ... Ein Socket ist andererseits eine "Verbindung" zwischen zwei "Dateien" - was auch sein kann Verwenden Sie ein Netzwerk und arbeiten Sie auf getrennten Computern - wobei ein Programm in eine "Datei" liest / schreibt und ein anderes Programm in eine andere "Datei" liest / schreibt ... Ich glaube nicht, dass sie sich so ähnlich sind ... Auf der anderen Seite beides Sockets und Named Pipes sowie Dateien, Geräte und symbolische Verknüpfungen verwenden alle Inodes und implementieren einige gemeinsame Funktionen (wie Lesen und Schreiben).

Baard Kopperud
quelle
1
Ja, Unix-Domain-Socket ist eine Art Socket, daher ähnelt seine API anderen Socket-APIs wie TCP oder UDP usw. Unix-Domain-Socket kann jedoch nur als "lokaler" IPC verwendet werden. Und die Art und Weise, wie Daten übertragen werden, ist in erster Linie eine Art FIFO & Pipe. Daher denke ich, dass es möglich ist, dass die API des Unix-Domain-Sockets nur eine weitere Verkapselung der identischen Implementierung ist. Wir verwenden sie also so, als wäre es ein Socket. Ich denke, es ist möglich, dass alle das gleiche interne Verhalten im Kernel haben ... Ich möchte bestätigen, ob es wahr ist oder nicht.
Justin
1

Ich glaube nicht, Justin. Wenn ich mich nicht irre, und ich bin es sehr wahrscheinlich, denke ich, dass FIFOs eine Datei auf der Festplatte verwenden und Unix-Domain-Sockets den Kernel-Speicher verwenden.

Als Ergänzung zu dem obigen Poster, in dem erwähnt wurde, dass Unix-Domain-Sockets bidirektional sind, ist dies nur bei Verwendung eines SOCK_STREAM-Sockets der Fall. SOCK_DGRAM Unix-Domain-Sockets sind tatsächlich unidirektional und können nur vom Code connect () zum Code bind () senden ().

Natürlich muss der Code, der connect () aufgerufen hat, bind () aufrufen, um einen eigenen Endpunkt zu erstellen, aber das hat nichts mit Ihrer Frage zu tun.

Anonym
quelle
3
Willkommen bei StackExchange und vielen Dank für die Veröffentlichung. Ein paar Anmerkungen ... 1) Wenn Sie sich "möglicherweise" irren, sollten Sie dies überprüfen, bevor Sie antworten. Diese Seite ist weder ein Forum noch ein Chat. 2) Vielen Dank für Ihre Präzision bei datagrammorientierten Sockets. 3) Es ist nicht erforderlich, etwas zu posten, das "nichts mit der Frage zu tun" hat. :)
lgeorget
1

Meine 2 Cent ... FIFO und UNIX-Socket sind beide bidirektional (ähnlich), aber Socket haben eine Sterntopologie, während ein FIFO nur eine Warteschlange ist (und sich daher nicht gegenseitig ersetzen kann).

**

char * myfifo = "/tmp/myfifo";
mkfifo(myfifo, 0666);
fd = open(myfifo, O_RDWR);   //so that you can read/write to it
 ...
write(fd, buff1, sizeof(buff1));  
getchar();//wait till some one reds this and writes something else
int sz=read(fd, buff1, sizeof(buff1));  //read that something**
Asif Bahrainwala
quelle
FIFO ist bidirektional?
jhfrontz