news 2026/7/13 4:01:58

select、poll、epoll 到底有什么区别?一文讲透 I/O 多路复用 _

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
select、poll、epoll 到底有什么区别?一文讲透 I/O 多路复用 _

同步: 同步就是发起一个调用后,被调用者未处理完请求之前,调用不返回。此时需要调用者询问处理结果
异步: 异步就是发起一个调用后,立刻得到被调用者的回应表示已接收到请求,但是被调用者并没有返回结果,此时调用者来询问处理结果,被调用者通常依靠事件,回调等机制来通知调用者其返回结果。
同步和异步最大的区别在于异步的话调用者不需要等待处理结果,被调用者会通过回调等机制来通知调用者其返回结果。

阻塞和非阻塞

这两个概念是程序级别的。

阻塞: 阻塞就是发起一个请求,调用者一直等待请求结果返回,也就是当前线程会被挂起,无法从事其他任务,只有当条件就绪才能继续。
非阻塞: 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
举个例子,理解下同步、阻塞、异步、非阻塞的区别:同步就是烧开水,要自己来看开没开;异步就是水开了,然后水壶响了通知你水开了(回调通知)。阻塞是烧开水的过程中,你不能干其他事情,必须在旁边等着;非阻塞是烧开水的过程里可以干其他事情。

从以上概念也可以看出,不会存在异步非阻塞的场景

Unix IO 模型简介
一个输入操作通常包括两个阶段:

等待数据准备好
从内核向进程复制数据
对于一个套接字上的输入操作,第一步通常涉及等待数据从网络中到达。当所等待分组到达时,它被复制到内核中的某个缓冲区。第二步就是把数据从内核缓冲区复制到应用进程缓冲区。

Unix 下有五种 I/O 模型:

阻塞式 I/O
非阻塞式 I/O
I/O 复用(select 和 poll)
信号驱动式 I/O(SIGIO)
异步 I/O(AIO)
阻塞式 I/O
应用进程被阻塞,直到数据复制到应用进程缓冲区中才返回。

应该注意到,在阻塞的过程中,其它程序还可以执行,因此阻塞不意味着整个操作系统都被阻塞。因为其他程序还可以执行,因此不消耗 CPU 时间,这种模型的执行效率会比较高。

下图中,recvfrom 用于接收 Socket 传来的数据,并复制到应用进程的缓冲区 buf 中。这里把 recvfrom() 当成系统调用。

c
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

非阻塞式 I/O
应用进程执行系统调用之后,内核返回一个错误码。应用进程可以继续执行,但是需要不断的执行系统调用来获知 I/O 是否完成,这种方式称为轮询(polling)。

由于 CPU 要处理更多的系统调用,因此这种模型是比较低效的。

I/O 复用
使用 select 或者 poll 等待数据,并且可以等待多个套接字中的任何一个变为可读,这一过程会被阻塞,当某一个套接字可读时返回。之后再使用 recvfrom 把数据从内核复制到进程中。

它可以让单个进程具有处理多个 I/O 事件的能力。又被称为 Event Driven I/O,即事件驱动 I/O。

如果一个 Web 服务器没有 I/O 复用,那么每一个 Socket 连接都需要创建一个线程去处理。如果同时有几万个连接,那么就需要创建相同数量的线程。并且相比于多进程和多线程技术,I/O 复用不需要进程线程创建和切换的开销,系统开销更小。

信号驱动 I/O
应用进程使用 sigaction 系统调用,内核立即返回,应用进程可以继续执行,也就是说等待数据阶段应用进程是非阻塞的。内核在数据到达时向应用进程发送 SIGIO 信号,应用进程收到之后在信号处理程序中调用 recvfrom 将数据从内核复制到应用进程中。

相比于非阻塞式 I/O 的轮询方式,信号驱动 I/O 的 CPU 利用率更高。

异步 I/O
进行 aio_read 系统调用会立即返回,应用进程继续执行,不会被阻塞,内核会在所有操作完成之后向应用进程发送信号。

异步 I/O 与信号驱动 I/O 的区别在于,异步 I/O 的信号是通知应用进程 I/O 完成,而信号驱动 I/O 的信号是通知应用进程可以开始 I/O

I/O 模型比较
同步 I/O 与异步 I/O
同步 I/O: 应用进程在调用 recvfrom 操作时会阻塞。
异步 I/O: 不会阻塞。
阻塞式 I/O、非阻塞式 I/O、I/O 复用和信号驱动 I/O 都是同步 I/O,虽然非阻塞式 I/O 和信号驱动 I/O 在等待数据阶段不会阻塞,但是在之后的将数据从内核复制到应用进程这个操作会阻塞。

五大 I/O 模型比较
前四种 I/O 模型的主要区别在于第一个阶段,而第二个阶段是一样的: 将数据从内核复制到应用进程过程中,应用进程会被阻塞。

I/O 多路复用

一个进程虽然任一时刻只能处理一个请求,但是处理每个请求的事件时,耗时控制在 1 毫秒以内,这样 1 秒内就可以处理上千个请求,把时间拉长来看,多个请求复用了一个进程,这就是多路复用,这种思想很类似一个 CPU 并发多个进程,所以也叫做时分多路复用。

