【问题标题】:What is the use case for EPOLLET? [closed]EPOLLET 的用例是什么? [关闭]
【发布时间】:2017-10-08 16:32:51
【问题描述】:

epoll在边沿触发模式下是一头奇怪的野兽。它要求该过程跟踪每个受监视 FD 的最后响应是什么。它要求进程无误地处理报告的每个事件(否则我们可能会认为 FD 没有报告任何内容,而实际上它被边缘触发行为静音了)。

边沿触发epoll 有意义的用例有哪些?

【问题讨论】:

    标签: linux epoll epollet


    【解决方案1】:

    据我所知,EPOLLET 的主要用例是微线程。

    回顾一下 - 用户空间正在根据工作的可用性在微线程(我将其称为“纤程”,因为它更短)之间进行上下文切换。这也称为“协作多任务”。

    文件描述符的基本处理是通过像这样包装相关的 IO 函数:

    ssize_t read(int fd, void *buffer, size_t length) {
      // fd should already be in O_NONBLOCK mode
      while(true) {
        ssize_t result = ::read(fd, buffer, length); // The real read
        if( result!=-1 || (errno!=EAGAIN && errno!=EWOULDBLOCK) )
          return result;
    
        start_monitoring(fd, READ);
        wait_event();
      }
    }
    

    start_monitoring 是一个确保fd 被监控读取可用性的函数。 wait_event 执行上下文切换,直到调度程序重新唤醒此纤程,因为 fd 现在已准备好读取数据。

    使用epoll 实现此功能的常用方法是在start_monitoring 内的fd 上调用EPOLL_CTL_MOD 以添加对EPOLLIN 的侦听,并在epoll 报告事件后再次停止侦听@987654332 @。

    这意味着有可用数据的 read 将在 1 个系统调用内完成,但返回 EAGAIN 的读取将需要至少 4 个系统调用(原始 read,两个EPOLL_CTL_MOD,最后一个成功的read)。

    请注意,上述内容不包括也必须发生的epoll_wait。我没有计算它,因为我假设其他纤程也将被同一个系统调用唤醒,因此将其成本完全归因于我们的纤程是不公平的。总而言之,这个机制需要 4+x 个系统调用,其中 x 介于 0 和 1 之间。

    降低成本的一种方法是使用EPOLLONESHOT。这样做会自动将fd 从监控中移除,从而将我们的成本降低到 3+x。更好,但我们还可以做得更好。

    输入EPOLLET。之前的fd 状态可以是武装或非武装(即——下一个事件是否会触发epoll)。此外,fd 当前(在进入read 时)可能有也可能没有准备好数据。四个州。让我们把它们散开。

    就绪(无论是否启用):第一次调用read 返回数据。 1 个系统调用。这条路径不会改变武装状态,就绪状态取决于我们是否读取所有内容。

    未准备好(无论是否武装):第一次调用read 返回EAGAIN,从而武装fd。我们在wait_event 中休眠,而无需执行另一个系统调用。一旦我们醒来,我们就处于非武装模式(因为我们刚刚醒来)。因此,我们不需要调用epoll_ctl 来禁用对 fd 的侦听。我们调用read 返回数据。我们让函数准备好或不准备好,但没有准备好。

    总成本:2+x。

    我们将不得不面对每个fd 的一次虚假唤醒,因为fd 开始武装。我们的代码必须处理epoll 报告没有光纤正在侦听的 fd 的情况。在这种情况下,处理只是意味着忽略并继续前进。 FD 不会再次被虚假报告。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-16
      • 2010-11-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多