计算机网络【EPoll原理】

预备知识:内核poll钩子原理
内核函数poll_wait

把当前进程加入到驱动里自定义的等待队列上 ;

当驱动事件就绪后,就可以在驱动里自定义的等待队列上唤醒调用poll的进程;

故poll_wait作用:可以让驱动知道事件就绪的时候唤醒哪些等待进程;

钩子poll

内核f_op->poll必须配合驱动自己的等待队列才能用,不然驱动有事件产生后不知道哪些进程调用了poll来等待这个事件。

内核f_op->poll要做的事情。

  • 调用poll_wait,将当前进程放入驱动设备的等待队列上,这样驱动就知道哪些进程在调用poll等待事件。
  • 检查此时立刻已有的事件(POLLIN\POLLOUT\POLLERR…)并返回掩码表示。

f_op->poll是一个非阻塞的操作,立即返回,返回值以掩码形式表示当前已产生的事件集合。

预备知识:等待队列

等待队列对头:wait_queue_head_t ;

队列的成员:wait_queue_t;

wait_queue_t的成员:

void *private; /*指向进程描述符task_struct*/    
wait_queue_func_t  func;//唤醒时调用此函数,即钩子函数    
struct list_head  task_list;//队列链表指针

一般钩子函数func是内核默认函数default_wake_function,功能就是唤醒了进程。

我们也可以在把进程放入等待队列时主动设定钩子函数,使得在唤醒进程时自动执行我们需要的操作。

epoll就利用了队列钩子函数:把产生的事件内容copy到rdlist 。这样,事件来临时会自动把事件内容放到rdlist中,而不需要我们自己遍历监听句柄们查有谁产生了事件。

调用epoll_create1/epoll_create

创建了epoll句柄eventpoll,返回其文件表示的描述符epfd。

img

eventpoll内部有以下关键数据结构:

  • rbtree:红黑树,每个被加入到epoll监控的文件事件会创建一个epitem结构,作为rbtree节点 。

​ 使用rbtree的优点:可容纳大量文件事件,方便增删改(O(logN))。

  • rdlist:内核链表,用于存放当前产生了期待事件产生的文件句柄们(这里的一个文件句柄可以理解为一个epoll_event)。

  • wq:当进程调用epoll_wait等待时,进程加入等待队列wq。

  • poll_wait:eventpoll本身的等待队列,由于eventpoll自己也被当做文件,这个队列用于自己被别人调用select/poll/epoll监听的情况(一般没啥用)。

poll_wait在啥时候用呢:

fd = socket(...);
efd1 = epoll_create();
efd2 = epoll_create();
epoll_ctl(efd1, EPOLL_CTL_ADD, fd, ...);
epoll_ctl(efd2, EPOLL_CTL_ADD, efd1, ...);

如上,efd1监控fd,而efd2监控了efd1,即嵌套的epoll监控:epoll监控另一个epoll句柄

efd2要监控efd1,将调用efd1的poll函数

回忆之前说过:文件f_op->poll需要配合驱动提供的等待队列

对于epollfd,等待队列就是poll_wait

efd2监听efd1,会调用efd1->f_op->poll,于是把当前进程放到efd1的poll_wait队列上

在epoll的内核实现中,当efd1本身监听到fd事件产生后,会顺便唤醒poll_wait上的进程

于是,“efd1监听到事件” 被通知到efd2。这样,就实现了epollfd被其他多路复用监听了!

故:poll_wait就是用于epoll句柄被另外的多路复用监听的,配合epoll自己的f_op->poll,看起来一般用不到

调用epoll_ctl操作句柄新增监控事件

epoll_ctl:EPOLL_CTL_ADD、EPOLL_CTL_MOD、EPOLL_CTL_DEL新增、修改、删除红黑树上的文件句柄。

其中epll_ctl:EPOLL_CTL_ADD新增句柄不仅仅新增红黑树节点,更关键的是对文件开始监控!

与select/poll的本质区别:并不是调用epoll_wait的时候才监听文件,而是EPOLL_CTL_ADD的时候就开始监听了。

epoll_ctl(epfd, EPOLL_CTL_ADD, fd, fdevent)核心流程:
  • 对要注册的事件event->events追加关心事件:EPOLLERR | EPOLLHUP。

​ 回忆epoll的使用中说过:EPOLLERR、EPOLLHUP事件会被自动监听,即使我们没设置。

  • 创建epitem结构,加入到红黑树中。

  • 【关键】revent = file->f_op->poll,即调用poll,把当前进程放到文件的等待队列上且设置回调函数ep_poll_callback,返回值revent是文件当前已产生事件掩码。

  • 检查返回事件:如果revent与关心事件event->events有交集(说明ADD之前事件就准备好了)。

    • 把此epitem节点拷贝到rdlist链表中;(就绪句柄拷贝到rdlist)。
    • 如果有进程在wq等待队列上(即有进程在调用epoll_wait等待),则唤醒之!
    • 顺便,如果有进程在poll_wait等待队列上(即有进程调用多路复用来监听当前epoll句柄),则唤醒之!

