IO多路复用机制——select、poll、epoll的原理和区别

     select,poll,epoll都是IO多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。  

问题:如果我们先前创建的几个进程承载不了目前快速发展的业务的话,是不是还得增加进程数?我们都知道系统创建进程是需要消耗大量资源的,所以这样就会导致系统资源不足的情况。

那么有没有一种方式可以让一个进程同时为多个客户端端提供服务?

对于IO复用,我们可以通过一个例子来很好的理解它。

某教室有10名学生和1名老师,这些学生上课会不停的提问,所以一个老师处理不了这么多的问题。那么学校为每个学生都配一名老师,也就是这个教室目前有10名老师。此后,只要有新的转校生,那么就会为这个学生专门分配一个老师,因为转校生也喜欢提问题。如果把以上例子中的学生比作客户端,那么老师就是负责进行数据交换的服务端。则该例子可以比作是多进程的方式。

后来有一天,来了一位具有超能力的老师,这位老师回答问题非常迅速,并且可以应对所有的问题。而这位老师采用的方式是学生提问前必须先举手,确认举手学生后在回答问题。则现在的情况就是IO复用。

select:

accept创建了五个客户端连接,并把相应的文件描述符fd放到数组中

文件描述符是随机产生的,并不是连续的

求出最大的文件描述符

if(fd[i]>max){
    max=fd[i];
}

 对需要关注的文件描述符初始化为0

FD_ZERO(&read_fds);

FD_SET设置哪个文件描述符被关注的置1

for(i=0;i<5;i++){
    FD_SET(fd[i],&read_fds);
}

过程:

select函数参数:

1、max+1,限定了循环遍历bitmap的范围,bitmap最多有1024位,限定了遍历的最大长度,可以减少无谓的扫描

2、读文件描述符的集合:读文件描述符实际上是bitmap,来表示具体哪个文件描述符被监听

3、写文件描述符的集合

4、异常文件描述符集合

5、超时时间,在指定的时间内如果还没有检测到某个文件描述符已就绪,这个时候也会阻塞,不再等待,立即返回。设置成NULL永不超时,一直阻塞下去,一直等到有数据到达,时间已就绪才返回。设置为0,表示不阻塞

ret = select(max + 1,&read_fds,NULL,NULL,NULL);

  进程A调用select会将bitmap拷贝到内核态中,由内核判断哪一个socket文件描述符也就是fd,有对应的数据到达,需要关注的事件已就绪。内核的效率比用户态要高,用户态判断的时候需要询问内核哪个文件描述符已就绪,这样就会产生用户态和内核态的上下文切换,如果每一次对每一个fd都判断一次的话,那么就会存在多次的内核态和用户态的上下文切换,会非常浪费资源,因此select函数就选择将bitmap一次性的拷贝内核态,由内核去遍历哪个fd有数据到达。

哪个socket文件描述符对应的数据接收队列有数据到达,那么就标志这个文件描述符已就绪,这个时候select函数就会返回,返回的时候不仅仅是拷贝已就绪的fd,他是把所有的文件描述符信息全部拷贝到用户态,同时告知用户态现在有几个文件描述符已就绪,只是告诉个数,并没有告诉具体哪个就绪,所以需要for循环去判断具体哪个文件描述符就绪了

