EPOLLLET可以与Edge Trigger比赛吗?

时间:2017-08-31 11:29:58

标签: race-condition epoll

假设我的进程使用epoll和Edge Trigger,以及以下内容 场景发生:

  1. 调用epoll_wait,成功完成一个fd阅读。
  2. 当recv()成功时,继续阅读所有数据
  3. recv()返回EWOULDBLOCK
  4. 现在有更多数据
  5. 转到步骤#1
  6. epoll_wait()会立即返回吗?或者等到下一个数据进入?

2 个答案:

答案 0 :(得分:1)

会立即返回。

不幸的是,边缘触发模式描述得不是很好(不是以任何方式,所以正常人无法理解它并且无论如何都不能做出错误的假设)。

它的作用是,当描述符的状态变为“就绪”(或者,无论你等待什么)时,它只生成一个事件,这意味着epoll_wait()将返回一次。然而,这不是故事的结局。

一旦状态转换为“未准备好”并返回,它就会生成下一个事件。这一点非常重要。单独进入的数据通常不够(虽然根据文档可能,并且传入数据可能生成多个事件。 。bleh)。

对于像插座或管道之类的东西,细微之处并不重要,因为无论如何你都要读取数据。这也是显而易见的,如果你考虑一下,它也很有意义。

如果描述符为false,则强调将{1}}翻转回true非常重要。假设您只需要唤醒服务员就可以发出eventfd的信号(并且它不会多次唤醒等待的线程,这很好)。当然,这就是它必须如何,而不是任何不同。没有人关心你发布的价值,呵呵......它只能存储一个被覆盖的值,而且我也不在乎阅读它。

嗯,这是如何运作,因为我发现了困难。唤醒一次后,您需要实际读取描述符,以便在再次等待之前将状态翻转为“未就绪”。否则,出乎意料的是,自你上次醒来以来另一件事发生的事实是无关紧要的 再说一次,如果你考虑一下,这甚至是有道理的。它可能不是你所期望的。

编写程序的方式,它将按预期工作。但请注意,只给出一个描述符,阻止它会更有效。

答案 1 :(得分:1)

这实际上是在epoll(7) manual page中解答的(在“水平触发和边缘触发”一节中)。

手册中说的是它应该可以正常工作,因为EPOLLET事件是由更改触发的,并且更改发生在您的步骤4中。

手册页甚至说使用EPOLLET解决问题的方法是

  
      
  1. 带有非阻塞文件描述符;以及

  2.   
  3. 仅在read(2)write(2)返回EAGAIN之后等待活动。

  4.   

您已经做过的事情(即使您使用等效的EWOULDBLOCK代替EAGAIN)。

简而言之:当您迭代回到第1步时,epoll_wait应立即返回。