2013-05-05 1 views
16

このプログラムは、ランダムな時間の後に "head -n 1"にパイプした後にSIGPIPEを生成します。最初の行の後ろに "head -n 1"を追加しているので、SIGPIPEを生成すると予想されますが、終了する前に乱数(通常は20以上、< 200)になります。どんな考え?このCプログラムはなぜSIGPIPEを予想より遅く生成するのですか?

これは宿題ではなく、わたしの教授のメモにはわかりません。

+0

Ehm、** 'const' **' char * s = ... ' –

+2

タバコを詰めるのに時間がかかります。 – Kaz

答えて

8

スケジューリングのバラエティです。

は、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です。

4

信号が非同期であるからといって単純だと思います。

更新:他の人が指摘しているように(もっと正確には、SIGPIPEを含む)そうではありません。これは疑いのない答えでした。

+0

stdioバッファリングがありません。 –

+5

SIGPIPEは同期信号です。 –

+0

@R .. 'stdio'は' fflush'を過ぎてバッファーしません。 – Kevin

0

ソケット書き込みはバッファリングされ、非同期であるため、通常、次の読み取りまたは書き込みまで特定の書き込みから生じるエラーは発生しません。

+5

ソケット書き込みがパイプ出力に関する質問にとって重要な理由はわかりません。 –

0

headコマンドはstdioを使用してstdinを読み込んでいるため、最初のgetcはバッファがいっぱいになるかEOFのどちらかが起きるまで戻りません。

+0

straceでこれを確認できます。 –

+1

いいえ、それはパイプ容量とスケジューリングです。私の答えを見てください。 – pilcrow

+0

pilcrowが言ったように、それは予定しています。このインスタンスでは、カーネルのパイプバッファ(通常64-128 KiB)は満たされません。これは約200 * 27 = 5.4 KBのデータしか書き込まれないためです。 –

関連する問題