MMU初探

1. 什麼是MMU

MMU是 MemoryManagementUnit 的縮寫即,內存管理單元. 針對各種CPU, MMU是個可選的配件. MMU負責的是虛擬地址與物理地址的轉換. 提供硬件機制的內存訪問授權.(現代 CPU 的應用中,基本上都選擇了使用 MMU)

現代的多用戶多進程操作系統, 需要MMU, 才能達到每個用戶進程都擁有自己的獨立的地址空間的目標. 使用MMU, OS劃分出一段地址區域,在這塊地址區域中, 每個進程看到的內容都不一定一樣. 例如MICROSOFT WINDOWS操作系統, 地址4M-2G處劃分爲用戶地址空間. 進程A在地址 0X400000映射了可執行文件. 進程B同樣在地址 0X400000映射了可執行文件. 如果A進程讀地址0X400000, 讀到的是A的可執行文件映射到RAM的內容. 而進程B讀取地址0X400000時則讀到的是B的可執行文件映射到RAM的內容.

 

2. MMU的產生

許多年以前,當人們還在使用DOS或是更古老的操作系統的時候,計算機的內存還非常小,一般都是以K爲單位進行計算,相應的,當時的程序規模也不大,所以內存容量雖然小,但還是可以容納當時的程序。但隨着圖形界面的興起還用用戶需求的不斷增大,應用程序的規模也隨之膨脹起來,終於一個難題出現在程序員的面前,那就是應用程序太大以至於內存容納不下該程序,通常解決的辦法是把程序分割成許多稱爲覆蓋塊(overlay)的片段。覆蓋塊0首先運行,結束時他將調用另一個覆蓋塊。雖然覆蓋塊的交換是由OS完成的,但是必須先由程序員把程序先進行分割,這是一個費時費力的工作,而且相當枯燥。人們必須找到更好的辦法從根本上解決這個問題。不久人們找到了一個辦法,這就是虛擬存儲器(virtual memory).虛擬存儲器的基本思想是程序,數據,堆棧的總的大小可以超過物理存儲器的大小,操作系統把當前使用的部分保留在內存中,而把其他未被使用的部分保存在磁盤上比如對一個16MB的程序和一個內存只有4MB的機器,OS通過選擇,可以決定各個時刻將哪4M的內容保留在內存中,並在需要時在內存和磁盤間交換程序片段,這樣就可以把這個16M的程序運行在一個只具有4M內存機器上了。而這個16M的程序在運行前不必由程序員進行分割

 

3. MMU 作用

MMU 的作用:

1. 將虛擬地址翻譯成爲物理地址,然後訪問實際的物理地址

2. 訪問權限控制

 

4. MMU 工作過程

MMU 進行虛擬地址轉換成爲物理地址的過程是 MMU 工作的核心

大多數使用虛擬存儲器的系統都使用一種稱爲分頁(paging)。虛擬地址空間劃分成稱爲頁(page)的單位,而相應的物理地址空間也被進行劃分,單位是頁框(frame).頁和頁框的大小必須相同。接下來配合圖片我以一個例子說明頁與頁框之間在MMU的調度下是如何進行映射的:

在這個例子中我們有一臺可以生成16位地址的機器,它的虛擬地址範圍從0x0000~0xFFFF(64K),而這臺機器只有32K的物理地址,因此他可以運行64K的程序,但該程序不能一次性調入內存運行。這臺機器必須有一個達到可以存放64K程序的外部存儲器(例如磁盤或是FLASH)以保證程序片段在需要時可以被調用。在這個例子中,頁的大小爲4K,頁框大小與頁相同(這點是必須保證的,內存和外圍存儲器之間的傳輸總是以頁爲單位的),對應64K的虛擬地址和32K的物理存儲器,他們分別包含了16個頁和8個頁框。

我們先根據上圖解釋一下分頁後要用到的幾個術語,在上面我們已經接觸了頁和頁框,上圖中綠色部分是物理空間,其中每一格表示一個物理頁框。橘黃色部分是虛擬空間,每一格表示一個頁,它由兩部分組成,分別是Frame Index(頁框索引)和位p(present 存在位),Frame Index的意義很明顯,它指出本頁是往哪個物理頁框進行映射的,位p的意義則是指出本頁的映射是否有效,如上圖,當某個頁並沒有被映射時(或稱映射無效,Frame Index部分爲X),該位爲0,映射有效則該位爲1。

我們執行下面這些指令(本例子的指令不針對任何特定機型,都是僞指令)

例1:
    MOVE REG,0 //將0號地址的值傳遞進寄存器REG

虛擬地址0將被送往MMU,MMU看到該虛地址落在頁0範圍內(頁0範圍是0到4095),從上圖我們看到頁0所對應(映射)的頁框爲2(頁框2的地址範圍是8192到12287),因此MMU將該虛擬地址轉化爲物理地址8192,並把地址8192送到地址總線上。內存對MMU的映射一無所知,它只看到一個對地址8192的讀請求並執行它。MMU從而把0到4096的虛擬地址映射到8192到12287的物理地址。

例2:
    MOVE REG,8192
    被轉換爲
    MOVE REG,24576 
因爲虛擬地址8192在頁2中,而頁2被映射到頁框6(物理地址從24576到28671)

例3:
    MOVE REG,20500
    被轉換爲
    MOVE REG,12308
虛擬地址20500在虛頁5(虛擬地址範圍是20480到24575)距開頭20個字節處,虛頁5映射到頁框3(頁框3的地址範圍是 12288到16383),於是被映射到物理地址12288+20=12308。

