红黑树下岗,内核新数据结构上场:maple tree!

news2024/11/24 1:13:31

 

在外界看来,Linux 内核的内部似乎变化很少,尤其是像内存管理子系统(memory-management subsystem)这样的子系统。然而,开发人员时常需要更换内部接口来解决某些长期存在的问题。比如,其中一个问题就是用来保护内存管理里的重要结构的锁的竞争问题,这些重要结构是指页表(page table)和虚拟内存区域(VMA, virtual memory area)等。Liam Howlett 和 Matthew Wilcox 一直在开发一种新的数据结构,称为 "maple tree",希望能取代目前用于 VMA 管理的数据结构。这个改动可能对内核内部结构造成巨大变化,作者已经公布了一个改动很大的 patch set 来召唤 review。

Linux 是一个虚拟内存(virtual-memory)系统。每个进程的地址空间中包含多个虚拟内存区域(VMA),都是由 vm_area_struct 结构表示。每个 vma 都代表一块连续的地址空间,并且这部分区域都是属于相同的内存类型,也就是可以是 anonymous memory(匿名内存,内容并不与某个文件对应)、memory-mapped file(内存映射文件),甚至是 device memory(设备内存)。从进程的角度来看,一个 VMA 区域都是连续的,而实际上底层的物理内存区域可能并不连续。此外,整个地址空间在各个 VMA 之间是有空洞的,当内核需要映射产生一个新的区域时(例如在加载一个库文件或者响应 mmap()调用时),内核就会从这些空洞分配出虚拟空间从而利用起来(当然还是会预留一些未映射的 "guard" page,有利于减少缓冲区溢出的危害)。

我们的系统中几乎所有工作都涉及到内存,所以对这些表示 VMA 的结构的操作必须要快。这些操作包括 lookup(查找,也就是找出哪个 VMA 是对应某个虚拟地址的、确认内存是否被 map 过,或者寻找一个空闲区域用于分配新的 VMA),以及修改(例如,增大堆栈空间)。

VMA 目前是通过一个红黑树(rbtree,red-black tree)的变种来管理的,针对红黑树来说增加了一个额外的双向链表,用来让内核遍历某个进程地址空间中的所有 VMA。内核开发者对这种数据结构的不满已经有一段时间了,原因有很多:rbtree 不能很好地支持范围(ranges),难以用 lockless(不需要获取锁)的方式来进行操作(rbtree 需要进行 balance 操作,这会同时影响多个 item),而且 rbtree 遍历的效率很低,这也是为什么需要一个额外的双向链表。

对 VMA 的操作会使用一个 lock 来保护(具体来说是一个 reader/writer semaphore),这个 lock 位于 struct mm_struct 中,此前名为 mmap_sem,2020 年 6 月的 5.8 版本将其改名为 mmap_lock。改名是为了能将对这个 lock 的操作都用 API 包装起来,希望将来替换的时候方便。

用户经常会碰到争抢这个 lock 的情况,尤其是那些在大型系统中使用多线程应用的用户。内核开发者已经多次讨论过这个问题,在 2019 年的 Linux Storage, Filesystem, and Memory-Management Summit (LFSMM) 峰会上至少有三次讨论过这个问题。问题的核心是,许多操作都需要获取 lock,这包括几乎全部的涉及 page table 和 VMA 的操作。还有其他一些相关的结构事实上也被 mmap_lock 地保护起来(麻烦的是相关文档也是缺失的)。开发者们在做的事情除了将不相关的结构从 mmap_lock 保护下拆分出来之外,还在考虑使用一个结构能允许 VMA 的访问变成 lockless 模式,或者使用某种类型的 range lock。当时有人提出了 maple tree 结构作为解决方案之一,但当时 maple tree 还处于早期开发状态,代码还没有完成。

相关视频推荐

5种红黑树的用途,从应用到内核场景的优缺点

红黑树、最小堆、时间轮、跳表多种方式实现定时器

7个方面讲解c/c++后端开发技术,让你对技术不再迷茫

免费学习地址:c/c++ linux服务器开发/后台架构师

需要C/C++ Linux服务器架构师学习资料加qun579733396获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

 

Introducing maple trees