for(int i=0;i<5;i++){
    if(FD_ISSET(fd[i],&read_fds)){
        ret = recv(fd[i],buff,sizeof(buff);
    }
}

poll

poll相比于select的亮点是定义了pollfd结构体,events代表用户关注的事件,比如读事件,写事件,revents指返回的事件,由系统的内核填充并返回,如果当前的文件描述符,有状态的变化,比如说已就绪的话,revents就会做出相应的变化,poll的结构体数组模式就不会有1024个文件描述符的限制,相对select来说,能够承受更高的并发。

执行原理:首先也是accept创建4个文件描述符,建立了四个客户端连接,同时注册了需要关注的读事件

参数的含义

1、传入文件描述符的结构体数组

2、结构体数组的最大长度

3、阻塞等待时间

ret = poll(fds,4,4000);

跟select一样,一次性将一批文件描述符发送到内核态,在内核中文件描述符遍历,看哪个文件描述符的数据接收队列有数据,就将revents置1,poll函数返回,将文件描述符的结构体数组拷贝回用户态,遍历具体哪个已就绪,与select不同的是,判断完成之后,直接将revents恢复成0. 

for(int i=0;i<4;i++){
    if(fds[i].revents & POLLIN){
        fd[i].revents = 0;
        ret = recv(fds[i].fd,buff,sizeof(buff)-1,0);
}

epoll 

首先定义了epoll_event的结构体,events表示关注的事件(读写事件),epoll_data是一个自定义的联合体,fd保存需要监听的文件描述符信息

int epoll_fd = epoll_reate

进程调用epoll_create方法时,内核会创建一个eventpoll结构体:

rdyList(就绪队列)已就绪的文件描述双链表,当某个读事件或者写事件就绪的时候,就会把相应的文件描述符信息放到已就绪的双链表中

rbr是一颗红黑树,用红黑树去管理用户进程放进来的所有socket连接

wq是一个等待队列,当他需要关注的某个事件未就绪的时候,就会把当前进程的描述符以及回调函数放到进程等待队列里,当软中断数据到达的时候就会通过检查阻塞队列,找到相应的阻塞进程去唤醒他执行后续的动作

epoll_ctl函数用于增加,删除,修改epoll事件,epoll事件会存储于内核epoll结构体红黑树中。每当我们创建一个客户端和服务端的socket连接的时候,就会把链接添加到一个红黑树里面。

#include <sys/epoll.h>
 
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
 
参数:
epfd:epoll文件描述符
op:操作码
EPOLL_CTL_ADD:插入事件
EPOLL_CTL_DEL:删除事件
EPOLL_CTL_MOD:修改事件
fd:事件绑定的套接字文件描述符
events:事件结构体
 
返回值:
成功:返回0
失败:返回-1

epoll_wait检查双链表中是否有就绪的事件,如果有就绪的事件的话,wait函数会立即返回不阻塞,但是这个里面为空的时候,它就会进行阻塞,等待有就绪事件到达。

#include <sys/epoll.h>
 
int epoll_wait(int epfd, struct epoll_event *events,              
int maxevents, int timeout);
 
参数:
epfd:epoll文件描述符
events:epoll事件数组
maxevents:epoll事件数组长度
timeout:超时时间
小于0:一直等待
等于0:立即返回
大于0:等待超时时间返回,单位毫秒
 
返回值:
小于0:出错
等于0:超时
大于0:返回就绪事件个数

区别

select,poll,epoll都是I/O多路复用机制,即能监视多个fd,一旦某fd就绪(读或写就绪),能够通知程序进行相应读写操作。 但select,poll,epoll本质都是同步I/O,因为他们都需在读写事件就绪后,自己负责进行读写,即该读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O实现会负责把数据从内核拷贝到用户空间。

select,poll需自己主动不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll其实也需调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但它是设备就绪时,调用回调函数,把就绪fd放入就绪链表,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,但select和poll在“醒着”时要遍历整个fd集合,而epoll在“醒着”的时候只需判断就绪链表是否为空,节省大量CPU时间,这就是回调机制带来的性能提升。

select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,且要把current往设备等待队列中挂一次,而epoll只要一次拷贝,且把current往等待队列上挂也只挂一次(在epoll_wait开始,注意这里的等待队列并不是设备等待队列,只是一个epoll内部定义的等待队列)。这也能节省不少开销。

select、poll和epoll都是用于实现 I/O 多路复用的方式,可以在同一时间内监听多个文件描述符的就绪状态。

  • select 是一种比较老的方式,它使用位图来表示文件描述符的状态。调用 select 时,内核需要遍历整个位图,检查每个文件描述符是否就绪。这种轮询的方式在连接数量很少时还是很有效的,但当连接数量增多时,性能会下降。由于使用位图来保存描述符,所以 select 还有描述符个数的限制,一般只能支持 2048 个,不过 select 的跨平台性比较好,几乎所有的平台都可以支持。
  • poll 使用链表结构来表示文件描述符的状态,没有最大连接数的限制。和 select 函数一样,poll 返回后,需要轮询来获取就绪的描述符,因此随着监视的描述符数量的增长,其效率也会线性下降。
  • epoll 是 Linux 特有的一种方式,它使用了事件驱动的模型,没有最大连接数的限制。它将文件描述符添加到 epoll 的事件集合中,等待事件的发生。与 select 和 poll 不同的是,epoll 不需要轮询,它使用回调的方式,只关注真正发生事件的文件描述符。这使得epoll在大规模高并发连接下具有卓越的性能。

应用场景上,select和poll适用于连接数量较少的场景,而epoll则适用于需要处理大规模并发连接且性能要求较高的场景。


参考:腾讯面试:请描述 select、poll、epoll 这三种IO多路复用技术的执行原理_哔哩哔哩_bilibili

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

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

相关文章

使用JMeter+Grafana+Influxdb搭建可视化性能测试监控平台

【背景说明】 使用jmeter进行性能测试时&#xff0c;工具自带的查看结果方式往往不够直观和明了&#xff0c;所以我们需要搭建一个可视化监控平台来完成结果监控&#xff0c;这里我们采用三种JMeterGrafanaInfluxdb的方法来完成平台搭建 【实现原理】 通过influxdb数据库存储…

共性化异步任务处理

背景 考虑到现有业务很多依赖于MQ的方式进行&#xff0c;这种方式需要依赖于MQ&#xff0c;发送消息到mq和消费mq消息时需要了解mq消息结构进行相应处理&#xff1b; 对于后续对同样的事件做其他处理的人如不能提前了解到已有相应消息发到了mq就得再发一次消息到mq等。 图1.1…

Paper - 蛋白质刚性对接(Rigid Protein-Protein Docking)的 ElliDock 算法

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/135973005 论文&#xff1a;ElliDock: Rigid protein-protein docking via equivariant elliptic-paraboloid interface prediction, ICLR 2024 …

【复现】智邦国际ERP SQL注入漏洞_36

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 智邦国际“一体化ERP”各类产品线&#xff0c;通过一体化ERP经典型、行业型、简易型、云应用、SAAS平台等产线产品&#xff0c;提…

【CSS】移动端适配

移动端适配怎么做&#xff1f; 适配的目的是在屏幕大小不同的终端设备拥有统一的界面&#xff0c;让拥有更大屏幕的终端展示更多的内容。 meta viewport (视口) 移动端初始视口的大小默认是980px&#xff0c;因为世界上绝大多数PC网页的版心宽度为980px &#xff0c;如果网页…

7.4 Highest Locker Protocol/Pattern

Bruce Powel Douglass大师介绍-CSDN博客https://blog.csdn.net/ChatCoding/article/details/134665868嵌入式软件开发从小工到专家-CSDN博客https://blog.csdn.net/ChatCoding/article/details/135297955C嵌入式编程设计模式源码-CSDN博客https://blog.csdn.net/ChatCoding/art…

IT行业中最重要的证书

在IT行业&#xff0c;拥有一些含金量较高的证书是职业发展的关键。这些证书不仅可以证明技能水平&#xff0c;还有助于提升在职场上的竞争力。本文将介绍几个IT行业中最重要的证书。 1. Cisco认证 CCNA&#xff08;Cisco Certified Network Associate&#xff09;是Cisco公司新…

Acrel-1200分布式光伏运维平台屋顶光伏工商业屋顶光伏应用

上海安科瑞电气股份有限公司 胡冠楠 咨询家&#xff1a;“Acrelhgn”&#xff0c;了解更多产品资讯 行业现状 “十四五”期间&#xff0c;随着“双碳”目标提出及逐步落实&#xff0c;本就呈现出较好发展势头的分布式光伏发展有望大幅提速。就“十四五”光伏发展规划&#xf…

关键字const

1.定义常量 const int a; 2.定义常量指针 1.不可以通过常量指针来修改其指向的内容。 2.不能把常量指针赋值给非常量指针&#xff0c;反过来可以。 3.函数参量为常函数指针时&#xff0c;可以避免函数内部不小心改变指针所指地方的内容。

Linux ---- Shell编程之免交互

一、Here Document 多行重定向 1、Here Document定义 使用I/O重定向的方式将命令列表提供给交互式程序标准输入的一种替代品Here Document 是标准输 入的一种替代品&#xff0c;可以帮助脚本开发人员不必使用临时文件来构建输入信息&#xff0c;而是直接就地生产出一个文件…

猫什么时候发腮?公认发腮效果好的生骨肉冻干推荐

猫什么时候发腮是许多猫主人非常关心的问题。在猫咪的成长过程中&#xff0c;发腮是一项重要的体征&#xff0c;也是猫咪成熟的标志。想要让猫咪拥有可爱的肉嘟嘟脸型&#xff0c;主人需要在适龄的年龄段加强营养补给&#xff0c;不要错失最佳发腮期。那么&#xff0c;猫咪的最…

netty源码:(58)NioEventLoop中处理IO事件和普通事件的时间比例是多少?

在NioEventLoop的run方法中有如下代码片段&#xff1a; 当ioRatio不为100时&#xff0c;首先通过System.nanoTime()获取IO事件的开始处理时间&#xff0c;然后调用processSelectedKeys方法处理IO时间&#xff0c;然后再计算IO事件执行了多长时间。最后通过ioTime&#xff08;I…

《区块链简易速速上手小册》第4章:区块链与加密货币(2024 最新版)

文章目录 4.1 比特币与区块链4.1.1 比特币基础4.1.2 比特币交易的工作流程&#xff1a;4.1.3 拓展案例 1&#xff1a;闪电网络4.1.4 拓展案例 2&#xff1a;比特币ATM 4.2 其他主要加密货币4.2.1 加密货币的多样性4.2.2 以太坊的案例4.2.3 拓展案例 1&#xff1a;非同质化代币&…

springboot 整合 PowerJob实现定时任务调度

最近项目需要使用定时任务&#xff0c;而使用了PowerJob做任务调度模块&#xff0c;感觉这个框架真香&#xff0c;今天我们就来深入了解一下新一代的定时任务框架——PowerJob&#xff01; 简介 PowerJob是基于java开发的企业级的分布式任务调度平台&#xff0c;与xxl-job一样…

【JavaEE Spring】Spring AOP

Spring AOP 1. AOP概述2. Spring AOP快速⼊⻔2.1 引⼊AOP依赖2.2 编写AOP程序 3. Spring AOP详解3.1 SpringAOP核⼼概念3.1.1 切点(Pointcut)3.1.2 连接点(JoinPoint)3.1.3 通知(Advice)3.1.4 切⾯(Aspect) 3.2 通知类型3.3 PointCut3.4 切⾯优先级Order3.5 切点表达式3.5.1 ex…

什么是网络数据抓取?有什么好用的数据抓取工具?电商数据API免费测试入口

什么是网络数据抓取 网络数据抓取&#xff08;Web Scraping&#xff09;是指采用技术手段从大量网页中提取结构化和非结构化信息&#xff0c;按照一定规则和筛选标准进行数据处理&#xff0c;并保存到结构化数据库中的过程。目前网络数据抓取采用的技术主要是对垂直搜索引擎&a…

Maya------布尔 圆形圆角组件

17. maya常用命令7.布尔 圆形圆角组件_哔哩哔哩_bilibili 选中一个模型&#xff0c;再按shift加选另外一个模型 圆形圆角命令

QT5.14+VS2017安装踩过的一些坑

1.在QT中使用MSVC只能用VS2017&#xff0c;相应的调试器的版本只能用15.9&#xff0c;高于15.9的亲测都不行。完整的安装除了需要QT5.15和VS2017&#xff0c;还需要Windows SDK (10.0.22621) 下载地址&#xff1a;https://developer.microsoft.com/zh-cn/windows/downloads/win…

Qt读写Execl:QXlsx库

Qt三方库开发技术&#xff1a;QXlsx介绍、编译和使用 我自己记录的实例代码&#xff1a;https://download.csdn.net/download/cao_jie_xin/88795216 目录 一、概述二、下载三、编译四、加载QXlsx静态库五、介绍一些常用的功能1、一些头文件和命名空间2、创建一个excel文件3、…

消息中间件之RocketMQ源码分析(四)

消费者的Rebalance机制 客户端是通过Rebalance服务做到高可靠的。当发生Broker掉线、消费者实例掉线、 Topic扩容等各种突发情况时&#xff0c;消费者组中的消费者实例是怎么重平衡的&#xff0c;以支持全部队列的正常消费的? Rebalance服务的类图 RebalanceImpl的核心属性 …