【Linux】select,poll和epoll
select,poll,epoll都是IO多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符fd,一旦某个描述符就绪(一般是读就绪或者写就绪),系统会通知有I/O事件发生了(不能定位是哪一个)。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。
select、poll和epoll这三个函数是Linux系统中I/O复用的系统调用函数。I/O复用使得这三个函数可以同时监听多个文件描述符(File Descriptor, FD),因为每个文件描述符相当于一个需要 I/O的“文件”,在socket中共用一个端口。
select
作用:监控多个文件描述符,就绪之后通知调用者
工作原理
函数
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *execptfds, struct timeval *timeout);
参数:
nfds:参数指定被监听的文件描述符的总数。他通常被设置为select监听所有文件描述符中最大值加1,因为文件描述符是从0开始计数的。
readfds、writefds和exceptfds参数分别指向可读、可写和异常等事件对应的文件描述符集合
timeout参数是用来设置select函数的超时时间。
返回值:
select成功时返回就绪(可读、可写和异常)文件描述符的总数。
select失败时将返回-1并设置errno。
timeout参数是用来设置select函数的超时时间。它是一个timeval结构类型的指针,其定义如下:
struct timeval{long tv_sec;/*秒数*/long tv_usec;/*微秒数*/
};
注:当我们给timeout设定了特定的时间后,假设是10s,如果select在10s内调用返回(3s就返回了),那么timeval的成员tv_sec和tv_usec的值将会被替换成剩余的秒数。
内核在使用该数组fd_set的时候采用的是位图的方式,一共有16*8*8=1024个比特位。其实fd_set结构就是一个整数数组,更严格的是,是一个“位图”,使用位图中对应的位来表示要监控的文件描述符,如下图所示:
为了方便操的作位图,可使用如下接口来操作fd_set:
从事件集合当中删除一个文件描述符:
void FD_CLR(int fd, fd_set *set);
判断文件描述符是否在某一个事件集合当中:
int FD_ISSET(int fd, fd_set *set);
设置文件描述符到事件集合当中:
void FD_SET(int fd, fd_set *set);
清空事件集合,将所有的比特位全部置为0:
void FD_ZERO(fd_set *set);
select的优点和缺点
优点:
- select遵循的是POSIX标准,说明select函数是一个跨平台的函数,既可以在Windows当中运行,也可以在Linux当中运行
- select在带有超时时间的监控的时候,超时时间的单位可以为微妙
缺点:
- 监控文件描述符个数的上限为1024
- 随着文件描述符的增多,select监控效率在下降(本质是select在轮询进行监控)
- 可读、可写、异常这些事件需要单独的添加到不同的事件集合当中
- 当select监控成功之后,会从事件集合当中去除掉未就绪的文件描述符,这使程序下一次调用select时,还需要重新添加文件描述符
- 在每次select进行监控的时候,都会将准备好的事件集合拷贝到内核空间,select返回的时候都会将内核空间拷贝给用户空间
1 #include<stdio.h> 2 #include<unistd.h>3 #include<sys/select.h>4 5 int main() 6 { 7 fd_set readfds; 8 FD_ZERO(&readfds);9 FD_SET(0,&readfds);10 11 while(1) 12 { 13 int ret = select(1,&readfds,NULL,NULL,NULL);14 if(ret < 0) 15 {16 perror("select");17 return 0;18 }19 20 char buf[1024] = {0};21 read(0,buf,sizeof(buf)-1);22 23 printf("%s\n",buf);24 } 25 26 return 0; 27 }
poll
可以认为poll是一个增强版本的select,因为select的比特位操作决定了一次性最多处理的读或者写事件(文件描述符数量)只有1024个,而poll使用一个新的方式优化了这个模型。
poll底层操作的数据结构pollfd:
struct pollfd {int fd; // 需要监视的文件描述符short events; // 需要内核监视的事件short revents; // 实际发生的事件
};
函数
int poll(struct pollfd *fds,nfds_t nfds,int timeout);
参数:
fds:想让poll监控多个文件描述符,只需要在定义事件结构数组的时候,多传递几个元素
eg:struct pollfd arr[10];
arr[0].fd = 0;
arr[0].events = POLLIN;
nfds:事件结构数组中有效元素的个数
timeout:
>0:带有超时时间,单位:秒
==0:非阻塞
<0:阻塞
返回值:就绪文件描述符的个数
内核修改的是revents的值,events是我们需要关注的文件描述符,revents是内核检测到文件描述符中有数据的而进行修改后的内容,
poll的优点和缺点
优点:
- 提出了事件结构的方式,在给poll函数传递参数的时候,不需要分别添加到“事件集合”中
- 事件结构数组的大小可以根据程序员自己进行定义,并没有上限要求
- 不用在监控到就绪文件描述符之后,重新添加文件描述符
缺点:
- 不支持跨平台
- 内核对事件结构数组的监控也是采用轮询遍历的方式,即随着监控文件描述符的增多,监控效率会下降
- 每次调用poll都需要把大量的pollf结构从用户态拷贝到内核态,poll返回的时候,会将内核空间拷贝给用户空间(从内核态到用户态会调用do_signal会有开销)
1 #include<stdio.h>2 #include<poll.h>3 #include<unistd.h>4 5 int main()6 {7 struct pollfd arr[10]; 8 9 arr[0].fd = 0;10 arr[0].events = POLLIN;11 12 while(1)13 {14 int ret = poll(arr,1,-1);15 if(ret < 0)16 {17 perror("poll");18 return 0;19 }20 for(int i = 0;i < 10;++i)21 {22 if(arr[i].revents == POLLIN)23 { 24 char buf[1024] = {0};25 read(arr[i].fd,buf,sizeof(buf)-1);26 printf("%s\n",buf);27 } 28 } 29 } 30 return 0; 31 }
epoll
epoll给出了一个新的模式,直接申请一个epollfd的文件,对这些进行统一的管理,初步具有了面向对象的思维模式。可理解为event poll,epoll会把哪个流发生哪种I/O事件通知我们。所以epoll是事件驱动(每个事件关联fd)的,此时我们对这些流的操作都是有意义的。复杂度也降低到了O(1)。
epoll通过在Linux内核中申请一个简易的文件系统。把原先的select/poll调用分成了3个部分:
- 调用epoll_create()建立一个epoll对象(在epoll文件系统中为这个句柄对象分配资源);
- 调用epoll_ctl向epoll对象中添加这些连接的套接字;
- 调用epoll_wait收集发生的事件的连接.
如此一来只需要在进程启动时建立一个epoll对象,然后在需要的时候向这个epoll对象中添加或者删除连接。同时,epoll_wait的效率也非常高,因为调用epoll_wait时,并没有一股脑的向操作系统复制这些连接的句柄数据,内核也不需要去遍历全部的连接。
工作原理
当调用epoll_create函数时,会在内核创建一个eventpoll结构体,在该结构体中有一个rdlist成员和rbr成员,它两分别是一个双向链表和红黑树,而调用epoll_ctl函数添加、修改、删除文件描述符对应的事件集合其实是对红黑树中的节点进行相应的添加、修改、删除操作,而所有添加到epoll的事件都会与设备(网卡)驱动程序建立回调关系,也就是说,当文件描述符准备就绪后,内核会回调ep_poll_callback函数,将准备就绪的事件集合添加到rdlist双向链表中,而当调用epoll_wait进行监控的时候,如果双向链表为空,则表明当前没有就绪的事件发生,如果不为空,则将双向链表中的内容复制到用户态,并返回将事件数量返回给用户。
函数
epoll_create
//创建一个epoll模型
int epoll_create(int size);
参数:
size参数自从Linux2.6.8之后,size参数是被忽略的,但size的值必须设置为大于0的值。size只是给内核一个提示,告诉它事件需要多大。仅仅只是给内核一个建议,具体多大还是操作系统说了算。
返回值:
epoll模型创建成功返回其对应的文件描述符,否则返回-1,同时错误码会被设置。
该函数返回的文件描述符将作为其他epoll系统调用的第一个参数,以指定要访问的内核事件表。
当不再使用时,必须调用close函数关闭epoll模型对应的文件描述符,当所有引用epoll实例的文件描述符都已关闭时,内核将销毁该实例并释放相关资源。
epoll_ctl
//向指定的epoll模型中注册事件
int epoll_ctl(int epfd,int op, int fd, struct epoll_event *event);
参数:
epfd:epoll操作句柄
op:告诉epoll要做什么是事
① EPOLL_CTL_ADD:添加一个文件描述符对应的事件结构到epoll当中
② EPOLL_CTL_MOD:修改一个文件描述符的事件结构
③ EPOLL_CTL_DEL:从epoll当中删除一个文件描述符对应的事件结构
fd:待处理(添加、修改、删除)的文件描述符
event:文件描述符对应的事件结构
epoll_event结构体
返回值:
epoll_ctl成功时返回0,失败则返回-1并设置errno。
epoll_wait
//用于收益监视的事件中已经就绪的事件
int epoll_wait(int epfd,struct epoll_event *events,int maxevents,int timeout)
参数:
epfd:epoll的操作句柄
events:时间结构数组(集合),从epoll当中获取就绪的事件结构
maxevents:最多一次获取多少个事件结构
timeout:
0:带有超时事件
==0:非阻塞
<0:阻塞返回值:就绪的文件描述符个数
epoll的优点和缺点
优点:
- 事件回调机制,当文件描述符就绪之后,会调用回调函数将事件结构复制到双向链表中,epoll_wait 返回直接访问就绪队列就知道哪些文件描述符就绪. 这个操作时间复杂度O(1). 即使文件描述符数目很多, 效率也不会受到影响.
- 数据拷贝轻量: 只在合适的时候调用 EPOLL_CTL_ADD 将文件描述符结构拷贝到内核中, 这个操作并不频繁(而select/poll都是每次循环都要进行拷贝)
- 没有数量限制: 文件描述符数目无上限.
LT和ET模式
首先,select、poll和epoll的工作模式默认情况下都是LT模式。但是epoll的工作模式有两种,分别为LT模式(水平触发模式)和 ET 模式(边缘触发模式)。
LT模式:举一个例子,张三买了很多快递,快递站的小王每隔一段时间通知张三取快递(张三没有去取快递或没取完的情况下,就会一直通知,这不就是轮询嘛)
ET模型:举一个例子,张三买了很多快递,快递站的小李会通知张三取快递,但是只通知一次(张三没有去取快递或没取完的情况下,小李在也不会通知了)
epoll默认是LT模式,我们要将其改为ET模式,只需要将其时间或上一个EPOLLET,在刚才的代码中有体现,可以尝试运行此服务器,测试其效果(我们测试时,只要关心监听套接字就足够了,其将accept函数部分注释掉。然后LT模式下,就会发现,当套接字有读事件就绪后,会不断的触发提示,告诉你有事件就绪;ET模式只会通知一次)
总结
相关文章:
【Linux】select,poll和epoll
select,poll,epoll都是IO多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符fd,一旦某个描述符就绪(一般是读就绪或者写就绪),系统会通知有I/O事件发生了(不能定位是哪一个)。但sel…...
Qt程序发布及打包成exe安装包
参考:Qt之程序发布以及打包成exe安装包 目录 一、简述 Qt 项目开发完成之后,需要打包发布程序,而因为用户电脑上没有 Qt 配置环境,所以需要将 release 生成的 exe 文件和所依赖的 dll 文件复制到一个文件夹中,然后再用 Inno Setup 打包工具打包成一个 exe 安装包,就可以…...
python怎样运行js语句
1. 安装 pip install PyExecJS # 需要注意, 包的名称:PyExecJS 2. 简单使用 import execjs execjs.eval("new Date") 返回值为: 2018-04-04T12:53:17.759Z execjs.eval("Date.now()") 返回值为:152284700108…...
汽车渲染领域:Blender 和 UE5 哪款更适用?两者区别?
在汽车渲染领域,选择合适的工具对于实现高质量的视觉效果至关重要。Blender和UE5(Unreal Engine 5)作为两大主流3D软件,各自在渲染动画方面有着显著的差异。本文将从核心定位与用途、工作流程、渲染技术和灵活性、后期处理与合成四…...
JAVA实现将PDF转换成word文档
POM.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.…...
前端-Git
一.基本概念 Git版本控制系统时一个分布式系统,是用来保存工程源代码历史状态的命令行工具 简单来说Git的作用就是版本管理工具。 Git的应用场景:多人开发管理代码;异地开发,版本管理,版本回滚。 Git 的三个区域&a…...
如何分析Windows防火墙日志
Windows防火墙,也被称为Windows Defender Firewall,是一种内置的安全功能,可以主动监控和分析运行Windows操作系统的计算机上通过Windows防火墙的网络流量,主要目的是作为计算机和互联网或其他网络之间的屏障,使管理员…...
工作坊报名|使用 TEN 与 Azure,探索你的多模态交互新场景
GPT-4o Realtime API 发布,语音 AI 技术正在进入一场新的爆发。语音AI技术的实时语音和视觉互动能力将为我们带来更多全新创意和应用场景。 实时音频交互: 允许应用程序实时接收并响应语音和文本输入。自然语音生成: 减少 AI 技术生成的语音…...
学习笔记041——Elastic Search的学习与使用以及SpringBoot整合
文章目录 1、Elastic Search介绍1.1、ES 的数据结构1.2、ES 为什么查询快1.3、CRUD 2、Spring Boot 整合 ES 1、Elastic Search介绍 Elasticsearch是一个分布式的、基于RESTful API的搜索和分析引擎,广泛用于大规模数据存储和快速检索。它最初由Shay Banon于20…...
R安装rgdal报错 解决办法
尝试了网上很多办法,不知道哪一步解决了,记录一下所有步骤: 1. 尝试github安装 options(repos c(CRAN "https://mirrors.tuna.tsinghua.edu.cn/CRAN/"))install.packages("devtools")library(devtools)devtools::in…...
【智能制造-46】人机工程(工厂自动化)
工作空间设计 设备布局规划 根据人体测量学数据,合理安排自动化设备、生产线和工作区域的布局。例如,考虑工人的操作空间和活动范围,确保他们能够舒适地接近和操作设备。在汽车装配车间,机器人和工人的工作区域应划分明确&#…...
C#笔记(5)
一、winform项目与窗体控件 1、部分类的使用 好处:让自动生成的代码后置,我们编写程序的代码显得更加简洁 特点:在最后编译的时候,仍然编译成一个窗体类。 窗体和控件的基本使用 3、Event事件(委托--》事件&#…...
【软件国产化】| Windows和Linux下文件名后缀是否区分大小写
今天在开发过程中遇到了个软件在Linux系统和Windows系统下功能表现不一致的bug,具体表现为: 插入一张图片(A文件夹中的001.jpg),然后使用“图片替换”功能,用B文件夹中的图片(B文件夹中的001.JP…...
讨论JAVA、JVM与Spring
Q1: 作为一个JAVA开发人员,对于jvm肯定不陌生,但很多人对它不陌生也仅止于概念上,而且对概念也是模糊不清的,但jvm实际是java程序运行在其中的实际存在的环境,对它的理解应该要是具象化的。 我们还是从一项技术产生的…...
【04】MySQL数据库和数据表的基本操作详解与实例
文章目录 一、连接MySQL服务器二、数据库的基本操作2.1数据库的基本操作1. 创建数据库2. 选择数据库3. 删除数据库4.查询所有数据库5.修改数据库的字符集 2.2 数据表的基本操作1. 创建数据表2. 查看数据表结构3. 删除数据表4. 修改数据表5. 插入数据6. 查询数据7. 更新数据8. 删…...
Spring中实现动态数据源切换,基于AbstractRoutingDataSource
背景 在项目开发过程中,我们可能会遇到一个场景:某个类型数据源有多个数据源实例,需要我们按照不同的请求切换到不同数据源去。 而目前绝大多数java应用都是基于Spring框架来开发,我们很多时候相关的数据源连接都是交给了Spring框…...
StarRocks-join优化
1、背景 有两个大表,都是6kw级别上下的,通过SR然后包装了一个接口对外提供查询,当前的问题是,这样大的join查询会导致BE直接宕机。并且这个sql很有代表性,我截图如下: 这个表是个单分区,所以直接…...
js 高亮文本中包含的关键词标红
在开发中,遇到需要将文本中包含的关键字高亮的情况,可以做以下处理。 <div class"title"v-html"highlightKeywords(item.title, state1.tags1.concat(state2.tags2).concat(state3.tags3))"> </div> ...... ...... con…...
DVWA靶场——File Inclusion
File Inclusion(文件包含)漏洞 指攻击者通过恶意构造输入,利用应用程序错误的文件包含机制,导致程序包含并执行未经授权的本地或远程文件。这类漏洞广泛存在于Web应用程序中,尤其是在那些允许用户提供文件路径或URL的地…...
Android Framework禁止弹出当前VOLTE不可用的提示窗口
文章目录 VoLTE简介VoLTE 的优势 当前VOLTE不可用的弹窗弹窗代码定位屏蔽弹出窗口 VoLTE简介 VoLTE(Voice over LTE)是一种基于4G LTE网络的语音通话技术。它允许用户在4G网络上进行高质量的语音通话和视频通话,而不需要回落到2G或3G网络。V…...
OceanBase 大数据量导入(obloader)
现需要将源数据库(Oracle|MySQL等)一些表的海量数据迁移到目标数据库 OceanBase 中,基于常规 jdbc 驱动编码的方式涉及开发工作,性能效率也要看编码的处理机制。 OceanBase 官方提供了的 OceanBase Migration Service (OMS) 数据…...
w058基于web的美发门店管理系统
🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文件࿰…...
实时数据开发 | checkpoints监控和调优
监控Checkpoints 监控 checkpoint 行为最简单的方法是通过 UI 的 checkpoint 部分。 监控这两个指标: 算子收到第一个 checkpoint barrier 的时间。当触发 checkpoint 的耗费时间一直很高时,这意味着 checkpoint barrier 需要很长时间才能从 source 到达 operator…...
el-tree的使用及控制全选、反选、获取选中
el-tree的使用及控制全选、反选、获取选中 组件使用获取选中的id全选实现反选实现全部代码 组件使用 引入组件,可以参考官网组件引入参考官网示例写好基础数据结构,不知道怎么转换树形机构的看文章:一维数组转树形 <template><el-…...
机器学习(二十五):决策树算法以及决策树和神经网络的对比
一、决策树集合 单一决策树会对训练数据的变化很敏感。例子:输入十个数据,判断是否是猫。只替换其中一个数据,信息增益最高的分裂特征就发生了改变,决策树就发生了变化。 使用决策树集合可以使算法更加健壮。例子:使用…...
新版布谷直播软件源码开发搭建功能更新明细
即将步入2025年也就是山东布谷科技专注直播系统开发,直播软件源码出售开发搭建等业务第9年,山东布谷科技不断更新直播软件功能,以适应当前新市场环境下的新要求。山东布谷科技始终秉承初心,做一款符合广大客户需求的直播系统软件。支持广大客户提交更多个…...
vue3 reactive响应式实现源码
Vue 3 的 reactive 是基于 JavaScript 的 Proxy 实现的,因此它通过代理机制来拦截对象的操作,从而实现响应式数据的追踪。下面是 Vue 3 的 reactive 源码简化版。 Vue 3 reactive 源码简化版 首先,我们需要了解 reactive 是如何工作的&…...
git的使用(简洁版)
什么是 Git? Git 是一个分布式版本控制系统 (DVCS),用于跟踪文件的更改并协调多人之间的工作。它由 Linus Torvalds 在 2005 年创建,最初是为了管理 Linux 内核的开发。Git 的主要目标是提供高效、易用的版本控制工具,使得开发者…...
使用命令行创建 Maven 项目
本指南将引导您通过命令行创建一个简单的 Maven 项目。本教程假设您已经在您的机器上安装了 Maven 和 JDK 21。 第一步:验证 Maven 和 Java 安装 在开始之前,我们需要验证 Maven 和 Java 是否已正确安装在您的系统上。 验证 Maven 安装 打开命令行终…...
JVM_栈详解一
1、栈的存储单位 **栈中存储什么?**, 每个线程都有自己的栈,栈中的数据都是以栈帧(Stack Frame)的格式存在。在这个线程上正在执行的每个方法都各自对应一个栈帧(Stack Frame)。 栈帧是一个内存…...
网站开发和安卓开发/天津放心站内优化seo
附件:Android-kali.zip:http://pan.baidu.com/s/1gdh7YjL 里面有linux Deploy,VNC,SSH以及最重要的linux.img。如果有不可以用的,自己再下新的就行了。 1.安装linux Deploy与配置 这里要注意的是发行版和架构的设置,如…...
网站的友情链接怎么做/手机如何建立网站
JavaFxJFoenix 【HBox布局】 1.HBox布局简介 HBox布局控件是一个水平布局控件,他创建一个水平的容器,让组件在这个水平的一条线上进行布局,但是一行满了之后不会换行。在第二行布局组件需要在创建一个HBox水平容器。 2.HBox 示例Demo packa…...
微网站怎么自己做/国际国内新闻最新消息今天
/*测试版的实现 开始*/介绍在用GridView自带的排序功能排序时,无法直观的知道当前是通过哪个字段排序?是升序还是降序?所以扩展一下,用图片或文字的形式来提示一下当前是根据哪个字段排序,是升序还是降序。控件开发1、…...
怎样做二维码链接到网站上/附近广告公司
水果行业专业朋友圈营销文案,同行朋友圈运营精选水果文案大全。水果文案已更新300多类的水果,千条文案和图片,复制轻松发朋友圈。 1、怎么能看到这些朋友圈文案 朋友圈下的搜一搜,搜鲁班文案,找出来的文章,…...
图片描述 wordpress/国家高新技术企业
待补充转载于:https://www.cnblogs.com/zcjboke/p/5514547.html...
网站的服务/环球军事网最新消息
1.写文件 f open(out.txt,w) f.write(%s %d %d %d %d 0 0 0 0 0 0 0%(bbx.name,bbx.x,bbx.y,bbx.w,bbx.h)) f.close() 2.读文件 第一种 f open("foo.txt") # 返回一个文件对象 line f.readline() # 调用文件的 readline()方法 while li…...