2017-08-31 52 views
1

假设我的过程中使用的epoll有边沿触发,下面 情形发生:带边缘触发器比赛的EPOLLLET可以吗?

  1. 调用epoll_wait,成功与一个FD准备好读。
  2. 同时的recv()成功,请继续阅读在现在
  3. 转到步骤#1

将epoll_wait()立即返回所有数据

  • 的recv()的返回EWOULDBLOCK
  • 更多的数据来?或等到下一个数据传入?

  • 回答

    1

    它会立即返回。

    不幸的是,边缘触发模式没有很好的描述(在任何情况下,一般人都不能理解它,并且不能做出错误的假设,无论如何,在我看来)。

    它是什么,它会产生什么时候的描述符的状态更改为“准备就绪”(或者,不管你等待)一个事件,这意味着epoll_wait()将返回一次。然而,这不是故事的结尾。

    然后,一旦状态翻转到“未准备好”并返回,它就会生成下一个事件。这一点非常重要。单独进来的数据通常不足(尽管根据文档可能是,并且输入数据可能产生多于一个事件......)。

    对于像套接字或管道或如此,细微之处并不重要,因为你要去反正读取数据什么。这也有点显而易见,如果你仔细想想,它也是非常有意义的。

    例如当您的描述符是eventfd时,重点在于翻转一次到false并返回到true。有一个假设,只要你需要唤醒一个服务员,你就可以发信号通知eventfd(并且它不会多次唤醒一个等待线程,这很好)。当然,这就是它的方式,没有什么不同。没人在乎你要么贴,呵呵......它只能存储其中一个被覆盖值的价值,我可以不关心阅读它。

    那么,这是不是事情是如何工作的,因为我发现了困难的方式。醒来一次后,您需要实际读取描述符以在再次等待之前将状态翻转为“未准备好”。否则,令人惊讶的是,自从你上次醒来以来发生的另一件事情是无关紧要的。
    再一次,如果你考虑一下,这甚至是有道理的。它可能不是你所期望的。

    你的程序写入的方式,它会正常工作。但是,请注意,只给定一个描述符,只是阻止更有效。

    1

    这在epoll(7) manual page实际上回答了(参见“电平触发和边沿触发”)。

    什么手册说的是,它应该工作正常,因为EPOLLET事件由变化触发而这种改变在你的脚步发生4

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

    1. 与非阻塞文件描述符;并且

    2. 只能在read(2)write(2)返回EAGAIN之后等待事件。

    这是你已经在做(即使你使用等效EWOULDBLOCK,而不是EAGAIN)。

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