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