一站式讲清IO多路复用(轻松愉悦版)


文章目录

  • 引言
  • Select:早期的探索
  • Poll:Select 的链表版
  • Epoll:Linux 的杀手锏
  • Java和Go有什么需要了解的小知识?
  • 总结

引言

作为一个 Java 和 Go 后端开发者,深刻理解 IO 多路复用是掌握高性能网络编程(如 Netty)的基石。

简单来说,IO 多路复用是一种允许单个线程同时监视多个文件描述符(FD, File Descriptor)的技术。一旦某个 FD 就绪(读/写就绪),内核会通知应用程序进行处理。

如果没有它,处理 10,000 个并发连接可能需要 10,000 个线程(资源消耗巨大)或者使用非阻塞 IO 轮询(空转烧 CPU)。

下面我将从底层原理对比selectpollepoll进行说明。

Select:早期的探索

select是最早期的 IO 多路复用实现。

  • 工作原理:

    1. 用户进程将需要监视的fd_set(一个位图 bitmap)拷贝到内核空间。
    2. 内核遍历一遍所有的 socket,如果有数据,就标记为可读/可写。
    3. 内核将fd_set拷贝回用户空间。
    4. 用户进程再次遍历fd_set,找到被标记的 socket 进行处理。
  • 缺点:

    • 性能开销大:每次调用都要把 FD 集合在用户态和内核态之间拷贝;内核和用户态都需要遍历整个 FD 集合(时间复杂度O ( n ) O(n)O(n))。
    • 连接数限制:默认限制为1024个连接(由FD_SETSIZE宏定义,虽然可以改,但效率会急剧下降)。

总的原因就是每次调用都需要拷贝fd_set,而且需要进行线性循环。来个形象的比喻就是服务员需要挨个问客人你点好单了吗,不用想都是效率十分低下。

这张图展示了select低效的原因:每次调用都需要在用户态和内核态之间拷贝整个文件描述符集合 (fd_set),并且内核和用户程序都需要进行 O(n) 的线性遍历。

Poll:Select 的链表版

pollselect本质区别不大。

  • 工作原理:

    • 它使用pollfd结构体的链表(或数组)而不是 bitmap 来传递 FD。
  • 改进点:

    • 没有最大连接数限制(受限于系统内存和文件描述符限制)。
  • 缺点:

    • 性能依然是瓶颈:它和select一样,内核需要线性遍历所有 FD 来检查状态,用户态也需要遍历所有 FD 来查找谁就绪了。随着连接数增加,性能线性下降

最大的性能瓶颈并没有解决,所以这个我们并不需要太了解。

Epoll:Linux 的杀手锏

epoll是为了解决 C10K 问题而生的,它是目前 Linux 下高性能网络编程的核心。

  • 核心设计(三个函数):

    1. epoll_create:在内核创建一个 epoll 对象(内部结构是一棵红黑树和一个双向链表)。
    2. epoll_ctl:向红黑树中添加、删除或修改感兴趣的 FD。这也是O ( log ⁡ n ) O(\log n)O(logn)的效率,比线性扫描快得多。
    3. epoll_wait:等待事件。
  • 工作原理(Callback 机制):

    • epoll不再轮询。它为每个 FD 注册一个回调函数
    • 当网卡接收到数据,中断程序会调用回调函数,将该 FD 添加到就绪链表(Ready List)中。
    • epoll_wait实际上只是在检查这个就绪链表是否为空。
    • 用户进程只需要处理就绪链表中的 FD,不需要遍历所有连接。
  • 优点:

    • 效率极高:时间复杂度为O ( 1 ) O(1)O(1)(严格来说是O ( k ) O(k)O(k),k 为活跃连接数)。性能不会随总连接数增加而下降,只与“活跃”连接数有关。
    • 内存拷贝少:使用了 mmap(内存映射)技术或高效的内存管理,减少了复制开销(注:现代实现主要是避免了像 select 那样每次调用都重复传入整个 FD 集合)。
  • 两种触发模式:

    • LT (Level Triggered - 水平触发):默认模式。只要缓冲区还有数据,内核就会一直通知你。
    • ET (Edge Triggered - 边缘触发):高速模式。只有数据状态发生变化(从无到有)时通知一次。如果你不读完,内核不会再通知,这要求程序必须一次性把数据读完。Go 和 Nginx 使用的是 ET 模式的变种或思想来追求极致性能。

