当前位置: 首页 > news >正文

【Linux】多路转接

📝前言:

这篇文章我们来讲讲Linux——多路转接

  • Select
  • Poll
  • Epoll
  • Reactor反应堆模式

🎬个人简介:努力学习ing
📋个人专栏:Linux
🎀CSDN主页 愚润求学
🌄其他专栏:C++学习笔记,C语言入门基础,python入门基础,C++刷题专栏


目录

  • 一,Select
    • 1. 接口概述
    • 2. fd_set位图操作
    • 3. select的缺点
  • 二,poll
    • 1. 接口介绍
    • 2. poll优缺点
  • 三,epoll
    • 1. epoll模型
    • 2. epoll接口介绍
      • epoll_create
      • epoll_ctl
      • epoll_wait
    • 工作流程
    • 3. LT 和 ET模式
    • 4. 简单示例
    • 5. epoll的写事件
  • 四,Reactor反应堆模式

一,Select

1. 接口概述

select用于监视多个文件描述符的状态变化,程序会停在 select 这里等待,直到被监视的文件描述符有一个或多个发生了状态改变。
在这里插入图片描述
参数

  • nfds:要监听的最大文件符的值 + 1
  • fd_set:分别对应于需要检测的可读文件描述符的集合(本质是位图,一个fd对应一个bit位),可写文件描述符的集 合及异常文件描述符的集合。
    • 这个参数是一个输入输出型参数,函数返回后,fd_set会被修改:返回本次调用监听到的文件描述符
    • 因为fd_set会被修改,所以我们一般需要一个辅助数组来保存我们需要监听的fd,然后每次select前把fd集合重置【这也是select的缺点之一】
  • timeout:监听时间(是一个结构体timeval)。在指定时间内如果没有监听到,则返回。如果监听到了,会返回剩余时间
    • NULL:则表示 select()没有 timeout,select 将一直被阻塞
    • 0:代表非阻塞监听
    • 具体的数值:监听时间具体时间

返回值

  • 成功:返回文件描述词状态已改变的个数
  • 超时:没有一个fd变化,返回0
  • 错误:-1,错误原因存于 errno,此时参数 readfds,writefds,exceptfds 和 timeout 的值变成不可预测。

2. fd_set位图操作

我们需要使用指定的接口来操作fd_set的位图

void FD_CLR(int fd, fd_set *set);// 用来清除描述词组 set 中相关fd 的位
int FD_ISSET(int fd, fd_set *set); // 用来测试描述词组 set 中相关fd 的位是否为真
void FD_SET(int fd, fd_set *set);// 用来设置描述词组 set 中相关fd 的位
void FD_ZERO(fd_set *set);// 用来清除描述词组 set 的全部位

3. select的缺点

  • selectfd集合是位图,支持的文件描述符数量有限
  • 每次调用select,都需要重新手动设置fd集合,使用不方便
  • 每次调用select,都需要把fd_set从用户态拷贝到内核态,有开销
  • 每次调用select,找就绪fd的时候,需要遍历所有fd,时间复杂度:O(n)

二,poll

1. 接口介绍

poll的使用场景较少,因为老系统用select,而poll又不如epoll好用
在这里插入图片描述
pollfd 结构:

struct pollfd {int fd; // 要监听的文件描述符/* file descriptor */short events; /* requested events */short revents; /* returned events */
};

poll接口把用户传入的需要监听的事件events,和内核返回给用户的监听到的事件revents做了区分

参数

  • fds:一个pollfd数组
  • nfds:fds 数组的长度
  • timeout:单位毫秒,超时时间(和select一样,不够更简单了)

2. poll优缺点

相比于select的优点:

  • 突破了文件描述符数量的限制
  • 文件描述符集合不会被重置

任然存在的缺点:

  • 每次调用 poll 时,仍需将整个pollfd数组从用户态拷贝到内核态
  • 查找就绪文件描述符的时间复杂度仍为 O (n),仍需遍历整个pollfd数组检查revents字段才能找到就绪的文件描述符

三,epoll

1. epoll模型

epoll模型包含三个重要组成部分:红黑树(用来存储要监听的fd,类似select的辅助数组),就绪队列(用来存储事件就绪的fd),回调方法(每个fd都注册了回调方法)

2. epoll接口介绍

epoll_create

