根据前文高性能网络设计推演中,epoll作为一个“大杀器”为网络开发提供强大的支持。Linux系统上IO多路复用方案有select、poll、epoll。其中epoll的性能表现最优,且支持的并发量最大。本文大概介绍epoll的底层实现。

一、示例引入

了解epoll开发,最基本的暴露给应用层用户开发使用的有三个方法:

  • epoll_create:创建一个 epoll 对象

  • epoll_ctl:向 epoll 对象中添加要管理的连接

  • epoll_wait:等待其管理的连接上的 IO 事件

一个简单的使用流程样例如下:

int main(){listen(lfd, ...);
​cfd1 = accept(...);cfd2 = accept(...);efd = epoll_create(...);
​epoll_ctl(efd, EPOLL_CTL_ADD, cfd1, ...);epoll_ctl(efd, EPOLL_CTL_ADD, cfd2, ...);epoll_wait(efd, ...)
}

二、关键数据结构eventpoll

        对于应用层epoll三个接口方法不再赘述,主要介绍一下eventpoll。其中eventpoll标识了一个epoll,对于一个进程可以管理多个连接fd,然后由epoll实现事件监听,并返回响应。都是围绕eventpoll所完成。以下为eventpoll源码:

/** This structure is stored inside the "private_data" member of the file* structure and represents the main data structure for the eventpoll* interface.*/
struct eventpoll {/** This mutex is used to ensure that files are not removed* while epoll is using them. This is held during the event* collection loop, the file cleanup path, the epoll file exit* code and the ctl operations.*/struct mutex mtx;
​/* Wait queue used by sys_epoll_wait() */wait_queue_head_t wq;
​/* Wait queue used by file->poll() */wait_queue_head_t poll_wait;
​/* List of ready file descriptors */struct list_head rdllist;
​/* Lock which protects rdllist and ovflist */rwlock_t lock;
​/* RB tree root used to store monitored fd structs */struct rb_root_cached rbr;
​/** This is a single linked list that chains all the "struct epitem" that* happened while transferring ready events to userspace w/out* holding ->lock.*/struct epitem *ovflist;
​/* wakeup_source used when ep_scan_ready_list is running */struct wakeup_source *ws;
​/* The user that created the eventpoll descriptor */struct user_struct *user;
​struct file *file;
​/* used to optimize loop detection check */int visited;struct list_head visited_list_link;
​
#ifdef CONFIG_NET_RX_BUSY_POLL/* used to track busy poll napi_id */unsigned int napi_id;
#endif
};
​

对于eventpoll需关注三个关键变量:

1、struct rb_root_cached rbr;

2、struct list_head rdllist;

3、wait_queue_head_t wq;

        通过源码中注释可以了解其中作用:rbr为红黑树,rdllist为就绪队列,wq为等待队列。这是三种数据结构,对应到epoll中的功能而言,rbr为一颗红黑树,他维护了对epoll需要监听的事件集合。rdllist维护了就绪事件集合,当有事件就绪后就会挂到rdllist上通知应用层程序处理。wq为维护的实现epoll线程的阻塞状态。因为epoll_wait执行时,如果没有事件就绪,此时会让出cpu从而阻塞该线程,此时就会将该线程挂到wq上,后续就绪事件来临时就会重新运行该线程。

        对于rdllist和wq都选用队列的数据结构比较好理解,因为此时的场景就是一个处理任务的场景,符合队列“先进先出”的特性。所以选用队列。

        而对于红黑树的选择原因是综合了各方面的最优解。其中对于查询效率,在整个epoll的event中有很多查询场景,所以维护整体事件集合的数据结构需要较高的查询效率,但是对应查询效率更好的还有hashmap。这里就需要综合事件集合的修改以及内存开销这两个问题。对于红黑树不需要连续的内存空间进行存储,而hashmap需要连续的空间,并且对于应用层数量不定的事件内存的开辟大小就是一个问题。如果过小,后续添加就需要重新开辟连续空间并拷贝,如果过大就会导致内存空间的浪费。而且对于事件集合的修改而言红黑树也要更加方便,并且无hash冲突问题。综上红黑树是最优解。

