【问题标题】:Does a read() in parent process wait for a child write() in a pipe?父进程中的 read() 是否等待管道中的子 write()?
【发布时间】:2016-01-02 16:46:52
【问题描述】:

我想在 C 语言中创建子编写器和父读取器之间的管道。 我认为我的父进程必须等待其子进程写入缓冲区才能读取它,但后来我想检查它,所以我编写了以下代码:

pipe(fd);
// ... checks for pipe
pid_t pid = fork();
// ... checks for fork
if (pid == 0) {
    close(fd[0]);
    // Long sleep hoping parent will terminate before the write()
    sleep(10);
    write(fd[1], "hello", strlen("hello") + 1);
    close(fd[1]);
} else {
    close(fd[1]);
    read(fd[0], buf, sizeof(buf));
    printf("received: %s\n", buf);
    close(fd[0]);
}
return 0;

输出意外(或者不是?)received: hello。 如果我用 for (volatile int i = 0; i < some_big_int; ++i); 循环替换对 sleep() 的调用,则输出相同。 我不认为对read() 的调用会阻塞我的父进程,直到子进程在管道的另一端写入,但我无法解释这种行为。有什么提示吗?

【问题讨论】:

  • 这是预期的操作:I.E. read() 块,将返回请求的总字节数被读取或遇到 eof。或某些错误事件和信号
  • 我在man 2 read 中找不到这样说的地方:例如这句话似乎表明如果没有要读取的内容, read() 返回并且是非阻塞的:In the absence of any errors, or if read() does not check for errors, a read() with a count of 0 returns zero and has no other effects.
  • read 在流式fd(例如管道)上传递非零count 时,它会阻塞直到至少有1 个字节可用,然后读取count那个时候可以。由于您writeclose(并且写入小于PIPE_BUF),它会立即刷新整个字符串,因此当它解除阻塞时,它会立即获取您写入的所有内容。
  • readcount 为 0 与您的情况无关,因为您没有通过 count 为 0。
  • write(fd[1], "hello", strlen("hello"));read(fd[0], buf, sizeof(buf)); 不会 NUL 终止 buf,因为终止的 NUL 不会写入管道。此外,printf("received: %s\n", buffer); 打印buffer 的输出,而不是buf 的内容。如果它试图打印buf 的内容,发布的代码将调用未定义的行为。此外,失败的fork() 调用将导致父进程在read() 中永远阻塞。

标签: c pipe fork ipc wait


【解决方案1】:

read 将阻塞直到至少有一个字节要读取,或者遇到错误,或者到达流的末尾。当至少有一个字节要读取时,它将读取尽可能多的字节(直到您指定的最大数量),然后返回。

在这种情况下,父进程对read 的调用将阻塞,直到子进程write 向管道发送某些内容。


来自man 7 pipe 部分管道和 FIFO 上的 I/O

如果一个进程试图从一个空管道中读取,那么 read(2) 将阻塞直到数据可用。如果一个进程试图写入一个完整的管道(见下文),那么 write(2) 会阻塞,直到从管道中读取了足够的数据以允许写入完成。通过使用 fcntl(2) F_SETFL 操作启用 O_NONBLOCK 打开文件状态标志,可以实现非阻塞 I/O。

【讨论】:

  • 这是在哪里指定的?不幸的是,我在man 2 pipeman 2 read 都找不到此信息
  • man 7 pipe 中找到它,并相应地编辑了您的答案。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-09
  • 2021-08-06
  • 1970-01-01
  • 2011-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多