操作系統開發:啓用內存分頁機制

該系列文章是在學習《操作系統真相還原》時通過閱讀後簡化並適當描述整理的學習筆記,首先,致敬作者鄭剛博士,在讀本書時不得不佩服作者計算機底層功力的深厚。


目前我們已進入保護模式,但依然會受到限制,雖然地址空間達到了4GB,但此空間是包括操作系統共享的4GB空間,我們把段基址+段內偏移地址稱爲線性地址,線性地址是唯一的,只屬於某一個進程。

在我們機器上即使只有512MB的內存,每個進程自己的內存空間也是4GB,這是指的虛擬內存空間。

爲什麼要分頁,分段它不香嗎?

一直以來我們都是在內存分段機制下工作的,該模式下如果系統裏面的應用程序過多,或者內存碎片過多無法容納新的進程,則可能會出現進程需要等待,或無法直接運行的局面,而內存分頁機制,理論上只要4KB內存就可以讓程序運行下去。

  • 在分段模式下

  • CPU認爲線性地址等於物理地址,而線性地址是由編譯器編譯出來的,它本身是連續的,所以要想運行程序,物理地址也必須要連續纔行,但在多數情況下物理地址並不是連續的。

  • 在分頁模式下

  • 線性地址可以連續而物理地址是分散的,我們通過某種映射關係來解除線性地址與物理地址的一一對應,然後通過映射機制將他們重新關聯起來,把線性地址關聯到任意的物理地址上面,理論上只要4KB內存就可以運行程序了。

對於分頁機制來說,CPU在硬件層面提供了支持,在CPU實現中,這種映射關係是通過頁表來實現的,由於地址轉換的實時性較高,所以查找頁表的功能也是被CPU硬件支持的。

什麼是一級頁表,它的作用是啥 ?

在保護模式中段寄存器中的內容是段選擇子,選擇子的最終目的就是爲了找到段基址,其內存訪問的核心機制依然是,段基址:段內偏移地址,這兩個地址相加後纔是絕對地址(線性地址),此地址在分段機制下被CPU認爲是物理地址可以直接被送上總線,該計算過程也是由段部件自動完成。

分頁機制依然要建立在分段機制的基礎之上,段部件依然需要工作,而分頁只能在分段機制之後進行。

CPU在不打開分頁機制的情況下,是按照分段方式工作的,將段地址和段內偏移地址經過段部件處理後所輸出的線性地址,CPU就認爲是物理地址,
而如果打開了分頁,段部件輸出的線性地址會變成虛擬地址,虛擬地址不等同於物理地址。

而CPU必須要拿到物理地址纔行,此虛擬地址對應的物理地址需要在頁表中查找,該工作由頁部件自動完成。

  • 分頁機制的思想:
  • 通過映射,可以使連續的線性地址與任意物理內存地址相關聯,邏輯上連續的線性地址其對應的物理地址可以不連續。
  • 分頁作用,將線性地址轉換成物理地址,用大小相等的頁(頁部件)代替大小不相等的段(段部件)。

通常情況下,經過段部件輸出的線性地址也可以叫做虛擬地址,所謂的轉換是指,從線性地址空間(段)到虛擬地址空間(頁)再到物理地址空間(實際),如下圖:

前面說過,分頁機制建立在分段機制之上,即使在分頁機制下的進程也要先經過邏輯上的分段,代碼段和數據段在邏輯上被拆分成爲以頁爲單位的小內存塊,此時的虛擬地址不能存放任何數據。

接着操作系統開始爲這些虛擬內存頁分配真實的物理內存頁,它查找物理內存中的可用頁,然後在頁表中登記這些物理頁地址,此時就完成了虛擬頁到物理頁的映射,每個進程都以爲自己獨享4GB地址空間。

用於存儲這種映射關係的表,就是頁表(PT),頁表中每一行(1個單元格)稱爲頁表項(PTE),其大小是4字節,頁表項的作用是存儲內存物理地址,當訪問一個線性地址時,實際上就是在訪問頁表項中所記錄的物理內存地址。


一個頁可被分爲高低位嗎?

CPU採用一個頁的大小是4KB,32位地址表示4GB空間,可將32爲地址分成高低兩部分,低地址是內存塊大小,高地址是內存塊數量,故內存塊數*內存塊大小=4GB,頁是地址空間的計量單位,只要是4KB的地址空間都可以稱爲一頁,所以線性地址空間也要對應物理地址空間的一頁。

一頁大小是4KB(頁大小是4KB所以頁表項中的物理地址都是4K的整數倍),這樣一來,4GB地址空間被劃分成4GB/4KB=1MB個頁,也就是4GB空間中可容納1048576個頁,頁表中自然也要有1048576個頁表項,這就是一級頁表。

任意一個地址最終都會落到某個實際的物理頁上,32位地址空間共有1MB個物理頁.

