Skip to content

Latest commit

 

History

History
149 lines (96 loc) · 4.53 KB

File metadata and controls

149 lines (96 loc) · 4.53 KB

面试题:IO 多路复用是什么?多路是什么?复用了什么?

这是操作系统内核、网络编程、Redis/Nginx/Reactor 模型中最经典的基础设施问题。 面试官问它,是想评估你对:

  • Linux IO 模型
  • 内核事件通知机制(epoll)
  • Reactor 单线程高性能的原因
  • 网络程序为什么用 select/epoll

这些核心基础的理解。

问题核心:

  1. IO 多路复用(I/O Multiplexing)到底是什么?
  2. 所谓“多路”指的是什么?
  3. 所谓“复用”又复用了什么?

只要你能把这三个点打透,面试官会认为你基础扎实。


一、IO 多路复用是什么?(一句话核心定义)

IO 多路复用就是:一个线程同时监控多个 IO 事件(socket),一旦任何一个就绪,就能被内核通知,从而处理对应的 IO。

更通俗点:

不用为每个连接开线程,也不用阻塞等待某一个 IO,而是用一个线程观察所有连接,一旦谁准备好了就处理谁。

这就是 Nginx、Redis、Netty 都能用单线程支撑十万连接的核心能力。


二、“多路”是什么?(多路 = 多个 IO 通道)

多路指的是:

  • 多个 socket
  • 多个文件描述符(fd)
  • 多个网络连接
  • 多个 input channel

举例:

你有 10000 个 TCP 连接,每条连接都是一“路 IO”。 在没有 IO 多路复用时,要么:

  • 每个连接一个线程(线程爆炸)
  • 或者循环一个个 poll(CPU 白忙活)

有了 IO 多路复用:

你只需要一个线程就能高效监听所有 10000 个连接是否有事件。

所以:

多路 = 多个 IO 通道(多个 socket/fd)。


三、“复用”复用了什么?(复用 = 复用一个线程 / 一个内核事件等待点)

最经典的答案:

复用的是一个线程(或一个等待点)来处理多个 I/O。

也可以说:

  • 复用 一个阻塞点
  • 复用 一个内核事件等待机制(epoll_wait)
  • 复用 一个线程上下文

在没有 IO 多路复用时:

socket A read 阻塞
socket B read 阻塞
socket C read 阻塞
……

你需要开多个线程。

现在用 epoll:

epoll_wait() 阻塞一次  
→ 内核一次性告诉你哪些 socket 就绪  
→ 一个线程逐个处理

阻塞的是 epoll_wait 而不是具体 socket。 这就是 “复用” 的本质。


四、为什么 IO 多路复用这么高效?(面试官爱问)

核心在于:

  1. 不需要每个连接一个线程(线程上下文切换极贵)
  2. 不需要主动轮询所有连接(CPU 不空转)
  3. 内核主动事件通知(epoll)非常高效

尤其是 epoll:

  • epoll_ctl:注册事件
  • epoll_wait:阻塞等待
  • 就绪的 fd 才回调(事件驱动)

事件驱动 + 非阻塞 IO + 单线程 是高性能服务器模型的关键。


五、各个 Linux IO 模型对比(面试深度加分)

IO 模型 机制 是否高效 性能瓶颈
blocking IO 读写直接阻塞 等待阻塞
non-blocking IO 读不到立即返回 busy loop
IO multiplexing(select/poll/epoll) 一个 wait 监听多个 fd select/poll 存在性能问题
signal driven IO 信号通知 罕用 信号复杂
asynchronous IO 内核全负责 IO 复杂/不常用 实现复杂

其中:

  • select:fd 数量有限(1024)、每次都要遍历
  • poll:无次数限制,但每次都遍历
  • epoll:事件驱动,不遍历所有 fd,性能最好

面试说到这里,胜率非常高。


六、最终面试总结

你可以这样说:

“IO 多路复用是让一个线程可同时监控多个 IO 通道的机制。

多路指多个 socket / 文件描述符; 复用指复用同一个线程或阻塞点来等待所有 IO 事件。

它的本质是:通过 select/poll/epoll 这种内核提供的事件通知机制,让我们不再为每个连接创建线程,也不需要轮询所有连接,而是让内核在某个 socket 可读可写时一次性通知我们。

特别是 epoll 的事件驱动模式,让 Nginx、Redis、Netty 等可以用少量线程处理大量连接,这也是高性能网络服务器的基础。”