乐趣区

selectpollepoll只需要看这一篇就好了

select、poll、epoll:select,poll,epoll 都是 IO 多路复用的机制

select,poll,epoll 本质上都是同步 I /O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步 I / O 则无需自己负责进行读写,异步 I / O 的实现会负责把数据从内核拷贝到用户空间。epoll 跟 select 都能提供多路 I / O 复用的解决方案。在现在的 Linux 内核里有都能够支持,其中 epoll 是 Linux 所特有,而 select 则一般操作系统均有实现。

1、没有最大并发连接的限制,能打开的 FD(file descriptor: 文件描述符) 的上限远大于 1024(1G 的内存上能监听约 10 万个端口);

2、效率提升,不是轮询的方式,不会随着 FD 数目的增加效率下降。只有活跃可用的 FD 才会调用 callback 函数;

即 Epoll 最大的优点就在于它只管你“活跃”的连接,而跟连接总数无关,因此在实际的网络环境中,Epoll 的效率就会远远高于 select 和 poll。

select 有三个缺点:

1、连接数受限

2、查找匹配速度慢

3、数据由内核拷贝到用户态

poll 改善了第一个缺点,epoll 改善了三个缺点。

(1)select==> 时间复杂度 O(n)

它仅仅知道了,有 I / O 事件发生了,却并不知道是哪那几个流(可能有一个,多个,甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。所以 select 具有 O(n) 的无差别轮询复杂度,同时处理的流越多,无差别轮询时间就越长。

(2)poll==> 时间复杂度 O(n)

poll 本质上和 select 没有区别,它将用户传入的数据拷贝到内核空间,然后查询每个 fd 对应的设备状态,但是它没有最大连接数的限制,原因是它是基于链表来存储的. 因为每次调用时都会对连接进行线性遍历,所以随着 FD 的增加会造成遍历速度慢的“线性下降性能问题”。

(3)epoll==> 时间复杂度 O(1)

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

总结:

综上,在选择 select,poll,epoll 时要根据具体的使用场合以及这三种方式的自身特点。

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

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

退出移动版