linux网络编程epoll内核实现代码分析

news2025/3/1 3:39:17

1、linux内核epoll相关数据结构

1.1、epoll相关数据结构类图

1.2、关键数据结构说明

        socket_wq结构体包含一个__wait_queue_head成员,__wait_queue_head用于连接wait_queue_t链表,对于epoll而言就是连接eppoll_entry;

        eppoll_entry包含一个epitem,epitem包含一个epoll_event以及eventpoll,epoll_event也就是监听的事件以及用户态传递过来的一个额外数据,eventpoll包含等待链表以及就绪的epitem链表,阻塞线程挂在eventpoll的等待链表。

2、epoll代码实现

2.1、eppoll_entry加入到socket_wq等待链表(epoll_ctl)

        epoll_ctl系统调用为SYSC_epoll_ctl,SYSC_epoll_ctl调用ep_ptable_queue_proc创建并初始化eppoll_entry,然后加入到socket_wq。

         SYSC_epoll_ctl系统调用栈:

 2.2、阻塞任务添加到eventpoll等待链表(epoll_wait)

        epoll_wait系统调用为SyS_epoll_wait,SyS_epoll_wait调用ep_poll,ep_poll调用ep_events_available检查是否有就绪的事件,如果没有就绪的事件,则调用__add_wait_queue_exclusive将当前线程加到eventpoll的等待队列。

2.3、任务切换(schedule) 

        当前线程加到eventpoll的等待队列之后,"循环"等待事件,等待过程可能被其他操作唤醒,所以唤醒之后不一定有就绪事件,所以for循环调用ep_events_available再次检查是否有就绪事件,并检查timed_out是否超时;在任务进入睡眠之前调用signal_pending检查是否有挂起的信号要处理,如果有信号要处理,那么不能进入睡眠状态,需要先处理挂起的事件;如果没有就绪事件也没有超时,另外也没有挂起的事件,那么调用schedule_hrtimeout_range进行任务切换。

         epoll_wait内核调用栈:

         schedule_hrtimeout_range检查是否有传递超时时间,如果没有超时时间,那么不需要启动超时定时器直接调用schedule,schedule保存当前阻塞任务的上下文,然后选择下一个就绪任务执行。

         调用switch_to切换任务上下文:

        切换调用栈:

 

3、socket可读事件处理

3.1、tcp收到数据(sock_def_readable)

        tcp协议栈收到数据之后调用sock_def_readable检查是否有等待任务;sock_def_readable调用skwq_has_sleeper检查socket等待链表是否不为空(这里的等待链表不是阻塞的任务),如果等待链表不为空,调用wake_up_interruptible_sync_poll唤醒等待链表。

3.2、监听事件检查 

        等待链表的回调函数为ep_poll_callback,sock_def_readable最终调用ep_poll_callback,ep_poll_callback检查epitem的event.events是否有poll任何事件,如果没有poll任务事件,那么不需要处理。

        检查是否有监听当前的事件,如果没有监听那么也不需要处理。

         检查epitem是否已经在rdllink就绪链表里面,如果已经在就绪链表里面,不需要再次加入就是链表,如果不在,那么调用list_add_tail将epitem添加到eventpoll的就绪链表rdllist。

 3.3、唤醒阻塞任务

        将就绪的epitem添加到就绪链表之后,调用epitem检查eventpoll的等待链表是否有阻塞的任务。

         eventpoll的等待链表有阻塞任务,调用wake_up_locked唤醒eventpoll的等待链表任务。

         wake_up_locked最终调用try_to_wake_up唤醒阻塞的任务,try_to_wake_up将阻塞任务的状态更新为TASK_WAKING。

         调用task_waking_fair更新任务的时间片相关时间值,任务睡眠期间没有随系统更新。

        选择唤醒任务运行的线程,调用ttwu_queue将任务添加到目标cpu的就绪任务队列。

         任务放入就绪队列之后,下次被调度将恢复阻塞是的上下文也就是恢复到epoll_wait切换出去的地方继续执行。

4、epoll_wait返回

         sock_def_readable唤醒epoll_wait阻塞的线程之后,阻塞的线程回到epoll_wait继续执行。

