03_010物理内存ram分配器,内存区域页分配及水位线等分析

news/2024/11/8 6:51:59/

memblock分配器

系统初始化的时候需要执行一些内存管理 内存分配任务就会需要内存管理器

内核初始化时候memblock分配器

先说说这个memblock分配器 有三个重要的结构体
struct memblock 表示这个分配器 内核初始化的时候 有个全局变量struct memblock
因为一个物理内存(节点node) 划分了不同的区域(zone) 所以这边的分配器根据类型也有个结构体 struct memblock_type
最后用 strcut_memblock_region 描述页的基地址 和大小 和对应的flag

在这里插入图片描述
初始化的时候 内核先解析设备树二进制节点 把所有物理内存加载到mem_block这里
在源文件"mm/memblock.c定义全局变量memblock,把成员bottom_ up初始化为假,表示从高地址向下分配。
具体分配的过程在memblock.c 直接一上来就弄了个全局变量在这
看看内核初始化过程
Init/main.c
start_kernel()
set_arch(&command_line)
fdt_ enforce_ memory_ region() ;//解析设备树二进制文件,得到可用内存范围,把超出物理内存的范围找出来,从memblock删除
//全局变量memstart_ addr记录内存的起始物理地址
memstart_ addr = round_ down (memblock_ start_ of_ DRAM() ,ARM64_ MEMSTART_ ALIGN) ;
设备树上的二进制节点 对应的命令行比如 mem内存方位可用内存大小 如果指定了内存大小 把超出长度的物理内存从memblock进行删除 因为内核镜像也被加载到了高地址 并且内核镜像可以通过线性映射区访问 所以要把内核镜像占用物理内存的范围重新添加

memblock分配器 源码查看

struct memblock {bool bottom up; // 表示分配内存的方式,值为真表示从低地址向上分配,值为假表示从高地址向下分配phys_ addr_ t current_ limit; //可分配内存的最大物理地址struct memblock_ type memory; //内存类型(包括已分配的内存和未分配的内存)struct memblock_ type reserved; //预留类型(已分配的内存)#ifdef CONFIG_ HAVE_ MEMBLOCK_ PHYS_ MAPstruct memblock_ type physmem; //物理 内存类型,#endif
};

物理内存类型和内存类型区别:内存类型是物理内存类型的子集,在引导内核时可以使用内核参数"mem= nn[KMG]“,指定可用内存的大小,导致内核不能看见所有的内存;物理内在类型总是包含所有内存范围,内存类型只包含内核参数” mem="指定的可用内在范围。

结构体 memblock_ _type

struct memblock_ _type {
unsigned long cnt;
// 当前管理集合中记录的内存区域个数
unsigned long max;
//当前管理集合中记录的内存区域的最大个数,最大值是INIT_ PHYSMEM REGIONS
phys_ _addr_ _t total_ size; //所有内存块区域的总长度
struct memblock_ region *regions; //执行内存区域结构的指针
char *name; //内存块类型的名称
};
//内存块区域的数据结构
struct memblock_ region {
phys_ _addr_ _t base; //起始物理地址
phys_ _addr_ _t size; //长度
unsigned long flags; //成员falgs是标志
#i fdef CONFIG HAVE MEMBLOCK NODE MAP
int nid; //节点编号
#endi f
};
// memblock分配器标志位定义
enum {//表示没有特殊要求区域MEMBLOCK_ NONE= 0x0/* No special request *///表示可以热插拔的区域,即在系统运行过程中可以拔出或插入物理内存MEMBLOCK_ HOTPLUG= 081/* hotpluggable region *///表示镜像的区域。将内存数据做两个复制,分配放在在主内存和镜像内存中MEMBLOCK_ MIRROR= 0x2,/* mirrored region *///表示不添加到内核直接映射区域(即线性映射区域)MEMBLOCK_ NOMAP= 0x4/* don't add to kernel direct mapping */
};

伙伴分配器

术语扫盲

虚拟地址
cpu看见的: 虚拟ram内存地址 需要mmu把(物理ram+外围设备)内存地址进行映射给cpu看
在这里插入图片描述
ram物理地址
外围设备和物理ram内存使用统一 的物理地址空间
之前有个图又放来这边用用
在这里插入图片描述
RAM中表示物理ram的一些结构体-
页:struct page ,如下图所示,x86架构下一般为4K为大小
分区:struct zone ,把整个内存划分为不同区域,x86架构下分为三个区 ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM+
​ 子结构体 struct free_area 区中空闲的区域
本文重点在分区
内存节点:struct node。对于一个简单的嵌入式系统只有一个node,

ZONE_DMA,一般由于内存碎片,有可能申请不到连续的一片物理内存,而DMA需要连续的物理内存,所以在X86下给DMA大概会留一块连续的16M的物理内存。
在这里插入图片描述

