不连续页分配器

不连续页分配器

在设备长时间运行后,内存碎片话,连续的物理页比较稀缺;伙伴分配器和slab块分配器,分配的内存物理上是连续的;在这种情况下,如果需要分配长度超过一页的内存块,可以使用不连续页分配器,分配虚拟地址连续但物理地址不连续的内存块;

编程接口

不连续页分配器提供以下编程接口

  1. vmalloc

分配不连续的物理页并且把物理页映射到连续的虚拟地址空间;

/**
 *	vmalloc  -  allocate virtually contiguous memory
 *	@size:		allocation size
 *	Allocate enough pages to cover @size from the page level
 *	allocator and map them into contiguous kernel virtual space.
 *
 *	For tight control over page level allocator and protection flags
 *	use __vmalloc() instead.
 */
void *vmalloc(unsigned long size);
  1. vfree

释放vmalloc分配的物理页和虚拟地址空间;

/**
 *	vfree  -  release memory allocated by vmalloc()
 *	@addr:		memory base address
 *
 *	Free the virtually continuous memory area starting at @addr, as
 *	obtained from vmalloc(), vmalloc_32() or __vmalloc(). If @addr is
 *	NULL, no operation is performed.
 *
 *	Must not be called in NMI context (strictly speaking, only if we don't
 *	have CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG, but making the calling
 *	conventions for vfree() arch-depenedent would be a really bad idea)
 *
 *	NOTE: assumes that the object at @addr has a size >= sizeof(llist_node)
 */
void vfree(const void *addr);
  1. vmap

把已经分配的不连续物理页映射到连续的虚拟地址空间;

/**
 *	vmap  -  map an array of pages into virtually contiguous space
 *	@pages:		array of page pointers
 *	@count:		number of pages to map
 *	@flags:		vm_area->flags
 *	@prot:		page protection for the mapping
 *
 *	Maps @count pages from @pages into contiguous kernel virtual
 *	space.
 */
void *vmap(struct page **pages, unsigned int count,
			unsigned long flags, pgprot_t prot);
  1. vunmap

释放vamp分配的虚拟地址空间;

/**
 *	vunmap  -  release virtual mapping obtained by vmap()
 *	@addr:		memory base address
 *
 *	Free the virtually contiguous memory area starting at @addr,
 *	which was created from the page array passed to vmap().
 *
 *	Must not be called in interrupt context.
 */
void vunmap(const void *addr);

有了不连续页分配器,在连续物理内存不足的情况下,就可以使用虚拟地址连续、物理地址不连续的内存;所以内核还提供了以下接口:

  1. kvmalloc

先尝试使用kmalloc分配内存块,如果失败,则使用vmalloc分配不连续的物理页;

/*attempt to allocate physically contiguous memory, but upon
 * failure, fall back to non-contiguous (vmalloc) allocation.
*/
void *kvmalloc(size_t size, gfp_t flags);
  1. kvfree

检查内存块是否是通过vmalloc分配的;如果是则使用vfree释放,否则使用kfree;

void kvfree(const void *addr)
{
	if (is_vmalloc_addr(addr))
		vfree(addr);
	else
		kfree(addr);
}

数据结构

不连续页分配器结构如下图:
image.png
每个虚拟内存区域对应一个vmap_area;每个vmap_area关联一个vm_struct;

struct vmap_area

vmap_area和vm_area_struct有什么区别?
vmap_area是内核虚拟地址空间,vm_area_struct是用户空间虚拟地址;

struct vmap_area {
	unsigned long va_start;
	unsigned long va_end;
	unsigned long flags;
	struct rb_node rb_node;         /* address sorted rbtree */
	struct list_head list;          /* address sorted list */
	struct llist_node purge_list;    /* "lazy purge" list */
	struct vm_struct *vm;
	struct rcu_head rcu_head;
};
  • va_start,起始虚拟地址;
  • va_end,结束虚拟地址;
  • flags,如果flags设置了标志位VM_VM_AREA,表示成员vm指向一个vm_struct实例,即vm_area关联一个vm_struct实例;
  • rb_node,红黑树节点,用来把vmap_area实例加入到根节点为vmap_area_root的红黑树中,虚拟地址作为key,提高查找效率;
  • list,链表节点,用来把vmap_area实例加入到头节点为vmap_area_list的链表中,该链表按虚拟地址从小到大排序;

sturct vm_struct

struct vm_struct {
	struct vm_struct	*next;
	void			*addr;
	unsigned long		size;
	unsigned long		flags;
	struct page		**pages;
	unsigned int		nr_pages;
	phys_addr_t		phys_addr;
	const void		*caller;
};

addr,起始虚拟地址;
size,虚拟内存区域的长度;
flags,如果设置了VM_ALLOC,表示虚拟内存区域是使用vmalloc分配的;
pages,表示page指针数组;
nr_pages,页数;
next,指向下一个vm_struct实例;仅在不连续页分配器初始化以前使用;
phys_addr,起始物理地址;仅在不连续页分配器初始化以前使用;

