Linux memory的初始化(三)

在阅读玩memory初始化的大部分代码之后,突然发现一个问题:在log中发现memory type的遍历过程中发现memory type cnt的值从之前初始化的一个变成了7个,但是搜遍所有的代码也没有发现具体在哪里初始化的这个值,也就是说在reserve type region增加的过程中如何做到memory type region也同时增加的呢?

将初始化的代码又撸过一遍之后终于在reserve代码中找到了一些端倪:

__fdt_scan_reserved_mem->__reserved_mem_reserve_reg->early_init_dt_reserve_memory_arch:

early_init_dt_reserve_memory_arch的第三个参数nomap为此问题的关键点:

nomap的官方解释是当此reserve memory节点不需要映射时会设置此属性,通过分析后可以理解为,当reserve的memory为单独一块或者几块连在一起时地址最小的那一块需要设置nomap。

如上图中ABCD均为reserve memory。其中A和B两块reserve memory就需要nomap设置,而nomap的设置和下面问题至关重要。

看代码:

int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
					phys_addr_t size, bool nomap)
{
	if (nomap)
		return memblock_remove(base, size);
	return memblock_reserve(base, size);
}

上面代码中当nomap设置之后,可以执行memblock_remove的操作,

memblock_remove->memblock_remove_range:

int __init_memblock memblock_remove_range(struct memblock_type *type,
					  phys_addr_t base, phys_addr_t size)
{
	int start_rgn, end_rgn;
	int i, ret;

	ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);------------------------(1)
	if (ret)
		return ret;

	for (i = end_rgn - 1; i >= start_rgn; i--)
		memblock_remove_region(type, i);---------------------------(2)
	return 0;
}

(1)memblock_isolate_range负责将需要reserve的memory从memory type中分离出来,如下图:


比如一整块内存,我需要reserve中间这一块,memblock_isolate_range会将这块memory分成三块,此时memory type region个数为3,其他在已经有reserve的内存上继续reserve的道理以此类推。

(2)memblock_remove_region将一分为三的三块内存中需要reserve的一块从memory type中remove掉,同时memory type region的个数减1,这样就达到了在reserve一块内存的同时,memory type region也增加1变成2个,待reserve操作完成之后,reserve memory region个数加1,memory会变成如下状态:

总结:memory reserve可以理解为在一块完整的memory上面不断的挖坑,来达到预留memory的目的。

猜你喜欢

转载自blog.csdn.net/zsj100213/article/details/80851038
今日推荐