深度剖析并发I/O模型select、poll、epoll与IOCP核心机制
核心概要:select
、poll
、epoll
和 IOCP
是四种用于提升服务器并发处理能力的I/O模型或机制。前三者主要属于I/O多路复用范畴,允许单个进程或线程监视多个I/O流的状态;而 IOCP
则是一种更为彻底的异步I/O模型。
一、引言:为何需要这些技术?
在网络服务器开发中,一个核心挑战是如何高效地处理大量并发连接。传统的阻塞式I/O模型(一个线程处理一个连接,并在I/O操作时阻塞)在并发量高时会导致线程数量激增,带来巨大的上下文切换开销和资源消耗。为了解决这一问题,发展出了I/O多路复用和异步I/O技术。
二、I/O多路复用技术:select
, poll
, epoll
I/O多路复用允许单个进程监视多个文件描述符(FD),一旦某个或某些FD就绪(例如,可读或可写),便通知应用程序进行相应的I/O操作。应用程序本身在调用这些多路复用函数时可能会阻塞,但一旦收到通知,后续的I/O操作(如read
, write
)通常可以非阻塞地执行,或者至少是已知的可操作状态。
1. select
一句话介绍:select
是一种传统的I/O多路复用机制,它允许程序监视一组文件描述符,等待一个或多个描述符变为就绪状态。
工作机制:
-
应用程序通过
fd_set
数据结构向内核注册需要监视的读、写和异常文件描述符集合。 -
调用
select
函数,该调用会阻塞,直到有文件描述符就绪或超时。 -
select
返回后,内核会修改传入的fd_set
来指示哪些文件描述符已就绪。 -
应用程序需要遍历整个
fd_set
来找出具体就绪的文件描述符,并对其进行操作。
主要特点:
-
跨平台性:作为早期标准,
select
具有良好的跨平台兼容性。 -
文件描述符数量限制:受
FD_SETSIZE
宏的限制(通常为1024或2048),能够监视的文件描述符数量有限。 -
性能开销:
-
每次调用都需要将
fd_set
在用户空间和内核空间之间完整拷贝。 -
内核在检查时需要遍历所有被监视的FD。
-
应用程序在返回后也需要遍历
fd_set
以确定哪些FD就绪。
-
举例:想象一位老派的邮局分拣员。每次来一批信件(FD集合),他都要把所有信箱(所有被监视的FD)检查一遍,看看哪些信箱里有新信(FD就绪)。即使只有少数信箱有信,他也得全部看一遍。而且他能管理的信箱总数也是固定的。
2. poll
一句话介绍:poll
是 select
的一种改进,它解决了文件描述符数量的限制,并使用不同的数据结构来管理监视的描述符。
工作机制:
-
应用程序使用一个
pollfd
结构体数组来指定要监视的文件描述符及其关心的事件(如POLLIN
表示可读,POLLOUT
表示可写)。 -
调用
poll
函数,该调用会阻塞,直到有描述符就绪或超时。 -
poll
返回后,内核会在pollfd
结构体中的revents
字段中标示出哪些文件描述符发生了哪些事件。 -
应用程序需要遍历这个
pollfd
数组来找出就绪的描述符。
主要特点:
-
无文件描述符数量硬性限制:监视的FD数量仅受系统资源限制。
-
数据结构改进:使用
pollfd
结构体,每个结构体对应一个FD,避免了select
中fd_set
的固定大小问题。 -
性能开销依然存在:
-
每次调用仍需将
pollfd
数组在用户空间和内核空间之间拷贝。 -
内核和应用程序仍需遍历所有被监视的FD(即使只有少数就绪)。
-
3. epoll
(Linux Specific)
一句话介绍:epoll
是 Linux 内核提供的高效I/O多路复用机制,它显著改善了处理大量并发连接时的性能。
工作机制:
epoll
的使用分为三个主要步骤:
-
epoll_create
/epoll_create1
:在内核中创建一个epoll
实例,返回一个代表该实例的文件描述符。 -
epoll_ctl
:向epoll
实例中添加(EPOLL_CTL_ADD
)、修改(EPOLL_CTL_MOD
)或删除(EPOLL_CTL_DEL
)需要监视的文件描述符及其关心的事件。这些信息由内核维护,不需要重复传递。 -
epoll_wait
:阻塞等待已注册的文件描述符上发生就绪事件。与select
和poll
不同,epoll_wait
仅返回那些已经就绪的文件描述符,而不是所有被监视的描述符。
主要特点:
-
高效性:
-
事件驱动:内核负责跟踪FD的状态,当FD就绪时,会将其放入一个就绪列表中。
epoll_wait
只需检查此列表。 -
减少数据拷贝:FD集合由内核管理,
epoll_wait
调用时无需拷贝整个FD集合。 -
无需遍历:应用程序直接从
epoll_wait
的返回中获取就绪的FD列表,避免了轮询。
-
-
支持边缘触发 (ET) 和水平触发 (LT):
-
LT (Level Triggered, 默认):只要FD处于就绪状态,
epoll_wait
就会通知。 -
ET (Edge Triggered):仅当FD状态从未就绪变为就绪时通知一次。这要求应用程序一次性处理完所有可用数据,编程更复杂,但能进一步减少
epoll_wait
的调用次数。
-
-
Linux 特有:不具备跨平台性。
举例:epoll
就像一个现代化的智能快递柜系统。快递员(内核)把包裹(数据)放进柜子(FD就绪)后,系统会自动给收件人(应用程序)发送一条取件码(epoll_wait
返回就绪的FD)。收件人凭码直接取件,无需检查每个柜子。
三、异步I/O模型:IOCP
(Windows Specific)
异步I/O (Asynchronous I/O) 模型与I/O多路复用有本质区别。在异步I/O中,应用程序发起一个I/O操作后立即返回,不等待操作完成。操作系统内核负责完成整个I/O过程(包括将数据从内核空间拷贝到用户指定的缓冲区),并在操作完成后通过特定机制通知应用程序。
IOCP
(I/O Completion Ports)
一句话介绍:IOCP
是 Windows 平台上一种高效、可伸缩的异步I/O模型,专为处理大量并发I/O操作设计。
工作机制:
-
创建完成端口:应用程序首先创建一个I/O完成端口 (
CreateIoCompletionPort
)。 -
关联设备句柄:将需要进行异步I/O操作的设备句柄(如套接字、文件句柄)与该完成端口关联。
-
发起异步I/O操作:应用程序调用异步I/O函数(如
ReadFile
,WriteFile
,WSASend
,WSARecv
),并提供一个OVERLAPPED
结构和一个可选的完成键。这些函数会立即返回,表示操作已成功提交给操作系统。 -
操作系统处理:操作系统内核在后台执行实际的I/O操作。
-
完成通知:当I/O操作完成(或失败)后,操作系统会将一个包含操作结果和
OVERLAPPED
结构指针的“完成包”排入与设备句柄关联的完成端口队列中。 -
获取完成状态:应用程序的工作线程调用
GetQueuedCompletionStatus
函数,该函数会阻塞等待,直到完成端口队列中有完成包。获取到完成包后,线程便可以处理已完成的I/O操作结果(数据已在用户缓冲区)。
主要特点:
-
真正的异步:应用程序不参与实际的I/O数据传输过程,仅发起请求和处理完成通知。
-
高效的线程管理:
IOCP
能够与线程池良好集成。操作系统会根据I/O负载和CPU核心数量智能地调度和唤醒工作线程,避免了过多的线程创建和上下文切换。 -
高吞吐量和伸缩性:非常适合构建高性能服务器应用。
-
Windows 特有:不具备跨平台性。
举例:IOCP
就像一个大型中央厨房的外卖系统。顾客(应用程序)通过App下单(发起异步I/O),然后就可以去做别的事情了。中央厨房(操作系统)负责烹饪并打包(执行I/O)。菜品完成后,系统会通知骑手(工作线程)去指定的取餐点(完成端口)取餐并配送(处理完成的I/O)。骑手们被高效地调度,确保外卖准时送达。
四、总结
特性 | select | poll | epoll (Linux) | IOCP (Windows) |
---|---|---|---|---|
模型 | 同步I/O多路复用 | 同步I/O多路复用 | 同步I/O多路复用 | 异步I/O |
核心思想 | 监视FD,等待就绪通知 | 监视FD,等待就绪通知 | 高效监视FD,仅返回就绪FD | 发起I/O,等待操作完成通知 |
数据传输 | 程序在收到通知后自行读写 | 程序在收到通知后自行读写 | 程序在收到通知后自行读写 | 内核完成数据传输 |
效率 | 低,受FD数量和轮询限制 | 一般,不受FD数量限制,但仍需轮询 | 高,事件驱动,无需轮询 | 非常高,内核级异步,线程调度优化 |
跨平台性 | 良好 | 较好 | 差 (Linux) | 差 (Windows) |
选择哪种技术取决于具体的应用场景、目标平台以及对性能和并发能力的要求。对于需要跨平台且并发要求不极端的情况,select
或 poll
可能是简单选择。对于Linux平台下追求极致性能的高并发服务器,epoll
是首选。对于Windows平台下的高性能服务器,IOCP
提供了强大的异步处理能力。
相关文章:

