天天看點

計算機系統——虛拟記憶體

實體記憶體和虛拟記憶體

通常所說的實體記憶體就是計算機記憶體條上的實際記憶體容量,是實體的記憶體大小。計算機主存被組織成由M個連續的位元組大小的單元組成的數組。每個位元組有唯一的實體位址。CPU通路記憶體最自然的方式就是直接使用實體位址進行實體尋址。

計算機系統——虛拟記憶體

虛拟記憶體是作業系統為作為記憶體使用的一部分磁盤空間,虛拟記憶體在磁盤上實際上就是一個碩大無比的檔案,其不是實體存在的(為了滿足實體記憶體的不足而提出的政策)。現在的作業系統大多數使用虛拟尋址來通路主存。大體過程就是CPU生成一個虛拟位址,虛拟位址在被送到記憶體之前會轉換成适當的實體位址(位址翻譯)。通過虛拟位址再進行實體尋址。

計算機系統——虛拟記憶體

位址空間是由表示最大位址所需要的位數來描述的。如一個包含N=2^n個位址的位址空間就叫做一個n位的位址空間。

虛拟記憶體作為緩存工具

如之前所說,虛拟記憶體概念上就是存放在磁盤上的N個連續的位元組大小的單元組成的數組。每個位元組都有一個索引,稱為虛拟位址。這個數組的部分内容會緩存在主存中(DRAM)。VM系統會将虛拟記憶體分成虛拟頁,每個虛拟頁的大小為P=2^p,類似的也有實體頁(頁幀)。

虛拟頁可分成三種:

  • 未配置設定的:VM系統還沒有配置設定的頁,就是還沒有在磁盤上生成的,是以不占用任何磁盤空間。
  • 緩存的:已經在實體記憶體中緩存的頁。
  • 未緩存的:沒有緩存在實體記憶體中的頁,就是雖然在磁盤上存在但是沒有緩存到DRAM中。
計算機系統——虛拟記憶體

虛拟頁0和3沒有配置設定,是以在磁盤上不存在,虛拟頁1,4,6緩存在實體記憶體中,頁2,5,7雖然被配置設定了(磁盤上已經有)但是沒有緩存在主存中。

DRAM緩存的組織結構

使用SRAM表示位于CPU和主存之間的高速緩存,使用DRAM表示虛拟記憶體系統的緩存,就是在主存中緩存虛拟頁。DRAM比SRAM慢大約10倍,磁盤比DRAM慢100000多倍。是以我們盡量從DRAM中取資料,是以需要做到以下:

  • 更大的頁尺寸:通常是4KB,有時可以達到4MB
  • 全相聯:每一個虛拟頁可以放在任意的實體頁中,沒有限制。

頁表

當有了虛拟記憶體後,我們需要知道虛拟頁和實體頁之間的映射關系,即虛拟頁位于哪個實體頁中,這就需要用到頁表。在實體記憶體中有一個叫頁表的資料結構,頁表可以将虛拟頁映射到實體頁。頁表就是一個頁表條目(PTE)的數組,每個PTE是由一個有效位和一個n位位址字段組成。每次位址翻譯硬體将一個虛拟位址轉換成實體位址時,都會讀取頁表,作業系統負責維護頁表的内容,以及在磁盤和DRAM之間來回傳送頁。頁表結構如下所示:

計算機系統——虛拟記憶體

虛拟頁VP1,VP2,VP4和VP7被緩存在DRAM中,VP0和VP5未配置設定,VP3和VP6已配置設定但是未緩存。因為DRAM緩存是全相聯的,是以任意實體頁都可以包含任意虛拟頁。

缺頁

DRAM緩存不命中稱為缺頁,就是在DRAM中還沒有緩存對應的虛拟頁。這時會觸發缺頁異常,調用缺頁異常處理程式,程式會在DRAM中選擇一個犧牲頁,将改犧牲頁替換,并修改相應的頁表條目。添加所缺頁後會傳回到導緻缺頁的指令,這時缺頁已經在主存中了,便可以正常執行讀取操作。下圖以VP3缺頁異常為例,VP4作為犧牲頁。

計算機系統——虛拟記憶體
計算機系統——虛拟記憶體

虛拟記憶體作為記憶體管理工具

作業系統為每一個程序提供一個獨立的頁表,就是一個獨立的虛拟位址空間。如下所示,程序i的頁表将VP1映射到PP2,VP2映射到PP7。程序j的頁表将VP1映射到PP7,VP2映射到PP10。多個虛拟頁可以映射到同一個共享的實體頁上。

計算機系統——虛拟記憶體

除此之外,虛拟記憶體可以簡化連結,簡化加載,簡化共享,簡化記憶體配置設定。

虛拟記憶體作為記憶體保護的工具

計算機系統提供手段來控制對記憶體系統的通路權限,如使用者程序,核心程序的通路權限,這些是通過虛拟記憶體實作的。在PTE上添加額外的控制位可以保護記憶體通路。如下所示,通過看許可位是否允許相應的通路來保護記憶體。

計算機系統——虛拟記憶體

位址翻譯

位址翻譯就是虛拟位址空間中的元素和實體位址空間元素之間的映射。MMU利用頁表可以實作這種映射。映射過程如下:

計算機系統——虛拟記憶體

當發生頁面命中時:

  • CPU生成一個虛拟位址,并把它從傳送給MMU
  • MMU生成PTE位址,并從高速緩存/主存請求得到它
  • 高速緩存/主存向MMU傳回PTE
  • MMU構造實體位址,并把它傳送給高速緩存/主存
  • 高速緩存/主存傳回請求的資料字給CPU
