【问题标题】:Kqueue (edge-triggered): Does a short read mean that read-readiness was lost?Kqueue(边缘触发):短读是否意味着读准备丢失?
【发布时间】:2017-02-28 15:15:00
【问题描述】:

在边沿触发模式 (EPOLLET) 下使用 Linux epoll 时,读/写失败并出现EAGAIN/EWOULDBLOCK,这意味着读/写准备丢失,并且保证一旦恢复就绪状态,就会通过epoll_wait() 提供新的就绪事件。

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

类似地,在边缘触发模式 (EV_CLEAR) 下使用 Kqueue (macOS/FreeBSD) 时,读取/写入失败并出现 EAGAIN/EWOULDBLOCK,这意味着读取/write-readiness 丢失了,一旦重新准备就绪,就可以通过kevent() 保证新的准备就绪事件可用。

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

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

Linux epoll 上下文中短读/写的含义,来自epoll(7) 手册页中的这条评论:

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

【问题讨论】:

    标签: c macos freebsd epoll kqueue


    【解决方案1】:

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

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

    (BSD documentation for kqueue())

    另外,你规定程序有

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

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

    不管怎样,你问题的核心是

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

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

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

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

    【讨论】:

    • 请注意,我在这个问题中假设非阻塞模式套接字,因此不会发生由于信号中断而导致的短读,至少在 Linux 上不会发生,而且我认为通常在任何类似 POSIX 的系统上。
    • Linux 上的短读/写保证意味着“失去读准备”,至少从 epoll 的角度来看是这样。这在 epoll 手册页(我在问题中引用的部分)中有明确说明。
    • 注意,我不包括 EV_EOF 事件(设置了该标志的事件)未决或已收到的情况,因为在这种情况下,短读总是由输入的结束,而不是读取准备的丢失。对于带有 Linux epoll 的 EPOLLRDHUP 也是如此。
    猜你喜欢
    • 2010-12-27
    • 2023-03-03
    • 2013-07-18
    • 2011-05-28
    • 1970-01-01
    • 2014-08-23
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多