之二 X86頁式記憶體管理

2021-06-26 17:54:29 字數 2145 閱讀 4989

記憶體管理的目的是什麼?記憶體管理本身就像乙個外觀模式,它隱藏底層細節而給應用程式提供乙個統一易用的訪問記憶體的介面。程式可以訪問4g空間中的任意位址,但實際上物理記憶體可能只有幾百m,這之間的矛盾該怎麼解決?關鍵時刻,還是得抱硬碟的大腿。當可用記憶體不足時,將記憶體中不緊急的內容從記憶體中換出到磁碟上,從而騰出記憶體給更緊急的程式使用。當需要訪問之前的內容時,再將磁碟中資料讀入到記憶體中。記憶體管理就這樣遊走在程序的夾縫中,像魔術師一樣硬生生的將幾百m的記憶體用出「就像有4g記憶體一樣」的效果。

核心問題來了,記憶體與磁碟的換入換出,該如何進行呢?顯然,為了降低系統的複雜度,每次換入的基本單元其大小最好固定,不能太大,太大則影響換入速度,也不能太小,太小則換入太頻繁。

那在段式管理中,該如何操作呢?將整個段一次性換入換出嗎?可是每個段的長度不固定呀,而且整個段似乎也太大了。有人會說,段選擇符最多支援8192個段(16位段暫存器的高13位用來索引段描述符),將4g的空間分攤到8192個段上,每個段的大小平均512k,可以滿足要求了吧,但是cpu中只有6個段暫存器(cs/ds/ss/es/gs/fs),要訪問8192個段,需要頻繁的切換段暫存器的內容,這也是一筆不小的開銷呀。

為了解決這個問題,intel在386引入頁式記憶體管理管理。由於有向前相容的包袱,而且記憶體的「保護模式」也是建立在段式記憶體管理之上的,intel的頁式管理不可能另起爐灶,只能在段式管理的基礎上實現。某本書的作者說「加層是解決計算機問題的萬金油」(原話可能不是這樣),誠不我欺也。在段式記憶體管理中,訪存指令中的「邏輯位址」經過段式轉換,變成了傳送到位址匯流排上的「實體地址」,這裡加層處理就是:「邏輯位址」經過段式轉換後,不再是「實體地址」而是「線性位址」,「線性位址」經過頁式記憶體管理轉換後才是最終發往位址匯流排上的「實體地址」。

頁式記憶體管理中將4gb位址空間分割成4kb大小的頁面,每個頁面可以對映至記憶體中任意位置處的4kb物理空間(邊界必須與4kb對齊)。在段式記憶體管理中,連續的邏輯位址對映到物理記憶體中也是連續的,而在頁式記憶體管理中,連續的線性位址對映到物理記憶體中就不一定是連續的了,這也正是頁式管理的靈活所在。由於頁式管理的引入,32位的線性位址有了新的解釋,如下:

其中高10位用作目錄表索引,一共可以索引1024個目錄項,目錄項是乙個32位的數,其中的高20位指向該目錄項對應的頁面表。同樣頁面表中有1024個頁面項,每個頁面項也是32位的數,其高20位指向物理頁面的基位址(邊界必須與4kb對齊),由於每個頁面有4kb的空間,所以線性位址中的低12位用來表示在頁面內的偏移。可見,如果我們可以獲取到目錄表的基位址,就可以將乙個線性位址轉換為對齊的實體地址了。剛剛好,intel的cpu中增加了乙個暫存器cr3,指向當前頁面表的基址。轉換過程示意如下:

那麼,為什麼要分兩個層次,先找到目錄項再找到頁面表,為什麼不一步到位直接在頁面表中找到對應的頁面?這是出於空間效率的考慮。假定一步到位即目錄表索引與頁面表索引合二為一的話,頁面表將有1k*1k=1m個頁面表項,其能定址的範圍也是1m*4k=4g,但是考慮到乙個程序不可能用到全部的4gb空間,所以某些頁面表項是不可能被訪問到的,那該頁面表項所占用的空間(32位)白白浪費了。而在分層處理中就不存在類似的問題,如果目錄表中的某個目錄項為空,則不用設定其對應的包含1024個頁面表項的頁表,從而省下一部分空間。當然最壞的情況下,假定乙個程序用滿全部的4g空間,分兩個層次會多出乙個目錄表(1024*4byte)的開銷,不過這種概率是極低的。另外,乙個頁面是4kb,而乙個頁面表也是4kb,乙個頁面剛好可以存下了。這樣一來,物理頁面的起始位址以及頁面表的基位址都與4kb對齊,位址的低12位都為0,而指向物理頁面起始位址的頁面表項以及指向頁面表基位址的目錄項,只需要有20位用於指標就夠了,剩餘的12位則可用於控制字段,目錄項的結構體如下:

頁表項的結構體與此類似,但沒有ps欄位,但d欄位則有效(d欄位在目錄項中保留不用),表示該頁面已經被寫過,所以髒了。最低位的p,表示頁面表或者相應的頁面是否在記憶體中,如果p為0,則試圖訪問該頁面時,cpu會觸發缺頁異常「page fault」,注意,這裡的異常是核心有意為之,目的是進入核心的異常處理程式,將該頁從磁碟上交換分割槽讀入到記憶體中,並設定相應的基位址,並將p位設定成1。相反,當乙個頁面已經換出到交換分割槽後,可將p設定成0,表項中其餘欄位均無意義,所以可被用來臨時儲存其他資訊,比如被換成的頁面在磁碟上的位置資訊等。

x86架構段頁式記憶體管理機制

記憶體定址總體流程 段暫存器 值得注意的是,計算機在描述記憶體分段時至少需要如下資訊 段的大小 段的起始位址 段的屬性。在80386以後的cpu中,需要使用64位來儲存這些資訊,但段暫存器只有16位 intel為了保持向後相容 因此在保護模式下,需要使用段描述符來儲存這些資訊,而段暫存器儲存的是段選...

X86記憶體管理之分段管理

最近一直在學習x86彙編,自己打算從基礎的開始學習,對以後做嵌入式開發有一定的幫助。今天看了關於在x86處理上兩種關於記憶體管理的方式 分段管理和分頁管理,以及課程中沒有講到的段頁式管理。一.分段管理 在286以下的cpu中 8086,8088 位址線是20位,可定址範圍220b 1m。而在8088...

x86記憶體定址

最近又研究了一下記憶體定址,沒有乙份資料能講的透徹,不是不細緻,而是缺乏整體感,都不全面,讓人看完後沒有乙個整體模型,現就我關心的問題記錄如下,如果要很全面很細緻的記錄的話會花費我很多精力,所以只是記錄大概流程,以後再慢慢修正吧。所有貼圖皆來自網路 一 分段的由來 1.8086 分段的產生主要是因為...