深度剖析并发I/O模型select、poll、epoll与IOCP核心机制
核心概要:select、poll、epoll 和 IOCP 是四种用于提升服务器并发处理能力的I/O模型或机制。前三者主要属于I/O多路复用范畴,允许单个进程或线程监视多个I/O流的状态;而 IOCP 则是一种更为彻底的异步I/O模型。 一、引言:为何需要这…...
单片机——实现交通信号灯管理
随便写写,汇总一下,就一个单片机,没有模拟软件,什么都没有~ 点阵、数码管、led同时点亮 #include <reg52.h>sbit ADDR0 P1^0; sbit ADDR1 P1^1; sbit ADDR2 P1^2; sbit ADDR3 P1^3; sbit ENLED P1^4;// 交通灯控制引…...

数据结构 -- 交换排序(冒泡排序和快速排序)
冒泡排序 基于“交换”的排序:根据序列中两个元素关键字的比较结果来对换这两个记录在序列中的位置 //交换 void swap(int &a,int &b){int temp a;a b;b temp; }//冒泡排序 void BubbleSort(int A[],int n){for(int i0;i<n-1;i){bool flag false; …...

【算法】: 前缀和算法(利用o(1)的时间复杂度快速求区间和)
前缀和算法:高效处理区间求和的利器 目录 引言什么是前缀和前缀和的基本实现前缀和的作用前缀和的典型应用场景前缀和的优缺点分析实战例题解析 引言 区间求和问题的普遍性暴力解法的时间复杂度问题前缀和算法的核心思想 什么是前缀和 前缀和的数学定义 通俗来…...

