虛擬地址與實體地址的轉換

  虛擬地址轉換為實體地址的第一步是將從處理器得到的虛擬地址和TLB中的虛擬地址進行比較。,今天小編與大家分享下,有需要的朋友不妨瞭解下。

  

  已知一個虛擬地址0x01AF5518, 則轉換的過程如下:

  注意: *這裡討論的以Windows下普通模式分頁的情況, 也就是2級頁表的情況*

  1.首先把虛擬地址拆分成3個部分低12位, 中10位, 高10位, 換成2進位制如下:

  -> 0000 0001 1010 1111 0101 0101 0001 1000

  按照10, 10, 12的位數重新排列後

  -> 頁目錄索引00 000 00110, 頁表項索引10 1111 0101, 偏移0101 0001 1000

  換算成十六進位制後可以得到如下結果

  頁目錄索引 = 6, 頁表項索引 = 0x2f5 , 偏移 = 0x518

  2. 根據當前的CR3暫存器中的實體地址定位頁目錄表基址

  Cr3中存放的是實體地址, 這個實體地址指向程序的頁目錄表基址, 由此可以得到

  頁目錄表基址PDE = Cr3 = 0xAA0E5000

  3. 計算頁表項的地址

  頁表地址存放在頁目錄表PDE中的第6個專案中, 也就是

  [0xAA0E5000 + 4 * 6] = [0xAA0E5018] = 0x3D955867, 其中0x00000867為該頁表屬性值, PTE = 0x3D955000

  3. 計算頁面實體地址

  我們要找的頁面在這個頁表中的第0x2f5項, 所以虛擬地址所在的頁的實體地址為

  [0x3D955000 + 0x2f5 * 4] = [0x3D955BD4] =

  假設[0x3D955BD4] = 0x7095e847, 頁面的實體地址 x0x7095e000, 0x00000847表示的是頁面屬性

  4. 計算最終的實體地址

  由虛擬地址分離的偏移可以計算出最終的實體地址為

  0x7095E000 + 0x00000518 = 0x7095E518.

  虛擬地址和實體地址的概念

  CPU通過地址來訪問記憶體中的單元,地址有虛擬地址和實體地址之分,如果CPU沒有MMUMemory Management Unit,記憶體管理單元,或者有MMU但沒有啟用,CPU核在取指令或訪問記憶體時發出的地址將直接傳到CPU晶片的外部地址引腳上,直接被記憶體晶片以下稱為實體記憶體,以便與虛擬記憶體區分接收,這稱為實體地址Physical Address,以下簡稱PA,如下圖所示。

 

  實體地址示意圖

  如果CPU啟用了MMU,CPU核發出的地址將被MMU截獲,從CPU到MMU的地址稱為虛擬地址Virtual Address,以下簡稱VA,而MMU將這個地址翻譯成另一個地址發到CPU晶片的外部地址引腳上,也就是將虛擬地址對映成實體地址,如下圖所示[1]。

 

  虛擬地址示意圖

  MMU將虛擬地址對映到實體地址是以頁Page為單位的,對於32位CPU通常一頁為4K。例如,虛擬地址0xb700 1000~0xb700 1fff是一個頁,可能被MMU對映到實體地址0x2000~0x2fff,實體記憶體中的一個物理頁面也稱為一個頁框Page Frame。

  核心也不能直接訪問實體地址.但因為核心的虛擬地址和實體地址之間只是一個差值0xc0000000的區別,所以從實體地址求虛擬地址或從虛擬地址求實體地址很容易,+-這個差就行了

  實體地址physical address

  用於記憶體晶片級的單元定址,與處理器和CPU連線的地址匯流排相對應。

  ——這個概念應該是這幾個概念中最好理解的一個,但是值得一提的是,雖然可以直接把實體地址理解成插在機器上那根記憶體本身,把記憶體看成一個從0位元組一直到最大空量逐位元組的編號的大陣列,然後把這個陣列叫做實體地址,但是事實上,這只是一個硬體提供給軟體的抽像,記憶體的定址方式並不是這樣。所以,說它是“與地址匯流排相對應”,是更貼切一些,不過拋開對實體記憶體定址方式的考慮,直接把實體地址與物理的記憶體一一對應,也是可以接受的。也許錯誤的理解更利於形而上的抽像。

  虛擬記憶體virtual memory

  這是對整個記憶體不要與機器上插那條對上號的抽像描述。它是相對於實體記憶體來講的,可以直接理解成“不直實的”,“假的”記憶體,例如,一個0x08000000記憶體地址,它並不對就實體地址上那個大陣列中0x08000000 - 1那個地址元素;

  之所以是這樣,是因為現代作業系統都提供了一種記憶體管理的抽像,即虛擬記憶體virtual memory。程序使用虛擬記憶體中的地址,由作業系統協助相關硬體,把它“轉換”成真正的實體地址。這個“轉換”,是所有問題討論的關鍵。

  有了這樣的抽像,一個程式,就可以使用比真實實體地址大得多的地址空間。拆東牆,補西牆,銀行也是這樣子做的,甚至多個程序可以使用相同的地址。不奇怪,因為轉換後的實體地址並非相同的。

  ——可以把連線後的程式反編譯看一下,發現聯結器已經為程式分配了一個地址,例如,要呼叫某個函式A,程式碼不是call A,而是call 0x0811111111 ,也就是說,函式A的地址已經被定下來了。沒有這樣的“轉換”,沒有虛擬地址的概念,這樣做是根本行不通的。

  打住了,這個問題再說下去,就收不住了。

  邏輯地址logical address

  Intel為了相容,將遠古時代的段式記憶體管理方式保留了下來。邏輯地址指的是機器語言指令中,用來指定一個運算元或者是一條指令的地址。以上例,我們說的聯結器為A分配的0x08111111這個地址就是邏輯地址。

  ——不過不好意思,這樣說,好像又違背了Intel中段式管理中,對邏輯地址要求,“一個邏輯地址,是由一個段識別符號加上一個指定段內相對地址的偏移量,表示為 [段識別符號:段內偏移量],也就是說,上例中那個0x08111111,應該表示為[A的程式碼段識別符號: 0x08111111],這樣,才完整一些”

  線性地址linear address或也叫虛擬地址virtual address

  跟邏輯地址類似,它也是一個不真實的地址,如果邏輯地址是對應的硬體平臺段式管理轉換前地址的話,那麼線性地址則對應了硬體頁式記憶體的轉換前地址。

  -------------------------------------------------------------

  CPU將一個虛擬記憶體空間中的地址轉換為實體地址,需要進行兩步:首先將給定一個邏輯地址其實是段內偏移量,這個一定要理解!!!,CPU要利用其段式記憶體管理單元,先將為個邏輯地址轉換成一個執行緒地址,再利用其頁式記憶體管理單元,轉換為最終實體地址。

  這樣做兩次轉換,的確是非常麻煩而且沒有必要的,因為直接可以把線性地址抽像給程序。之所以這樣冗餘,Intel完全是為了相容而已。

  實體地址就是,機器內主存的地址,包括RAM和ROM

  邏輯地址就是,程式執行在記憶體中,使用的地址。

  虛擬地址就是,cpu支援的記憶體空間遠遠大於機器主存的大小,這些多出來的空間對於程式來說是可以用的,這個時候的所有地址都稱為虛擬地址

  實體地址:最小系統下的儲存器的實際地址,一般只是由CPU記憶體控制器地址線可以管理的容量為最大地址,而實際上這個容量由地址產生的遠大於實際存在的容量;實際的儲存器容量所需要的地址記憶體控制器管理的容量;它的大小一般由晶片決定

  邏輯地址:相對程式設計師而言使用的地址,或說程式無需知道具體的實際地址管理數,而只要在系統操作允許範圍內使用就行了這時使用的是一種演算法控制下的地址,實際上它只是借用地址概念產生的程式執行模式,它所要說明的是方便,也就是一個線性的最好的程式指令排列方式。它的大小一般由作業系統決定

  虛擬地址:將具有儲存功能的所有儲存器不僅僅是最小系統概念下的,進行“統一”編址,而不考慮儲存器之間的差異快慢等,這時的地址是一個比邏輯地址理會數學化的編號地址,它的大小等往往由應用程式決定