天天看點

MMU工作原理

http://blog.chinaunix.net/uid-20698426-id-136197.html

一、MMU的産生

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

任何時候,計算機上都存在一個程式能夠産生的位址集合,我們稱之為位址範圍。這個範圍的大小由CPU的位數決定,例如一個32位的CPU,它的位址範圍是0~0xFFFFFFFF (4G)而對于一個64位的CPU,它的位址範圍為0~0xFFFFFFFFFFFFFFFF (64T),這個範圍就是我們的程式能夠産生的位址範圍,我們把這個位址範圍稱為虛拟位址空間,該空間中的某一個位址我們稱之為虛拟位址。與虛拟位址空間和虛拟位址相對應的則是實體位址空間和實體位址,大多數時候我們的系統所具備的實體位址空間隻是虛拟位址空間的一個子集,這裡舉一個最簡單的例子直覺地說明這兩者,對于一台記憶體為256MB的32bit x86主機來說,它的虛拟位址空間範圍是0~0xFFFFFFFF(4G),而實體位址空間範圍是0x000000000~0x0FFFFFFF(256MB).

在沒有使用虛拟存儲器的機器上,虛拟位址被直接送到記憶體總線上,使具有相同位址的實體存儲器被讀寫。而在使用了虛拟存儲器的情況下,虛拟位址不是被直接送到記憶體位址總線上,而是送到記憶體管理單元——MMU(主角終于出現了)。他由一個或一組晶片組成,一般存在與協處理器中,其功能是把虛拟位址映射為實體位址。

MMU工作原理

(1)cpu看到的是VA

(2)caches和MMU使用的是MVA,

(3)實際實體設裝置使用的是PA。

二、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。

例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。

我們已經知道,大多數使用虛拟存儲器的系統都使用一種稱為分頁(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,這樣才能通路到一個頁中的所有位址),8196的二進制碼如下圖所示:

該位址的頁号索引為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的工作過程。