深入理解Linux虚拟内存管理(二)

news2024/11/23 4:22:01

在这里插入图片描述

系列文章目录


Linux 内核设计与实现
深入理解 Linux 内核(一)
深入理解 Linux 内核(二)
Linux 设备驱动程序(一)
Linux 设备驱动程序(二)
Linux 设备驱动程序(三)
Linux设备驱动开发详解
深入理解Linux虚拟内存管理(一)
深入理解Linux虚拟内存管理(二)


文章目录

  • 系列文章目录
  • 第8章 slab分配器
    • 8.1 高速缓存
      • 8.1.1 高速缓存描述符
      • 8.1.2 高速缓存静态标志位
      • 8.1.3 高速缓存动态标志位
      • 8.1.4 高速缓存分配标志位


第8章 slab分配器

   这一章将介绍一种通用的分配器:slab 分配器。它与 Solaris 系统 [MM01] 上的通用内核分配器在许多方面都很相似。Linuxslab 的实现主要是基于 Bonwick[Bon94 ] 的第 1slab 分配器的论文,并进一步做了大量的改进,这在他最近的论文中 [BA01] 有所描述。这一章我们先对 slab 分配器做一个快速的浏览,然后描述所用到的数据结构,并深入讨论 slab 分配器的每一项功能。

   slab 分配器的基本思想是:将内核中经常使用的对象放到高速缓存中,并且由系统保持为初始的可利用状态。如果没有基于对象的分配器,内核将花费更多的时间分配、初始化以及释放一个对象。slab 分配器的目的是缓存这些空闲的对象,保留基本结构,从而能够重复使用它们 [Bon94]。

   slab 分配器由多个高速缓存组成,它们通过双向循环链表连接在一起,称为高速缓存链表。在 slab 分配器中,高速缓存可以管理各种不同类型的对象,如 mm_struct 或者 fs_cache,它们由 struct kmem_cache_s 管理,在后面我们将详细讨论这个结构。高速缓存链表是通过字段 next 链接在一起的。

   每一个高速缓存包括若干 slabslab 由连续的页面帧组成,它们被划分成许多小的块以存放由高速缓存所管理的数据结构和对象。不同数据结构之间的关系如图 8.1 所示。

在这里插入图片描述

   slab 分配器有三个基本目标:

  • 减少伙伴系统分配小块内存时所产生的内部碎片。
  • 把经常使用的对象缓存起来,减少分配、初始化以及释放对象的时间开销。在 Solaris 上的基准测试表明,使用 slab 分配器后速度有了很大的提高 [Bon94]。
  • 调整对象以更好地使用 L1L2 硬件高速缓存。

   为减少二进制伙伴分配器所产生的内部碎片,系统需要维护两个由小内存缓冲区所构成的高速缓存集,它们的大小从 25(32) 字节到 217(131 072) 字节。一个高速缓存集适用于使用 DMA 的设备。这些高速缓存叫作 size-Nsize-N(DMA)N 是分配器的尺寸,而函数 kmalloc()(见 8.4.1 小节)负责分配这些高速缓存。这样就解决了低级页分配器最大的问题。我们将在 8.4 节详细讨论指定大小的高速缓存。

   slab 分配器的第 2 个任务是缓存经常使用的对象。初始化内核中许多数据结构所需要的时间与分配空间所花的时间相当,甚至超过了分配空间所花时间。在创建一个新的 slab 时,一些对象被存放在里面,并且由可用的构造器初始化它们。而在对象释放后,系统将保持它们为初始化时的状态,所以再次分配对象的速度很快。

   slab 分配器的第 3 个任务是充分利用硬件高速缓存。若对象放入 slab 还有剩余的空间,它们就用于为 slab 着色。slab 着色方案试图让不同 slab 中的对象使用不同的硬件高速缓存行。通过将对象放置在 slab 中不同的位移起始处,对象将很可能利用 CPU 中不同的硬件高速缓存行,因此来自同一个 slab 中的对象不会彼此刷新高速缓存。这样,空间可能会因为着色而浪费掉。如图 8.2 所示,从伙伴分配器分配的页面如何存储因对齐 CPU L1 硬件高速缓存而着色的对象。

