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

memblock分配器

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

内核初始化时候memblock分配器

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

03_010物理内存ram分配器,内存区域页分配及水位线等分析_第1张图片
初始化的时候 内核先解析设备树二进制节点 把所有物理内存加载到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_ MAP
	struct 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看
03_010物理内存ram分配器,内存区域页分配及水位线等分析_第2张图片
ram物理地址
外围设备和物理ram内存使用统一 的物理地址空间
之前有个图又放来这边用用
03_010物理内存ram分配器,内存区域页分配及水位线等分析_第3张图片
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的物理内存。
03_010物理内存ram分配器,内存区域页分配及水位线等分析_第4张图片

背景描述

伙伴分配器用在ram的物理内存管理 为什么有ram内存管理
长时间使用会有内存碎片化 引入内存管理系统
03_010物理内存ram分配器,内存区域页分配及水位线等分析_第5张图片
物理内存被分为几个区域。每一个区域都有一个伙伴系统。每个伙伴系统都管理着每个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
{
    //节点结构体里面还有个数据结构体来表示它的zone
    typedef 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) : 如果内存区域的空闲页数小于最低水线,说明廖内存区域的内存严重不足。
03_010物理内存ram分配器,内存区域页分配及水位线等分析_第6张图片

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

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

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

你可能感兴趣的:(狂刷KPI,链表,数据结构)