背景描述

伙伴分配器用在ram的物理内存管理 为什么有ram内存管理
长时间使用会有内存碎片化 引入内存管理系统
在这里插入图片描述
物理内存被分为几个区域。每一个区域都有一个伙伴系统。每个伙伴系统都管理着每个zone的物理内存。但是他们的原理一样。

介绍

伙伴系统(Buddy System)是一种管理物理内存的算法,主要于管理大块的内存区域,如页框。
伙伴系统通过将大的内存块不断分割成两个较小的伙伴块,然后按照块大小将伙伴块归入不同的空闲链表中,以便快速找到符合要求的内存块。
伙伴系统通常用于分配物理内存,由于内核中的物理内存总量比较有限,因此在分配物理内存时需要考虑内存碎片的问题。
而slab则是用于管理内核对象的内存分配器。
它的设计目的是为了提高内核对象的内存分配效率,减少内存碎片,提高内存分配的速度。slab分配器将内存分为不同的slab,每个slab管理一 类内核对象,slab中的页框可以被分配给该类对象进行使用,从而提高了内存的利用率和访问速度。
在实现上,伙伴系统和slab通常是一起使用的。当需要为内核对象分配内存时,slab会先从伙伴系统中分配出一块合适大小的物理内存,然后将该物理内存划分为slab,并在其中管理内核对象。因此,伙伴系统和slab可以说是相互配合的内存管理机制。

zone区域结构体查看

看的是zone结构体 表示物理ram区域的结构体 因为伙伴系统需要的属性都保存在zone结构体里。
zone结构体是描述物理内存区域的数据结构,所以能理解为每个zone都有一个自己的伙伴分配器
其中包含了伙伴系统需要的所有属性。下面是 zone中伙伴系统需要使用到的属性:

struct zone {unsigned long watermark[NR_WMARK];//伙伴系统需要使用水位线来控制内存的分配和回收,其中//watermark表示内存空闲的水位线,watermark boost表示需要提高的水位线。long lowmem_reserve[MAX_NR_ZONES];unsigned long		zone_start_pfn;//表示该区域的起始页框号。unsigned long		managed_pages;//表示该区域管理的页框总数,包括已分配和未分配的页框。unsigned long		spanned_pages;//示该区域所管理的所有物理页框的数量。unsigned long		present_pages;//struct free_area	free_area[MAX_ORDER]; //伙伴系统需要在每个区域内维护可用内存块的链表,这些链表就存储在free _area数组中。unsigned long		flags;//存储了该区域的一些状态信息,例如该区域是否允许交换、是否允许内存高端地址分配等。...
} ____cacheline_internodealigned_in_smp;
该区域空闲的位置 zone->free_area,简单说一下内存足够的时候怎么分配的
struct free_area {struct list_head	free_list[MIGRATE_TYPES];unsigned long		nr_free;
};

结构体free_ area 是伙伴系统中管理每个块大小的可用空闲页框链表的数据结构。它定义了一个数组free_ list, 每个元素都是一个链表头, 代表了一个特定大小的空闲页框的链表。
nr_ free记录了该数组中链表中可用的空闲页框数量。nr_ free记录的是free_ list数组中存储的空闲页的数量。因为每个空闲块都对应一个空闲页,所以nr_ free等于所有free_ list数组中链表节点个数之和。free_ area 是作为一个zone结构体中的一部分来使用的。
zone是Linux内核中的一个管理物理内存的单元,一个物理内存可以被划分为多个zone,每个zone中包含了一定数量的物理页框。
在一个zone中,free_ area 数组中的每个元素都代表了该zone中的一一个固定大小的页框。
zone中的页框大小按照2的幂次方增加,即从小到大排列,如free_ area[0] 示一个页框大小为2^0个物理页框的链表,
free_ area[1] 示-个页框大小为2^1个物理页框的链表,
依此类推,直到最大的页框大小2^{MAX_ ORDER}。
在伙伴系统中,每个可用的空闲页框都被划分到适当大小的free_ area 链表中。
例如,当系统需要一个大小为2^3个物理页框的连续空间时,会在free_ area[3] 的链表中查找。
如果free_ area[3]中没有可用的空闲页框,系统会向较大的链表free_ area[4] 甚至更大的链表中寻找可用空闲页框。

如果所有的free_ area链表中都没有可用的空闲页框,那么系统就需要等待一段时间,直到有足够数量的页框空闲为止。
在释放一个空闲页框时,它会被添加到对应的free_ area链表中,等待被再次分配。
通过这种方式,伙伴系统可以高效地管理可用的空闲页框,同时避免了内存碎片化的问题。
free_ area中free_ list链表下一个结点对应的就是page中的buddy_ list,
再通过计算地址即可得到需要的page,后续的笔记会记录Linux的数据机构。

