【问题标题】:What is the purpose of epoll's edge triggered option?epoll的边缘触发选项的目的是什么?
【发布时间】:2012-02-28 01:57:19
【问题描述】:

来自 epoll 的手册页:

epoll is a variant of poll(2) that can be used either as an edge-triggered
or a level-triggered interface

什么时候会使用边缘触发选项?手册页给出了一个使用它的示例,但我不明白为什么在示例中它是必要的。

【问题讨论】:

    标签: c sockets epoll


    【解决方案1】:

    当 FD 准备好读取或写入时,您可能不一定要立即读取(或写入)所有数据。

    只要 FD 准备就绪,电平触发的 epoll 就会一直唠叨你,而边缘触发的不会再打扰你,直到你下次收到 EAGAIN (所以它的代码更复杂,但可以效率更高,具体取决于您需要做什么)。

    假设您正在从资源写入 FD。如果您将该 FD 准备好写入电平触发注册您的兴趣,您将收到持续通知,表明 FD 仍准备好写入。如果资源还不可用,那是在浪费唤醒,因为无论如何你不能再写了。

    如果您将其添加为边沿触发,您会收到 FD 已准备好写入一次的通知,然后当其他资源准备好时,您会尽可能多地写入。然后如果write(2) 返回EAGAIN,你就停止写,等待下一个通知。

    这同样适用于读取,因为您可能不想在准备好对它执行任何操作之前将所有数据拉入用户空间(因此必须对其进行缓冲等)。使用边缘触发的 epoll,您会在准备好读取时被告知,然后可以记住这一点并“随时”进行实际读取。

    【讨论】:

    • 这种边缘触发的行为在竞争条件下是否安全,例如如果在read 失败并出现EAGAIN 但在调用epoll 之前数据可用?
    • 当然。 epoll 如果 FD 已经准备好并且您尚未收到通知,则会立即返回。
    • ET 对于多核机器上的多线程服务器也特别好。您可以每个内核运行一个线程,并让它们在同一个 epfd 上调用 epoll_wait。当数据进入 fd 时,只会唤醒一个线程来处理它。
    • @windfinder 如果我错了,请纠正我,但在 LT 模式下,只要数据存在,多个线程可能会在同一个 FD/SD 上并行唤醒。当数据存在时,ET one only 为 FD/SD 设置通知,因此只有一个线程会收到此类通知;其他线程可能会收到相同 FD/SD 的通知,但前提是原始线程将读取/写入通知的 all 数据;可以想象,用 ET 编写 MT epoll 进程会很多容易。希望这会有所帮助。
    • @Emanuele - 确认,ET 保证只唤醒一个线程。
    【解决方案2】:

    在我的实验中,ET 不能保证只唤醒一个线程,尽管它通常只唤醒一个。 EPOLLONESHOT 标志就是为此目的。

    【讨论】:

    • man 7 epoll:因为即使是边沿触发的epoll,在接收到多个数据块时也可以生成多个事件,调用者可以选择指定EPOLLONESHOT标志,告诉epoll 在收到带有epoll_wait(2) 的事件后禁用关联的文件描述符。当指定EPOLLONESHOT 标志时,调用者负责使用epoll_ctl(2)EPOLL_CTL_MOD 重新配置文件描述符。
    • 没错,每个上升沿都会通知您一次。如果将标准输入添加到作为 EPOLLET 的 epoll 集中,则每次按下回车键都会生成一个事件。这就是需要 EPOLLONESHOT 的原因。
    • 你有不同的 epoll FD 还是只有一个在线程之间共享?我的理解是所有 epoll FD 都应该唤醒,但共享 FD 可能只有一个线程。新的EPOLLEXCLUSIVE 修复了多个 epoll FD 的雷鸣般的羊群问题。
    • 我的意思是多个线程在等待一个 FD。如果未设置 EPOLLONESHOT 标志,有时会唤醒多个线程。如果设置了标志,只有一个会醒来。
    猜你喜欢
    • 2016-07-08
    • 2014-10-14
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    相关资源
    最近更新 更多