该程序SIGPIPE在head -n 1随机时间之后将其管理到" "之后生成.据我所知,因为我们在head -n 1第一行之后给"更多" ,我们会期望它生成SIGPIPE,但是在退出之前它会变成一个随机数(通常> 20和<200).知道为什么吗?
#include <stdio.h>
#include <stdlib.h>
main()
{
int i;
char *s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n";
i = 0;
while (1) {
fputs(s, stdout);
fflush(stdout);
fprintf(stderr, "Iteration %d done\n", i);
i++;
}
}
Run Code Online (Sandbox Code Playgroud)
这不是家庭作业,只是我教授的笔记中我不明白的东西.
这是调度的变幻莫测.
您的生产者 - 让我们称之为alphabeta- 能够在head能够读取和退出(因此破坏管道)之前运行一段时间.
当然,"一些时间"是可变的.
有时会alphabeta运行20次head才能读取标准输出并退出.有时200次.在我的系统上,有时300或1000或2000次.实际上,它理论上可以循环到连接生产者和消费者的管道的容量.
为了演示,让我们引入一些延迟,以便我们可以合理地确定head在alphabeta生成单行输出之前卡在read()中:
so$ { sleep 5; ./alphabeta; } | head -n 1
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Iteration 0 done
Run Code Online (Sandbox Code Playgroud)
(注意,不能保证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
Run Code Online (Sandbox Code Playgroud)
顺便说一句,@ R ..在他的评论中是完全正确的,即SIGPIPE是同步的.在您的情况下,第一次fflush引起的断管写入(head退出后)将同步生成信号.这是记录在案的行为.