- 論壇徽章:
- 2
|
第2章
2.2節(jié)需要理解的點:
*頁式存儲管理相對于段式存儲管理的好處:大小固定,方便管理;換出到磁盤時,提高效率
*i386既有段式存管,又有頁式存管,是因為他在支持頁式的時候,段式已經(jīng)存在相當長時間了,為了保留已有資源,Linux內(nèi)核作為軟件要面對他,也只能跟著多此一舉,只能“服從”,實際上是“欺騙”
*通過“Hello world!\n”程序熟悉地址映射全過程
a. ld為elf格式可執(zhí)行代碼從0x8000000開始安排代碼段,運行時用內(nèi)核分配的物理頁面決定到底在內(nèi)存的什么地方
b. CPU根據(jù)指令性質(zhì)判斷相應地址對應的段寄存器,根據(jù)段寄存器值(“|-描述項下標-|-GDTR/LDTR-|-權(quán)限-|”)以及邏輯地址,得到段映射得到的虛擬地址
c. 內(nèi)核建立新進程時,會將regs(進程的寄存器“現(xiàn)場”吧)的cs,ds、es、ss的值分別設(shè)置為__USER_CS(index=4,TI=0,RPL=3),__USER_DS(index=5,TI=0,RPL=3),這里驗證了“第2、3個描述項用于內(nèi)核代碼段和數(shù)據(jù)段,第4、5項用于當前進程的代碼段和數(shù)據(jù)段”這句話
內(nèi)核進程RPL=0,用戶進程RPL=3
d. GDT內(nèi)容固定不變,其中根據(jù)第4、5個描述項內(nèi)容,可以計算基地址為0,段長度為4GB,從而Linux中虛擬地址到線性地址映射不變,糊弄i386 CPU,而之所以可以糊弄,是因為Linux保護機制是在頁式管理做的,不依賴i386本身的保護
內(nèi)核進程DPL=0,用戶進程DPL=3
e. asm volatile("movl %0,%%cr3": :"r" (__pa(next->pgd)));進入內(nèi)核,切換到新進程
這行代碼切換了CR3值,會不會造成前后的代碼不連續(xù)?個人理解,不知道對不對,希望大牛指導:這是不是因為在內(nèi)核里,地址不會經(jīng)過頁式映射,即不會受到CR3影響?因為可以反過來想CR3是干什么的,是切換用戶進程的,而不內(nèi)核只有一個,沒有“在不同內(nèi)核切換”的說法,頂多內(nèi)核態(tài)用戶態(tài)之間有切換;蛘哒f,GDTR=CR3所指向的GDT,讓每個用戶進程的空間隔離了,才使得每個進程都有“3GB”自己獨立空間,如果在內(nèi)核態(tài)地址映射也這樣,內(nèi)核豈不也“虛擬”了,但實際上內(nèi)核空間是共享的。
f. 根據(jù)線性地址(與邏輯地址一樣),以及剛設(shè)置好CR3賦值到GDTR所指向的目錄表,結(jié)合線性地址映射物理地址過程,得到物理地址
*段描述項結(jié)構(gòu)
*分頁管理由硬件支持,并且得用高速緩存,所以很快
*modify_ldt(),vm86(),暫且不管
*經(jīng)過前面軟硬件對比,可以發(fā)現(xiàn),Linux內(nèi)核要面對的是各種CPU,所以不能依賴某一種CPU的特性去完成某種機制,換句話說,如果遇到另外一種CPU沒有這種特性,那么這種機制也失效了,作為Linux,他是不會讓這種情況發(fā)生的,所以看到一些不和睦的地方:
Linux內(nèi)核不理i386 CPU意圖一:三層映射“欺騙”兩層映射
Linux內(nèi)核不理i386 CPU意圖二:糊弄i386的段頁映射,邏輯地址->線性地址不變
Linux內(nèi)核不理i386 CPU意圖三:ds、es、ss都賦值__KERNEL_DS或__USER_DS
Linux內(nèi)核不理i386 CPU意圖四:Intel希望每個用戶進程用自己的LDT,但Linux內(nèi)核建立的進程,TI=0,即都用GDT。LDT只是在VM86模式中運行wine能及其它在Linux上模擬運行Windows軟件或DOS軟件的程序中才使用 |
|