對虛擬位址空間對應實際實體地址的理解

2021-09-03 10:32:28 字數 4609 閱讀 5204

在進入正題前先來談談作業系統記憶體管理機制的發展歷程,了解這些有利於我們更好的理解目前作業系統的記憶體管理機制。

一 早期的記憶體分配機制

在 早期的計算機中,要執行乙個程式,會把這些程式全都裝入記憶體,程式都是直接執行在記憶體上的,也就是說程式中訪問的記憶體位址都是實際的物理記憶體位址。當計算機同時執行多個程式時,必須保證這些程式用到的記憶體總量要小於計算機實際物理記憶體的大小。那當程式同時執行多個程式時,作業系統是如何為這些程式分配記憶體 的呢?下面通過例項來說明當時的記憶體分配方法:

某台計算機總的記憶體大小是 128m ,現在同時執行兩個程式 a 和 b , a 需占用記憶體 10m , b 需占用記憶體 110 。計算機在給程式分配記憶體時會採取這樣的方法:先將記憶體中的前 10m 分配給程式 a ,接著再從記憶體中剩餘的 118m 中劃分出 110m 分配給程式 b 。這種分配方法可以保證程式 a 和程式 b 都能執行,但是這種簡單的記憶體分配策略問題很多。

圖一 早期的記憶體分配方法

問題 1 :程序位址空間不隔離。由於程式都是直接訪問物理記憶體,所以惡意程式可以隨意修改別的程序的記憶體資料,以達到破壞的目的。有些非惡意的,但是有 bug 的程式也可能不小心修改了其它程式的記憶體資料,就會導致其它程式的執行出現異常。這種情況對使用者來說是無法容忍的,因為使用者希望使用計算機的時候,其中乙個任務失敗了,至少不能影響其它的任務。

問題 2 :記憶體使用效率低。在 a 和 b 都執行的情況下,如果使用者又執行了程式 c ,而程式 c 需要 20m 大小的記憶體才能執行,而此時系統只剩下 8m 的空間可供使用,所以此時系統必須在已執行的程式中選擇乙個將該程式的資料暫時拷貝到硬碟上,釋放出部分空間來供程式 c 使用,然後再將程式 c 的資料全部裝入記憶體中執行。可以想象得到,在這個過程中,有大量的資料在裝入裝出,導致效率十分低下。

問題 3 :程式執行的位址不確定。當記憶體中的剩餘空間可以滿足程式 c 的要求後,作業系統會在剩餘空間中隨機分配一段連續的 20m 大小的空間給程式 c 使用,因為是隨機分配的,所以程式執行的位址是不確定的。

二 分段

為 了解決上述問題,人們想到了一種變通的方法,就是增加乙個中間層,利用一種間接的位址訪問方法訪問物理記憶體。按照這種方法,程式中訪問的記憶體位址不再是實際的物理記憶體位址,而是乙個虛擬位址,然後由作業系統將這個虛擬位址對映到適當的物理記憶體位址上。這樣,只要作業系統處理好虛擬位址到物理記憶體位址的映 射,就可以保證不同的程式最終訪問的記憶體位址位於不同的區域,彼此沒有重疊,就可以達到記憶體位址空間隔離的效果。

當建立乙個程序時,作業系統會為該程序分配乙個 4gb 大小的虛擬程序位址空間。之所以是 4gb ,是因為在 32 位的作業系統中,乙個指標長度是 4 位元組,而 4 位元組指標的定址能力是從 0x00000000~0xffffffff ,最大值 0xffffffff 表示的即為 4gb 大小的容量。與虛擬位址空間相對的,還有乙個實體地址空間,這個位址空間對應的是真實的物理記憶體。如果你的計算機上安裝了 512m 大小的記憶體,那麼這個實體地址空間表示的範圍是 0x00000000~0x1fffffff 。當作業系統做虛擬位址到物理位址對映時,只能對映到這一範圍,作業系統也只會對映到這一範圍。當程序建立時,每個程序都會有乙個自己的 4gb 虛擬位址空間。要注意的是這個 4gb 的位址空間是「虛擬」的,並不是真實存在的,而且每個程序只能訪問自己虛擬位址空間中的資料,無法訪問別的程序中的資料,通過這種方法實現了程序間的位址隔離。那是不是這 4gb 的虛擬位址空間應用程式可以隨意使用呢?很遺憾,在 windows 系統下,這個虛擬位址空間被分成了 4 部分: null 指標區、使用者區、 64kb 禁入區、核心區。應用程式能使用的只是使用者區而已,大約 2gb 左右 ( 最大可以調整到 3gb) 。核心區為 2gb ,核心區儲存的是系統執行緒排程、記憶體管理、裝置驅動等資料,這部分資料供所有的程序共享,但應用程式是不能直接訪問的。

