管道上的 read() 没有阻塞

read() on a pipe is not blocking

我有以下代码,我在 parent 和 child 进程之间使用管道进行双向读写。

据我所知,如果我不使用 O_NONBLOCK,读取应该会阻塞,直到数据从另一端写入管道。

但是,我注意到 parent 端的读取没有阻塞。我知道,因为我在 gdb 中调试,所以我在 child 中将睡眠作为第一个语句。

为什么 parent 的 read() 没有阻塞在这里?另外,我还需要做些什么来同步两个进程之间的 read/write 吗?

typedef struct
{
    int x;
    int y;
}PayLoad;

PayLoad pl;
bool b = false;

int pipe_fds[2];


void p(int i, int j)
{
   pl.x = i;
   pl.y = j;

   pipe(pipe_fds);
   pid_t cpid = fork();

   if (cpid == 0) // child process
   {
       std::this_thread::sleep_for(std::chrono::seconds(100)); // just for debugging
       close(pipe_fds[1]);
       read(pipe_fds[0], &pl, sizeof(Payload));
       //... do some processing on read data

       close(pipe_fds[0]);
       write(pipe_fds[1], &b, sizeof(bool));
       close(pipe_fds[1]);
   }
   else if (cpid > 0) // parent process
   {
       close(pipe_fds[0]);
       write(pipe_fds[1], &pl, sizeof(Payload));
       close(pipe_fds[1]);
       read(pipe_fds[0], &b, sizeof(bool));  <------ did not block!
       close(pipe_fds[0]);
   }
}

如果设置了 O_NONBLOCK,read() 将 return a -1 并将 errno 设置为 [EAGAIN]。

真正的问题是您在使用文件描述符之前关闭了它们。例如,在子进程中,您正在关闭 pipe_fds[1] 并使用它来写入一些值。在父进程中,您正在关闭 pipe_fds[0] 并使用它来读取一些值。进程关闭文件描述符后,进程不应使用它进行读取或写入。通常管道概念是一个进程(父进程或子进程)将使用管道创建的文件描述符之一写入,而另一个进程(父进程或子进程)将使用另一个文件描述符读取数据。