參考:
基本思想:
每個進程擁有自己的地址空間,地址空間被分成許多塊,稱為頁面,每一頁有連續的地址范圍
與地址空間一樣,物理內存也被分成許多塊,塊的大小與頁一樣大,稱為頁框。
頁映射到頁框,被程序引用,一旦程序引用到未映射的頁,就會發生缺頁中斷,把引用的頁映射到頁框,再重新進行引用。
分頁
-
進程并不直接引用物理內存地址,而是先引用虛擬地址,再由內存管理單元(Memory Manaement Unit, MMU)把虛擬地址映射為物理內存地址。
如下圖
image -
虛擬地址與物理內存地址的映射為頁面與頁框的映射關系,頁面映射到了頁框就意味著該頁面在物理內存上。
如下圖
image 一旦進程引用到了未映射的頁面,就會發生缺頁中斷,從映射的頁面中選一個,換上要用的頁面,再重新進行引用。
頁表
每個進程都有自己的頁表,用于記錄自己的虛擬地址和物理內存地址的映射情況,頁表存在MMU。切換進程的時候,頁表也會切換。
-
頁表的最簡單實現是:把虛擬地址分成虛擬頁號(高位部分)和偏移0量(低位部分)。
虛擬頁號作為頁表的索引,找到相應的頁表項,從而找到頁框號,再由頁框號和偏移量構成物理內存地址。
如下圖:
image -
頁表項的結構基本如下:
- 在/不在位:1有效;0無效,引發缺頁中斷
- 修改位:1被修改過,移除頁框時要寫回磁盤;0未修改過,無需寫回磁盤。
- 保護位:1讀/寫;2只讀
-
高速緩存禁止位:對于映射到設備的頁面,不能用被緩存的副本,要用最新的內容。(如鍵盤)
image.png
頁表并不保存頁面的磁盤地址,由另外的機制來保存。
關于分頁的兩個問題
- 虛擬地址到物理內存地址的映射必須非常快
- 如果虛擬地址空間很大,那頁表也會很大。
-
加速分頁過程
解決第一個問題,使用快表(TLB)。TLB是MMU的緩存,用于存儲經常被訪問到的頁表項。
軟失效: 頁面訪問不在TLB,在內存。僅需更新一下TLB,不需要產生磁盤I/O。
硬失效:頁面不在內存。發生缺頁中斷。
針對大內存的頁表
解決第二個問題。-
多級頁表
把虛擬地址劃分為PT1,PT2,Offset,PT1作為頂級頁表的索引,PT2作為二級頁表的索引。
結構上類似B+樹。
一般最多2級,再往上會帶來更大的復雜性。
-
對于32位還可以接受,64位需要耗費的空間太大。
image
-
倒排頁表
一個頁框為一個表項,而不是一個頁面為一個表項,這樣頁表的大小取決于頁框的數量而不是虛擬地址的大小。
缺點:虛擬地址轉換為物理內存地址時要遍歷整個頁表。
改進:使用哈希表來存儲。用虛擬地址來散列。這樣無需遍歷。
頁面置換算法
其他
-
分離數據段和代碼段,節省地址空間
image 父子進程共享代碼段,數據段使用寫時復制。
寫時復制即數據段在未被修改時共享,一旦發生修改操作,就復制數據段,父子進程擁有獨立的數據段。清除策略
啟動一個分頁守護進程的后臺進程,定期喚醒檢查分頁情況,在空閑頁框過少時,通過頁面置換算法確保空閑頁框的數量。