I/O多路复用

你好,我是吴计可师,一个工作十多年的后端开发,曾就职京东、阿里等多家互联网头部企业。

点击下方👇关注公众号,带你一起复习后端技术,看看面试考点,补充积累技术知识,每天都为面试准备积累

文章可能会比较长,主要解析的非常详解,或涉及一些底层知识,供面试高阶难度用。可以根据自己实际理解情况合理取舍阅读


I/O多路复用机制 是一种高效的网络通信技术,允许程序同时监听多个 I/O 事件,提高系统对高并发请求的处理能力。它主要解决 单线程无法高效处理多个连接 的问题,在网络编程中至关重要。


01
什么是I/O多路复用?


I/O多路复用指通过一个或多个系统调用,使一个线程可以监控多个文件描述符(文件、套接字等)的 I/O 事件(如读、写、异常),一旦有事件就绪,程序可以进行相应处理。

本质:让单个线程高效地处理多个 I/O 连接。

关键优势:无需为每个连接创建一个线程或进程,节省资源,提高并发性能。


02
常见的I/O多路复用机制


select

工作原理:


  • 使用一个位图表示所有监听的文件描述符。

  • 每次调用 select,内核会遍历所有文件描述符,检查哪些就绪。

优点:跨平台,简单易用。

缺点:

  • 每次调用都需要遍历所有 fd,效率低,时间复杂度 O(n)。

  • 文件描述符有上限(默认 1024)。


poll

工作原理:


  • 使用一个链表存储所有文件描述符和监听的事件。

  • 内核遍历链表检查就绪的文件描述符。

优点:没有文件描述符数量限制。

缺点:同样需要遍历所有 fd,效率较低。时间复杂度仍为 O(n)。



epoll(Linux特有)

工作原理:


  • 采用 事件驱动机制,将文件描述符和事件注册到内核,内核维护就绪事件。

  • 使用一个红黑树管理监听的文件描述符,就绪队列存储触发的事件。

关键特性:
  • 事件通知机制,避免遍历所有文件描述符。

  • 支持 水平触发(LT) 和 边缘触发(ET)。


优点:

  • 效率高,时间复杂度接近 O(1)。

  • 支持大量并发连接,性能优越。

缺点:Linux 特有,代码复杂度略高。


kqueue 和 IOCP

kqueue:FreeBSD 系统的 I/O多路复用机制,与 epoll 类似,提供高效事件通知。

IOCP(I/O Completion Port):Windows 平台的高效 I/O 机制,基于异步事件通知。


03
I/O多路复用与线程/进程的对比


传统线程/进程:

  • 为每个 I/O 连接创建一个线程或进程,占用大量系统资源。

  • 上下文切换开销大,效率低。

I/O多路复用:

  • 单线程可同时处理多个连接,减少线程数量和上下文切换开销。

  • 更适合高并发场景。


04
 I/O多路复用的应用场景


高并发网络服务器:Nginx、Redis、Netty 等框架使用 epoll 进行 I/O 多路复用。

即时通讯系统:需要监听大量连接的实时消息传输。

长连接场景:大量用户维持长连接,比如聊天室、WebSocket 等。


05
直击面试


5.1 什么是水平触发(LT)和边缘触发(ET)?

水平触发(Level Triggered, LT):

只要文件描述符上的 I/O 事件还未被处理,系统会持续通知应用程序。容易处理,但可能导致重复通知。

边缘触发(Edge Triggered, ET):
只有在文件描述符的状态发生变化时,系统才会通知应用程序。

更高效,但要求程序确保一次性处理完所有数据。


5.2 为什么epoll比select和poll更高效?

事件驱动:epoll 使用事件通知机制,避免轮询所有文件描述符。

时间复杂度:epoll 的时间复杂度接近 O(1),而 select 和 poll 为 O(n)。

无文件描述符限制:epoll 不受文件描述符数量限制。

就绪队列:epoll 维护一个就绪队列,只返回就绪的事件,减少了数据拷贝。


5.3 epoll的三种操作是什么?

epoll_create:创建一个 epoll 实例,返回一个文件描述符。

epoll_ctl:对文件描述符执行操作(添加、删除、修改)。

  • EPOLL_CTL_ADD:添加事件。

  • EPOLL_CTL_DEL:删除事件。

  • EPOLL_CTL_MOD:修改事件。

epoll_wait:等待事件发生,并返回就绪的事件。


5.4 epoll的红黑树和就绪队列分别用于什么?

红黑树:存储所有被监控的文件描述符和事件,方便快速增删改查。

就绪队列:存储已经触发的事件,epoll_wait 直接返回就绪事件,避免遍历。

5.5 在实际应用中,如何选择select、poll和epoll?

select:适合小规模连接,跨平台简单实现。

poll:适合中等规模连接,较 select 改进,无文件描述符上限。

epoll:适合大规模高并发场景,Linux 环境下首选。

实际应用:

  • Nginx 和 Redis 使用 epoll

  • 跨平台网络库可能基于 select/poll 实现

今天的内容就分享到这儿,喜欢的朋友可以关注,点赞。有什么不足的地方欢迎留言指出,您的关注是我前进的动力!

END


扫码关注

一起积累后端知识
不积跬步,无以至千里
不积小流,无以成江海

喜欢此内容的人还喜欢

谈谈id那些事(五)——美团的 Leaf 的ID生成


一个阿里二面面试官必问的问题


谈谈id那些事(三)——阿里巴巴的 TDDL的ID生成


分享面试:mysql数据库索引失效的情况


面试常被忽略的问题——内存区域划分