今天查找頁表映射資料時,無意發現一個有趣的概念,就是頁表自映射。
頁目錄基址記為PDT,頁目錄項記為PDE,頁表項記為PTE。BITS(m,n,value)表示取value從高m位到高n位的值。
32位系統下,所有的PTE所占的空間剛好是4MB。如果將這些PTE連續地放在內存中,那么這4MB內存空間對應的PTE(稱為PTE的PTE)剛好在一個4KB頁中,而這個4KB在頁目錄表中剛好也占一項。
如果再合理地設置4MB頁表的地址,那么就可以使得PTE的PTE所占的4KB的內容與PDE所占的4KB的內容完全相同。這樣一來,可以就可以將頁目錄表也作為一個頁表,這也意味着,頁目錄表中有一項會指向自己。
頁目錄表本身占用4KB,所以它也剛好對應了一個PTE。而從前面的設置可以知道頁目錄表本身也是一個頁表,那么指向頁目錄表的那個PTE必然也在頁目錄表當中。頁目錄表基址經過兩級頁表轉換之后仍然可以轉換成自己的物理地址,所以頁目錄表基地址的對應的PDE指向自己,對應的PTE也指向自己。
符合上面的要求的一個實例:將頁表安排在0xc0000000~0xc0400000,頁目錄安排在0xc0300000~0xc0400000。
按照上面的設置,可以如下兩個效果:
1. 通過一個頁的PTE(xPTE)的虛地址v_pte,可以直接得到該頁的虛地址為(v_pte<<10)
2. 通過一個頁表的PDE(xPDE)的虛地址v_pde,可以直接得到該頁表所在頁的虛地址為( v_pde<<10)
下面來解釋一下為什么:
1.1 首先看看v_pte自己轉換成物理地址的過程
1.1.1 v_pte取出BITS(31,22)在頁目錄表中查找,根據上面的設置,找到的PDE項剛好指向頁目錄表
1.1.2 再取出BITS(21,12),在頁目錄表(此時頁目錄表也作為一個頁表)中查找,找到的PTE項指向xPTE所在的頁表
1.1.3 再計算頁內偏移,找到了xPTE的物理地址
1.2 再來看看(v_pte<<10)轉換成物理地址的過程
1.2.1 (v_pte<<10)取出BITS(31,22)(即v_pte的BITS(21,12))在頁目錄表中查找,根據上面的巧妙設置,相當於1.1.2的過程,取到的PDE項指向xPTE所在的頁表
1.2.2 (v_pte<<10)取出BITS(21,12)(即v_pte的BITS(11, 2)在xPTE所在頁表查找,找到的剛好是xPTE這個PTE
1.2.3 xPTE指向的頁面的物理地址加上(v_pte<<10)的低12位(低12位為全0)就是(v_pte<<10)的物理地址。也就是說(v_pte<<10)對應的物理地址剛好就是xPTE指向的頁面的物理地址,反過來,也就是說(v_pte<<10)就是這個頁面的虛地址。
2.1 首先看看xPDE自己的虛地址如何轉換成物理地址
v_pde的BITS(31,12)剛好就等於頁目錄表基址,按照頁目錄表和頁表位置的安排,有
2.1.1 v_pde取出BITS(31,22),找到的PDE指向頁目錄表本身
2.1.2 v_pde取出BITS(21,12),找到的PTE也指向頁目錄表本身
2.1.3 v_pde取出BITS(11,0)作為偏移,加上頁目錄表的物理地址,得到v_pde的物理地址
2.2 再來看看(v_pde<<10)的虛地址如何轉換成物理地址
2.2.1 (v_pde<<10)取出BITS(31,22),也就是v_pde的BITS(21,12),在頁目錄表中查找,找到的PDE指向頁目錄表本身,這一步相當於2.1.2
2.2.2 (v_pde<<10)取出BITS(21,12),也就是v_pde的BITS(11, 2),仍在頁目錄表中查找,找到的就是xPDE所指向的頁表的物理地址
2.2.3 (v_pde<<10)的BITS(11,0)為全0,所以轉換出來的物理地址等於xPDE所指向的頁表的物理地址。(v_pde<<10)的物理地址等於xPDE所指向的頁表的物理地址,反過來看,(v_pde<<10)就是xPDE所指向的頁表的虛地址。
參考資料: