虛擬內存和物理內存,虛擬地址和物理內存地址之間的映射機制


物理內存(ram,random access memory)

即插在主板槽上的那塊真實的內存條。

 

虛擬內存(virtual memory)

虛擬內存是一種計算機內存管理的技術,它讓程序認為程序自身有一段完整的連續可用的內存(一個地址空間)。當程序運行時所占的內存空間大於物理空間容量,操作系統可以將暫時不用的數據放入到磁盤,用的時候再拿出來,這樣磁盤有一部分空間就是用來存放這樣的數據,即ram與硬盤的臨時空間結合使用,這個臨時空間就叫虛擬內存。每個程序用的虛擬地址相互獨立,不同的程序可以使用相同的虛擬地址。

 

 

 物理地址就是物理內存上的地址,但虛擬地址空間是一個空間,不是真正存在的,只是通過CPU的尋址虛擬出來的一個范圍,操作系統和軟件(其實操作系統也可以說是軟件)可以根據cpu的最大尋址范圍來建立自己的尋址范圍。而虛擬內存是實實在在的硬盤的空間。

 

 

物理地址與虛擬地址的聯系

程序給出的地址是虛擬地址,不是實際的物理地址,這些虛擬地址會交給cpu去處理,然后映射出對應的物理地址,並且每次程序運行時,操作系統都會重新建立物理內存和虛擬內存的映射關系,哪段物理內存空閑就用哪一段。

 

映射機制

如果以程序為單位,那么會像是下圖一樣工作:

整個程序的虛擬地址會通過映射關系一一對應到物理內存地址上

好處:

1.每個程序之間使用的虛擬地址獨立(固定的虛擬地址),並且以映射關系一一對應一個物理地址,虛擬內存空間占用一個字節,在物理內存空間也占用一個字節。

2.可以將程序之間很好地進行隔離,這樣一個程序若出現了越界訪問,那么就會被操作系統認定非法,並把錯誤報告給用戶,通常會直接結束這個程序的運行,而如果直接把程序放在物理內存,沒有以程序為單位辨別,那么惡意程序或者程序一些bug就可以損壞自身程序或其他程序的數據,導致程序出錯或崩潰

缺點:

以整個程序為單位進行映射,若需要用到虛擬內存,那么進行磁盤I/O時要大量的磁盤讀寫,非常大的時間開銷,所以此方法略粗糙。

 

內存分頁

事實上,當一個程序運行時,某一個時間段內,它只會頻繁用到小部分數據,其他很多數據是在磁盤里面的,所以完全可以優化上面的方案,現代計算機用的是分頁機制。

分頁(paging)是指把地址空間分成許多等大小的一份,這樣一份就叫一頁。

好處:以頁為單位進行內存的換入換出,可以有效減小時間開銷。

頁的映射就如下圖

圖中program1和program2某一些虛擬頁對應了同一個物理頁,這樣能實現內存共享,有些虛擬頁沒有任何箭頭,這些虛擬頁處於未使用狀態,有些虛擬頁是還在磁盤中,當進程用到它時,會找不到,這時將產生頁錯誤(page fault),這時操作系統將接管它,並把磁盤中的頁讀取並裝入到內存中,並建立這些頁(讀入到物理內存的dp1)與虛擬頁(vp0)的映射關系。

 

以下均以32位電腦為例(這是指cpu32位)

頁的大小

頁的大小是由硬件決定,然后由操作系統來選擇,比如Intel pentium系列的cpu,提供4kb或者4mb大小的頁,那么操作系統就可以來選擇是4kb還是4mb,但注意,同一時刻,只能使用一種頁的大小,所以,頁的大小在某一時刻,是固定的。

頁的具體映射機制

 如果不用頁,比較容易想到的一種方法是定義一個數組,這個數組的下標是虛擬地址,每個數組元素的值是這個虛擬地址映射的物理地址,但是這樣一個數組有4GB個元素,有4GB*4的大小,這根本就不能塞進物理內存,不能用這樣的方法。

一級頁表