内存不足怎么分配物理页到这个区域

当前这个物理区域会根据水位线(下面会说)来判断当前区域的内存是否足够
内存不足的话会考虑去备用区域寻找页 进行分配
先看看内存节点结构体

struct  page
{//节点结构体里面还有个数据结构体来表示它的zonetypedef struct pglist_ data {struct zone node_ zones [MAX_ NR_ ZONES]; //内存区域数组struct zonelist node_ zonelists[MAX_ ZONELISTS]; //备用区域列表int nr_ _zones; //该节点包含的内存区域数量}
};
备用区域

两个借用规则 如果能满足当前zone的借用规则 就被放到了这个zone的备用区域列表中
借用必须遵守规则: 节点规则(嵌入式可以不关心 我们就一个节点)
一个内存节点的某个区域类型可以从另-一个内存节点的相同区域类型借用物理页,比如节点0的普通区
域可以从节点1的普通区域借用物理页;
借用必须遵守规则: 高低区域规则
高区域类型可以从低区域类型借用物理页,比如普通区域可以从DMA区域借用物理页; .
低区域类型不能从高区域类型借用物理页。比如DMA区域不能从普通区域借用物理页。

水位线

上面的区域结构体中 有个数组变量来表示水位线
首选的内存区域什么情况下从备用区域借用物理页呢?每个内存区域有3个水线
a.高水线(high) :如果内存区域的空闲页数大于高水线,说明内存区域的内存充足;
b.低水线(low) :如果内存区域的空闲页数小于低水线,说明内存区域的内存轻微不足;
C.最低水线(min) : 如果内存区域的空闲页数小于最低水线,说明廖内存区域的内存严重不足。
在这里插入图片描述

最后看看怎么分配的流程和系统中如何查看

第一次尝试使用低水线 如果首选内存区域的空闲页的数量小于低水线 就从备用区域借用物理页 如果还是失败 就换起所有内存节点的页回收线程 用异步的方式进行回收页 再一次尝试最低水线
如下能看到每个节点 对应的每个区域 里面分别的水线

han@ubuntu:~$ cat /proc/zoneinfo
Node 0, zone      DMAper-node statsnr_inactive_anon 10820nr_active_anon 320858nr_inactive_file 231022nr_active_file 234555nr_unevictable 16nr_slab_reclaimable 44884nr_slab_unreclaimable 18674nr_isolated_anon 0nr_isolated_file 0workingset_nodes 0workingset_refault 0workingset_activate 0workingset_restore 0workingset_nodereclaim 0nr_anon_pages 320578nr_mapped    153680nr_file_pages 476705nr_dirty     26878nr_writeback 0nr_writeback_temp 0nr_shmem     11129nr_shmem_hugepages 0nr_shmem_pmdmapped 0nr_file_hugepages 0nr_file_pmdmapped 0nr_anon_transparent_hugepages 0nr_unstable  0nr_vmscan_write 0nr_vmscan_immediate_reclaim 0nr_dirtied   287542nr_written   244390nr_kernel_misc_reclaimable 0pages free     3968min      77low      96high     115spanned  4095present  3997managed  3976protection: (0, 2445, 3369, 3369, 3369)nr_free_pages 3968nr_zone_inactive_anon 0nr_zone_active_anon 0nr_zone_inactive_file 0nr_zone_active_file 0nr_zone_unevictable 0nr_zone_write_pending 0nr_mlock     0nr_page_table_pages 0nr_kernel_stack 0nr_bounce    0nr_zspages   0nr_free_cma  0numa_hit     1numa_miss    0numa_foreign 0numa_interleave 0numa_local   1numa_other   0pagesetscpu: 0count: 0high:  0batch: 1vm stats threshold: 6cpu: 1count: 0high:  0batch: 1vm stats threshold: 6cpu: 2count: 0high:  0batch: 1vm stats threshold: 6cpu: 3count: 0high:  0batch: 1vm stats threshold: 6node_unreclaimable:  0start_pfn:           1
Node 0, zone    DMA32pages free     43834min      12202low      15252high     18302spanned  1044480present  782288managed  759709protection: (0, 0, 924, 924, 924)nr_free_pages 43834nr_zone_inactive_anon 8454nr_zone_active_anon 245858nr_zone_inactive_file 181846nr_zone_active_file 177532nr_zone_unevictable 4nr_zone_write_pending 26534nr_mlock     4nr_page_table_pages 5641nr_kernel_stack 8472nr_bounce    0nr_zspages   0nr_free_cma  0numa_hit     4159869numa_miss    0numa_foreign 0numa_interleave 192366numa_local   4159869numa_other   0pagesetscpu: 0count: 50high:  378batch: 63vm stats threshold: 36cpu: 1count: 335high:  378batch: 63vm stats threshold: 36cpu: 2count: 300high:  378batch: 63vm stats threshold: 36cpu: 3count: 121high:  378batch: 63vm stats threshold: 36node_unreclaimable:  0start_pfn:           4096
Node 0, zone   Normalpages free     5754min      4615low      5768high     6921spanned  262144present  262144managed  236760protection: (0, 0, 0, 0, 0)nr_free_pages 5754nr_zone_inactive_anon 2366nr_zone_active_anon 75000nr_zone_inactive_file 49176nr_zone_active_file 57023nr_zone_unevictable 12nr_zone_write_pending 344nr_mlock     12nr_page_table_pages 5556nr_kernel_stack 7096nr_bounce    0nr_zspages   0nr_free_cma  0numa_hit     839519numa_miss    0numa_foreign 0numa_interleave 223408numa_local   839519numa_other   0pagesetscpu: 0count: 253high:  378batch: 63vm stats threshold: 24cpu: 1count: 202high:  378batch: 63vm stats threshold: 24cpu: 2count: 325high:  378batch: 63vm stats threshold: 24cpu: 3count: 291high:  378batch: 63vm stats threshold: 24node_unreclaimable:  0start_pfn:           1048576
Node 0, zone  Movablepages free     0min      0low      0high     0spanned  0present  0managed  0protection: (0, 0, 0, 0, 0)
Node 0, zone   Devicepages free     0min      0low      0high     0spanned  0present  0managed  0protection: (0, 0, 0, 0, 0)
han@ubuntu:~$ 

