没有时是否正在监视 epoll 事件 epoll_waiting
Are epoll events being watched when not epoll_waiting
我对基于事件的编程比较陌生。我正在试验 epoll
的 edge-mode,它显然只向 read/write 准备就绪的文件发出信号(与发出所有信号的电平模式相反)就绪文件,无论是否已经就绪,或刚刚准备就绪)。
我不清楚的是:在边缘模式下,我是否被告知在我未 epoll_wait
时发生的就绪事件?尚未重新武装的一次性文件的事件怎么办?
为了说明我为什么要问这个问题,请考虑以下情况:
- 连接了 10 个非阻塞套接字
- 配置
epoll_ctl
在套接字准备好读取时做出反应,在edge-mode + oneshot中:EPOLLET | EPOLLONESHOT | EPOLLIN
epoll_wait
发生某事(最多报告 10 个事件)
- linux 唤醒我的进程并报告套接字 #1 和 #2 已就绪
- 我
read
并处理数据套接字 #1(直到 E_AGAIN
)
- 我
read
并处理数据套接字 #2(直到 E_AGAIN
)
- 当我这样做时,套接字S接收数据
- 我处理了所有事件,所以我在
EPOLL_CTL_MOD
模式下用 epoll_ctl
重新准备触发文件,因为 oneshot
- 我的循环返回到
epoll_wait
处理下一批事件
好的,最后一个 epoll_wait
always 会被通知 socket S 就绪了吗?事件如果 S 是 #1(即它没有重新武装)?
I'm experimenting with epoll's edge-mode which apparently only signals
files which have become ready for read/write (as opposed to level-mode
which signals all ready files, regardless of whether there were
already ready, or just became ready)
首先让我们清楚地了解系统,您需要一个关于系统如何工作的准确心智模型。您对 epoll(7)
的看法并不准确。
边沿触发和电平触发之间的区别在于对事件的确切定义。前者为文件描述符上订阅的每个动作生成一个事件;一旦你消费了这个事件,它就消失了——即使你没有消费产生这样一个事件的所有数据。 OTOH,后者会一遍又一遍地生成相同的事件,直到您消耗掉生成该事件的所有数据。
这是一个将这些概念付诸实践的示例,公然盗自 man 7 epoll
:
The file descriptor that represents the read side of a pipe (rfd) is registered on the epoll instance.
A pipe writer writes 2 kB of data on the write side of the pipe.
A call to epoll_wait(2) is done that will return rfd as a ready file descriptor.
The pipe reader reads 1 kB of data from rfd.
A call to epoll_wait(2) is done.
If the rfd file descriptor has been added to the epoll interface using
the EPOLLET (edge-triggered) flag, the call to epoll_wait(2) done in
step 5 will probably hang despite the available data still present in
the file input buffer; meanwhile the remote peer might be expecting a
response based on the data it already sent. The reason for this is
that edge-triggered mode delivers events only when changes occur on
the monitored file descriptor. So, in step 5 the caller might end up
waiting for some data that is already present inside the input buffer.
In the above example, an event on rfd will be generated because of the
write done in 2 and the event is consumed in 3. Since the read
operation done in 4 does not consume the whole buffer data, the call
to epoll_wait(2) done in step 5 might block indefinitely.
简而言之,根本区别在于"event"的定义:边缘触发将事件视为您消耗一次的单个单元; level-triggered 将事件的消耗定义为等同于消耗属于该事件的所有数据。
现在,让我们解决您的具体问题。
in edge-mode, am I informed of readiness events that happen while I'm
not epoll_waiting
是的,你是。在内部,内核将每个文件描述符上发生的有趣事件排队。它们会在下次调用 epoll_wait(2)
时返回,因此您可以放心,您不会丢失事件。好吧,如果还有其他事件未决并且传递给 epoll_wait(2)
的事件缓冲区无法容纳所有事件,那么可能不会在下一次调用时准确显示,但重点是,最终将报告这些事件。
What about events on one-shot files that haven't been rearmed yet?
同样,您永远不会输掉比赛。如果文件描述符还没有重新装备,如果出现任何有趣的事件,它只是在内存中排队,直到文件描述符重新装备。一旦它 被 重新装备,任何未决事件 - 包括那些在描述符重新装备之前发生的 - 将在下一次调用 epoll_wait(2)
时报告(同样,可能不完全是下一次一个,但他们会被报告)。换句话说,EPOLLONESHOT
不会禁用事件监听,它只是暂时禁用事件通知。
Ok, so will the last epoll_wait always be notified of the readiness of
socket S? Event if S is #1 (i.e. it's not rearmed)?
根据我上面所说的,现在应该很清楚了:是的,会的。您不会丢失任何事件。 epoll 提供了强有力的保证,它很棒。它也是线程安全的,您可以在不同线程中等待同一个 epoll fd 并同时更新事件订阅。 epoll非常强大,值得花时间学习!
我对基于事件的编程比较陌生。我正在试验 epoll
的 edge-mode,它显然只向 read/write 准备就绪的文件发出信号(与发出所有信号的电平模式相反)就绪文件,无论是否已经就绪,或刚刚准备就绪)。
我不清楚的是:在边缘模式下,我是否被告知在我未 epoll_wait
时发生的就绪事件?尚未重新武装的一次性文件的事件怎么办?
为了说明我为什么要问这个问题,请考虑以下情况:
- 连接了 10 个非阻塞套接字
- 配置
epoll_ctl
在套接字准备好读取时做出反应,在edge-mode + oneshot中:EPOLLET | EPOLLONESHOT | EPOLLIN
epoll_wait
发生某事(最多报告 10 个事件)- linux 唤醒我的进程并报告套接字 #1 和 #2 已就绪
- 我
read
并处理数据套接字 #1(直到E_AGAIN
) - 我
read
并处理数据套接字 #2(直到E_AGAIN
) - 当我这样做时,套接字S接收数据
- 我处理了所有事件,所以我在
EPOLL_CTL_MOD
模式下用epoll_ctl
重新准备触发文件,因为 oneshot - 我的循环返回到
epoll_wait
处理下一批事件
好的,最后一个 epoll_wait
always 会被通知 socket S 就绪了吗?事件如果 S 是 #1(即它没有重新武装)?
I'm experimenting with epoll's edge-mode which apparently only signals files which have become ready for read/write (as opposed to level-mode which signals all ready files, regardless of whether there were already ready, or just became ready)
首先让我们清楚地了解系统,您需要一个关于系统如何工作的准确心智模型。您对 epoll(7)
的看法并不准确。
边沿触发和电平触发之间的区别在于对事件的确切定义。前者为文件描述符上订阅的每个动作生成一个事件;一旦你消费了这个事件,它就消失了——即使你没有消费产生这样一个事件的所有数据。 OTOH,后者会一遍又一遍地生成相同的事件,直到您消耗掉生成该事件的所有数据。
这是一个将这些概念付诸实践的示例,公然盗自 man 7 epoll
:
The file descriptor that represents the read side of a pipe (rfd) is registered on the epoll instance.
A pipe writer writes 2 kB of data on the write side of the pipe.
A call to epoll_wait(2) is done that will return rfd as a ready file descriptor.
The pipe reader reads 1 kB of data from rfd.
A call to epoll_wait(2) is done.
If the rfd file descriptor has been added to the epoll interface using the EPOLLET (edge-triggered) flag, the call to epoll_wait(2) done in step 5 will probably hang despite the available data still present in the file input buffer; meanwhile the remote peer might be expecting a response based on the data it already sent. The reason for this is that edge-triggered mode delivers events only when changes occur on the monitored file descriptor. So, in step 5 the caller might end up waiting for some data that is already present inside the input buffer. In the above example, an event on rfd will be generated because of the write done in 2 and the event is consumed in 3. Since the read operation done in 4 does not consume the whole buffer data, the call to epoll_wait(2) done in step 5 might block indefinitely.
简而言之,根本区别在于"event"的定义:边缘触发将事件视为您消耗一次的单个单元; level-triggered 将事件的消耗定义为等同于消耗属于该事件的所有数据。
现在,让我们解决您的具体问题。
in edge-mode, am I informed of readiness events that happen while I'm not epoll_waiting
是的,你是。在内部,内核将每个文件描述符上发生的有趣事件排队。它们会在下次调用 epoll_wait(2)
时返回,因此您可以放心,您不会丢失事件。好吧,如果还有其他事件未决并且传递给 epoll_wait(2)
的事件缓冲区无法容纳所有事件,那么可能不会在下一次调用时准确显示,但重点是,最终将报告这些事件。
What about events on one-shot files that haven't been rearmed yet?
同样,您永远不会输掉比赛。如果文件描述符还没有重新装备,如果出现任何有趣的事件,它只是在内存中排队,直到文件描述符重新装备。一旦它 被 重新装备,任何未决事件 - 包括那些在描述符重新装备之前发生的 - 将在下一次调用 epoll_wait(2)
时报告(同样,可能不完全是下一次一个,但他们会被报告)。换句话说,EPOLLONESHOT
不会禁用事件监听,它只是暂时禁用事件通知。
Ok, so will the last epoll_wait always be notified of the readiness of socket S? Event if S is #1 (i.e. it's not rearmed)?
根据我上面所说的,现在应该很清楚了:是的,会的。您不会丢失任何事件。 epoll 提供了强有力的保证,它很棒。它也是线程安全的,您可以在不同线程中等待同一个 epoll fd 并同时更新事件订阅。 epoll非常强大,值得花时间学习!