人們之所以要建立乙個虛擬位址空間,目的是為了解決程序位址空間隔離的問題。但程式要想執行,必須執行在真實的記憶體上,所以,必須在虛擬位址與實體地址間建立一種對映關係。這樣,通過對映機制,當程式訪問虛擬位址空間上的某個位址值時,就相當於訪問了實體地址空間中的另乙個值。人們想到了一種分段 (sagmentation) 的方法,它的思想是在虛擬位址空間和實體地址空間之間做一一對映。比如說虛擬位址空間中某個10m 大小的空間對映到實體地址空間中某個10m 大小的空間,可以多對一,就是說可虛擬位址的多個10m大小的空間可以對映到相同的實體地址空間的某個10m。這種思想理解起來並不難,作業系統保證不同程序的位址空間被對映到實體地址空間中不同的區域上,這樣每個程序最終訪問到的

實體地址空間都是彼此分開的。通過這種方式,就實現了程序間的位址隔離。還是以例項說明,假設有兩個程序 a 和 b ,程序 a 所需記憶體大小為 10m ,其虛擬位址空間分布在 0x00000000 到 0x00a00000 ,程序 b 所需記憶體為 100m ,其虛擬位址空間分布為 0x00000000 到 0x06400000 。那麼按照分段的對映方法,程序 a 在物理記憶體上對映區域為 0x00100000 到 0x00b00000 ,,程序 b 在物理記憶體上對映區域為 0x00c00000 到 0x07000000 。於是程序 a 和程序 b 分別被對映到了不同的記憶體區間,彼此互不重疊,實現了位址隔離。從應用程式的角度看來,程序 a 的位址空間就是分布在 0x00000000 到 0x00a00000 ,在做開發時,開發人員只需訪問這段區間上的位址即可。應用程式並不關心程序 a 究竟被對映到物理記憶體的那塊區域上了,所以程式的執行位址也就是相當於說是確定的了。 圖二顯示的是分段方式

的記憶體對映方法。

圖二 分段方式的記憶體對映方法

這 種分段的對映方法雖然解決了上述中的問題一和問題三,但並沒能解決問題二,即記憶體的使用效率問題。在分段的對映方法中,每次換入換出記憶體的都是整個程式,這樣會造成大量的磁碟訪問操作,導致效率低下。所以這種對映方法還是稍顯粗糙,粒度比較大。實際上,程式的執行有區域性性特點,在某個時間段內,程式只是訪 問程式的一小部分資料,也就是說,程式的大部分資料在乙個時間段內都不會被用到。基於這種情況,人們想到了粒度更小的記憶體分割和對映方法,這種方法就是分頁(paging) 。  

三 分頁

分頁的基本方法是,將位址空間分成許多的頁。每頁的大小由 cpu 決定,然後由作業系統選擇頁的大小。目前 inter 系列的 cpu 支援 4kb 或 4mb 的頁大小,而 pc 上目前都選擇使用 4kb 。按這種選擇, 4gb 虛擬位址空間共可以分成 1048576 個頁, 512m 的物理記憶體可以分為 131072 個頁。顯然虛擬空間的頁數要比物理空間的頁數多得多。

在分段的方法中,每次程式執行時總是把程式全部裝入記憶體,而分頁的方法則有所不同。分頁的思想是程式執行時用到哪頁就為哪頁分配記憶體,沒用到的頁暫時保留在硬碟上。當用到這些頁時再在實體地址空間中為這些頁分配記憶體,然後建立虛擬位址空間中的頁和剛分配的物理記憶體頁間的對映。

