i/O复用---EPOLL
EPOLL
epoll是linux下锁独有的i/o复用的方式,不同于poll和select,前面两种方法都是使用一个函数实现,epoll采用三个函数进行实现,
分别为epoll_create()创建一个epoll句柄,可以往该句柄里面添加相应的描述符和事件。向epoll_create()创建的句柄当中添加事件是使用
epoll_ctl()函数,将对应的描述符和该描述符上感兴趣的事件注册到该句柄上,最后调用epoll_wait()来监听描述符上是否有事件发生,该
函数直接将所有有事件发生的描述符全部返回,省去了轮询的过程,因此在描述符较多,但活跃的连接较少的情况下具有较高的效率。
epoll具有两种工作模式,分别为ET和LT,称为边缘触发和水平触发。LT模式下,描述符上的事件描述符上有事件发生时,如果你没有
对该事件进行处理或者是该事件没有处理完成,那么该描述符上的事件就会被一直触发,在有大量不需要处理的描述符情况下,该种工作方
会大大的降低处理的效率。而在边缘触发的模式下,描述符上有事件时会通知,无论你是否处理或处理完成,在调用下一次的epoll_wait()
时都不会再次通知该事件,直到有新的事件发生时,才会再次触发,因此这种工作模式不会导致要处理大量的无用描述符。
Epoll的主要实现过程:
epoll_create()函数调用,epoll会在内核空间申请一个文件系统,用于存储需要监听的文件描述符,当
调用epoll_ctl()向该文件系统添加fd时,会建立一个fd文件节点,这些fd文件节点被以红黑树的组织形式存
在epoll的内核缓冲区当中,同时还会在文件系统当中建立一个就绪的链表用于存放就绪的事件描述符。
在调用epoll_ctl(),向管理的结构中插入该节点,如果该节点存在,则直接返回,否则将节点加入管理的
树当中,同时向内核注册该fd的回调函数,当该fd上有事件发生时,内核会将数据读取到内核缓冲区当中,然
后调用回调函数,将该节点加入到就绪的链表上。
调用epoll_wait()函数时,在设置的timeout超时时间前等待,到达超时时间后,会将就绪链表上的事件
直接返回到用户空间,而此时epoll_wait()返回的方式并不是使用直接将就绪的数据从内核态拷贝到用户态,
而是使用基于mmap机制实现的共享内存机制,返回的是就绪文件描述符的大小,然后共享内核的空间即可,
避免了内核态向用户态拷贝数据的开销。

浙公网安备 33010602011771号