简体   繁体   English

是否在不等待epoll_waiting时监视epoll事件

[英]Are epoll events being watched when not epoll_waiting

I'm rather new to event based programming. 我对基于事件的编程很陌生。 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). 我正在尝试使用epolledge-mode ,它显然只发出已准备好进行读/写的信号(与level-mode相对,它发出所有准备好的文件的信号,无论是否已经准备好或刚刚准备就绪) 。

What's not clear to me, is: in edge-mode, am I informed of readiness events that happen while I'm not epoll_wait ing ? 我不清楚的是: 在边缘模式下,我是否被告知当我没有epoll_wait ing时发生的准备事件? What about events on one-shot files that haven't been rearmed yet ? 尚未恢复的单发文件事件如何处理?

To illustrate why I'm asking that, consider the following scenario: 为了说明我为什么要问这个问题,请考虑以下情形:

  • have 10 non-blocking sockets connected 已连接10个非阻塞插座
  • configure epoll_ctl to react when the sockets are ready for read, in edge-mode + oneshot : EPOLLET | EPOLLONESHOT | EPOLLIN 配置epoll_ctl当所述插座是准备用于读,在边缘模式+单稳反应: EPOLLET | EPOLLONESHOT | EPOLLIN EPOLLET | EPOLLONESHOT | EPOLLIN
  • epoll_wait for something to happen (reports max 10 events) epoll_wait等待某事发生(最多报告10个事件)
  • linux wakes my process and reports sockets #1 and #2 are ready linux唤醒我的进程并报告套接字#1和#2已准备好
  • I read and process data socket #1 (until E_AGAIN ) read并处理了数据套接字#1(直到E_AGAIN
  • I read and process data socket #2 (until E_AGAIN ) read并处理了数据套接字2(直到E_AGAIN
  • While I'm doing that , a socket S receives data 在执行此操作时 ,套接字S接收数据
  • I processed all events, so I rearm the triggered files with epoll_ctl in EPOLL_CTL_MOD mode, because of oneshot 我处理了所有事件,因此由于oneshot,我在EPOLL_CTL_MOD模式下使用epoll_ctl重新触发了文件
  • my loop goes back to epoll_wait ing the next batch of events 我的循环返回到epoll_waitepoll_wait下一批事件

Ok, so will the last epoll_wait always be notified of the readiness of socket S ? 好的, epoll_wait 总是将套接字S的就绪状态通知给最后一个epoll_wait Event if S is #1 (ie it's not rearmed) ? 如果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的边缘模式,该模式显然仅信号通知已准备好进行读/写的文件(与级别模式相反,该信号通知所有准备就绪的文件,无论是否已经准备就绪或刚刚准备就绪)

First let's get a clear view of the system, you need an accurate mental model of how the system works. 首先,让我们对系统有一个清晰的了解,您需要一个关于系统如何工作的准确的思维模型。 Your view of epoll(7) is not really accurate. 您对epoll(7)看法并不十分准确。

The difference between edge-triggered and level-triggered is the definition of what exactly makes an event. 边沿触发和电平触发之间的区别在于对事件产生原因的定义。 The former generates one event for each action that has been subscribed on the file descriptor; 前者为已在文件描述符上预订的每个动作生成一个事件。 once you consume the event, it is gone - even if you didn't consume all the data that generated such an event. 一旦您使用了该事件,它就消失了-即使您没有使用所有生成此类事件的数据。 OTOH, the latter keeps generating the same event over and over until you consume all the data that generated the event. OTOH,后者会不断重复生成同一事件,直到您消耗掉生成该事件的所有数据为止。

