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