Linux 如果在边缘触发模式下调用epoll_ctl之前文件是可读的,那么后续的epoll_wait会立即返回吗?

Linux 如果在边缘触发模式下调用epoll_ctl之前文件是可读的,那么后续的epoll_wait会立即返回吗?,linux,epoll,Linux,Epoll,epoll是否保证在向epoll_ctl注册epoll_用于EPOLLIN的文件后,对epoll_的第一次(或正在进行的)调用会等待,并且如果文件在epoll_ctl调用之前已经可读,EPOLLET会立即返回?从我对测试程序的实验来看,答案似乎是肯定的。下面有几个例子来澄清我的问题: 假设我们已经初始化了一个epoll文件efd和一个文件fd以及以下事件定义: event.data.fd = fd; event.events = EPOLLIN | EPOLLET; 现在考虑这个场景: 线程

epoll是否保证在向epoll_ctl注册epoll_用于EPOLLIN的文件后,对epoll_的第一次(或正在进行的)调用会等待,并且如果文件在epoll_ctl调用之前已经可读,EPOLLET会立即返回?从我对测试程序的实验来看,答案似乎是肯定的。下面有几个例子来澄清我的问题:

假设我们已经初始化了一个epoll文件
efd
和一个文件
fd
以及以下事件定义:

event.data.fd = fd;
event.events  = EPOLLIN | EPOLLET;

现在考虑这个场景:

  • 线程1:将数据写入
    fd
  • 线程2:
    epoll\u ctl(efd、epoll\u ctl\u ADD、fd和事件)
  • thread2:
    epoll\u wait(efd,events,MAXEVENTS,-1)
  • 现在,步骤3中的调用是否立即返回?以我的经验,的确如此。这有保证吗

    现在考虑第二个场景,扩展第一个:

  • 线程1:将数据写入
    fd
  • 线程2:
    epoll\u ctl(efd、epoll\u ctl\u ADD、fd和事件)
  • thread2:
    epoll\u wait(efd,events,MAXEVENTS,-1)
  • 线程2:
    epoll\u ctl(efd、epoll\u ctl\u MOD、fd和事件)
  • thread2:
    epoll\u wait(efd,events,MAXEVENTS,-1)
  • 步骤5中的调用是否立即返回?以我的经验,的确如此。有保证吗

    epoll手册页对此问题并不完全清楚。特别是,手册页建议,在使用边缘触发模式时,在返回EAGAIN之前,应始终读取文件。但是,这些评论似乎是假设您在等待文件时没有重新注册该文件

    这是一个相关的讨论。第一个答案的前两条评论似乎证实了我所看到的行为是预期的


    是一个C测试程序,它说明了带有管道的epoll的行为似乎与我描述的一样

    由于
    epoll
    是特定于Linux的,因此没有真正的规范,因此基本上取决于实际实现的内容(手册页试图以更用户友好的方式描述这一点,但没有提供边缘情况的所有细节)

    查看并同时检查当前事件位(不考虑
    EPOLLET
    ):


    这就解释了你所看到的行为,而且这似乎是故意的。但是,由于没有规范,也没有铸铁材料可以保证这种行为在将来不会改变。

    是的。看起来您提到的轮询调用填充了revents,这似乎是就绪事件的位图,几行之后,有代码将这些位与正在注册的事件进行检查,如果就绪事件匹配,则将文件添加到“就绪列表”;e、 g.这里是ep_insert中的以下几行:
    /*如果文件已经“准备就绪”,我们将其放入就绪列表中*/
    如果((revents&event->events)&!ep_是链接的(&epi->Rdlink)){
    列表_添加尾部(&epi->Rdlink,&ep->rdllist);
    /*
     * Get current event bits. We can safely use the file* here because
     * its usage count has been increased by the caller of this function.
     */
    revents = epi->ffd.file->f_op->poll(epi->ffd.file, &pt);