【Linux:IO多路复用(select函数)

embedded/2024/11/14 4:19:47/

什么是IO多路复用?

一种网络通信的手段,IO多路复用可以同时监测多个文件描述符,且这个过程是阻塞的,当检测有文件描述符就绪,程序的阻塞就会解除,就可以通过这些就绪的文件描述符进行通信。通过这种方式在单线程/进程的场景下也可以在服务器端实现并发。常见的IO多路转接方式有:select、poll、epoll。

select:

该函数是跨平台的,检测文件描述符的读写状态

 这三个指针是指向三个文件描述符集合的指针。

参数介绍:

  • nfds:是在这三个文件描述符集合中找出一个最大的文件描述符再+1
    • 内核中需要线性遍历这些集合中的文件描述符,该值是循环结束的条件
    • 该参数在windows中无效,指定为-1即可
  • readfds:读集合一般都是需要进行检测的,这样才能知道哪些文件描述符可以接收数据
  • writefds:内核只检测这个集合中的文件描述符对应的写缓冲区,如果不使用该参数可以用NULL指定
  • exceptfds:内核只检测这个集合中的文件描述符是否有异常状态,如果不使用该参数可以用NULL指定
  • timeout:是表示检测文件描述符的时间,超过该时间函数返回。超长时长,用来解除select函数的阻塞
    • 等待固定时长:如果函数检测不到就绪的文件描述符,在指定时长过后就会解除堵塞
    • 如果设定为NULL:检测不到就绪的文件描述符就会一直阻塞
    • 不等待时长:检测不到就绪的文件描述符就会直接返回,不会阻塞

 select函数返回值:

  • >0:返回集合中就绪的文件描述符的个数
  • =0:超时,没有检测到就绪的文件描述符
  • <1:函数调用失败

fd_set类型:

fd_set类型的数据拥有1024个字节,也就是128个比特位,这个可以把他想象成一个整型的数组,大小为32。 fd_set中存储了要委托内核检测读缓冲区的文件描述符集合。

  • 如果集合中的标志位为0表示不检测这个文件描述符状态
  • 如果集合中的标志位为1表示检测这个文件描述符状态

内核如何更新集合中的标志位 

  

  • 假设需要检测读集合是否有文件描述符触发
  • 传入内核中的集合在此之前做初始化之后再传入
  • 内存中的数据拷贝到内核中
  • 内核检测拷贝的数据,检测完后,把满足条件的文件描述符重新写入到该内存中(可以理解为内核需要更新fd_set中的数据)

  • 把文件描述符中fd3,fd5,fd6,fd8,fd9,fd10,fd11设置到fd_set文件描述符集合中
  • 再通过select函数将文件描述符集合传递给内核
  • 内核把传入的集合拷贝一份(数据拷贝的过程)
  • 内核基于拷贝出来的集合做线性检测
  • 内核通过拷贝的集合与文件描述符表做对比
  • 文件描述符表的每个文件描述符具有两个缓冲区:读和写的缓冲区
  • 检测读缓冲区是否有数据
  • 内核基于拷贝的该线性表把需要检测的文件描述符的读缓冲区检验一遍
  • 把满足条件的文件描述符再重新写入指定的内存中

写集合也是一样的道理

以上函数能够实现把文件描述符存储到fd_set这个集合中/把已经存储的文件描述符从集合中删除等对该表的一系列增删查改 

处理并发问题

