I/O多路转接之select

news2024/11/16 7:26:21

初识select

系统提供select函数来实现多路复用输入/输出模型:

  • select系统调用是用来让我们的程序监视多个文件描述符的状态变化的;
  • 程序会停在select这里等待,直到被监视的文件描述符有一个或多个发生了状态改变;

在这里插入图片描述

文章目录

  • 初识select
  • 一:Select函数原型
    • 参数解释:
    • 参数timeout的设置:
    • fd_set类型解析
    • 函数的返回值
  • 二:理解Select的执行过程
  • 三:Select的特点
  • 四:Select的简单示例

一:Select函数原型

int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

参数解释:

  • 参数nfds是需要监视的最大的文件描述符值+1;
  • rdset,wrset,exset分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集 合及异常文件描述符的集合;
  • 参数timeout为结构timeval,用来设置select()的等待时间。

参数timeout的设置:

  • NULL:则表示select()没有timeout,select将一直被阻塞,直到某个文件描述符上发生了事件;
  • 0:仅检测描述符集合的状态,然后立即返回,并不等待外部事件的发生。
  • 特定的时间值:如果在指定的时间段里没有事件发生,select将超时返回。

fd_set类型解析

在使用select函数时,就免不了用到fd_set结构体。那fd_set就是怎么样的?
下面我们先看在man手册中关于select:
在这里插入图片描述
那么fd_set究竟是什么?

typedef long int __fd_mask;


/* It's easier to assume 8-bit bytes than to get CHAR_BIT. */
#define __NFDBITS (8 * (int) sizeof (__fd_mask))
#define __FDELT(d) ((d) / __NFDBITS)
#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS))

/* fd_set for select and pselect. */
typedef struct
  {
    /* XPG4.2 requires this member name. Otherwise avoid the name
       from 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;

/* Maximum number of file descriptors in `fd_set'. */
#define FD_SETSIZE __FD_SETSIZE   //__FD_SETSIZE等于1024

/* Access macros for `fd_set'.  */
#define FD_SET(fd, fdsetp)      __FD_SET (fd, fdsetp)
#define FD_CLR(fd, fdsetp)      __FD_CLR (fd, fdsetp)
#define FD_ISSET(fd, fdsetp)    __FD_ISSET (fd, fdsetp)
#define FD_ZERO(fdsetp)         __FD_ZERO (fdsetp)

根据分析,我么可以把这个结构理解为一个整数数组,更严格的说, 是一个 “位图”。使用位图中对应的位来表示要监视的文件描述符。
💡💡💡并且还提供了一组操作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的全部位

函数的返回值

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

其中,错误值可能为:

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

二:理解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位置为1) 。
(3)若再加入fd=2,fd=1,则set变为0001,0011 。
(4)执行select(6,&set,0,0,0)阻塞等待 。
(5)若fd=1,fd=2上都发生可读事件,则select返回,此时set变为0000,0011。注意:没有事件发生的fd=5被清空。

三:Select的特点

  1. 可监控的文件描述符个数取决与sizeof(fd_set)的值。我这边服务器上sizeof(fd_set)=512,每bit表示一个文件描述符,则我服务器上支持的最大文件描述符是512*8=4096。
  2. 将fd加入select监控集的同时,还要再使用一个数据结构array保存放到select监控集中的fd。

这里我们思考为什么需要额外的数据结构array保存放到select监控集中的fd?

  • 一是用于再select 返回后,array作为源数据和fd_set进行FD_ISSET判断。
  • 二是select返回后会把以前加入的但并无事件发生的fd清空,则每次开始select前都要重新从array取得
    fd逐一加入(FD_ZERO最先),扫描array的同时取得fd最大值maxfd,用于select的第一个参数。

也正是因为以上两点,Select也有不得不说的缺点!!!

  • 每次调用select, 都需要手动设置fd集合, 从接口使用角度来说也非常不便。
  • 每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大。
  • 同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大。
  • select支持的文件描述符数量太小。

四:Select的简单示例

只检测标准输入:

