第2章 存儲(chǔ)管理
LINUX頁(yè)式管理
PGD PMD PT PTE
頁(yè)表目標(biāo) 中間目錄 頁(yè)表 頁(yè)表項(xiàng)
LINUX在32位地址下采取二層映射
#define PGDIR_SHIFT 22
#define PTRS_PER_PGD 1024
#define PMD_SHIFT 22
#define PTRS_PER_PMD 1
#define PTRS_PER_PTE 1024
根據(jù)以上宏定義,PMD被完美的架空了,而相當(dāng)于采取了二層映射
其中PGD用了線性地址的最高10位 與 MMU 對(duì)應(yīng)
線性地址的中間10位是所對(duì)應(yīng)的PTE在PT中的索引
剩下的最低12位則是頁(yè)中的偏移量
虛擬地址 = 段基地址:段偏移量
16位 32位
更準(zhǔn)確的講是段選擇子了吧
在LINUX中段基地址 = 0(下面的____KERNEL_CS等),所以可以認(rèn)為線性地址與虛擬地址總是相等的,但其本質(zhì)不是一個(gè)東西
0xC0000000-0xFFFFFFFF為內(nèi)核占用
0x0-0xBFFFFFFF為用戶控件
內(nèi)核的虛擬內(nèi)存為簡(jiǎn)單的線性映射
#__PAGE_OFFSET (0xC0000000)
#define PAGE_OFFSET ((unsigned long) __PAGE_OFFSET)
#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x) +PAGE_OFFSET)
__pa是從虛擬地址轉(zhuǎn)換成物理地址
__va是從物理地址轉(zhuǎn)換成虛擬地址
在GDT中有4個(gè)段描述符
其索引是2-5
分別是
__KERNEL_CS 內(nèi)核代碼段
__KERNEL_DS 內(nèi)核數(shù)據(jù)段
__USER_CS 用戶代碼段
__USER_DS 用戶數(shù)據(jù)段
#define start_thread(regs,new_eip,new_esp) do {\
__asm__("movl %0,%%fs;movl %0,%%gs"::"r"(0)); \
set_fs(USER_DS);
regs->xds = __USER_DS; \
regs->xes = __USER_DS; \
regs->xss = __USER_DS; \
regs->xcs = __USER_CS; \
regs->eip = new_eip; \
regs->esp = new_esp; \
}while(0)
通過(guò)這段宏可以看出,LINUX沒(méi)用段式存儲(chǔ),雖然它也走了這個(gè)流程
MMU的流程 MMU使用物理地址
頁(yè)式映射
從REG CR3拿PGD的地址
找到頁(yè)面目錄,線性地址中的高10位為索引,找到頁(yè)面目錄項(xiàng),從中拿高20位作為頁(yè)面表的索引,頁(yè)面表與4k字節(jié)邊界對(duì)齊,CPU自動(dòng)補(bǔ)充前12位為0得到頁(yè)面表地址。
然后拿線性地址的中間10位,得到頁(yè)面表中的索引,拿到頁(yè)面表項(xiàng),頁(yè)面表項(xiàng)的高20位在低位補(bǔ)充12個(gè)0,再加上線性地址的低12位組成物理地址。
mm_struct 任務(wù)相關(guān)的虛擬內(nèi)存
vm_area_struct 一段虛擬內(nèi)存的抽象,也可以理解為段
mm_struct中擁有vm_area_struct的指針
在vm_area_struct多的時(shí)候使用avl樹來(lái)存儲(chǔ)
mem_map_t 物理頁(yè)表
zone_struct 物理內(nèi)存的區(qū)結(jié)構(gòu),zone_struct把物理內(nèi)存分成了幾個(gè)部分
ZONE_DMA 0 供DMA使用
ZONE_NORMAL 普通使用
ZONE_HIGHMEN 高段內(nèi)存,內(nèi)核映射不到
物理內(nèi)存之間區(qū)的劃分并不是強(qiáng)制的,如果某一個(gè)區(qū)已經(jīng)沒(méi)有內(nèi)存可用,是可以去別的區(qū)拿內(nèi)存的
其實(shí)一直對(duì)內(nèi)核的尋址有些疑問(wèn)
不過(guò)剛剛似乎想通了
內(nèi)核會(huì)做預(yù)映射,把PGD第768項(xiàng)以后的都做映射,也就是1G的空間
而這種映射應(yīng)該是滿足__pa()宏,即線性地址與物理地址是線性映射的。
所以最終__pa()宏被用作在內(nèi)核代碼中顯性的獲得某個(gè)線性地址所對(duì)應(yīng)的物理地址
而MMU負(fù)責(zé)把一個(gè)線性地址隱式的轉(zhuǎn)成了物理地址,而這已轉(zhuǎn)換與內(nèi)核代碼無(wú)關(guān)。
不知這樣理解是否正確?
今天只看到了這里
待續(xù)……
說(shuō)起來(lái)把這么個(gè)東西放到首頁(yè)很不好意思,主要目的是希望有看到的人幫我指正一下我所認(rèn)知的錯(cuò)誤或者解惑。謝謝啦:)