[Linux][网络][高级IO][IO多路转接][select][poll]详细讲解

目录

  • 1.IO多路转接之select
    • 1.初识select
    • 2.select()
    • 3.关于fd_set结构
    • 4.关于timeval结构
    • 5.理解select执行过程
    • 6.select就绪条件
    • 7.select特点
    • 8.select优点(任何一个多路转接方案,都具备)
    • 9.select缺点
    • 10.select的一般编写代码的模式
    • 11.思考 && 问题
  • 2.IO多路转接之poll
    • 1.poll()
    • 2.pollfd结构
    • 3.poll就绪条件
    • 4.poll的优点
    • 5.poll缺点


1.IO多路转接之select

1.初识select

  • select系统调用是用来让程序监视多个文件描述符的状态变化的
  • 程序会停在select这里等待,直到被监视的文件描述符有一个或多个发生了状态改变
  • 总结:
    • 帮用户进行一次等待多个文件描述符
    • 当哪些文件描述符就绪了,select就要通知用户,对应就绪的sock有哪些,然后用户再调用recv/read等接口进行数据读取

2.select()

  • 原型:int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

  • 参数:

    • nfds:要监视的最大的文件描述符+1
    • readfds,writefds,exceptfds:均为输入输出型参数,分别对应于需要检测的可读/可写/异常文件描述符的集合
      • 输入时:用户告诉内核,你要帮我关心哪些fd的哪一种事件
        • bit位的位置表示文件描述符值,bit位的内容表示是否关心(1/0)
      • 输出时:内核告诉用户,我所关心的fd中,哪些fd上的哪类事件已经就绪了
        • bit位的位置表示文件描述符值,bit位的内容表示是否就绪(1/0)
      • 用户和内核都会修改同一个位图结构,这些参数用一次之后,一定要进行重新设定
    • timeout:用来设置select()的等待时间,其取值
      • nullptr:阻塞等待
      • 0:非阻塞等待
      • 特定时间值:如果在指定的时间段里没有事件发生,select()将超时返回
      • 如果等待时间内,有fd就绪,会怎样呢?
        • 呈现输出型,存放距离下一次timeout剩余多长时间
  • 返回值

    • 执行成功则返回文件描述词状态已改变的个数
    • 如果返回0代表在描述词状态改变前已超过timeout时间,没有返回
    • 当有错误发生时则返回-1,错误原因存于errno,此时参数readfds,writefds, exceptfds和timeout的值变成不可预测
  • 错误码可能值

    • EBADF:文件描述词为无效的或该文件已关闭
    • EINTR:此调用被信号所中断
    • EINVAL:参数n为负值
    • ENOMEM:核心内存不足

3.关于fd_set结构

