- epoll 是 Linux 特有的 I/O 复用函数。
- 它在实现和使用上与 select、poll 有很大差异。
- 首先,epoll 使用一组函数来完成任务,而不是单个函数。
- 其次,epoll 把用户关心的文件描述符上的事件放在内核里的一个事件表中。
- 从而无需像 select 和 poll 那样每次调用都要重复传入文件描述符或事件集。
- 但 epoll 需要使用一个额外的文件描述符,来唯一标识内核中的这个事件表。
实现机制
当某一进程调用epoll_create方法时,Linux内核会创建一个eventpoll结构体,这个结构体中有两个成员与epoll的使用方式密切相关。eventpoll结构体如下所示:
struct eventpoll{
....
红黑树的根节点,这颗树中存储着所有添加到epoll中的需要监控的事件
struct rb_root rbr;
双链表中则存放着将要通过epoll_wait返回给用户的满足条件的事件
struct list_head rdlist;
....
};
每一个epoll对象都有一个独立的eventpoll结构体,用于存放通过epoll_ctl方法向epoll对象中添加进来的事件。这些事件都会挂载在红黑树中,如此,重复添加的事件就可以通过红黑树而高效的识别出来(红黑树的插入时间效率是lgn,其中n为树的高度)。
.
而所有添加到epoll中的事件都会与设备(网卡)驱动程序建立回调关系,也就是说,当相应的事件发生时会调用这个回调方法。这个回调方法在内核中叫ep_poll_callback,它会将发生的事件添加到rdlist双链表中。
在epoll中,对于每一个事件,都会建立一个epitem结构体,如下所示:
struct epitem{
struct rb_node rbn;红黑树节点
struct list_head rdllink;双向链表节点
struct epoll_filefd ffd