前面一篇博客介绍了memblock初始化的流程,实际上并没有介绍完整,只是列出了大概的流程,设计到的相关数据结构都没有介绍,所以接下里继续了解memblock使用到的数据结构,以及是如何进行内存分配和管理的。
linux-4.10/include/linux/memblock.h
47 struct memblock {
48 bool bottom_up; /* is bottom up direction? */
49 phys_addr_t current_limit;
50 struct memblock_type memory;
51 struct memblock_type reserved;
52 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
53 struct memblock_type physmem;
54 #endif
55 };
bottom_up:表示分配器分配内存的方式 true:从低地址向高地址分配 false:相反就是从高地址向地址分配内存.
current_limit:指出了内存块的大小限制
memory:可分配内存的集合,申请内存时,会从这些集合中分配内存
reserved:已分配内存的集合,分配出去的内存会放在这个集合里面管理
physmem:物理内存的集合
linux-4.10/include/linux/memblock.h
40 struct memblock_type {
41 unsigned long cnt; /* number of regions */
42 unsigned long max; /* size of the allocated array */
43 phys_addr_t total_size; /* size of all regions */
44 struct memblock_region *regions;
45 };
cnt:当前管理的集合中记录的内存区域个数
max:当前管理的集合中可记录的内存区域的最大个数,最大值是INIT_PHYSMEM_REGIONS
total_size:集合记录的内存总和
regions:执行内存区域结构(memblock_region)的指针
linux-4.10/include/linux/memblock.h
31 struct memblock_region {
32 phys_addr_t base;
33 phys_addr_t size;
34 unsigned long flags;
35 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
36 int nid;
37 #endif
38 };
base:内存区域起始地址,是物理地址
size:内存区域大小,单位是字节
flags:该内存区域的标识,例如MEMBLOCK_NOMAP,在做映射的时候不要映射到内核中
nid:CPU被划分为多个节点(node),每个node 有对应的内存簇bank,一个标识
struct memblock,struct memblock_type 和struct memblock_region 这三个数据结构的关系如上图
linux-4.10/include/linux/memblock.h
20 #define INIT_MEMBLOCK_REGIONS 128
21 #define INIT_PHYSMEM_REGIONS 4
320 #define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)
所以INIT_MEMBLOCK_REGIONS 的值是128,INIT_PHYSMEM_REGIONS 对应的值是4 ,MEMBLOCK_ALLOC_ANYWHERE 是0xffffffff(32位)
在memblock 中,管理内存的数据结构(struct memblock)被定义成为一个全局的变量,并且赋予了对应的初值。
linux-4.10/mm/memblock.c
28 static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
29 static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
30 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
31 static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock;
32 #endif
33
34 struct memblock memblock __initdata_memblock = {
35 .memory.regions = memblock_memory_init_regions,
36 .memory.cnt = 1, /* empty dummy entry */
37 .memory.max = INIT_MEMBLOCK_REGIONS,
38
39 .reserved.regions = memblock_reserved_init_regions,
40 .reserved.cnt = 1, /* empty dummy entry */
41 .reserved.max = INIT_MEMBLOCK_REGIONS,
42
43 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
44 .physmem.regions = memblock_physmem_init_regions,
45 .physmem.cnt = 1, /* empty dummy entry */
46 .physmem.max = INIT_PHYSMEM_REGIONS,
47 #endif
48
49 .bottom_up = false, //内存分配方式是从高地址往低地址分配
50 .current_limit = MEMBLOCK_ALLOC_ANYWHERE,
51 };
memblock.memory.regions 指向memblock_memory_init_regions 数组,数组大小是128,memblock.reserved.regions指向memblock_reserved_init_regions数组,数组大小是128,memblock.physmem.regions指向memblock_physmem_init_regions数组,数组大小是4.
memblock 初始化后如上图。
memblock api介绍,接下来我们重点分析下面4个api的实现,虽然memblock定义了很多个api,但并不需要全部了解。
int memblock_add(phys_addr_t base, phys_addr_t size);
int memblock_remove(phys_addr_t base, phys_addr_t size);
phys_addr_t memblock_alloc(phys_addr_t size, phys_addr_t align);
int memblock_free(