內存分頁機制的理解

                                  理解內存分頁機制
老是沒理解這個東東,今天決定好好看看。
windows NT引入了內存分頁機制,此種內存管理機制,使得從應用程序角度來看,其是獨佔使用4
GB的內存空間,應用程序間內存空間隔離而互不影響,一個進程崩潰不會蔓延、影響到其它進程,另外使得虛擬內存機制成爲可能,把暫時不用的內存頁交換到磁盤pagefile文件中,需要時再交換進來。
內存分頁機制是把物理內存按固定大小分成很多個等份,一般爲4K大小,下面也以4K爲一頁來說明,每個等份稱爲一頁,我稱它爲物理頁,線性地址空間也進行了分頁,我稱它爲線性頁,對於某個進程可訪問的線性地址空間0~0x3fffffff,如何映射到物理內存中呢?也就是說線性頁如何映射到物理頁呢?線性頁和物理頁好像沒人如此叫,我來引入一個。下面來探討一下。
    原來在進程地址空間的0xC0000000起始處的4M空間,到0xC03fffff結束,存放了各個線性頁所對應的物理頁的物理地址值,每4字節爲一項,每1024個項組成一個頁表PT,故共1024個PT,頁表內的項索引叫PTE(page table entry),如第一個線性頁,即0~0x00000fff線性地址空間,其物理頁是哪個呢?顯然是線性地址0xC0000000指向的DWORD值,依此類推,第二個線性頁,物理頁爲線性地址0xC0000001的值,線性頁映射到物理頁後加上頁內偏移就可以得到物理地址了,原來挺簡單的嘛。
 顯然頁內偏移爲線性地址的末尾12位嘛,即有如下公式:
 offset=LA && 0x00000fff
LA : 線性地址,line address
offset:頁內偏移
PA:物理地址,physic address
理解了前面的描述,易知,線性地址的高20位即爲PTE索引
 即有PA=*(0xC0000000+LA>>12*4),*表示取地址內容

那0xC0000000開始的4M線性地址,物理頁是哪些呢?我們來計算一下
 0xC0000000+0xC0000000>>12*4=0xC0300000

可見0xC0300000開始的頁表比較特殊,稱爲頁目錄表,該表的每一項正好指向一個頁表的開始位置,也就是頁表的表,頁目錄表的索引,稱爲PDE(page directory entry),
 假設知道了一個線性地址的PDE,PTE,可按以下公式計算物理地址:
 PA = *(0xC0000000+PDE*1024*4+PTE*4)
    = *(0xC0000000+(PDE<<10+PTE)<<2)
 對比前面的公式,
  *(0xC0000000+LA>>12*4) == *(0xC0000000+(PDE<<10+PTE)<<2)
  LA>>12 == (PDE<<10+PTE)
 PDE,PTE最大1024=2的10次方,所以PDE即爲線性地址的高10位,PTE爲線性地址的中間10
位,線性地址的低12爲頁內偏移。
 有些文章中提到的PDE地址,PTE地址,如何理解?
 PDE地址指線性地址在頁目錄表對應項的地址,
  PDE_add=LA>>22+0xC0300000

 PTE地址指線性地址在頁表對應項的地址,
  PTE_add=LA>>12+0xC0000000
 PTE地址低12位包含了頁屬性,用windbg可看到
 lkd> dt _hardware_PtE
nt!_HARDWARE_PTE
   +0x000 Valid            : Pos 0, 1 Bit
   +0x000 Write            : Pos 1, 1 Bit
   +0x000 Owner            : Pos 2, 1 Bit
   +0x000 WriteThrough     : Pos 3, 1 Bit
   +0x000 CacheDisable     : Pos 4, 1 Bit
   +0x000 Accessed         : Pos 5, 1 Bit
   +0x000 Dirty            : Pos 6, 1 Bit
   +0x000 LargePage        : Pos 7, 1 Bit
   +0x000 Global           : Pos 8, 1 Bit
   +0x000 CopyOnWrite      : Pos 9, 1 Bit
   +0x000 Prototype        : Pos 10, 1 Bit
   +0x000 reserved         : Pos 11, 1 Bit
   +0x000 PageFrameNumber  : Pos 12, 20 Bits
   當0位爲1時,說明PTE有效,頁在物理內存中,而7位的LargePage表示當前虛擬地址大於等於0x80000000並且小於0xa0000000(減去0x80000000就得到了物理地址)
   CPU是如何計算一個線性地址的物理地址的呢?以下參考了一些網上資料。
   1 CR3寄存器保存了當前活動進程的頁目錄所在物理頁地址,CPU通過CR3找到當前頁目錄所在的物理頁地址a
   2 計算PDE的物理地址:a+ 線性地址高10位左移兩位 (因爲每個頁目錄項四個字節),取出該地址處的PDE,PDE的前20位+低12位0是這個虛擬地址對應頁表的物理地址b
   3 計算PTE的物理地址:b+ 虛擬地址的中間10位左移兩位,取出該地址處的PTE,PTE的前20位是這個虛擬地址+低12位0是所對應物理頁的地址c
   4 計算該虛擬地址對應的物理地址:c + 虛擬地址最低12位

寫了這麼多,發現比以前理解多了,看來不太理解的問題,自己嘗試去寫下來,就理解了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章