如果虚拟内存区域是使用vmap分配的,vm_struct实例的差别是:成员flags没有设置VM_ALLOC,成员pages是NULL,成员nr_pages是0;
image.png

技术原理

vmalloc虚拟地址空间范围

vmalloc虚拟地址空间的范围是[VMALLOC_START,VMALLOC_END),每种处理器架构都需要定义这两个宏,例如ARM64架构定义如下:

/*
 * VMALLOC range.
 *
 * VMALLOC_START: beginning of the kernel vmalloc space
 * VMALLOC_END: extends to the available space below vmmemmap, PCI I/O space
 *	and fixed mappings
 */
#define VMALLOC_START		(MODULES_END)
#define VMALLOC_END		(PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - SZ_64K)

MODULES_END,内核模块区域的结束地址;
PAGE_OFFSET,线性映射区域的起始地址;
PUD_SIZE,一个页上层目录表项映射的地址空间长度;在页表中进行介绍;
VMEMMAP_SIZE,vmemmap区域的长度;
vmalloc虚拟地址空间的起始地址等于内核模块区域的结束地址;
vmalloc虚拟地址空间的结束地址,等于(线性映射区域的起始地址-一个页上层目录表项映射的地址空间长度-vmemmap区域的长度-64KB);

vmalloc函数执行步骤

函数vmalloc的执行过程分为3步:

  1. 分配虚拟内存区域;

分配vmap_area实例和vm_struct实例;之后遍历vmap_area_list,在两个相邻vmap_area之间找到一个足够大的空洞,如果找到了,把起始虚拟地址和结束虚拟地址保存在新的vmap_area实例中,将新的vmap_area加入到vmap_area_list中;并把它加入到红黑树中;最后把新的vmap_area实例关联到vm_struct实例中;

  1. 分配物理页;

vm_struct实例的成员nr_pages存放页数n;分配page指针数组,数组的长度是n,vm_struct实例的成员pages指向page指针数组;之后连续执行n次如下操作:从页分配器(伙伴分配器)分配一个物理页,把物理页对应的page实例的地址存放到page指针数组中;

  1. 在内核的页表中把虚拟页映射到物理页;

内核的页表就是0号线程的页表;0号内核线程的进程描述符是全局变量init_task,成员active_mm指向全局变量init_mm,init_mm的成员pgd指向页全局目录swapper_pg_dir;

函数vmap和函数vmalloc的区别仅仅在于不需要分配物理页;

linux中常用内存分配函数

用户空间

malloc/calloc/realloc/free

glibc提供的标准接口;申请的内存,虚拟地址连续,物理地址不一定连续;从堆中申请内存,使用系统调用为brk/mmap;

mmap/munmap

场景:将文件利用虚拟内存技术映射到内存当中,直接操作内存,提供文件访问速度;

brk/sbrk

brk也用于内存映射,通常用于调整堆内存的大小;

内核空间

_get_free_page/_get_free_pages

伙伴系统,页分配器,分配的内存物理页是连续的;

kmalloc/kcalloc/kfree

slab,块分配器,基于伙伴系统管理小块内存,分配的内存物理页是连续的;分配小块内存,大小有限,不如vmalloc大;

vmalloc/vfree

不连续页分配器,分配的内存虚拟地址连续,物理地址不连续;从vmalloc区分配内存;能分配大块内存;

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

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

相关文章

LeetCode-17. 电话号码的字母组合【哈希表 字符串 回溯】

LeetCode-17. 电话号码的字母组合【哈希表 字符串 回溯】 题目描述:解题思路一:回溯三部曲:解题思路二:回溯解题思路三: 题目描述: 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组…

【JavaSE】反射

Java代码的生命周期 Java代码在计算机中经历的阶段:Source源代码阶段、Class类对象阶段、RunTime运行时阶段。 Source源代码阶段: 这个阶段是由程序员编写生成源代码,再由Javac编译器生成class文件。 Class类对象阶段:由类加载器将class文件加载到JVM内…

【保姆级教程】如何订阅OnlyFans?如何在OnlyFans上面支付?OnlyFans虚拟卡订阅教程

1. 引言 什么是OnlyFans:OnlyFans是一种内容订阅服务,成立于2016年,允许内容创作者从用户那里获得资金,用户需要支付订阅费用才能查看他们的内容。它在多个领域受到欢迎,包括音乐、健身、摄影,以及成人内容…

C语言之指针(4)使用并模拟实现qsort

冒泡排序有局限性,实现时间长而且只能进行整型数据的排序,接下来介绍模拟实现qsort来方便实现各种数据的排序。 函数基本形式: 可以看到该函数有四个参数,第四个参数是一个函数指针,这个指针指向的函数第一个参数和第…

数据分析——数据规范化

数据规范化是数据分析中的一个重要步骤,其目的在于确保数据的一致性和可比性,提高数据质量和分析结果的准确性。以下是一些数据规范化的常见方法和技术: 数据清洗:此步骤主要清除数据中的重复项、空格、格式错误等,确…

【Oracle】oracle、mysql、sql server三者区别

