Linux 网络编程:select 与 epoll IO 多路复用详解

IO模型 + select、epoll 核心知识点

标签:Linux网络编程 IO多路复用 select epoll TCP并发

目录

  • 一、4种常见IO模型
  • [二、select 知识点](#二、select 知识点)
    • [1. fd_set 集合操作宏](#1. fd_set 集合操作宏)
    • [2. select函数](#2. select函数)
    • [3. select缺点(考试重点)](#3. select缺点(考试重点))
  • [三、epoll 三大API](#三、epoll 三大API)
    • [1. epoll_create](#1. epoll_create)
    • [2. epoll_ctl](#2. epoll_ctl)
    • [3. epoll_wait](#3. epoll_wait)
  • [四、epoll while(1)循环核心逻辑(高频代码考点)](#四、epoll while(1)循环核心逻辑(高频代码考点))
  • [五、select VS epoll对比](#五、select VS epoll对比)
  • 六、事件标记

一、4种常见IO模型

  1. 阻塞IO

    没有数据时CPU将任务挂起,任务不占用CPU资源,效率高。

  2. 非阻塞IO

    没有数据时,程序不停轮询检测数据是否到来,CPU持续执行代码,效率低。

  3. 信号驱动IO(异步IO)

    把fd设置为异步IO,内核监测fd事件;事件发生内核发送SIGIO信号通知用户层,程序捕获信号处理IO。

  4. 多路复用IO

    由内核同时监听一堆文件描述符,只要其中任意fd就绪,就返回给应用层,主要实现:selectepoll

补充:多线程TCP并发:

每个客户端分配一个独立线程;线程拥有独立栈空间,并发数量有限,客户端太多有系统崩溃风险;实际开发一般搭配线程池使用。

二、select 知识点

1. fd_set 集合操作宏

作用
FD_ZERO(fd_set *set) 清空文件描述符集合
FD_SET(int fd, fd_set *set) 将fd加入集合
FD_CLR(int fd, fd_set *set) 把fd从集合清除
FD_ISSET(int fd, fd_set *set) 判断fd是否在就绪集合中

2. select函数

c 复制代码
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  • 参数
    1. nfds最大文件描述符 + 1
    2. readfds:读事件fd集合;writefds:写事件fd集合;exceptfds:异常事件集合
    3. timeout:超时时间。传NULL代表永久阻塞等待事件。
  • 返回值
    *

    0:就绪的fd个数

    • -1:函数出错
    • 0:超时,没有任何事件发生

3.select缺点(考试重点)

  1. 返回后集合会被内核修改,每次循环必须重新FD_ZERO、FD_SET
  2. 需要循环从0~nfds‑1遍历全部fd,调用FD_ISSET判断是否就绪;
  3. 文件描述符数量有上限。

三、epoll 三大API

1. epoll_create

c 复制代码
int epoll_create(int size);
  • 功能:创建内核事件监听表
  • 参数:size现在被内核忽略,随便传正数
  • 返回:成功返回epoll的文件描述符epfd;失败返回‑1

2. epoll_ctl

c 复制代码
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
  • 功能:增、删、改内核事件表里的fd
  • op操作选项
    • EPOLL_CTL_ADD:添加fd进事件表
    • EPOLL_CTL_MOD:修改已经注册fd的监听事件
    • EPOLL_CTL_DEL:从事件表删除fd
  • struct epoll_event
c 复制代码
struct epoll_event{
    uint32_t events;    //监听的事件:EPOLLIN读 / EPOLLOUT写 / EPOLLET边沿触发
    epoll_data_t data;  //联合体,保存fd(常用data.fd)或者自定义指针
};
  • 返回值:成功0,失败‑1

3. epoll_wait

c 复制代码
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
  • 功能:阻塞等待事件发生
  • 参数
    1. epfd:epoll实例fd
    2. events:数组首地址,内核把已经就绪的事件拷贝到这个数组
    3. maxevents:events数组最大容量
    4. timeout:超时;‑1代表永久阻塞
  • 返回值
    *

    0:就绪fd的数量nready,只用遍历0 ~ nready‑1

    • -1:出错
    • 0:超时无事件

四、epoll while(1)循环核心逻辑(高频代码考点)

  1. 调用epoll_wait()阻塞等待事件;
  2. 根据返回的nready只循环nready次处理就绪事件;
  3. 判断就绪fd:
    • 如果是监听sockfd:代表新客户端连接,accept()得到confd,用EPOLL_CTL_ADD加入epoll监听;
    • 如果是普通客户端confd:客户端发来数据,执行读写处理函数;
  4. 客户端断开/出错:必须两步:EPOLL_CTL_DEL移除fd + close(confd),防止资源泄漏、CPU死循环;
  5. 处理完成回到循环开头继续epoll_wait等待。

五、select VS epoll对比

  1. select:返回要遍历全部fd;内核修改传入的集合,每次循环要重置集合;fd有上限。
  2. epoll:内核直接把就绪事件给到events数组,只遍历就绪的nready个;不需要每次重置集合;支持海量文件描述符。

六、事件标记

  • EPOLLIN:可读事件(客户端发来数据 / 新连接到来)
  • EPOLLOUT:可写事件
  • EPOLLET:边沿触发模式;默认是水平触发
相关推荐
未济2 天前
linux 配置环境变量
linux
傲世仙尊2 天前
目录即文件-Ext文件系统收尾篇
linux·c语言
虎头金猫2 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
这个DBA有点耶2 天前
MVCC深入:Read View、版本链与快照读——InnoDB并发控制的内核
数据库·mysql·架构
DBA_G2 天前
从地面到云霄:GBase数据库在民航三大场景的落地实践
数据库
自由能燃气设备2 天前
商用全预混低氮冷凝锅炉免费方案vs付费方案对比+选型避坑指南
大数据·数据库·人工智能
科创致远2 天前
科创致远 ESOP 系统核心效能与实战价值展示
大数据·数据库·人工智能·精益工程
_艾伦 耶格尔.2 天前
进程间通信
linux
Liuqy-052 天前
Linux IO编程——静态库、动态库
linux
wuyk5552 天前
《WiFi 嵌入式物联网开发全套实战》| 第 16 章 ESP32 AP+STA 双模共存原理与工程坑点
网络·stm32·物联网