読むときにパイプがいっぱいである必要があるというのは要件ですか? それとも、パイプの 1 つがいっぱいで、子の書き込みがブロックされている場合でも、両方の子から読み取り続ける必要があるだけですか?
パイプがいっぱいになった場合に高くする標準的な方法はわかりません。FIONREAD
ioctl を使用して、パイプで読み取るデータの量を判断しPIPE_BUF
、それPIPE_BUF
をそれ以上PIPE_BUF
; その呼び出しは、パイプをいっぱいにすることなくブロックする可能性があります。私はこのテクニックが機能することに頼りません。
2 つのファイル記述子から読み取りを続ける通常の方法は、どちらが準備できているかに関係なく、select
システム コールを使用することです。これにより、いずれかのファイル記述子でデータが利用可能になるまで待つことができます。これは、親プロセスが、使用可能なデータを持たない 1 つの子からの読み取りをブロックしないことを意味しますが、もう 1 つの子はバッファーがいっぱいであるためにブロックされています。
編集:質問を読み直した後、実際には両方の子供が書き込んでいるパイプが1つしかないように思えます。あれは正しいですか?繰り返しますが、子供たちがブロックするまで待つ必要があるかどうかという質問が出てきます. 親が単にパイプから読み取る場合、子の 1 つがパイプに書き込むまでブロックされます。特別なことをする必要はありません。
パイプが実際にいっぱいになるまで待つ必要がある場合は、正確な文言を確認したいと思います.
編集 2 : コメントでの質問への回答:
親プロセスのコードは、プログラム内の 2 つの子プロセスのコードに従う必要がありますか?
いいえ、親プロセスまたは子プロセスのコードの順序に関する要件はありません。親が実行するコードと子が実行するコードを区別するために、 の戻り値をチェックしますfork()
。戻り値が 0 の場合、子プロセスにいます。そうでない場合は、親にいます。戻り値が -1 の場合はエラー、正の場合は子プロセスの PID です。
したがって、次のようなコードを記述できます。
int pid = fork();
if (pid) {
// in the parent, check if pid is -1 for errors
} else {
// in the child
}
または:
int pid = fork();
if (pid == 0) {
// in the child, do whatever you need to do and...
exit(0);
}
// in the parent; since the child calls exit() above, control will never
// reach here in the child. Or you could do an execl() in the child, which
// replaces the current program with another one, so again, control will
// never reach here within the child process.
2 つの子が終了し、パイプが空になるまでパイプから読み取り続けるにはどうすればよいですか?
パイプの読み取り側では、すべてのプロセスがパイプの書き込み側を閉じ、すべてのデータがパイプから読み取られるまで、0 を返しませんread
。read
何かがまだ開いているが、パイプにデータがない場合、データがパイプにread
書き込まれるまでブロックされます。
落とし穴の 1 つは、試行する前に、親プロセスでパイプの書き込み側を閉じることを忘れないことread
です。そうしないと、子が終了した後に親が a を実行しようとすると、親read
が独自のパイプを閉じるのを待ってブロックされます。