1. linux内存管理系统
1. 1 内存配置
vim .config
由上图可知,当前系统配置的内存资源为:
-
虚拟页大小4KiB -
虚拟地址带宽48bit -
物理地址带宽48bit -
4级页表,pgd pud pmd pte
1.2 查看内存页的布局情况
make menuconfig
利用qemu环境进行查看。 不知道如何搭建环境的可以参考这个链接: https://editor.csdn.net/md/?articleId=123156383
cat sys/kernel/debug/kernel_page_tables
1.3 物理内存信息大概流程
start_kernel
setup_arch
early_fixmap_init//初始化fixmap,从体系代码中给一点物理内存用于启动物理内存的基础
setup_machine_fdt//fixmap_remap_fdt,设备树中内存的映射展开
arm64_memblock_init//启动阶段的内存管理
paging_init
->map_kernel
->map_mem//为系统各个region建立物理内存和虚拟内存的映射
1.4 设备树内存映射
参考链接1有详细的说明 2.1参考链接1
1.5 SMP、AMP、BMP
1.6 NUMA与UMA两种内存管理
NUMA的核心思想是当前系统中所有CPU共享通用内存,每个CPU访问到内存的时间是一样的。
UMA的核心思想是,当前系统所有CPU共享通用内存,但是每个CPU访问到内存的时间不完全相同,性能受到内存与CPU相对路径差距的影响。
Linux内核代码,将(N)UMA类型的计算机管理物理内存抽象为struct pglist_data类型的pg_data_t的数据结构。
1.7 平坦、不连续、稀疏三种内存模型
Linux的早期,Linux跑的内存是flat的,就是一块连续的物理内存块。 用struct page这个数据结构来抽象物理内存管理的基本单元,它描述的范围是一个page frame的物理内存region
1.8 数据结构
struct page *mem_map; pg_data_t struct mem_section **mem_section;
init/main.c
start_kernel
->setup_arch(&command_line);//初始化跟arch相关的配置
->arm64_memblock_init();//启动阶段的内存管理器初始化,这个很重要,后续单独描述,总的来说,这个步骤既做好了内存检查、划分,又有简单的内存分配行为
|paging_init();//映射系统自身各个段、系统的物理内存
|bootmem_init();
| ->arm64_numa_init();//看名字就知道本章核心就在这里,numa初始化
| ->numa_init(dummy_numa_init);//细节跟memblock关系较大,这里不扣memblock细节
| |numa_init(),
| ->numa_alloc_distance();//分配node实例,直接写死,只分配nr_node_ids个node
| |numa_register_nodes();
| ->setup_node_data();//初始化node,填充全局struct pglist_data *node_data[];数组,填充pg_data_t数据结构相关字段
| |node_set_online(nid);//设置当前node为online,到这一步,可以认为node初始化完成。
|
|sparse_init();//稀疏内存模型初始化
|zone_sizes_init(min, max);//zone内存区域初始化
init/main.c
start_kernel
->setup_arch(&command_line);//初始化跟arch相关的配置
->sparse_init();//分配一个mem_map,然后将物理内存关联到section中。
/* 在这里之前,内核以及静态定义了全局变量struct mem_section **mem_section; 它就是sparse的核心,初始化sparse,就是将section关联到node以及struct page*/
2. 总结
2.1 技术参考
参考链接1:dtb加载 https://blog.csdn.net/u010923083/article/details/110480198
|