このプログラムは、ランダムな時間の後に "head -n 1
"にパイプした後にSIGPIPE
を生成します。最初の行の後ろに "head -n 1
"を追加しているので、SIGPIPE
を生成すると予想されますが、終了する前に乱数(通常は20以上、< 200)になります。どんな考え?このCプログラムはなぜSIGPIPEを予想より遅く生成するのですか?
これは宿題ではなく、わたしの教授のメモにはわかりません。
このプログラムは、ランダムな時間の後に "head -n 1
"にパイプした後にSIGPIPE
を生成します。最初の行の後ろに "head -n 1
"を追加しているので、SIGPIPE
を生成すると予想されますが、終了する前に乱数(通常は20以上、< 200)になります。どんな考え?このCプログラムはなぜSIGPIPEを予想より遅く生成するのですか?
これは宿題ではなく、わたしの教授のメモにはわかりません。
スケジューリングのバラエティです。
は、head
が読み取りと終了(したがってパイプの破損)が可能になるまで、ある程度の時間稼働することができます。
もちろん、「ある程度の時間」は可変です。
ときどきalphabeta
が20回実行されてからhead
が読み込まれ、終了することがあります。時には200回。私のシステムでは、時々300または1000または2000回。実際、それは理論的にはプロデューサとコンシューマを接続するパイプの容量までループすることができます。デモンストレーションのために
、alphabeta
は単一の出力行を生成する前に、我々は)head
が(読み取りに立ち往生していることを合理的に確認することができますので、のは、いくつかの遅延をご紹介しましょう:
so$ { sleep 5; ./alphabeta; } | head -n 1
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Iteration 0 done
(NBそれはalphabeta
がすることを保証していませんしかし、がアンロードされたシステムでの場合は、これは常にそうなるでしょう:head
は準備ができており、その読み込み/終了は直ちに起こります。
ウォッチではなく、我々は人工的head
を遅らせるときに何が起こるか:余談として
so$ ./alphabeta | { sleep 2; head -n 1; }
Iteration 0 done
...
Iteration 2415 done # <--- My system *pauses* here as pipe capacity is reached ...
Iteration 2416 done # <--- ... then it resumes as head completes its first read()
...
Iteration 2717 done # <--- pipe capacity reached again; head didn't drain the pipe
ABCDEFGHIJKLMNOPQRSTUVWXYZ
を、@Rは... SIGPIPEが同期していることをかなり右の彼の発言です。あなたのケースでは、壊れたパイプへの最初のfflushによる書き込み(head
が終了した後)が同期して信号を生成します。これはdocumented behaviorです。
信号が非同期であるからといって単純だと思います。
更新:他の人が指摘しているように(もっと正確には、SIGPIPEを含む)そうではありません。これは疑いのない答えでした。
ソケット書き込みはバッファリングされ、非同期であるため、通常、次の読み取りまたは書き込みまで特定の書き込みから生じるエラーは発生しません。
ソケット書き込みがパイプ出力に関する質問にとって重要な理由はわかりません。 –
head
コマンドはstdioを使用してstdinを読み込んでいるため、最初のgetcはバッファがいっぱいになるかEOFのどちらかが起きるまで戻りません。
straceでこれを確認できます。 –
いいえ、それはパイプ容量とスケジューリングです。私の答えを見てください。 – pilcrow
pilcrowが言ったように、それは予定しています。このインスタンスでは、カーネルのパイプバッファ(通常64-128 KiB)は満たされません。これは約200 * 27 = 5.4 KBのデータしか書き込まれないためです。 –
Ehm、** 'const' **' char * s = ... ' –
タバコを詰めるのに時間がかかります。 – Kaz