linux系统中select函数的用法实现

前言:

select机制已经被很多人都讲解过,select使用起来也不是特别难,为什么还要花时间再次讲解select机制?

在回答这个问题之前,我们先问一下自己,是否有足够的信心保证在使用select编程时不出错,select机制虽然看起来简单,实际在使用时有很多坑,当我们没有从原理上真正理解select机制时,我们随时会掉入这些坑,所以这篇文章我尽量把select实现原理和细节交待清楚。

1.select简介

select机制是一种I/O多路复用技术,它可以同时监视多个文件描述符,当某个文件描述符就绪(一般是读写就绪)时,就会通知程序进行相应的操作。

select机制的优点是可以同时处理多个连接,避免了大量的线程或进程切换,提高了系统的并发性能。

在Linux系统中,select机制可以通过select函数来实现。select函数的参数包括需要监视的文件描述符集合、超时时间等。当select函数返回时,程序可以通过遍历文件描述符集合来确定哪些文件描述符已经就绪,然后进行相应的操作。

2.select实现原理

(老规矩先上原理图)

这张原理图把select主要活动轨迹都进行了描述。

  • select核心实现原理是位图,select总共有三种位图,分别为读,写,异常位图,用户程序预先将socket文件描述符注册至读,写,异常位图,然后通过select系统调用轮询位图中的socket的读,写,异常事件。

  • select底层通过轮询方式获取读,写,异常位图中注册的socket文件事件,如果检测到有socket文件处于就绪状态,则会将socket对应的事件设置到输出位图,等所有位图中的socket都被轮询完,会统一将输出位图通过copy_to_user函数复制到输入位图,并且覆盖掉输入位图注册信息(也就是用户初始化的位图被内核修改)

  • select轮询完所有位图,如果未检测到任何socket文件处于就绪状态,根据超时时间确定是否返回或者阻塞进程。

  • socket检测到读,写,异常事件后,会通过注册到socket等待队列的回调函数poll_wake将进程唤醒,唤醒的进程将再次轮询所有位图。

  • select返回时会将剩余的超时时间通过copy_to_user覆盖原来的超时时间。

3.select位图

3.1 select位图定义

#define __FD_SETSIZE        1024

#define __NFDBITS   (8 * (int) sizeof (long int))

typedef struct

{

    long int fds_bits[__FD_SETSIZE / __NFDBITS];

} fd_set;

  • select位图为1024比特位图,通过整型数组模拟而成。

  • select位图每个比特对应一个文件描述符数值。

  • select位图数组长度为16,每个数组元素为8字节,一个字节为8比特,位图大小=16 * 8 * 8 = 1024比特。

3.2 常用位图操作函数:

void FD_CLR(int fd, fd_set *set); //设置fd对应位图位置为0。

int FD_ISSET(int fd, fd_set *set); //判断fd对应位图位置是否为1。

void FD_SET(int fd, fd_set *set); //设置fd对应位图位置为1。

void FD_ZERO(fd_set *set);//整个位图清零。

4.select编程

4.1 select函数原型

int select(int nfds, fd_set *readfds, fd_set *writefds,          

          fd_set *exceptfds, struct timeval *timeout);

功能:select函数是Linux系统中的一种I/O多路复用机制,它可以同时监视多个文件描述符。

参数:

nfds:最大文件描述符+1。

readfds:读文件描述符集合,可设置为NULL。

writefds:写文件描述符集合,可设置为NULL。

exceptfds:异常文件描述符集合,可设置为NULL。

timeout:超时时间,设置为NULL为阻塞模式,

struct timeval {

    __kernel_time_t     tv_sec;     //秒,超时多少秒。

    __kernel_suseconds_t    tv_usec;    //微妙,超时多少微秒。

};

返回值:

成功:返回检测到的文件描述符数量。

失败:返回-1,设置errno。

超时:返回0。

4.2 select使用示例:

fd_set rfds;

FD_ZERO(&rfds_storage); //清空位图

FD_SET(sock_fd, &rfds_storage); //设置位图

struct  timeval tv = {.tv_sec = 5, .tv_usec = 0}; //设置超时时间

ret = select(max_fd + 1, &rfds, NULL, NULL, &tv);

4.3 select编程模型

5.select常见问题?

问题1:select函数最大文件描述(maxfd)有什么作用?

select使用1024比特位图监测最多1024个文件描述符,然而实际的情况很少会到达1024文件描述符上限,使用maxfd可以避免每次都轮询1024个文件描述符,从而提高轮询效率。

maxfd通常设置为已打开最大文件描述符+1,目的是为了保证位图中每个文件描述符都被轮询到。

