首页 > 编程语言 >I/O 多路复用,网络编程中的select、poll、epoll的发展历史、原理详解以及代码实现(一)

I/O 多路复用,网络编程中的select、poll、epoll的发展历史、原理详解以及代码实现(一)

时间:2025-01-07 10:32:07浏览次数:3  
标签:epoll 并发 描述符 Linux poll select

selectpollepoll 的发展历史与背景

selectpollepoll 是 Linux/Unix 系统中处理多路 I/O 复用的核心技术,随着计算机网络的发展,它们的演进反映了高并发场景对性能优化的不断需求。

1. select 的起源

背景

  • 在 20 世纪 80 年代,Unix 系统的网络编程开始兴起,早期的 Unix 系统通常是为单任务场景设计的,I/O 操作依赖于阻塞模式。
  • 但随着网络服务(如 Telnet 和 FTP)的普及,单线程阻塞 I/O 的模式逐渐暴露问题:
    • 单个阻塞 I/O 操作会导致整个程序被挂起,无法处理其他任务。
    • 需要一种能够同时监控多个 I/O 描述符(文件描述符或套接字)的机制,以便支持高效的多任务操作。

发展

  • 1983 年select 系统调用首次在 BSD Unix 中引入,作为早期的多路复用 I/O 解决方案。
  • 它通过一个 固定长度的文件描述符集合(fd_set)监控多个文件描述符的状态(是否可读、可写或有异常)。
  • 使用场景:适用于早期的网络编程需求(例如监控少量的网络连接)。

问题

  1. 性能问题select 每次调用都需要将文件描述符集合从用户态复制到内核态(开销大)。内核会遍历所有文件描述符,即使大部分描述符无事件发生,依然需要轮询(时间复杂度 O(n))。
  2. 文件描述符数量限制select 通常限制最大文件描述符数为 1024(可以通过宏定义修改,但这会带来兼容性问题)。
  3. 不适合高并发:轮询方式效率低下,不适用于需要监听大量文件描述符的高并发场景。

2. poll 的改进

背景

  • 随着 90 年代互联网的兴起(如万维网的普及),网络服务器需要同时处理更多的客户端连接。
  • select 的性能瓶颈逐渐显现,尤其是在高并发场景下(如早期的 HTTP 服务器)。
  • Linux 逐步发展自己的多路 I/O 机制,poll 应运而生,作为 select 的改进版本。

发展

  • 1986 年poll 在 System V Unix 中首次引入,随后被移植到 Linux 和其他 Unix 系统。
  • select 的核心区别:
    • 使用一个动态数组(struct pollfd 数组)代替固定大小的 fd_set
    • 文件描述符数量不再受固定大小的限制。
    • 支持更灵活的事件注册机制。

优点

  1. 文件描述符无上限:数量不再固定,可以根据需求动态调整数组大小。
  2. 接口更直观:通过结构体 pollfd 明确指示每个文件描述符的状态和事件。

问题

  1. 性能问题依旧pollselect 一样,每次调用都需要遍历整个文件描述符集合(时间复杂度 O(n))。即使只有少数文件描述符发生事件,仍然需要轮询所有描述符。
  2. 内核交互开销:每次调用 poll 都需要将整个描述符数组从用户态复制到内核态。
  3. 高并发场景受限:大量无效文件描述符时,CPU 资源浪费严重。

3. epoll 的引入

背景

  • 随着 2000 年代互联网的高速发展(如 Web 2.0 的兴起),网络应用开始面临海量连接的需求:
    • 如电商、社交网络、在线游戏等应用,需要同时处理数万、甚至数十万的并发连接。
    • 高并发 I/O 场景对 selectpoll 的性能瓶颈暴露得更加明显。
    • 需要一个高效的事件通知机制,避免轮询所有文件描述符。
  • Linux 2.5.44(2002 年)epoll 在此版本中被引入,由 Linux 社区开发,成为 Linux 独有的多路复用 I/O 机制。

设计目标

  • 提升性能:
    • 采用事件驱动(Event-Driven)的方式,仅监控实际发生事件的文件描述符,避免轮询整个集合。
    • 减少内核与用户态之间的交互开销。
  • 适应高并发场景:
    • 通过注册机制,允许对文件描述符的事件监听进行增量更新。

优点

  1. 高效事件通知:文件描述符通过 epoll_ctl 注册到内核的红黑树中,后续的事件通知仅处理实际发生事件的文件描述符。
  2. 时间复杂度 O(1):对于就绪的文件描述符,内核通过就绪列表(双向链表)通知应用程序,无需遍历所有描述符。
  3. 边缘触发模式(ET):除了传统的水平触发模式(LT),epoll 支持边缘触发模式,只在状态发生变化时通知应用程序,提高性能。
  4. 无需重复传递描述符:描述符的注册和修改通过 epoll_ctl 完成,后续无需重复传递整个描述符集合。

问题

  1. 复杂性:相比 selectpollepoll 的使用更复杂,需要额外学习成本。
  2. 仅支持 Linuxepoll 是 Linux 特有的机制,缺乏跨平台支持。
  3. 过度依赖内核优化epoll 的性能在不同版本的 Linux 内核上可能有所不同。
  4. 并不是真正的异步操作:epoll在监听到 I/O有事件触发时,仍需阻塞并等待事件完成,与真正的异步 I/O(io_uring)不同。

4. 三者的历史时间线

