阅读和写入管道问题

时间:2017-08-15 18:45:03

标签: c pipe fork

以下是该计划:

  int fd[2];
  char buf1 [31];
  int i;
  char buf2;

  pipe(fd);

  if (fork() == 0) { // child
    close(fd[1]); // close writing pipe
    for(i = 0; i< 20; i++) { 
        read(fd[0], buf1, 30);
        printf("%s\n", buf1);

    }
    close(fd[0]);
  }

  else { // parent
    close(fd[0]); // close reading end
    buf2 = 'a';
    for (i = 0; i < 20; i++) {
        write(fd[1], &buf2, sizeof(buf2));
    }
    close(fd[1]);
  }
  wait(NULL);

由于读取阻塞,如果没有任何内容,我们将首先写入管道。

我的问题是关于功能。 for循环运行20次,每次我向管道写a。经过20次迭代后,写入端的管道将包含aaaaaaaaaaaaaaaaaaaa

在孩子中,我将所有20 a's读到buf1,然后打印结果。

现在管道是空的,因为我们已经写过并阅读了我们写的内容?

由于这里还有一个for循环,我们再次阅读,但这一次,我认为管道是空的,所以没有什么可读的。所以我认为20次迭代后的最终输出就是 aaaaaaaaaaaaaaaaaaaa

但实际上就是这样:

aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa

为什么呢?我们读完后管道不是空的吗?

1 个答案:

答案 0 :(得分:2)

你是正确的,如果孩子在父母写过任何东西之前调用read,那么呼叫将会阻止;但是,在父关闭文件描述符后,情况不再如此,read将返回0表示EOF。

read调用不会清除缓冲区。操作系统成功读取零个字符,因此更改缓冲区的前0个字符。也就是说,它根本不会改变buf1。因此,一旦所有数据都被读入缓冲区,printf调用将始终执行相同的操作。

请注意,您无法保证获得此输出。孩子完全有可能在父母的一些但不是所有的write来电之后运行,在这种情况下,它不会同时读取所有20个a并打印更短的字符串。这就是为什么上面我说过printf调用在读完所有数据后总是做同样的事情。要处理未写入所有数据的情况,应检查read的返回值。如果它小于20,你没有将完整的字符串读入缓冲区(并且应该再次调用read并使目标指针前进,这样就不会覆盖你的数据);如果它为零,那么你已到达文件结尾(写入结束);如果它是否定的则出现错误,您应该检查errno来处理它。