当前位置: 首页 > news >正文

epoll、poll、select的原理和区别

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

select

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

select函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。调用后select函数会阻塞,直到有描述副就绪(有数据 可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以 通过遍历fdset,来找到就绪的描述符。

select的缺点:

  1. select支持的文件描述符数量太小了,默认是1024

  2. 每次调用select都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

  3. 每次调用select都需要在内核遍历传递进来的所有fd,查看有没有就绪的fd,这个开销在fd很多时也很大,效率随FD数目增加而线性下降

poll

int poll (struct pollfd *fds, unsigned int nfds, int timeout);
struct pollfd {int fd; /* file descriptor */short events; /* requested events to watch */short revents; /* returned events witnessed */
};

pollfd结构包含了要监视的event和发生的event,不再使用select“参数-值”传递的方式。同时,pollfd并没有最大数量限制(但是数量过大后性能也是会下降)。 和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符。

从上面看,select和poll都需要在返回后,通过遍历文件描述符来获取已经就绪的socket。事实上,同时连接的大量客户端在一时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降。

poll还有一个特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。

poll的缺点:
每次调用select都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

每次调用select都需要在内核遍历传递进来的所有fd,查看有没有就绪的fd,这个开销在fd很多时也很大,效率随FD数目增加而线性下降

poll跟select对比的优点

解决了select的第一个缺点,poll没有最大文件描述符数量的限制

epoll


epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关心的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。

epoll显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率,因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被监听的文件描述符集合,另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入就绪队列的描述符集合就行了。

epoll操作过程

epoll操作过程需要三个接口,分别如下:

int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
  1. int epoll_create(int size);创建一个epoll的句柄,参数size并不是限制了epoll所能监听的描述符最大个数,只是对内核初始分配内部数据结构的一个建议。
    当创建好epoll句柄后,它就会占用一个fd值,在linux下如果查看/proc/进程id/fd/,是能够看到这个fd的,所以在使用完epoll后,必须调用close()关闭,否则可能导致fd被耗尽。
  2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); 函数是对指定描述符fd执行op操作。
epfd:是epoll_create()的返回值。
op:表示op操作,用三个宏来表示:添加EPOLL_CTL_ADD,删除EPOLL_CTL_DEL,修改EPOLL_CTL_MOD。分别添加、删除和修改对fd的监听事件。
fd:是需要监听的fd(文件描述符)
epoll_event:是告诉内核需要监听什么事,struct epoll_event结构如下:
struct epoll_event {__uint32_t events;  /* Epoll events */epoll_data_t data;  /* User data variable */
};//events可以是以下几个宏的集合:
EPOLLIN :表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
EPOLLOUT:表示对应的文件描述符可以写;
EPOLLPRI:表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来);
EPOLLERR:表示对应的文件描述符发生错误;
EPOLLHUP:表示对应的文件描述符被挂断;
EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里

int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
等待epfd上的io事件,最多返回maxevents个事件。参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将永久阻塞直到有监听的io事件发生)。该函数返回需要处理的事件数目,如返回0表示已超时。

epoll工作模式:

epoll对文件描述符的操作有两种模式:LT(level trigger)和ET(edge trigger)。LT模式是默认模式,LT模式与ET模式的区别如下:

LT模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll_wait时,会再次响应应用程序并通知此事件。

ET模式:当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件。

epoll的跟select和poll对比的优点:

  1. 支持一个进程打开大数目的socket描述符。它所支持的FD上限是最大可以打开文件的数目,这个数字一般远远于2048,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。
  2. select和poll每次调用都需要把所有要监听的fd重新拷贝到内核空间;epoll只在调用epoll_ctl时拷贝一次要监听的fd,调用epoll_wait时不需要每次把所有要监听的fd重复拷贝到内核空间。
  3. IO效率不随FD数目增加而线性下降。传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合,任一时间只有部分的socket是”活跃”的,但是select/poll每次调用都会线性扫描全部的集合,导致效率呈现线性下降。但是epoll不存在这个问题,它只会对”活跃”的socket进行操作。这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。那么,只有”活跃”的socket才会主动的去调用callback函数,其他idle状态socket则不会。

总结

