管道是否可以实现读取不阻塞,但写入阻塞?

5

man 2 select 在BUGS部分提到:

在Linux下,当数据已经到达但检查和丢弃时,select()可能会将套接字文件描述符报告为“准备好读取”,而随后的读取却被阻塞。文件描述符被错误地报告为就绪的情况可能还有其他情况。因此,在不应该阻塞的套接字上使用O_NONBLOCK可能更安全。

因此,我的read调用不能阻塞,因此我已经将我的管道文件描述符标记为O_NONBLOCK。然而,我希望write调用在写入管道时阻塞,直到数据被写入。

是否可能使write在向管道写入数据时阻塞,但read不会阻塞读取端?例如,在管道创建后仅对一个端点调用fcntl是否合法,因为读取和写入端点具有单独的文件描述符?

1个回答

2
您可以使用fcntl在每个write之前删除O_NONBLOCK标志,并在write完成后将其放回。然而,保持套接字始终为非阻塞状态,并将write放入循环直到其完成似乎更好。为了不过载CPU,请放置一个select,它会阻塞进程直到套接字准备好进行写操作。
因此,写入代码将如下所示:
int blockingWriteOnNonBlockingFd(int fd, char *buf, int size) {
  fd_set wset, w;
  int    n, r;
  FD_ZERO(&wset);
  FD_SET(fd, &wset);
  n = 0;
  while (n < size) {
    w = wset;
    select(fd+1, NULL, &w, NULL, NULL);
    r = write(fd, buf+n, size-n);
    if (r <= 0) {
       if (r<0 && (errno == EWOULDBLOCK || errno == EAGAIN)) r = 0;
       else { /* broken connection */ break; }
    }
    n += r;
  }
  return(n);
}

我能否将写入FD设置为阻塞,将读取FD设置为非阻塞,因为在使用管道时它们是单独的文件描述符? - Flash
是的,你可以这么做。我可能误解了原来的问题。我认为你想要从/写入同一个套接字。 - Marian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接