macOS 安装 PostgreSQL
文章目录 安装安装信息 验证GUI 工具下载 安装 最简单的方式是通过 brew 安装 brew install postgresql17该版本在 brew 上的详情页:https://formulae.brew.sh/formula/postgresql17 你也可以根据需要,搜索 安装更新版本 如果你没有安装 brew…...
打破传统范式,线上 3D 画展彰显多元亮点
(一)沉浸式体验,身临其境赏画 线上 3D 画展运用先进的 3D 建模和虚拟现实(VR)技术,高度还原了真实的展厅环境 。展厅内的布局、灯光,甚至墙壁的质感都被完美复刻,让观众仿佛置身于…...

Linux系统:基础命令之 ls~pwd~cd
文章目录 前言一、ls命令📘 命令简介:🧠 基本语法:演示ls🔧 常用选项:-l选项-a选项-h选项 小结 ls 二、pwd命令📘 命令简介:何为绝对路径!何为相对路径!&…...
MuJoCo安装记录
一、Anaconda安装 1. 下载安装包:https://repo.anaconda.com/archive/Anaconda3-2021.11-Linux-x86_64.sh 2. 进入下载界面执行以下命令安装 sudo chmod x Anaconda3-2021.11-Linux-x86_64.sh ./Anaconda3-2021.11-Linux-x86_64.sh 3. 如果安装anaconda之后打开…...
软件工程(八):UML类图的几种关系
依赖(Dependency) 定义:一个类使用到了另一个类(例如作为参数、局部变量等)。表示:虚线箭头,箭头指向被依赖的类。关键词:uses、depends on。示例:类 A 的某个方法使用类…...
python定时删除指定索引
脚本 import logging from datetime import datetime, timedelta from elasticsearch import Elasticsearch# 配置日志记录 logging.basicConfig(filenamedelete_uat_indices.log,levellogging.INFO,format%(asctime)s - %(levelname)s - %(message)s )# Elasticsearch 集群的…...

