个人博客

IO多路复用——select、poll、epoll

IO多路复用的本质就是通过一种机制,让单个进程可以监听多个文件描述符,一旦某个文件描述符就绪,就能通过程序进行相应的读写操作。

目前常用的IO多路复用模型就有select、poll、epoll。

简介

select的时间复杂度为O(n),它仅仅只是知道了有IO事件的发生,却不知道是哪个文件描述符的,只能无差别的轮询所有的文件描述符,找出能读或者能写的文件描述符,对它们进行操作。

poll的时间复杂度为O(n),poll本质上和select没有区别,一样需要轮询所有的文件描述符,但是它没有最大连接数的限制,原因是它是基于链表来存储的。

epoll的时间复杂度为O(n),epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll会把哪个文件描述符发生了怎么样的IO事件通知我们。所以我们说epoll是事件驱动(每个事件关联上fd)的,此时我们对这些流的操作都是有意义的。

select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。这样所带来的缺点是:1,单个进程壳监视的fd数量被限制;2,对socket进行扫描是线性扫描,即采用轮询的方式,效率低;

poll的实现和select非常类似,只是描述fd的集合方式不同,即使用的数据结构不同。其他的都差不多,都是使用轮询的方式,但是poll没有最大文件描述符数量的限制,因为它是用链表来存储的。

epoll有LT(水平触发)和ET(边缘触发)两种触发方式。在LT模式下,只要这个fd还有数据可读,每次epoll_wait都会返回它的事件,提醒用户去操作;而在ET模式下,它只会提醒一次,直到下次再有数据流入之前都不会再提示,无论fd中是否还有数据可读。epoll使用事件就绪通知的方式,通过epoll_ctl注册fd,一旦fd就绪,内核就会采用回调机制来激活该fd,epoll_wait便可以收到通知。

区别

1,支持一个进程所能打开的最大连接数:

select:单个进所能打开的最大连接数有FD_SETSIZE宏定义。

poll:poll本质上和select没有区别,但是它没有最大连接数的限制,因为它用链表来存储。

epoll:虽然连接数有上限,但是很大,1G内存的机器上可以打开10W左右的连接,2G内存的机器可以打开20W左右的连接。

2,fd剧增后带来的IO问题:

select:因为每次调用时都会进行线性遍历,所以随着fd的增加会造成遍历速度变慢。

poll:同样存在和select一样的问题。

epoll:因为epoll内核中实现是根据fd上的callback函数来实现的,只有活跃的socket才会主动调用callback,所以在活跃socket较少的情况下,使用epoll没有前两者的线性下降的性能问题。但是所有socket都很活跃时,可能就会有性能的问题。

3,消息传递方式:

select:内核需要将消息传递到用户空间,都需要内核得拷贝动作。

poll:poll的方式和select一样。

epoll:epoll通过内核和用户空间共享一块内存来实现。

相关标签
回到顶部