新闻详情

新闻详情

首页 / 资讯中心 / 详情

epoll 到底快在哪?三张图看懂 select、poll、epoll 的区别

发布时间:2026/10/2 17:18:32来源:尧图网络
epoll 到底快在哪?三张图看懂 select、poll、epoll 的区别
图解epoll 到底快在哪三张图看懂 select、poll、epoll 的区别理解 epoll可以先看 select、poll 在等待事件时反复做了哪些工作再看 epoll 怎样减少这些工作。核心是保存监听关系并在事件发生时提前记录就绪对象。一 select 和 poll 的重复开销假设程序监听 A、B、C、D、E 五个连接开始都没有事件随后只有 B、D 可读。select、poll 都能让调用线程睡眠数据到达后再唤醒它它们的开销主要在下面三处。每轮都要传入完整的监听范围。即使还是关注 A 到 E下一次调用仍要把完整集合或数组交给内核产生重复的参数拷贝。select 使用位图返回时会修改集合所以再次调用前还要恢复监听集合poll 使用数组可以复用用户态数组但每次仍要提交它。内核需要扫描才能确定谁已就绪。调用时先检查监听项如果没有事件就睡眠被唤醒后再检查。即使只有 B、D 可读也要检查 A 到 E而不能直接从一个保存好的就绪链表中取出 B、D。连接越多检查非活跃连接的工作越多。应用还要从返回的标记中找出就绪连接。select 的结果位图 只保留 B、D 的就绪位其他位清零poll 的数组仍包含 A 到 E在 B、D 对应项的revents中设置就绪标记。应用需要检查位图或数组中的标记找到本轮要处理的连接。二 epoll 如何减少重复开销epoll 将“管理监听关系”和“等待事件”分成了epoll_ctl()与epoll_wait()并在内核中保存监听关系和就绪链表。三个问题分别对应三个改进select 和 poll 的重复工作epoll 的解决方式每轮传入完整监听范围用epoll_ctl()注册内核红黑树持续保存监听关系需要增删改时才更新epoll_wait()不再传入整份监听范围。内核扫描全部监听项寻找就绪连接注册时建立回调关联B、D 就绪时回调直接找到对应监听记录把它们加入就绪链表这样就不用遍历全部监听项了。epoll_wait()主要复查这些候选。应用检查集合或数组中的标记需要二次处理才能拿到就绪的事件epoll_wait()把就绪链表的事件写入用户态数组这个数组的事件都是就绪事件应用逐项处理这些事件即可。下面的图把同一次事件放到三种机制中比较上方是用户态下方是内核态按编号看执行顺序。接下来只看 epoll把它拆成注册和数据到达两个阶段。三 注册监听假设程序已经创建了 epoll 实例socket 101 当前没有数据可读。程序调用epoll_ctl(ADD)把 socket 101 加入监听范围。内核按图中的顺序完成以下工作。找到 epoll 和 socket。内核通过文件描述符找到这次使用的 epoll 实例以及需要监听的 socket。把监听记录放入红黑树。内核创建一条监听记录叫作epitem记下目标 socket 和关注的事件再把它加入红黑树。红黑树保存着这个 epoll 实例的全部监听记录。在 socket 上登记回调。回调就是提前登记好、在相应事件发生时被调用的函数。这里使用的是内核函数ep_poll_callback内核在 socket 的等待队列中登记一个调用它的回调项并将这个回调项与监听记录关联起来。这个回调负责把“socket 可读了”变成“epoll 有事件可以处理了”。socket 变为可读时内核调用它它就直接找到对应的监听记录加入就绪链表如果有线程正在等待再唤醒线程。所以回调的作用是记录就绪、通知等待线程。真正读取数据的工作由应用拿到事件后调用recv()完成。检查现在是否已经可读。本例还没有数据所以就绪链表为空。如果注册时就已经可读则会直接把对应监听项加入就绪链表。注册完成后程序调用epoll_wait()。如果没有就绪事件并且允许阻塞线程就进入epoll 的等待队列等待通知。这里等待的是调用epoll_wait()的应用线程epoll 不会为每个 socket 新建线程。epoll 等待队列的作用是记住哪些线程正在等事件。没有事件时这些线程可以睡眠、让出 CPU回调记录就绪后再按需唤醒它们。就绪链表记录“哪些连接需要处理”epoll 等待队列记录“哪些线程等待通知”。到这里监听关系已经建立好了后续每次等待都可以复用。四 数据到达现在socket 101 收到了数据而程序正阻塞在epoll_wait()中。接下来看数据到达后的流程。数据进入 socket。网卡收到数据协议栈处理后把数据交给目标 socket保存在接收缓冲区中。socket 发出可读通知。当 socket 满足可读条件时触发它的等待队列中登记的回调。回调找到对应的监听记录。利用注册时保存的关联回调直接找到 socket 101 对应的epitem不用遍历全部连接也不用重新搜索红黑树。把监听项加入就绪链表。回调把它记录为待处理的就绪项如果已经在链表中就不重复加入。它在红黑树中的监听关系仍然保留。唤醒等待线程。回调唤醒阻塞在 epoll 等待队列中的线程使程序有机会继续执行。返回就绪事件。epoll_wait()检查就绪链表中的候选确认当前状态再把符合条件的事件返回给程序。程序拿到“socket 101 可读”的事件后再调用recv()读取数据。epoll 返回的是就绪事件实际数据由程序随后通过recv()从 socket 接收缓冲区读取。可以用下面两条流程记住它注册找到连接 → 保存监听记录 → 登记回调 → 检查当前状态 通知数据到达 → 回调记录就绪 → 唤醒等待线程 → 返回事件 → recv 读取数据红黑树记住“关注谁”就绪链表记住“谁需要处理”等待队列记住“哪些线程正在等事件”。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Python文本驱动知识图谱构建实战:从非结构化文本到可查询图谱 2026/10/2 18:09:14