基于OAuth2-proxy和Keycloak为comfyui实现SSO
背景 comfyui无认证被漏扫后易被rce挖矿 攻击过程 https://www.oschina.net/news/340226 https://github.com/comfyanonymous/ComfyUI/discussions/5165 阿里云漏洞库关于comfyui的漏洞 https://avd.aliyun.com/search?qcomfyui×tamp__1384n4%2BxBD0GitGQ0QD8ID%2F…...

SmartSoftHelp 之 SQL Server 数据库安全备份与安全还原详解---深度优化版:SmartSoftHelp DeepCore XSuite
SmartSoftHelp 菜单之 DBMS 数据库备份与还原 (DBBackRest) 使用实例 SQL Server 数据库备份与还原详解 SQL Server 数据库的备份与还原是管理数据库的核心任务之一,涉及本地与远程操作、大小监控及目录管理等多个方面。以下是详细说明: 一、数据库…...

Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决
Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决 Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决1. 问题现象与初步分析2 . 原因探究:代理机制对分布式锁生命周期的干扰3. 问题复现伪代码4. 解决方案࿱…...

【数据结构】队列的完整实现
队列的完整实现 队列的完整实现github地址前言1. 队列的概念及其结构1.1 概念1.2 组织结构 2. 队列的实现接口一览结构定义与架构初始化和销毁入队和出队取队头队尾数据获取size和判空 完整代码与功能测试结语 队列的完整实现 github地址 有梦想的电信狗 前言 队列&…...
2025 全球优质 AI 产品深度测评:从通用工具到垂直领域的技术突围 —— 轻量聚合工具篇
在 AI 技术爆发式增长的 2025 年,全球范围内涌现出大量兼具技术创新与场景价值的优质产品。本文从通用对话、多模态生成、开发者工具、企业级方案及垂直领域深耕五个维度,深度解析 18 款国内外标杆产品,附独家对比数据与选型策略,…...
Python爬虫实战:获取天气网最近一周北京的天气数据,为日常出行做参考
1. 引言 随着互联网技术的发展,气象数据的获取与分析已成为智慧城市建设的重要组成部分。天气网作为权威的气象信息发布平台,其数据具有较高的准确性和实时性。然而,人工获取和分析天气数据效率低下,无法满足用户对精细化、个性化气象服务的需求。本文设计并实现了一套完整…...

根据YOLO数据集标签计算检测框内目标面积占比(YOLO7-10都适用)
程序: 路径改成自己的,阈值可以修改也可以默认 #zhouzhichao #25年5月17日 #计算时频图中信号面积占检测框面积的比值import os import numpy as np import pandas as pd from PIL import Image# Define the path to the directory containing the lab…...
Helm简介、安装、配置、使用!
一、简介 Helm 是 Kubernetes 的包管理器。包管理器类似于我们在 Ubuntu 中使用的apt、Centos中使用的yum 或者Python中的 pip 一样,能快速查找、下载和安装软件包。Helm 由客户端组件 helm 和服务端组件 Tiller 组成, 能够将一组K8S资源打包统一管理, 是查找、共享…...

