kernel启动流程-start_kernel的执行_4.mm_init

本文详细解析了Linux 5.10内核mm_init阶段的内存管理初始化流程,涉及内存模型、内存映射、DMA映射、slab机制、kmem_cache初始化等关键步骤,展示了内核启动时对内存资源的精细化管理。

1. 前言

本专题文章承接之前《kernel启动流程_head.S的执行》专题文章,我们知道在head.S执行过程中保存了bootloader传递的启动参数、启动模式以及FDT地址等,创建了内核空间的页表,最后为init进程初始化好了堆栈,并跳转到start_kernel执行。
本文重点介绍start_kernel的mm_init的主要流程.

kernel版本:5.10
平台:arm64

2. mm_init

|- -page_ext_init_flatmem

page_ext_init_flatmem();

在linux内核中支持3中内存模型,分别是:flat memory model,Discontiguous memory model和sparse memory model;
因为CONFIG_SPARSEMEM为true,因此采用sparse memory model,此函数为空

|- -init_debug_pagealloc

init_debug_pagealloc();

需要使能CONFIG_DEBUG_PAGEALLOC

|- -report_meminit

report_meminit();

打印结果如下:

[    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off

|- -mem_init

mem_init();
mem_init
    |--swiotlb_init(1)
    |--set_max_mapnr(max_pfn - PHYS_PFN_OFFSET);
    |--free_unused_memmap();
    \--memblock_free_all()

|- - -swiotlb_init(1)

由于内存的物理空间较大,而DMA访问的地址空间较小,因此如果指定一个DMA无法访问的地址空间,就会通过一段提前分配的软件的buffer进行映射,让DMA可以访问这段内存空间,这样造成的结果是CPU与DMA看到的内存物理地址是不一样的,这个技术就是swiotlb
参考:https://blog.youkuaiyun.com/liuhangtiant/article/details/87825466

|- - -set_max_mapnr(max_pfn - PHYS_PFN_OFFSET);

设置全局max_mapnr为max_pfn - PHYS_PFN_OFFSET

其中,PHYS_PFN_OFFSET为内存物理首地址的页帧号,定义为:

#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
/* PHYS_OFFSET - the physical address of the start of memory. */
 #define PHYS_OFFSET             ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; })

其中memstart_addr值为:0x40000000

arch/arm64/mm/init.c中有如下的赋值:
memstart_addr = round_down(memblock_start_of_DRAM()

max_pfn通过gdb打印看值为:0x80000

|- - -free_unused_memmap

遍历memblock.memory的所有range区域,释放没有使用的mem_map区域,实际就是这段区域对应的page

|- - -memblock_free_all

释放空闲页给buddy分配器

memblock_free_all
  |--reset_all_zones_managed_pages
  |--pages = free_low_memory_core_early()
       |--for_each_reserved_mem_range(i, &start, &end)
       |      reserve_bootmem_region(start, end)
       \--for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end...)
             count += __free_memory_core(start, end);
|- - - -reset_all_zones_managed_pages

遍历所有的node的所有zone,将zone的managed_pages初始化为0,atomic_long_set(&z->managed_pages, 0)
在这里插入图片描述

|- - - -free_low_memory_core_early
|--pages = free_low_memory_core_early()
       |--for_each_reserved_mem_range(i, &start, &end)
       |      reserve_bootmem_region(start, end)
       \--for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end...)
             count += __free_memory_core(start, end);

(1)遍历memblock.reserved的每个range,通过
reserve_bootmem_region->__SetPageReserved(page)来设置每个range对应的所有page为保留标志;
(2)遍历memblock.memory的每个range, 通过__free_memory_core将空闲range释放给buddy, 并统计释放页帧的数目

__free_memory_core(start, end)
    |--__free_pages_memory
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值