Kqueue(边缘触发):短读是否意味着读取准备就失去了?

时间:2016-10-19 06:19:02

标签: c macos freebsd epoll kqueue

在边缘触发模式(EPOLLET)中使用 Linux epoll 时,如果EAGAIN / EWOULDBLOCK读/写失败,则表示已读取/ write-readyiness已丢失,并且只要重新获得准备就绪,就可以通过epoll_wait()保证新的就绪事件可用。

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

同样,在边缘触发模式(EWOULDBLOCK)中使用 Kqueue (macOS / FreeBSD)时,读取/写入失败并显示EV_CLEAR / {{1} },这意味着读/写就绪已经丢失,并且只要重新获得准备就绪,就可以保证通过EAGAIN提供新的就绪事件。

问题:在边缘触发模式下使用 Kqueue 和非阻塞流模式套接字时,如果我们对EWOULDBLOCK事件感兴趣,并且还没有收到kevent()事件,是否有类似的保证,短读/写意味着读/写就绪失效,并且当准备就绪时保证会产生新的准备事件恢复?

编辑:注意:知道短读取意味着读取就绪性的失败使我(在一般情况下)避免EV_EOF的冗余调用只是为了得到{{ 1}} / EV_EOF失败。

Linux epoll上下文中的简短读/写的含义,请参见read()(7)手册页中的注释:

  

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

1 个答案:

答案 0 :(得分:1)

您询问“ Kqueue 处于边缘触发模式”,但kqueue文档不使用该术语。我认为你必须意味着你已经为相关事件启用了EV_CLEAR标志,其效果是

  

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

BSD documentation for kqueue()

此外,您规定该程序具有

  

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

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

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

  

是否有类似的保证,短读/写意味着读/写就绪失效,并且在重新获得准备就绪时保证会产生新的准备事件?

据我所知,无法保证短读取信号会导致读取准备就绪丢失,无论是BSD还是Linux。实际上,read(2)的Linux文档特别指出接收信号是短读的可能替代原因。

此外,Linux epoll()文档推荐用于边缘触发模式下的非阻塞文件描述符的使用模型是重复读取,直到读取因{1}}失败,使用 表示在文件结束前失去准备状态。对于EAGAIN生效的事件,我建议对kqueue系统遵循相同的策略。

我认识到你希望通过停止一次简短的阅读来保存一个EV_CLEAR电话,但我认为这会给这个过程带来真正的风险,这个过程可以无限期地保留传入的数据流。此外,除非您确定这些额外的读取是导致可测量的,不可接受的性能消耗的原因,否则您的担忧是不成熟的。