首先定位到某個具體物理頁,然後給出物理頁內的偏移量就可以訪問到任意1字節的內存,虛擬地址的高20位用來定位具體的物理頁,低12位則用來在該物理頁內尋址。


一級分頁中的地址轉換過程是怎樣的?

頁表是位於內存中的,在打開分頁前需要將頁表物理地址加載到CR3寄存器內,只要提供頁表物理地址,便能夠訪問到頁表中任意一個頁表項地址。

一個頁表項對應一個頁,所以,用線性地址的高20位作爲頁表項的索引,每個頁表項要佔用 4 字節大小,所以這高20位的索引乘以4後纔是該頁表項相對於頁表物理地址的字節偏移量。用 cr3 寄存器中的頁表物理地址加上此偏移量便是該頁表項的物理地址,從該頁表項中得到映射的物理頁地址,然後用線性地址的低 12 位與該物理頁地址相加,所得的地址之和便是最終要訪問的物理地址。CPU 中集成了專門用來幹這項工作的硬件模塊,我們把該模塊稱爲頁部件。

  • 總結一下頁部件的工作
  • 用線性地址的高 20 位在頁表中索引頁表項,用線性地址的低 12 位與頁表項中的物理地址相加,所求的和便是最終線性地址對應的物理地址。


什麼是二級頁表,它的作用是啥 ?

一級頁表與二級頁表原理一致,但在現代操作系統中一般都採用二級頁表結構,兩種頁表結構區別如下:

  • 1.一級頁表中最多可容納 1M(1048576)個頁表項,每個頁表項是 4 字節,如果頁表項全滿的話,便是 4MB 大小。
  • 2.一級頁表中所有頁表項必須要提前建好,原因是操作系統要佔用 4GB 虛擬地址空間的高 1GB,用戶進程要佔用低 3GB。
  • 3.每個進程都有自己的頁表,進程一多,光是頁表佔用的空間就很可觀了。
  • 4.不要一次性地將全部頁表項建好,需要時動態創建頁表項。

無論是幾級頁表,標準頁的尺寸都是 4KB,所以 4GB 線性地址空間最多有 1M 個標準頁。一級頁表是將這 1M 個標準頁放置到一張頁表中,二級頁表是將這 1M 個標準頁平均放置 1K 個頁表中,每個頁表中包含有 1K 個頁表項。頁表項是 4 字節大小,頁表包含 1K 個頁表項,故頁表大小爲4KB,這恰恰是一個標準頁的大小。

頁目錄表來存儲這些頁表,每個頁表的物理地址在頁目錄表中都以頁目錄項(Page Directory Entry, PDE)的形式存儲,頁目錄項大小同頁表項一樣,都用來描述一個物理頁的物理地址,其大小都是 4 字節,而且最多有 1024 個頁表,所以頁目錄表也是 4KB 大小,同樣也是標準頁的大小。

頁目錄表中共 1024 個頁目錄項,一個頁目錄項中記錄一個頁表物理頁地址,頁大小都是 0x1000,即 4096,每個頁表中有 1024 個頁表項,每個頁表項中是一個物理頁地址,最終數據寫在這頁表項中指定的物理頁中。

二級頁表是如何工作的 ?

二級頁表地址轉換原理是將 32 位虛擬地址拆分成高 10 位、中間 10 位、低 12 位三部分,

  • 高 10 位作爲頁表的索引,用於在頁目錄表(PT)中定位一個頁目錄項(PDE),頁目錄項中有頁表物理地址,也就是定位到了某個頁表。
  • 中間 10 位作爲物理頁的索引,用於在頁表內定位到某個頁表項(PTE),頁表項中有分配的物理頁地址,也就是定位到了某個物理頁。
  • 低 12 位作爲頁內偏移量用於在已經定位到的物理頁內尋址。

訪問任何頁表內的數據都要通過物理地址,由於頁目錄項 PDE 和頁表項 PTE 都是 4 字節大小,給出了 PDE 和 PTE 索引後,還需要乘以 4,再加上頁表物理地址,這纔是最終要訪問的絕對物理地址。

  • 具體流程如下
  • 1.用虛擬地址的高 10 位乘以 4,作爲頁目錄表內的偏移地址,加上頁目錄表的物理地址(CR3內的基地址),所得的和,便是頁目錄項的物理地址。讀取該頁目錄項,從中獲取到頁表的物理地址。
  • 2.用虛擬地址的中間 10 位乘以 4,作爲頁表內的偏移地址,加上在第 1 步中得到的頁表物理地址,所得的和,便是頁表項的物理地址。讀取該頁表項,從中獲取到分配的物理頁地址。
  • 3.虛擬地址的高 10 位和中間 10 位分別是 PDE 和 PTE 的索引值,所以它們需要乘以 4,而低 12 位作爲頁內偏移直接與第2步物理頁地址相加,即可得到實際內存物理地址。

111

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