三、具体流程

        对于epoll的实现介绍,本文从应用层角度和内核态角度分别简单介绍,即“三+一“。应用层三个接口实现和内核层一个关键接口实现。(此处并非内核层只有一个接口,而是个人认为十分关键的一个实现,从而能够支持整体epoll的功能实现)

        应用层角度:三个接口:epoll_create、epoll_ctl、epoll_wait

        1、epoll_create:该接口关键功能为初始化eventpoll数据结构,具体为上文提到的rbr、rdllist等。然后返回一个epoll_fd。应用层后续可以通过该句柄实现对epoll的操作。

        2、epoll_ctl:根据操作的不同(增加、删除、修改)对epitem节点进行操作。epitem节点标识了一个监听的句柄的某个事件。其中EPOLL_CTL_ADD为添加,最重要的是建立socket句柄与epoll的关联,即注册ep_poll_callback回调函数到sock->sk_wq。并将eptime挂到socket->wq->wait_queue_head上。后续当socket句柄可读或者可写时,会执行该回调函数以通知eventpoll,将该epitem挂到rdllist队列,如果此时epoll线程是阻塞的话也会将该线程从wq中唤醒。

        3、epoll_wait:该操作会遍历rdllist就绪队列,如果就绪队列有就绪事件,则正常返回由应用层进行处理。否则会阻塞当前线程并将线程挂到eventpoll->wq上,然后让出CPU使用进入阻塞态。

        4、当数据来临时,数据由网卡->网卡驱动->Linux内核协议栈(ip、tcp/udp等)调用sock_def_wakup唤醒该sock的wait_queue上的eptime,然后回调ep_poll_callback。由回调函数将epitme挂到eventpoll->rdllist,如果之前epoll_wait阻塞了当前线程,则一并唤醒当前线程。

        5、ep_send_events实现从eventpoll->rdllist中取出就绪事件,并返回应用层event数组。后续由应用层处理就绪事件。

更多内容可参考:0voice · GitHub 

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

协议转换赋能光伏制造:DeviceNET转PROFINET网关的通信质检实践

协议转换赋能光伏制造:DeviceNET转PROFINET网关的通信质检实践 某光伏电池片生产线创新性地将网关作为计算节点,通过搭载DeviceNET-PROFINET智能网关-稳联技术WL-PN-DVNM,在协议转换层直接运行AI质检模型。DeviceNET端采集的高清图像数据经网…

学习永无止境