处理流程的步骤: 

  1. 创建套接字
  2. 绑定本地IP端口
  3. 建立监听
  4. 对需要检测的文件描述符做初始化(前三步完成后拥有一个监听的文件描述符)
    1. 监听的文件描述符用于检测是否有客户端连接
    2. 若客户端有连接请求,文件描述符会把发送进来存储到用于监听的文件描述符的读缓冲区中
  5. 创建一个fd_set的读集合并初始化(把标记为初始化为0)
  6. 再通过fd_set把监听的文件描述符对应的标志位设置为1
  7. 调用select进行检测
    1. select调用一次只检测一次
    2. 需要多次检测需要写入到循环中
    3. 返回值为-1或者0,即可做异常处理
      1. >0:文件描述符如果是监听的描述符,大于0表示有新的客户端连接到达
        1. 调用accept与客户端建立连接(不会阻塞,内核已检测完并知道文件描述符中是有数据的)得到通信的文件描述符
        2. 把得到的文件描述符放入读集合中,如果不进行下一轮的检测,服务端则不知道客户端有新的数据到达
  8. 检测到通信的文件描述符,调用recv接收数据
    1. 返回值:
      1. <0:客户端断开连接,调用close关闭通信的套接字,紧接着调用fd_clr函数删除
      2. >0:接收到数据,调用send函数发送数据

http://www.ppmy.cn/embedded/137406.html

相关文章

使用YOLOv9进行图像与视频检测

大家好&#xff0c;YOLOv9 与其前身v8一样&#xff0c;专注于识别和精确定位图像和视频中的对象。本文将介绍如何使用YOLOv9进行图像与视频检测&#xff0c;自动驾驶汽车、安全系统和高级图像搜索等应用在很大程度上依赖于此功能&#xff0c;YOLOv9 引入了比 YOLOv8 更令人印象…

hbase集成phoenix

1.环境 环境准备 三台节点zookeeper三节点hadoop三节点hbase三节点 2.pheonix集成 官网下载地址&#xff0c;需挂梯子&#xff0c;使用官网推荐的对应hbase版本即可 https://phoenix.apache.org/download.html下载及解压 wget https://dlcdn.apache.org/phoenix/phoenix-…

npm list @types/node 命令用于列出当前项目中 @types/node 包及其依赖关系

文章目录 作用示例常用选项示例命令注意事项 1、实战举例**解决方法**1. **锁定唯一的 types/node 版本**2. **清理依赖并重新安装**3. **设置 tsconfig.json 的 types**4. **验证 Promise 类型支持** **总结** npm list types/node 命令用于列出当前项目中 types/node 包及其…

Typescript类型运算符、关键字以及内置高级类型

目录 类型运算符 |运算符 &运算符 类型关键字 Infer 示例 extends typeof keyof in 注意 内置高级类型 类型 PropertyKey ArrayBufferLike 对类型集合的操作 Exclude,> Extract,> 对类型的操作 NonNullable Readonly Required Partial Pick…

ONLYOFFICE8.2版本测评,团队协作的办公软件

文章目录 引言ONLYOFFICE产品简介功能与特点1. 实时协作2. 兼容性3. 模板库4. 评论和修订5. 安全性 体验与测评功能测试 邀请用户使用项目介绍结尾了解更多 引言 在数字化办公的浪潮中&#xff0c;效率和协作成为了工作的核心。ONLYOFFICE作为一个强大的办公套件&#xff0c;正…

【Unity/GameFramework】Start Force ——配置和表加载

文章目录 前言寻找流程具体加载配置加载&#xff1a;获取路径&#xff1a;添加到标志数组&#xff1a;进行实际加载&#xff1a; 数据表加载&#xff1a;获取路径&#xff1a;添加到标志数组&#xff1a;进行实际加载&#xff1a; 语言加载&#xff1a;字体加载&#xff1a; 前…

java操作ES(一)RestHighLevelClient(2)集成与demo

一、集成方法 1、pom依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.x.x</version> <!-- 请使用与你的Elasticsearch版本相匹配的版…

打响反对人工智能的第一枪

序言&#xff1a;人工智能的讨论不能只有一片叫好的声音&#xff0c;一味的追捧反而可能隐藏巨大的危机。因此&#xff0c;必须有反对的声音&#xff0c;且越强烈越能激发深入思考。本篇文章的作者就以犀利的视角&#xff0c;漂亮地打响了反对人工智能应用的第一枪。 我以前一…