上一篇博客https://www.cnblogs.com/yongjin-hou/p/14655881.html提到,与 poll 的事件宏相比,epoll 新增了两个事件宏 EPOLLET和EPOLLONESHOT,EPOLLET事件类型对应的就是水平触发模式,今天要讲的是EPOLLONESHOT事件类型。
即使我们使用EL模式,一个fd上的某个事件仍可能被触发多次。比如在多线程程序中,线程A读取完fd上的数据后开始处理这些数据,在处理过程中,fd上又有新数据可读,此时,线程B来读取并处理这些数据;出现了两个线程同时处理一个fd的情况,而我们期望一个fd在任何时候都只被一个线程处理。
我们可以通过注册EPOLLONESHOT事件来解决上述问题,对于注册了EPOLLONESHOT事件的fd,操作系统最多触发其上注册的一个可读/可写/异常事件,且只触发一次,这样,一个线程在处理某个fd时,另一个线程是不可能有机会操作该fd的;同时,当fd上的事件被某个线程处理完之后,需要立即重置EPOLLONESHOT事件,确保下一次有时间发生时,能够被触发,让其他线程有机会处理该fd。