在继续之前等待fork子项写入管道

时间:2014-11-08 08:45:49

标签: c concurrency fork

了解C {/ 1}}和fork()

以下代码创建了一个管道和一个子进程。孩子发送一条消息,父母将其阅读。

pipe()

它运作正常。如果你评论int main () { int fd[2]; pid_t pid; pipe(fd); pid = fork(); if (pid == 0) { // Child close(fd[0]); write(fd[1], "HELLO", (strlen("HELLO")+1)); exit(0); }else{ // Parent close(fd[1]); char buffer[80]; read(fd[0], buffer, sizeof(buffer)); printf("Received string: %s", buffer); } return 0; } 行,父母会报告它收到一个带有奇怪字符的字符串,我认为这是正常的,因为它正在读取与我的程序无关的内存。

然而,它带来了一个问题:父母是否有可能在 之前读取管道 ,孩子可以写数据?如果发生了这种情况,它将会读取奇怪的字符。

父母如何等待"从孩子那里写数据?

将来我可能会有几个孩子的过程,我希望父母等待所有孩子完成这些过程。继续他们的工作。

1 个答案:

答案 0 :(得分:1)

  

如果您对写入行进行注释,则父级将报告它收到了带有奇怪字符的字符串

如果在孩子中跳过了对write的调用,则子进程结束,管子端的子进程结束将被关闭。

父母检测到孩子的管道末端已关闭,这使得对read()的调用返回。父母实际上没有读任何东西,所以缓冲区保持未初始化状态,"垃圾"打印出来。

请从以下read's POSIX specification找到relvant部分:

  

尝试从空管道或FIFO读取时:

     
      
  • 如果没有进程打开管道进行写入,则read()将返回0以指示文件结束。
  •   
     

[...]

     
      
  • 如果某个进程打开了管道并且O_NONBLOCK已清除,则read()将阻塞调用线程,直到写入一些数据或管道被管道打开以供写入的所有进程关闭。
  •   

要使代码能够处理孩子不写任何内容的情况,请测试父母对“读取()”的调用是否真正读过:

            ssize_t result = read(fd[0], buffer, sizeof(buffer));
            if (-1 == result) /* Also ALWAYS test for error. */
            {
              perror("read() failed");
            }
            else if (0 == result)
            {
              fprintf(stderr, "read() returned without having read anything.\n")
            }
            else
            {
              printf("Received string: '%s'", buffer);
            }