select、poll、epoll的原理与区别

本文详细介绍了Linux中IO复用的三种方法:select、poll和epoll的工作原理及区别。select存在文件描述符数量限制和线性扫描的效率问题,poll改进了描述符存储方式,而epoll则引入了事件注册和回调机制,提供更高效和灵活的IO管理。epoll的LT和ET模式分别适用于不同场景,其性能优势在于减少了轮询和系统调用的次数。

转载: select、poll、epoll的原理与区别

IO复用

select、poll、epoll都是IO复用的基本实现,select出现的最后,之后是poll,再是epoll。

Select

我们使用select就可以实现同时处理多个网络连接的IO请求,基本原理就是程序调用select,然后整个程序就进入阻塞状态,这个时候,kernel内核就会轮询检查所有select负责的文件描述符fd,当找到其中哪个数据准备好了文件描述符,会返回给select,select通知系统调用,将数据从内核复制到进程的缓存区。

原理图如下:

836qER.png

时间复杂度未O(n)

缺点:

进程可以打开的fd有限制,(32位机1024个,64位2048个)(原因是存储fd是一个固定大小的数组)
对socket进行扫描是线性扫描,即采用轮询的方法,效率较低。
用户空间和内核空间之间复制数据非常的消耗资源

poll

poll的基本原理和select非常的类似,但是采用的是链表来存储fd,且poll相比select不会修改描述符。poll相对于select提供了更多的事件类型,并且对描述符的重复利用比select高。

select和poll的返回结果没有声明哪些描述符已经准备好了,如果返回值大于0.,应用进程就需要使用轮询的方式找到IO完成的描述符。这也是影响效率的一大因素

epoll

epoll提供了三个函数:

//  建立一個 epoll 对象,并传回它的id
    int epoll_create(int size);
  
//事件注册函数,将需要监听的事件和需要监听的fd交给epoll对象
    int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
    
//等待注册的事件被触发或者timeout发生
    int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

epoll主要解决了这些问题:

  • 对fd的数量没有限制,所以最大数量与能打开的fd数量有关。

  • epoll不再需要每次调用都从用户空间将fd_set复制到内核

  • select和poll都是主动去轮询,需要遍历每个fd。而epoll采用的是被动触发的方式,给fd注册了相应的事件的时候,为每个fd指定了一个回调函数,当数据准备好后,就会把就绪的fd加入到就绪队列中,epoll_wait的工作方式实际上就是再这个就绪队列中查看有没有就绪的fd,如果有,就唤醒就绪队列上的等待者,然后调用回调函数。

  • 就是select和poll只能通知有fd已经就绪了,但不能知道究竟是哪个fd就绪,所以select和poll就要去主动轮询一遍找到就绪的fd。而epoll则是不但可以知道有fd可以就绪,而且还具体可以知道就绪fd的编号,所以直接找到就可以,不用轮询。这也是主动式和被动式的区别。
    epoll有两种触发方式:LT(水平触发),ET(边缘触发)

  • LT模式:当epoll_wait()检查到描述符事件到达时,将此事件通知进行,进程可以不立即处理该事件,下次调用epoll_wait()会再次通知进程。是默认的一种模式,并且同时支持Blocking和No-Blocking。

  • ET模型:和LT模式不同的是,通知之后进程必须立即处理事件,下次再调用epoll_wait()时不会再得到事件到达的通知。ET模式很大程度上减少了epoll事件被重复触发的次数,因此效率比LT模式要高。只支持No-Blocking,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。
    881oqg.png

应用场景

select应用场景

select的timeout参数精度为1nm,比poll和epoll的1ms精度更高,因此select适合实时性要求比较高的场景。select的可移植性非常的好。

poll应用场景

poll没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用poll而不是select

epoll应用场景

只需要运行在linux平台下,有大量的描述符需要同时轮询,并且这些连接最好时长连接。在监听少量的描述符的适合,体现不出epoll的优势。

在需要监控的描述符状态变化多,而且都是非常短暂的,也没有必要使用epoll。因为epoll中的所有描述符都存储在内核中,造成了每次需要对描述符的状态改变都需要通过epoll_ctl()进行系统调用,频繁的系统调用降低了效率。并且因为epoll的描述符存储在内核中,不容易调试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值