select/poll/epoll 内核提供给用户态的多路复用系统调用,进程可以通过一个系统调用函数从内核中获取多个事件。select/poll/epoll 在获取事件时,先把所有连接(文件描述符)传给内核,再由内核返回产生了事件的连接,然后在用户态中再处理这些连接对应的请求即可。

select/poll
select 实现多路复用的方式是,将已连接的 Socket 都放到一个文件描述符集合,然后调用 select 函数将文件描述符集合拷贝到内核里,让内核来检查是否有网络事件产生,检查的方式很粗暴,就是通过遍历文件描述符集合的方式,当检查到有事件产生后,将此 Socket 标记为可读或可写, 接着再把整个文件描述符集合拷贝回用户态里,然后用户态还需要再通过遍历的方法找到可读或可写的 Socket,然后再对其处理。

所以,对于 select 这种方式,需要进行 2 次「遍历」文件描述符集合,一次是在内核态里,一个次是在用户态里 ,而且还会发生 2 次「拷贝」文件描述符集合,先从用户空间传入内核空间,由内核修改后,再传出到用户空间中。

select 使用固定长度的 BitsMap,表示文件描述符集合,而且所支持的文件描述符的个数是有限制的,在 Linux 系统中,由内核中的 FD_SETSIZE 限制, 默认最大值为 1024,只能监听 0~1023 的文件描述符。

poll 不再用 BitsMap 来存储所关注的文件描述符,取而代之用动态数组,以链表形式来组织,突破了 select 的文件描述符个数限制,当然还会受到系统文件描述符限制。

但是 poll 和 select 并没有太大的本质区别,都是使用「线性结构」存储进程关注的 Socket 集合,因此都需要遍历文件描述符集合来找到可读或可写的 Socket,时间复杂度为 O(n),而且也需要在用户态与内核态之间拷贝文件描述符集合,这种方式随着并发数上来,性能的损耗会呈指数级增长。

epoll
如下的代码中,先用e poll_create 创建一个 epol l对象 epfd,再通过 epoll_ctl 将需要监视的 socket 添加到epfd中,最后调用 epoll_wait 等待数据。

epoll 通过 epoll_create、epoll_ctl 和 epoll_wait 三个系统调用来实现。

c
int s = socket(AF_INET, SOCK_STREAM, 0);
bind(s, …);
listen(s, …)

int epfd = epoll_create(…);
epoll_ctl(epfd, …); //将所有需要监听的socket添加到epfd中

while(1) {
int n = epoll_wait(…);
for(接收到数据的socket){
//处理
}
}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/13 4:01:12

Python遗传算法实战:N皇后问题从零实现与调优

1. 这不是教科书,而是一次手把手带你跑通遗传算法实战的现场复盘你点开这篇文章,大概率不是为了背诵“遗传算法是模拟生物进化过程的优化方法”这种定义。你真正想搞明白的是:当代码跑起来之后,那一堆population、fitness、mutati…

作者头像 李华
网站建设 2026/7/13 3:56:32

2026最新7款高性价比AI编程助手企业选型实测

这次对比的起因很偶然:5 款 AI 编程工具都在同一周发布了大版本更新,我趁机做了一次同条件下的横评。我去年7月刚毕业进公司做后端开发,手里负责的是代号为「橙果」的生鲜电商小程序后端迭代项目,当时团队要赶618大促的功能上线&a…

作者头像 李华
网站建设 2026/7/13 3:54:59

2026最新猫眼协议抢票-破军网络

mtgsig 1.2 完整逆向拆解(美团小程序 H5guard 加密)一、先明确核心结论你现在用的 9521 端口服务 官方封装好的黑盒 RPC 加密服务,本质是内置了完整逆向还原后的 H5guard 1.2 算法,输入请求参数直接输出可用 mtgsig,不…

作者头像 李华
网站建设 2026/7/13 3:53:22

网络安全主要是做什么

网络安全主要是做什么 数据保护 确保数据访问安全。只有经过授权的用户才能访问和使用数据。 保护数据机密性。防止数据泄露。 维护数据完整性。确保数据不被篡改或损坏。 系统防护 保护企业的网络、系统、设备和其他敏感信息免受攻击。 对服务器、网络设备和安全产品进行维护…

作者头像 李华
网站建设 2026/7/13 3:51:17

DeepSeek注释生成合规性红线预警:GDPR/等保2.0/信创要求下,这5类敏感信息必须拦截——审计通过率提升至99.6%

更多请点击: https://intelliparadigm.com 第一章:DeepSeek注释生成合规性红线预警总览 DeepSeek系列大模型在代码注释自动生成场景中展现出强大能力,但其输出内容若未经严格合规校验,可能触碰法律、安全与工程治理的多重红线。本…

作者头像 李华
网站建设 2026/7/13 3:50:07

C盘空间告急:从快速清理到长期管理的完整解决方案

今天我们来解决一个很实际的问题:C盘空间告急。如果你的C盘显示剩余容量181G/1.07TB,说明总容量约1TB,已使用近820GB,剩余空间约17%。这个比例对系统盘来说已经相当紧张,需要立即清理和优化。系统盘空间不足会导致Wind…

作者头像 李华