简体   繁体   English

读取和写入管道问题

[英]reading and writing to a pipe c issue

Here is the program: 这是程序:

  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);

Since read blocks if there is nothing in there, we will first write to the pipe. 由于如果其中没有任何内容,则读取会阻塞,因此我们将首先写入管道。

My question is regarding the write function. 我的问题是关于功能。 The for loop runs 20 times, and each time I am writing an a to the pipe. for循环运行20次,每次将a写入管道时。 After 20 iterations, the pipe on write end will contains aaaaaaaaaaaaaaaaaaaa 经过20次迭代后,写入端的管道将包含aaaaaaaaaaaaaaaaaaaa

In the child, I read all 20 a's into buf1 , and I print the result. 在孩子中,我将所有20个a's都读到buf1 ,然后打印结果。

Now is the pipe empty, since we have wrote, and read what we wrote? 现在,既然我们已经写完并阅读了我们写的内容,管道是空的吗?

Since there is also a for loop here, we read again, but this time, I think the pipe is empty, so theres nothing to read. 由于这里也有一个for循环,我们再次阅读,但是这次,我认为管道是空的,因此没有什么可读取的。 So I think the final output after 20 iterations of reading is just aaaaaaaaaaaaaaaaaaaa 所以我认为经过20次迭代的读取后的最终输出只是aaaaaaaaaaaaaaaaaaaa

But actually it's this: 但实际上是这样的:

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

Why? 为什么? Is the pipe not empty after we read? 阅读后管道不为空吗?

You are correct that if the child calls read before the parent has written anything, the call will block; 您是正确的,如果子级调用在父级写任何东西之前先read ,则该调用会阻塞; however, after the parent closes the file descriptor, this is no longer the case and read will return 0 for EOF. 但是,在父级关闭文件描述符之后,情况就不再如此,并且read将为EOF返回0。

The read call doesn't clear the buffer. read调用不会清除缓冲区。 The OS successfully reads zero characters, and therefore changes the first zero characters of the buffer. 操作系统成功读取零字符,因此更改了缓冲区的前零个字符。 That is, it doesn't change buf1 at all. 也就是说,它根本不会改变buf1 Thus, once all the data has been read into the buffer, the printf call will always do the same thing. 因此,一旦所有数据都已读入缓冲区, printf调用将始终执行相同的操作。

Note that you aren't guaranteed to get this output. 请注意,您不能保证获得此输出。 It is perfectly possible that the child will be run after some but not all of the write calls from the parent, in which case it will not read all 20 a s at once and print shorter strings. 很有可能子进程将在父进程的一些但不是全部的write调用之后运行,在这种情况下,它将不会一次读取所有20 a并打印较短的字符串。 That's why above I said that the printf call will always do the same thing once all the data has been read . 这就是为什么我在上面说过, 一旦读取了所有数据printf调用将始终执行相同的操作。 To handle the case where not all the data has been written, you should check the return value of read . 要处理未写入所有数据的情况,应检查read的返回值。 If it is less than 20 you didn't read the full string into the buffer (and should call read again with the destination pointer advanced so you don't overwrite your data); 如果它小于20,则您没有将完整的字符串读入缓冲区(并且应在目标指针提前的情况下再次调用read ,以免覆盖数据)。 if it is zero then you've reached end-of-file (the write end is closed); 如果它为零,那么您已经到达文件末尾(写结束已关闭); if it is negative there was an error and you should check errno to handle it. 如果为负,则有一个错误,您应该检查errno来处理它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM