天天看點

一文了解作業系統虛拟記憶體

原文位址​​An introduction to virtual memory​​

計算機是用來執行簡單任務的複雜機器:比如 上網、文本編輯、網頁服務、視訊遊戲……,還可以對資料進行操作,圖檔 音樂 文本 資料庫……

當計算機不使用的時候,程式和資料都安靜地躺在磁盤裡,即便你關機了資料也會在。運作一個應用就是讓處理器(CPU)讀取和執行程式代碼的機器指令處理資料。

磁盤可以儲存大量的資訊,但存取的時候都非常非常慢,比CPU慢得多,如果CPU直接從磁盤中讀取指令,顯然會成為整個系統的性能瓶頸。為此,主存/記憶體(RAM)就誕生了,記憶體是比磁盤小,但讀寫速度快得多的儲存設備。應用運作時其程式和資料首先拷貝到記憶體中,這樣處理器就可以在記憶體中讀寫資料,進而避免了大量的等待。

主存可以看作是一個很長的單元格清單,每個單元格包含一些二進制資料,并用一個稱為記憶體位址的數字進行标記。根據系統中可用的主存數量,記憶體位址的範圍從0到N。程式使用的位址範圍稱為位址空間。

一文了解作業系統虛拟記憶體

早期計算機的記憶體使用

在早期的計算機中(現在也見于某些嵌入式系統),程式是可以通路整個記憶體空間的,記憶體的管理也得由程式員自己實作。在這種類型的計算機上寫程式是一種挑戰,因為程式員得找到一種好的記憶體管理方式,以確定各程式之間記憶體不會覆寫和幹擾。

問題在多任務的時候更複雜,因為程式員必須面對更嚴峻的問題?

  1. 記憶體布局 —— 當第一個程式配置設定走特定數目的記憶體空間後,可用記憶體初始範圍将不再是0-n了,開發者得妥善處理記憶體偏移。
  2. 記憶體分段。當記憶體被不斷地配置設定回收之後,可用空間會逐漸變成越來越小的碎片,會越來越難以找到整塊的空間配置設定給新的程式或者資料。
  3. 安全性。 如果程式A不小心覆寫了程式B的資料?或者有人故意從其他程序中讀取敏感資料,比如密碼和信用卡資訊?

是以在1960年代初期,找到一種能自動管理記憶體方式尤為關鍵,這可以大幅度簡化代碼編寫,并修複潛在的記憶體問題。最終誕生了我們今天要說的虛拟記憶體。

虛拟記憶體簡介

在虛拟記憶體中程式并不直接通路實體記憶體,而是和虛拟記憶體位址空間互動。作業系統和處理器将虛拟記憶體位址轉化為實體記憶體位址。

程序每次的記憶體的讀寫都是在虛拟記憶體位址之上的,虛拟位址并不執行特定的實體位址,是以每次記憶體通路時程式并不知道硬體層面發生了什麼。

一文了解作業系統虛拟記憶體

虛拟記憶體的優點

在上圖中我們可以看到虛拟位址和實體位址之間的映射關系,這種映射關系帶來了兩個好處。

  1. 每個程式都可以有一個從0開始的虛拟記憶體位址空間,這大大簡化了程式猿的編碼,因為不需要再去手動維護記憶體位址的偏移了。
  2. 即便實體記憶體位址不連續但虛拟記憶體位址可以做到總是連續的,這樣作業系統算是間接完成了将記憶體碎片合并成一塊可用記憶體的艱巨工作。

虛拟記憶體機制也解決了記憶體有限的問題,因為作業系統可以給每個程序配置設定比實際記憶體大的多的虛拟記憶體空間。另外虛拟記憶體也可以保證安全性,程式A無法在不觸發作業系統錯誤的情況下讀取到程式B的資料,下文中我們将會介紹這一切是如何實作的。

分頁

虛拟記憶體機制需要一個地方來存儲虛拟位址和實體位址之間的映射關系,因為我們需要将虛拟位址X轉化為實體位址Y,當然你不能用1:1的映射,因為這樣的映射關系資料将和實際記憶體一樣大。

現代虛拟記憶體将多個固定大小的整塊實體記憶體合并成一個清單管理,解決了上述映射關系過大的問題,這種實作方式就叫做分頁。其中每一塊在虛拟記憶體中叫頁面在實體記憶體中叫頁框,每一個頁面和頁框是對應的。CPU的記憶體管理單元(MMU)以一種叫做頁表的特殊資料結果存儲這虛拟頁框到實體頁框的映射關系。頁表好比是有個資料庫,每一行都存儲這頁号+頁框對應的實體記憶體位址。每個程序在MMU中都會有自己的頁表,如下圖。

一文了解作業系統虛拟記憶體

頁表到頁框的轉化