在这里插入图片描述

   Linux 显然不会试图去给基于物理地址分配的页面帧着色 [Kes91],也不会将对象放在某一特定位置,如数据段 [GAV95]、代码段 [HK97]中,但是 slab 着色方案都可以提高硬件高速缓存行的利用率。在 8.1.5 小节中将深入讨论高速缓存着色。在 SMP 系统中,有另外的方案来利用高速缓存,即每一个高速缓存都有一个小的对象数组,而这些对象就是为每一个 CPU 所保留的。这些内容将会在 8.5 节中进一步讨论。

   在编译的时候,如果设置了选项 CONFIG_SLAB_DEBUGslab 分配器会提供额外的 slab 调试选项。其中提供的两个调试特征称为红色区域和对象感染。在红色区域中,每一个对象的末尾有一个标志位。如果这个标志位被打乱,分配器就会知道发生缓冲区溢出的对象的位置并且向系统报告。创建和释放 slab 时,感染一个对象会将预先定义好的位模(在 mm/slab.c 中定义为 0x5A)填入其中。分配时会检查这个位模,如果被改变,分配器就知道这个对象在之前已经使用过,并把它标记出来。

   分配器中小而强大的 API 如表 8.1 所列。

在这里插入图片描述

8.1 高速缓存

8.1.1 高速缓存描述符

   所有描述高速缓存的信息都存储在 mm/slab.c 中声明的 struct kmem_cache_s 中。它是一个非常大的结构,这里仅描述其中一部分。

struct kmem_cache_s {
/* 1) each alloc & free */
	// 下面这些字段在分配和释放对象时很重要。
	
	/* full, partial first, then free */
	// slabs_ * :在前一节中介绍的三个 slab 链表。
	struct list_head	slabs_full;
	struct list_head	slabs_partial;
	struct list_head	slabs_free;
	// slab 中每一个对象的大小。
	unsigned int		objsize;
	// 一组标志位,决定分配器应该如何处理高速缓存,见 8.1.2 小节。
	unsigned int	 	flags;	/* constant flags */
	// 每一个 slab 中包含的对象个数。
	unsigned int		num;	/* # of objs per slab */
	// 并发控制锁,避免并发访问高速缓存描述符。
	spinlock_t		spinlock;
#ifdef CONFIG_SMP
	// 在前面的章节中描述的为 per-cpu 高速缓存批量分配的对象数目。
	unsigned int		batchcount;
#endif
	
/* 2) slab additions /removals */
	// 从高速缓存中分配和释放 slab 时将用到这些字段。
	
	/* order of pgs per slab (2^n) */
	// slab 以页为单位的大小,每个 slab 占用用 2*fpoder 个连续页面帧,其中分配的大小
	// 由伙伴系统提供。
	unsigned int		gfporder;

	/* force GFP flags, e.g. GFP_DMA */
	// 调用伙伴系统分配页面帧时用到的一组 GFP 标志位,完整列表见 7.4 节。
	unsigned int		gfpflags;
	// 尽可能将 slab 中的对象存储在不同的硬件高速缓存行中。高速缓存着色将在
	// 8.1.5 小节中进一步讨论。
	size_t			colour;		/* cache colouring range */
	// 对齐 slab 中的字节。例如 ,size-X 高速缓存对齐 L1 硬件高速缓存。
	unsigned int		colour_off;	/* colour offset */
	// 这是下一个将使用的着色行,其值超过 colour 时,它重新从 0 开始。
	unsigned int		colour_next;	/* cache colouring */
	kmem_cache_t		*slabp_cache;
	// 这个标志位用于指示高速缓存是否增长。如果设置了该标志位,就不太可能在
	// 处于内存压力的情况下选中该高速缓存以回收空闲 slab。
	unsigned int		growing;
	// 动态标志位,在高速缓存的生命期里动态变化,见 8.1.3 小节。
	unsigned int		dflags;		/* dynamic flags */

	/* constructor func */
	// 为复杂对象提供的构造函数,用以初始化每一个新的对象。这是一个函数指针,可
	// 能为空(NULL)。
	void (*ctor)(void *, kmem_cache_t *, unsigned long);

	/* de-constructor func */
	// 对象的析构函数指针,也可能为空。
	void (*dtor)(void *, kmem_cache_t *, unsigned long);
	// 仅仅初始化为 0,其他的地方都没有用到。
	unsigned long		failures;

/* 3) cache creation/removal */
	// 这两个字段在创建高速缓存时设置。
	
	// 便于识别的高速缓存名称。
	char			name[CACHE_NAMELEN];
	// 指向高速缓存链表中的下一个高速缓存。
	struct list_head	next;
#ifdef CONFIG_SMP
/* 4) per-cpu data */
	// per-cpu 数据,在 8.5 中进一步讨论。
	cpucache_t		*cpudata[NR_CPUS];
#endif
	// 在编译时设置 CONFIG_SLAB_DEBUG 选项时,这些数字才有效。它们都是不重要的计
	// 数器,一般不必关心。读取/proc/slabinfo 里的统计信息时,与其依赖这些字段是否有效,还不
	// 如通过另一个进程检查每个高速缓存里的每个 slab 使用情况。
#if STATS
	// 当前在高速缓存中活动的对象数目。
	unsigned long		num_active;
	// 已经分配的对象数目。
	unsigned long		num_allocations;
	// num_active 的上限。
	unsigned long		high_mark;
	// kmem_cache_grow()的调用次数。
	unsigned long		grown;
	// 该高速缓存被回收的次数。
	unsigned long		reaped;
	// 这个字段从未使用过。
	unsigned long 		errors;
#ifdef CONFIG_SMP
	// 分配器使用 per-cpu 高速缓存的次数。
	atomic_t		allochit;
	// 对 allochit 的补充,是分配器未命中 per-cpu 高速缓存的次数。
	atomic_t		allocmiss;
	// 在 per-cpu 高速缓存中空闲的次数。
	atomic_t		freehit;
	// 对象释放后被置于全局池中的次数。
	atomic_t		freemiss;
#endif
#endif
};

