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的目的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章