可以看到,如果在EPOLL_CTL_ADD一个文件之前,这个文件关心的事件就已经产生了的话,由于会唤醒wq队列上的进程,则此时EPOLL_CTL_ADD会使得epoll_wait函数从阻塞中返回。

img
再说回调函数干了什么

回调函数ep_poll_callback作为等待队列的回调函数:

当文件事件来临,唤醒文件等待队列上进程,ep_poll_callback函数将被自动调用,并把已产生事件们作为其参数传入。

回调函数ep_poll_callback核心流程:

ep_poll_callback检查已产生事件与关心事件是否有交集,如果有:

  • 将文件的epitem节点拷贝到rdlist链表上(就绪句柄拷贝到rdlist)。
  • 如果有进程在wq等待队列上(即有进程在调用epoll_wait等待),则唤醒之!
  • 顺便,如果有进程在poll_wait等待队列上(即有进程调用多路复用来监听当前epoll句柄),则唤醒之!

简而言之:回调函数把文件句柄拷贝到rdlist,并唤醒epoll_wait等待的进程。

当文件有事件来临时:
  1. 对应的等待队列上的进程被唤醒,执行回调函数ep_poll_callback,并把已产生事件们以参数传入;
  2. call ep_poll_callback;

img

简而言之:事件发生时,文件句柄被自动拷贝到rdlist,调用epoll_wait等待的进程们被唤醒。

调用epoll_wait等待事件

epoll_wait并不监听文件句柄,而是等待rdlist不空 or 收到信号 or 超时这三种条件后返回。

主要逻辑:

  1. 不断让出CPU,直到:
    • rdlist有数据;
    • 超时;
    • 收到信号;
  2. 如果rdlist有数据,则拷贝到用户传入的events数组。

img

简而言之:等待rdlist不空或者超时、信号中断,rdlist不空则把句柄们拷贝到用户空间。

拷贝到用户这个环节看边缘触发与水平触发的区别

拷贝句柄函数ep_send_events会先遍历rdlist中每个句柄,对于每个句柄,再次调用poll获取实际事件:

如果与关心事件有交集:

  • 如果句柄是水平触发(EPOLLLT),则再次把句柄加入到rdlist;否则从rdlist中删除。

于是水平模式下次还会准备好,这就是EPOLLET 与 EPOLLLT的区别原理。

  • 如果与关心事件无交集,从rdlist中删除之。

问题:如此一来看起来水平模式的句柄永远都不断重新加入rdlist,这就成永远都通知了吧?

当事件已经被处理完后,调用poll得到的实际事件与关心事件已经无交集了,于是会被删除的!

ep_send_events函数内再次调用poll获取实际事件就是为了EPOLLLT模式而生的,防止其永远加入rdlist!

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

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

相关文章

蛇目标检测数据集VOC格式100张

蛇是一种广泛分布于地球各个角落的爬行动物,是无脚类爬行动物中最为特殊的一类。它们身体长而细长,通常由许多鳞片组成,没有四肢。蛇生活的环境非常多样,可以在沙漠、森林、草原和水域等各种地方找到它们的踪迹。 蛇是以捕食其他…

VS2013中特殊操作

代码段管理器(查看代码补全快捷方式) 1.点击 工具 ->点击 代码片段管理器->看到 语言->选择 Visual C 2.可以点击下方添加 自定义一个属于自己的快捷代码补全方式 3.结果图: 设置自动换行与行号 1.点击 工具->点击 选项->找到 文本编辑器(然后点击)…

百度地图添加坐标点

​​​​​​html <!DOCTYPE html><html xmlns"http://www.w3.org/1999/xhtml"> <head runat"server"><meta http-equiv"Content-Type" content"text/html; charsetutf-8" /><title>查看签到信息-地图…

[蓝桥杯2022省赛] X 图形

X 图形 问题描述 给定一个字母矩阵。一个 X 图形由中心点和由中心点向四个 4545 度斜线方向引出的直线段组成&#xff0c;四条线段的长度相同&#xff0c;而且四条线段上的字母和中心点的字母相同。 一个 X 图形可以使用三个整数r,c,L 来描述&#xff0c;其中 r,c 表示中心点…

stm32中的i2c协议

stm32中I2C 文章目录 stm32中I2CI2C 协议简介I2C物理层协议层I2C基本读写过程 **通讯的起始和停止信号****数据有效性****地址及数据方向****响应** STM32的I2C特性及架构**STM32** **的** I2C外设简介STM32 的 I 2C 架构剖析通讯引脚 通讯过程主发送器主接收器 I2C初始化结构体…

工程(十六)——自己数据集跑Fast_livo

一、基础环境 Ubuntu20.04 ROS noetic PCL 1.8 Eigen 3.3.4 Sophus git clone https://github.com/strasdat/Sophus.git cd Sophus git checkout a621ff mkdir build && cd build && cmake .. make sudo make install 下面两个直接把包下载下来一起编译…

swing快速入门(三十二)消息对话框