8.1.2 高速缓存静态标志位

   一些标志位在高速缓存初始化时就被设置了,并且在生命周期内一直不变。这些标志位影响到 slab 的结构如何组织以及对象如何存储在 slab 中。这些标志位组成一个位掩码,存储在高速缓存描述符的字段 flag 中。所有的标志位都在 linux/slab.h 中声明。

   有 3 组标志位,第 1 组是内部标志位,仅由 slab 分配器使用,如表 8.2 所列。CFGS_OFF_SLAB 标志位决定 slab 描述符存储的位置。

在这里插入图片描述

   第 2 组在创建高速缓存时设置,这些标志位决定分配器如何处理 slab,如何存储对象。列表如 8.3 所列。

在这里插入图片描述

   第 3 组在编译选项 CONFIG_SLAB_DEBUG 设置后才有效,列表如 8.4 所列。它们决定了对 slab 和对象做哪些附加的检查,主要与新建的高速缓存相关。

在这里插入图片描述

   为了防止调用错误的标志位,mm/slab.c 中定义了 CREATE_MASK,它由所有允许的标志位所组成。在创建一个高速缓存时,请求的标志位会和 CREATE_MASK 作比较,如果使用了无效的标志位,系统将会报告一个错误。

8.1.3 高速缓存动态标志位

   虽然字段 dflag 中只有一个标志位 DFLGS_GROWN,但它却非常重要。该标志位在 kmem_cache_grow() 中设置,这样 kmem_cache_reap() 就就不会选择该高速缓存进行回收。kmem_cache_reap() 将跳过设置了该标志位的高速缓存,并清除该标志位。

8.1.4 高速缓存分配标志位

   这些标志位,与为 slab 分配页面帧的 GFP 页面标志位选项相对应,列表如 8.5 所列。调用者既可以使用 SLAB_* 标志位,也可以使用 GFP * 标志位,但实际上应该仅仅使用 SLAB_* 标志位。它们和 6.4 节中所述的标志位直接对应,所以在这里不再详细讨论。假设存在这些标志位是为了明确不同的作用,在这种情况下 slab 分配器对不同的标志位就要作出不同的响应。而事实上它们没有任何区别。

在这里插入图片描述

   极少部分的标志位可能会传递给构造函数和析构函数,列表如 8.6 所列。

在这里插入图片描述

123

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

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

相关文章

生态系统NPP及碳源、碳汇模拟、土地利用变化、未来气候变化、空间动态模拟实践技术

由于全球变暖、大气中温室气体浓度逐年增加等问题的出现,“双碳”行动特别是碳中和已经在世界范围形成广泛影响。碳中和可以从碳排放(碳源)和碳固定(碳汇)这两个侧面来理解。陆地生态系统在全球碳循环过程中有着重要作…

加盐加密算法

文章目录 为什么需要加密?加盐加密MD5盐值加密Spring Security加盐 为什么需要加密? 从下面的图片中,可以看到用户的密码在数据库中存储时,如果不对密码加密,则是以明文的方式存储的,如果被别人获取到数据…

Mobx和Mobx-react:集中式状态管理

一、Mobx (1) Mobx是一个功能强大,上手非常容易的状态管理工具。 (2) Mobx背后的哲学很简单: 任何源自应用状态的东西都应该自动地获得。只获取与自己相关的数据,不获取无关数据(redux则相反) (3) Mobx利用getter和setter来收集组…

科技兴警,优云「公安一体化安全运维解决方案」亮相2023警博会

日前,第十一届中国国际警用装备博览会(警博会)在北京首钢会展中心成功举办,600余家企业参展,集中展示国内外前沿警用装备及尖端技术,大力推进警用装备现代化。 国内领先的平台级数字化运维软件服务商广通优…

TDengine集群搭建

我这里用三台服务器搭建集群 1、如果搭建集群的物理节点上之前安装过TDengine先卸载清空,直接执行以下4条命令 rmtaos rm -rf /var/lib/taos rm -rf /var/log/taos rm -rf /etc/taos2、确保集群中所有主机开放端口 6030-6043/tcp,6060/tcp,…

