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?
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?
Antworten:
Hier sind die großen Sieben:
Nützlich nur bei Prozessen, die als Eltern / Kind zusammenhängen. Rufen Sie an pipe(2)
und fork(2)
. Unidirektional.
FIFO oder Named Pipe
Zwei nicht verwandte Prozesse können FIFO im Gegensatz zu Plain Pipe verwenden. Rufen Sie an mkfifo(3)
. Unidirektional.
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)
.
Das Betriebssystem verwaltet eine diskrete Nachricht. Siehe sys / msg.h .
Das Signal sendet eine Ganzzahl an einen anderen Prozess. Passt nicht gut zu Multithreads. Rufen Sie an kill(2)
.
Ein Synchronisationsmechanismus für mehrere Prozesse oder Threads, ähnlich einer Warteschlange von Personen, die auf das Badezimmer warten. Siehe sys / sem.h .
Führen Sie Ihre eigene Parallelitätskontrolle durch. Rufen Sie an shmget(2)
.
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_MAX
oder zu beschränken UINT_MAX
und zuzustimmen, die Nachrichtenlänge zuerst in char
oder 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.
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.
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:
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.