注释很详细&#xff0c;直接上代码 新增内容 1.自定义对话框前列图标 2.消息对话框的若干种形式 package swing21_30;import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent;public class swing_test_30 {// 定义一个JFrameJFrame jFrame new JFram…

React 、Vue进度 条首屏加载制作

React 大家都听说过&#xff0c;是一个非常出名的前端 框架 &#xff0c;目前在公司 用的比较多的两个前端框架 &#xff0c;一个是 React , 一个 是 Vue 2 、3 &#xff0c;公司 的首页 &#xff0c;后台 前端部分 都是 以这两个为主 &#xff0c;做了 不下 数十个 项目 但是 …

大数据背后的绿色收割:基于Hadoop的农产品价格信息智能分析

大数据背后的绿色收割&#xff1a;基于Hadoop的农产品价格信息智能分析 引言正文1. 数据获取与准备2. 数据清洗与处理3. Hadoop数据分析引擎的运用4. MySQL数据库的集成5. 创新性的可视化6. 结论与展望 结语 引言 随着信息技术的不断发展&#xff0c;农业领域也在数字化的浪潮…

【2023年终总结】纵是一路仆仆风尘,也莫忘了仰头

文章目录 1. 写在前面2. 关于生活3. 关于工作4. 关于以后 【作者主页】&#xff1a;吴秋霖 【作者介绍】&#xff1a;Python领域优质创作者、阿里云博客专家、华为云享专家。长期致力于Python与爬虫领域研究与开发工作&#xff01; 【作者推荐】&#xff1a;对JS逆向感兴趣的朋…

阿里云2核2G3M服务器放几个网站?

阿里云2核2g3m服务器可以放几个网站&#xff1f;12个网站&#xff0c;阿里云服务器网的2核2G服务器上安装了12个网站&#xff0c;甚至还可以更多&#xff0c;具体放几个网站取决于网站的访客数量&#xff0c;像阿里云服务器网aliyunfuwuqi.com小编的网站日访问量都很少&#xf…

三路电源互备自投电路

当供电源停电时&#xff0c;主备用电源自动投入运行&#xff0c;当主备用电源断电时&#xff0c;则次备用电源自动投入运行&#xff0c;从而大大提高供电的可靠性。

基于three.js的室内全景3D展馆案例分享

先看效果图 实现了第一人称行走&#xff0c;WASD点击目标画册进行预览查看位置音乐播放环绕地面镜面反光碰撞检测等等. 地址在gitee上gallery: 数字展馆概念的demo项目&#xff0c;本项目中使用的技术栈为three.js 有兴趣的伙伴可以去下载看看&#xff0c;有这方面的项目应该能…

Python FastApi连接oracle进行查询

这边技术选型是cx_oracle进行连接查询&#xff0c;cx_oracle的使用首先要有官方的客户端才能连接到数据库&#xff0c;python并不自带客户端。我用是Python3.9 安装客户端 可以到官网在选择最新版进行下载。 Instant Client for Microsoft Windows (x64) 64-bit 或者直接从我…

maven命令行安装依赖测试

mvn dependency:get -DgroupIdorg.springframework -DartifactIdspring-core -Dversion5.3.9作用&#xff1a;可用于测试配置环境变量后&#xff0c;能否下载依赖到本地仓库

【SpringCloud】从实际业务问题出发去分析Eureka-Server端源码

文章目录 前言1.EnableEurekaServer2.初始化缓存3.jersey应用程序构建3.1注册jeseryFilter3.2构建JerseyApplication 4.处理注册请求5.registry&#xff08;&#xff09; 前言 前段时间遇到了一个业务问题就是k8s滚动发布Eureka微服务的过程中接口会有很多告警&#xff0c;当时…

nacos入门篇001-安装与启动

1、下载zip包 我这里下载的是版本2.2.0 Nacos 快速开始 2、修改配置文件 2.1集群模式修改成单例模式 vi startup.sh 2.2 修改数据库配置信息 3、初始化数据库 3.1 创建db名称&#xff1a;db_nacos 3.2 执行mysql-schema.sql 3.3 执行完截图&#xff1a; 4、运行脚本启动 …

实现区域地图散点图效果,vue+echart地图+散点图

1.效果图 2.准备工作,在main.js和index.js文件中添加以下内容 main.js app.use(BaiduMap, {// ak 是在百度地图开发者平台申请的密钥 详见 http://lbsyun.baidu.com/apiconsole/key */ak: sRDDfAKpCSG5iF1rvwph4Q95M6tDCApL,// v:3.0, // 默认使用3.0// type: WebGL // ||API…

【Kubernetes】kubectl 常用命令

kubectl 常用命令 1.基础命令2.部署命令3.集群管理命令4.故障诊断与调试命令5.高级命令6.设置命令7.其他命令 1.基础命令 命令 说明 create通过文件名或标准输入创建 Kubernetes 的资源expose将 Kubernetes 的资源展露为一个服务run在集群中运行一个特定的镜像set修改对象的特…

初识Java并发,一问读懂Java并发知识文集(3)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…