16

该程序在随机时间后将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++;
  }
}

这不是家庭作业,只是我教授的笔记中我不明白的东西。

4

4 回答 4

8

这是日程安排的变幻莫测。

你的生产者——我们称之为它alphabeta——能够运行一段时间,然后head才能读取和退出(从而破坏管道)。

当然,“一些时间”是可变的。

有时alphabeta运行 20 次head才能读取标准输入并退出。有时200次。在我的系统上,有时 300 或 1000 或 2000 次。事实上,理论上它可以循环到连接生产者和消费者的管道的容量。

为了演示,让我们引入一些延迟,以便我们可以合理地确定在产生单行输出head之前卡在 read()中:alphabeta

so$ { sleep 5; ./alphabeta; } | head -n 1
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Iteration 0 done

(注意,不能保证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退出后)将同步生成信号。这是记录在案的行为

于 2013-05-05T03:45:08.670 回答
4

我认为这仅仅是因为信号是异步的。

更新:正如其他人指出的那样(更确切地说,很多,包括 SIGPIPE)不是。这是一个不假思索的答案:)

于 2013-05-05T00:50:19.790 回答
0

head命令使用 stdio 读取标准输入,因此第一个 getc 直到缓冲区已满或 EOF 才会返回,以先发生者为准。

于 2013-05-05T03:18:52.633 回答
0

套接字写入是缓冲的和异步的,因此在接下来的读取或写入之前,您通常不会收到由特定写入引起的错误)。

于 2013-05-05T00:55:36.083 回答