`getline` 在没有关闭管道 [1] 的情况下挂起

`getline` hangs without closing pipe[1]

我正在用 fork()pipe() 编写一个程序,使子进程写入管道,父进程从管道读取(getline())。但是如果不在父进程中关闭 pipe[1]getline() 就会永远挂起。为什么会这样?

我正在使用 Ubuntu 18.04 LTS。我阅读了手册,但没有提到为什么 getline() 可能会挂在那里。

我的程序的一个简单的错误版本:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
  int fd[2];
  char *s = NULL;
  size_t n = 0;
  int rt;
  pipe(fd);

  pid_t pid = fork();
  if (pid != 0) {
    //close(fd[1]); // without this line, getline() hangs
    dup2(fd[0], STDIN_FILENO);
    close(fd[0]);
    while ((rt = getline(&s, &n, stdin)) != -1) {
      printf("rt: %d\n", rt);
    }
  } else {
    close(fd[0]);
    dup2(fd[1], STDOUT_FILENO);
    close(fd[1]);
    for (int i = 0; i < 10; ++i) {
      printf("aaa\n");
    }
  }
  return 0;
}

管道的 "read" 端将不会出现文件结束条件,直到对管道 "write" 端的所有引用都已关闭。 fork() 递增所有打开文件描述的引用。 pipe(fd) 创建管道时将两个打开的文件描述设置为阻塞模式,因此如果没有任何内容写入管道的 "write" 端,则对管道 "read" 端的读取操作将被无限期封锁。