#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>
int main() {
	fd_set read_fds;
	FD_ZERO(&read_fds);
	FD_SET(0, &read_fds);
	for (;;) {
		printf("> ");
		fflush(stdout);
		int ret = select(1, &read_fds, NULL, NULL, NULL);
		if (ret < 0) {
			perror("select");
			continue;
		}
		if (FD_ISSET(0, &read_fds)) {
			char buf[1024] = { 0 };
			read(0, buf, sizeof(buf) - 1);
			printf("input: %s", buf);
		}
		else {
			printf("error! invaild fd\n");
			continue;
		}
		FD_ZERO(&read_fds);
		FD_SET(0, &read_fds);
	}
	return 0;
}
 

说明:当只检测文件描述符0(标准输入)时,因为输入条件只有在你有输入信息的时候,才成立,所以如果
一直不输入,就会产生超时信息。

select示例代码

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

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

相关文章

Goby 漏洞发布|Avaya Aura Device Services r软件 PhoneBackup 任意文件上传漏洞

漏洞名称&#xff1a;Avaya Aura Device Services r软件 PhoneBackup 任意文件上传漏洞 English Name&#xff1a;Avaya Aura Device Services PhoneBackup File Upload Vulnerability CVSS core: 9.0 影响资产数&#xff1a;565 漏洞描述&#xff1a; Avaya Aura Device …

【linux 新机配置】

1&#xff0c;安装 node https://juejin.cn/post/7102790458132135944 2 linux 安装 Yarn https://juejin.cn/post/7102793669425496077 3 安装Nginx 安装 dnf install nginx 启动 systemctl start nginx systemctl status nginx systemctl enable nginx 配置&#xff0…

python机器人编程——差速AGV机器、基于视觉和预测控制的循迹、自动行驶(下篇)

目录 一、前言二、基于轨迹与路面重心偏离度误差的预测自动差速小车循迹控制策略三、轨迹图像的处理要点四、本篇部分核心控制策略python代码&#xff1a;五、结论 一、前言 基于最近的测试&#xff0c;得到了一种粗略控制的算法&#xff0c;其控制效果适合单线路和急转弯的情…

LLM探索:GPT类模型的几个常用参数 Top-k, Top-p, Temperature

Top-k抽样模型从最可能的"k"个选项中随机选择一个如果k10&#xff0c;模型将从最可能的10个单词中选择一个Top-p抽样模型从累计概率大于或等于“p”的最小集合中随机选择一个如果p0.9&#xff0c;选择的单词集将是概率累计到0.9的那部分Temperature控制生成文本随机性…

对比之前的组件优化说明React.memo的作用

我们之前写的react PureComponent讲述了 PureComponent 组件优化特性的强大功能 还有就是 shouldComponentUpdate 生命周期的一个解决方案 那么呢 今天我们要说另一个 也是类似于组件性能优化的新特性 打开我们的react项目 在src下的components创建一个组件 例如 我这里叫 dom…

【C++】-8.2- string〔string类模拟实现〕

文章目录 //模拟实现string类&#xff0c;并完成测试• string类的基本结构• Destructor• Construct〔构造函数〕‹ 无参构造 ›‹ 单参数构造 ›‹ 全缺省参数构造 › 〔拷贝构造〕 • operator 赋值重载• Element access&#xff08;operator[]&#xff09;补充&#xff1…

Android强大的原生调试工具adb的常用命令

文章目录 ADB简介常用命令列出链接的设备进入设备的shell环境设备日志安装应用程序卸载应用程序将本地文件复制到调试设备上将设备上的文件拉取到本地启动程序强制停止程序运行截图屏幕录制列出调试设备所有的应用的报名 结语 ADB简介 ADB&#xff08;Android Debug Bridge&am…

BioXFinder生物数据库

BioXFinder是目前国内第一个也是国内唯一一个生物信息数据库&#xff0c;由享融智云公司精心研发&#xff0c;主要针对生物科研工作者的综合性生物数据检索及分析平台&#xff0c;汇集了核酸、蛋白、蛋白结构、代谢通路和信号通路信息&#xff0c;解决海外数据访问难、访问慢的…

Adobe Creative Cloud 摄影计划 - 当图像与想象力相遇。 PS+LRc套餐 国际版 1年订阅/398

这里重点介绍国际版摄影计划套餐详情&#xff1a; 国际版包括&#xff1a;Photoshop、Lightroom Classic、Photoshop Express、Lightroom Mobile、Lightroom、云服务。中国版包括&#xff1a;Photoshop、Lightroom Classic、Photoshop Express、Lightroom Mobile 桌面应用程序…

SpringBoot集成Kafka的简单实现案列