Select、Poll与Epoll区别

  1. select有最大文件描述符数量限制;poll,epoll则没有最大文件描述符数量限制。
  2. select,poll每次调用都要把fd集合从用户态往内核态拷贝一次,并且要把current往设备等待队列中挂一次,而epoll只在调用epoll_ctl时拷贝一次,而且把current往等待队列上挂也只挂一次(在epoll_wait的开始,注意这里的等待队列并不是设备等待队列,只是一个epoll内部定义的等待队列)。这也能节省不少的开销。
  3. select,poll实现需要自己不断轮询所有fd集合,直到设备就绪,期间可能要睡眠和唤醒多次交替。而epoll其实也需要调用epoll_wait不断轮询就绪链表,期间也可能多次睡眠和唤醒交替,但是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,但是select和poll在“醒着”的时候要遍历整个fd集合,而epoll在“醒着”的时候只要判断一下就绪链表是否为空就行了,这节省了大量的CPU时间。这就是回调机制带来的性能提升。
  4. 如果没有大量的idle-connection或者dead-connection,epoll的效率并不会比select/poll高很多,但是当遇到大量的idle-connection,就会发现epoll的效率大大高于select/poll。

 

相关文章:

epoll、poll、select的原理和区别

select,poll,epoll都是IO多路复用的机制。I/O多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但select&a…...

【学习笔记】Java安全之反序列化

文章目录 反序列化方法的对比PHP的反序列化Java的反序列化Python反序列化 URLDNS链利用链分析触发DNS请求 CommonCollections1利用链利用TransformedMap构造POC利用LazyMap构造POCCommonsCollections6 利用链 最近在学习Phith0n师傅的知识星球的Java安全漫谈系列,随…...

算法练习--leetcode 数组

文章目录 爬楼梯问题裴波那契数列两数之和 [数组]合并两个有序数组移动零找到所有数组中消失的数字三数之和 爬楼梯问题 输入n阶楼梯,每次爬1或者2个台阶,有多少种方法可以爬到楼顶? 示例1:输入2, 输出2 一次爬2阶&a…...

本地 shell无法连接centos 7 ?

1、首先检查是否安装ssh服务; yum list installed | grep openssh-server# 没有安装尝试安装下 yum install openssh-server 2、检查ssh服务是否开启 systemctl status sshd.service# 未开启,开启下 systemctl start sshd.service # 将sshd 服务添…...

C 语言的基本算术运算符 = + - * /

C 语言的基本算术运算符有: - * / 赋值运算符 赋值运算符左侧必须引用一个内存中的位置, 最简单的方法就是使用变量名, 也可以使用指针指向内存中的某个位置. 赋值表达式的目的是把值储存到目标内存位置上. 下面语句中的 表示初始化而不是赋值: const int …...

SQL注入实操三(SQLilabs Less41-50)

文章目录 一、sqli-labs靶场1.轮子模式总结2.Less-41 stacked Query Intiger type blinda.注入点判断b.轮子测试c.获取数据库名称d.堆叠注入e.堆叠注入外带注入获取表名f.堆叠注入外带注入获取列名g.堆叠注入外带注入获取表内数据 3.Less-42 Stacked Query error baseda.注入点…...

HOT77-买卖股票的最佳时机

leetcode原题链接:买卖股票的最佳时机 题目描述 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所…...

CSS调色网有哪些

本文章转载于湖南五车教育,仅用于学习和讨论,如有侵权请联系 1、https://webgradients.com/ Wbgradients 是一个在线调整渐变色的网站 ,可以根据你想要的调整效果,同时支持复制 CSS 代码,可以更好的与开发对接。 Wbg…...

Day10-NodeJS和NPM配置

Day10-NodeJS和NPM 一 Nodejs 1 简介 Nodejs学习中文网:https://www.nodeapp.cn/synopsis.html Nodejs的官网:https://nodejs.org/ 概念:Nodejs是JavaScript的服务端运行环境.Nodejs不是框架,也不是编程语言,就是一个运行环境. Nodejs是基于chrome V8引擎开发的一套js代码…...

线性代数 | 机器学习数学基础

前言 线性代数(linear algebra)是关于向量空间和线性映射的一个数学分支。它包括对线、面和子空间的研究,同时也涉及到所有的向量空间的一般性质。 本文主要介绍机器学习中所用到的线性代数核心基础概念,供读者学习阶段查漏补缺…...

