epoll_wait, epoll_pwait, epoll_pwait2 - 在epoll fd上等待I/O事件
events 指向了事件缓冲区,每当interest list中fd触发事件加入到ready list后,会将其返回到事件缓冲区中。最大返回 maxevents 个,因此 maxevent s至少大于0。返回的event顺序写入缓冲区。 timeout 参数指定epoll_wait将阻塞的毫秒数。
epoll_wait()将会一直阻塞直到:fd产生事件 / 被信号处理函数打断 / 超时。
时间测量将使用CLOCK_MONOTONIC (系统启动后到现在的时间,记录的是tick的总次数) 时钟,超时时间将向上舍入到系统时钟粒度,内核调度延迟可能让阻塞时间稍微超出。指定为-1时将无限期阻塞,指定为0时若没有可用事件则立即返回。
返回的epoll_event中,data字段与使用event_ctl(2)(EPOLL_CTL_ADD,EPOLL_CTL_MOD)传入的data一致。 (所以一般来说用fd足矣) ,而events字段是此fd触发的事件。
与epoll_wait自比,后者允许应用程序安全的等待(在调用epoll_wait(),设置自定义的信号掩码,并在epoll_wait()结束后恢复),直到文件描述等就绪或信号被捕获。
等价于:
sigmask指定为NULL时,epoll _pwait与epoll_wait相同。epoll_pwait2与epoll_pwait除timeout参数外完全相同,它指定timespec结构来执行纳秒级的等待。设为NULL时将一直等。
错误将返回-1,并设定errno;
超时将返回0;
成功将返回触发I0事件的fd个数。
epoll_wait() 在 2.6 版中被添加到内核中。 从版本 2.3.2 开始,glibc 中提供了库支持。
epoll_pwait() 在内核 2.6.19 中被添加到 Linux。 从版本 2.6 开始,glibc 中提供了库支持。
epoll_pwait2() 在内核 5.11 中被添加到 Linux。
epoll_wait(), epoll_pwait(), and epoll_pwait2() are Linux-specific.
虽然一个线程在调用 epoll_wait() 时被阻塞,但另一个线程可能会向等待的 epoll 实例添加文件描述符。 如果新的文件描述符准备好,它将导致 epoll_wait() 调用解除阻塞。
如果在调用 epoll_wait() 时有超过 maxevents 个文件描述符准备就绪,那么连续的 epoll_wait() 调用将 循环遍历 准备好的文件描述符集。 此行为有助于避免饥饿情况,即进程未能注意到其他文件描述符已准备就绪,因为它专注于一组已知已准备就绪的文件描述符。循环遍历的意义就在于避免只访问固定位置的事件。
请注意,可以在 interest-list 当前为空的 epoll 实例上调用 epoll_wait() (或者其interest-list因为文件描述符被关闭或从另一个线程中的兴趣中删除而变为空)。 该调用将阻塞,直到在另一个线程中将某个文件描述符添加到interest-list并且该文件描述符准备就绪。
C library/kernel differences
原始的 epoll_pwait() 和 epoll_pwait2() 系统调用有第六个参数 size_t sigsetsize,它指定了 sigmask 参数的字节大小。 glibc epoll_pwait() 包装函数将此参数指定为固定值(等于 sizeof(sigset_t))。
在 2.6.37 之前的内核中,大于大约 LONG_MAX / HZ 毫秒的超时值被视为 -1(即无穷大)。 因此,例如,在 sizeof(long) 为 4 且内核 HZ 值为 1000 的系统上,这意味着大于 35.79 分钟的超时被视为无穷大