tft每日頭條

 > 生活

 > 虛拟内存實際的物理内存

虛拟内存實際的物理内存

生活 更新时间:2024-08-16 06:13:59

一、 虛拟地址的由來

在早期的計算機中,要運行一個程序,會把這個程序全部都加載到内存,程序是直接運行到物理内存上的。也就是說,程序運行時直接訪問的就是實際的物理内存地址。當計算機要運行某些程序時(運行中的程序稱為進程),隻要這些進程所需要的内存空間不超過計算機所擁有的物理内存空間,那麼就不會出問題。由于程序都是直接訪問物理内存,所以一個進程是可以随意修改别的進程的内存數據。如果某個"惡意"的進程修改了其它進程的内存數據,往往就會導緻系統奔潰。這種情況對我們來說是無法容忍的,因為我們希望使用計算機的時候,任意一個任務出現問題了,不要去影響其它任務的執行。當在使用不同順序去運行多個任務時,這些程序的運行内存地址是不确定的。假如當時的計算機物理内存空間有128MB,操作系統的運行要78MB的物理内存空間,那麼就剩餘50MB的物理内存空間了,此時再運行一個任務A需要30MB的物理内存空間,若要再運行一個任務B,那麼任務B所要求的物理内存空間不能超過20MB,否則就會出問題,下一次先運行任務B,再運行任務A,此時它們的地址和上次是不一樣的。而且在程序運行時,如果去竄改程序上運行的物理内存的數據的,輕則程序挂掉,重則計算機系統奔潰。從上面可以看到,計算機的物理内存使用率是比較低下的,而且也是不安全的,輕微的一個失誤都可能導緻系統的奔潰,而且某個程序在運行時,并不需要運行所有的功能,隻是某一時段運行某一功能。在程序的執行過程中,也存在着大量在物理内存和硬盤之間的數據交換過程

二、分段

為了解決上述一系列問題,人們想到了一種有效的方法,增加一個程序與物理内存之間的中間層,利用一種間接的地址訪問方法去訪問物理内存。按照這種方法,程序中訪問的内存地址不再是實際的物理内存地址,而是一個虛拟地址,然後由操作系統将這個虛拟地址映射到物理内存地址上。這樣,隻要操作系統處理好虛拟地址到物理内存地址的映射關系,就可以保證不同的程序最終訪問的内存地址位于不同的區域,彼此不會存在地址重疊的現象,就可以達到物理内存地址被隔離的效果,進而保護計算機不會被"輕易"破壞。比如在一個32位的Windows操作系統中,當創建一個進程時,操作系統會為該進程分配一個4GB大小的虛拟進程地址空間。之所以是4GB,是因為在32位的操作系統中,一個指針長度是4字節,而4字節指針的尋址能力是從0x00000000~0xFFFFFFFF,最大值0xFFFFFFFF表示的即為4GB大小的容量。與虛拟地址空間相對的,還有一個物理地址空間,這個地址空間對應的是真實的物理内存。如果你的計算機上安裝了512MB大小的内存,那麼這個物理地址空間表示的範圍是0x00000000~0x1FFFFFFF。當操作系統做虛拟地址到物理地址映射時,隻能映射到這一範圍,操作系統也隻會映射到這一範圍。當進程創建時,每個進程都會有一個自己的4GB虛拟地址空間。要注意的是這個4GB的地址空間是"虛拟"的,并不是真實存在的,而且每個進程隻能訪問自己虛拟地址空間中的數據,無法訪問别的進程中的數據,通過這種方法實現了進程間的地址隔離。那是不是這4GB的虛拟地址空間應用程序可以随意使用呢?很遺憾,在Windows系統下,這個虛拟地址空間被分成了4部分:NULL指針區、用戶區、隔離區和内核區。

1) NULL指針區(0x00000000~0x0000FFFF):如果進程中的一個線程試圖操作這個分區中的數據,CPU就會引發非法訪問。它的作用是,當調用 malloc 等内存分配函數時,如果無法找到足夠的内存空間,它将返回 NULL。而不進行安全性檢查。它隻是假設地址分配成功,并開始訪問内存地址 0x00000000(NULL)。由于禁止訪問内存的這個分區,因此會發生非法訪問現象,并終止這個進程的運行。

2) 用戶區(0x00010000~0xBFFEFFFF):這個分區中存放進程的私有地址空間。一個進程無法以任何方式訪問另外一個進程駐留在這個分區中的數據(相同exe,通過copy-on-write來完成地址隔離)。(在windows中,所有.exe和動态鍊接庫都載入到這一區域。系統同時會把該進程可以訪問的所有内存映射文件映射到這一分區)。

