我正在使用来自TCP套接字的非阻塞select()
的{{1}}。当read()
表示有数据可供阅读时,我不确定在select()
之后是否仍需要处理EINTR
。
答案 0 :(得分:5)
是的,绝对的。 select
函数是一种状态报告功能,可以在您调用select
时和注意到其返回值时报告某些事件的状态。它绝对是 no 未来的保证,期限。
这是一种非常常见的误解。但是认为select
确保将来的操作将提供某些特定结果是错误的,因为认为检查磁盘上有空闲空间意味着未来的写入不会失败。即使你认为有足够的可用空间,也可以允许实现在没有足够空闲空间的情况下失败。这个空间可以填补空间并尝试使用它。
select
也是如此。没有规则,实现必须以某种方式记住它给你一个select
的命中,并且这会影响后续读取的实现。人们多次做出这种假设,并被它咬得可怕。不要以为只是因为你无法想到任何失败的方式,这意味着它不会失败。
例如,没有规则禁止实现执行以下操作:
select
返回就绪状态。此时发出的read
将返回数据。read
操作块,因为没有要读取的数据。如果您认为某些标准禁止它,请引用该标准。 read
点击后select
因任何原因导致read
点击select
失败后失败。 select
函数从不提供未来保证。
答案 1 :(得分:2)
他们我理解文档(我没有读过内核的代码,所以我可能错了),答案是:是的。
如果在内核的read
操作期间发生中断(当内核将数据从套接字的缓冲区复制到用户的内存并更新套接字的状态时),操作将被取消并且read
功能将返回-1
(errno
设置为EINTR
)。
套接字是非阻塞的这一事实只会最小化“窗口”,但它不会阻止这种情况发生。
另外,即使不是这种情况,我也建议你假设EINTR
是可能的。只要文档没有声明EINTR
错误对非阻塞文件描述符无效,对内核实现的未来更新可能会在他们认为合适时调用此错误。
另外,考虑到即使read
操作对应用程序来说是原子的,内核也在处理许多内部结构(套接字的读缓冲区本身就有许多需要在内存之后更新的元素被复制了)。因此,内部结构具有锁定/同步机构。尽管套接字是非阻塞的,但仍有一段时间可以中断呼叫。