web-dev-qa-db-ja.com

Unix / Linuxの比較IPC

Unix/Linuxには、パイプ、ソケット、共有メモリ、dbus、メッセージキューなど、多くのIPCが用意されています。

それぞれに最適なアプリケーションとは何ですか?

76
user27424

Unix IPC

ビッグ7は次のとおりです。

  1. パイプ

    親/子として関連するプロセス間でのみ有用です。 pipe(2) および fork(2) を呼び出します。単方向。

  2. [〜#〜] fifo [〜#〜] 、または名前付きパイプ

    2つの無関係なプロセスはFIFOプレーンパイプとは異なります。 mkfifo(3) 。Unidirectionalを使用できます。

  3. ソケット および nixドメインソケット

    双方向。ネットワーク通信を意味しますが、ローカルでも使用できます。さまざまなプロトコルに使用できます。 TCPにはメッセージ境界はありません。 socket(2) を呼び出します。

  4. メッセージキュー

    OSは個別のメッセージを保持します。 sys/msg.h を参照してください。

  5. 信号

    シグナルは整数を別のプロセスに送信します。マルチスレッドとうまく噛み合わない。 kill(2) を呼び出します。

  6. セマフォ

    バスルームを待っている人の列に似た、マルチプロセスまたはスレッドの同期メカニズム。 sys/sem.h を参照してください。

  7. 共有メモリ

    独自の同時実行制御を行います。 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のように動作するため、プログラム的にバイトストリームを扱う方が簡単です。

95
Eugene Yokota

共有メモリは、その上に独自の通信スキームを構築するため、最も効率的ですが、多くの注意と同期が必要です。共有メモリを他のマシンに配布するためのソリューションも利用可能です。

ソケットは最近では最もポータブルですが、パイプよりも多くのオーバーヘッドが必要です。ソケットをローカルで、またはネットワークを介して透過的に使用できることは、大きなボーナスです。

メッセージキューとシグナルは、ハードリアルタイムアプリケーションには最適ですが、柔軟性はそれほど高くありません。

これらのメソッドは、プロセス間の通信用に自然に作成されたものであり、プロセス内で複数のスレッドを使用すると、特にシグナルの場合、事態が複雑になります。

16
Judge Maygarden

簡単なベンチマークを使用したWebページを次に示します。 https://sites.google.com/site/rikkus/sysv-ipc-vs-unix-pipes-vs-unix-sockets

私が知る限り、それぞれに利点があります:

  • パイプI/Oは最速ですが、動作するには親子関係が必要です。
  • Sysv IPCにはメッセージ境界が定義されており、異なるプロセスをローカルに接続できます。
  • UNIXソケットは、異なるプロセスをローカルに接続でき、より高い帯域幅を持ちますが、固有のメッセージ境界はありません。
  • TCP/IPソケットは、ネットワークを介して任意のプロセスに接続できますが、オーバーヘッドが高く、固有のメッセージ境界はありません。
10
Phillip Whelan

多くのライブラリは、あるタイプのものを別のものの上に実装していることに注意してください。

共有メモリは恐ろしいsysv共有メモリ関数を使用する必要はありません-mmap()を使用する方がはるかにエレガントです(名前を付けたい場合はtmpfs/dev/shmにファイルをマップします;必要であればmmap/dev/zero exec'dプロセスではなくフォークして、匿名で継承します)。ただし、問題を回避するために、プロセスに同期の必要性が残っています。通常、他のIPCメカニズムを使用して、共有メモリ領域へのアクセスの同期を行います。

8
MarkR