【IO复用】epoll和select以及poll的区别

select原理

说在前面,整个select在内核空间中的工作事实上非常有趣,中间还会穿插一些可抢占点,检测当前是否有进程可以调度,增加系统的实时性

初始化阶段:

FD_set,把要监听的fd都添加到监听集合中去

监听/唤醒 阶段:

调用select()

通过系统调用,会把监听集合中所有fd都copy到kernel space,并填充fds数据结构

调用poll_initwait(),(作用待探究)

(第一次遍历!)遍历fds中有效的fd,判断fd对应的文件有没有打开,如果打开了就调用设备文件节点对应的driver中的poll

这个poll做的事情是把当前进程挂到对应driver的等待队列中,并设置一个回调函数(当数据到了,有数据可读,则触发硬件中断,并在硬件中断处理中调用回调函数,从而唤醒这个driver的等待队列中的进程去对数据进行操作)

(实际上发生阻塞的位置)在do_select中调用schedule_timeout阻塞进程

(从阻塞中返回,唤醒进程的位置)当数据来了,driver中断处理调用wake_up来唤醒进程,也是返回到这个time_out这里

(第二次遍历!)从schedule_timeout返回后又要重新遍历fd,给有事件发生的fd添加一个mask掩码

把fd复制回userspace

select()返回

数据处理阶段

(FD_ISSET)通过FD_ISSET()判断是什么fd可读/可操作,从而去进行数据处理

总结:

以上这个过程一般放在一个for(;;)中,也就是说会重复调用select,这个过程会发生多次内核态和用户态的切换和数据拷贝,此外,还有两次对全部fd的遍历,当fd数量上来以后,性能上的损耗就会非常大。

poll原理

 poll在内核中组织fd的方式与select不同,所以破除了文件描述符的限制(用的链表,可以增删,select固定是1024个)

epoll原理

epoll做的事和select一样,都是监听,但是方法不同,分析epoll相对于select的改进,我们先看看select都有哪些缺点

select的几大缺点:

(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

(2)同时每次调用select(无论是初始化阶段还是唤醒阶段)都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大

(3)select支持的文件描述符数量太小了,默认是1024

接下来我们看看epoll如何改进这些缺点:

对于(1),epoll提供了epoll_ctl接口,每当需要监听新的fd时,则只需把新增的fd拷贝到内核,不需要重复拷贝全部集合;在epoll中,fd在内核的组织形式是红黑树,相较于select的fd_set和poll的pollfd,红黑树增删改查的效率都要高得多

对于(2),还是epoll_ctl接口,在注册新的fd的时候,就会把current(当前进程,后面都用current指代)挂到driver的等待队列上,并注册回调函数,这点跟select第一次遍历做的事情很像,所以事实上epoll也做了遍历这件事,但是它只做了这一次,而且在每次新增fd的时候,也是O(1)复杂度的增加操作

另外,select在唤醒后会遍历所有fd,而epoll在来数据了以后,epoll在driver的中断处理程序中注册的回调函数,不是简单的给fd集合增加一个mask掩码,而是把有事件到来的需要读写的fd都添加到了一个双链表,从而当epoll_wait返回的时候,只需要处理双链表中的fd即可

此外,epoll_wait返回的时机也是相当有趣的(详见epoll源码分析一篇),在调用epoll时可以设置参数,分别设置为:

  • 一直等待,直到有fd有效才返回
  • 立即返回,无论有没有fd有效
  • 在设定的时间内等待,有fd有效或者时间到了就返回

对于(3),epoll支持的文件描述符数量,在1GB大小内存的机器上,数量大概在10万个左右

总结:

epoll对于select的改进主要在于以下几点:

1、另外提供了一个关键的epoll_ctl接口来管理和组织监听集合,不像select那样只有一个select()接口做完所有的事情了

2、管理监听集合(全部fd)的数据结构采用了红黑树,效率更高,并且只在需要增加新fd时增加,不会重复多次拷贝遍历

3、另外采用了一个双链表来管理有效的fd,虽然在epoll_wait返回后也放生了把有效fd从链表拷贝到用户空间的过程,但数量级肯定是小了很多的

 

posted on   甲鱼写代码  阅读(198)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示