4.1、阻塞任务被唤醒继续执行

        阻塞任务唤醒之后,继续执行上下文切换处的代码,schedule_hrtimeout_range内部检查是否是定时器超时导致的唤醒并返回是否超时,如果超时,则设置timed_out为1,否则timed_out为0,如果超时了,后面肯定不能继续阻塞等待事件了,如果因为别的事件导致的任务被唤醒,那么需要继续等待事件。

4.2、检查就是事件及超时

         再次检查是否有就绪事件或者是否超时,如果有就是事件或者超时,那么break退出循环,不再阻塞等待。

 4.3、将当前任务从等待队列移除

        有就绪事件或者等待超时,将当前任务从eventpoll等待队列删除并更新当前任务的状态为TASK_RUNNING。

 4.4、检查获取就绪事件链表

调用ep_events_available检查rdllist是否有就绪epitem,如果有就绪事件,调用ep_send_events获取的事件链表。

        ep_send_events调用ep_scan_ready_list将就绪事件拷贝到用户态的结果里面。

         函数调用栈:

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

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

相关文章

第七届信息类研究生学术论坛参赛有感

因为疫情不仅感叹时光飞逝,上了大半年的网课再次回到校园已经有师弟师妹了。今年的研究生学术论坛更卷了,入围了88项作品。这次科研作品征集研究生在学期间信息类相关研究成果,鼓励实物参展,包括软件系统、硬件系统等,…

Kubernetes(k8s)CNI(Calico)网络模型原理

文章目录一、概述二、Calico 架构和核心组件三、什么是BGP?三、Calico 两种网络模式1)IPIP 模式2)BGP 模式四、安装Calico插件1)通过helm安装Calico2)通过yaml文件安装3)k8s flannel网络切换calico1、卸载f…

适配不同场景的RestTemplate