问题2:select优缺点有哪些?

优点:

  • select支持多种文件描述符类型,包括socket、标准输入输出、管道、FIFO等。

  • select是跨平台的,可以在多种操作系统上使用。

缺点:

  • select的效率不高,每次调用select都需要将所有的文件描述符从用户态复制到内核态,这个过程比较耗时。

  • select返回后需要遍历所有的文件描述符,找到就绪的文件描述符,这个过程也比较耗时。

  • select支持的文件描述符数量有限,通常是1024个。 

问题3:select为什么会有1024文件描述符限制?

  • 进程默认打开最大文件描述符为1024(次要原因)。

  • select采用轮询的方式获取读,写,异常事件,如果需要轮询的文件描述符比较多的话,select执行效率会非常低(个人观点)。

  • select是通过一个整型数组来模拟位图,整型数组长度和元素大小已经固定,只能模拟出1024比特位图,使用select如果超过1024文件描述符的限制,可能会导致内存越界和其他未知问题(真正原因)。

问题4:select有哪些设计缺陷?

  • select最大文件描述符为1024,所以无法满足高并发应用场景,高并发场景请使用epoll机制。

  • select采用轮询的方式获取读,写,异常事件,轮询的方式效率低,不管文件事件是否就绪,都需要去做检测。

  • select位图设置和获取采用覆盖方式,用户输入的读,写,异常位图会被内核修改,编程非常容易出错,可参考select实现原理图分析,所以每次调用select之前都要重新设置位图。

  • select执行完后会返回剩余超时时间,剩余超时时间会覆盖原来的超时时间,导致超时机制异常。可参考select实现原理图分析,所以每次调用select之前都要重新设置超时时间。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数字图像处理】均值滤波与中值滤波

在数字图像处理中,均值滤波和中值滤波是常见的空间域处理方法,可以用于过滤图像中的噪声。本文主要介绍数字图像均值滤波与中值滤波的基本原理,并记录在紫光同创 PGL22G FPGA 平台的布署与实现过程。 目录 1. 均值滤波与中值滤波 2. FPGA 布署与实现 2.1 功能与指标定义

C语言 - 基础

C 语言 1. Hello World #include <stdio.h>int main(int argc, const char *argv[]) {printf("hello world\n");return 0; }注意: 所有的标点符号必须在英文状态下输入单词不要写错注意空格 创建 C语言 程序步骤&#xff1a; 1、创建一个文档&#xff0c;以…

MYSQL 及 SQL 注入

文章目录 前言什么是sql注入防止SQL注入Like语句中的注入后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;Mysql &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握&#xff0c;正在不断努力填补技术短板。(如果出现…

「最优化基础知识2」一维搜索,以及python代码

最优化基础知识&#xff08;2&#xff09; 无约束优化问题&#xff0c;一维搜索 一、一维搜索 一维搜索的意思是在一个方向上找到最小点。 用数学语言描述&#xff0c;X*Xk tPk&#xff0c;从Xk沿着Pk方向行走t到达最小点X*。 1、收敛速度&#xff1a; 线性收敛&#xff1…

mac测试远程端口是否可连接

打开命令行工具&#xff0c;使用命令nc -z ip port即可 &#xff0c;如果成功&#xff0c;则会返回如下信息&#xff1a; 。

FANUC机器人系统配置相关--系统变量介绍

FANUC机器人系统配置相关–系统变量介绍 系统配置页相关变量 1- 停电处理$SEMIPOWERFL = TRUE(有效)/FALSE(无效) 2- 停电处理中的I/O $PWF_IO = 1(不恢复)/2(仿真恢复)/3(解除仿真)/4(恢复所有) 3- 停电处理无效时自动执行的程序 $PWR_NORMAL = ‘’ 4- 停电处理有效时自动…

【21年扬大真题】编写程序,通过指针p的改变,实现一维数组的输入及逆序输出

【21年扬大真题】编写程序&#xff0c;通过指针p的改变&#xff0c;实现一维数组的输入及逆序输出 例如&#xff0c;输入为1,2,3,4,5,6,7&#xff1b; 输出为7,6,5,4,3,2,1 法一&#xff1a;不改变原数组&#xff0c;仅逆序打印输出 #define _CRT_SECURE_NO_WARNINGS #includ…

Linux下安装python3步骤:

1.下载Python3源码 你需要从Python官网下载Python3的源码包。本文以Python 3.9.9为例。你可以使用wget命令来下载源码包到你的Linux主目录中: wget https://www.python.org/ftp/python/3.9.9/Python-3.9.9.tgz2.编译和安装Python3 下载好源码包后&#xff0c;你需要解压它&…

