以前的一片文章講了為什麼會出現分頁, 是為了解決什麼問題?
- 首先澄清一個概念.其實虛拟記憶體和分頁是兩件事, 分頁是指将把位址空間人為地等分成固定大小的頁, 這個頁的粒度比段更小, 以友善在外存與記憶體換入換出, 而虛拟記憶體是為了解決程式的加載和重定位的問題, 即解除線性位址與實體位址之間的相等關系, 因為如果這樣, 線性位址是由編譯器翻譯出來的, 它本身是連續的, 而實體位址也必須連續才行, 但實體記憶體往往在運作時間長了之後, 成為各個碎片, 這就導緻實體位址很難成為連續的(是以平時使用完電腦要記得關機), 是以要建立一種線性位址與實體位址之間的映射關系.而且虛拟記憶體可以同樣解決程式重定位問題, 是以這就是天選之子啊! 對, 忘了說, 虛拟記憶體就是說邏輯上建立一張表, 讓每個程序都擁有一張固定大小的位址空間,是假的, 隻是邏輯上建立一張映射關系. 現代作業系統都是讓每個程序邏輯上擁有4GB的空間.
-
由于分頁功能的出現, 弱化了人們關于分段機制是否合理的信心. 記憶體的通路是通過頁目錄表和頁表進行的, 每個任務都有自己的頁目錄表和頁表, 作業系統控制着實體頁的配置設定權, 除非他把一個也配置設定給某個任務, 并填寫到那任務的頁目錄表和頁表裡, 否則, 那個任務不可能擁有通路那個記憶體位置的權利. 但分頁機制還是建立在分段機制之上的. Intel之是以這麼多年長盛不衰的原因, 我想很大一部分是由于他的向下相容性, 是以即使這個機制已經沒有作用了, 但是還是的用, 是以在保護模式下, 還是要經過段部件處理後, 得到線性位址, 然後經過頁部件轉換, 得到實體位址. 盡管處理器的設計者一直在宣稱, 把分段和分頁機制結合在一起, 将獲得最大強度的保護功能, 但是, 事實上, 在現實的軟體設計者那裡, 多段模式已經不那麼吃香了.
典型的, 32位的處理器擁有32根位址線, 64位處理器擁有64根位址線, 這使得他不用将4GB或多于4GB的記憶體空間劃分成多個段, 就能完全控制它. 如此一來, 軟體設計者就會傾向于不分段 .
- 平坦模式(Flat Model): 将全部的4GB記憶體整體上作為一個大段來處理, 而不是分成小的區塊. 在這種模型上, 所有的段都是4GB, 每個段的段描述符都指向4GB的段, 段的基位址都是0x00000000, 段界都是0xFFFFF, 粒度為4KB.
啟用分頁機制,我們需要做三件事:
- 準備好頁目錄表及頁表
- 将頁表位址寫入控制寄存器cr3
- 寄存器cr0的PG位置1
首先, 開始說第一件, 建立頁目錄表和頁表
分頁機制本質上将大小不同的大記憶體段拆分成大小相等的小記憶體塊. 記憶體塊數 * 記憶體塊大小 = 4GB, 現在普遍采用的虛拟位址空間為4GB.

滑塊的位置不能太偏左, 記憶體塊太大, 會導緻程式的換入換出不友善, 實體記憶體的使用率低, 滑塊的位置不能太偏右, 記憶體塊太小, 會導緻頁表占用記憶體過多.而現在作業系統普遍将記憶體塊的尺寸規定為12位, 4KB.
每個程序邏輯上有4GB的位址空間, 4GB/ 4KB = 1M, 是以需要1M個頁表項, 32位下實體記憶體也為4GB, 是以索引到一個具體的實體位址上, 也需要32位, 如果程序使用一級頁表的話, 需要1M * 4B = 4MB, 每個程序需要4MB的實體記憶體存儲頁表. 但是對于大多數程式, 他使用不了所有的記憶體空間, 是以頁表項大多都是空的, 這樣就引入了二級頁表
二級頁表:
由上面我們能得出結論, 我們需要1M個頁表項, 1M = 1K * 1K, 而一張頁表大小= 4KB, 4KB / 4B = 1K, 是以我們可以一張頁目錄表, 1K張頁表, 而如果有連續的空間空閑, 比如 n * 1k * 4KB, 那是不是這n張頁表就可以不配置設定記憶體, 而有一張頁目錄表就可以标志n張頁表在實體記憶體中不存在, 這樣就能節省下來實體記憶體.
接下來開始說, 二級頁表位址轉換原理.
由于頁的大小都是4KB, 是以頁表項中的實體位址都是4K的整數倍, 是以可以講32位的位址劃分成20:12, 前20位用來索引實體頁, 後12位用來确定偏移位址.
在二級頁表是這樣的:
每個頁表中可容納 1024 個實體頁,故每個頁表可表示的記憶體容量是 1024 * 4KB = 4MB。頁目錄中共有1024 個頁表,故所有頁表可表示的記憶體容量是 1024 * 4MB =4GB ,這己經達到了 32 位位址空間的最大容量。
是以說,任意一個 32 位實體位址,它必然在某個頁表之内的某個實體頁中。我們定位某 個實體頁,必然要先找到其所屬的頁表。頁目錄中 1024 個頁表,隻需要 10 位二進制就能夠表示了,是以,虛拟位址的高10 位(第 31 ~22 位)用來在頁目錄中定位一個頁表,也就是這高 10 位用于定位頁目錄中的頁目錄項 PDE,PDE 中有頁表實體頁位址。找到頁表後,到底是頁表中哪一個實體頁呢?由于頁表中可容納 1024 個實體頁,故隻需要 10 位二進制就能夠表示了。是以虛拟位址的中間 10 位(第 21 12 位)用來在頁表中定位具體的實體頁,也就是在頁表中定位一個頁表項PTE, PTE中有配置設定的實體頁位址。由于标準頁都是 4KB, 12位二進制便可以表達 4KB之内的任意位址,故線性位址中餘下的 12 (第 11 位)用于頁内偏移量。
經以上分析,二級頁表位址轉換原理是将 32 位虛拟位址拆分成高 10 位、中間 10 位、低 12 位三部分,它們的作用是:高 10 位作為頁表的索引,用于在頁目錄表中定位一個頁目錄項 PDE,頁目錄項中有頁表實體位址,也就是定位到了某個頁表。中間 10 位作為實體頁的索引,用于在頁表内定位到某個頁表項 PTE ,頁表項中有配置設定的實體頁位址,也就是定位到了某個實體頁。低 12 位作為頁内偏移量用于在已經定位到的實體頁内尋址。同一級頁表一樣, 通路任何頁表内的資料都要通過實體位址。由于頁目錄項 PDE 和頁表項 PTE 都是4位元組大小,給出了 PDE和PTE索引後,還需要在背後悄悄乘以4 ,再加上頁表實體位址,這才是最終要通路的絕對實體位址。轉換過程背後的具體步驟如下。
到了現在, 我們該講講頁目錄項和頁表項的事啦, 一直說它是4位元組大小, 用來存儲實體頁位址, 但也一直未曾見過他們的真面目.
具體位什麼意思, 此處不多加闡述.
其他有待補充…