内存映射过程之memblock
导读
本文主要整理如下问题:
- 在mem系统还未建立起来之前,kernel如何管理使用内存?
- 经过memblock初始化完成后,提供怎样的功能?
涉及到的目录文件:
目录 | 描述 |
---|---|
./kernel-4.9/drivers/of/fdt.c | 关于设备树相关函数的定义实现位置 |
./kernel-4.9/Documentation/kernel-parameters.txt | kernel中的命令参数 |
./kernel-4.9/include/linux/memblock.h | memblock相关定义位置 |
1. memblock 是什么?
memblock即linux 启动后kernel管理dram空间抽象出来的结构,此时buddy系统,slab分配器等并没有被初始化好,当需要执行一些内存管理、内存分配的任务,则先使用memblock的机制;
当buddy系统和slab分配器初始化好后,在mem_init()中对memblock分配器进行释放,内存管理与分配由buddy系统,slab分配器等进行接管。
注意memblock是bootmem的升级版本,在config中有配置:CONFIG_NO_BOOTMEM=y
1.1 结构体关系
1.1.1 code
如下为几个结构体的定义
memblock结构
#define INIT_MEMBLOCK_REGIONS 128
#define INIT_PHYSMEM_REGIONS 4
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
};
struct memblock_type {
unsigned long cnt; /* number of regions */
unsigned long max; /* size of the allocated array */
phys_addr_t total_size; /* size of all regions */
struct memblock_region *regions;
};
struct memblock_region {
phys_addr_t base;
phys_addr_t size;
unsigned long flags;
#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
int nid;
#endif
};
/* Definition of memblock flags. */
enum {
//region 的type
MEMBLOCK_NONE = 0x0, /* No special request */
MEMBLOCK_HOTPLUG = 0x1, /* hotpluggable region */
MEMBLOCK_MIRROR = 0x2, /* mirrored region */
MEMBLOCK_NOMAP = 0x4, /* don't add to kernel direct mapping */
};
1.1.2 关系图示
简单图示如下:
- memblock的基本单位是region;
- 将memblock划分为reserved部分和memory部分:
- reserve部分其实是已经使用了的,早期分配时先将FDT的搞出来,如果配置了no-map则后续系统不可见(paging_init会过滤);
- memory为实际系统可使用内存大小;
上述图示使用graphviz实现,如下为源码记录:
digraph memblock {
graph[nodesep="1.50"]
node [fontsize = "10", color = "skyblue", shape = "record"];
memblock [label = "{
<head> memblock |
bool bottom_up |
phys_addr_t current_limit |
<memory> memory |
<reserved> reserved |
<physmem> physmem
}"];
memblock_type [label = "{
<head> memory |
unsigned long cnt /* number of regions */ |
unsigned long max /* size of the allocated array */ |
phys_addr_t total_size /* size of all regions */|
<memory> regions;
}"];
memblock_type1 [label = "{
<head