Vergleich von Unix / Linux IPC

78

Unix / Linux bietet viele IPCs an: Pipes, Sockets, Shared Memory, DBus, Message Queues ...

Was sind die jeweils am besten geeigneten Anwendungen und wie funktionieren sie?

user27424
quelle
1
dbus wird zusätzlich zu den anderen IPC-Typen implementiert: Unix-Domain-Sockets, TCP / IP und Pipes reichen weit ...
Richter Maygarden

Antworten:

100

Unix IPC

Hier sind die großen Sieben:

  1. Rohr

    Nützlich nur bei Prozessen, die als Eltern / Kind zusammenhängen. Rufen Sie an pipe(2)und fork(2). Unidirektional.

  2. FIFO oder Named Pipe

    Zwei nicht verwandte Prozesse können FIFO im Gegensatz zu Plain Pipe verwenden. Rufen Sie an mkfifo(3). Unidirektional.

  3. Socket und Unix Domain Socket

    Bidirektional. Gemeint für die Netzwerkkommunikation, kann aber auch lokal verwendet werden. Kann für verschiedene Protokolle verwendet werden. Es gibt keine Nachrichtengrenze für TCP. Rufen Sie an socket(2).

  4. Nachrichtenwarteschlange

    Das Betriebssystem verwaltet eine diskrete Nachricht. Siehe sys / msg.h .

  5. Signal

    Das Signal sendet eine Ganzzahl an einen anderen Prozess. Passt nicht gut zu Multithreads. Rufen Sie an kill(2).

  6. Semaphor

    Ein Synchronisationsmechanismus für mehrere Prozesse oder Threads, ähnlich einer Warteschlange von Personen, die auf das Badezimmer warten. Siehe sys / sem.h .

  7. Geteilte Erinnerung

    Führen Sie Ihre eigene Parallelitätskontrolle durch. Rufen Sie an shmget(2).

Problem mit der Nachrichtengrenze

Ein entscheidender Faktor bei der Auswahl einer Methode gegenüber der anderen ist das Problem der Nachrichtengrenze. Sie können erwarten, dass "Nachrichten" voneinander diskret sind, dies gilt jedoch nicht für Byte-Streams wie TCP oder Pipe.

Betrachten Sie ein Paar Echo-Client und -Server. Der Client sendet eine Zeichenfolge, der Server empfängt sie und sendet sie sofort zurück. Angenommen, der Client sendet "Hallo", "Hallo" und "Wie wäre es mit einer Antwort?".

Mit Byte-Stream-Protokollen kann der Server "Hell", "oHelloHow" und "about a answer?" Empfangen. oder realistischer "Hallo Hallo, wie wäre es mit einer Antwort?". Der Server hat keine Ahnung, wo sich die Nachrichtengrenze befindet.

Ein uralter Trick besteht darin, die Nachrichtenlänge auf CHAR_MAXoder zu beschränken UINT_MAXund zuzustimmen, die Nachrichtenlänge zuerst in charoder zu senden uint. Wenn Sie also auf der Empfangsseite sind, müssen Sie zuerst die Nachrichtenlänge lesen. Dies bedeutet auch, dass jeweils nur ein Thread die Nachricht lesen sollte.

Mit diskreten Protokollen wie UDP oder Nachrichtenwarteschlangen müssen Sie sich nicht um dieses Problem kümmern, aber programmgesteuerte Byte-Streams sind einfacher zu handhaben, da sie sich wie Dateien und stdin / out verhalten.

Eugene Yokota
quelle
Ich denke, Sie könnten dort Semaphore einfügen, aber ich sehe es eher als Parallelitätswerkzeug als als Interprozesskommunikationswerkzeug.
Eugene Yokota
2
Übrigens können Sie Dateideskriptoren über einen Unix Domain Socket [ linux.die.net/man/7/unix]
senden
2
Eine kleine nit: pipe (2) kann auch in Geschwisterprozessen verwendet werden - zum Beispiel ist die Shell allen Prozessen in der Pipeline übergeordnet.
Hudson
5
Beachten Sie, dass Sie nachrichtenorientierte Unix-Domain-Sockets haben können. Im Gegensatz zu Internet sind sie zuverlässig.
Tom Anderson
2
Gibt es einen Benchmark oder einen qualitativen Leistungsvergleich dieser Ansätze?
Kakyo
17

