是否可以对管道进行读而不是块,而是写块?

问题描述 投票:0回答:1

man 2 select
在“BUGS”下说明以下内容:

在 Linux 下,select() 可能会将套接字文件描述符报告为“ready for 读”,而随后的读块。这可以用于 示例发生在数据已到达但经检查有错误时 校验和并被丢弃。可能还有其他情况,其中 文件描述符被错误地报告为就绪。因此可能更安全 在不应阻塞的套接字上使用 O_NONBLOCK。

因此,我的

read
调用不需要阻塞,因此我标记了我的管道文件描述符
O_NONBLOCK
。但是,我希望
write
调用阻塞,直到数据写入管道。

是否可以在向管道写入数据时让

write
阻塞,但让
read
不阻塞读取端?例如,仅在创建管道后才在一端调用
fcntl
是否合法,因为读端和写端具有单独的文件描述符?

c unix pipe posix posix-select
1个回答
2
投票

您当然可以在每个

write
之前使用
fcntl
删除 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);
}
© www.soinside.com 2019 - 2024. All rights reserved.