1

在使用边缘触发和 EPOLLONESHOT 时,我对 EPOLL 有一些疑问。

下面列出了简化的语句序列。实际上,多个文件由一个 Epoll Fd 监控,一组文件通过特定线程进行管理。使用的变量名不言自明,当然是设置好的。为简洁起见,省略了该部分:

1.  Create epollFd
  epollFd = epoll_create1(EPOLL_CLOEXEC);

2.  Create events to monitor
  epollEventParam.events  = EPOLLIN |  EPOLLPRI | EPOLLERR | EPOLLHUP | EPOLLET | EPOLLONESHOT;


3.  Add the FD to monitor and the events
  epoll_ctl(epollFd, EPOLL_CTL_ADD, socketFd, &epollEventParam);

4.  While loop with epoll_wait
   while (1) {

     noFdsEvented = epoll_wait(epollFd, epollEventsReported, maxEvents, -1);


     /***************** REARM Here or after processing the events? ******/
     epoll_ctl(epollFd, EPOLL_CTL_MOD, (int)epollEventsReported[i].data.fd, &epollEventParam);


     /** if EPOLLIN, read until read returns EAGIN  ***/
     //Relevant code to read...
     //After EAGAIN is returned, REARM Here instead of doing so earlier (above)?

     /** if EPOLLOUT, write until write returns EAGIN  ***/
     //Relevant code to write...
     //After EAGAIN is returned, REARM Here instead of doing so earlier (above)?

     /*** If other events... process accordingly ***/

}

问题:

  1. 使用 EPOLLONESHOT 时,应何时重新武装 EPOLL?收到事件后还是处理完事件后?

  2. 初级。在写入或读取时,我们会跟踪写入/读取的数据点,直到返回 EAGAIN 或部分读取/写入?是/否。

  3. 最初没有设置 EPOLLOUT。写入时,当write返回EAGAIN时,我们将EPOLLOUT添加到要监控的事件中。是/否?

  4. 当 FD 再次触发 EPOLLOUT 时,我们从上次收到 EAGAIN 的点继续写入,直到我们再次获得 EAGAIN。然后我们重新武装。是/否?

  5. 如果我们读取部分而不重新ARM,新数据将继续到达但不会触发任何事件。因此,如果我们读取部分内容,我们需要对其进行跟踪,而不是仅依赖事件处理程序进行读取处理。对?

4

1 回答 1

1

我不能全部回答,但我可以尝试回答几个。

  1. 初级。在写入或读取时,我们会跟踪写入/读取的数据点,直到返回 EAGAIN 或部分读取/写入?是/否。
    • 对于读取/接收:您应该处理以下所有情况
      1. 如果您阅读/接收 EAGAIN 或 EWOULDBLOCK。这表明没有任何东西可以读取/接收,您应该从接收循环中中断。
      2. 您收到 0 个字节。这表明另一端不再连接
      3. 您收到 0 > 个字节。您成功读取/接收数据,应该再次读取/接收。
    • 您不一定需要跟踪数据,而只是确保您处理上述 3 种情况。
  2. 最初没有设置 EPOLLOUT。写入时,当write返回EAGAIN时,我们将EPOLLOUT添加到要监控的事件中。是/否?

    • 是的...我相信在最初设置 EPOLLOUT 的情况下,send() FD 上的行为应该与您在问题中描述的一样...假设您将简单地写入 FD 而不管事件通知如何并且只有在收到 EAGAIN/EWOULDBOCK 错误时才停止。
于 2020-03-23T22:41:08.250 回答