Nios初体验之——Hello world!

文章目录 前言一、系统设计1、系统模块框图2、系统涉及到的模块1、时钟2、nios2_qsys3、片内存储(onchip_rom、onchip_ram)4、串行通信(jtag_uart)5、System ID(sysid_qsys) 二、硬件设计1、创建Qsys2、重命…...

[Linux]理解文件系统!动静态库详细制作使用!(缓冲区、inode、软硬链接、动静态库)

hello,大家好,这里是bang___bang_,今天来谈谈的文件系统知识,包含有缓冲区、inode、软硬链接、动静态库。本篇旨在分享记录知识,如有需要,希望能有所帮助。 目录 1️⃣缓冲区 🍙缓冲区的意义 …...

【Linux操作系统】Vim:提升你的编辑效率

Vim是一款功能强大的文本编辑器,它具有高度可定制性和灵活性,可以帮助程序员和文本编辑者提高编辑效率。本文将介绍Vim的基本使用方法、常用功能和一些实用技巧。 文章目录 1. Vim的基本使用方法:2. 常用功能:2.1 文件操作&#…...

Mybatis-plus 的自动填充策略

当在项目中需要对某些实体类中的公共的属性进行自动填充时,可以使用Mybatis-plus中的自动填充功能。 (1)我们可以在实体类中把要自动填充的类属性加上指定的注解TableField(填写在上面方法时进行填充的枚举类型填充策略&#xff…...

大数据课程G2——Hbase的基本架构

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握Hbase的基本架构; ⚪ 掌握Hbase的读写流程; ⚪ 掌握Hbase的设计与优化; 一、基本架构 1. HRegion 1. 在HBase中,会将一个表从行键方向上进行切分,切分成1个或者多个HRegion。 …...

微信小程序wx.getlocation接口权限申请总结

先附上申请通过截图 插播内容:可代开通,保证通过。wx.getLocation接口(获取当前的地址位置) qq: 308205428 如何申请 当申请微信小程序的wx.getLocation接口权限时,你可以…...

简单游戏截图_可控截取内容1

一个需求 我需要在场景中截取不同层级的截图(如只截模型或只截UI或只截外部相加看到的画面 或全都截或和Shader配合呈现人眼夜视仪热成像的画面切换) 将截图排到列表中,在场景UI中展示出来 如何做 相机要能够看到不同的画面 将当前帧画面存储下来 将存储的画面展示出…...

Vue3_02 创建Vue3.0工程

1.使用 vue-cli 创建 ## 查看 vue/cli 版本,确保 vue/cli 版本在4.5.0以上 vue -V 或 vue --version## 安装或升级你的 vue/cli npm install -g vue/cli## 创建 vue create vue_test## 启动 cd vue-test npm run serve 2.使用 vite 创建 什么是vite?——新一代…...

Arduino ESP 8266 ESPAsyncWebServer AsyncCallbackJsonWebHandler

Arduino-ESP 8266 踩坑(一) ESPAsyncWebServer AsyncCallbackJsonWebHandler 在使用 ESPAsyncWebServer 时 由于我想用 asyncWebServer 通过 application/json POST 请求拿数据, 就翻看了 ESPAsyncWebServer 的 git 文档, 他是这样说的 : //JSON body handling with ArduinoJ…...

Source Insight_突出显示对选定字符的引用

1、突出显示对选定字符的引用 在Source Insight中,当我们选中一个函数或者变量的时候,关于它的所有引用地方都高亮显示,想要实现效果如下。 2、配置方法 (1)点击"Options"→“File Type options...” (2)勾选“Highlight referenc…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

HTML 列表、表格、表单

1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构

React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...

Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程

鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…...

大模型——基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程

基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程 下载安装Docker Docker官网:https://www.docker.com/ 自定义Docker安装路径 Docker默认安装在C盘,大小大概2.9G,做这行最忌讳的就是安装软件全装C盘,所以我调整了下安装路径。 新建安装目录:E:\MyS…...

鸿蒙Navigation路由导航-基本使用介绍

1. Navigation介绍 Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(Navigation的子组件)或非首页显示(Nav…...