欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

linux 手册翻译 - epoll_wait(2)

最编程 2024-04-15 08:42:22
...

\color{#A00000}{NAME}
epoll_wait, epoll_pwait, epoll_pwait2 - 在epoll fd上等待I/O事件

\color{#A00000}{SYNOPSIS}

#include <sys/epoll.h>
int epoll_wait (int epfd , struct epoll_event * events,
                int maxevents,int timeout);
int epoll_pwait(int epfd, struct epoll_event*events,
                int maxevents,int timeout,const sigset_t*sigmask);
int epoll_pwait2(int epfd, struct epoll_event*events, 
                int maxevents,const struct timespec*timeout,const sigset_t*sigmask

\color{#A00000}{DESCRIPTION}
events指向了事件缓冲区,每当interest list中fd触发事件加入到ready list后,会将其返回到事件缓冲区中。最大返回maxevents个,因此maxevents至少大于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_pwait( )

与epoll_wait自比,后者允许应用程序安全的等待(在调用epoll_wait(),设置自定义的信号掩码,并在epoll_wait()结束后恢复),直到文件描述等就绪或信号被捕获。

ready = epoll_pwait(epfd, &events, maxevents, timeout, &sigmask);

等价于:

sigset_t origmask;
pthread_sigmask(SIG_SETMASK, &sigmask, &origmask);
ready = epoll_wait(epfd, &events, maxevents, timeout);
pthread_sigmask(SIG_SETMASK, &origmask, NULL);

sigmask指定为NULL时,epoll _pwait与epoll_wait相同。epoll_pwait2与epoll_pwait除timeout参数外完全相同,它指定timespec结构来执行纳秒级的等待。设为NULL时将一直等。

\color{#A00000}{RETURN VALUE}
错误将返回-1,并设定errno;
超时将返回0;
成功将返回触发I0事件的fd个数。

\color{#A00000}{ERRORS}

  • EBADF
    epfd 不是有效的文件描述符。

  • EFAULT
    事件指向的内存区域不能通过写权限访问。

  • EINTR
    在事件发生或超时之前,调用被信号处理程序中断; 见信号(7)。

  • EINVAL
    epfd 不是 epoll 文件描述符,或者 maxevents 小于或等于 0。

\color{#A00000}{VERSIONS}
epoll_wait() 在 2.6 版中被添加到内核中。 从版本 2.3.2 开始,glibc 中提供了库支持。
epoll_pwait() 在内核 2.6.19 中被添加到 Linux。 从版本 2.6 开始,glibc 中提供了库支持。
epoll_pwait2() 在内核 5.11 中被添加到 Linux。

\color{#A00000}{CONFORMING TO}
epoll_wait(), epoll_pwait(), and epoll_pwait2() are Linux-specific.

\color{#A00000}{NOTES}
虽然一个线程在调用 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))。
\color{#A00000}{BUGS}
在 2.6.37 之前的内核中,大于大约 LONG_MAX / HZ 毫秒的超时值被视为 -1(即无穷大)。 因此,例如,在 sizeof(long) 为 4 且内核 HZ 值为 1000 的系统上,这意味着大于 35.79 分钟的超时被视为无穷大

推荐阅读