概述
由于 poll() 和 select() 的局限,Linux 2.6内核引入了 event poll(epoll) 机制。虽然 epoll 的实现比 poll() 和 select() 要复杂得多,epoll 解决了前两个存在的基本性能问题,并增加了一些新的特性。
对于poll() 和 select(),每次调用时都需要所有被监听的文件描述符列表。内核必须遍历所有被监视的文件描述符。当这个文件描述符列表变得很大时——包含几百个甚至几千个文件描述符时——每次调用都要遍历列表就变成了规模上的瓶颈。
epoll 把监听注册从实际监听中分离出来,从而解决了这个问题。一个系统调用会初始化 epoll 上下文,另一个从上下文中加入或删除监视的文件描述符,第三个执行真正的事件等待(event wait)。
Event Poll
创建新的 epoll 实例
通过 epoll_create1() 创建 epoll 上下文:
#include <sys/epoll.h>
int epoll_create1 ( int flags);
/* deprecated. use epoll_create1() in new code */
int epoll_create (int size);
调用成功时,epoll_create1() 会创建新的 epoll 实例,并返回和该实例关联的文件描述符。这个文件描述符和真正的文件没有关系,仅仅是为了后续调用 epoll 而创建的。参数 flags 支持修改 epoll 行为,当前,只有 EPOLL_CLOEXEC 是个合法的 flag,它表示进程被替换时关闭文件描述符。
出错时,返回 -1,并设置 errno 为下列值之一:
EINVAL 参数 flags 非法
EMFILE 用户打开的文件数达到上限
ENFILE 系统打开的文件数达到上限
ENOMEN 内存不足,无法完成本次操作
epoll_create() 是老版本的epoll_create1()的实现,现在已经废弃。它不接受任何标志位。相反地,它接收 size 参数,该参数没有用。size 之前是用于表示要监视的文件描述符个数;现在,内核可以动态获取数据结构的大小,只需要 size 参数大于 0 即可。如果 size 值小于0,会返回 EINVAL。如果应用所运行的系统其Linux版本低于Linux内核2.6.27 以及 glibc 2.9,应该使用老的 epoll_create() 调用。
epoll 的标准调用方式如下:
int epfd;
epfd = epoll_create1 (0);
if (epfd < 0) {
perror ("epoll_create1");
}
当完成监视后,epoll_create1() 返回的文件描述符需要通过 close() 调用来关闭。
控制 epoll
epoll_ctl() 函数可以指向的 epoll 上下文中加入或删除文件描述符:
&nbs