計算機系統——虛拟記憶體

當發生缺頁時:

  • 1-3步和命中時的1-3步相同
  • PTE的有效位是0,觸發異常,執行缺頁異常處理程式
  • 缺頁處理确定在實體記憶體中的犧牲頁,若該犧牲頁已被修改,把其換出到磁盤
  • 調入新的頁面,更新記憶體中的PTE
  • 傳回到原來的程序,再次執行導緻缺頁的指令,這時即可正常讀取。
計算機系統——虛拟記憶體

TLB加速位址翻譯

每次CPU産生一個虛拟位址,MMU必須查閱一個PTE(主存中),這會浪費時間。如果PTE正好緩存在L1中,就會快很多。是以可以在MMU中包括一個關于PTE的小緩存,這樣就不用每次再讀取PTE了,直接從MMU中擷取即可,這個緩存稱為緩存後備緩沖器(TLB)。其結構如下:

計算機系統——虛拟記憶體

這樣在位址翻譯時,過程就會發生在晶片上的MMU中,速度會很快。

計算機系統——虛拟記憶體

和PTE命中不同的就是在翻譯的位置不同。

當虛拟記憶體位數過大時,儲存虛拟頁的頁表就是一個大問題,為了解決這個問題,使用多級頁表,這裡就不過多解釋。

動态記憶體配置設定

動态記憶體配置設定器維護着一個程序的虛拟記憶體區,稱為堆。配置設定器把堆看作不同大小的塊的集合來維護。每個塊是一個連續的虛拟記憶體塊,包括已配置設定的和空閑的。配置設定器有兩種:

  • 顯式配置設定器:顯式的配置設定和回收塊。(malloc和free,new和delete)。
  • 隐式配置設定器:隻負責配置設定,自動回收。隐式配置設定器也稱為垃圾收集器。

malloc和free函數

這裡看下malloc和free是如何管理堆的。每個方框代表4位元組的字,有陰影的是配置設定塊,沒陰影的是空閑塊,雙字對齊。

計算機系統——虛拟記憶體

使用動态記憶體配置設定的原因是到程式運作時才知道這些記憶體的大小。其記憶體配置設定不是在編譯期,而是在記憶體期。

配置設定器的要求和目标

要求:

  • 處理任意請求序列
  • 立即響應請求
  • 隻使用堆
  • 對齊塊
  • 不修改已配置設定的塊

目标:

  • 最大化吞吐率
  • 最大化記憶體使用率

碎片

内部碎片:已配置設定塊大于有效載荷時發生,如記憶體對齊需要增加塊來滿足。

外部碎片:空閑記憶體合計起來足夠滿足一個配置設定請求,但是單個小空閑記憶體不滿足。

實際的記憶體配置設定器需要解決的問題:

  • 如何記錄空閑塊?
  • 如何選擇空閑塊來放置新配置設定的塊?
  • 配置設定完塊後,如何處理空閑塊的剩餘部分?
  • 如何處理釋放的塊?

隐式空閑連結清單

計算機系統——虛拟記憶體

一個簡單的堆塊的結構如上所示,假設有一個已配置設定的塊,大小為24(0x18)位元組,那麼頭部是0x18|0x1=0x19,一個40(0x28)位元組的空閑塊,其頭部是0x28|0x0=0x28。填充部分是為了滿足某些要求,如記憶體對齊。

隐式空閑連結清單如下所示:

計算機系統——虛拟記憶體

放置已配置設定塊

查找合适的配置設定位置時有三種方法:

  • 首次适配:每次都從頭進行搜尋,找到第一個合适的塊,優點是将大的空閑塊留在連結清單後面,缺點是在連結清單開始處留下碎片,搜尋時間長。
  • 下一次适配:每次從上次搜尋結束的位置繼續搜尋,速度較快,但可能會有更多碎片,記憶體使用率更加低。
  • 最佳适配:檢查每個空閑塊,找到最合适的塊,碎片較少,但是速度最慢。

分割空閑塊

計算機系統——虛拟記憶體

擷取額外堆記憶體: 當配置設定器找不到合适的空閑塊時,會合并相鄰的空閑塊,如果還是不夠,會向記憶體申請額外的堆記憶體,将記憶體轉化成空閑塊并插入到空閑連結清單中,最後将請求的塊放到這個空閑塊中。

合并空閑塊

當配置設定器釋放一個配置設定塊時,可能有其他空閑塊與剛釋放的塊相鄰,這樣會産生假碎片。就是許多可用的空閑塊被切割成小的無法使用的空閑塊。這時我們需要将它們合并。

  • 立即合并:在每次塊被釋放時,就立即合并相鄰塊。
  • 推遲合并:等到某個稍晚的時候再合并空閑塊。

為了能夠合并前面的空閑塊,在堆塊增加一個标記。這樣就能知道前面塊的位置和狀态。

計算機系統——虛拟記憶體

垃圾收集

當申請的記憶體不使用時,需要回收。垃圾收集器是一種動态記憶體配置設定器,它自動釋放程式不再需要的已配置設定塊。在支援垃圾回收的系統中,應用顯示配置設定堆塊,但是不需要顯示回收。

垃圾收集器的基本知識

垃圾回收器可以将記憶體看作一張有向可達圖。如下所示:

計算機系統——虛拟記憶體

當存在從根節點到達點p的有向路徑時,就說p是可達的,不可達的節點對應為垃圾,垃圾回收器會釋放這些不可達點将它們傳回空閑連結清單,定期回收它們。

繼續閱讀