maple tree(取这个名字可能是借用了枫叶的形状,意指能走向多个方向)与 rbtrees 有根本性的差异。它们属于 B-tree 类型(
https://en.wikipedia.org/wiki/B-tree),也就是说它们的每个节点可以包含两个以上的元素,leaf node(叶子节点)中最多包含 16 个元素,而 internal node(内部节点)中最多包含 10 个元素。使用 B-trees 也会导致很少需要创建新的 node,因为 node 可能包含一些空余空间,可以随着时间的推移而填充利用起来,这就不需要额外进行分配了。每个 node 最多需要 256 字节,这是常用的 cache line size 的整数倍。node 中增加的元素数量以及 cache-aligned size 就意味着在遍历树时会减少 cache-miss。

maple tree 对搜索过程也有改进,同样是来自于 B-tree 结构特点。在 B-tree 中,每个 node 都有一些 key 键值,名为 "pivot",它会将 node 分隔成 subtree(子树)。在某个 key 之前的 subtree 只会包含小于等于 key 的数据,而这个 key 之后的子树只包含大于 key 的值(并且小于下一个 key 值)。

当然,maple tree 的设计中也是按照 lockless 方式的要求来的,使用 read-copy-update (RCU) 方式。maple tree 是一个通用结构,可以用在内核的不同子系统中。第一个用到 maple tree 的地方就是用来替换 VMA 管理中用到的 rbtree 和双向链表。作者之一 Liam Howlett 在一篇博客中解释了设计由来(
https://blogs.oracle.com/linux/the-maple-tree)。

Maple tree 提供了两组 API:一个是简单 API ,一个是高级 API。简单 API 使用 mtree_前缀来标记相关功能,主结构 struct maple_tree 定义如下:

struct maple_tree {
  spinlock_t    ma_lock;
  unsigned int  ma_flags;
  void __rcu    *ma_root;
};

需要静态初始化(static initialize)的话,可以使用 DEFINE_MTREE(name) 和 MTREE_INIT(name,flags),后者会的 flags 目前只定义了两个 bit 选项,其中 MAPLE_ALLOC_RANGE 表示该树将被用于分配 range,并且需要把多个分配区域之间的空间(gap)管理起来;MAPLE_USE_RCU 会激活 RCU mode,用在多个 reader 的场景下。mtree_init() API 也使用相同的 flags,不过是用在动态初始化(dynamic initialization)场景:

void mtree_init(struct maple_tree *mt, unsigned int ma_flags);

开发者可以用这个函数来 free 整个 tree:

void mtree_destroy(struct maple_tree *mt);

可以用三个函数来给树增加条目:mtree_insert()、mtree_insert_range()和 mtree_store_range()。前两个函数只有在条目不存在的情况下才会添加,而第三个函数可以对现有的条目进行覆盖。它们的定义如下:

int mtree_insert(struct maple_tree *mt, unsigned long index,
                 void *entry, gfp_t gfp);
int mtree_insert_range(struct maple_tree *mt, unsigned long first,
                       unsigned long last, void *entry, gfp_t gfp);
int mtree_store_range(struct maple_tree *mt, unsigned long first,
                      unsigned long last, void *entry, gfp_t gfp);

mtree_insert()的参数 mt 是指向 tree 的指针,index 就是 entry index,entry 是指向一个条目的的指针,有必要的话可以利用 gfp 来指定新增 tree node 的内存分配参数(memory allocation flag)。mtree_insert_range() 会利用给出的 entry 数据来插入从 first 到 last 的一个 range 范围。这些函数成功时返回 0,否则返回负值,如果返回-EEXIST 就表示 key 已经存在。mtree_store_range()与 mtree_insert_range()接受的参数相同,不同的是,它会替换相应 key 的任何现有条目。

有两个函数可以用来从 tree 中获取一个条目或删除一个条目:

void *mtree_load(struct maple_tree *mt, unsigned long index);
void *mtree_erase(struct maple_tree *mt, unsigned long index);

要读取一个条目的话,可以使用 mtree_load(),它的参数是一个指向 tree 的指针 mt ,以及所要读取的数据的键值 index。该函数会返回一个指向该条目的指针,如果在 tree 中没有找到键值,则返回 NULL。mtree_erase() 也是同样的语法,用于从 tree 中删除一个 entry。它会从 tree 中删除给定的 key,并返回相关的 entry,如果没有找到,则返回 NULL。

简单的 API 不止上面这些,还有比如 mtree_alloc_range() 可以用来从 key space 中分配一个 range。而高级 API (用 mas_ 前缀标记出来了) 则额外增加了遍历整个 tree 的迭代函数,以及使用 state variable 来访问后一个或者前一个元素。通过这种细粒度的操作,开发者就可以根据需要来恢复中断了的搜索。还有供开发人员找到空闲区域或者对 tree 进行复制操作的 API。

Replacing the VMA rbtree (and more)

patch set 中不仅仅是引入了 maple tree。着重需要指出的是,这组 patch set 中有很大一部分是增加修改测试代码,考虑到这个改动会带来的巨大影响,以及新的数据结构在未来的重要性,这些测试代码是非常值得鼓励的。

这组 patch set 中有 70 个 patch 将 VMA 的所有操作中的 rbtree 操作换成了 maple tree,其中一个 patch 彻底在 VMA 中禁用了 rbtree。patch set 中另一部分代码移除了 VMA 里的双向链表。这个改动需要修改内核中所有直接地使用了 VMA 链表的代码:体系架构相关代码,core dump 代码,program 加载代码,一些设备驱动程序等,当然还有 memory-management 代码。patch set 里还删除了 VMA cache(用来跟踪每个进程最近访问过的 VMA,从而加快 lookup 速度),这是因为使用 maple tree 实现后速度更快,不再需要 VMA cache 了。

Patch set 的第一封邮件中还包括了一些性能数据 ,不过结果有些难以理解。一些 microbenchmark 的结果说明性能提升了,而其他一些(数量较少)则说明性能下降了。编译内核的时间与 5.10 内核本身相类似,只是多执行了几条指令(可能与添加的代码有关)。Howlett 希望大家给些建议如何对这些结果进行更深入的分析。

Current status and next steps

目前 Maple tree 还处于 RFC 阶段,有一些缺点。比如说,目前的实现不支持 32 位系统或 non-MMU 的平台。不过,这些代码已经可以实际用起来了,内核开发者们可以研究一下,从而决定是否符合他们期望的方向(因为这组 patch set 并没有去掉 mmap_lock )。这个 patch set 太大了,可能需要不少时间才能完成 review。

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

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

相关文章

五个程序员必要的在线绘图工具

说到程序员,每个人的第一反应都是敲代码。事实上,画图也是程序员必备的技能之一。各种流程图、架构图、UML类图、线框图等多种多样。 1.即时设计 即时设计是一款免费的在线 UI 设计工具,无系统限制,浏览器打开即可使用&#xff…

算法修炼之练气篇——练气七层

博主:命运之光 专栏:算法修炼之练气篇 前言:每天练习五道题,炼气篇大概会练习200道题左右,题目有C语言网上的题,也有洛谷上面的题,题目简单适合新手入门。(代码都是命运之光自己写的…

Recoil在React中完整实践方案

先让我吐槽一下,Recoil这个玩意文档是真的不友好,另外发现国内很少有人去用Recoil,然后好多文章都是照搬官网文档,我特喵的要是出了问题直接看官方不就行了。如果你碰巧看到这个文章了,就细心看完吧,绝对的…

从一文不值到数字黄金 诞生于极客圈的比特币,究竟经历了什么?

比特币作为技术性很强的神奇发明,从一文不值到数字黄金,在发展过程中不仅为金融范式转变奠定了基础,改变了人们感知和交易价值的方式,也为无数数字资产开辟了一条可追随的道路。 比特币之所以复杂,是因为技术属性、金融…

在线未注册域名批量查询-域名注册批量查询

域名批量注册查询 域名批量注册查询是一种工具,可以帮助用户批量查询并注册多个域名。这种工具通常被域名管理者、品牌专家、互联网营销人员等使用。 以下是域名批量注册查询工具的优点: 提高效率:与手动单独注册域名相比,域名批…

机器学习基础(粗学)【未完待续】

卷积神经网络粗学 卷积:用卷积求系统的存量 卷积,就是把输出函数反转一下。。。。(离谱) 实际不是从物理意义上理解的函数翻转,而是应该从数学意义上,去理解卷积的…

六、IDEAJ同一个服务启动多台服务器的方法

目录 1、打开启动类配置窗口--->选择Edit Configurations进入配置窗口 2、从左侧Springboot应用选择需要启动的多台服务器(服务只要启动一次就会在此窗口有显示)--->勾选Allow parallel run菜单(默认不勾选,则只能启动一台…

【JAVAEE】常见的锁策略

目录 1.常见的锁 1.乐观锁&悲观锁 2.轻量级锁&重量级锁 3.读写锁&普通互斥锁 4.自旋锁&挂起等待锁 5.可重入锁&不可重入锁 6.公平锁&非公平锁 2.CAS 1.什么是CAS 2.CAS的应用 1.实现原子类 2.实现自旋锁 3.synchronized用到的锁策略 1.s…

RobotFramework +appium实现Android自动化

环境准备 1、已安装python37版本(SDK、JDK均已安装完成,且环境变量都配置好了)。 2、已安装robotframework。 3、已安装安卓模拟器(本文使用夜神模拟器)。 4、安装appium(下载地址:http://6…

立创梁山派学习笔记——GPIO输出控制

梁山派 前言开发板简介GD32F407ZGT6官方资源数据手册1.系统框图2. 引脚复用表3.命名规则4.其他 用户手册固件库与PACK包 开发环境搭建立创官方的资料包资料齐活,开发1.工程搭建2.使用寄存器点亮LEDGPIO数量LED的GPIO口GPIO的配置流程GPIO的寄存器1.端口控制寄存器&a…

假如你是一位测试主管,如何判断一名测试工程师是否优秀?

假如你是一位测试主管,去评价一名测试工程师是否优秀,那么你将如何去判断呢?你最看重的是哪方面的能力呢? 对于这个问题,是不能一概而论的,要分为两种情况,情况不同,答案一定是不同…

自媒体素材哪里找?这5个网站告诉你答案。

做自媒体最需要的就是各种视频、配乐、图片等素材了。想要图文好,那就必须要一个好封面图。想要视频好,那就必须要有好的素材和配乐。 那要如何找到这些素材?看这几个网站就够了。 1、菜鸟图库 https://www.sucai999.com/video.html?vNTY…

基于Kubernetes集群构建大中型企业CICD应用平台(1)-- devOps

一、DevOps介绍 软件开发最开始是由两个团队组成: 开发计划由开发团队从头开始设计和整体系统的构建。需要系统不停的迭代更新。 运维团队将开发团队的Code进行测试后部署上线。希望系统稳定安全运行。 这看似两个目标不同的团队需要协同完成一个软件的开发。 …

【游戏逆向】《创世战车》玩家遍历分析

对于这种FPS游戏来说,玩家的血量并不是很关键,不过想分析玩家对象内的其他信息,还是要从血量作为突破口的。 但是由于试驾场是很少有发包的,包括战车的攻击等等,所以只能通过正常匹配战斗进行扫描。又由于匹配模式中没…

局域网会议软件

局域网会议软件怎么选?连通宝视频会议系统,当然也可以从以下维度进行视频会议选择。 1、部署简单方便连通宝视频会议系统部署简单,五分钟部署专业级的视频会议系统,系统支持主流视频会议设备,支持桌面型会议、机顶盒型…

字节面试挂在2面,复盘总结了经验,决定再战一次.....

先说下我基本情况,本科不是计算机专业,现在是学通信,然后做图像处理,可能面试官看我不是科班出身没有问太多计算机相关的问题,因为第一次找工作,字节的游戏专场又是最早开始的,就投递了&#xf…

算法修炼之练气篇——练气十一层

博主:命运之光 专栏:算法修炼之练气篇 前言:每天练习五道题,炼气篇大概会练习200道题左右,题目有C语言网上的题,也有洛谷上面的题,题目简单适合新手入门。(代码都是命运之光自己写的…

【2023 阿里云云计算工程师 ACP 认证练习题库】01、VPC 专有网络题库

目录 一、多选题 1 1 答案与解析 2 2 答案与解析 3 ​3 答案与解析 辑 4 4 答案与解析 5 5 答案与解析 6 ​6 答案与解析 7 7 答案与解析 8 ​8 答案与解析 9 ​9 答案与解析 10 ​10 答案与解析 11 ​11 答案与解析 12 ​12 答案与解析 13 ​13…

HTB靶机011-Node-WP

11-Node 10.10.10.58 1、PortScan 上来端口扫描,masscan扫全端口,nmap快速扫前100端口 ┌──(xavier㉿kali)-[~] └─$ sudo masscan 10.10.10.58 -p1-65535 -e tun0 --max-rate 500┌──(xavier㉿kali)-[~] └─$ sudo nmap -sSV -T4 -F 10.10.10.…

需求、测试用例、BUG、软件的生命周期开发模型(瀑布、螺旋、增量迭代、敏捷)和测试模型(V模型和W模型)【详细介绍】

本篇文章将详细介绍测试中的相关概念(需求、BUG、测试用例)以及常见的开发模型和测试模型。 目录 一、需求 1.需求的定义 2.需求的产生 3.测试人员眼中的需求 练习:将“删除微信聊天记录功能是否正常”的需求拆分成子需求(测…