プロセスとスレッドの比較からの続き。
Linuxにはプロセス間通信の手段がいくつかある。
それぞれに特徴があり、それによって用途もある程度決まってくる。
そういうプロセス間の通信について個人的なまとめ。
ちなみにIPCの手段によってパフォーマンスや特性が異なる。
参考:プロセス間通信の比較 - ka2yanの日記
#ファイル
えっ!?
はいファイルです。
ファイル、それはグローバルなリソース。
2つのプロセスがO_RDWRでファイルを奪いあえば排他制御もできる。
ファイルを2つ用意すれば双方向通信もできる。
フォーマットも自由に決められる。ストリームもパケットもOK。
欠点はストレージ経由のため遅く、IPCの取り決めが面倒なこと。
だが簡易的なIPCで良ければ十分実用になる。
#パイプ
親子関係のプロセス間限定でメッセージを交換する手段。
ファイルディスクリプタ(fd)にバッファを関連付けて通信を行う。
通信はストリームデータでありデータ区切りはない。
単方向通信である。
#名前つきパイプ
依存関係のない同一ホスト内のプロセス間で通信する手段。
パイプの場合はバッファをfdに結び付けて通信を行うが、
名前つきパイプはopen()したfdの先にバッファが作られる。
バッファはカーネルが用意する。単方向通信である。
fdは権限のあるディレクトリなら作成できるが、ホスト内限定。
通信はストリームデータでありデータ区切りはない。
性能は多分パイプと同じはずである(同じ仕組みのため)。
readerプロセスはCPUの浪費防止でブロッキングwaitしたいが
若干問題がある。
###open()でブロッキングする場合
open()/close()のコンテキストスイッチングが遅い。
通信頻度が少なくオーバーヘッドが無視できるなら問題はない。
###read()でブロッキングする場合
使ったことはないが、open()ブロッキングより高速なはずである。
ただしO_RDWRでopen()する必要があり、その場合の動作は未定義。
参考:FIFOについてもう少し
#ネットワークソケット
TCP/UDPのソケットをopen()してネットワーク通信を行う。
ネットワーク越しになるためパフォーマンスはよくない。
その代わり同一ホストに限定されないプロセス間通信が可能。
ローカルネットワークでもインターネット越しでも使える。
双方向通信である。
#Unixドメインソケット
依存関係のない同一ホスト内のプロセス間で通信する手段。
ネットワークソケットのIPアドレスをfdに置き換えたイメージ。
名前付きパイプより若干低速らしい。双方向通信である。
#メッセージキュー(MQ)
Linux限定で説明するが、SystemVとPOSIXがある。
しかしPOSIX MQ推奨のため、SystemVは無視していいだろう。
メッセージは区切りがあり、固定サイズのデータ配列になる。
read()でブロッキングでき、パイプより高速である。
mq_timedreceive()を使えばタイムアウト監視も可能。
欠点はキューのパラメータがシステムファイルであること。
管理者権限で編集しないと要素数と要素サイズは変更不可。
ただしキューのブロッキング属性だけは動的に変更できる。
単方向通信である。
#共有メモリ
プロセス間でページ単位のメモリを共有する。
仮想アドレスはプロセス別だが物理アドレスは同一である。
ただのメモリなので単方向でも双方向でも思うがままだ。
メモリのread/writeと同じなので高速でもある。
ただし本気で実装すると排他制御が結構面倒である。
#セマフォ
プロセス間で整数値を共有し、排他するための機構。
情報交換するIPCとしての機構には向かない。
#シグナル
ソフトウェア割り込み、という理解でいいと思う。
寝ているプロセスをシグナルで起こせるかは調べていない。
ソフトウェア割り込みなので通知そのものは高速である。
シグナルハンドラを実装しないとデフォルトハンドラが呼ばれる。
シグナルハンドラは非同期シグナル安全なAPIしか使えない。
シグナルを受信したら通知のみ行い、メイン側で対応すべきだ。
共有メモリと組み合わせたIPCが実現できそうである。