Shared Memory kann am effizientesten sein, da Sie darauf Ihr eigenes Kommunikationsschema aufbauen. Es erfordert jedoch viel Sorgfalt und Synchronisierung. Es sind Lösungen verfügbar, um gemeinsam genutzten Speicher auf andere Computer zu verteilen.

Steckdosen sind heutzutage am tragbarsten, erfordern jedoch mehr Overhead als Rohre. Die Möglichkeit, Sockets lokal oder über ein Netzwerk transparent zu verwenden, ist ein großer Bonus.

Nachrichtenwarteschlangen und -signale eignen sich hervorragend für harte Echtzeitanwendungen, sind jedoch nicht so flexibel.

Diese Methoden wurden natürlich für die Kommunikation zwischen Prozessen entwickelt, und die Verwendung mehrerer Threads innerhalb eines Prozesses kann die Dinge komplizieren - insbesondere bei Signalen.

Richter Maygarden
quelle
Nach meiner Erfahrung können benannte Rohre genauso schnell sein und sind sicherer als fast jede andere Methode.
Erik Aronesty
10

Hier ist eine Webseite mit einem einfachen Benchmark: https://sites.google.com/site/rikkus/sysv-ipc-vs-unix-pipes-vs-unix-sockets

Soweit ich das beurteilen kann, hat jeder seine Vorteile:

  • Pipe I / O ist am schnellsten, benötigt jedoch eine Eltern-Kind-Beziehung, um zu funktionieren.
  • Sysv IPC hat eine definierte Nachrichtengrenze und kann unterschiedliche Prozesse lokal verbinden.
  • UNIX-Sockets können unterschiedliche Prozesse lokal verbinden und haben eine höhere Bandbreite, aber keine inhärenten Nachrichtengrenzen.
  • TCP / IP-Sockets können alle Prozesse verbinden, auch über das Netzwerk, haben jedoch einen höheren Overhead und keine inhärenten Nachrichtengrenzen.
Phillip Whelan
quelle
vielleicht das. sites.google.com/site/rikkus/…
scythargon
Wie vergleiche ich dbus mit anderen?
BЈовић
DBUS verwendet einen oder mehrere dieser Mechanismen. Es gibt einige langjährige Arbeiten an ihrem eigenen IPC-Mechanismus namens DBUS1 (oder KDBUS ...), der jedoch noch nicht in den Mainline-Kernel integriert wurde.
Phillip Whelan
8

Es ist erwähnenswert, dass viele Bibliotheken eine Art von Dingen übereinander implementieren.

Der gemeinsam genutzte Speicher muss nicht die schrecklichen Funktionen des gemeinsam genutzten sysv-Speichers verwenden - es ist viel eleganter, mmap () zu verwenden (mmap eine Datei in einem tmpfs / dev / shm, wenn Sie den Namen haben möchten; mmap / dev / zero, wenn Sie möchten gabelte nicht ausgeführte Prozesse, um sie anonym zu erben). Trotzdem müssen Ihre Prozesse immer noch synchronisiert werden, um Probleme zu vermeiden. In der Regel werden einige der anderen IPC-Mechanismen verwendet, um den Zugriff auf einen gemeinsam genutzten Speicherbereich zu synchronisieren.

MarkR
quelle
Ich hatte noch nie von mmaping / dev / zero gehört. Genial! Sie erwähnen, dass es nur für untergeordnete Elemente freigegeben werden kann. Können Sie den von Ihnen verwendeten Dateideskriptor mithilfe von cmsg / SCM_RIGHTS über einen Unix-Domain-Socket an einen nicht verwandten Prozess senden und dort eine gemeinsame Zuordnung erhalten? Oder ist es das Mapping, das Sie erben, nicht der Dateideskriptor? Selbst wenn es funktioniert, benötigen Sie den Socket noch irgendwo im Dateisystem, um dies zu tun. Selbst wenn die Zuordnung anonym ist, ist der Socket, der zum Einrichten verwendet wird, dies nicht. Guh. IPC ist schwer. Gehen wir einkaufen!
Tom Anderson
mmaping / dev / zero wird tatsächlich von einigen Arten der Speicherzuweisung verwendet. Der Vorteil ist jedoch, dass MAP_SHARED bei Verwendung mit Ihren untergeordneten Prozessen von fork () gemeinsam genutzt wird (normalerweise wird der Speicher logisch kopiert). Können Sie es mit einem nicht verwandten Prozess teilen? Das glaube ich nicht. Ich vermute, dass der Aufruf von mmap () freigegeben werden muss, nicht der Dateideskriptor.
MarkR