內(nèi)存映射結(jié)構(gòu):
1、32位地址線尋址4G的內(nèi)存空間,其中0-3G為用戶程序所獨(dú)有,3G-4G為內(nèi)核占有。
2、struct page:整個(gè)物理內(nèi)存在初始化時(shí),每個(gè)4kb頁(yè)面生成一個(gè)對(duì)應(yīng)的struct page結(jié)構(gòu),這個(gè)page結(jié)構(gòu)就獨(dú)一無(wú)二的代表這個(gè)物理內(nèi)存頁(yè)面,并存放在mem_map全局?jǐn)?shù)組中。
3、段式映射:首先根據(jù)代碼段選擇子cs為索引,以GDT值為起始地址的段描述表中選擇出對(duì)應(yīng)的段描述符,隨后根據(jù)段描述符的基址,本段長(zhǎng)度,權(quán)限信息等進(jìn)行校驗(yàn),校驗(yàn)成功后。cs:offset中的32位偏移量直接與本段基址相累加,得出最終訪問(wèn)地址。
0-3G與mem_map的映射方式:
因linux中 采用的段式映射為flat模式,所以從邏輯地址到線性地址沒(méi)有變化。從段式出來(lái)進(jìn)入頁(yè)式,每個(gè)用戶進(jìn)程都獨(dú)自擁有一個(gè)頁(yè)目錄表(pdt),運(yùn)行時(shí)存放于 CR3。 CR3(頁(yè)目錄) + 前10位 => 頁(yè)面表基址 + 中10位 => 頁(yè)表項(xiàng) + 后12位 => 物理頁(yè)面地址
3G-4G與mem_map的映射方式:
分為三種類(lèi)型:低端內(nèi)存/普通內(nèi)存/高端內(nèi)存。
低端內(nèi)存:3G-3G+16M 用于DMA __pa線性映射
普通內(nèi)存:3G+16M-3G+896M __pa線性映射 (若物理內(nèi)存<896M,則分界點(diǎn)就在3G+實(shí)際內(nèi)存)
高端內(nèi)存:3G+896-4G 采用動(dòng)態(tài)的分配方式
4、高端內(nèi)存(假設(shè)3G+896為高端內(nèi)存起址)
作用:訪問(wèn)到1G以外的物理內(nèi)存空間。
線性地址共分為三段:vmalloc段/kmap段/kmap_atomic段(針對(duì)與不同的內(nèi)存分配方式)
從內(nèi)存分配函數(shù)的結(jié)構(gòu)來(lái)看主要分為下面幾個(gè)部分:
a.伙伴算法(最原始的面向頁(yè)的分配方式)
alloc_pages 接口:
struct page * alloc_page(unsigned int gfp_mask)--分配一頁(yè)物理內(nèi)存并返回該頁(yè)物理內(nèi)存的page結(jié)構(gòu)指針。
struct page * alloc_pages(unsigned int gfp_mask, unsigned int order)--分配 個(gè)連續(xù)的物理頁(yè)并返回分配的第一個(gè)物理頁(yè)的page結(jié)構(gòu)指針。
<釋放函數(shù):__free_page(s)>
內(nèi)核中定義:#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
最終都是調(diào)用 __alloc_pages.
其中MAX_ORDER 11,及最大分配到到頁(yè)面?zhèn)€數(shù)為2^10(即4M)。
分配頁(yè)后還不能直接用,需要得到該頁(yè)對(duì)應(yīng)的虛擬地址:
void *page_address(struct page *page);
低端內(nèi)存的映射方式:__va((unsigned long)(page - mem_map) << 12)
高端內(nèi)存到映射方式:struct page_address_map分配一個(gè)動(dòng)態(tài)結(jié)構(gòu)來(lái)管理高端內(nèi)存。(內(nèi)核是訪問(wèn)不到vma的3G以下的虛擬地址的) 具體映射由kmap / kmap_atomic執(zhí)行。
get_free_page接口:(alloc_pages接口兩步的替代函數(shù))
unsigned long get_free_page(unsigned int gfp_mask)
unsigned long __get_free_page(unsigned int gfp_mask)
Unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order)
<釋放函數(shù):free_page>
與alloc_page(s)系列最大的區(qū)別是無(wú)法申請(qǐng)高端內(nèi)存,因?yàn)樗祷氐绞且粋€(gè)線性地址,而高端內(nèi)存是需要額外映射才可以訪問(wèn)的。
b.slab高速緩存(反復(fù)分配很多同一大小內(nèi)存) 注:使用較少
kmem_cache_t* xx_cache;
創(chuàng)建: xx_cache = kmem_cache_create(“name”, sizeof(struct xx), SLAB_HWCACHE_ALIGN, NULL, NULL);
(責(zé)任編輯:VEVB)
新聞熱點(diǎn)
疑難解答
圖片精選