是否在epoll_waiting时观看epoll事件

时间:2015-07-23 08:23:44

标签: linux epoll event-based-programming epollet

我对基于事件的编程很新。我正在试验epoll边缘模式,这显然只会发出已准备好进行读/写的文件信号(而不是水平模式,它会发出全部信号)准备好的文件,无论是否已经准备就绪,或者刚刚准备好了。

我不清楚的是:处于边缘模式,我是否知道在我epoll_wait之前发生的准备事件?那些尚未被重新安装的一次性文件的事件呢?

为了说明我提出这个问题的原因,请考虑以下情况:

  • 连接了10个非阻塞套接字
  • 配置epoll_ctl以便在套接字准备好阅读时做出反应,在边缘模式+ oneshot EPOLLET | EPOLLONESHOT | EPOLLIN
  • epoll_wait发生的事情(报告最多10个事件)
  • linux唤醒了我的进程并报告了套接字#1和#2已准备就绪
  • read并处理数据套接字#1(直到E_AGAIN
  • read和处理数据套接字#2(直到E_AGAIN
  • 虽然我正在,但套接字 S 会收到数据
  • 我处理了所有事件,因此我在epoll_ctl模式下使用EPOLL_CTL_MOD重新启动了触发的文件,因为oneshot
  • 我的循环回到epoll_wait下一批事件

好的,最后epoll_wait 总是会收到socket S 的准备情况吗?如果 S 为#1(即它没有重新安装),会发生什么事?

1 个答案:

答案 0 :(得分:5)

  

我正在试验epoll的边缘模式,这显然只是信号   已准备好进行读/写的文件(与级别模式相反)   它会发出所有就绪文件的信号,无论是否存在   已准备好,或刚刚准备好了)

首先,让我们清楚地了解系统,您需要一个准确的心理模型来了解系统的工作原理。您对epoll(7)的看法并不准确。

边缘触发和水平触发之间的区别在于对事件的确切定义。前者为已在文件描述符上订阅的每个操作生成一个事件;一旦你消耗了这个事件,它就会消失 - 即使你没有消耗产生这种事件的所有数据。 OTOH,后者一直反复生成相同的事件,直到你消耗了生成事件的所有数据。

这是一个将这些概念付诸实践的例子,从man 7 epoll公然被盗:

  
      
  1. 表示管道读取端(rfd)的文件描述符已在epoll实例上注册。

  2.   
  3. 管道写入器在管道的写入端写入2 kB数据。

  4.   
  5. 完成对epoll_wait(2)的调用,将rfd作为就绪文件描述符返回。

  6.   
  7. 管道读取器从rfd读取1 kB数据。

  8.   
  9. 完成了对epoll_wait(2)的调用。

  10.         

    如果已将rfd文件描述符添加到epoll接口使用   EPOLLET(边缘触发)标志,对epoll_wait(2)的调用完成   尽管仍然存在可用数据,但步骤5可能会挂起   文件输入缓冲区;同时远程同伴可能会期待一个   根据已发送的数据做出响应。原因是   边缘触发模式仅在发生更改时才传递事件   受监视的文件描述符。因此,在步骤5中,呼叫者可能会结束   等待输入缓冲区中已存在的一些数据。   在上面的示例中,将生成rfd上的事件,因为   写入2完成并且事件在3中消耗。自读取   在4中完成的操作不消耗整个缓冲区数据,即调用   在步骤5中完成的epoll_wait(2)可能会无限期地阻止。

简而言之,根本区别在于"事件":边缘触发将事件视为您消耗一次的单个单位; level-triggered定义事件的消耗等同于消耗属于该事件的所有数据。

现在,尽管如此,让我们解决您的具体问题。

  

在边缘模式下,我被告知在我的时候发生的准备事件   不是epoll_waiting

是的,你是。在内部,内核将每个文件描述符上发生的有趣事件排队。他们会在下次致电epoll_wait(2)时退回,因此您可以放心,您不会丢失任何活动。好吧,如果还有其他事件未决,并且传递给epoll_wait(2)的事件缓冲区无法容纳所有事件,那么也许不会完全在下一次调用中,但关键是,最终将报告这些事件。

  

有关未经重新安装的一次性文件的事件呢?

同样,你永远不会失去事件。如果文件描述符还没有被重新安装,如果出现任何有趣的事件,它只是在内存中排队,直到文件描述符被重新引导。一旦 重新启动,任何待处理事件 - 包括在描述符被重新启动之前发生的事件 - 将在下一次调用epoll_wait(2)时报告(再次,可能不完全是下一个,但是他们将被报道)。换句话说,EPOLLONESHOT不会禁用事件监控,它只是暂时禁用事件通知

  

好的,最后一次epoll_wait也会被告知准备好了   插座S?如果S是#1(即它没有重新安装),则会发生事件?

鉴于我上面所说的,现在应该很清楚:是的,它会。你不会输掉任何比赛。 epoll提供强有力的保证,非常棒。它也是线程安全的,您可以在不同的线程中等待相同的epoll fd并同时更新事件订阅。 epoll非常强大,非常值得花时间学习它!