memblock工作原理
memblock是Linux启动阶段的一种内存管理方式,是对bootmem的补充,是为了应对bootmem易产生外部碎片而产生。他的初始化函数arm_memblock_init和bootmem初始化所在的函数paging_init紧挨着,都在setup_arch中。
struct memblock {
phys_addr_t current_limit;
phys_addr_t memory_size; /* Updated by memblock_analyze() */
struct memblock_type memory;
struct memblock_type reserved;
};
current_limit:表示memblock可分配的内存地址的上限值,其初始化的过程为
paging_init -> sanity_check_meminfo -> memblock_set current_limit(limit)
其中limit = __pa(vmalloc_min-1) + 1 = VMALLOC_END - 128M = 4G - 128M(high mem)
memory_size:记录总的内存数量,在memory_analyze中更新
memory,reserved:是两张表格,前者是系统所拥有的物理内存块,后者可以理解为已分配的内存块
1. 初始化
1)mdesc->reserve是在arch/arm/mach-omap2/board-d7800.c中分配给machine_desc变量。
2)meminfo的初始化可以参考另外一篇笔记meminfo初始化
2.内存分配
1)MEMBLOCK_ALLOC_ACCESSIBLE的值为0,则后面的max_addr也为0,但并不意味着搜索的上限也为0。在memblock_find_base中end,也就是搜索的上限(其实是搜索的起始值,因为我们的搜索时从内存的最高值开始的,这么做是有用意的,详见第2点)赋为memblock.current_limit,它的值可以参考本文前面的介绍。
2)为什么是从内存的高地址开始搜索,mm/memblock.c中的有注释道
/* We do a top-down search, this tends to limit memory
* fragmentation by keeping early boot allocs near the
* top of memory
*/
看起来是为了解决碎片的问题,但为什么能解决,不清楚。
3)代码中的跟内存区的始末位置有关的值都进行了对齐,用到如下的语句
size = memblock_align_up(size, align)
base = memblock_align_down((end - size), align)
这些也都是为了解决碎片问题,mm/memblock.c 中有注释,道
/* We align the size to limit fragmentation. Without this, a lot of
* small allocs quickly eat up the whole reserve array on sparc
*/
4)memblock_addrs_overlap中判断交叠的方法很值得学习。