一文带你深入了解Linux五种I/O模型和I/O多路复用
一文带你深入了解Linux五种I/O模型和I/O多路复用
这个思维导图主要涵盖了 Linux 五种 I/O 模型 和 I/O 多路复用(select/poll/epoll) 的核心知识点。我将按照你的结构分模块详细解答,并总结常见的面试题。
一、几种典型 I/O 模型
1. 阻塞 I/O
定义:进程发起 I/O 系统调用后,内核等待数据准备完成,进程被挂起(阻塞),直到数据从内核复制到用户空间,调用才返回。
特点:
- 调用是否立即返回:否。
- 功能是否由自己完成:是(同步)。
- 例子:
read()、write()默认行为。
2. 非阻塞 I/O
定义:进程发起 I/O 调用后,如果内核数据未准备好,立即返回一个错误码(如 EWOULDBLOCK),进程可以继续轮询检查。
特点:
- 调用是否立即返回:是。
- 功能是否由自己完成:是(同步)。
- 需要循环调用,浪费 CPU。
3. 信号驱动 I/O
定义:进程发起调用后立即返回,当数据准备好时,内核发送 SIGIO 信号通知进程,进程再通过 recvfrom 等调用读取数据。
特点:
- 调用是否立即返回:是。
- 功能是否由自己完成:否(异步通知,但读取仍需自己完成,严格说是“异步通知型同步 I/O”)。
- 适用于 UDP,TCP 较复杂。
4. I/O 多路复用(高级 I/O)
定义:通过 select/poll/epoll 监控多个文件描述符,当某个描述符就绪时,通知进程进行 I/O 操作。
特点:
- 阻塞在 select 上,而非单个 I/O。
- 可以同时监控多个 fd。
5. 异步 I/O(AIO)
定义:进程发起 aio_read 等调用后立即返回,内核完成数据准备并复制到用户空间后,通过信号或回调通知进程。
特点:
- 调用是否立即返回:是。
- 功能是否由自己完成:否(内核完成全部操作)。
- 真正的异步 I/O。
二、阻塞与非阻塞 vs 同步与异步
| 维度 | 阻塞与非阻塞 | 同步与异步 |
|---|---|---|
| 关注点 | 调用是否立即返回 | I/O 操作由谁完成 |
| 组合 | 阻塞 I/O、非阻塞 I/O | 同步 I/O、异步 I/O |
- 阻塞 I/O:调用不返回,直到数据就绪。
- 非阻塞 I/O:调用立即返回,数据未就绪则返回错误。
- 同步 I/O:进程自己负责将数据从内核复制到用户空间。
- 异步 I/O:内核负责全部,完成后通知进程。
三、I/O 多路转接模型
1. select
实现流程:
- 调用 select,传入 fd_set 集合。
- 内核遍历所有 fd,检查状态。
- 有 fd 就绪或超时,返回。
- 用户遍历 fd_set 找到就绪 fd。
优点:
- 跨平台支持好。
缺点:
- fd 数量受限(FD_SETSIZE,通常 1024)。
- 每次调用都要将 fd_set 从用户态拷贝到内核态。
- 返回后需要遍历所有 fd 才能知道哪些就绪。
2. poll
实现流程:
- 调用 poll,传入 pollfd 数组。
- 内核遍历 pollfd,检查事件。
- 有 fd 就绪或超时,返回。
- 用户遍历 pollfd 检查 revents。
优点:
- 无最大 fd 数限制(基于链表)。
- 传入传出分离(events 和 revents)。
缺点:
- 仍然需要遍历所有 fd。
- 大量 fd 时性能线性下降。
3. epoll
实现流程:
epoll_create创建 epoll 对象。epoll_ctl注册要监控的 fd。epoll_wait等待事件发生。- 返回就绪事件列表。
触发方式:
- 水平触发(LT):只要 fd 可读/写,每次 epoll_wait 都会返回。
- 边缘触发(ET):仅在状态变化时通知一次,需要非阻塞 fd + 循环读写。
优点:
- 仅返回就绪 fd,无需遍历。
- 使用红黑树管理 fd,增删改查高效。
- 支持边缘触发,提高效率。
缺点:
- 仅 Linux 支持。
- 边缘触发编程复杂。
惊群问题
定义:多个进程/线程同时 epoll_wait 同一个 fd,当事件发生时,所有进程都被唤醒,但只有一个能处理,造成资源浪费。
解决:
- Linux 内核 4.5+ 解决了 epoll 惊群(
EPOLLEXCLUSIVE)。 - 也可用 SO_REUSEPORT 或自己实现负载均衡。
四、常见面试题总结
1. 阻塞与非阻塞的区别?
- 阻塞:调用不返回直到完成。
- 非阻塞:调用立即返回,未完成则返回错误。
2. 同步与异步的区别?
- 同步:进程自己完成 I/O(包括等待和复制)。
- 异步:内核完成 I/O,完成后通知进程。
3. select、poll、epoll 的区别?
- select:fd 有限、每次全量拷贝、返回后需遍历。
- poll:无上限、仍遍历、传入传出分离。
- epoll:事件驱动、只返回就绪 fd、高效、支持 ET。
4. epoll 的 LT 和 ET 区别?
- LT:安全、简单,但可能重复通知。
- ET:高效、需配合非阻塞 I/O 循环读写。
5. 什么是惊群问题?如何解决?
- 多个进程等待同一事件,事件触发时全部唤醒。
- 使用
EPOLLEXCLUSIVE或 SO_REUSEPORT。
6. 什么时候用 select/poll/epoll?
- select:简单、跨平台、少量 fd。
- poll:fd 数量较多但变化不大。
- epoll:高性能服务器、大量并发连接。
如果你需要我画一个流程图或对比表格,或者整理成 PDF 笔记,也可以告诉我。
总结
这篇文章是作者搜集大量面经和资料这里出来的。感谢你的支持
作者wkm是一名中国矿业大学(北京) 大一的新生,希望得到你的关注
如果可以的话,记得一键三联!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)