
彼のページ紹介これ自己管理技術、Dan Bernsteinは、信号の観点から競合状態を説明し、select()
解決策を提供し、次のように結論付けます。
もちろん、正しい方法は
fork()
プロセスIDではなくファイル記述子を返すことです。
これが意味するのは、select()
このような状態変更の通知を受け取るためにシグナルハンドラを使用する代わりに、子プロセスの状態変更を自分で処理することは可能ですか?
答え1
問題はソースコードで説明されており、select()
thisなどの信号で中断する必要がありますSIGCHLD
が、場合によっては正しく機能しません。したがって、解決策は信号をパイプに書き込み、それを監視することですselect()
。ファイル記述子の監視は、この問題を解決するように設計されていますselect()
。
回避策は、デフォルトでシグナルイベントをファイル記述子イベントに変換します。 fdが最初に返されると、fork()
回避策は必要ありません。対応するfdはおそらく一緒に直接使用できるからですselect()
。
はい、最後の段落の説明が私の考えに合うようです。
fd(または他のタイプのカーネルハンドル)が通常のプロセスID番号よりも良いもう1つの理由は、プロセスが終了した後にPIDを再利用できることです。場合によっては、プロセスにシグナルを送信するときに問題が発生する可能性があり、そのプロセスが同じPIDを再利用する他のプロセスではなく、考えているプロセスであることを確認することは不可能です。 (子プロセスにシグナルを送信するときにこれが問題になるとは思いませんが、wait()
PIDを解放するには親プロセスを子プロセスで実行する必要があるためです。)
答え2
Bernsteinはこの「正しい仕事」コメントに多くの文脈を提供していませんが、推測する危険があります。 fork(2) が PID を返すのは、open(2)、creat(2) などと一致しません。ファイル記述子。残りのUnixシステムでは、PIDの代わりにプロセスを表すファイル記述子を使用してプロセス操作を完了できます。システムコールsignalfd(2)これは、シグナルとファイル記述子の間のより良い対話を可能にし、プロセスを表すファイル記述子が機能できることを示しています。
答え3
これは「Unixを今とは違うデザインにしてほしい」という反省に過ぎません。
PIDの問題は、PIDが他のプロセスに再利用できるグローバルネームスペースにあることであり、fork()
常に子プロセスを参照するように保証されているハンドルの種類が親プロセスから返された場合に便利です。継承またはUnixソケットを介して他のプロセスに渡すことができますSCM_RIGHTS
。 [1]
ディスカッションも参照してくださいここclone()
Linuxでこの問題を「修正」する最近の努力には、PIDの代わりにpid-fdを返すようにフラグを追加することが含まれます。
しかし、それにもかかわらず、セルフパイプラインハッキング[2]やより良いインターフェースが必要ないわけではありません。なぜなら、親プロセスに子プロセスの状態を知らせる信号が、プロセスが処理しようとする唯一の信号ではないからである。プログラムのメインループ。残念ながら、epoll(7) + signalfd(2)
LinuxやBSDkqueue(2)
では標準ではありません。基準インターフェイス(以前のシステムではサポートされていません)が悪いですpselect(2)
。
[1]システムコールが返されたときにPIDがリサイクルされるのを防ぎ、戻り値を使用することは、最新のシステムで以下を使用することでwaitpid()
可能です。waitid(.., WNOWAIT)
[2]私は自分がそれを発明したというDJ Bernsteinの主張については言及しません(略して申し訳ありません;-))。
答え4
要点は、ファイル記述子の観察に基づいてイベントループスタイルモデルを実行するプログラムが多いことです。選択(2)/世論調査(2)/電子世論調査(7)。しかし、歴史的には、子プロセスのプロセス状態の切り替え(終了など)を含むファイル記述子を使用して通知を受け取らなかったさまざまなイベントがありました。これらのその他のイベント(タイマーの有効期限、信号、同期イベント(セマフォの変更など)など)は別々に処理する必要があるため、イベントループモデルのプログラミングが複雑になります。
Linux開発はここ数年でこの問題を解決してきました。signalfd(2)(ファイル記述子から信号を読み取ることができるようにする)eventfd(2)(ハンドルはファイル記述子の同期の基本要素です)タイマー fd_create(2)(ファイル記述子を介して通知を受け取るタイマーを生成します。)これらすべては、次に提供できるファイル記述子を生成します。選択(2)/世論調査(2)/電子世論調査(7)。
最後に、Linuxの最新バージョンでは、プロセスハンドルの概念がファイル記述子として追加されました。CLONE_PIDFD
旗クローン3()ファイル記述子がハンドルとして返される子プロセスを作成するために使用できます。ファイル記述子を入力することもできます。選択(2)/世論調査(2)/電子世論調査(7)子プロセスが終了すると、表示を読み取ることができます。