天天看點

寫給新手的MMU工作原理

很多人接觸Linux的記憶體管理是從malloc()這個C語言庫函數開始,也是從那時開始就知道了虛拟記憶體的概念。但很多人可能并不知道虛拟位址是如何轉換成實體位址的,今天帶你搞懂虛拟位址到實體位址的轉換過程,這其實也是MMU的工作原理。

1、預備知識

我們知道,在Linux中,每個程序都有自己獨立的位址空間,且互不幹擾。每個程序的位址空間又分為使用者空間和核心空間,但這些位址空間使用的都是虛拟位址,它們和實體位址空間關系是怎樣的呢?虛拟位址空間和實體位址空間的關系如下:

寫給新手的MMU工作原理

對于不同的程序,面對的都是同一個核心,其核心空間的位址對應的實體位址都是一樣的,是以程序1和程序2中核心空間都映射到了相同的實體記憶體

PA1

上。

而不同程序的使用者空間是不一樣的,即便相同的虛拟位址,也會被映射到不同的實體位址上。如圖中兩個程序相同使用者空間的位址

0x123456

分别被映射到了

PA2

PA3

實體位址上。

那麼如何完成上述虛拟位址到實體位址的轉換呢?

完成虛拟位址到實體位址的轉換,我們需要借助一個硬體——

MMU

MMU

: Memory manager unit,記憶體管理單元,負責将虛拟位址(VA)轉為實體位址(PA)。

在介紹MMU是如何将虛拟位址轉為實體位址之前,我們需要了解一些記憶體管理機制。

2、分頁機制

在Linux系統上,現在用到的記憶體管理機制,大部分是分頁機制。在分頁機制出現之前,還出現過動态分區法、分段機制。

動态分區法是還沒用引入虛拟位址之前使用的,使用的都是實體記憶體,屬于非常早期的機制。分段機制則引入了虛拟位址的概念,而分頁機制在分段機制後出現,主要解決分段機制記憶體碎片的問題。本篇以分頁機制講解虛拟位址到實體位址的轉換,下面介紹分頁機制的一些基本概念。

分頁機制的基本概念:

  • 分頁

    :将記憶體劃分為固定長度的單元,每個單元就是一頁
  • :對于

    虛拟位址空間

    ,将位址空間劃分為固定大小單元的單元,每個單元稱為一頁
  • 頁幀

    :對于

    實體位址空間

    ,将位址空間分為固定大小的單元,每個單元稱為頁幀
  • VPN

    :Virtual Page Number,虛拟頁面号
  • PFN

    :Physical Frame Number,實體頁幀号

分頁管理記憶體的核心問題就是虛拟位址頁到實體位址頁幀的映射關系

3、虛拟位址到實體位址轉換過程

虛拟位址和實體位址都被劃分了兩部分:

寫給新手的MMU工作原理

虛拟位址由虛拟頁面号

VPN

和虛拟位址偏移

VA offset

兩部分組成。同樣,實體位址由實體頁幀号

PFN

和實體位址偏移

PA offset

兩部分組成。

虛拟位址轉換成實體位址時,需要将

VPN

轉成

PFN

PA offset

通常就是

VA offset

是以實體位址 =

PFN

+

VA offset

這裡的核心就是VPN到PFN的映射,而VPN到PFN的映射關系是通過頁表記錄。就是說,頁表存儲了VPN和PFN的映射關系,MMU根據VPN,在頁表中找到PFN,再把PFN和VA offset相加,就得到了實體位址,進而将虛拟位址轉為實體位址。

這裡要區分一下,頁表存儲了VA到PA的映射關系,是以說找到頁表就找到了實體位址。但是這個頁表是軟體提供的,MMU隻負責将虛拟位址翻譯成實體位址,翻譯的依據就是頁表,MMU本身不負責建立頁表。是以說,在開啟MMU之前,系統就要提前建立好虛拟位址到實體位址的映射關系,然後儲存到頁表中,這樣開啟MMU時,MMU才能正确找到對應的實體位址。

4、頁表在哪

頁表都存儲在實體記憶體中, MMU将虛拟位址轉換為實體位址,需要通路實體記憶體中對應的頁表。

實際上,頁表通常就是用一個數組來表示。

這裡可能會一些疑問:

疑問:放到實體記憶體,每次轉換都要通路記憶體,速度不慢嗎?

答:慢。怎麼解決呢?如果有cache是不是就很快了?是的,這塊cache就叫TLB。

疑問:都放到實體記憶體,占用實體記憶體空間不大嗎?

答:大,怎麼解決?多級頁表+缺頁異常!多級頁表可以減少記憶體占用,而通常隻需将一級頁表存儲到實體記憶體,查找的時候,找不到二級頁表,觸發一個缺頁異常,這時再配置設定頁表,進而節省記憶體。

關于頁表放到實體記憶體的問題,涉及到cache和其他的一些知識,内容很多且比較複雜,暫時不深究,知道頁表是放在記憶體中的即可。

5、MMU如何知道頁表在哪

前面說頁表存儲在實體記憶體中,那麼MMU怎麼知道這個頁表在記憶體中的具體位址呢?

通常CPU會提供一個頁表基址寄存器給作業系統使用,用于給MMU訓示頁表的基位址。不同處理器架構對應的寄存器也不一樣:

x86

:CR3(Control Register 3)

ARM-v8

:系統寄存器TTBR(Translation Table Base egister)

RISC-V

:SATP(Supervisor Address Translation and Protection)

寫給新手的MMU工作原理

頁表基址寄存器存儲了第一級頁表的基位址,通過通路該寄存器,就能知道頁表在那個位置。

6、多級頁表轉換過程

實際使用中,都是用多級頁表來存儲虛拟位址和實體位址的映射關系,

以二級頁表為例(假設是32位系統),其虛拟位址轉換為實體位址的過程如圖所示:

寫給新手的MMU工作原理

PGD

:Pgea Global Directory,全局頁目錄,存儲了下一級頁表的基位址

PTE

:Page Table Entrys,頁表入口,PTE才是真正存儲了實體位址的頁表

VA到PA的轉換過程:

MMU

通過通路頁表基址寄存器,得到一級頁表

PGD

的基位址,再結合虛拟位址中的

PGD index

找到了下一級頁表

PTE

的基位址;得到了

PTE

的基址,再結合虛拟位址中的

PTE index

找到

PFN

,然後再和

VA

相加得到實體位址。

這裡需要注意,使用多少級的頁表、以及虛拟位址、實體位址的格式、PTE的格式等等,與32系統還是64位系統有關,也與處理器的架構有關,需要根據不同系統、不同處理器架構分析。

但是MMU工作原理都是一樣的,不管是二級頁表、三級頁表還是四級頁表,都是通過第一級頁表找到第二級頁表,通過第二級頁表找到第三級頁表......最終找到實體位址。隻要明白了MMU的工作原理,分析其他的頁表也是大同小異。

總結

本文帶大家了解了虛拟位址和實體位址的一些概念,以及MMU将虛拟位址轉為實體位址的過程,相信通過以上内容,對虛拟位址、實體位址、MMU、多級頁表等這些概念都不陌生了。

本文隻講解了MMU是通過頁表将虛拟位址轉為了實體位址的,但沒有說頁表是如何建立的,因為頁表的建立每個處理器架構都不一樣,本文隻講通用性的MMU原理,後續再深入分析頁表建立。

繼續閱讀