原文地址 An introduction to virtual memory
計算機是用來執行簡單任務的複雜機器:好比 上網、文本編輯、網頁服務、視頻遊戲……,還能夠對數據進行操做,圖片 音樂 文本 數據庫…… html
當計算機不使用的時候,程序和數據都安靜地躺在磁盤裏,即使你關機了數據也會在。運行一個應用就是讓處理器(CPU)讀取和執行程序代碼的機器指令處理數據。 linux
磁盤能夠保存大量的信息,但存取的時候都很是很是慢,比CPU慢得多,若是CPU直接從磁盤中讀取指令,顯然會成爲整個系統的性能瓶頸。爲此,主存/內存(RAM)就誕生了,內存是比磁盤小,但讀寫速度快得多的存儲設備。應用運行時其程序和數據首先拷貝到內存中,這樣處理器就能夠在內存中讀寫數據,從而避免了大量的等待。 程序員
主存能夠看做是一個很長的單元格列表,每一個單元格包含一些二進制數據,並用一個稱爲內存地址的數字進行標記。根據系統中可用的主存數量,內存地址的範圍從0到N。程序使用的地址範圍稱爲地址空間。 數據庫
在早期的計算機中(如今也見於某些嵌入式系統),程序是能夠訪問整個內存空間的,內存的管理也得由程序員本身實現。在這種類型的計算機上寫程序是一種挑戰,由於程序員得找到一種好的內存管理方式,以確保各程序之間內存不會覆蓋和干擾。
問題在多任務的時候更復雜,由於程序員必須面對更嚴峻的問題?編程
因此在1960年代初期,找到一種能自動管理內存方式尤其關鍵,這能夠大幅度簡化代碼編寫,並修復潛在的內存問題。最終誕生了咱們今天要說的虛擬內存。瀏覽器
在虛擬內存中程序並不直接訪問物理內存,而是和虛擬內存地址空間交互。操做系統和處理器將虛擬內存地址轉化爲物理內存地址。 安全
進程每次的內存的讀寫都是在虛擬內存地址之上的,虛擬地址並不執行特定的物理地址,因此每次內存訪問時程序並不知道硬件層面發生了什麼。
app
在上圖中咱們能夠看到虛擬地址和物理地址之間的映射關係,這種映射關係帶來了兩個好處。編程語言
虛擬內存機制也解決了內存有限的問題,由於操做系統能夠給每一個進程分配比實際內存大的多的虛擬內存空間。另外虛擬內存也能夠保證安全性,程序A沒法在不觸發操做系統錯誤的狀況下讀取到程序B的數據,下文中咱們將會介紹這一切是如何實現的。編輯器
虛擬內存機制須要一個地方來存儲虛擬地址和物理地址之間的映射關係,由於咱們須要將虛擬地址X轉化爲物理地址Y,固然你不能用1:1的映射,由於這樣的映射關係數據將和實際內存同樣大。
現代虛擬內存將多個固定大小的整塊物理內存合併成一個列表管理,解決了上述映射關係過大的問題,這種實現方式就叫作分頁。其中每一塊在虛擬內存中叫頁面在物理內存中叫頁框,每個頁面和頁框是對應的。CPU的內存管理單元(MMU)以一種叫作頁表的特殊數據結果存儲這虛擬頁框到物理頁框的映射關係。頁表比如是有個數據庫,每一行都存儲這頁號+頁框對應的物理內存地址。每一個進程在MMU中都會有本身的頁表,以下圖。
虛擬內存地址由兩部分組成
這些信息足夠MMU將一個虛擬地址轉化爲物理地址了。當一個進程讀寫一個虛擬地址時,它先喚醒MMU從虛擬地址中截取出頁號並根據頁表找到相應的頁框,當頁框根據頁內偏移計算出實際的物理地址,到這裏轉化就完成了。這時候程序就有了一個實際可讀寫的物理內存地址。
當程序有了連續、整潔的虛擬內存空間後,操做系統和硬件在後臺對物理內存作一些很瘋狂的事了。
例如:操做系統的延時加載,數據並非在程序開始運行前就加載數據,而是等到程序實際須要使用時才加載。全部你會發現有些時候可能某個程序的頁面對應一些不存在的頁框或者是尚未分配的頁框。好比上圖中的最後兩個頁面就沒有指向任何頁框。
像這樣的取巧的手段對應用程序是徹底透明的,它保持讀取和寫入本身的虛擬地址空間而不受背景噪音的影響。可是,程序早晚要訪問一個沒有映射到RAM的虛擬地址:該怎麼辦
缺頁中斷髮生於當程序嘗試去訪問一個沒有映射到物理頁框的虛擬地址時。更準確地講,缺頁中斷髮生於程序訪問一個虛擬內存地址存在但在物理內存中沒有對應地址的狀況。
當MMU檢測到缺頁中斷後會將中斷信息轉交給操做系統,操做系統會嘗試去找到虛擬地址到物理地址的映射,大多數狀況下這個是一個很簡單的操做,除非物理內存已經耗盡。
分頁也帶來一個其餘的好處。當物理內存不足時,操做系統能夠把部分頁面寫入到磁盤中騰出空間。儘管不夠百分百準確,但這種方法有時也叫作swapping(交換),Swapping實際上是把整個進程都挪到磁盤中,固然如今有些操做系統在必要的時候也會這麼作。
分頁給了程序一種有無限可用內存的假象。操做系統樂觀地容許一個比物理內存更大的虛擬內存地址空間,由於在須要的狀況下數據能夠被換進和換出硬盤。有些系統(例如Windows)會使用一個稱爲分頁文件的特殊文件來達到這個目的。其餘操做系統(例如Linux)有一個專用的硬盤分區,稱爲交換分區(因爲歷史緣由,現代Linux執行分頁而不是交換)。
當操做系統花更多的數據在執行分頁而不是應用程序的時候就會發生抖動,通常是由一系列的缺頁中斷致使的。這種狀況極易發生在當你運行大量超過物理內存大小的程序時或者硬盤交換分區沒有作優化時。這時候操做系統會努力執行大量的缺頁中斷,持續把數據從硬盤中移動到物理內存中,最終可能讓系統卡住。解決方法是加大內存或者減小進程數量或者調整交換分區大小。
虛擬內存也提供了跨進程的安全性。你的瀏覽器沒法在不侵入操做系統的狀況下窺探你文本編輯器裏的內容,由於它沒法訪問不屬於本身的內存空間。
內存保護機制是由MMU和其管理的頁表實現的,也許其餘硬件有不一樣的實現策略。當程序試圖訪問不屬於它的虛擬內存時,會觸發invalid page 錯誤。MMU和操做系統捕捉到這個信號,並引起一個名爲段錯誤(segmentation fault)(Unix)或無效訪問(access violation)(Windows),操做系統而後就會直接殺死這個進程。
段錯誤和無效訪問可能會程序錯誤而產生。可以手動管理內存的編程語言容許你本身管理一部份內存用來存儲程序數據,操做系統會給你劃分出一段空閒內存(又名緩衝區),以便根據你的程序須要進行讀寫。可是,沒有什麼能夠阻止你在緩衝區邊界以外讀寫,訪問不屬於您的程序或根本不存在的內存時,操做系統就會報出非法訪問的信號。
虛擬內存的技術爲不少有趣的課題鋪平了道路,好比內存文件就顛覆了傳統的文件讀取方式,傳統的文件讀取方式是把文件拷貝到內存裏,取而代以內存映射的方式是把整個文件都加載到內存後直接在內存裏操做。在必要時,虛擬內存機制將像往常同樣負責將數據從硬盤驅動器移動到RAM。內存映射文件簡化了程序員的工做也加快文件訪問。更多信息參考這裏。
虛擬內存也讓統計內存消耗變得更加困難。假設你的一個程序佔用了300m的內存:它是虛擬的仍是物理的?該空間的一部分是否分頁到磁盤?若是是,分頁操做是否足夠快?此外,若是您想使系統處於良好狀態,那麼調優分頁文件/交換區域是一個重要的步驟。操做系統提供了許多度量和調整內存的工具:點擊這裏查看。
Computer Hope — Memory
Peter J. Denning — Before memory was virtual
Android Authority — What is virtual memory?
Kernel.org — Memory Management
Operating Systems: Three Easy Pieces — Chapter 18: Paging
Philippe's Oppermann — Introduction to Paging
Computer Science from the Bottom Up — Chapter 6. Virtual Memory
Dr. John T. Bell — Operating systems, Virtual Memory
StackOverflow — Do modern OS's use paging and segmentation?
StackOverflow — What is thrashing? Why does it occur?
Wikipedia — Memory address
Wikipedia — Paging
Wikipedia — Address space
Wikipedia — Virtual memory
Wikipedia — Virtual address space
Wikipedia — Thrashing
Wikipedia — Segmentation fault
ITPro Today — Paging Performance
Aleph One — Smashing The Stack For Fun And Profit