【外贸干货】领英客户开发与营销的六个策略方向

领英(LinkedIn)已经成为外贸营销人员&#xff0c;尤其是B2B外贸营销人员&#xff0c;一个重要且有效的社交媒体平台。 相比于其他社交媒体平台&#xff0c;领英(LinkedIn)在增加流量、产生高质量的潜在客户和建立思想领导力方面有着独有的优势。 因为领英(LinkedIn)不仅仅是获…

idea自动切换输入法Smart Input

idea搜索后下载 红色表示中文输入法 再ideavim场景下会自动切换成英文非常好用强烈推荐下载一个

英特尔和 ARM 将合作开发移动芯片技术,如何看待双方合作?

英特尔和 ARM 将合作开发移动芯片技术&#xff0c;如何看待双方合作&#xff1f; 最近市场传出Arm要自产芯片&#xff0c;供智能手机与笔电等使用后&#xff0c;外媒指Arm自产芯片将由英特尔晶圆代工部门打造&#xff0c;变成英特尔晶圆代工客户。将采用英特尔18A工艺&#xff…

电子学会C/C++编程等级考试2022年03月(二级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:温度统计 现有一段时间的温度数据,请统计指定温度出现的次数。 时间限制:1000 内存限制:65536输入 第一行一个整数n,表示温度数据的个数。(0 < n ≤ 200) 第二行n个整数,以空格分隔,每个整数表示一个温度,温度的范围大…

我好像发现了车载测试面试成功的秘籍

在汽车行业中&#xff0c;车载测试工程师扮演着至关重要的角色。他们负责确保汽车的各种系统和功能在各种条件下都能正常运行&#xff0c;以确保车辆的安全性、可靠性和性能。如果你梦想成为一名车载测试工程师&#xff0c;那么你可能需要准备好回答一些关键的面试问题。在本文…

华大基因基因检测产品发布,助力早发冠心病风险评估

冠状动脉性心脏病&#xff0c;简称冠心病。冠心病作为导致猝死的常见原因之一&#xff0c;近年来备受关注。早发冠心病是指冠心病发病年龄男性≤55岁&#xff0c;女性≤60岁。早发冠心病是一种发病时心肌损伤严重的冠心病&#xff0c;由于心肌缺血&#xff0c;还有可能会导致急…

使用 PyODPS 采集神策事件数据

文章目录 一、前言二、数据采集、处理和入库2.1 获取神策 token2.2 请求神策数据2.3 数据处理-面向数组2.4 测试阿里云 DataFrame 入库2.5 调度设计与配置2.6 项目代码整合 三、小结四、花絮-避坑指南第一坑&#xff1a;阿里云仅深圳节点支持神策数据第二坑&#xff1a;神策 To…

Vue与UserEcharts、DataV的协同

文章目录 引言一、Vue.js简介二、ECharts和UserEcharts1.ECharts简介2.UserEcharts&#xff1a;Vue和ECharts的结合 三、DataV简介四、Vue与DataV的结合1.DataV的Vue插件2.Vue和DataV的数据交互 结论我是将军&#xff0c;我一直都在&#xff0c;。&#xff01; 引言 接着上一篇…

代码随想录算法训练营第五十八天|739. 每日温度、496. 下一个更大元素 I

第十章 单调栈part01 739. 每日温度 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用…

LLM之Agent(一):使用GPT-4开启AutoGPT Agent自动化任务完整指南

在ChatGPT引领的大模型时代&#xff0c;要想让大模型按照用户的指令执行&#xff0c;Prompt设计是一门艺术&#xff0c;由此还催生了一个职业”Prompt工程师“。其实&#xff0c;并不是所有人都可以设计出好的Prompt&#xff0c;甚至同样的Prompt应用在不同的大模型上表现的结果…

小程序中的大道理--综述

前言 以下将用一个小程序来探讨一些大道理, 这些大道理包括可扩展性, 抽象与封装, 可维护性, 健壮性, 团队合作, 工具的利用, 可测试性, 自顶向下, 分而治之, 分层, 可读性, 模块化, 松耦合, MVC, 领域模型, 甚至对称性, 香农的信息论等等. 为什么不用大程序来说大道理呢? …

flink源码分析之功能组件(二)-kubeclient

简介 本系列是flink源码分析的第二个系列,上一个《flink源码分析之集群与资源》分析集群与资源,本系列分析功能组件,kubeclient,rpc,心跳,高可用,slotpool,rest,metrics,future。其中kubeclient上一个系列介绍过,为了系列完整性,这里“copy”一下。 kubeclient组件…