Here's an example that puts these concepts in action, blatantly stolen from man 7 epoll : 这是一个将这些概念付诸实践的示例,这些概念被公然自man 7 epoll窃取了:

  1. The file descriptor that represents the read side of a pipe (rfd) is registered on the epoll instance. 代表管道(rfd)读取端的文件描述符在epoll实例上注册。

  2. A pipe writer writes 2 kB of data on the write side of the pipe. 管道写入器在管道的写入侧写入2 kB的数据。

  3. A call to epoll_wait(2) is done that will return rfd as a ready file descriptor. 完成对epoll_wait(2)的调用,该调用将返回rfd作为就绪文件描述符。

  4. The pipe reader reads 1 kB of data from rfd. 管道读取器从rfd读取1 kB数据。

  5. A call to epoll_wait(2) is done. 对epoll_wait(2)的调用已完成。

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; 如果已使用EPOLLET(边缘触发)标志将rfd文件描述符添加到epoll接口,则尽管文件输入缓冲区中仍然存在可用数据,但步骤5中对epoll_wait(2)的调用可能会挂起; 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. 因此,在步骤5中,调用方可能最终等待输入缓冲区中已经存在的某些数据。 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. 在上面的示例中,由于在2中完成写操作,因此将在rfd上生成一个事件,并且该事件在3中使用。由于在4中完成的读取操作不会消耗整个缓冲区数据,因此对epoll_wait(2)的调用已完成在第5步中可能会无限期屏蔽。

In short, the fundamental difference is in the definition of "event": edge-triggered treats events as a single unit that you consume once; 简而言之,根本的区别在于“事件”的定义:边缘触发将事件视为您消耗一次的单个单位; level-triggered defines the consumption of an event as being equivalent to consuming all of the data belonging to that event. 级别触发将事件的消耗定义为等同于消耗属于该事件的所有数据。

Now, with that out of the way, let's address your specific questions. 现在,让我们解决您的特定问题。

in edge-mode, am I informed of readiness events that happen while I'm not epoll_waiting 在边缘模式下,我是否得知在不epoll_waiting时发生的准备事件

Yes, you are. 是的,你是。 Internally, the kernel queues up the interesting events that happened on each file descriptor. 在内部,内核将每个文件描述符上发生的有趣事件排队。 They are returned on the next call to epoll_wait(2) , so you can rest assured that you won't lose events. 它们在下次调用epoll_wait(2) ,因此您可以放心,您不会丢失任何事件。 Well, maybe not exactly on the next call if there are other events pending and the events buffer passed to epoll_wait(2) can't accommodate them all, but the point is, eventually these events will be reported. 好吧,如果还有其他未决事件并且传递给epoll_wait(2)的事件缓冲区无法容纳所有事件,则可能不完全在下一个调用中,但是关键是最终将报告这些事件。

What about events on one-shot files that haven't been rearmed yet? 尚未恢复的单发文件事件如何处理?

Again, you never lose events. 同样,您永远不会输掉任何事件。 If the file descriptor hasn't been rearmed yet, should any interesting event arise, it is simply queued in memory until the file descriptor is rearmed. 如果还没有恢复文件描述符,那么如果发生任何有趣的事件,它只会在内存中排队,直到恢复文件描述符为止。 Once it is rearmed, any pending events - including those that happened before the descriptor was rearmed - will be reported in the next call to epoll_wait(2) (again, maybe not exactly the next one, but they will be reported). 一旦重新进入工作状态,任何未决的事件-包括那些描述符被重新进入工作状态之前发生了-将被报告到下一次调用epoll_wait(2)再次,也许不完全是下一个,但他们会报)。 In other words, EPOLLONESHOT does not disable event monitoring, it simply disables event notification temporarily. 换句话说, EPOLLONESHOT不会禁用事件监视,它只是暂时禁用事件通知

Ok, so will the last epoll_wait always be notified of the readiness of socket S? 好的,那么是否总是将套接字S的就绪状态通知给最后一个epoll_wait? Event if S is #1 (ie it's not rearmed)? 如果S为#1(即不重新设置),会发生事件吗?

Given what I said above, by now it should be pretty clear: yes, it will. 鉴于我上面所说的,现在应该很清楚:是的,它将。 You won't lose any event. 您不会丢失任何事件。 epoll offers strong guarantees, it's awesome. epoll提供了有力的保证,这很棒。 It's also thread-safe and you can wait on the same epoll fd in different threads and update event subscription concurrently. 它也是线程安全的,您可以在不同线程中等待同一epoll fd并同时更新事件订阅。 epoll is very powerful, and it is well worth taking the time to learn it! epoll非常强大,值得花时间学习它!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM