简介:bootmem分配器是系统启动初期的内存分配方式,在耳熟能详的伙伴系统,slab系统建立前内存都是利用bootmem分配器来分配的,伙伴系统框架建立起来后,bootmem会过度到伙伴系统,bootmem大致思想就是收集内存中的可用内存,然后建立bit位图,然后需要的内存从这些空闲内存中分配,分配了就标记占用,当然这种分配方式很低效,但是由于只占用启动阶段很少一部分,所以也大可接受了,好了,废话不多说,一起看代码吧,
相关阅读:
一、初始化部分
init/main.c中
start_kernel函数
{
...
setup_arch(&command_line);
...
}
代码位于arch/arm/kernel/setup.c中,
void __init setup_arch(char **cmdline_p)
{
...
paging_init(mdesc);
...
}
*******************************************************
* 继续跟进paging_init函数在arch/arm/mm/mmu.c中
*
*******************************************************
* paging_init() sets up the page tables, initialises the zone memory
* maps, and sets up the zero page, bad page and bad page tables.
*/
void __init paging_init(struct machine_desc *mdesc)
{
void *zero_page;
memblock_set_current_limit(lowmem_limit);
build_mem_type_table();
prepare_page_table();
map_lowmem();
devicemaps_init(mdesc);
kmap_init();
top_pmd = pmd_off_k(0xffff0000);
/* allocate the zero page. */
zero_page = early_alloc(PAGE_SIZE);
bootmem_init();
empty_zero_page = virt_to_page(zero_page);
__flush_dcache_page(NULL, empty_zero_page);
}
* 其中的bootmem_init()就是我们要找的,对应arm的定义在
* arch/arm/mm/init.c
***************************************************************
void __init bootmem_init(void)
{
unsigned long min, max_low, max_high;
max_low = max_high = 0;
/*
*找到内存区域大小,max_low低端内存上界限
*max_high 总内存上界
*/
find_limits(&min, &max_low, &max_high);
//arm bootmem初始化
arm_bootmem_init(min, max_low);
/*
* Sparsemem tries to allocate bootmem in memory_present(),
* so must be done after the fixed reservations
*/
arm_memory_present();
/*
* sparse_init() needs the bootmem allocator up and running.
*/
sparse_init();
/*
* Now free the memory - free_area_init_node needs
* the sparse mem_map arrays initialized by sparse_init()
* for memmap_init_zone(), otherwise all PFNs are invalid.
*/
arm_bootmem_free(min, max_low, max_high);
high_memory = __va(((phys_addr_t)max_low << PAGE_SHIFT) - 1) + 1;
/*
* This doesn't seem to be used by the Linux memory manager any
* more, but is used by ll_rw_block. If we can get rid of it, we
* also get rid of some of the stuff above as well.
*
* Note: max_low_pfn and max_pfn reflect the number of _pages_ in
* the system, not the maximum PFN.
*/
max_low_pfn = max_low - PHYS_PFN_OFFSET;
max_pfn = max_high - PHYS_PFN_OFFSET;
}
*******************************************************
* 这里的函数需要一个一个的过一下,先看这个
* find_limits(&min, &max_low, &max_high)函数
* 同文件夹下
*******************************************************
static void __init find_limits(unsigned long *min, unsigned long *max_low,
unsigned long *max_high)
{
struct meminfo *mi = &meminfo; //内存bank的表述结构
int i;
*min = -1UL;
*max_low = *max_high = 0;
for_each_bank (i, mi) {
struct membank *bank = &mi->bank[i];
unsigned long start, end;
start = bank_pfn_start(bank);
end = bank_pfn_end(bank);
if (*min > start)
*min = start; //保证min最后是最小值
if (*max_high < end) //保证最后的max_high是最大值
*max_high = end;
if (bank->highmem) //如果bank是高端内存那么不再标记max_low
continue;
if (*max_low < end) //如果是普通内存,那么max_low继续跟着增大
*max_low = end;
}
}