通過適當的設置MMU,可以把16個虛頁隱射到8個頁框中的任何一個,但是這個方法並沒有有效的解決虛擬地址空間比物理地址空間大的問題。從上圖中我們可以看到,我們只有8個頁框(物理地址),但我們有16個頁(虛擬地址),所以我們只能把16個頁中的8個進行有效的映射。我們看看例4會發生什麼情況:

例4:

MOV REG,32780

虛擬地址32780落在頁8的範圍內,從上圖總我們看到頁8沒有被有效的進行映射(該頁被打上X),這是又會發生什麼?MMU注意到這個頁沒有被映射,於是通知CPU發生一個缺頁故障(page fault).這種情況下操作系統必須處理這個頁故障,它必須從8個物理頁框中找到1個當前很少被使用的頁框並把該頁框的內容寫入外圍存儲器(這個動作被稱爲page copy),隨後把需要引用的頁(例4中是頁8)映射到剛纔釋放的頁框中(這個動作稱爲修改映射關係),然後從新執行產生故障的指令(MOV REG,32780)。假設操作系統決定釋放頁框1,那麼它將把虛頁8裝入物理地址的4-8K,並做兩處修改:首先把標記虛頁1未被映射(原來虛頁1是被影射到頁框1的),以使以後任何對虛擬地址4K到8K的訪問都引起頁故障而使操作系統做出適當的動作(這個動作正是我們現在在討論的),其次他把虛頁8對應的頁框號由X變爲1,因此重新執行MOV REG,32780時,MMU將把32780映射爲4108。

我們大致瞭解了MMU在我們的機器中扮演了什麼角色以及它基本的工作內容是什麼,下面我們將舉例子說明它究竟是如何工作的(注意,本例中的MMU並無針對某種特定的機型,它是所有MMU工作的一個抽象)。

首先明確一點,MMU的主要工作只有一個,就是把虛擬地址映射到物理地址。
我們已經知道,大多數使用虛擬存儲器的系統都使用一種稱爲分頁(paging)的技術,就象我們剛纔所舉的例子,虛擬地址空間被分成大小相同的一組頁,每個頁有一個用來標示它的頁號(這個頁號一般是它在該組中的索引,這點和C/C++中的數組相似)。在上面的例子中0~4K的頁號爲0,4~8K的頁號爲1,8~12K的頁號爲2,以此類推。而虛擬地址(注意:是一個確定的地址,不是一個空間)被MMU分爲2個部分,第一部分是頁號索引(page Index),第二部分則是相對該頁首地址的偏移量(offset). 。我們還是以剛纔那個16位機器結合下圖進行一個實例說明,該實例中,虛擬地址8196被送進MMU,MMU把它映射成物理地址。16位的CPU總共能產生的地址範圍是0~64K,按每頁4K的大小計算,該空間必須被分成16個頁。而我們的虛擬地址第一部分所能夠表達的範圍也必須等於16(這樣才能索引到該頁組中的每一個頁),也就是說這個部分至少需要4個bit。一個頁的大小是4K(4096),也就是說偏移部分必須使用12個bit來表示(2^12=4096,這樣才能訪問到一個頁中的所有地址),8192的二進制碼如下圖所示:

該地址的頁號索引爲0010(二進制碼),既索引的頁爲頁2,第二部分爲000000000100(二進制),偏移量爲4。頁2中的頁框號爲6(頁2映射在頁框6,見上圖),我們看到頁框6的物理地址是24~28K。於是MMU計算出虛擬地址8196應該被映射成物理地址24580(頁框首地址+偏移量=24576+4=24580)。同樣的,若我們對虛擬地址1026進行讀取,1026的二進制碼爲0000010000000010,page index="0000"=0,offset=010000000010=1026。頁號爲0,該頁映射的頁框號爲2,頁框2的物理地址範圍是8192~12287,故MMU將虛擬地址1026映射爲物理地址9218(頁框首地址+偏移量=8192+1026=9218)。以上就是MMU的工作過程。

 

5. MMU 的 TLB 

由上面的例子可知,在 MMU 工作的時候,軟件也需要進行配合,軟件需要準備一張表,來告訴 MMU 當前的地址映射的關係(即,虛擬地址和物理地址的對應關係)。而這張表存儲在內存中(代碼的數據結構),每次 MMU 工作的時候,都去便利這個表裏面的關係,然後找到對應的映射,這個過程叫做 table walk。這樣會嚴重影響系統效率。於是乎,MMU 中增加了 Cache,這個 Cache 叫做 TLB。

爲了減少存儲器訪問的平均消耗, 轉換表遍歷結果被高速緩存在一個或多個叫作 Translation Lookaside Buffers(TLBs)的結構中。通常在ARM 的實現中每個內存接口有一個TLB。當存儲器中的轉換表被改變或選中了不同的轉換表(通過寫CP15 的寄存器,先前高速緩存的轉換表遍歷結果將不再有效。MMU 結構提供了刷新TLB 的操作。MMU 結構也允許特定的轉換表遍歷結果被鎖定在一個TLB 中,這就保證了對相關的存儲器區域的訪問絕不會導致轉換表遍歷,這也對那些把指令和數據鎖定在高速緩存中的實時代碼有相同的好處。

當ARM 要訪問存儲器時,MMU 先查找 TLB 中的虛擬地址表,如果沒有命中,則,還是要去走 table walk 的流程。即,如果TLB 中沒有虛擬地址的入口,則轉換表遍歷硬件從存在主存儲器中的轉換表中獲取轉換和訪問權限。一旦取到,這些信息將被放在 TLB 中,它會放在一個沒有使用的入口處或覆蓋一個已有的入口。

關於更多的 ARM 架構的 MMU 以及如何和 Linux 分頁機制進行配合的步伐,在後續進行分析。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章