1&#xff0c;首先搭建一个Springboot项目准备一个测试服务器 2&#xff0c;引入pom <dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId></dependency>他其中包括一些其他的包如果有冲突可…

有哪些值得注意的隔断小技巧可以让酒店更美观实用

以下是一些可以使酒店隔断更美观实用的小技巧&#xff1a; 1. 选择透明或半透明材料&#xff1a;使用透明或半透明的材料&#xff0c;如玻璃、亚克力或薄钢板&#xff0c;可以增加空间的亮度和通透感。 2. 考虑隔断的尺寸和布局&#xff1a;确保隔断的尺寸和布局适应空间大小和…

AI血洗时尚圈!就连这些线上店家都开始用AI生成爆款商品了

量子位 | 公众号 QbitAI 家人们谁懂啊&#xff0c;刷屏的《哈利波特》AI时装秀&#xff0c;看几次都不够&#xff01; 这些时装造型火遍全网&#xff0c;视频播放量破千万&#xff0c;还只是技术给时尚圈带来的一点小小震撼。 现在&#xff0c;用AI辅助设计服装、食品包装、装…

Elasticsearch初探

ElasticSearch Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。 Elasticsearch结合Kibana、Logstash、Beats&#xff0c;也就是elastic stack(ELK)。被广泛应用在日志分析、实时监控&#xff08;CPU、Memory、Program&#xff09;等领域。 elasticsearch是…

【​区块链】相关专业名词术语

区块链 区块链是一个共享数据库&#xff0c;存储于其中的数据或信息&#xff0c;具有不可伪造、全程留痕、可以追溯、公开透明和集体维护等特征。可以把区块链理解为一个共享的、不可更改的电子账本&#xff0c;能够在网络中记录交易和跟踪资产。这里的资产可以是有形的&#…

mount.nfs: access denied by server while mounting

问题及截图&#xff1f; 客户端挂载nfs共享目录的时候提示如下&#xff1a; mount.nfs: access denied by server while mounting 192.168.44.10:/xxx 问题原因有两方面&#xff1a; 一&#xff1a;权限问题 服务器端的共享目录没有给足相应的权限导致&#xff0c;导致挂载失…

如何做mysql调优?绝命7招,让慢SQL调优100倍

前言&#xff1a; 在40岁老架构师尼恩的读者社区&#xff08;50&#xff09;中&#xff0c;很多小伙伴拿不到offer&#xff0c;或者拿不到好的offer。 尼恩经常给大家 优化项目&#xff0c;优化简历&#xff0c;挖掘技术亮点。在指导简历的过程中&#xff0c; Java 调优是一项…

HiveSQL在使用聚合类函数的时候性能分析和优化详解

文章目录 概述1.仅在Reduce阶段聚合的SQL执行逻辑2.在map和reduce阶段聚合的SQL逻辑 概述 前文我们写过简单SQL的性能分析和解读&#xff0c;简单SQL被归类为select-from-where型SQL语句&#xff0c;其主要特点是只有map阶段的数据处理&#xff0c;相当于直接从hive中取数出来…

C++模板和模板的特化,模板的扩展和智能指针------(14)

模板 概念 模板的作用是实现类型通用&#xff0c;降低代码的冗余度 模板可以为一种算法定义不同类型的版本 实现机制&#xff1a; 复制代码使用类型参数突破类型的限制&#xff0c;丧失一定的类型安全 模板需要实例化才能使用&#xff0c;实例化由编译器完成 模板的分类 …

对比学习初认识

这篇文章我们通过SimCLR模型来对对比学习技术有一个认知。 1.什么是对比学习系统 根据上面这个图&#xff0c;来介绍下怎么做一个抽象的对比学习系统。以一个图像为例子&#xff0c;通过自动构造正例或负例&#xff0c;形成图片的两个view&#xff0c;通过encoder把它们编码&a…

第十届中医药健康文化节:御医传人龚洪海强调心血管疾病中医治疗"治未病"的重要性

在第十届中医药健康文化节上&#xff0c;备受瞩目的中医世家龚洪海医生强调了中医对心血管疾病的有效治疗&#xff0c;并提出了更为重要的概念——"治未病"。这一观念的传达不仅对预防常见病和多发病有益&#xff0c;同时在重大疑难疾病的防治中发挥着关键作用&#…