epoll

epoll API执行一个类似的任务来poll:监视多个文件描述符来查看是否有任何I / O是可能的。 epoll API既可以用作edge-triggered的接口,也可以用作Level-triggered 的接口,并可以很好地扩展到大量的观察文件描述符。 提供以下系统调用来创建和管理epoll实例:
* epoll_create创建一个epoll实例并返回一个引用该实例的文件描述符。 (最近的epoll_create1扩展了epoll_create的功能。)
*对特定文件描述符的兴趣是通过epoll_ctl注册的。 当前在epoll实例上注册的文件描述符集有时被称为epoll集。
* epoll_wait等待I / O事件,如果当前没有事件可用,则阻塞调用线程。
级别触发和边缘触发
Level-triggered and edge-triggered

#include <sys/epoll.h>
int epoll_create(int size);
int epoll_create1(int flags);

epoll_create()创建一个epoll实例。自从Linux 2.6.8,xize参数被忽略,但必须大于零;

epoll_create()返回一个引用新的epoll实例的文件描述符。此文件描述符用于所有后续对epoll接口的调用。当不再需要时,epoll_create()返回的文件描述符应该使用close来关闭。当所有引用epoll实例的文件描述符都被关闭时,内核将销毁实例并释放相关资源以供重用。

epoll_create1()如果flags为0,那么除了废弃大小参数被删除之外,epoll_create1()epoll_create()相同。标志中可以包含以下值以获得不同的行为:
EPOLL_CLOEXEC 在新文件描述符上设置close-on-exec(FD_CLOEXEC)标志。请参阅openO_CLOEXEC标志的说明。

返回值
成功时,这个系统调用返回一个非负文件描述符。出错时,返回-1,并将errno设置为指示错误。
错误:
EINVALsize不正确
EINVAL (epoll_create1())flags中指定的值无效。

在最初的epoll_create()实现中,size参数向内核通知了调用者期望添加到epoll实例的文件描述符的数量。 内核使用这个信息作为提示描述事件的内部数据结构中最初分配的空间量。 (如果需要的话,如果调用者的用法超出了给定的提示,内核将分配更多的空间)。现在,这个提示不再需要(内核动态地调整所需数据结构的大小,而不需要提示),但大小必须是 大于零,以确保在旧的内核上运行新的epoll应用程序时向后兼容。
epoll_ctl : epoll描述符的控制接口

 #include <sys/epoll.h>

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
该系统调用对文件描述符epfd引用的epoll实例执行控制操作。 它要求对目标文件描述符fd执行操作。
op参数的有效值是:
EPOLL_CTL_ADD在文件描述符epfd引用的epoll实例上注册目标文件描述符fd,并将事件event与链接到fd的内部文件相关联。
EPOLL_CTL_MOD更改与目标文件描述符fd关联的事件event
EPOLL_CTL_DELepfd引用的epoll实例中删除(注销)目标文件描述符fd。 该事件被忽略,可以是NULL(但请参阅下面的BUGS)。
event参数描述链接到文件描述符fd的对象。 结构epoll_event被定义为:

typedef union epoll_data {
           void        *ptr;
           int          fd;
           uint32_t     u32;
           uint64_t     u64;
       } epoll_data_t;

       struct epoll_event {
           uint32_t     events;      /* Epoll events */
           epoll_data_t data;        /* 用户数据变量 */
       };

events成员是使用以下可用事件类型组成的位掩码:

EPOLLIN关联的文件可用于read操作。

EPOLLOUT关联的文件可用于write操作。

EPOLLRDHUP (since Linux 2.6.17)
流套接字关闭连接,或关闭写入连接的一半。 (当使用Edge Triggered监视时,这个标志对编写简单的代码来检测对等关闭特别有用。)

EPOLLPRI紧急数据可用于read操作。

EPOLLERR错误情况发生在关联的文件描述符上。epoll_wait将一直等待这个事件; 没有必要把它设置在事件中。

EPOLLHUP挂起发生在关联的文件描述符上。 epoll_wait将一直等待这个事件; 没有必要把它设置在事件中。 请注意,从管道或流套接字等通道读取时,此事件仅表示对等关闭了通道的末端。 只有在通道中所有未完成的数据被消耗之后,通道的后续读才会返回0(文件的结尾)。

EPOLLET设置关联文件描述符的边缘触发行为。 epoll的默认行为是电平触发。

EPOLLONESHOT (since Linux 2.6.2)
设置关联文件描述符的一次性行为。 这意味着在事件被epoll_waitpull out之后,关联的文件描述符被内部禁用,epoll接口不会报告其他事件。 用户必须使用

EPOLL_CTL_MOD调用epoll_ctl()以使用新的事件掩码重新装入文件描述符。

在2.6.9之前的内核版本中,EPOLL_CTL_DEL操作在event中需要一个非空指针,即使这个参数被忽略。 从Linux 2.6.9开始,使用EPOLL_CTL_DEL时,event可以指定为NULL。 需要在2.6.9之前移植到内核的应用程序应该在event中指定一个非空指针。

如果在flags中指定EPOLLWAKEUP,但调用者不具有CAP_BLOCK_SUSPEND功能,则EPOLLWAKEUP标志将被忽略。 这种不幸的行为是必要的,因为在原始实现中对flags参数没有进行有效性检查,并且在调用者没有CAP_BLOCK_SUSPEND能力的情况下,通过检查导致调用失败的EPOLLWAKEUP的添加至少导致了破坏 一个现有的用户空间应用程序发生随机(无用)指定此位。 因此,如果尝试使用EPOLLWAKEUP标志,强健的应用程序应该仔细检查它是否具有CAP_BLOCK_SUSPEND功能。
更多参数类型参照 man 文档。

epoll_pwait - 等待epoll文件描述符上的I / O事件

#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);

epoll_wait()系统调用等待文件描述符epfd引用的epoll实例上的事件。 事件指向的内存区域将包含调用程序可用的事件。 epoll_wait()返回最多的事件。 maxevents参数必须大于零。

timeout参数指定epoll_wait()将阻塞的毫秒数。 该呼叫将阻止,直到:
*文件描述符传递一个事件;
*呼叫被信号处理程序中断;
*超时到期。
请注意,timeout间隔将四舍五入到系统时钟粒度,并且内核调度延迟意味着阻塞间隔可能会超出一小部分。 指定-1的timeout会导致epoll_wait()无限期地被阻塞,同时指定一个等于零的timeout会导致epoll_wait()立即返回,即使没有事件可用。
结构epoll_event被定义为:

typedef union epoll_data {
           void    *ptr;
           int      fd;
           uint32_t u32;
           uint64_t u64;
       } epoll_data_t;

       struct epoll_event {
           uint32_t     events;    /* Epoll events */
           epoll_data_t data;      /* User data variable */
       };

每个返回结构体的data将包含用户使用epoll_ctl(EPOLL_CTL_ADD,EPOLL_CTL_MOD)设置的相同数据,而events成员将包含返回的事件位字段。

在2.6.37之前的内核中,超过大约LONG_MAX / HZ毫秒的timeout值被视为-1(即,无穷大)。 因此,例如,在sizeof(long)为4且kernel HZ值为1000的系统上,这意味着大于35.79分钟的超时被视为无穷大。

C library/kernel differences
原始epoll_pwait()系统调用具有第六个参数,size_t sigsetsize,它指定了sigmask参数的大小(以字节为单位)。glibc epoll_pwait()包装函数将此参数指定为固定值(等于sizeof(sigset_t))。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值