3) 隔離區(0xBFFF0000~0xBFFFFFFF):這個分區禁止進入。任何試圖訪問這個内存分區的操作都是違規的。微軟保留這塊分區的目的是為了簡化操作系統的現實。

4) 内核區(0xC0000000~0xFFFFFFFF):這個分區存放操作系統駐留的代碼。線程調度、内存管理、文件系統支持、網絡支持和所有設備驅動程序代碼都在這個分區加載,該分區被所有進程共享。

虛拟内存實際的物理内存(物理内存與虛拟内存)1

虛拟地址空間

由于程序的運行必須運行在真實的物理内存上,而直接操作物理内存的危險性較大,所以通過創建了一個虛拟地址空間,虛拟地址和物理地址之間存在一一映射的關系,程序運行地址和物理地址的隔離,确保不同的進程地址空間被映射到不同的人物理地址空間上去。從而解決了同一計算機相同程序運行地址不确定的問題,也解決了因程序運行時被其它程序修改物理内存數據直接導緻系統奔潰的弊病。但是物理内存使用效率低下的問題依然沒有得到解決。

三、分頁

為了解決物理内存使用效率低下的問題,于是人們又提出了分頁的辦法。分頁的基本方法是,将地址空間分成許多頁,每頁的大小由CPU決定,然後由操作系統選擇執行頁的多少。有些CPU頁的大小為4KB,也有些CPU頁的大小為4MB。假設頁大小為4KB,那麼4GB的虛拟内存空間共可分為4×1024×1024÷4=1048576頁,如果此時計算機安裝的内存條大小為512MB,那麼512MB的物理内存可分為512×1024÷4=131072頁,顯然虛拟内存地址空間的頁數要比物理内存空間的頁數多得多。

在分段方法中,每次程序的運行都會被全部加載到虛拟内存中;而分頁方法則不同,它是将程序的大部分存在硬盤中,此時該部分硬盤稱為"交換區",而将少部分要運行的加載到虛拟内存中,通過映射在物理内存中運行,從而提高了物理内存的使用率。

虛拟内存實際的物理内存(物理内存與虛拟内存)2

物理内存與交換區

為了方便CPU高效執行管理物理内存,每一次都需要從虛拟内存中拿一個頁的代碼放到物理内存。虛拟内存頁有三種狀态,分别是未分配、已緩存和未緩存狀态。

未分配:指的是未被操作系統分配或者創建的,未分配的虛拟頁不存在任何數據和代碼與它們關聯,因此不占用磁盤資源;

已緩存:表示的是物理内存中已經為該部分分配的,存在虛拟内存和物理内存映射關系的;

未緩存:指的是已經加載到虛拟内存中的,但是未在物理内存中建立映射關系的。

虛拟内存實際的物理内存(物理内存與虛拟内存)3

四、頁表

虛拟内存中的一些虛拟頁是要緩存在物理内存中才能被執行的,因此操作系統存在一種機制用來判斷某個虛拟頁是否被緩存在物理内存中,還需要知道這個虛拟頁存放在磁盤上的哪個位置,從而在物理内存中選擇空閑頁或者更新緩存頁,并将需要的虛拟頁從磁盤複制到物理内存中。這些功能是由軟硬件結合完成的,他存放在物理内存中一個叫頁表的數據結構中。頁表的結構如下圖所示:

虛拟内存實際的物理内存(物理内存與虛拟内存)4

頁表實際上是一個數組。該數組存放的是一個稱為頁表條目(PTE)的結構。虛拟地址空間的每一個頁在頁表中,都有一個對應的頁表條目(PTE)。虛拟頁地址翻譯的時候就是查詢的各個虛拟頁在頁表中的PTE,從而進行地址翻譯的。地址翻譯的過程如下所示:

虛拟内存實際的物理内存(物理内存與虛拟内存)5

假設每一個PTE都有一個有效位和一個n位字段的地址。其中有效位表示對應的虛拟頁是否緩存在了物理内存中。0表示未緩存。1表示已緩存。n位地址字段表示如果未緩存(有效字段為0),n位地址字段不為空的話,這個n位地址字段就表示該虛拟頁在磁盤上的起始的位置。如果這個n位字段為空,那麼就說明該虛拟頁未分配;如果已緩存(有效字段為1),n位地址字段則不為空,它表示該虛拟頁在物理内存中的起始地址。