时间技术背景与动机
1983 年select早期网络编程需求出现,select 提供了多路复用 I/O 的基础解决方案。
1986 年poll为解决 select 的文件描述符限制和接口灵活性问题,poll 在 System V 中引入。
2002 年epoll面对互联网的高并发需求,epoll 在 Linux 2.5.44 引入,解决了 selectpoll 的性能瓶颈。

 

总结

  1. select

    • 出现于 20 世纪 80 年代,适用于早期的低并发网络应用,已逐渐过时。
    • 主要解决单线程阻塞 I/O 的问题,简化多路复用。
  2. poll

    • select 基础上改进,适应更高的并发,但仍然存在性能瓶颈。
    • 动态数组的机制解决了文件描述符数量限制。
  3. epoll

    • 针对高并发场景设计,是现代 Linux 网络编程的主流解决方案。
    • 通过事件驱动和内核优化,显著提升了多路复用的效率。

selectpoll轮询式的多路复用模型,而 epoll事件驱动式的多路复用模型。它们的发展见证了网络编程从低并发到高并发的转变,同时也推动了操作系统内核技术的演进。

 本篇文章主要从select、poll、epoll的发展历史和背景进行了介绍,目的是梳理清楚这三者的出现顺序,以及是为了解决哪些具体的实际问题,后续将带来对select、poll、epoll的原理详解以及代码实现。

标签:epoll,并发,描述符,Linux,poll,select
From: https://blog.csdn.net/hz_uzi/article/details/144930266

相关文章

  • Tomcat 三大核心线程组件Acceptor、Poller 和 Executor&为什么tomcat 要把Acceptor单
    在Tomcat的架构中,Acceptor、Poller 和 Executor 是处理网络连接和请求的重要组件。 AcceptorAcceptor 是Tomcat中负责接受新连接的组件。它的主要职责包括:监听端口:Acceptor在线程中监听一个特定的端口,等待客户端连接请求。接受连接:当有新的连接请求到达时,Accepto......
  • Vue+Elementui: el-select组件下拉数据量大,产生页面卡顿或崩溃,详细解决方案!
    1.安装插件npminstallvue-virtual-scroll-list2.封装组件1>新建文件夹VirtualSelect创建文件:index.vue,OptionNode.vue/VirtualSelect/index.vue<template><div><el-selectsize="mini"popper-class="virtualselect"......
  • SQL 基础教程 - SQL SELECT 语句
    SQL SELECT 语句SELECT语句用于从数据库中选取数据。SQLSELECT语句SELECT语句用于从数据库中选取数据。结果被存储在一个结果表中,称为结果集。SQLSELECT语法SELECTcolumn1,column2,...FROMtable_name;与SELECT*FROMtable_name;参数说明:column1,co......
  • 为了解决服务启动慢的问题,我为什么要给Apollo和Spring提交PR?
    最近在整理之前记录的工作笔记时,看到之前给团队内一组服务优化启动耗时记录的笔记,简单整理了一下分享出来。问题原因并不复杂,主要是如何精准测量和分析,优化后如何定量测量优化效果,说人话就是用实际数据证明优化效果。背景团队内有一组服务启动明显较其它服务要慢(线上启动超过2分......
  • HTML Select Drop Down List Data Source From Web API
    前端,html还是mvc页面,我们想实现一个下拉选单,写<select>指定id或者name,稍后在js代码能获取到它。 #7~#9行,没有参数条件可传,保留为空。#19WebAPI地址。#21为异步方法,看下,#37,是为了不让代码写在一块,Insus.NET已经重构成另一个function,也是本示例中重点核心代码,下面继续看看,......
  • toad.selection.select函数
    toad.selection.select函数概述toad.selection.select是toad库中用于自动特征选择的一个重要函数。它根据指定的阈值条件,筛选出符合要求的特征,同时可以根据特征间的相关性进一步剔除冗余特征。这个函数特别适用于信用评分卡建模和其他金融风控场景,帮助快速清洗和优化特......
  • selectdataset 发布2024最热门Top100数据集
    遇见数据集索引了国内外的大部分网站。首页有最新的数据集推荐:GitHub、HuggingFace、arXiv这些热门站点​,都属于日级别的更新。这个站点是从搜索引擎方面去监控最新的数据集,大家如果有关注某个一个特点领域或话题的更新,可以关注这个站点:遇见数据集-让每个数据集都被发现,让每......
  • layui框架中利用xm-select实现下拉多选功能,以及如何设置默认值
    xm-select.js的下载地址:https://gitee.com/maplemei/xm-select/tree/master/dist引入xm-select.js<scriptsrc="/static/tools/pear/component/pear/xm-select.js"></script>dom元素<divid="doors"></div>layui中使用layui.......
  • selection
    selection基础库3.6.4开始支持,低版本需做兼容处理。渲染框架支持情况:WebView功能描述局部文本选区。属性说明属性类型默认值必填说明最低版本disable-context-menubooleanfalse否是否隐藏客户端原生文本选区按钮3.6.4bindselectionchangeeventhan......
  • mybatis一对多collection select
     mybatis一对多collectionselect在MyBatis中,处理一对多关系时,通常会在映射文件中使用<collection>元素,并在其中嵌套一个<select>元素来实现对关联表的查询。这种方式允许你从一个表(称为“一”的一方)中查询数据,并同时获取与其关联的多个表(称为“多”的一方)中的数据......