I/O复用、select、poll、epoll的区别以及epoll的内核实现

一、select系统调用

(1)select系统调用的用途是:在一段指定的时间内,监听用户感兴趣的文件描述符上的可读、可写和异常事件。

(2)select的实现

select的参数类型fd_set没有将文件描述符和事件绑定,它仅仅是一个文件描述符集合,因此select需要提供3个这种类型的参数来分别传入和输出可读、可写及异常等事件。这一方面使得select不能处理更多类型事件,另一方面由于内核对fd_set集合在线修改,应用程序下次调用select前不得不重置这3个fd_set集合。

二、poll

   poll函数将用户关注的文件描述符以及其关注的事件、内核返回的文件描述符上发生的事件分离开表示,并且通过一个用户数组将所有的文件描述符传递给内核。因此,poll函数能关注的事件类型更多,每次调用也不需要重新设置

三、epoll

(1)epoll通过一组函数来完成的,epoll通过epoll_create创建一个内核事件表,通过epoll_ctl函数添加、删除、修改事件,epoll_wait只需要从内核事件表中读取用户的注册事件。当某个描述符有事件发生的时候,就会触发回调函数call_back()

(2)epoll的ET/LT模式在实现上有什么区别?

a:LT模式下:描述符上事件就绪后,如果没有把数据处理完成,或者没有处理,下一次epoll会继续提醒应用程序。

    LT是默认的工作模式,这种模式下epoll相当于一个效率较高的poll

b:ET模式下:描述符上事件就绪后,如果没有把数据处理完或者没有处理,下一次epoll不会提醒应用程序,所以要求应用程序在收到一次提醒时,必须把当前的所有数据处理完成

(3)内核上两种模式的实现

  epoll_wait每次将收集到的就绪事件和描述符返回给应用程序,过程是这样的,当检测到就绪队列不为空时,就说明有事件就绪,使用ep_collect_ready_items方法将就绪队列rdlist中的数据挪到txlist中,此时,就绪队列为空。再通过ep_send_events方法将就绪事件返回给应用程序,同时又会调用ep_reinject_items方法将一些有设置EPOLLET的事件的描述符又放回到就绪队列中,这样下一轮,epoll_wait会发现有就绪事件,但会再次检查是否有数据,有就返回,没有就继续阻塞。但设置了EPOLLET事件,相应的描述符在ep_reinject_items方法中不会被放回到就绪队列中,只有等设备驱动程序检查到有事件产生才会再次将事件放到rdlist。所以,如果ET模式数据没有读完不会放回rdlist,那么也就不会再去检查是否有数据,提醒应用程序了,直到下次设备驱动程序检查到了,事件才会放入就绪队列中

四、selectpollepoll的区别(加上上面一、二、三)

(1)使用限制:

a:select所使用的fd_set结构实际上是一个整型数组,32位系统上关注的文件描述符最多1024个,最大文件描述符数是1023

b:poll和epoll的最大文件文件描述符个数是系统允许打开的最大文件描述符65535

(2)使用效率

a:select、poll每次调用都需要将用户空间的文件描述符拷贝到内核空间,epoll则直接从内核读取,效率更高

b:select、poll每次都将所有的文件描述符(就绪和未就绪的)返回,所以应用程序检索就绪文件描述符的事件复杂度位O(n),epoll通过events参数返回所有就绪的文件描述符,应用程序检索就绪文件描述符的时间复杂度位O(1)

c:select、poll只能工作在效率较低的LT模式下,而epoll则能工作在ET高效模式,并且epoll还支持EPOLLONSHOT事件,从而进一步减少事件被触发的次数

(3)内核效率

Select和poll采用轮询的方式检测就绪事件,即每次都需要扫描整个注册的文件描述符集合,并将其中就绪的文件描述符返回给用户程序,因此,内核中检测就绪文件描述符的算法事件复杂度位O(n),epoll则采用回调的方式检测就绪事件,内核检测到就绪的文件描述符,就触发回调函数,将文件描述符及发生的事件插入到内核就绪事件队列中,因此,epoll在内核中检测就绪文件描述符的算法事件复杂度位O(1),但是,当链接的活动比较频繁时,select和poll的效率要比epoll高,因此epoll的回掉函数调用过去频繁,所以,epoll适用于链接较多,但是活动不频繁的情况

(4)工作模式

select、poll使用LT,epoll使用ET模式

五、epoll的内核实现,及哪些数据结构?

  Epoll功能的实现分了三个系统调用完成

(1)epoll_create:创建内核事件表用于存放描述符和关注的事件,主要数据结构有:struct eventpoll;其中两个重要成员红黑树也就是内核事件表,和就绪事件存放的队列

(2)epoll_ctl:为红黑树添加、移除、修改节点的操作,红黑树的一个节点就是一个描述符和事件的结构体

(3)epoll_wait:负责收集就绪事件,注意是收集,所以它并没有太多的事情做,效率自然就高,那数据是怎么就绪的呢?第二步在添加数据的时候会注册回调函数,当关注的描述符上有事件就绪,就将该描述符和事件放到就绪队列,也就是第一步创建的就绪队列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值