linux操作系统在对IO的操作,实际上是对每个物理设备对应文件的操作,对应到操作系统里是文件操作符,即(File Describe)FD,文件描述符包含了操作文件的位置、内容等信息;用户的io请求连接首先会注册到多路复用器selector,通过一个特定的selector线程管理多个链接,多路复用器通过指定以下函数轮训,直到IO操作的数据准备完成,才会通知线程进行操作IO,等待数据阶段非阻塞,数据获取阶段需要从内核空间复制到用户空间属于阻塞IO
多路复用IO属于非阻塞IO的一种,也称为“伪异步I/O”,因为其在数据准备阶段不需要阻塞IO,但是在复制数据阶段仍然要阻塞线程,复制数据到用户空间缓冲区以供应用程序使用;
(以下函数仅在数据准备阶段使用)
1、select函数
select函数实现通过bitmap数组存储文件描述符,受操作系统限制32位最大支持1024,64为最大支持2048,所以如果使用select函数,则io操作最大并发只能是1024或者2048;
select函数实现多路复用是阻塞用户进程,线性轮训fd数组,当fd数组很大是,效率线性降低
2、poll
基于链表存储FD,解决了select函数fd数量限制;其他和select函数没什么区别
3、epoll
基于事件回调机制,标记哪些FD进入就绪状态,内核采用callback的回调机制激活FD,效率提升,不用轮训无用的FD
没有最大并发限制,具体和内存、硬件有关系
当连接较少的情况下效率和select、poll无太大区别,遇到大量的连接的时候,效率远高于select和poll
总结:select实现简单,有最大连接数限制,轮训时,select线程占用cpu时间片长,poll出来无连接数限制外其他和select类似;epoll即无连接数限制也不会过多占用cpu,但实现机制更为复杂