【发布时间】:2018-12-07 16:54:26
【问题描述】:
有没有办法在管道/终端/等上以非阻塞模式单个 read(),就像我可以在带有recv(MSG_DONTWAIT) 的套接字上那样做? p>
我需要这样做的原因是因为我无法保证文件描述符上的 read() 返回为可供select() 或poll() 读取的准备不会 阻塞。
我知道可以使用fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) 使文件描述符非阻塞,但这将全局更改该文件描述符的模式,而不仅仅是在调用线程/进程中。例如:
% perl -MFcntl=F_SETFL,F_GETFL,O_NONBLOCK -e 'fcntl STDIN, F_SETFL, fcntl(STDIN, F_GETFL, 0) | O_NONBLOCK; select undef, undef, undef, undef'
^Z # put it in the background
% cat
cat: -: Resource temporarily unavailable
这也将使 fd 对 读取和写入都非阻塞,这可能会混淆另一个进程在同一个 fd 上执行相反操作,如:
non_blocking_read | filter | blocking_write
我想到的一种方法是在启动和SIGCONT 上保存文件状态标志,并在退出和SIGTSTP 上恢复它们(就像使用 termios 设置完成的方式一样),但这非常有限,容易竞争,并且在程序异常退出的情况下会留下一团糟。
在每个read() 之前/之后使用fcntl() 进行保存/恢复也感觉丑陋和愚蠢,并且可能还有其他问题。在 read 之前的 ioctl(FIONREAD) 也是如此(我什至不确定它是否能可靠地与任何 fd 一起工作;不过,欢迎朝这个方向保证)。
即使使用特定于系统(例如 linux 或 bsd-only)的解决方案,我也会很高兴。
供参考,here 是关于在 linux 中修复它的讨论;不过,这个想法似乎没有成功。
【问题讨论】:
标签: unix pipe nonblocking file-descriptor tty