Python文本驱动知识图谱构建实战:从非结构化文本到可查询图谱

简介:这是一套面向Python开发者与知识图谱初学者的自动化文本分析实践项目,聚焦从非结构化文本中高效提取实体关系、构建可扩展知识图谱的核心流程。资源共26个文件,含9个Python源码(涵盖config.py配置管理、scrach.py/sink.py主控…

阅读更多 →
Java电影网站开发实战:Spring Boot从零搭建与避坑指南 2026/10/2 18:09:14

Java电影网站开发实战:Spring Boot从零搭建与避坑指南

简介:这是一套基于SSM框架与Vue前端的完整电影网站系统源码,面向Java Web初学者与课程设计学生,解决毕业设计、实训项目中缺乏可运行全栈案例的问题。资源包含880个文件,涵盖144个Java后端逻辑类、53个Vue组件、167个JS交互脚本、…

阅读更多 →
【电路笔记 信号】DBPSK 波形查找表+脉冲成形(升余弦+根升余弦滤波) 2026/10/2 18:09:08

【电路笔记 信号】DBPSK 波形查找表+脉冲成形(升余弦+根升余弦滤波)

文章目录DBPSK 波形查找表提升每比特的周期数量脉冲成形理想波形矩形包络发送波形基带成形脉冲(升余弦方式)成形后的发送信号收发两端用根升余弦成型滤波器的影响CGDBPSK 波形查找表 // // DBPSK 波形查找表 // int16 DBPSK_Signal[2][SYMBLE_LEN] {…

阅读更多 →
EfficientVMamba实战:状态空间模型在图像分类中的高效应用与落地 2026/10/2 18:09:08

EfficientVMamba实战:状态空间模型在图像分类中的高效应用与落地

简介:面向图像分类任务与轻量级模型实战需求,这份资源围绕EfficientVMamba_T模型提供了一套完整可运行的植物幼苗分类方案。内容涵盖数据预处理、模型搭建、训练与评估等环节,适合有一定深度学习基础、希望借助视觉状态空间模型(S…

阅读更多 →
基于Node.js+Vue的校园信息共享系统:从开发到部署全流程实战 2026/10/2 18:09:08

基于Node.js+Vue的校园信息共享系统:从开发到部署全流程实战

做校园信息共享系统这个选题,最常被问到的问题就是:为什么非要用Node.js和Vue这套组合?我的答案一直很直接:因为这套技术栈能让一个两三个人的小团队,在最短时间内把"信息发布、分类检索、实时聊天"这些核心…

阅读更多 →
SQL Server备份还原修复实战:从维护计划到MDF损坏恢复 2026/10/2 18:09:08

SQL Server备份还原修复实战:从维护计划到MDF损坏恢复

简介:SQL Server备份、还原与修复全流程知识整理文档,面向需要保障数据库安全与业务连续性的DBA、开发人员及运维新手,涵盖从日常备份到故障恢复的完整链路。内容首先区分完整备份、差异备份与事务日志备份的适用场景,随后详解SSM…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