Linux epoll事件是否在epoll_未等待时被观看

Linux epoll事件是否在epoll_未等待时被观看,linux,epoll,event-based-programming,epollet,Linux,Epoll,Event Based Programming,Epollet,我对基于事件的编程相当陌生。我正在试验epoll的边缘模式,它显然只向已经准备好读/写的文件发送信号(与级别模式相反,级别模式向所有准备好的文件发送信号,而不管是否已经准备好或刚刚准备好) 我不清楚的是:在边缘模式下,在我不等待时,是否通知我准备就绪事件?关于尚未重新整理的一次性文件上的事件呢? 为了说明我为什么要问这个问题,考虑下面的场景: 连接10个非阻塞插座 将epoll_ctl配置为在插槽准备好读取时,在边缘模式+oneshot下做出反应:EPOLLET | epolleneshot

我对基于事件的编程相当陌生。我正在试验
epoll
边缘模式,它显然只向已经准备好读/写的文件发送信号(与级别模式相反,级别模式向所有准备好的文件发送信号,而不管是否已经准备好或刚刚准备好)

我不清楚的是:在边缘模式下,在我不等待时,是否通知我准备就绪事件?关于尚未重新整理的一次性文件上的事件呢?

为了说明我为什么要问这个问题,考虑下面的场景:

  • 连接10个非阻塞插座
  • epoll_ctl
    配置为在插槽准备好读取时,在边缘模式+oneshot下做出反应:
    EPOLLET | epolleneshot | EPOLLIN
  • epoll\u等待事件发生(最多报告10个事件)
  • linux唤醒我的进程,并报告套接字#1和#2已就绪
  • I
    读取
    并处理数据套接字#1(直到
    E#u再次
  • I
    读取
    并处理数据套接字#2(直到
    E#u再次
  • 当我这样做时,套接字接收数据
  • 我处理了所有事件,因此我在
    epoll\u ctl\u MOD
    模式下使用
    epoll\u ctl
    重新启动触发的文件,因为只有一个镜头
  • 我的循环返回到
    epoll\u wait
    ing下一批事件
好的,那么最后一个
epoll\u wait
是否总是会收到套接字准备就绪的通知?如果S为#1(即未重新武装)时发生事件

我正在试验epoll的边缘模式,它显然只发出信号 已准备好读/写的文件(与级别模式相反 它会向所有就绪文件发出信号,而不管是否存在 已经准备好,或者刚刚准备好)

首先,让我们对系统有一个清晰的认识,你需要一个系统如何工作的精确的心智模型。您对epoll(7)
的看法并不准确

“边缘触发”和“级别触发”之间的区别在于如何定义事件。前者为已在文件描述符上订阅的每个操作生成一个事件;一旦您消费了事件,它就消失了——即使您没有消费生成此类事件的所有数据。OTOH,后者会一次又一次地生成相同的事件,直到您使用生成该事件的所有数据

下面是一个将这些概念付诸实施的示例,它公然从
Man7ePoll
中窃取:

  • 表示管道读取端(rfd)的文件描述符在epoll实例上注册

  • 管道写入器在管道的写入端写入2 kB的数据

  • 完成对epoll_wait(2)的调用,该调用将rfd作为就绪文件描述符返回

  • 管道读取器从rfd读取1KB的数据

  • 对epoll_wait(2)的调用已完成

  • 如果已使用将rfd文件描述符添加到epoll接口 EPOLLET(边缘触发)标志,在中完成对epoll_wait(2)的调用 第5步可能会挂起,尽管可用数据仍存在于 文件输入缓冲区;同时,远程对等方可能期望 基于已发送数据的响应。原因是 边缘触发模式仅在上发生更改时才传递事件 监视的文件描述符。因此,在步骤5中,调用方可能会 正在等待输入缓冲区中已存在的某些数据。 在上面的示例中,由于 写入在2中完成,事件在3中消耗。自从阅读 在4中完成的操作不会消耗整个缓冲区数据,调用 步骤5中完成的等待(2)可能会无限期阻塞

    简言之,根本区别在于“事件”的定义:边缘触发将事件视为一个单独的单元,您只需消费一次;级别触发将事件的消耗定义为等同于消耗属于该事件的所有数据

    现在,让我们谈谈你的具体问题

    在边缘模式下,我是否被告知在我工作时发生的准备就绪事件 不要等待

    是的,你是。在内部,内核对每个文件描述符上发生的有趣事件进行排队。它们将在下次调用
    epoll\u wait(2)
    时返回,因此您可以放心不会丢失事件。好吧,如果有其他事件挂起,并且传递给
    epoll\u wait(2)
    的事件缓冲区不能容纳所有事件,那么下一次调用时可能不是这样,但关键是,最终会报告这些事件

    关于尚未重新整理的一次性文件上的事件呢

    同样,你永远不会输掉比赛。如果文件描述符还没有重新排列,如果出现任何有趣的事件,它将在内存中排队,直到重新排列文件描述符。重新启动后,任何未决事件(包括重新启动描述符之前发生的事件)都将在下一次调用
    epoll\u wait(2)
    时报告(同样,可能不完全是下一个事件,但会报告它们)。换句话说,
    epolonneshot
    不会禁用事件监视,它只是暂时禁用事件通知

    好的,那么最后一次epoll_等待是否总是会被通知已准备就绪 插座S?如果S为#1(即未重新武装)时发生事件


    考虑到我上面所说的,现在应该很清楚了:是的,会的。你不会输掉任何比赛。epoll提供了强有力的保证,非常棒。它也是线程安全的,您可以在不同的线程中等待相同的epollfd,并同时更新事件订阅。epoll非常强大,值得花时间学习

    真棒的回答,干杯。我会花时间去的