LLM笔记(九)KV缓存(2)
文章目录 1. 背景与动机2. 不使用 KV Cache 的情形2.1 矩阵形式展开2.2 计算复杂度 3. 使用 KV Cache 的优化3.1 核心思想3.2 矩阵形式展开3.3 计算复杂度对比 4. 总结5. GPT-2 中 KV 缓存的实现分析5.1 缓存的数据结构与类型5.2 在注意力机制 (GPT2Attention) 中使用缓存5.3 缓…...
开发 前端搭建npm v11.4.0 is known not to run on Node.js v14.18.1.
错误nodejs 和npm 版本不一致 ERROR: npm v11.4.0 is known not to run on Node.js v14.18.1. This version of npm supports the following node versions: ^20.17.0 || >22.9.0. You can find the latest version at https://nodejs.org/. ERROR: D:\softTool\node-v14…...

LVS 负载均衡集群应用实战
前提:三台虚拟机,有nginx,要做负载 1. LVS-server 安装lvs管理软件 [root@lvs-server ~]# yum -y install ipvsadm 程序包:ipvsadm(LVS管理工具) 主程序:/usr/sbin/ipvsadm 规则保存工具:/usr/sbin/ipvsadm-save > /path/to/file 配置文件:/etc/sysconfig/ipvsad…...

MySQL——基本查询内置函数
目录 CRUD Create Retrieve where order by limit Update Delete 去重操作 聚合函数 聚合统计 内置函数 日期函数 字符函数 数学函数 其它函数 实战OJ 批量插入数据 找出所有员工当前薪水salary情况 查找最晚入职员工的所有信息 查找入职员工时间升序排…...

Day34打卡 @浙大疏锦行
知识点回归: CPU性能的查看:看架构代际、核心数、线程数GPU性能的查看:看显存、看级别、看架构代际GPU训练的方法:数据和模型移动到GPU device上类的call方法:为什么定义前向传播时可以直接写作self.fc1(x) 作业 计算资…...
【Jitsi Meet】(腾讯会议的平替)Docker安装Jitsi Meet指南-使用内网IP访问
Docker安装Jitsi Meet指南-使用内网IP访问 下载官方代码配置环境变量复制示例环境文件并修改配置:编辑 .env 文件: 修改 docker-compose.yml 文件生成自签名证书启动服务最终验证 腾讯会议的平替。我们是每天开早晚会的,都是使用腾讯会议。腾…...

AdGuard解锁高级版(Nightly)_v4.10.36 安卓去除手机APP广告
AdGuard解锁高级版(Nightly)_v4.10.36 安卓去除手机APP广告 AdGuard Nightly是AdGuard团队为及时更新软件而推出的最新测试版本,适合追求最新功能和愿意尝试新版本的用户。但使用时需注意其潜在的不稳定性和风险。…...

C++修炼:红黑树的模拟实现
Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路! 我的博客:<但凡. 我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》 欢迎点赞,关注&am…...

基于Python+YOLO模型的手势识别系统
本项目是一个基于Python、YOLO模型、PyQt5的实时手势识别系统,通过摄像头或导入图片、视频,能够实时识别并分类不同的手势动作。系统采用训练好的深度学习模型进行手势检测和识别,可应用于人机交互、智能控制等多种场景。 1、系统主要功能包…...

自制操作系统day10叠加处理
day10叠加处理 叠加处理(harib07b) 现在是鼠标的叠加处理,以后还有窗口的叠加处理 涉及图层 最上面小图层是鼠标指针,最下面的一张图层用来存放桌面壁纸。移动图层的方法实现鼠标指针的移动以及窗口的移动。 struct SHEET { u…...
docker初学
加载镜像:docker load -i ubuntu.tar 导出镜像:docker save -o ubuntu1.tar ubuntu 运行: docker run -it --name mu ubuntu /bin/bash ocker run -dit --name mmus docker.1ms.run/library/ubuntu /bin/bash 进入容器:docke…...
## Docker 中 Elasticsearch 启动失败:日志文件权限问题排查与解决
好的,这是一份关于你遇到的 Docker Elasticsearch 启动报错问题的笔记,包含问题描述、我的分析判断以及最终的解决方案,适合用于整理成文章。 Docker 中 Elasticsearch 启动失败:日志文件权限问题排查与解决 在使用 Docker部署 E…...