flink的几种source来源

简单的总结了flink的几种source来源,可以参考下 package com.atguigu.apitestimport java.util.Propertiesimport org.apache.flink.api.common.serialization.SimpleStringSchema import org.apache.flink.streaming.api.functions.source.SourceFunction import …

涨点技巧:注意力机制---Yolov8引入Resnet_CBAM,CBAM升级版

1.计算机视觉中的注意力机制 一般来说,注意力机制通常被分为以下基本四大类: 通道注意力 Channel Attention 空间注意力机制 Spatial Attention 时间注意力机制 Temporal Attention 分支注意力机制 Branch Attention 1.1.CBAM:通道注意力和空间注意力的集成者 轻量级…

版本控制系统有哪些推荐? - 易智编译EaseEditing

以下是几个常用的版本控制系统(Version Control System)推荐,并对它们进行简单介绍: Git: Git是目前最流行的分布式版本控制系统。它具有高效、灵活和强大的功能,支持快速的代码提交、分支管理、合并操作…

高频面试八股文原理篇(五)索引相关

目录 索引的优缺点 MySQL索引类型 索引原理 常见索引类型 MySQL数据库要⽤B树存储索引⽽不⽤红⿊树、B树、 Hash的原因 怎么验证 MySQL 的索引是否满足需求 聚簇索引和非聚簇索引 索引的优缺点 索引的优点 可以大大加快数据的检索速度,这也是创建索引的最主…

蚂蚁Ant Design组件库的免费在线资源

Ant Design(蚂蚁组件)是蚂蚁集团体验技术部经过大量项目实践和总结,逐步打磨出的一个设计系统,内含带有 React 的 UI 库。它是为企业级产品设计而创建的。Ant Design 提供了高质量的交互界面设计组件和演示。作为 UI 设计师&#…

Spring:Spring框架结构 ②

一、结构体现的价值 1、可读性强。 2、可维护性。 3、优秀的框架均具有分而治之的思想。清晰的设计、合理的归类、模块化是走向优秀框架的基础性武器。 二、Spring框架的模块划分 1、整体轮廓 Spring框架包含的功能大约由20个小模块组成。这些模块按组可分为核心容器(Core Co…

独立、相关、正交

文章目录 【1. 独立】【2. 相关】【3.正交】【4. 相互关系】相关和独立相关和正交独立和正交独立、不相关和正交小结 【5. 参考文献】 【1. 独立】 独立:对于两个随机变量 y 1 y_1 y1​ 和 y 2 y_2 y2​,若 y 1 y_1 y1​ 的有关信息不给出 y 2 y_2 …

基于AT89C52单片机的无线温度监测设计

点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/87848530?spm1001.2014.3001.5503 源码获取 主要内容: 设计一个温度监测器,温度异常时警报器能够响起,设定初始温度&#xff0…

0基础学习VR全景平台篇第33章:场景功能-嵌入标尺

功能位置示意 一、本功能将用在哪里? 嵌入功能可对VR全景作品嵌入【图片】【视频】【文字】【标尺】四种不同类型内容; 本次主要带来标尺类型的介绍,可对VR全景作品中,位置信息较多的场景进行标注,在单场景中植入更多…

R-Meta分析与【文献计量分析、贝叶斯、机器学习等】多技术融合实践

Meta分析是针对某一科研问题,根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法,对来源不同的研究成果进行收集、合并及定量统计分析的方法,最早出现于“循证医学”,现已广泛应用于农林生态,资源环境等方面。…

linux守护进程简单创建

1.什么是守护进程? 守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引 导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。 用户使守护进程独立…

平行云X火山引擎:探索XR观展的极致体验

5月20日,素有艺术界“奥林匹克”之称的第18届威尼斯国际建筑双年展(以下简称“威尼斯双年展”)中国国家馆展览正式开幕。 威尼斯双年展为当今世界规模最大、最具影响力的国际艺术盛事之一,中国文化和旅游部自2005年起主办中国国家…

六一儿童节海外网红营销指南:出海品牌的增长秘诀

六一儿童节作为全球范围内备受关注的节日之一,为孩子们提供了欢乐和庆祝的机会。对于出海品牌来说,利用六一儿童节进行海外网红营销不仅可以吸引年轻消费者的关注,还能够增加品牌的知名度和影响力。根据行业研究机构Statista的数据&#xff0…

第十三章行为型模式—模板模式

文章目录 模板模式解决的问题结构实例存在的问题适用场景 JDK源码 - InputStream 行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为…

hive如何实现oracle的connect by prior函数

Hive中如何实现层级查询 类似oracle中 connect by prior 实现的效果? - 知乎 大佬写的很详细,有兴趣自己看,但是存在一个问题 create table test.emp ( empno string, ename string, job string, mgr strin…