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 列表
相关推荐
好记忆不如烂笔头abc2 小时前
Ubuntu 20.04.6上实现远程桌面连接
服务器·网络·数据库
乐维_lwops2 小时前
IT运维的核心目标和主要工作内容
运维·网络·it运维
云老大TG:@yunlaoda3602 小时前
华为云国际站代理商运维保障的具体要求有哪些?
大数据·运维·华为云
旖旎夜光2 小时前
Linux(3)(上)
linux·学习
❀͜͡傀儡师3 小时前
Docker安装SQL Server并使用Navicat远程连接
运维·docker·容器
zhuzewennamoamtf3 小时前
Linux Regmap API寄存器映射抽象化
linux·运维·服务器
Joker 0073 小时前
Linux nohup命令实战指南
linux·运维·wpf
大聪明-PLUS3 小时前
管理 Linux 内核模块
linux·嵌入式·arm·smarc
lifewange3 小时前
关于进程的 Linux 命令有哪些?
linux·运维·服务器