欢迎来到《小5讲堂》,大家好,我是全栈小5。 这是《Oracle》系列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识…

Waifu2x:使用深度卷积神经网络的动漫风格艺术的图像超分辨率

Github网址:nagadomi/waifu2x:动漫风格艺术的图像超分辨率 (github.com) 该项目主要讲述的是如何利用预训练的深度学习模型来达到无损扩大收缩和去噪,对于一般训练图像的小伙伴应该很清晰图像经常要通过resize操作固定大小,然后c…

操作系统① —— 进程管理

1. 进程、线程、协程 进程: 是系统进行资源分配的基本单位私有地址空间,私有栈、堆上下⽂切换需要切换虚拟地址空间 线程: 是资源调度的基本单位公有同⼀地址空间,公有堆、私有栈上下⽂切换只需要切换少量寄存器 进程和线程的对比…

Oracle APEX 23.2版本 使用应用程序工作副本进行协作开发

现状描述: 当前APEX协作开发都是在同一应用程序下进行的,这样做有可能因同一时间对同一数据进行操作造成锁表或其他问题,Oracle APEX23.2版本迭代后新增了部分功能,可以创建应用程序的工作副本来修复错误、添加功能,然…

趣学前端 | 综合一波CSS选择器的用法

背景 最近睡前习惯翻会书,重温了《HTML5与CSS 3权威指南》。这本书,分上下两册,之前读完了上册,下册基本没翻过。为了对得起花过的每一分钱,决定拾起来近期读一读。 CSS 选择器 在CSS3中,提倡使用选择器…

大模型生成RAG评估数据集并计算hit_rate 和 mrr

文章目录 背景简介代码实现公开参考资料 背景 最近在做RAG评估的实验,需要一个RAG问答对的评估数据集。在网上没有找到好用的,于是便打算自己构建一个数据集。 简介 本文使用大模型自动生成RAG 问答数据集。使用BM25关键词作为检索器,然后…

AI图片智能选区抠像解决方案

高质量的图片处理往往依赖于繁琐的手动操作,耗费大量时间与精力。美摄科技推出了一款革命性的AI图片智能选区抠像解决方案,旨在帮助企业轻松实现图片的高效处理,提升内容创作效率与质量。 美摄科技的AI图片智能选区抠像解决方案,…

An Aspect-Based Engine

GPU Pro 译: By 王钰涵 2024 4.14 10.1 Introduction(简介) 引擎的定义在整个行业中有所不同。在最基本的层面上,该术语描述了一个代码库,它在多个项目中提供共同的功能。其目的是分享开发这些功能所需的资源成本…

知网参考文献引用格式转latex中BibTex-Python操作

处理思路 参考 处理步骤: (单条处理:) 1、选知网NoteExpress格式的2-7行复制信息 2、新建一个文本文件,命名为cite.txt,把知网所复制信息粘贴进来 (txt文件保存编码ANSI可行) 3、…

GD32F470_TTP224 4路 电容式 触摸开关 数字触摸传感器模块移植

2.8 TTP224触摸传感器 该模块是一个基于触摸检测IC(TTP223B)的电容式点动型触摸开关模块。常态下,模块输出低电平,模式为低功耗模式;当用手指触摸相应位置时,模块会输出高电平,模式切换为快速模式;当持续12秒没有触摸时…

C#智慧手麻系统源码 医院手术麻醉系统源码 支持三甲医院评级需求 可提供演示

C#智慧手麻系统源码 医院手术麻醉系统源码 支持三甲医院评级需求 可提供演示 手术麻醉管理系统是应用于医院手术室、麻醉科室的计算机软件系统。该系统针对整个围术期,对病人进行全程跟踪与信息管理,自动集成病人HIS、LIS、RIS、PACS信息,采…

吃豆豆 经典的区间DP 好题典题

这里很巧妙的注意一点是,你最后要把所有的豆子都吃掉,所以你只要看你多增加的尽量的少就好了 然后维护一段区间,表示的是吃掉这段区间里面的所有豆子的最小代价,然后发现最后一个是左端点或者右端点 你吃一段新的区间的同时会把…

c++的学习之路:11、string(3)

昨天写string的时候没有说全,这里就开始接着讲。 目录 一、resize 二、insert 三、erase 一、resize 昨天说这个的时候没有考虑到缩小范围时咋处理,然后发现报错了,接着我调试发现缩小就不能正常执行了,因为用的是strcap所以…

有关字符串算法

例题一 解法: 算法思路(两两⽐较): 我们可以先找出前两个的最⻓公共前缀,然后拿这个最⻓公共前缀依次与后⾯的字符串⽐较,这样就可以找出所有字符串的最⻓公共前缀。 例题二 解法(中⼼扩散&am…

UNIAPP(小程序)每十个文章中间一个广告

三十秒刷新一次广告 ad-intervals"30" <template><view style"margin: 30rpx;"><view class"" v-for"(item,index) in 100"><!-- 广告 --><view style"margin-bottom: 20rpx;" v-if"(inde…