在这里插入图片描述

  • size:在老版本中,代表文件描述符的数量,新版本已经不用管了。【数量不限】
  • 返回值:返回一个epfd(文件描述符)
  • 注意:用完以后,需要close()关闭这个epfd

epoll模型存储在epfd中,被一个private_data指针指向

epoll_ctl

在这里插入图片描述

  • 用于管理要监听的fd,常见的op(管理操作)有:
    • EPOLL_CTL_ADD:注册新的 fd 到 epfd 中
    • EPOLL_CTL_MOD:修改已经注册的 fd 的监听事件
    • EPOLL_CTL_DEL:从 epfd 中删除一个 fd
  • 不同于select()在监听事件时告诉内核要监听什么类型的事件,epoll要先注册要监听的事件类型。

struct epoll_event结构如下:
在这里插入图片描述
events 可以是以下几个宏的集合:

  • EPOLLIN : 表示对应的文件描述符可以读 (包括对端 SOCKET 正常关闭);
  • EPOLLOUT : 表示对应的文件描述符可以写;
  • EPOLLPRI : 表示对应的文件描述符有紧急的数据可读 (这里应该表示有带外
    数据到来);
  • EPOLLERR : 表示对应的文件描述符发生错误;
  • EPOLLHUP : 表示对应的文件描述符被挂断;
  • EPOLLET : 将 EPOLL 设为边缘触发(Edge Triggered)模式, 这是相对于水平触发(Level Triggered)来说的.
  • EPOLLONESHOT:只监听一次事件, 当监听完这次事件之后, 如果还需要继续监听这个 socket 的话, 需要再次把这个 socket 加入到 EPOLL 队列里

epoll_dataOS不做修改,用户可以用来自行保存一些自定义数据。

epoll_wait

在这里插入图片描述

  • 作用:epoll_wait 会等待内核就绪队列中有事件发生(即fd就绪),然后将就绪的事件(包含 fd 和事件类型)从内核态传递到用户态的 events 数组中。这个过程通过内存映射(mmap)优化,减少了传统拷贝的开销。
  • maxeventsevents的大小,不能超过用户态 events 数组的实际大小
  • 参数 timeout 是超时时间 (毫秒,0 会立即返回,-1 是永久阻塞).
  • 返回值:如果函数调用成功,返回对应 I/O 上已准备好的文件描述符数目,如返回 0 表示已超时, 返回小于 0 表示函数失败

工作流程

  1. 通过epoll_create创建epoll模型实例
  2. 通过epoll_ctl来管理要监听的fd,已经要等待的事件(所有事件被维护在一个红黑树中),每个fd会注册相应的回调方法。
  3. 当事件发生的时候,会触发回调方法,把就绪的事件加入到就绪队列中
  4. 当调用 epoll_wait 时,检查就绪队列中是否有已经就绪的事件

在这里插入图片描述

3. LT 和 ET模式

  • LT模式(epoll的默认行为):当 fd 处于就绪状态(如缓冲区有未读数据)时,每次调用epoll_wait都会返回该事件,直到数据被完全读取(缓冲区为空)
    • read的阻塞行为:没数据读 / 读不够。如:内核缓冲区只有512,但是read要读1024个,所以会:先拷贝 512 字节到用户态,然后阻塞,等待更多数据凑够 1024 字节
    • 支持阻塞和非阻塞读,因为就算一次读到的数据不满足read的要求也不会阻塞(因为下一次epoll_wait任然会通知)
  • ET模式:仅在 fd 状态从 “未就绪” 变为 “就绪” 时触发一次事件(如数据首次到达),后续即使缓冲区仍有未读数据,也不会再次通知,直到有新数据写入才会再次触发。
    • 只支持非阻塞读,因为ET模式只通知一次,如果当前数据不够读,则会阻塞,影响进程后续。
    • 所以要求用while在一次通知时循环读完,直到返回EAGAIN或EWOULDBLOCK(表示当前无更多数据),确保不会遗漏数据。

ET对比LT的优势:

  • ET通知更高效,epoll_wait的次数更少,有效通知次数更多
  • ET要求非阻塞 + while循环读,规范程序员写的代码。
  • 并且这种一次性读完的要求,可以尽快读取所有数据,腾出接受缓冲区空间,给对方提供一个更大的win窗口,加大对方滑动窗口的大小,提高网络发送的报文的并发度

