IO多路复用模型(select ,poll,epoll)

备注:FD是File Discriptor ,中文翻译为文件描述符

        IO多路复用是什么意思?一个线程,通过记录I/O流的状态来同时管理多个I/O,可以提高服务器的吞吐能力。不好理解?举一个生活的例子。宿管大妈是你家亲戚,来帮你监视下楼的妹子, 这个期间你可以些其他的事情. 例如读书,看报等等. IO复用又包括 select, poll, epoll 模式. 那么它们的区别是什么?

        select模式:每一个女生下楼, 大妈一个一个询问, 并且大妈能力还有限, 最多一次帮你监视1024个妹子。

        poll模式:不限制盯着女生的数量, 只要是经过宿舍楼门口的女生, 都会帮你去问是不是你女神。

        epoll模式:不限制盯着女生的数量, 并且也不需要一个一个去问. 怎么做? 大妈会为每个进宿舍楼的女生脸上贴上一个大字条,上面写上女生自己的名字, 只要女生下楼了, 大妈就知道哪个是你女神了, 然后大妈再通知你。

一.select模型

        基本原理:select 函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。调用后select函数会阻塞,直到有描述符就绪(有数据 可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以通过遍历fdset,来找到就绪的描述符。

        select目前几乎在所有的平台上支持其良好跨平台支持。select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024,可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但是这样也会造成效率的降低。select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。这样所带来的缺点是:select最大的缺陷就是单个进程所打开的FD是有一定限制的,它由FD_SETSIZE设置,默认值是1024。一般来说这个数目和系统内存关系很大,具体数目可以cat /proc/sys/fs/file-max查看。32位机默认是1024个。64位机默认是2048.对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低。当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。

二.poll模型

      基本原理:poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态,如果设备就绪则在设备等待队列中加入一项并继续遍历,如果遍历完所有fd后没有发现就绪设备,则挂起当前进程,直到    设备就绪或者主动超时,被唤醒后它又要再次遍历fd。这个过程经历了多次无谓的遍历。

       poll没有最大连接数的限制,原因是它是基于链表来存储的,但是同样有一个缺点:大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。poll还有一个特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。

三.epoll模型

        基本原理:epoll支持水平触发和边缘触发,最大的特点在于边缘触发,它只告诉进程哪些fd刚刚变为就绪态,并且只会通知一次。还有一个特点是,epoll使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd,epoll_wait便可以收到通知。

       epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。

       epoll对文件描述符的操作有两种模式:LT(level trigger)和ET(edge trigger)。LT模式是默认模式,LT模式与ET模式的区别如下:
LT模式-延迟处理:一种缺省的工作方式,当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll_wait时,会再次响应应用程序并通知此事件。
ET模式-立即处理:一种高速的工作方式,当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序立即处理该事件。

      epoll的优点:

     1.没有最大并发连接的限制,能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)。
     2.效率提升,不是轮询的方式,不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数,
     3.内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销。

四.select、poll、epoll区别

    1.select模型单个进程有最大连接数限制,poll没有连接数限制,基于链表存储,epoll虽然有限制,但是很大,1G内存的机器可以打开10w左右的连接。

    2.FD剧增后带来的IO效率问题,select和poll都是线性遍历,在FD剧增的情况下,速度变慢。

    3.消息传递方式  select和poll都有内核拷贝动作,内核将消息传递给用户空间,epoll是内核和用户空间空享内存

五.总结

select,poll,epoll时要根据具体的使用场合以及这三种方式的自身特点:

    1.表面上看epoll的性能最好,但是在连接数少并且连接都十分活跃的情况下,select和poll的性能可能比epoll好,毕竟epoll的通知机制需要很多函数回调。

    2.select低效是因为每次它都需要轮询。但低效也是相对的,视情况而定,也可通过良好的设计改善。

posted @ 2019-06-13 16:42  Don'tYouSee  阅读(505)  评论(0)    收藏  举报