天天看點

Linux中的虛拟記憶體機制和記憶體映射【轉】

Linux中的虛拟記憶體機制和記憶體映射【轉】

Linux中的虛拟記憶體機制和記憶體映射

找工作ing...

最近學習了Linux中的虛拟記憶體,這個機制真的是非常的妙。虛拟記憶體可以說是硬體異常、主存、外存和作業系統的完美互動,而且更妙的是,這個機制是完全自動運作的。如果我們了解一點點虛拟記憶體的原理,就可以了解經常出現的記憶體錯誤的原因,還可以了解什麼是記憶體映射mmap。

一、實體位址空間是什麼

了解虛拟位址空間還得從實體位址空間開始說起。我們知道記憶體就像一個數組,每個存儲單元被配置設定了一個位址,這個位址就是實體位址,所有實體位址構成的集合就是實體位址空間。實體位址也就是真實的位址,對應真實的那個記憶體條。

如果CPU使用實體位址向記憶體尋址的話,就是下面這樣,這條指令中的位址就是資料真實存放的位址。

Linux中的虛拟記憶體機制和記憶體映射【轉】

二、虛拟位址空間是什麼

引入虛拟位址之後,對于每一個程序,作業系統提供一種假象,讓每個程序感覺自己擁有一個巨大的連續的記憶體可以使用,這個虛拟的空間甚至還可以比記憶體的容量還大。這個“假象”就是虛拟位址空間。虛拟位址是面向每個程序的,隻是一個“假象”罷了。

此時CPU使用虛拟位址向記憶體尋址,通過專用的記憶體管理單元(MMU)硬體把虛拟位址轉換為真實的實體位址(位址翻譯),作業系統負責把虛拟位址和實體位址的映射關系維護在頁表之中。

Linux中的虛拟記憶體機制和記憶體映射【轉】

指令中的位址不是資料真實存放的位址

三、程式和程序

當我們寫完代碼,編譯,連結并且生成可執行檔案後,得到的這個東西就是一系列二進制代碼的集合,我們管這東西叫做程式,存儲在磁盤上。隻有當我們執行這個檔案後,程式才會被作業系統讀入記憶體運作,但是注意系統并不會把程式全部讀入記憶體,我們把正在運作的程式叫做程序。

從程序的視角來看,我的資料和代碼被存放在一個連續的空間之中,每個區域分别有着不同的功能。典型的如存放代碼的區域和存放資料的區域。

Linux中的虛拟記憶體機制和記憶體映射【轉】

然而我們知道,這隻是個假象。代碼和資料中的位址都是一個虛拟位址,還需要經過位址翻譯才能得到真正的實體位址。

四、分頁、頁表和缺頁異常

虛拟位址和實體位址的映射關系是以“頁”為機關的。分頁就是把整個虛拟記憶體和實體記憶體分割成大小固定的塊,以一個頁作為映射的最小機關。運作時,CPU請求一個虛拟位址,虛拟位址又被翻譯為實體位址,進而确定資料在記憶體中的哪個位置。下面的頁表中記錄了這個程序虛拟記憶體每個頁的映射關系。

Linux中的虛拟記憶體機制和記憶體映射【轉】
Linux中的虛拟記憶體機制和記憶體映射【轉】

當CPU尋址的時候,這個映射會有三種可能。

未配置設定:虛拟位址所在的那一頁并未被配置設定,代表沒有資料和他們關聯,這部分也不會占用記憶體。

未緩存:虛拟位址所在的那一頁被配置設定了,但并不在記憶體中。

已緩存:虛拟位址所在的那一頁就在記憶體中。

當通路一個未緩存的區域時,系統将産生缺頁中斷,然後程序被阻塞,等待作業系統将缺失的那一頁從磁盤複制到記憶體。當複制完成後,CPU繼續執行導緻缺頁中斷的那條指令,此時就會正常執行了。這種僅在需要的時候将頁面拷貝到記憶體的政策叫做按需排程頁面。 可以想象當程式被裝入記憶體的時候,開始時僅有有很小的一部分内容被放入記憶體。程式在運作中不斷缺頁,不斷的把需要的部分拷貝進記憶體。

從上面的圖中還可以看出,虛拟記憶體實際上就是磁盤的緩存。系統通過缺頁中斷的機制,小心的維護着每個程序的虛拟位址假象。

五、虛拟記憶體的應用

在Linux中,将一片虛拟記憶體和一個磁盤上的對象關聯起來,并用磁盤上的對象初始化這片虛拟記憶體,這個機制就叫做記憶體映射。

1、化簡資源的共享

當我們使用共享庫的函數時時,例如printf(),沒有必要為每個程序拷貝一本代碼,這樣太浪費記憶體了。我們隻需要讓每個程序的一塊虛拟記憶體映射到相同的對象上就可以了。

Linux中的虛拟記憶體機制和記憶體映射【轉】

假如程序1和程序2想要共享同一個檔案。其中檔案A已經被映射到程序2(檔案被緩存在記憶體中),程序2還是通過缺頁中斷載入的檔案A。

Linux中的虛拟記憶體機制和記憶體映射【轉】

此時程序1也打開檔案A,由于檔案的名字在系統中是唯一的,作業系統清楚檔案A已經被緩存在記憶體之中。是以系統将程序1的虛拟記憶體映射到相同記憶體之中,完成檔案的共享。

Linux中的虛拟記憶體機制和記憶體映射【轉】

2、零拷貝技術的一種實作

對于linux中最常用的I/O函數 read() 來說,檔案先會被系統複制到核心空間的緩沖區,然後再複制到使用者空間。讀一個檔案需要複制兩次顯然不是我們希望的,尤其是讀大檔案的時候, sad...

Linux中的虛拟記憶體機制和記憶體映射【轉】

通過記憶體映射,我們可以繞過核心緩沖,直接将檔案A映射到虛拟記憶體,這裡一共就發生一次拷貝,nice~

Linux中的虛拟記憶體機制和記憶體映射【轉】

六、總結

虛拟記憶體無時無刻都在為我們工作,而且我們不需要任何幹涉就能自動地工作。虛拟記憶體可以看成對磁盤的一個緩存,它通過缺頁中斷觸發作業系統處理通路未緩存塊的問題。虛拟記憶體可以應用在處理共享對象、減少I/O開銷問題中。

虛拟記憶體十分的強大,以上介紹的僅僅是虛拟記憶體的一部分功能。如果文中出現錯誤歡迎指出,希望這篇文章對你有用。如果希望看到更多類似的内容請關注我的個人公衆号↓

【作者】張昺華