4. 简单示例

epoll服务器(LT模式)→ 我的 Github

5. epoll的写事件

写就绪介绍

  • epoll读默认是不就绪的,写默认是就绪的(因为初始写入缓冲区为空)。
  • 读事件检测可以常设,但是写事件要按需设置
    • 正常情况下,若没有数据要写,无需将 “写事件” 添加到 epoll 监听中(因为初始就绪状态会导致 epoll 频繁唤醒,浪费资源)。
    • 只有当主动写数据时发现写缓冲区已满(write() 返回 -1 且 errno=EAGAIN/EWOULDBLOCK),才需要将 “写事件” 添加到 epoll 中,等待内核缓冲区有空闲空间后再重试写入。
    • 一旦数据写完(或缓冲区有足够空间写完剩余数据),必须立即删除 epoll 中的写事件监听,避免后续缓冲区空闲时 epoll 持续触发就绪通知(“写风暴”)。

处理写事件的标准流程(以非阻塞套接字为例)

  1. 初始不监听写事件:仅监听读事件(EPOLLIN),有数据要写时直接调用 write()
  2. 写操作判断
    • 若 write() 返回值 > 0:表示成功写入部分 / 全部数据,若数据已写完则结束,否则继续写。
    • 若 write() 返回 -1,且 errno=EAGAIN/EWOULDBLOCK:表示缓冲区已满,立即将 EPOLLOUT 事件添加到 epoll 监听中,等待后续就绪通知。
  3. 写事件触发后的处理:
    • 当 epoll 通知 EPOLLOUT 就绪时,再次调用 write() 写入剩余数据。
    • 若数据全部写完:立即从 epoll 中删除 EPOLLOUT 事件(避免后续频繁触发)。
    • 若仍返回 EAGAIN:说明缓冲区仍未足够,保留 EPOLLOUT 监听,等待下一次就绪。
  4. 错误处理:若 write() 返回其他错误(如 EPIPE、ECONNRESET),则关闭套接字并清理 epoll 监听。

当非阻塞IO的时候,遇到 error == EINTR 的错误,这是遇到了中断导致调用无法完成,这时候无序管它,continue即可

四,Reactor反应堆模式

代码 → 我的Github


🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

http://www.dtcms.com/a/495418.html

相关文章:

  • 可视化开发 + AI:软件开发的黄金组合
  • 哪个网站做质量认证书范本ps教程
  • 河北邢台有几个区县合肥seo网站优化培训
  • 2025年智能装备与机器人国际学术会议(IER 2025)
  • Fixed VLC snap on Ubuntu
  • 豆瓣 wordpress 插件做一个网站加优化排名得多少钱
  • 医疗实验室智能搬运方案:柔性革命与精准革新
  • 数据库快速加密与脱敏的融合实践:破解开发测试与数据共享的安全困局
  • 依赖关系管理:大模型分析代码库中的依赖关系,优化模块化设计
  • 在芯片互联中铝为什么会被替代呢?
  • 三门峡做网站手机销售培训网站
  • 东莞市建设公共交易中心网站首页乌克兰设计网站建设
  • QML学习笔记(四十一)QML的ColorDialog和FontDialog
  • [LVGL] 从0开始,学LVGL:进阶应用与项目实战(上)
  • 使用 Loki + Promtail + Grafana搭建日志系统
  • PySide 查找功能大杂烩 基于文本编辑器(QPlainTextEdit)
  • Vue3 路由配置和使用与讲解(超级详细)
  • 东盟建设集团重庆工程有限公司网站500强企业排名(2022最新名单)
  • 初次使用基于K3S的大数据平台
  • 极简入门Zookeeper
  • 国产工业软件:制造强国的“破局”之路
  • 从重机展到全球市场:数字化助力装备制造企业实现规范化管理
  • 半导体制造工艺基本认识 二 氧化
  • MongoDB 是关系型数据库吗?
  • 织梦dedecms网站内容页wordpress rss导入
  • RAG各模块联合优化思路:多智能体协作建模-MMOA-RAG浅尝
  • 【小白笔记】KNN 核心预测函数 _predict_one 的过程
  • 营销人职业成长路径:从执行到战略的能力进阶与知识体系构建
  • Elasticsearch 推理 API 增加了开放的可定制服务
  • 做电影网站还能赚钱ace wordpress