可能有錯,更新中。。。
用2級頁表將用戶空間的0-3G線性地址映射到256MBSDRAM的物理地址3000 0000-3FFF FFFF中
2^10=1024=0x400 2^12=4096=0x1000 2^14=16384=0x4000
1個頁目錄-->覆蓋3GB物理內存范圍(可以4GB)
1個頁目錄項-->1個頁表-->覆蓋4MB物理內存范圍
1個頁表項-->1個物理頁框-->覆蓋4KB物理內存范圍
1個頁目錄占1個頁框,4KB
一個頁表占1個頁框,4KB
**********************************************************************************************************************
1每個進程對應一個頁目錄(花費4KB內存)--頁目錄應該放在了內核空間的起始地址即0xc000 0000(如果內核空間起始地址映射到了物理空間起始地址處,則上面的例子有些不妥,頁目錄起始地址應該是0x3000 0000才好)
--頁目錄中,每個進程的0-767項不怎么相同,但所有進程的768-1023項和內核頁目錄的768-1023項相同,見ulk3 ch2 進程頁表那節
2.如果進程0將其768個頁目錄項都用完,意味這對應有768個頁表(需花費3MB內存)
所以如果一個內核要完全映射一個大小為3GB的進程(代碼段數據段等的總大小),需要額外用3MB+4KB的內存來保存相關尋址信息
不過現階段貌似不會發生這種情況,最常見的每個進程只使用幾百kB(linux操作系統原理與應用 陳莉君 p95),一個頁目錄+1個頁表(共計8KB)足夠用了
3.兩個相鄰的頁目錄項可以指向不相鄰的物理頁
4.兩個相鄰的頁表項可以指向不相鄰的物理頁
5.頁目錄的內容隨着頁表的增加減少更改而更新,頁表的內容隨着物理頁框的增加減少更改而更新
實際中,剛開始時這些頁表項的內容為空,而在真正要對某個線性地址讀寫數據的時候才會分配物理單元。如下
當訪問一個線性地址如0xBFC0 4FFE時,mmu根據線性地址的信息找到了頁表767的4號頁表項,發現其內容為空,於是發出缺頁中斷,內核控制路徑用get_zerod_page(lkd2 p148)在適當的內存區找到一個物理頁,將該物理頁的page結構體count+1(表明此物理頁已名花有主),然后將此物理頁的首地址塞進4號頁表項里,然后mmu就可以執行上面的第3步了
(現階段是這樣理解的外加一點猜測可能有誤更新中),一個疑問,get_zerod_page返回的是什么樣的線性地址???
當下一次再去訪問這個地址時,由於線性地址已經映射過物理頁框,便可直接訪問
**********************************************************************************************************************
比如要訪問線性地址0xBFC0 4FFE(1byte),
2進制形式
假設linux是按照上圖所示安排進程0的頁目錄和頁表
假設進程0在運行,進程0的頁目錄起始物理地址保存在cr3寄存器中cr3=0x3800 0000
1.mmu先取線性地址高10位(31-22)=767,x4=3068=0xBFC,+cr3=0x3800 0bfc,即頁目錄項在內存的地址,此地址的內容0x392f f000即頁表首地址(頁對齊最后12位清0)
2.mmu取線性地址下面10位數(21-12)=4,x4=16=0x10,+0x392f f000=0x392f f010,即頁表項在內存的地址,此地址的內容0x3080 4000即物理頁面的首地址(頁對齊最后12位清0)
3.mmu取線性地址最后12位數(11-0)=4094=0xffe作為低12位,0x3080 4000的前20位作為高20位,組成一個新的32位數0x3080 4ffe即線性地址0xBFC0 4FFE對應的物理地址
內核中涉及的不都是線性地址嗎?而要從線性地址得到物理地址要經過mmu轉換,現在mmu還沒開始呢,那么內核從哪里搞來這個物理地址的呢?下面回答了這個問題,不是所有的線性地址都經過mmu才能找到物理地址的,_pa也可以,他給mmu的上場表演開了一個頭
(
進程的頁目錄PGD(屬於內核數據結構)就處於內核空間中。在進程切換時,要將寄存器CR3設置成指向新進程的頁目錄PGD,而該目錄的起始地址在內核空間中是虛地址,但CR3所需要的是物理地址,這時候就要用__pa()進行地址轉換。在mm_context.h中就有這么一行語句:
asm volatile(“movl %0,%%cr3”: :”r” (__pa(next->pgd));
這是一行嵌入式匯編代碼,其含義是將下一個進程的頁目錄起始地址next_pgd,通過__pa()轉換成物理地址,存放在某個寄存器中,然后用mov指令將其寫入CR3寄存器中。經過這行語句的處理,CR3就指向新進程next的頁目錄表PGD了。
refer to http://oss.org.cn/kernel-book/ch06/6.1.2.htm
)
一個進程的線性地址范圍是0-3GB,即線性地址在c000 0000以內,即前12位是1100 0000 00以內,即768以內,即最多有768個頁目錄項,項索引為0-767(其余的768-1023項內容見上所述),所以可以尋址3GB的物理內存,但范圍可以不限於0-3GB,即映射到哪個物理頁由頁表項的內容決定,比如一個頁表項內容是CFFF 1000,則訪問此物理頁,即物理地址不會局限在c000 0000以內
*****************************************************************************************************************************************
頁表項的內容代表了實際的物理地址,所以如果一個系統僅有256MB的內存,則共需64個頁表,64x1024個頁表項,且物理地址從0x3000 0000開始,那么頁表項的內容應該在0x3000 0000---0x3FFF FFFF之間的數字即
0x3000 0000
0x3000 1000...
0x303F F000
0x3040 0000
0x3040 1000...
0x307F F000
0x3080 0000
0x3080 1000...
0x30BF F000
0x30C0 0000
0x30C0 1000...
0x30FF F000
0x3100 0000
0x3100 1000...
0x313F F000
0x3140 0000
0x3140 1000...
0x317F F000
...
...
0x3FC0 0000
0x3FC0 1000...
0x3FFF F000
具有256MB內存的mini2440的頁表內容的應該此范圍內----可惜linux2.6.32.2用4級頁表,所以不成立
內核負責維護頁表項的內容,因為內核知道哪個物理頁面可以用,但手動幫內核修改一下頁表項的內容便可實現操作特定的物理頁面的效果
*****************************************************************************************************************************************
頁目錄項或頁表項的最后12位是其屬性,具體格式如下(上面為了表達簡潔,將最后12位全設0,實際不是)
(點擊查看大圖)圖4-18 頁目錄和頁表的表項格式
P--位0是存在(Present)標志,用於指明表項對地址轉換是否有效。P=1表示有效;P=0表示無效。在頁轉換過程中,如果說涉及的頁目錄或頁表的表項無效,則會導致一個異常。如果P=0,那么除表示表項無效外,其余位可供程序自由使用,如圖4-18b所示。例如,操作系統可以使用這些位來保存已存儲在磁盤上的頁面的序號。
R/W--位1是讀/寫(Read/Write)標志。如果等於1,表示頁面可以被讀、寫或執行。如果為0,表示頁面只讀或可執行。當處理器運行在超級用戶特權級(級別0、1或2)時,則R/W位不起作用。頁目錄項中的R/W位對其所映射的所有頁面起作用。
U/S--位2是用戶/超級用戶(User/Supervisor)標志。如果為1,那么運行在任何特權級上的程序都可以訪問該頁面。如果為0,那么頁面只能被運行在超級用戶特權級(0、1或2)上的程序訪問。頁目錄項中的U/S位對其所映射的所有頁面起作用。
A--位5是已訪問(Accessed)標志。當處理器訪問頁表項映射的頁面時,頁表表項的這個標志就會被置為1。當處理器訪問頁目錄表項映射的任何頁面時,頁目錄表項的這個標志就會被置為1。處理器只負責設置該標志,操作系統可通過定期地復位該標志來統計頁面的使用情況。
D--位6是頁面已被修改(Dirty)標志。當處理器對一個頁面執行寫操作時,就會設置對應頁表表項的D標志。處理器並不會修改頁目錄項中的D標志。
AVL--該字段保留專供程序使用。處理器不會修改這幾位,以后的升級處理器也不會。
原文鏈接:https://blog.csdn.net/opencpu/article/details/6784344