現在我們把地址空間分成了頁,那我們可以換個思路,用到哪個數據時,只要定位到它所在的頁,並知道它在頁內的偏移,就能取到它,由於我們現在是32位機示范,那么再以4kb大小的頁為例,一個虛擬地址空間有4GB/4KB==2^32/2^12==2^20==1M個頁,那么就可以定義數組:這個數組有1m個元素,每個元素保存的是每個頁的編號,叫做頁表數組(page table array,只占1m*4個字節,完全可以在內存中實現,並且數組的下標數量只需二十個位就能表示完,每個頁的大小也只需要十二個位就能遍歷,那么我們可以把虛擬地址這樣划分:

這樣虛擬地址后二十位作為數組下標,前十二位作為頁內偏移,就可以精准定位到物理頁中的數據,而頁表數組元素划分又如下圖

因為頁編號也只需要二十個位就可以表示完,所以數組類型為整形的頁表數組每個元素還剩下了十二個位,這十二個位用來表示頁的相關屬性,比如有無被換出到硬盤,有無讀寫權限,是否已經被分配了物理內存等等。

那么完整舉個例子就是,假設有個虛擬地址為0x0758BC00,那么它的高二十位是0x0758B,對應得是頁表數組下標為0x0758B的元素,假設這個元素值為0x045934B0,它的高二十位是0x04593,所以這個虛擬地址對應的物理頁編號是0x04593,再看虛擬地址前十二位,是0xC00,那么可以算出這個虛擬地址對應的物理地址為0x04593*2^12+0xC00==0x04593000+0xC00==0x04593C00

用圖表示則是這樣的

 

缺點:使用一級頁表時,無論程序占用多大的內存,因為虛擬空間高1G或2G的地址空間是被系統占用的,並且虛擬地址后二十位對應着頁表數組的下標,所以必須保證較大的數組下標有效,那么前面較小的數組元素也要跟着分配才能達成“保證較大的數組下標有效”,始終要為頁表數組分配4M物理內存,雖然對於現在的電腦來說不要緊,但是在幾十年前內存還很小,所以一級頁表還要進行壓縮。

 

二級頁表

上面說了,我們32位電腦有2^10*2^10個頁,那我們可以想象出一個頁矩陣,橫豎都是2^10,按照二維數組拆成一維數組的方法,把每一橫看成是一個小頁表,那么我們就有1024個小頁表,每個小頁表有1024個元素,只占用2^10*4b==4kb,這些小頁表可以分散到不同的物理頁,它們之間可以不連續的。

這樣只要定位到這些小頁表和知道頁內偏移就能知道數據的值了,那么如何定位這些小頁表呢,如果用指針指,那要1024個指針,浪費太多空間了,我們可以按照頁表數組的思路,定義一個整形數組,這個數組每個元素都是一個頁表數組的編號,取名為頁目錄(page director),對虛擬地址做如下划分

我們根據頁目錄下標,找到物理內存上的小頁表,再根據這個頁表下標找到對應的頁在物理內存上的編號,再根據頁內偏移精准定位到所要數據,並且用一個指針指向頁目錄就能隨時找到它了。

舉個例子,虛擬地址為10110111  00110010  11100010,高十位是10110111,根據指針找到物理內存上的頁目錄,然后找到對應頁目錄下標為10110111的小頁表(也在物理內存上),然后找到小頁表下標為00110010的元素,假設這個元素是0x774BAC31,那么對應物理頁編號為0x774BA,那么物理地址為0x774BA*2^12+0xE2==0x774BA0E2.

 

 

 

好處:本來一級頁表的話,無論怎么樣都要分配4M內存給頁表數組,但現在二級頁表把物理內存上的頁表數組分成了1024個小頁表數組,那么如果沒有任何用戶程序進行的話,只有系統占用內存時,我們可以只需要把系統數據對應的小頁表數組放入物理內存,當有程序運行時,也是在把對應的小頁表放入內存即可,那么二級頁表占用內存就跟程序占用內存大小成正比,這樣只有在極端情況(所有小頁表都用上)才會達到4m+4kb(頁目錄)的內存占用,所以總體來說比一級頁表占用得少得多。

 

多級頁表

現在計算機很多都是64位了,虛擬地址空間整整達到了256TB,會有非常多個頁,即使是分成二級頁表也仍占用不小的物理內存,所以依然可以按照上面的思路繼續細分,如下圖

一級頁表

 

二級頁表

 

不管多少級頁表,其實本質還是在虛擬地址和頁表之間不斷加介質來達到進一步壓縮的目的而已,按這個思路即可。

 

 

內存管理單元(MMU,memory management unit)

用頁表進行映射時,要經過多次轉換,還要計算,讓操作系統來完成這項任務的話會成倍降低程序性能,不過我們有一個更好的方法來解決這個問題----MMU

MMU就是負責完成虛擬地址映射成物理地址和對內存權限進行控制的,工作流程如下

頁映射模式時,cpu會把虛擬地址發送給MMU,MMU會將根據頁表進行映射,算出物理地址。

不過這樣有一個缺點,那就是MMU還是需要不斷地訪問內存,依然較大地降低性能,所以我們在MMU中加入一個緩存,這個緩存是用來存儲頁目錄和頁表的,緩存有限,在頁表過多過大時,只能將常用的頁表放入緩存,但是經過算法的巧妙設計,緩存的命中率能達到百分之九十以上,當沒有命中時再從物理內存加載頁表,注意頁表不是MMU創建的,是操作系統完成的,在程序運行時,操作系統會不斷地更新頁表信息,並將頁目錄的物理地址放到cr3寄存器中,MMU會根據cr3的頁目錄的物理地址找到頁目錄,再根據虛擬地址的信息來找到頁表,最后根據頁內偏移找到所要的數據。

ps:CR3寄存器是專門用來保存頁目錄的物理地址的。

有了硬件的支持,使用虛擬地址和直接使用物理地址相比,損失的性能已經很小了。

 

內存權限控制

上面說到了,頁表數組的元素,包含了頁相關屬性(內存權限),操作系統會在創建頁表時定義好頁相關屬性,MMU在進行虛擬地址映射時,先檢查這個程序有無權限使用,有就映射,沒有就產生一個異常,操作系統會直接終止程序,而在linux會產生段錯誤(Segment Fault)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM