fork()
次の/SIGCHLD
疑似コードを検討してください。
// main program excerpt
for (;;) {
if ( is_time_to_make_babies ) {
pid = fork();
if (pid == -1) {
/* fail */
} else if (pid == 0) {
/* child stuff */
print "child started"
exit
} else {
/* parent stuff */
print "parent forked new child ", pid
children.add(pid);
}
}
}
// SIGCHLD handler
sigchld_handler(signo) {
while ( (pid = wait(status, WNOHANG)) > 0 ) {
print "parent caught SIGCHLD from ", pid
children.remove(pid);
}
}
上記の例では、競合状態があります。/* child stuff */
" " が開始する前に " " が終了する可能性/* parent stuff */
があります。その結果、子の pid が終了後に子のリストに追加され、決して削除されない可能性があります。アプリが終了する時が来ると、親は既に完成した子が完成するのを際限なく待ちます。
これに対抗するために考えられる解決策の 1 つは、 と の 2 つのリストを作成することstarted_children
ですfinished_children
。今追加しstarted_children
ているのと同じ場所に追加しchildren
ます。しかし、シグナル ハンドラでは、 fromchildren
を削除する代わりに、 to を追加しfinished_children
ます。started_children
アプリが終了すると、親はとの差finished_children
がゼロになるまで待つことができます。
私が考えることができる別の可能な解決策は、共有メモリを使用することです。たとえば、親の子のリストを共有し、子.add
と.remove
自分自身を許可しますか? しかし、私はこれについてあまり知りません。
編集: 最初に頭に浮かんだ別の解決策は、単純にsleep(1)
先頭に a を追加する/* child stuff */
ことですが、それは私には変なにおいがするので、省略しました。また、それが 100% 修正されるかどうかもわかりません。
では、この競合状態をどのように修正しますか? また、これの定評のあるおすすめパターンがあれば教えてください!
ありがとう。