不好理解?来个比喻:服务员再也不用去挨个问是否点好单,而是由大堂经理将需要订单的顾客名单给服务员去通知后厨

这张图展示了epoll高效的原因:它使用红黑树来管理所有的文件描述符(只需注册一次),并采用事件驱动的机制。当网络设备有数据到达时,通过回调函数直接将就绪的 FD 加入到“就绪链表”中,应用程序只需要处理这个链表即可,无需遍历所有连接

Java和Go有什么需要了解的小知识?

作为后端开发,了解这些对你理解语言底层至关重要:

  1. Java (NIO / Netty):

    • Java 的java.nio.channels.Selector是一个抽象层。
    • 在 Linux 上,JDK 会自动映射到底层的epoll
    • Netty的核心 EventLoop 也就是在一个线程中不断轮询这个Selector(即epoll_wait),实现了高性能的 Reactor 模型。
  2. Go (Goroutine & Netpoller):

    • Go 的网络编程看起来是同步阻塞的(比如conn.Read()),但底层完全是异步非阻塞的。
    • Go Runtime 包含了一个Netpoller(网络轮询器)。
    • 在 Linux 下,Netpoller 封装了epoll。当你调用conn.Read()且没有数据时,Go 调度器会将该 Goroutine 挂起(Gopark),并将 FD 注册到epoll中。
    • epoll通知数据就绪,Go 调度器再唤醒该 Goroutine。

这就是 Go 高并发的核心秘密:用同步的代码逻辑,享受了 epoll 的异步性能。

总结

这就是全部内容,下面是一个小结表格。

特性SelectPollEpoll
底层数据结构Bitmap (数组)链表 / 数组红黑树(存储FD) +双向链表(存储就绪FD)
时间复杂度O ( n ) O(n)O(n)O ( n ) O(n)O(n)O ( 1 ) O(1)O(1)(与活跃数有关)
最大连接数1024 (默认)无限制无限制 (受系统内存限制)
IO效率随连接数增加而显著下降随连接数增加而显著下降不随总连接数线性下降
数据拷贝每次调用都需要拷贝全部 FD每次调用都需要拷贝全部 FDFD 仅在注册时拷贝一次

如果觉得我讲的好,就给我点赞+收藏+关注吧,这是我更新的最大动力❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1120178.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于微信小程序的体育场馆预约平台设计与实现(源代码+文档+PPT+调试+讲解)

课题摘要基于微信小程序的体育场馆预约平台,聚焦体育场馆运营 “预约便捷化、时段精细化、数据可视化” 的核心需求,针对传统场馆预约 “电话沟通低效、时段冲突多、利用率不均” 的痛点,构建覆盖预约用户、场馆管理员、平台运营者的全流程预…

基于 MATLAB 的电力系统动态分析研究【IEEE9、IEEE68系节点】​附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室🍊个人信条:格物致知,完整Matlab代码及仿真咨询…

Pharos STEM 台式场发射电镜在外泌体形貌与粒径分析中的应用

外泌体(Exosomes)是一类由细胞主动分泌的纳米级细胞外囊泡,近年来在生命科学与医学研究中受到广泛关注。作为细胞间信息传递的重要载体,外泌体在疾病诊断、作用机制研究以及药物递送等方向均显示出重要研究价值。在外泌体研究中&a…

一些常见的英文期刊库(爱思唯尔、MDPI、施普林格等)

一、爱思唯尔(Elsevier)ScienceDirect 网址:https://www.sciencedirect.com/ 二、MDPI 官网:https://www.mdpi.com/ 三、施普林格 网址:https://link.springer.com/ 四、arXiv(预印本) 网址…

Pharos STEM 台式场发射电镜在外泌体形貌与粒径分析中的应用

外泌体(Exosomes)是一类由细胞主动分泌的纳米级细胞外囊泡,近年来在生命科学与医学研究中受到广泛关注。作为细胞间信息传递的重要载体,外泌体在疾病诊断、作用机制研究以及药物递送等方向均显示出重要研究价值。在外泌体研究中&a…

python网络流量分析与入侵检测-计算机毕业设计源码+LW文档

网络流量分析与入侵检测 摘 要 在当今数字化时代,互联网技术蓬勃发展,网络攻击手段也随之呈现出复杂多样的态势。SQL注入、XSS跨站脚本、DDoS攻击等恶意行为频繁发生,给企业和个人的信息安全带来了巨大威胁。传统基于规则库的网络入侵检测…

