IO复用模型epoll
一、简介
epoll是Linux多路复用IO接口select/poll的加强版,e对应的英文单词就是enhancement【增强】
定义:epoll是一种当文件描述符的内核缓冲区非空的时候,发出可读信号进行通知,当写缓冲区不满的时候,发出可写信号通知的机制
二、方法
-
epoll_create :创建epoll实例,会创建所需要的红黑树,以及就绪链表,以及代表epoll实例的文件句柄
-
epoll_ctl:添加,修改,或者删除 注册到epoll实例中的文件描述符上的监控事件
-
epoll_wait:等待epoll实例中注册的事件触发
三、流程
1、进程调用epoll_create方法时,Linux内核会创建一个eventpoll结构体。
struct eventpoll{
....
/*红黑树的根节点【红黑树数据结构,操作时间复杂度lgn】,这颗树中存储着所有添加到epoll中的需要监控的事件*/
struct rb_root rbr;
/*双链表中则存放着将要通过epoll_wait返回给用户的满足条件的事件*/
struct list_head rdlist;
....
};
2、进程调用epoll_ctl方法,向epoll对象中添加事件对象,这些事件对象会存储在rbr红黑树上,所有添加到epoll中的事件都会与设备(网卡)驱动程序建立回调关系,也就是说,当相应的事件发生时会调用这个回调方法。这个回调方法在内核中叫ep_poll_callback,它会将发生的事件添加到rdlist双链表中。
事件对象—epitem结构体
struct epitem{
struct rb_node rbn;//红黑树节点
struct list_head rdllink;//双向链表节点
struct epoll_filefd ffd; //事件句柄信息
struct eventpoll *ep; //指向其所属的eventpoll对象
struct epoll_event event; //期待发生的事件类型
}
3、调用epoll_wait检查是否有事件发生时,只需要检查eventpoll对象中的rdlist双链表中是否有epitem元素即可。如果rdlist不为空,则把发生的事件复制到用户态,同时将事件数量返回给用户。
三部曲:
第一步:epoll_create()系统调用。此调用返回一个句柄,之后所有的使用都依靠这个句柄来标识。
第二步:epoll_ctl()系统调用。通过此调用向epoll对象中添加、删除、修改感兴趣的事件,返回0标识成功,返回-1表示失败。
第三部:epoll_wait()系统调用。通过此调用收集收集在epoll监控中已经发生的事件。
四、工作模式
水平触发(level-trggered) :
只要文件描述符关联的读内核缓冲区非空,有数据可以读取,就一直发出可读信号进行通知,
当文件描述符关联的内核写缓冲区不满,有空间可以写入,就一直发出可写信号进行通知
边缘触发(edge-triggered) :
当文件描述符关联的读内核缓冲区由空转化为非空的时候,则发出可读信号进行通知,
当文件描述符关联的内核写缓冲区由满转化为不满的时候,则发出可写信号进行通