关于使用Epoll Edge Triggered时re-arming EPOLL的时机问题及相关问题
Question on the timing of re-arming EPOLL and related questions when using Epoll Edge Triggered
我对使用 Edge Triggered 和 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 ***/
}
问题:
使用EPOLLONESHOT时,什么时候REARMED EPOLL?事件接收后还是事件处理后?
初级。写入或读取时,我们会跟踪数据点 written/read 直到返回 EAGAIN 或部分 read/written? Yes/No.
最初没有设置 EPOLLOUT。写的时候,写returnsEAGAIN的时候,我们把EPOLLOUT加到事件中
被监控。 Yes/No?
当一个FD再次触发EPOLLOUT时,我们从上次接收到EAGAIN的点继续写入
一直这样做,直到我们再次获得 EAGAIN。然后我们重新武装。 Yes/No?
如果我们只读了一部分,不REARM,新数据会不断到达,但不会触发任何事件。
所以,如果我们部分读取,我们需要跟踪它,而不是仅仅依靠事件处理程序来进行读取处理。对吧?
我不能全部回答,但我可以尝试回答一些。
- 初级。写入或读取时,我们会跟踪数据点 written/read 直到返回 EAGAIN 或部分 read/written? Yes/No.
- 对于read/recv:您应该处理以下所有情况
- 如果您 read/recv EAGAIN 或 EWOULDBLOCK。这表明 read/recv 没有任何剩余,您应该从接收循环中中断。
- 您收到 0 个字节。这表示对方已经没有连接了
- 您收到 0 > 个字节。您成功 read/recv 数据,应该再次 read/recv。
- 您不一定需要跟踪数据,只需确保处理上述 3 种情况即可。
最初没有设置 EPOLLOUT。写的时候,写returnsEAGAIN的时候,我们把EPOLLOUT加入到要监听的事件中。 Yes/No?
- 是的...我相信在最初设置 EPOLLOUT 的情况下,send() FD 上应该会出现与您在问题中描述的相同的行为...假设您只需写入 FD无论事件通知如何,只有在收到 EAGAIN/EWOULDBOCK 错误后才会停止。
我对使用 Edge Triggered 和 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 ***/
}
问题:
使用EPOLLONESHOT时,什么时候REARMED EPOLL?事件接收后还是事件处理后?
初级。写入或读取时,我们会跟踪数据点 written/read 直到返回 EAGAIN 或部分 read/written? Yes/No.
最初没有设置 EPOLLOUT。写的时候,写returnsEAGAIN的时候,我们把EPOLLOUT加到事件中 被监控。 Yes/No?
当一个FD再次触发EPOLLOUT时,我们从上次接收到EAGAIN的点继续写入 一直这样做,直到我们再次获得 EAGAIN。然后我们重新武装。 Yes/No?
如果我们只读了一部分,不REARM,新数据会不断到达,但不会触发任何事件。 所以,如果我们部分读取,我们需要跟踪它,而不是仅仅依靠事件处理程序来进行读取处理。对吧?
我不能全部回答,但我可以尝试回答一些。
- 初级。写入或读取时,我们会跟踪数据点 written/read 直到返回 EAGAIN 或部分 read/written? Yes/No.
- 对于read/recv:您应该处理以下所有情况
- 如果您 read/recv EAGAIN 或 EWOULDBLOCK。这表明 read/recv 没有任何剩余,您应该从接收循环中中断。
- 您收到 0 个字节。这表示对方已经没有连接了
- 您收到 0 > 个字节。您成功 read/recv 数据,应该再次 read/recv。
- 您不一定需要跟踪数据,只需确保处理上述 3 种情况即可。
- 对于read/recv:您应该处理以下所有情况
最初没有设置 EPOLLOUT。写的时候,写returnsEAGAIN的时候,我们把EPOLLOUT加入到要监听的事件中。 Yes/No?
- 是的...我相信在最初设置 EPOLLOUT 的情况下,send() FD 上应该会出现与您在问题中描述的相同的行为...假设您只需写入 FD无论事件通知如何,只有在收到 EAGAIN/EWOULDBOCK 错误后才会停止。