基于 YOLOv8 的部落冲突 (Clash of Clans) 目标检测系统

1. 项目背景 《部落冲突》(Clash of Clans) 是一款风靡全球的策略类手机游戏。在游戏中,玩家需要通过识别敌方的防御建筑布局来制定进攻策略。本项目旨在利用深度学习技术,特别是 YOLOv8 目标检测算法,实现对游戏场景中关键建筑(如…

2026运维监控平台选型避坑指南

引言:此前我们已在《2025企业级运维监控平台哪家强?头部厂商及生态全景解析》一文中,梳理了企业级运维监控平台的头部厂商与生态格局,为企业选型提供了基础参考。本文将在此基础上,进一步系统拆解运维监控平台选型的常…

基于 SIFT 和 RANSAC 算法对高分辨率图像进行图像伪造检测附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室🍊个人信条:格物致知,完整Matlab代码及仿真咨询…

基于Android的校园互助平台-计算机毕业设计源码+LW文档

摘要 当前,随着移动互联网意义。 本文研究内容聚焦于利用Android操作系统的强大功能和广泛的用户基础,设计并实现一款集闲置物品交易、跑腿服务、广告发布及信息交流等多功能于一体的校园互助平台。该平台通过深入分析校园用户需求,结合先进的…

探秘 AgentRun|流量一大就瘫痪?如何解决AI 模型调用之痛

阿里云函数计算 AgentRun 全新发布后,我们整理了“探秘 AgentRun”系列文章,本系列将梳理企业落地Agent 常见难题,给出具体解法,助力 Agentic AI 快速走进生产级环境。欢迎加入“函数计算 AgentRun 客户群”与我们交流&#xff0c…

全网最全研究生必用AI论文写作软件TOP9:开题报告文献综述必备

全网最全研究生必用AI论文写作软件TOP9:开题报告文献综述必备 一、不同维度核心推荐:9款AI工具各有所长 在研究生论文写作过程中,从开题报告到文献综述,再到初稿撰写、查重降重、排版格式等环节,每一步都离不开高效、专…

基于 VSC 的 UPFC(统一潮流控制器)研究附Simulink仿真

✅作者简介:热爱科研的Matlab仿真开发者,擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室🍊个人信条:格物致知,完整Matlab代码及仿真咨询…

AI生成内容降重实录:我的论文降AI率经验分享

"## 随着AIGC技术的普及,越来越多的高校论文检测系统(尤其是知网)对AI生成内容的识别能力大幅提升,论文AI率成为提交前必须严肃面对的问题。我自己的毕业论文起初知网AIGC检测结果高达62%,深感焦虑。经过尝试多款…

【Transformer回归预测】基于TCN-Transformer实现数据回归预测附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 🍎 往期回顾关注个人主页:Matlab科研工作室 👇 关注我领取海量matlab电子书和数学建模资料 &#x1…

ChatGPT论文降重经验分享:如何有效降低论文AI率

"## 作为一名长期被论文查重和AIGC检测折磨的学生,论文的降重、降AI率工作一直是我绕不过的难题。尤其是近年来,随着知网AIGC检测的普及,越来越多的同学发现单纯靠传统的查重修改已经难以满足要求,论文中的AI生成内容比例&am…

day 50

浙大疏锦行

【从江瑶浴】品牌代表深度测评:谁才是真正的行业第一?

【从江瑶浴】品牌代表深度测评:谁才是真正的行业第一?在追求健康养生的今天,瑶浴以其独特的“以药入浴”方式,成为备受青睐的自然疗法。然而,面对市场上琳琅满目的瑶浴品牌,消费者往往难以抉择:…

MIPS架构是什么?

MIPS架构是什么? MIPS架构 是一种经典的精简指令集计算机(RISC) 处理器架构,以其简洁、高效和可扩展的设计而闻名。一、 核心设计哲学与技术实现 MIPS是“Microprocessor without Interlocked Pipeline Stages”的缩写&#xff0c…

【阵列优化】基于遗传算法及其在稀布阵列天线中的应用附matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 🍎 往期回顾关注个人主页:Matlab科研工作室 👇 关注我领取海量matlab电子书和数学建模资料 &#x1…