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.mzph.cn/news/169193.shtml

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

相关文章

【Linux】常见指令及周边知识(一)

【Linux】常见指令及周边知识(一) 一、初始Linux操作系统1.Linux背景2.如何使用Linux 二、学习Linux之前的预备周边知识(重点):1.什么叫做文件?2. Linux下的路径分隔符3.在Linux中为什么会存在路径&#xf…

开发者的 Debian 12 KDE 配置优化指南

博客地址 开发者的 Debian 12 KDE 配置优化指南 0x00 简介 本文仅适用于配置 Debian 12 Bookworm 文中包含 KDE Plasma X11 桌面配置 文中使用 debianuser 代替用户名,执行命令或复制配置时请注意替换 文中涉及的带版本号的软件包/环境,版本号使用…

vue 富文本编辑器多图上传

首先我使用的富文本编辑器是vue-quill-editor 使用npm进行下载 npm install vue-quill-editor --save当然也可以按照官方的方法下载,到官方 因为我是在原有老项目上开发的使用的组件库是ant-design-vue 1x版,当然使用其他组件库也可以 然后还有重要的一…

interface previously declared 的bug问题

其实就是重复定义了,只需要加如下的代码即可: 其中把APB的部分改成自己的接口名字就好了。

JS手写instanceof(内含源码与详解)

前言 本文主要讲解JavaScript如何手写一个简易的instanceof,从而实现数据类型判断的作用.那么好,本文正式开始. instanceof作用 instanceOf的作用就是用来判断JavaScript中的数据类型是否是开发所输入的那种, 语法格式:obj instanceof objtype 左侧就是要判断的数据,而右侧就…

HCIP-九、路由控制

九、路由控制 实验拓扑实验需求及解法1.企业生产网运行 OSPF,完成以下需求:2.数据中心运行 ISIS3.路由引入4.路由策略5.策略路由6.ISP 过滤私网路由 实验拓扑 实验需求及解法 1.企业生产网运行 OSPF,完成以下需求: 1.1 OSPF 进程…

prometheus|云原生|grafana-9.4.3版本的主题更改

一, grafana-9.4.3版本的主题更改 grafana-9.4.3版本应该是目前比较高的版本了,但不知道是什么原因,grafana的主题界面并不多,只有暗色,亮色和系统色三种 配置管理----首选项里可以看到 亮色: 暗色&…

Nginx安装与配置、使用Nginx负载均衡及动静分离、后台服务部署、环境准备、系统拓扑图

目录 1. 系统拓扑图 2. 环境准备 3. 服务器安装 3.1 mysql,tomcat 3.2 Nginx的安装 4. 部署 4.1 后台服务部署 4.2 Nginx配置负载均衡及静态资源部署 1. 系统拓扑图 说明: 用户请求达到Nginx若请求资源为静态资源,则将请求转发至静态…

JVM 内存分析工具 MAT及实践

线程分析工具 MAT 官网下载地址:http://www.eclipse.org/mat/downloads.php mat百度网盘链接:(速度更快) 链接:https://pan.baidu.com/s/1tMp8MQIXuPtg9zBgruO0Ug?pwdjqtv 提取码:jqtv jdk17 百度网盘链接…

计算机体系结构概念总结

CH1 基本概念 课件补充 概念汇总 CH2 指令系统 课件补充 能够改变控制流的指令:分支、跳转、过程调用、过程返回 概念汇总 课后习题 CH3 流水线 课件补充 概念汇总 指令发射:指令从流水线的译码段进入执行段的过程称为指令发射。 向量处理机&#xf…

【深度学习】因果推断与机器学习的高级实践 | 数学建模

文章目录 因果推断因果推断的前世今生(1)潜在结果框架(Potential Outcome Framework)(2)结构因果模型(Structual Causal Model,SCM) 身处人工智能爆发式增长时代的机器学…

Ansible的循环:loop,with_<lookup>和until

环境 管理节点&#xff1a;Ubuntu 22.04控制节点&#xff1a;CentOS 8Ansible&#xff1a;2.15.6 循环的方法 loopwith_<lookup>until 用这几种方式都可以实现循环。其中&#xff0c; loop 是推荐的用法&#xff0c;在很多时候能够替换 with_<lookup> 。 loop…

Loadrunner安装大全

目录 一 、下载篇 二、安装篇 三、破解篇 四、Loadrunner支持哪些操作系统&#xff1f; 五、安装Loadrunner需要满足哪些系统要求&#xff1f; 六、安装Loadrunner时是否需要注意什么问题&#xff1f; 七、安装完成后如何验证Loadrunner是否正常工作&#xff1f; 八、如…

【每日一题】二叉树中的伪回文路径

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;递归&#xff08;DFS&#xff09;方法二&#xff1a;位运算 写在最后 Tag 【递归/DFS】【伪回文】【二叉树】【2023-11-25】 题目来源 1457. 二叉树中的伪回文路径 题目解读 伪回文路径指的是路径中的节点值经过重新…

基于51单片机的FM数字收音机系统电路设计

**单片机设计介绍&#xff0c;基于51单片机的FM数字收音机系统电路设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的FM数字收音机系统是一种用于接收和播放FM广播信号的设备&#xff0c;以下是一个基本的电路设…

ubuntu22.04 安装 jupyterlab

JupyterLab Install JupyterLab with pip: pip install jupyterlabNote: If you install JupyterLab with conda or mamba, we recommend using the conda-forge channel. Once installed, launch JupyterLab with: jupyter lab

Pycharm创建项目新环境,安装Pytorch

在python项目中&#xff0c;很多项目使用的各类包的版本是不一致的。所以我们可以对每个项目有专属于它的环境。所以这个文章就是教你如何创建新环境。 一、创建新环境 首先我们需要去官网下载conda。然后在Pycharm下面添加conda的可执行文件。 用conda创建新环境。 二、…

CSS新特性(2-2)

CSS新特性&#xff08;2-2&#xff09; 前言box相关box-shadow background背景rgba颜色与透明度transform:rotate(Xdeg) 2D旋转transform:tranlate 平移 前言 本文继续讲解CSS3其他的新特性&#xff0c;想看之前新特性点击这里&#xff0c;那么好本文正式开始。 box相关 box…

二十三种设计模式全面解析-揭秘访问者模式:开启对象间灵活交互之门

在软件设计中&#xff0c;我们经常会遇到需要对一组对象进行操作和处理的情况。但是&#xff0c;如果对象结构复杂且对象类型众多&#xff0c;传统的处理方式可能会导致代码的冗长和维护困难。然而&#xff0c;访问者模式&#xff08;Visitor Pattern&#xff09;以其优雅的解决…

开源与闭源

我的观点&#xff1a; 开源与闭源软件都有各自的优势和劣势&#xff0c;没有绝对的对错之分。.. 一、开源和闭源的优劣势比较 开源的好处与劣处 优势&#xff1a; 创新与合作&#xff1a;开源软件能够吸引更多的开发者参与到项目中来&#xff0c;促进创新和合作。开放的源代码…