內核中與驅動相關的內存操作之一(MMU)

1.MMU的存在意義:

    MMU(Memory Manage Unit)的出現是爲了解決以下這類問題的一種"硬件算法"或者說策略:16MB的程序運行於4MB內存空間的問題,實現內存的更高效地利用.類比於現實生活中的銀行.銀行無須要保障每時每刻都準備充足以備所有用戶同時取錢--這種情況基本上不會發生.通過挖東牆補西牆,實現資金的更高效利用.從而達到一種"動態平衡",而使人表面上看到的是"靜止"的.

    1-1.虛擬地址:

    虛擬地址是指CPU物理尋址能力的地址範圍,通常是PC指針的大小.它是由CPU的位數決定的,比如32位的CPU,它的物理尋址能力爲0x0000 0000 ~ 0xffff ffff(2^32 = 4G).

    1-2.物理地址:

    和虛擬地址相對立,和實際設備相對應.比如256MB的32位的CPU而言,它的有效的物理空間爲0x000000000~0x0FFFFFFF(256MB).物理地址有效訪問範圍爲:基地址 ~ 基地址 + 0x0fffffff.

    物理地址是虛擬地址的一個子集.

    1-3.虛擬地址到物理地址的投射:

    我們實際的數據交互都沒辦法離開實質的物質存在作爲載體.比如我們的物理地址範圍爲[BASE,BASE + 0x0FFFFFFF],如果代碼操作在此區間之外的虛擬地址的話,必須要把這個虛擬地址投影到[BASE,BASE + 0x0FFFFFFF]這個範圍之內.這工作由MMU完成.比如LINUX是一個虛擬內存的OS,操作的都是虛擬地址,因此必須要轉化爲物理地址去實現物理設備的操作.因此,它的宏觀流程如下: 

虛擬地址-->MMU-->物理地址

2.頁和頁框:

    2-1.頁(page):

    任何東西都存在其最基本單元,而虛擬地址以"頁"爲其基本單元.對於內核而言,頁大小大多數平臺架構下都是4KB.

    2-2.頁框(frame):

    頁框是實質物理地址空間的基本單元.

    虛擬地址和物理地址交互單元是"頁<-->頁框".就是說,虛擬地址上的"頁"要和物理地址的"頁框"相對應.因此,它們的大小必須相等.但是虛擬地址上的"頁"和物理地址哪個"頁框"關聯,其過程是動態的,裏面有硬件算法,而這種硬件算法的實現,就是由MMU去實現的.MMU一般是CPU裏面的一個IP(內置外設).如下圖所示:

   


    虛擬地址上的頁被投影到物理地址上的哪一個頁框是不定的,因此,頁必須知道一種"信息"用來獲取頁是否可以被投影?如果多個頁框可以被投影,那麼選哪一個頁框比較好?因此,頁至少包含兩部分信息:頁期望投影到哪頁框上?期望投影到的頁框是否有效?對應頁的"Frame Index | P".下面給出幾個實例描述這一過程:


例一:

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的物理地址.

例二:

MOVE REG,8192

  因爲虛擬地址8192在頁2中,而頁2被映射到頁框6(物理地址從24576到28671).因此,上述這條語句被轉換爲下面的語句:

MOVE REG,24576

例三:

MOVE REG,20500

    虛擬地址20500在虛頁5(虛擬地址範圍是20480到24575)距開頭20個字節處,虛頁5映射到頁框3(頁框3的地址範圍是 12288到16383),於是被映射到物理地址12288+20=12308.因此,上述這條語句被轉換爲下面的語句:

MOVE REG,12308

例四:

MOV REG,32780

    從上圖中我們可以看到,我們只有8個頁框(物理地址),但我們有16個頁(虛擬地址),所以我們只能把16個頁中的8個進行映射.虛擬地址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.

 

3.虛擬地址值的意義:

  和內核打交道的地址都是虛擬地址,這個虛擬地址每個bit都是有意義的.對MMU來說,這個虛擬地址就相當於一張索引圖,MMU通過這張圖爲我們找到相應的有效的物理地址.很多使用虛擬存儲技術的現代系統,都採用了分頁技術.把虛擬地址空間分成大小相同的一組頁,每個頁必須有唯一的標識號.在實際編程中,我們並不是以頁爲單位的,而是以字節爲單位的,所以還要一個偏移數據位段.因此,對於MMU而言,虛擬地址分兩部分:

PageIndex|Offset

  兩者並起來就是CPU的位數,如32位.PageIndex是頁的索引值,而Offset即爲選定頁的偏移量.如ARM平臺的LINUX內核頁大小一般爲4KB,因此,如果以字節爲單位的話,必須要有12bit來表徵其偏移量Offset(2^12 = 4KB).而頁的數目,32bit的CPU其虛擬空間爲4GB(2^32=4GB),以4KB爲頁大小的話,則有4GB/4KB=2^20個頁.爲了保證頁的唯一性,需要20bit來表徵PageIndex.如下:

PageIndex|Offset = [31,12] | [11,0]

    當操作一個虛擬地址的時候,MMU會根據這兩部分作爲索引位圖去找到相應的有效的物理地址.這裏需要注意的是,虛擬地址並不是直接轉換爲物理地址的,中間還要經過一個"表",這個表就是轉換表--"TranslateTable".這張表記錄的纔是虛擬地址到物理地址的索引.細則如下:

  虛擬地址-->[MMU]-->TTB-->物理地址

   因此,下面將對TTB的功能進行描述.

 