虛拟記憶體位址由兩部分組成

  1. 頁号(頁索引),辨別這個虛拟記憶體位址屬于哪個頁面。
  2. 頁内偏移,辨別這個位址在頁框中的具體位置。

    這些資訊足夠MMU将一個虛拟位址轉化為實體位址了。當一個程序讀寫一個虛拟位址時,它先喚醒MMU從虛拟位址中截取出頁号并根據頁表找到相應的頁框,當頁框根據頁内偏移計算出實際的實體位址,到這裡轉化就完成了。這時候程式就有了一個實際可讀寫的實體記憶體位址。

虛拟記憶體的背後

當程式有了連續、整潔的虛拟記憶體空間後,作業系統和硬體在背景對實體記憶體做一些很瘋狂的事了。

例如:作業系統的延時加載,資料并不是在程式開始運作前就加載資料,而是等到程式實際需要使用時才加載。所有你會發現有些時候可能某個程式的頁面對應一些不存在的頁框或者是還沒有配置設定的頁框。比如上圖中的最後兩個頁面就沒有指向任何頁框。

像這樣的取巧的手段對應用程式是完全透明的,它保持讀取和寫入自己的虛拟位址空間而不受背景噪音的影響。但是,程式遲早要通路一個沒有映射到RAM的虛拟位址:該怎麼辦

缺頁錯誤(中斷)

缺頁中斷發生于當程式嘗試去通路一個沒有映射到實體頁框的虛拟位址時。更準确地講,缺頁中斷發生于程式通路一個虛拟記憶體位址存在但在實體記憶體中沒有對應位址的情況。

當MMU檢測到缺頁中斷後會将中斷資訊轉交給作業系統,作業系統會嘗試去找到虛拟位址到實體位址的映射,大多數情況下這個是一個很簡單的操作,除非實體記憶體已經耗盡。

分頁,當實體記憶體不足時如何實作?

分頁也帶來一個其他的好處。當實體記憶體不足時,作業系統可以把部分頁面寫入到磁盤中騰出空間。盡管不夠百分百準确,但這種方法有時也叫做swapping(交換),Swapping其實是把整個程序都挪到磁盤中,當然現在有些作業系統在必要的時候也會這麼做。

分頁給了程式一種有無限可用記憶體的假象。作業系統樂觀地允許一個比實體記憶體更大的虛拟記憶體位址空間,因為在需要的情況下資料可以被換進和換出硬碟。有些系統(例如Windows)會使用一個稱為分頁檔案的特殊檔案來達到這個目的。其他作業系統(例如Linux)有一個專用的硬碟分區,稱為交換分區(由于曆史原因,現代Linux執行分頁而不是交換)。

抖動

當作業系統花更多的資料在執行分頁而不是應用程式的時候就會發生抖動,一般是由一系列的缺頁中斷導緻的。這種情況極易發生在當你運作大量超過實體記憶體大小的程式時或者硬碟交換分區沒有做優化時。這時候作業系統會努力執行大量的缺頁中斷,持續把資料從硬碟中移動到實體記憶體中,最終可能讓系統卡住。解決方法是加大記憶體或者減少程序數量或者調整交換分區大小。

記憶體保護

虛拟記憶體也提供了跨程序的安全性。你的浏覽器無法在不侵入作業系統的情況下窺探你文本編輯器裡的内容,因為它無法通路不屬于自己的記憶體空間。

記憶體保護機制是由MMU和其管理的頁表實作的,也許其他硬體有不同的實作政策。當程式試圖通路不屬于它的虛拟記憶體時,會觸發invalid page 錯誤。MMU和作業系統捕捉到這個信号,并引發一個名為段錯誤(segmentation fault)(Unix)或無效通路(access violation)(Windows),作業系統然後就會直接殺死這個程序。

段錯誤和無效通路可能會程式錯誤而産生。能夠手動管理記憶體的程式設計語言允許你自己管理一部分記憶體用來存儲程式資料,作業系統會給你劃分出一段空閑記憶體(又名緩沖區),以便根據你的程式需要進行讀寫。但是,沒有什麼可以阻止你在緩沖區邊界之外讀寫,通路不屬于您的程式或根本不存在的記憶體時,作業系統就會報出非法通路的信号。

更多内容

虛拟記憶體的技術為很多有趣的課題鋪平了道路,比如​​記憶體檔案​​​就颠覆了傳統的檔案讀取方式,傳統的檔案讀取方式是把檔案拷貝到記憶體裡,取而代之記憶體映射的方式是把整個檔案都加載到記憶體後直接在記憶體裡操作。在必要時,虛拟記憶體機制将像往常一樣負責将資料從硬碟驅動器移動到RAM。記憶體映射檔案簡化了程式員的工作也加快檔案通路。更多資訊參考​​這裡​​。

參考資料

繼續閱讀