Linux网络编程——IO多路复用

目录

[一、IO 多路复用的定义和作用](#一、IO 多路复用的定义和作用)

[二、Linux 提供的 IO 模型](#二、Linux 提供的 IO 模型)

[三、IO 多路复用之 select](#三、IO 多路复用之 select)

[1.select 的处理流程](#1.select 的处理流程)

[2.select 相关函数](#2.select 相关函数)

[四、IO 多路复用之 epoll](#四、IO 多路复用之 epoll)

[1.epoll 的处理流程](#1.epoll 的处理流程)

[2.epoll 相关函数](#2.epoll 相关函数)

[2.1 创建 epoll 集合](#2.1 创建 epoll 集合)

[2.2 管理 FD(添加 / 删除)](#2.2 管理 FD(添加 / 删除))

[2.3 等待就绪事件](#2.3 等待就绪事件)

[五、select 与 epoll 的区别](#五、select 与 epoll 的区别)


在 Linux 网络编程中,IO 多路复用是处理高并发场景的核心技术之一。它让单线程 / 进程能同时监听多个 IO 对象(比如 socket、文件描述符),大幅提升程序的资源利用率。

一、IO 多路复用的定义和作用

  • 定义:单线程 / 单进程同时监测多个文件描述符(FD),判断哪些可以执行 IO 操作的能力。
  • 核心作用
    1. 用在 TCP Server 中,同时处理多个客户端请求;
    2. 对多个阻塞设备做 IO:哪个设备数据先就绪(可读 / 可写),就优先处理。

二、Linux 提供的 IO 模型

Linux 下常见的 IO 模型有 5 种,其中IO 多路复用是高并发场景的首选:

  1. 阻塞 IO(默认):IO 操作时阻塞线程,直到完成;
  2. 非阻塞 IO:不阻塞线程,但需轮询判断是否就绪;
  3. 信号驱动 IO(SIGIO):用得较少;
  4. 并行模型(进程 / 线程):资源开销大;
  5. IO 多路复用:select、poll、epoll。

三、IO 多路复用之 select

select 是 IO 多路复用的经典实现,核心是轮询检测 FD 集合

1.select 的处理流程

  1. 创建 FD 集合(数组);
  2. 将需要监听的 FD 添加到集合;
  3. select 阻塞等待,轮询检测 FD 是否就绪;
  4. 遍历集合,找到就绪的 FD;
  5. 对就绪 FD 执行 read/write 操作;
  6. 注意 :每次检测后需手动清除集合的标志位(因为 select 会修改集合)。

2.select 相关函数

cpp 复制代码
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  • **功能:**阻塞等待,检测集合中就绪的 FD;
  • 参数:
    • nfds:监听的最大 FD+1;
    • readfds/writefds/exceptfds:读 / 写 / 异常 FD 集合;
    • timeout:超时时间(NULL 表示一直阻塞);
  • 辅助函数:
    • FD_ZERO(fd_set *set):清空 FD 集合;
    • FD_SET(int fd, fd_set *set):将 FD 加入集合;
    • FD_CLR(int fd, fd_set *set):从集合中移除 FD;
    • FD_ISSET(int fd, fd_set *set):判断 FD 是否在集合中。

四、IO 多路复用之 epoll

epoll 是 select 的 "加强版",专为高并发设计,核心是事件驱动 + 主动上报

1.epoll 的处理流程

  1. 创建 epoll 集合(内核维护的二叉树结构);
  2. 将需要监听的 FD 添加到集合;
  3. epoll_wait 阻塞等待,由内核主动上报就绪 FD;
  4. 从返回的 rev 数组中直接获取就绪 FD;
  5. 对就绪 FD 执行读写操作。

2.epoll 相关函数

2.1 创建 epoll 集合

cpp 复制代码
int epoll_create(int size);
  • **功能:**创建 epoll 集合
  • **参数:**size:指定集合的大小
  • 返回值:
    • >0:epoll 对应的文件描述符(epfd)
    • -1:错误

2.2 管理 FD(添加 / 删除)

cpp 复制代码
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
  • **功能:**向集合中添加或删除文件描述

  • 参数:

    • size:指定集合的大小

    • op:

      • EPOLL_CTL_ADD:添加描述描述符到集合
      • EPOLL_CTL_DEL :从集合中删除文件描述符
    • fd:关心的文件描述符

    • event:监听的事件
      *

      cpp 复制代码
      struct epoll_event {
          uint32_t events; // 关心读(EPOLLIN),写(EPOLLOUT)
          epoll_data_t data; // 用户自定义数据,方便后期查找
      };
  • 返回值:

    • 0:成功
    • -1:错误

2.3 等待就绪事件

cpp 复制代码
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
  • **功能:**等待 io 事件的到来,阻塞函数
  • 参数:
    • epfd:需要检测的集合
    • events:当有 io 事件到来时,存储准备(可读或可写)就绪的文件描述符数组
    • maxevents:events 数组的大小
    • timeout :超时值设置。 单位 ms(毫秒)(-1:阻塞版本)
  • 返回值:
    • >0:集合中准备就绪的文件描述符的个数
    • 0:超时
    • -1:错误

五、select 与 epoll 的区别

对比维度 select epoll
FD 数量限制 最多 1024 个 无限制(仅受系统资源约束)
性能 随 FD 数量增加而下降(O (n) 轮询) 不随 FD 数量变化(O (1) 主动上报)
数据传递 内核 - 用户层多次拷贝 FD 集合 共享内存,无额外拷贝
返回结果 需遍历原始集合找就绪 FD 直接返回就绪 FD 列表
相关推荐
酱学编程12 分钟前
【从零到一实现一个 AI Agent 框架 · 第四篇】04. 任务规划:拆解复杂目标 -
服务器·网络·数据库·人工智能
风行南方1 小时前
密码学之分组密码
网络·密码学
SkyWalking中文站1 小时前
认识 Horizon UI · AI Assistant:用日常语言查询你的可观测性数据
运维·监控·自动化运维
艾莉丝努力练剑2 小时前
OpenCode AI 编程:Ubuntu 24.04 环境安装与使用指南
linux·服务器·网络·人工智能·tcp/ip·ubuntu
崇山峻岭之间2 小时前
Keil5输出hex转换为bin的设置
linux·运维·服务器
Hoxy.R3 小时前
KingbaseES读写分离高可用集群扩容、备库重建与故障切换实战
运维·数据库
谷雪_6583 小时前
Linux 网络命名空间:从内核原理到企业级容器网络架构全景实战
linux·网络·架构
liulilittle3 小时前
KCC 拥塞控制算法缺陷修复记录(26/07/05)
网络·tcp/ip·计算机网络·c·信息与通信·tcp·通信
Tian_Hang3 小时前
Eclipse Ditto 的权限策略
java·服务器·前端·网络·ide·ubuntu·eclipse
qq_163135754 小时前
Linux 【03- chgrp命令超详细教程】
linux