Fla*_*ash 5 c unix select posix pipe
man 2 select在“BUGS”下说明以下内容:
在 Linux 下,select() 可能会将套接字文件描述符报告为“已准备好读取”,但后续读取会阻塞。例如,当数据已到达但经检查校验和错误并被丢弃时,可能会发生这种情况。可能存在文件描述符被错误地报告为就绪的其他情况。因此,在不应阻塞的套接字上使用 O_NONBLOCK 可能更安全。
因此,我的read调用不需要阻塞,因此我标记了我的管道文件描述符O_NONBLOCK。但是,我希望write调用阻塞,直到数据写入管道。
是否有可能write向管道写入数据时发生阻塞,但read读取端没有阻塞?例如,fcntl仅在创建管道后才在一端调用是否合法,因为读取端和写入端具有单独的文件描述符?
您当然可以在每个writewith之前删除 O_NONBLOCK 标志fcntl,并在完成后将其放回原处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);
}
Run Code Online (Sandbox Code Playgroud)