4.TTB和TLB:

  4-1.TTB(TranslateTable):

  TTB是協助MMU完成虛擬地址到物理地址投影、內存的訪問權限和設置虛擬存儲空間緩衝的重要手段.TTB每一行代表一個頁信息,裏面包含了虛頁到實頁轉換需要的所有信息,如如何投影的、訪問權限等.TTB存在於內存當中,它的基本單位爲地址變換條目,即"entry".在ARM體系當中,TTB在內存中的地址被記錄在協處理器CP15的C2寄存器中.

  4-2.TLB(Translate Lookside Table):

  從虛擬地址到物理地址的變換過程其實是查表的過程.內存的使用是最廣最頻繁的,像LINUX這樣的虛擬存儲系統,把虛擬地址變換爲物理地址的過程是很頻繁的,如果頁表是存放在內存當中,這種代價也是很大的.作爲一種硬件優化策略,CPU內置了一個叫TLB的RAM段.TLB相當於CPU內置的RAM,容量比較小,比較小的爲8~16個字節,這個RAM段的訪問速度相當快,和CPU訪問寄存器的速度相當.裏面存放的是地址變換條目.因此,虛擬地址到物理地址的過程進一步細化如下:

虛擬地址-->[MMU]-->TLB-->TTB-->物理地址

  TLB把經常訪問的虛擬地址和物理地址建立起一種投影關係.當CPU請求存儲訪問時,首先在TLB查找虛擬地址,進一步找到此虛擬地址對應的條目,如果找到此虛擬地址對應的條目,即可投影到相應的物理地址.否則只能從TTB查找,然後更新到TLB.如果TLB滿的話,通過硬件算法,需要對TLB上的條目進行淘汰.

 

5.條目(entry):

  條目(entry)包含了虛擬地址到物理地址的所有信息體,比如虛頁應該投影到哪個實頁,內存訪問的結果等等.當CPU處理一個虛擬地址,無論是TTB還是TLB,最終都要落實到條目去索引相應的實頁.條目,可以說是虛擬地址到物理地址轉向的"核心數據"單元.它是虛擬存儲空間中一塊連續的存儲空間被映射成物理存儲空間中同樣大小的一塊連續存儲空間的"依據".

  5-1.內存塊:

   MMU進行映射時,是以"塊"爲基本單位來進行映射的.ARM支持的存儲塊的以下四種:

1).段(section):大小爲1M;
2):大頁(LargePages):大小爲16KB;
3).小頁(SmallPages):大小爲4KB;
4).極小頁(TinyPages):大小爲1KB;

  通過配置相關的協處理器寄存器,可以選擇"塊"的尺寸.

  5-2.描述符

  協處理器的C2保存了TTB的基地址.類比於一個數組,此數組的基地址存放在C2寄存器上,數組裏面的每一個元素籠統地稱之爲"條目(Entry)".而我們的數組是有元素的,每個元素都是有類型的,比如說int型,char型,甚至是結構體等.因此,TTB裏面每個元素籠統叫法是"條目(Entry)",更準確的叫法爲"描述符",而描述符再具體而分,分爲"一級描述符"和"二級描述符".和數組裏面的元素一樣,描述符也是有地址的,分別爲"一級描述符地址"、"二級描述符地址".通過地址,我們可以索引到數組元素(描述符).

  如果某CPU被配置成一級頁錶轉換的話,TTB可以理解爲一個一維數組.這個一維數組裏面每一個元素都是"一級描述符".通過解析"一級描述符",可以得到物理地址;如果某CPU被配置成二級頁錶轉換的話,TTB可以理解爲一個二維數組,要想訪問某一元素,必須先檢索到此元素所在的"子數組(一級描述符)"裏面,在"子數組"裏面再去檢索"目標元素(二級描述符)".通過解析二級描述符可以得到物理地址.

  無論是一級描述符還是二級描述符,都可以籠統地稱之爲"條目".和數組一樣,每個元素都是有地址的.訪問數組裏面的元素我們可以通過地址索引的方式實現.同樣,訪問TTB裏面的條目也是通過地址索引的方式來實現的.描述符的地址在ARM核裏面是有這樣的規定:

一級頁表的描述符地址 = TTB[31,14] | (VA[31,20] >> 14) | [1,0]

  CP15的寄存器C2的[31,14]和虛擬地址的[31,20]並湊成一個32位數的高30位,低兩位爲00b,從而形成一個32位的索引值,通過該索引可以從頁表中查到一個4字節的地址變換條目.該條目中或者包含了一個一級描述符,或者包含了一個指向二級頁表的指針.注意,這裏我們僅僅找到的是"條目",至於這個條目裏面的信息是什麼,需要我們根據具體的協處理配置去解析--到底是一級描述符還是指向二級頁表的指針.

  一級頁表地址轉換:

  一級頁表地址轉換對應了一級描述符,而一級描述符根據上述索引的32位數的最低兩位,可以分爲四種可能.如下:

  下面以一級描述符爲段描述符爲例,即32位地址索引的最低兩位爲10b.CPU核發出一個VA(虛擬地址),MMU截取VA[31,20]並結合TLB/TTB[31,14]索引到此段描述符的地址,從而索引到此段描述符的內容,如下:

 

 

  該段描述符的bit[31,20]對應了物理段(一共12bit,32位的CPU的可訪問物理空間爲2^32=4G.一個段爲1M.2^12=4096個段.)

  得到了對應的物理段地址後,再通過VA的偏移地址結合得到物理地址PA.其過程如下:

 

 

  二級頁表地址轉換:

  二級頁表地址轉換,即一級描述符裏面記錄並不是物理地址,而是二級描述符的索引.通過一級描述符索引到二級描述符,再通過二級描述符找到相應的物理地址.以大頁爲例,其實質也是以地址爲索引:



 












   

  

   




發佈了131 篇原創文章 · 獲贊 17 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章