內(nèi)存管理是操作系統(tǒng)內(nèi)核中最復(fù)雜的部分之一, start_kernel函數(shù)在內(nèi)核啟動第一個init進程前初始化了所有的內(nèi)核特性(包括那些依賴于不同架構(gòu)的特性),你也許還記得引導(dǎo)時創(chuàng)立的臨時頁表,但復(fù)雜的內(nèi)存管理部分還沒有開始,當(dāng)start_kernel函數(shù)被調(diào)用時,我們會看到初期內(nèi)存管理到更復(fù)雜的內(nèi)存管理數(shù)據(jù)結(jié)構(gòu)和技術(shù)的轉(zhuǎn)變,為了更好的理解內(nèi)核的初始化過程,我們需要對這些技術(shù)有更清晰的理解,今天我們會著重討論這個過程,主要針對初期的內(nèi)存管理memblock的介紹。
首先我們知道在內(nèi)核啟動后,對于內(nèi)存,分成好幾塊:
內(nèi)存中的某些部分使永久分配給內(nèi)核的,例如代碼段和數(shù)據(jù)段、ramdisk和dtb占用的空間、臨時頁表和設(shè)備數(shù)中的保留區(qū)域等,是系統(tǒng)內(nèi)存的一部分,不能被侵占,也不參與內(nèi)存的分配,稱之為靜態(tài)內(nèi)存;
GPU/camera/多核共享的內(nèi)存都需要預(yù)留大量連續(xù)內(nèi)存,這部分內(nèi)存平時不使用,但是必須為各個應(yīng)用場景預(yù)留,這樣的內(nèi)存稱之為預(yù)留內(nèi)存;
內(nèi)存其余的部分,是需要內(nèi)核管理的內(nèi)存,稱之為動態(tài)內(nèi)存;
那么memblock就是將以上內(nèi)存按功能劃分為若干內(nèi)存區(qū),使用不同的類型存放在memory和reserved的兩個集合中,memory即為動態(tài)內(nèi)存,而resvered包括靜態(tài)內(nèi)存等。
memblock是什么
memblock介紹
memblock即linux啟動后kernel管理內(nèi)存空間抽象出來的結(jié)構(gòu),此時buddy系統(tǒng)和slab分配器等并沒有初始化,當(dāng)需要執(zhí)行一些內(nèi)存管理、內(nèi)存分配的任務(wù),此時就是有初期的管理模塊memblock機制。在mm_init中會建立內(nèi)核的內(nèi)存分配器,停用memblock,釋放內(nèi)存給伙伴系統(tǒng)和slab分配器。memblock是bootmem的升級版本,在config中配置:CONFIG_NO_BOOTMEM=Y。
需要的結(jié)構(gòu)體
第一個結(jié)構(gòu)體的名字就叫做 memblock。它的定義如下:
struct memblock {
bool bottom_up;
phys_addr_t current_limit;
struct memblock_type memory; --> array of memblock_region
struct memblock_type reserved; --> array of memblock_region
#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
struct memblock_type physmem;
#endif
};
這個結(jié)構(gòu)體包含五個域。第一個 bottom_up 域置為 true 時允許內(nèi)存以自底向上模式進行分配。下一個域是 current_limit。這個域描述了內(nèi)存塊的尺寸限制。接下來的三個域描述了內(nèi)存塊的類型。內(nèi)存塊的類型可以是:被保留、內(nèi)存和物理內(nèi)存( CONFIG_HAVE_MEMBLOCK_PHYS_MAP 編譯配置選項被開啟)。
接下來我們可以看看下一個數(shù)據(jù)結(jié)構(gòu)memblock_type,定義如下:
struct memblock_type {
unsigned long cnt;
unsigned long max;
phys_addr_t total_size;
struct memblock_region *regions;
};
memblock_region 提供了內(nèi)存區(qū)域的基址和大小,如果 CONFIG_HAVE_MEMBLOCK_NODE_MAP 編譯配置選項被開啟, memblock_region 結(jié)構(gòu)體也提供了整數(shù)域 - numa 節(jié)點選擇器。flags 域可以是:
/* Definition of memblock flags. */
enum memblock_flags {
MEMBLOCK_NONE = 0x0, /* No special request */
MEMBLOCK_HOTPLUG = 0x1, /* hotpluggable region */
MEMBLOCK_MIRROR = 0x2, /* mirrored region */
MEMBLOCK_NOMAP = 0x4, /* don't add to kernel direct mapping */
};
以上的關(guān)系如圖所示: