
本文概述
IO多路复用是Linux网络和嵌入式面试的高频题,select/poll/epoll三件套几乎是必问。面试官想听的不是“epoll性能好”,而是你懂不懂IO多路复用的本质(一个线程同时监控多个fd)、select/poll/epoll的原理(轮询 vs 事件回调)、三者区别(fd上限、效率、触发模式)、以及epoll为什么快(红黑树+就绪链表、回调通知)。本文从“IO多路复用是什么”讲起,讲阻塞IO与非阻塞IO的背景、select/poll的轮询机制、epoll的事件驱动机制、三者的对比(上限、时间复杂度、拷贝开销、触发模式)、以及怎么选型,强调参数和结论按内核版本和应用场景理解,不套绝对化说法。
核心要点
IO多路复用:一个线程同时监控多个文件描述符(fd),有事件才处理
select:fd集合轮询,有上限(FD_SETSIZE,通常1024量级)、内核态用户态拷贝开销
poll:链表管理fd,无上限,但仍轮询(O(n))
epoll:事件驱动,红黑树+就绪链表,只返回有事件的fd(O(1)量级),支持ET/LT
epoll优势:无上限、不用全量拷贝、只遍历就绪fd
触发模式:LT水平触发(默认)、ET边缘触发(配合非阻塞IO)
选型:fd少/简单用select,通用/无上限用poll,高并发/大连接数用epoll(Linux)
面试官考察点
考察点拆解
面试官问IO多路复用,重点考察:第一,你懂不懂IO多路复用要解决的问题(多fd监控);第二,你懂不懂select/poll/epoll各自原理;第三,你懂不懂epoll为什么快(事件驱动 vs 轮询);第四,你懂不懂LT/ET和阻塞/非阻塞。
追问方向:epoll原理、ET和LT区别、为什么epoll快、什么场景用哪个。
回答思路
答题主线
建议按“解决的问题 → select → poll → epoll → 对比选型”来答,从演进逻辑讲。
先讲背景:阻塞IO浪费CPU。
讲select/poll:轮询机制与缺点。
讲epoll:事件驱动。
讲对比:LT/ET、选型。
参考回答
我先讲IO多路复用解决什么问题,再对比三个API。
第一,背景。阻塞IO下,一个线程read一个fd会阻塞,多个fd就要多线程/多进程,浪费资源。IO多路复用让一个线程同时监控多个fd:内核告诉我哪些fd就绪,我再处理。
第二,select。把要监控的fd放到fd_set(位图),交给内核,内核轮询每个fd,返回就绪集合,用户再遍历fd_set检查。缺点:1)fd上限(FD_SETSIZE,通常1024量级,按系统);2)每次调用要全量拷贝fd集合进出内核;3)返回后要全量遍历才知道哪些就绪(O(n))。
第三,poll。用pollfd数组(链表结构)替代位图,没有fd上限(受系统限制),但仍需全量拷贝、全量轮询(O(n))。
第四,epoll。Linux下的事件驱动方案:
epoll_create建红黑树;epoll_ctl把fd加入/修改/删除(注册fd到内核);
fd就绪时内核回调把它挂到就绪链表;
epoll_wait只返回就绪的fd,不用全量遍历(就绪fd少时接近O(1)量级);
没有fd上限(受系统文件数限制);不需要全量拷贝(fd注册一次,内核维护)。
第五,触发模式。LT水平触发(默认):fd一直有数据就一直返回,处理简单;ET边缘触发:只有状态变化(新数据到来)时返回一次,必须配合非阻塞IO循环读尽,效率高但容易漏读。
第六,选型。fd少、简单场景用select即可;通用性(跨平台)用poll;高并发、大连接数(Linux服务器)用epoll。epoll是Linux特有,嵌入式Linux同样适用。

扫码关注




