http://www.ppmy.cn/news/1010044.html

相关文章

在家下载Springer、IEEE、ScienceDirect等数据库论文的论文下载工具

Springer、IEEE、ScienceDirec数据库是我们查找外文文献常用数据库,当我们没有数据库使用权限的时该如何下载这些数据库的学术论文呢?下面就讲解一下在家下载数据库学术文献的论文下载工具。 一、查找下载外文文献,我们可以谷歌学术检索&…

Docker Compose 使用方法

目录 前言 安装 Docker Compose Ubuntu 安装与更新 Red Hat 安装与更新 验证是否安装 Docker Compose 创建 docker-compose.yml 文件 创建一个MySQL 与 tomcat 示例 使用Docker Compose启动服务 前言 Docker Compose 是一个工具,旨在帮助定义和 共享多容器…

C++拷贝wstring到wchar_t*中踩的坑

使用wchar_t指针将wstring中的数据拿出来,发现释放的时候异常,不是深拷贝和浅拷贝的问题 首先先看看string怎末复制到char中,代码如下 string str1"\"0.2.0\"";char* tnew char[str.size()1];memcpy(t, str1.c_str(), s…

Spring(九) - 解惑 spring 嵌套事务.2

1. 事务传播特性 在所有使用 spring 的应用中, 声明式事务管理可能是使用率最高的功能了, 但是, 从我观察到的情况看,绝大多数人并不能深刻理解事务声明中不同事务传播属性配置的的含义, 让我们来看一下 TransactionDefinition 接口中的定义 Java代码 /** * Support a cu…

如何使用本地mock数据

当后端同事接口数据还未完成,我们前端开发需要使用数据时,怎么办呢?这里可以自己本地mock数据先用着啦!仅在开发时使用 1. 创建一个 xxx.js文件,对外暴露一个数组; 对新建js文件编写导出,返回数…

面试之快速学习c++11 -auto 和decltype

学习地址: http://c.biancheng.net/view/3730.html 1. auto 1. 使用了 auto 关键字以后,编译器会在编译期间自动推导出变量的类型 2. 使用 auto 类型推导的变量必须马上初始化,这个很容易理解,因为 auto 在 C11 中只是“占位符…

npx 的使用原理,以及使用 npx 的一些注意事项

如何使用npx npx pkg-name 如果自己开发了一个cli第三方包 只需要在项目中执行npx <pkg-name> <bin>即可&#xff0c;没安装则会去远程下载。 npx bin 当执行 $ npx <command> 相关命令的时候&#xff0c;npx 会先本地找&#xff08;可以是项目中的也可…

​双标大型现场?马斯克被指虚伪:边解雇不满员工,边提供援助

8月6日消息&#xff0c;推特创始人兼首席执行官埃隆马斯克今日在推特上宣布一项令人震惊的举措。他表示&#xff0c;对于在X平台上发布或支持特定内容而受雇主不公平对待的用户&#xff0c;推特将提供无限法律援助费用以支持他们&#xff0c;并为受影响用户提供强有力的支持。 …