4

当在边缘触发模式 ( ) 下使用Linux epollEPOLLET时,读/写失败并带有EAGAIN/ ,这意味着读/写准备丢失,并且一旦EWOULDBLOCK准备就绪,就会保证新的准备事件可用epoll_wait()恢复。

此外,当在边缘触发模式下使用Linux epoll和非阻塞流模式套接字时,如果我们注册了对事件的兴趣EPOLLRDHUP,并且EPOLLRDHUP尚未收到事件,则短读/写(返回值小于请求的大小) 也意味着读/写准备的丢失,当重新准备就绪时,我们仍然可以依赖新的准备通知,即使没有读/写因EAGAIN/失败EWOULDBLOCK

类似地,当在边缘触发模式(一旦恢复准备就绪。EV_CLEAREAGAINEWOULDBLOCKkevent()

问题:在边缘触发模式下使用Kqueue和非阻塞流模式套接字时,如果我们注册了对事件的兴趣EV_EOF,并且EV_EOF尚未收到事件,是否有类似的保证,即短读/写意味着失去读/写准备,并且当重新准备就绪时保证会产生新的准备事件?

编辑:注意:知道短读意味着失去读准备允许我(在一般情况下)避免冗余调用read()只是为了获得EAGAIN/EWOULDBLOCK失败。

Linux epoll 上下文中短读/写的含义来自epoll(7) 手册页中的此注释:

对于面向流的文件(如管道、FIFO、流套接字),也可以通过检查目标文件描述符读/写的数据量来检测读/写I/O空间耗尽的情况。例如,如果您通过请求读取一定数量的数据来调用 read(2),而 read(2) 返回的字节数较少,则可以确定文件描述符的读取 I/O 空间已用尽。使用 write(2) 写入时也是如此。(如果你不能保证被监控的文件描述符总是指向一个面向流的文件,请避免使用后一种技术。)

4

1 回答 1

1

您询问“边缘触发模式下的Kqueue ”,但 kqueue 文档没有使用该术语。我想你的意思一定是你已经EV_CLEAR为有问题的事件启用了标志,大意是

用户检索到事件后,将重置其状态。

BSD 文档kqueue()

此外,您规定该程序具有

注册了对事件的兴趣EV_EOF,并且EV_EOF尚未收到事件

EV_EOF它本身并不是一个事件;相反,它是一些可用过滤器将在适当时设置的标志,尤其是EVFILT_READ.

无论如何,你问题的核心是

是否有类似的保证,短读/写意味着读/写准备的丢失,并且当重新准备好时保证会产生新的准备事件?

据我所知,无论是对于 BSD 还是对于 Linux,都不能保证短暂的读取表明准备就绪的损失。实际上,Linux 文档read(2)专门将接收信号作为短读的可能替代原因。

此外,Linuxepoll()文档针对边缘触发模式下的非阻塞文件描述符推荐的使用模型是重复读取,直到读取失败并显示EAGAIN,使用作为文件结束前准备就绪的指示。我建议对EV_CLEAR有效的事件遵循与 kqueue 系统相同的策略。

我认识到您希望read()通过在短读时停止来节省一个呼叫,但我认为这会带来一个真正的风险,即让传入的数据流无限期地得不到服务。此外,除非您确定这些额外的读取会导致可衡量的、不可接受的性能消耗,否则您的担忧还为时过早。

于 2016-10-27T22:54:23.223 回答