/* The fd_set member is required to be an array of longs.  */
typedef long int __fd_mask;typedef struct{/* XPG4.2 requires this member name.  Otherwise avoid the namefrom the global namespace.  */
#ifdef __USE_XOPEN__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->fds_bits)
#else__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->__fds_bits)
#endif} fd_set;
  • 其实这个结构就是一个整数数组,更严格的说,是一个**“位图”,使用位图中对应的bit位来表示要监视的文件描述符**
  • 提供了一组操作fd_set的接口, 来比较方便的操作位图
    void FD_CLR(int fd, fd_set *set); // 用来清除描述词组set中相关fd的bit位
    int FD_ISSET(int fd, fd_set *set); // 用来测试描述词组set中相关fd的but位是否为真
    void FD_SET(int fd, fd_set *set); // 用来设置描述词组set中相关fd的bit位
    void FD_ZERO(fd_set *set); // 用来清除描述词组set的全部bit位
    

4.关于timeval结构

  • timeval结构用于描述一段时间长度,如果在这个时间内,需要监视的文件描述符没有事件发生则函数返回,返回值为0
    struct timeval
    {__time_t tv_sec;    /* Seconds. */__suseconds_t tv_usec;  /* Microseconds. */
    };
    

5.理解select执行过程

  • 理解select模型的关键在于理解fd_set,为说明方便,取fd_set长度为1字节
  • fd_set中的每一bit可以对应一个文件描述符fd,则1字节长的fd_set最大可以对应8个fd.
    1. 执行fd_set set; FD_ZERO(&set);
      • 则set用位表示是0000,0000
    2. 若fd=5,执行FD_SET(fd, &set);
      • set变为0001,0000(第5个bit位置为1)
    3. 若再加入fd=2,fd=1
      • 则set变为0001,0011
    4. 执行**select(6, &set, nullptr, nullptr, nullptr)**阻塞等待
    5. 若fd=1,fd=2上都发生可读事件,则select返回
      • 此时set变为0000,0011
      • **注意:**没有事件发生的fd=5被清空

6.select就绪条件

  • 读就绪
    • socket内核中,接收缓冲区中的字节数,大于等于低水位标记SO_RCVLOWAT
      • 此时可以无阻塞的读该文件描述符,并且返回值大于0
    • socket TCP通信中,对端关闭连接,此时对该socket读,则返回0
    • 监听的socket上有新的连接请求
    • socket上有未处理的错误
  • 写就绪
    • socket内核中,发送缓冲区中的可用字节数(发送缓冲区的空闲位置大小),大于等于低水位标记SO_SNDLOWAT
      • 此时可以无阻塞的写,并且返回值大于0
    • socket的写操作被关闭(close或者shutdown),对一个写操作被关闭的socket进行写操作,会触发SIGPIPE信号
    • socket使用非阻塞connect连接成功或失败之后
    • socket上有未读取的错误

7.select特点

  • 可监控的文件描述符个数取决与sizeof(fd_set)的值
    • 我虚拟机上sizeof(fd_set)=128,每bit表示一个文件描述符,则支持的最大文件描述符是128*8=1024
  • 将fd加入select监控集的同时,还要再使用一个第三方数组用来保存所有的合法fd
    1. 用于在select返回后,array作为源数据和fd_set进行FD_ISSET判断
    2. select返回后会把以前加入的但并无事件发生的fd清空,则每次开始select前都要重新从array取得fd并逐一加入(FD_ZERO最先),扫描array的同时取得fd最大值maxfd,用于select的第一个参数

8.select优点(任何一个多路转接方案,都具备)

  • 效率高
  • 应用场景:有大量的链接,但是只有少量是活跃的,节省资源

9.select缺点

  • 为了维护第三方数组,select服务器会充满大量遍历,OS底层帮用户关心fd的时候,也要遍历
  • 每一次都要对select输出参数进行重新设定
  • 能够同时管理的fd的个数是有上限的 <-- fd_set大小是被固定了的
  • 因为几乎每一个参数都是输入输出型的,select一定会频繁地进行用户到内核,内核到用户的参数数据拷贝
  • 编码比较复杂

10.select的一般编写代码的模式

while(true)
{// 1.遍历数组,更新出最大值// 2.遍历数组,添加所有需要关心的fd到fd_set位图中// 3.调用select进行事件检测// 4.遍历数组,找到就绪的事件,根据就绪的事件,完成对应的动作// a.Accepter b.recver
}

11.思考 && 问题

  • 如何看待_listensock?
    • 获取新连接,依然把它看成IO,如果没有连接到来,就阻塞
  • 参数影响编码模式
    1. nfds:随着获取的sock越来越多,添加到select的sock越来越多,注定了nfds每一次都可能要变化,需要对它动态计算
    2. readfds/writefds/exceptfds:都是输入输出型参数,输入输出不一定是一样的,所以注定每次都要对其进行重新添加
    3. timeout:输入输出型参数,每一次都要进行重置,前提是需要的话
      • 1,2 --> 注定必须自己将合法的fd单独全部保存起来,以支持:a.更新最大fd b.更新位图结构

2.IO多路转接之poll

1.poll()

  • 原型:int poll(struct pollfd *fds, nfds_t nfds, int timeout);
  • 参数:
    • fds:是一个poll()监听的结构的数组,每一个元素中,包含了三部分内容:文件描述符,监听的事件集合,返回的事件集合
    • nfds:表示fds数组的长度
    • **timeout:
      • 表示poll()的超时时间,单位是毫秒
      • 设置为0,表示非阻塞等待
      • 设置为-1,表示阻塞等待
  • 返回值
    • 执行成功则返回文件描述词状态已改变的个数
    • 如果返回0代表在描述词状态改变前已超过timeout时间,没有返回
    • 当有错误发生时则返回-1,错误原因存于errno

2.pollfd结构

struct pollfd
{int fd;        /* File descriptor to poll.  */short int events;  /* Types of events poller cares about.  */short int revents; /* Types of events that actually occurred. */
};
  • events****和revents的取值
事件描述是否可作为输入是否可作为输出
POLLIN数据(包括普通数据和优先数据)可读
POLLRDNORM普通数据可读
POLLRDBAND优先级带数据可读(Linux不支持)
POLLPRI高优先级数据可读,比如TCP带外数据
POLLOUT数据(包括普通数据和优先数据)可写
POLLWRNORM普通数据可写
POLLRDHUPTCP****连接被对方关闭,或者对方关闭了写操作,它由GNU引入
POLLERR错误
POLLHUP挂起,比如管道的写端被关闭后,读端描述符上将收到POLLHUP事件
POLLNVAL文件描述符没有打开

3.poll就绪条件

  • 同select

4.poll的优点

  • 效率高
  • 应用场景:有大量的链接,但是只有少量是活跃的,节省资源
  • 输入输出参数是分离的,不需要进行大量的重置
  • 没有可以管理的fd最大数量限制

5.poll缺点

  • poll依旧需要不少的遍历,在用户层检测事件就绪、内核检测fd就绪,都需要大量遍历
    • 且用户还是需要自己维护第三方数组
  • poll需要内核到用户的拷贝 – 少不了的
  • poll的代码结构依然比较复杂 – 比select容易

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/12441.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【PB案例学习笔记】-02 目录浏览器

写在前面 这是PB案例学习笔记系列文章的第二篇&#xff0c;该系列文章适合具有一定PB基础的读者&#xff0c; 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上…

基于Django实现的(bert)深度学习文本相似度检测系统设计

基于Django实现的&#xff08;bert&#xff09;深度学习文本相似度检测系统设计 开发语言:Python 数据库&#xff1a;MySQL所用到的知识&#xff1a;Django框架工具&#xff1a;pycharm、Navicat、Maven 系统功能实现 登录页面 注册页面&#xff1a;用户账号&#xff0c;密码…

05-14 周二 PyTorch动态量化和静态量化理解

05-14 周二 PyTorch动态量化和静态量化理解 时间版本修改人描述2024年5月14日10:44:30V0.1宋全恒新建文档2024年5月14日16:28:16V1.0宋全恒填充了PyTorch对于两种量化方式的内容 简介 Pytorch动态量化 设计神经网络时&#xff0c;可以进行许多权衡。在模型开发和训练期间&…

Dilworth定理:最少的下降序列个数就等于整个序列最长上升子序列的长度

概念如下&#xff1a; 狄尔沃斯定理_百度百科 (baidu.com) 本质就是找要求序列中最长的单调的子序列&#xff08;不一定连续&#xff09;的长度。 模板如下&#xff1a; 时间复杂度为O&#xff08;N^2&#xff09; #include<iostream>using namespace std;int dp[100…

RK3568平台开发系列讲解(SPI篇)SPI数据的传输

🚀返回专栏总目录 文章目录 一、数据结构1.1、spi_transfer 结构体1.2、spi_message二、数据发送程序分析沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 参考资料: spi_transferspi_message一、数据结构 spi 数据传输主要使用了 spi_message 和 spi_transfer 结构…

二叉树的前序遍历(leetcode)

144. 二叉树的前序遍历 - 力扣&#xff08;LeetCode&#xff09; 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 这道题的启发性真的很强 &#xff0c;这里必须传入i的指针进去&#xff0c;下一次栈帧i&#xff0c;但回到了上一层i又变回到了原来的i&#…

docker network ls(用于列出 Docker 主机上的所有网络)

docker network ls 是一个 Docker 命令&#xff0c;用于列出 Docker 主机上的所有网络。Docker 允许你创建自定义的网络&#xff0c;以便更好地控制容器之间的通信。 当你运行 docker network ls 命令时&#xff0c;你可能会看到如下类似的输出&#xff08;输出可能会根据你的…

每日一题12:Pandas:数据重塑-融合

一、每日一题 解答&#xff1a; import pandas as pddef meltTable(report: pd.DataFrame) -> pd.DataFrame:reshaped_report report.melt(id_varsproduct, var_namequarter, value_namesales)return reshaped_report 题源&#xff1a;Leetcode 二、总结 melt()函数是Pa…

Nginx生产环境最佳实践之配置灰度环境

你好呀&#xff0c;我是赵兴晨&#xff0c;文科程序员。 下面的内容可以说是干货满满建议先收藏再慢慢细品。 今天&#xff0c;我想与大家深入探讨一个我们日常工作中不可或缺的话题——灰度环境。你是否在工作中使用过灰度环境&#xff1f;如果是&#xff0c;你的使用体验如…

AI图像生成-基本步骤

模型板块 1、新建采样器&#xff1a;新建节点-》采样器-》K采样器 2、拖动模型节点后放开&#xff0c;选择checkpoint加载器&#xff08;简易&#xff09;&#xff0c;模型新建成功 提示词板块 1、拖动正面条件节点后放开&#xff0c;选择CLIP文本编码器&#xff0c;模型新建…

mysql 一次删除多个备份表

show tables时&#xff0c;发现备份的表有点多&#xff0c;想要一个sql就删除 总不能drop table xx ; 写多次吧。 方式一 1.生成删除某个数据库下所有的表SQL -- 查询构建批量删除表语句&#xff08;根据数据库名称&#xff09; select concat(drop table , TABLE_NAME, ;)…

代码随想录算法训练营第39天|● 62.不同路径 ● 63. 不同路径 II

62. 不同路径 递归栈很酷 但超时 class Solution:def uniquePaths(self, m: int, n: int) -> int:if m1 or n1:return 1return self.uniquePaths(m-1,n)self.uniquePaths(m,n-1) 逐行dp class Solution:def uniquePaths(self, m: int, n: int) -> int:dp[1]*nfor j in…

FSMC的NOR Flash/PSRAM 控制器功能介绍(STM32F4)

目录 概述 1 FSMC支持的类型 1.1 信号类型概述 1.2 FSMC的应用 2 外部存储器接口信号 2.1 I/O NOR Flash 2.2 PSRAM/SRAM 3 支持的存储器和事务 4 通用时序规则 5 NOR Flash/PSRAM 控制器异步事务 5.1 模式 1 - SRAM/PSRAM (CRAM) 5.2 模式 A - SRAM/PSRAM (CRAM…

Golang | Leetcode Golang题解之第90题子集II

题目&#xff1a; 题解&#xff1a; func subsetsWithDup(nums []int) (ans [][]int) {sort.Ints(nums)n : len(nums) outer:for mask : 0; mask < 1<<n; mask {t : []int{}for i, v : range nums {if mask>>i&1 > 0 {if i > 0 && mask>&…

[HUBUCTF 2022 新生赛]ezsql

测试无结果 扫描目录&#xff0c;得到源码 找到注入点 思路&#xff1a;更新资料的时候可以同时更新所有密码 我们需要知道密码的字段名 爆库 nicknameasdf&age111,description(select database())#&descriptionaaa&token31ad6e5a2534a91ed634aca0b27c14a9 爆表…

运维别卷系列 - 云原生监控平台 之 08.prometheus grafana 实践

文章目录 [toc]部署 Grafana准备配置文件grafana.iniprovisioning/datasources/prometheus.yamlprovisioning/dashboards/dashboards.yamlprovisioning/dashboards/views 创建 svc创建 deployment Grafana 是一个图形化界面&#xff0c;配置 Prometheus 作为数据源&#xff0c;…

网络库-POCO介绍

1.简介 POCO C Libraries 提供一套 C 的类库用以开发基于网络的可移植的应用程序&#xff0c;它提供了许多模块&#xff0c;包括网络编程、文件系统访问、线程和并发、数据库访问、XML处理、配置管理、日志记录等功能。Poco库的设计目标是易于使用、高度可定制和可扩展。 包含…

Postman的简介,安装,注册。

一、安装 1.Chrome应用商品搜索Postman安装。(翻墙) 2.客户端安装官网地址:https://www.postman.com/downloads/ 3.Postman的注册和登录。 4.Postman的界面介绍 Home主页 workspaces 工作空间 Collections 集合&#xff0c;项目集合。 Apis api文档 EnViromments …

Oracle如何加密解密sha256

在Oracle数据库中&#xff0c;您可以使用内建的加密函数或者通过PL/SQL扩展来实现SHA-256加密。但请注意&#xff0c;SHA-256是一个哈希算法&#xff0c;它主要用于生成数据的哈希值&#xff0c;而不是用于加密和解密数据。哈希算法是单向的&#xff0c;即它只能从原始数据生成…

基于MSWA相继加权平均的交通流量分配算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于MSWA相继加权平均的交通流量分配算法matlab仿真.如图所示交通网络中&#xff0c;包含6个节点、11各路段、9个OD对。经枚举可得每个OD对间存在3条无折返有效路…