多路复用IO实现方式:select,poll,epoll的区别

三种多路复用IO实现方式:select,poll,epoll的区别

直接看表:
多路复用IO实现方式:select,poll,epoll的区别



以下内容转载于:http://watter1985.iteye.com/blog/1614039

以上文章内部有select/poll/epoll的具体实现。

内核调用总结:

poll/select/epoll的实现都是基于文件提供的poll方法(f_op->poll),
该方法利用poll_table提供的_qproc方法向文件内部事件掩码_key对应的的一个或多个等待队列(wait_queue_head_t)上添加包含唤醒函数(wait_queue_t.func)的节点(wait_queue_t),并检查文件当前就绪的状态返回给poll的调用者(依赖于文件的实现)。
当文件的状态发生改变时(例如网络数据包到达),文件就会遍历事件对应的等待队列并调用回调函数(wait_queue_t.func)唤醒等待线程。


 poll 和 select

poll和select的实现基本上是一致的,只是传递参数有所不同,他们的基本流程如下:

1. 复制用户数据到内核空间

2. 估计超时时间

3. 遍历每个文件并调用f_op->poll 取得文件当前就绪状态, 如果前面遍历的文件都没有就绪,向文件插入wait_queue节点

4. 遍历完成后检查状态:

        a). 如果已经有就绪的文件转到5;

        b). 如果有信号产生,重启poll或select(转到 1或3);

        c). 否则挂起进程等待超时或唤醒,超时或被唤醒后再次遍历所有文件取得每个文件的就绪状态

5. 将所有文件的就绪状态复制到用户空间

6. 清理申请的资源


公共函数

 下面是poll/select公用的一些函数,这些函数实现了poll和select的核心功能。

poll_initwait 用于初始化poll_wqueues,

__pollwait 实现了向文件中添加回调节点的逻辑,

pollwake 当文件状态发生改变时,由文件调用,用来唤醒线程,

poll_get_entry,free_poll_entry,poll_freewait用来申请释放poll_table_entry 占用的内存,并负责释放文件上的wait_queue节点。

其中,poll,select对poll_table_entry的申请和释放采用的是类似内存池的管理方式,先使用预分配的空间,预分配的空间不足时,分配一个内存页,使用内存页上的空间。

流程图:

多路复用IO实现方式:select,poll,epoll的区别

epoll而言:

递归深度检测(ep_call_nested)

循环检测(ep_loop_check)

 唤醒风暴检测(reverse_path_check)

流程图:

多路复用IO实现方式:select,poll,epoll的区别