一个基本实现 如果项目里可能只是偶尔通过一个url,发起一个http请求,一个基本实现如下: Configuration public class RestTemplateConfiguration {Beanpublic RestTemplate restTemplate() {RestTemplate restTemplate new RestTemplate()…

项目常遇到的问题

这里写自定义目录标题1:uniapp生成二维码2:uniapp onShow接收参数3:javascript如何获取对象的key和value4:uni-app:页面直接传递复杂参数5:js对于数组元素相同的分类方法1:uniapp生成二维码 选择…

关联式容器(Associative Container)

1:什么是关联式容器&#xff1f; 关联式容器依照特定的排序准则 自动为元素排序 元素可以是任何类型的value 也可以是 key/value pair key可以是任何类型 映射至一个相关value 而value也可以是任意类型 通常是所有容器默认以<进行比较 也可以通过自己的比较函数 定义出不同的…

Dubbo基础

目录 什么是 RPC 那为什么要有 RPC&#xff0c;HTTP 不好么&#xff1f; RPC 的原理是什么? 如何设计一个 RPC 框架 从底向上的思路 服务消费者 服务提供者 注册中心 监控运维 小结一下 简单实现一个 RPC 框架 Dubbo 简介 Dubbo的历史 Dubbo的功能 为什么要用 …

Java语法之继承

上次给大家分享了Java的封装&#xff0c;今天小编给大家分享面向对象三大特性的第二大特性&#xff0c;也就是继承&#xff0c;fighting~~ 目录 &#x1f384;一.继承的概念 &#x1f384;1.1为什么需要继承 &#x1f384;1.2继承的概念 &#x1f384;1.3继承的语法 &#…

Android App开发中补间动画的讲解以及实现钟摆动画效果实战(附源码 简单易懂 可直接使用)

需要图片集和源码请点赞关注收藏后评论区留言~~~ 一、补间动画的种类 Android提供了补间动画&#xff0c;它允许开发者实现某个视图的动态变换&#xff0c;具体包括四种动画效果&#xff0c;分别是灰度动画&#xff0c;平移动画&#xff0c;缩放动画和旋转动画。因为开发者提供…

缓存穿透、缓存击穿、缓存雪崩区别和解决方案

生命无罪&#xff0c;健康万岁&#xff0c;我是laity。 我曾七次鄙视自己的灵魂&#xff1a; 第一次&#xff0c;当它本可进取时&#xff0c;却故作谦卑&#xff1b; 第二次&#xff0c;当它在空虚时&#xff0c;用爱欲来填充&#xff1b; 第三次&#xff0c;在困难和容易之…

【c++】类和对象

目录 1.面向过程和面向对象初步认识 2.类的引入 3.类的定义 3.1类的两种定义方式&#xff1a; 4.类的访问限定符及封装 4.1访问限定符 5.类的作用域 6.类的实例化 7.类对象模型 7.1 如何计算类对象的大小 8.this指针 8.1 this指针的引出 8.2 this指针的特性 9.类的6个默认成员函…

深度学习简介及反向传播

Datawhale开源学习&#xff0c;机器学习课程&#xff0c;项目地址&#xff1a;https://github.com/datawhalechina/leeml-notes 之前学习机器学习的时候&#xff0c;总结了三步&#xff1a; define a set of functiongoodness of functionpick the best function 这三步所做的…

机器学习之决策树【西瓜书】

当一个有经验的老农看一个瓜是不是好瓜时&#xff0c;他可能会先看下瓜的颜色&#xff0c;一看是青绿的&#xff0c;心想有可能是好瓜&#xff1b;接着他又看了下根蒂&#xff0c;发现是蜷缩着的&#xff0c;老农微微点头&#xff0c;寻思着五成以上是好瓜&#xff1b;最后他又…

基于51单片机的客车辆超载报警Proteus仿真

资料编号&#xff1a;111 下面是相关功能视频演示&#xff1a; 111-基于51单片机的客车辆超载报警Proteus仿真&#xff08;源码仿真原理图全套资料&#xff09;功能如下&#xff1a; 利用单片机设计一个超载检测控制电路。 通过 2 组红外对管(类似电路模拟)检测上车人数和下车…

Flink-水位线的设置以及传递

6.2 水位线 6.2.1 概述 分类 有序流 无序流 判断的时间延迟 延迟时间判定 6.2.2 水位线的设置 分析 DataStream下的assignTimstampsAndWatermarks方法&#xff0c;返回SingleOutputStreamOperator本质还是个算子&#xff0c;传入的参数是WatermarkStrategy的生成策略 但…

C51 - 中断系统

Contents1> 定义2> 作用3> 组成3.1> 中断系统结构3.2> 8个中断源3.3> 中断向量3.4> 中断优先级4> 原理5> 应用1> 定义 中断&#xff08;interrupt&#xff09;是指&#xff1a; CPU执行某一程序过程中&#xff0c;由于系统内&#xff0c;或外部某…

【操作文件的系统调用】

目录文件操作系统调用的基本库函数打开文件读取文件写入文件关闭文件应用文件操作代码举例文件操作与进程复制的结合先打开文件再复制进程先进程复制&#xff0c;再进行打开文件缓冲区的知识回顾在上一篇讲述僵尸进程的文章中对文件的系统调用做了一点点的代码讲述&#xff0c;…

day08 微服务保护

1、JMeter压力测试 1.1、安装启动 JMeter 依赖于JDK&#xff0c;所以必须确保当前计算机上已经安装了 JDK&#xff0c;并且配置了环境变量。 Apache Jmeter官网下载&#xff0c;地址&#xff1a;http://jmeter.apache.org/download_jmeter.cgi 解压缩即可使用&#xff0c;目…

【Acwing—单源最短路:建图】

y总说&#xff0c;图论题的难点不在于打板子&#xff0c;而是建图的过程 个人觉得&#xff0c;建图的过程分成以下阶段&#xff1a; 1.确定结点的意义 2.确定边权的意义 结点一般都很显然&#xff0c;但是边权的意义我们一般把它设成对答案&#xff08;或需要维护的东西&am…

C++入门知识(二)

最近太忙了&#xff0c;发论文写开题&#xff0c;有两周时间没有学习C了&#xff0c;因为都是抽时间来学习&#xff0c;所以本篇博客也是零零散散的&#xff0c;接下来尽量抽时间吧 目录 六、引用 6.1 引用概念 6.2 引用特性 6.3 常引用 6.4 使用场景 6.5 传值、传引用…

并发编程(一)可见性

【并发编程三大特性】&#xff1a; 可见性 有序性 原子性&#xff08; 较复杂 &#xff09; 【线程的可见性】&#xff1a; 【一个例子认识线程的可见性】&#xff1a; import Utils.SleepHelper; import java.io.IOException;public class T01_HelloVolatile {private sta…