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 列表
相关推荐
FJW020814几秒前
【Linux】SElinux的管理及优化
linux·运维·服务器
坐怀不乱杯魂5 分钟前
Linux - 进程控制
linux·运维·服务器
重生之绝世牛码25 分钟前
Linux软件安装 —— zookeeper集群安装
大数据·linux·运维·服务器·zookeeper·软件安装
谢怜8226 分钟前
计算机网络第二章物理层
网络·计算机网络
额12937 分钟前
磁盘物理卷、卷组、逻辑卷管理
linux·运维·服务器
Maggie_ssss_supp37 分钟前
Linux-正则表达式
linux·运维·正则表达式
重生之绝世牛码1 小时前
Linux软件安装 —— kafka集群安装(SASL密码验证)
大数据·linux·运维·服务器·分布式·kafka·软件安装
努力的小帅1 小时前
Linux_多线程(Linux入门到精通)
linux·多线程·多进程·线程同步·线程互斥·生产消费者模型
凛_Lin~~1 小时前
安卓网络框架——OkHttp源码解析(基于3.14.x)
android·网络·okhttp