已掌握以下每个,有属于自己的一套架构方式: vue.element-ui:后台管理 vue.uni-app:H5,小程序,Android,IOS php:​​RESTful,服务,业务逻辑(如电商…

永磁无刷电机旋转原理

目录 1. 磁场的基本知识 2. 角速度,线速度,工程转速 3.力和力矩 4. 惯量,转动惯量 5. 电机的四种状态 5.1 空载 5.2 带载 5.3 满载 5.4 堵转 6. 功和功率 1. 磁场的基本知识 无头无尾,转了一圈,就叫有旋…

Ubuntu 物理桌面远程访问教程(基于 RealVNC / mstsc)

Ubuntu 物理桌面远程访问教程(基于 RealVNC / mstsc) 适用对象:任意安装了 GNOME GDM 的 Ubuntu 系统 目标:远程连接系统默认物理桌面 :0,无虚拟桌面、无 Xfce,真实 GNOME 桌面环境 1. 准备条件 Ubuntu 系…

Vue3 工程化实战

Vue3 工程化实战 引言:构建工具的演进与选择 在前端工程化领域,构建工具的选择直接影响开发效率与项目性能。随着Vue3的普及,构建工具生态也发生了显著变化:传统vue-cli逐渐进入维护模式,而新一代构建工具Vite凭借其…

调用phantomjs(前端)插件生成ECharts图片

package com.demo.common.utils; //json格式化工具,可以其他工具类 import cn.hutool.json.JSONUtil; import lombok.extern. public class FileUtil { /** * 调用phantomjs(前端)插件生成ECharts图片 * @param path 根路径 * @param option ECharts配置J…

React Hooks详解

React Hooks 常考内容 React Hooks 是 React 16.8 引入的重要特性,用于在函数组件中使用状态和其他 React 特性。以下是面试中常考的核心内容: 基础 Hook useState: 用于管理组件内部状态,返回状态变量和更新状态的函数。useEffect: 处理副…

c++17标准std::filesystem常用函数

std::filesystem 是 C17 引入的标准库&#xff0c;用于处理文件系统操作&#xff0c;提供了跨平台的文件和目录操作能力。以下是一些常用的函数和类&#xff1a; 一、路径操作&#xff08;std::filesystem::path&#xff09; cpp 运行 #include <filesystem> namespa…

非结构化文档的自动化敏感标识方法技术解析

在数字化时代&#xff0c;企业与组织面临的数据形态正发生深刻变革。据统计&#xff0c;非结构化数据占企业数据总量的 80% 以上&#xff0c;涵盖文本、邮件、PDF、日志、社交媒体内容等多种形式。这些数据中往往蕴含着大量敏感信息&#xff0c;如个人身份信息、商业机密、医疗…

c语言中的字符类型

字符类型 char char是一种整数&#xff0c;也是一种特殊的类型&#xff1a;字符。 #include <stdio.h> int main(){char c,d;c 1; //把整数1赋值给变量cd 1; //把字符‘1’赋值给变量dif (c d){printf("相等");}else{printf("不相等\n");…

Cribl stream 管道对时间的改变时区

先说一下时区的重要性&#xff0c;要是cribl 时区是UTC&#xff0c;但是过来数据是GTM8 就是中国时区&#xff0c;那么数据过来&#xff0c;就可能在后端的Splunk 没有显示&#xff0c;那么解决这个问题&#xff0c;cribl 管道引入了auto timestamp 的功能&#xff1a; 注意到&…

深度学习:PyTorch卷积神经网络(1)

本文目录&#xff1a; 一、CNN概述二、CNN日常应用三、CNN的卷积层&#xff08;一 &#xff09;基本介绍&#xff08;二&#xff09;卷积层计算1.对输入数据的要求2.卷积核核心参数3.计算过程4.特征图尺寸计算5.1、多通道卷积计算5.2、多卷积核计算6.PyTorch卷积层API 前言&…

linux网络编程socket套接字

套接字概念 Socket本身有“插座”的意思&#xff0c;在Linux环境下&#xff0c;用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件。 既然是文件&#xff0c;那么理所当然的&#xff0c;我们可以使用文件描述符引用套接字。与管道类似的&#xff0c;L…

Python 数据分析与可视化 Day 5 - 数据可视化入门(Matplotlib Seaborn)

&#x1f3af; 今日目标 掌握 Matplotlib 的基本绘图方法&#xff08;折线图、柱状图、饼图&#xff09;掌握 Seaborn 的高级绘图方法&#xff08;分类图、分布图、箱线图&#xff09;熟悉图像美化&#xff08;标题、标签、颜色、风格&#xff09;完成一组学生成绩数据的可视化…

CephFS “Client Failing to Respond to Cache Pressure“ 告警分析

告警含义 当出现 Client failing to respond to cache pressure 警告时,表明: 元数据服务器 (MDS) 要求客户端释放缓存的元数据(如 inode Capabilities)客户端未能及时响应 释放请求核心触发机制 MDS 通过以下周期性流程管理缓存 阶段操作触发条件Cache Trim 周期每隔 mds…

生成式人工智能实战 | 生成对抗网络(Generative Adversarial Network, GAN)

生成式人工智能实战 | 生成对抗网络 0. 前言1. 生成对抗网络2. 模型构建2.1 生成器2.2 判别器 3. 模型训练3.1 数据加载3.2 训练流程 0. 前言 生成对抗网络 (Generative Adversarial Networks, GAN) 是一种由两个相互竞争的神经网络组成的深度学习模型&#xff0c;它由一个生成…

缓存与加速技术实践-MongoDB数据库应用

一.什么是MongoDB MongoDB 是一个文档型数据库&#xff0c;数据以类似 JSON 的文档形式存储。 MongoDB 的设计理念是为了应对大数据量、高性能和灵活性需求。 MongoDB 使用集合&#xff08;Collections&#xff09;来组织文档&#xff08;Documents&#xff09;&#xff0…

声网对话式AI把“答疑机器人”变成“有思维的助教”

作为一家专注初高中学生的线上教育平台&#xff0c;我们精心打磨的系统化课程收获了不少认可&#xff0c;但课后无人答疑的难题却始终横亘在前。学生课后遇到疑惑&#xff0c;要么只能默默憋在心里&#xff0c;要么就得苦苦等待下一节课&#xff0c;家长们也频繁抱怨 “花了钱&…

常见的排序方法

目录 1. 插入排序 2. 希尔排序 3. 选择排序 4. 堆排序 5. 冒泡排序 6. 快速排序 1. 快速排序的实现 1. 思路&#xff08;以从小到大排序为例&#xff09; 2. 选取基准元素的方法&#xff08;Hoare&#xff09; 3. 选取基准元素的方法&#xff08;挖坑法&#xff09; …

【matlab定位例程】基于AOA和TDOA混合的定位方法,背景为三维空间,自适应锚点数量,附下载链接

文章目录 代码概述代码功能概述核心算法原理AOA定位模型TDOA定位迭代算法混合定位策略关键技术创新 运行结果4个锚点的情况40个锚点的情况 MATLAB源代码 代码概述 代码功能概述 本代码实现了一种三维空间中的混合定位算法&#xff0c;结合到达角&#xff08; A O A AOA AOA&a…