Unix/Linux では、パイプ、ソケット、共有メモリ、dbus、メッセージ キューなど、多くの IPC が提供されています。
それぞれに最も適したアプリケーションは何ですか?また、それらはどのように機能しますか?
ビッグセブンは次のとおりです。
FIFO、または名前付きパイプ
プレーン パイプとは異なり、関連のない 2 つのプロセスが FIFO を使用できます。コールしmkfifo(3)
ます。単方向。
双方向。ネットワーク通信用ですが、ローカルでも使用できます。異なるプロトコルに使用できます。TCP にはメッセージ境界がありません。コールしsocket(2)
ます。
OS は個別のメッセージを維持します。sys/msg.hを参照してください。
Signal は整数を別のプロセスに送信します。マルチスレッドとうまく噛み合わない。コールしkill(2)
ます。
トイレを待つ人々の列に似た、マルチプロセスまたはスレッドの同期メカニズム。sys/sem.hを参照してください。
独自の同時実行制御を行います。コールしshmget(2)
ます。
どちらか一方の方法を選択する際の決定要因の 1 つは、メッセージ境界の問題です。「メッセージ」は互いに分離していると思われるかもしれませんが、TCP やパイプのようなバイト ストリームはそうではありません。
エコー クライアントとサーバーのペアを考えてみましょう。クライアントは文字列を送信し、サーバーはそれを受信してすぐに送り返します。クライアントが「Hello」、「Hello」、「返事は?」と送信したとします。
バイト ストリーム プロトコルを使用すると、サーバーは「Hell」、「oHelloHow」、および「about an answer?」として受信できます。またはより現実的に「こんにちはこんにちは答えはどうですか?」. サーバーは、メッセージの境界がどこにあるのかわかりません。
古いトリックは、メッセージの長さを または に制限し、メッセージの長CHAR_MAX
さを最初にまたはUINT_MAX
で送信することに同意することです。したがって、受信側の場合は、最初にメッセージの長さを読み取る必要があります。これは、一度に 1 つのスレッドだけがメッセージの読み取りを行う必要があることも意味します。char
uint
UDP やメッセージ キューなどの個別のプロトコルでは、この問題を心配する必要はありませんが、ファイルや stdin/out のように動作するため、プログラムでバイト ストリームを処理する方が簡単です。
共有メモリは、その上に独自の通信スキームを構築するため、最も効率的ですが、多くの注意と同期が必要です。共有メモリを他のマシンに分散するためのソリューションも利用できます。
最近ではソケットが最も移植性がありますが、パイプよりも多くのオーバーヘッドが必要です。ソケットをローカルまたはネットワーク上で透過的に使用できることは、大きな利点です。
メッセージ キューとシグナルは、ハード リアルタイム アプリケーションには最適ですが、それほど柔軟ではありません。
これらのメソッドは、プロセス間の通信のために自然に作成されたものであり、プロセス内で複数のスレッドを使用すると、特にシグナルが複雑になる可能性があります。
簡単なベンチマークの Web ページを次に示します: https://sites.google.com/site/rikkus/sysv-ipc-vs-unix-pipes-vs-unix-sockets
私が知る限り、それぞれに利点があります。
多くのライブラリが、あるタイプのものを別のタイプの上に実装していることは注目に値します。
共有メモリは恐ろしいsysv共有メモリ関数を使用する必要はありません-mmap()を使用する方がはるかにエレガントです(名前を付けたい場合はtmpfs / dev/shmにファイルをmmapします;必要な場合はmmap/dev /zero匿名で継承するためにプロセスを実行しないようにフォークしました)。そうは言っても、問題を回避するためにプロセスを同期する必要があります。通常は、他のIPCメカニズムのいくつかを使用して、共有メモリ領域へのアクセスの同期を行います。