下面通過介紹乙個可執行檔案的裝載過程來說明分頁機制的實現方法。乙個可執行檔案 (pe 檔案 ) 其實就是一些編譯鏈結好的資料和指令的集合,它也會被分成很多頁,在 pe 檔案執行的過程中,它往記憶體中裝載的單位就是頁。當乙個 pe 檔案被執行時,作業系統會先為該程式建立乙個 4gb 的程序虛擬位址空間。前面介紹過,虛擬位址空間只是乙個中間層而已,它的功能是利用一種對映機制將虛擬位址空間對映到實體地址空間,所以,建立 4gb 虛擬位址空間其實並不是要真的建立空間,只是要建立那種對映機制所需要的資料結構而已,這種資料結構就是頁目和頁表。

當建立完虛擬位址空間所需要的資料結構後,程序開始讀取 pe 檔案的第一頁。在 pe 檔案的第一頁包含了 pe 檔案頭和段表等資訊,程序根據檔案頭和段表等資訊,將 pe 檔案中所有的段一一對映到虛擬位址空間中相應的頁 (pe 檔案中的段的長度都是頁長的整數倍 ) 。這時 pe 檔案的真正指令和資料還沒有被裝入記憶體中,作業系統只是根據 pe 檔案的頭部等資訊建立了 pe 檔案和程序虛擬位址空間中頁的對映關係而已。當 cpu 要訪問程式中用到的某個虛擬位址時,當 cpu 發現該位址並沒有相相關聯的實體地址時, cpu 認為該虛擬位址所在的頁面是個空頁面, cpu 會認為這是個頁錯誤 (page fault) , cpu 也就知道了作業系統還未給該 pe 頁面分配記憶體, cpu 會將控制權交還給作業系統。作業系統於是為該 pe 頁面在物理空間中分配乙個頁面,然後再將這個物理頁面與虛擬空間中的虛擬頁面對映起來,然後將控制權再還給程序,程序從剛才發生頁錯誤的位置重新開始執行。由於此時已為 pe 檔案的那個頁面分配了記憶體,所以就不會發生頁錯誤了。隨著程式的執行,頁錯誤會不斷地產生,作業系統也會為程序分配相應的物理頁面來滿足程序執行的需求。

分頁方法的核心思想就是當可執行檔案執行到第 x 頁時,就為第 x 頁分配乙個記憶體頁 y ,然後再將這個記憶體頁新增到程序虛擬位址空間的對映表中 , 這個對映表就相當於乙個 y=f(x) 函式。應用程式通過這個對映表就可以訪問到 x 頁關聯的 y 頁了。

總結:

32 位的cpu 的定址空間是4g , 所以虛擬記憶體的最大值為4g , 而windows 作業系統把這4g 分成2 部分, 即2g 的使用者空間和2g 的系統空間, 系統空間是各個程序所共享的, 他存放的是作業系統及一些核心物件等, 而使用者空間是分配給各個程序使用的, 使用者空間包括用: 程式**和資料, 堆, 共享庫, 棧。

**:

虛擬位址與實體地址

乙個程式編譯連線後形成的位址空間是乙個虛擬位址空間,但是程式最終還是要執行在物理記憶體中。因此,應用程式所給出的任何虛位址最終必須被轉化為實體地址,所以,虛擬位址空間必須被對映到物理記憶體空間中,這個對映關係需要通過硬體體系結構所規定的資料結構來建立。這就是我們所說的段描述符表和頁表,linux主要...

邏輯位址 實體地址 虛擬位址

用於記憶體晶元級的單元定址,與處理器和cpu連線的位址匯流排相對應。雖然可以直接把實體地址理解成插在機器上那根記憶體本身,把記憶體看成乙個從0位元組一直到最大空量逐字節的編號的大陣列,然後把這個陣列叫做實體地址,但是事實上,這只是乙個硬體提供給軟體的抽像,記憶體的定址方式並不是這樣。所以,說它是 與...

實體地址和邏輯位址(虛擬位址)

1.實體地址 實體地址是載入到記憶體位址暫存器中的位址,是指記憶體中各物理儲存單元的位址從統一的基位址進行的順序編址。又稱絕對位址,它是資料在記憶體單元的真正位址。在前端匯流排上傳輸的記憶體位址都是物理記憶體位址,編號從0開始一直到可用物理記憶體的最高端。這些數字被北橋 nortbridge chi...