ユーザー側の違いだけでなく、Linuxカーネル実装の違い・共通部分も知りたいです。
2 に答える
パイプは単方向であるため、双方向通信を行うには2つのパイプが必要ですが、ソケットペアは双方向です。
パイプは常にストリーム指向ですが、ソケットペアはデータグラム指向にすることができます。
ソケットペアは通常の
AF_UNIX
ソケットです。つまり、のような補助メッセージをソケットにSCM_RIGHTS
渡すSCM_CREDENTIALS
ことができます。
カーネルでは、パイプはファイルシステムコードに実装され、ソケットペアはネットワークコードに実装されます。
マルチスレッド プログラムでサブプロセスとの競合防止通信を実装するには、ソケットペアのshutdown()
およびSCM_RIGHTS
機能が必要です。
pipe()
複数のスレッドがfork()
同時に存在する場合、パイプが誤って複製される可能性があります。その場合、パイプの書き込み側が閉じられず、読み取り側で EOF が発生せず、デッドロックが発生する可能性があります。サブプロセスのみを使用するプログラムfork()
(つまり、すべてfork()
の s がすぐにexecve()
子プロセスの後に続く) の場合でも、同時実行によるパイプ キャプチャfork()
はビットの設定と競合し、を受け入れるFD_CLOEXEC
移植性のない Linux システム コールの使用を禁止します。pipe2()
O_CLOEXEC
このハザードを移植可能な方法で解決するには、fork()
を呼び出さずexecve()
にソケットペアを使用するプログラムについても同様です。
- アウトバウンド チャネル (つまり、メイン プログラムからサブプロセスへの書き込み) の場合: ファイル記述子が複製されたかどうかに関係なく、パイプの代わりにソケットペアを使用し、親から
shutdown()
beforeを呼び出しclose()
て、競合防止 EOF 条件を引き起こします。 - インバウンド チャネル (つまり、サブプロセスからの読み取り) の場合、子にパイプを作成し (偶発的な複製のために書き込み側が親に表示されないようにするため)、読み取り側のみをメッセージ付きのソケットペアを介して親に送信し
SCM_RIGHTS
ます。