虛拟内存實際的物理内存(物理内存與虛拟内存)6

在上圖中,四個虛拟頁VP1 , VP2, VP4 , VP7 是被緩存在物理内存中。 兩個虛拟頁VP0, VP5還未被分配。但是剩下的虛拟頁VP3 ,VP6已經被分配了,但是還沒有緩存到物理内存中去執行。

五、内存管理單元MMU(Memory Management Unit)

内存管理單元MMU的主要功能是虛拟地址到物理地址的轉換。除此之外,它還可以實現内存保護、緩存控制、總線仲裁以及存儲體切換。也就是說程序運行的過程所需要的物理内存地址都是經過一個叫内存管理單元的東西完成的,需要注意的是内存管理單元是硬件管理,而不是軟件實現内存管理的。内存管理單元使每一個程序都有自己獨立的虛拟地址空間,提高了物理内存的使用率,它還提供了内存保護功能,可以将特定的内存塊設置為讀、寫或者可執行屬性,可以防止被程序惡意竄改内存。它的工作流程如下所示:

虛拟内存實際的物理内存(物理内存與虛拟内存)7

六、邏輯地址、線性地址、物理地址和虛拟地址的區别

1)邏輯地址(Logical Address):是指由程序産生的和分段相關的偏移地址部分。例如,你在進行 C 語言指針編程中,能讀取指針變量本身值( &操作 ),實際上這個值就是邏輯地址,它是相對于你當前進程數據段的地址,不和絕對物理地址相幹。隻有在 Intel 實模式下,邏輯地址才和物理地址相等(因為實模式沒有分段或分頁機制,CPU不進行自動地址轉換),邏輯地址也就是在Intel保護模式下,程序執行代碼的偏移地址(假定代碼段、數據段如果完全相同)。程序員開發應用程序時是需要和邏輯地址打交道,而不需要和分段和分頁機制打交道,分段分頁是系統編程人員要涉及的。程序員雖然能直接操作内存,那也隻能在操作系統給你分配的内存段操作。

2)線性地址(Linear Address):是邏輯地址到物理地址變換之間的中間層。程序代碼會産生邏輯地址,或說是段中的偏移地址,加上相應段的基地址就生成了一個線性地址。如果啟用了分頁機制,那麼線性地址能再經變換以産生一個物理地址。若沒有啟用分頁機制,那麼線性地址直接就是物理地址。Intel 80386 的線性地址空間容量為 4G(2的32次方即32根地址總線尋址)。

3)物理地址(Physical Address):是指出目前 CPU 外部地址總線上的尋址物理内存的地址,是地址變換的最終結果地址,也就是計算機安裝的内存條大小。如果啟用了分頁機制,那麼線性地址會使用頁目錄和頁表中的項變換成物理地址。如果沒有啟用分頁機制,那麼線性地址就直接成為物理地址了。

4)虛拟地址(Virtual Address):是指計算機呈現出要比實際擁有的内存大得多的内存量,每一個程序都用自己的虛拟内存,而且一般和物理内存大小一樣。因此允許程序員編寫并運行比實際系統擁有的内存大得多的程序。這使得許多大型項目也能夠在具有有限内存資源的系統上實現。一個恰如其分的比喻是,你要從深圳去北京,你不必擁有一列長度像從深圳到北京距離的火車,隻需要有兩段比火車稍長的鐵軌就能完成這個任務,在火車行駛時,隻要鋪鐵軌的動作足夠快,就可以使用兩段鐵軌交替鋪在路上的辦法使火車從深圳行駛到北京,讓火車就像行駛在一條鐵路上一樣。這也就是虛拟内存管理需要完成的任務。在Linux 0.11内核中,給每個進程都劃分了總容量為64MB的虛拟内存空間。因此程序的邏輯地址範圍是0x0000000到0x4000000。有時我們也把邏輯地址稱為虛拟地址。邏輯地址和物理地址的差值是0xC0000000,是由于虛拟地址->線性地址->物理地址映射正好差這個值。這個值是由操作系統指定的。邏輯地址(或稱為虛拟地址)到線性地址是由CPU的分段機制自動轉換的。如果沒有開啟分頁管理,則線性地址就是物理地址。如果開啟了分頁管理,那麼系統程序需要參和線性地址到物理地址的轉換過程。具體是通過設置頁目錄表和頁表項進行的。

虛拟内存實際的物理内存(物理内存與虛拟内存)8

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved