在現(xiàn)在的工作項目中雖然沒有使用到MMU功能,但MMU是較復雜的嵌入式操作系統(tǒng)運行的基礎。例如Linux就不能夠運行在沒有MMU的ARM7處理器上,ucLinux就是為了適應沒有MMU的處理器而對Linux進行的裁剪和修改。了解MMU基礎知識,對理解編譯鏈接,OS多進程,嵌入式系統(tǒng)架構等有很好的幫助。由于該部分內(nèi)容涉及到MMU硬件、CPU架構、編譯鏈接、OS等知識,學習難度較大。
關鍵字 MMU、TLB、多任務OS、地址空間、虛擬內(nèi)存、虛擬地址/物理地址
學習順序 問題的引出、虛擬地址和物理地址、虛擬內(nèi)存、OS進程和MMU,MMU運行
早期的計算機PC,或者現(xiàn)在使用8位/16位MCU(單片機)的嵌入式設備,程序是直接運行在物理內(nèi)存上的(SDRAM或者NOR Flash)。所謂直接運行在物理內(nèi)存上,是指程序在運行時所訪問的地址都是物理地址。例如,程序計數(shù)器PC中的值就是預取指令所在的物理內(nèi)存的地址值。
這種程序直接運行在物理內(nèi)存上的方式簡單,但是并不適應于復雜的系統(tǒng),尤其是擁有多任務的OS。我們首先看看原來的方式有哪些不足和缺陷。
于是人們就引入了虛擬內(nèi)存管理(Virtual Memory Management)技術。有關虛擬內(nèi)存管理(Virtual Memory Management)技術在下面會有詳細的介紹。需要說明的是,上面的幾點缺陷除了第一點之外,其它都是針對有OS的系統(tǒng)而言的。 虛擬內(nèi)存管理技術的出現(xiàn)和操作系統(tǒng)的發(fā)展有本質(zhì)的聯(lián)系。 本節(jié)可以參考《程序員的自我修養(yǎng)-鏈接、裝載與庫》第1章 1.5 內(nèi)存不夠怎么辦。
隨著計算機的發(fā)展,應用程序的規(guī)模逐漸增大,一個難題出現(xiàn)在程序員的面前,那就是應用程序太大以至于內(nèi)存容納不下該程序,通常解決的辦法是把程序分割成許多稱為覆蓋塊(overlay)的片段。覆蓋塊0首先運行,結(jié)束時他將調(diào)用另一個覆蓋塊。雖然覆蓋塊的交換是由OS完成的,但是必須先由程序員把程序先進行分割,這是一個費時費力的工作,而且相當枯燥。人們必須找到更好的辦法從根本上解決這個問題。
人們找到了另外一個辦法,這就是虛擬內(nèi)存管理(Virtual Memory Management)技術。虛擬內(nèi)存管理技術的基本思想是程序,數(shù)據(jù),堆棧的總的大小可以超過物理存儲器的大小,操作系統(tǒng)把當前使用的部分保留在內(nèi)存中,而把其他未被使用的部分保存在磁盤上。比如對一個16MB的程序和一個內(nèi)存只有4MB的機器,OS通過選擇,可以決定各個時刻將哪4M的內(nèi)容保留在內(nèi)存中,并在需要時在內(nèi)存和磁盤間交換程序片段,這樣就可以把這個16M的程序運行在一個只具有4M內(nèi)存機器上了。而這個16M的程序在運行前不必由程序員進行分割。需要說明的一點,操作系統(tǒng)的內(nèi)核是常駐內(nèi)存的。
圍繞著虛擬內(nèi)存管理(Virtual Memory Management)技術,就產(chǎn)生了分頁技術,虛擬地址,地址空間,TLB,MMU等概念。
虛擬內(nèi)存管理技術中最常見的是分頁(paging)技術,MMU就是該技術的硬件實現(xiàn)。虛擬地址空間劃分成稱為頁(page)的單位,而相應的物理地址空間也被進行劃分,單位是頁框(frame),頁和頁框的大小必須相同。接下來配合圖片以一個例子說明頁與頁框之間在MMU的調(diào)度下是如何進行映射。
在這個例子中我們有一臺可以生成16位地址的機器,它的虛擬地址范圍從0x0000~0xFFFF(64K),而這臺機器只有32K的物理內(nèi)存。它可以運行64K的程序,但該程序不能一次性調(diào)入內(nèi)存運行。這臺機器必須有一個達到可以存放64K程序的外部存儲器(例如磁盤或是FLASH),以保證程序片段在需要時可以被調(diào)用。在這個例子中,頁的大小為4K,頁框大小與頁相同(這點是必須保證的,內(nèi)存和外圍存儲器之間的傳輸總是以頁為單位的),對應64K的虛擬地址和32K的物理內(nèi)存,他們分別包含了16個頁和8個頁框。
我們先根據(jù)上圖解釋一下分頁后要用到的幾個術語,在上面我們已經(jīng)接觸了頁和頁框,上圖中綠色部分是物理空間,其中每一格表示一個頁框。橘黃色部分是虛擬空間,每一格表示一個頁,它由兩部分組成,分別是Frame Index(頁框索引)和位p(present 存在位),F(xiàn)rame Index的意義很明顯,它指出本頁是往哪個物理頁框進行映射的,位p的意義則是指出本頁的映射是否有效,如上圖,當某個頁并沒有被映射時(或稱“映射無效”,F(xiàn)rame Index部分為X),該位為0,映射有效則該位為1。
我們執(zhí)行下面這些指令(本例子的指令不針對任何特定機型,都是偽指令)
例1:MOVE REG,0 //將地址0x0000的值傳遞進寄存器REG.
虛擬地址0將被送往MMU,MMU看到該虛地址落在頁0范圍內(nèi)(頁0范圍是0到4095),從上圖我們看到頁0所映射的頁框為2(頁框2的地址范圍是8192到12287),因此MMU將該虛擬地址轉(zhuǎn)化為物理地址8192,并把地址8192送到地址總線上。內(nèi)存對MMU的映射一無所知,它只看到一個對地址8192的讀請求并執(zhí)行它。MMU從而把0到4096的虛擬地址映射到8192到12287的物理地址。
例2:MOVE REG,20500
虛擬地址20500在虛頁5(虛擬地址范圍是20480到24575)距開頭20個字節(jié)處,虛頁5映射到頁框3(頁框3的地址范圍是 12288到16383),于是被映射到物理地址12288+20=12308。
通過適當?shù)脑O置MMU,可以把16個頁隱射到8個頁框中的任何一個,這可以解決上面提到的第二個問題程序運行的地址不確定,但是這個方法并沒有有效的解決虛擬地址空間比物理地址空間大的問題。從上圖中我們可以看到,我們只有8個頁框(物理地址),但我們有16個頁(虛擬地址),所以我們只能把16個頁中的8個進行有效的映射。我們看看下面發(fā)生什么情況。
例3:MOV REG,32780
虛擬地址32780落在頁8的范圍內(nèi),從上圖中我們看到頁8沒有被有效的進行映射(該頁被打上X),這是又會發(fā)生什么?MMU注意到這個頁沒有被映射,于是通知CPU發(fā)生一個 缺頁故障(page fault) 。這種情況下操作系統(tǒng)必須處理這個頁故障,它必須從8個物理頁框中找到1個當前很少被使用的頁框并把該頁框的內(nèi)容寫入外圍存儲器(這個動作被稱為page copy),把對應虛擬地址處的程序從外圍存儲器拷貝到剛才騰空的頁框中,隨后把需要引用的頁(頁8)映射到剛才釋放的頁框中(這個動作稱為修改映射關系),然后從新執(zhí)行產(chǎn)生故障的指令(MOV REG,32780)。假設操作系統(tǒng)決定釋放頁框1,那么它將把頁8裝入物理地址的4-8K,并做兩處修改:首先把標記頁1未被映射(原來虛頁1是被影射到頁框1的),以使以后任何對虛擬地址4K到8K的訪問都引起頁故障而使操作系統(tǒng)做出適當?shù)膭幼鳎ㄟ@個動作正是我們現(xiàn)在在討論的),其次把頁8對應的頁框號由X變?yōu)?,因此重新執(zhí)行MOV REG,32780時,MMU將把32780映射為4108。
正如本節(jié)開頭所述,MMU是分頁技術的硬件實現(xiàn)。我們大致了解了MMU在我們的機器中扮演了什么角色以及它基本的工作內(nèi)容是什么。注意,本例中的MMU并無針對某種特定的機型,它是所有MMU工作的一個抽象。
要理解內(nèi)存在程序中是如何分配的,首先需要理解操作系統(tǒng)如何將內(nèi)存分配給程序。計算機上的每一個進程都認為自己可以訪問所有的物理內(nèi)存。顯然,由于同時在運行多個程序,所以每個進程不可能擁有全部內(nèi)存。實際上,這些進程使用的是虛擬內(nèi)存。
舉個例子,讓我們假定您的程序正在訪問地址為 629 的內(nèi)存。不過,虛擬內(nèi)存系統(tǒng)不需要將其存儲在位置為 629 的 RAM 中。實際上,它甚至可以不在 RAM 中 ―― 如果物理RAM已經(jīng)滿了,它甚至可能已經(jīng)被轉(zhuǎn)移到硬盤上!由于這類地址不必反映內(nèi)存所在的物理位置,所以它們被稱為虛擬內(nèi)存。操作系統(tǒng)維持著一個虛擬地址到物理地址的轉(zhuǎn)換的表,以便計算機硬件可以正確地響應地址請求。如果地址在硬盤上而不是在RAM中,那么操作系統(tǒng)將暫時停止您的進程,將其他內(nèi)存轉(zhuǎn)存到硬盤中,從硬盤上加載被請求的內(nèi)存, 然后再重新啟動您的進程。這樣,每個進程都獲得了自己可以使用的地址空間,可以訪問比您物理上安裝的內(nèi)存更多的內(nèi)存。
在32-位的x86系統(tǒng)上,每一個進程可以訪問4GB內(nèi)存?,F(xiàn)在,大部分人的系統(tǒng)上并沒有4GB內(nèi)存,即使您將swap也算上, 每個進程所使用的內(nèi)存也肯定少于 4 GB。因此,當加載一個進程時, 它會得到一個取決于某個稱為系統(tǒng)中斷點(system break)的特定地址的初始內(nèi)存分配。該地址之后是未被映射的內(nèi)存 ――用于在RAM或者硬盤中沒有分配相應物理位置的內(nèi)存。因此,如果一個進程運行超出了它初始分配的內(nèi)存,那么它必須請求操作系統(tǒng)“映射進來(map in)”更多的內(nèi)存。(映射是一個表示一一對應關系的數(shù)學術語 ―― 當內(nèi)存的虛擬地址有一個對應的物理地址來存儲內(nèi)存內(nèi)容時,該內(nèi)存將被映射。)
基于UNIX的系統(tǒng)有兩個可映射到物理內(nèi)存中的基本系統(tǒng)調(diào)用:
如您所見, brk() 或者 mmap() 都可以用來向我們的 進程添加額外的虛擬內(nèi)存。在我們的例子中將使用 brk(),因為它更簡單,更通用。
摘自Jonathan Bartlett《內(nèi)存管理內(nèi)幕-動態(tài)分配的選擇、折衷和實現(xiàn)》。
地址空間是一個抽象的概念,由CPU體系架構的地址總線決定,一般等同于CPU的尋址范圍、x位處理器中的x。地址空間一般分為 虛擬地址空間 和 物理地址空間 。
任何時候,計算機上都存在一個程序能夠訪問的地址集合,我們稱之為地址空間。這個空間的大小由CPU的位數(shù)決定,例如一個32位的CPU,它的地址范圍是0~0xFFFFFFFF (4G),而對于一個64位的CPU,它的地址范圍為0~0xFFFFFFFFFFFFFFFF (64T)。這個空間就是我們的程序能夠產(chǎn)生的地址范圍,我們把這個地址范圍稱為 虛擬地址空間 ,該空間中的某一個地址我們稱之為虛擬地址。與虛擬地址空間和虛擬地址相對應的則是物理地址空間和物理地址,大多數(shù)時候我們的系統(tǒng)所具備的物理地址空間只是虛擬地址空間的一個子集,這里舉一個最簡單的例子直觀地說明這兩者,對于一臺內(nèi)存為256MB的32bit x86主機來說,它的虛擬地址空間范圍是0~0xFFFFFFFF(4G),而物理地址空間范圍是0x000000000~0x0FFFFFFF(256MB)。
虛擬地址又被簡稱為虛地址,物理地址又被稱為實地址。虛擬地址和物理地址之間的轉(zhuǎn)換,又稱為虛實地址轉(zhuǎn)化。
在沒有使用的虛擬內(nèi)存管理(Virtual Memory Management)技術機器上,虛擬地址被直接送到內(nèi)存總線上,使具有相同地址的物理存儲器被讀寫。而在使用了虛擬存儲器的情況下,虛擬地址不是被直接送到內(nèi)存地址總線上,而是送到內(nèi)存管理單元MMU。他由一個或一組芯片組成,一般存在與協(xié)處理器中,其功能是把虛擬地址映射為物理地址。
下面這張圖就是描述虛擬地址/物理地址和CPU核、MMU、內(nèi)存之間的關系。
虛擬內(nèi)存管理(Virtual Memory Management)技術中重要的一點,就是將地址空間分成了虛擬地址和物理地址,在CPU核和內(nèi)存之間的地址總線上增加了一層。首先需要指出的是,TLB和MMU只是實現(xiàn)虛擬地址到物理地址轉(zhuǎn)化最為常見的一種辦法,還有另外的方法,如下文所描述。
為了區(qū)分不同進程的存儲空間,現(xiàn)在多任務的操作系統(tǒng)以及處理器都需要支持虛擬地址(Virtual Address, VA)物理地址(Physical Address, PA)轉(zhuǎn)化,地址轉(zhuǎn)換主要分為兩種:
摘自《處理器的存儲子系統(tǒng)》by Sigma。直接映射的方式在MIPS內(nèi)存模型中的kseg0和kseg1就是使用的這種辦法,直接將虛擬地址的高1位或者3位去掉,轉(zhuǎn)化成物理地址。參考和《See MIPS Run》p47。
下面我們只介紹使用MMU和TLB的映射原理。
MMU是如何把VA映射成PA的呢?內(nèi)存中保存一張VA轉(zhuǎn)PA的表,MMU被配置為指向該表的開始的物理地址,給一個VA通過MMU查表就可以查到PA,這是從簡單處理解。實際上并不是這么簡單,通常要有一個多級的查表過程,對于ARM體系結(jié)構是兩級查表,對于一些64位體系結(jié)構則需要更多級。MMU的工作原理和機制,參考下面的各處理器架構MMU實例章節(jié)。
以32位的x86系統(tǒng)為例。
x86采用兩級頁表結(jié)構,第一級稱為頁目錄表,第二級稱為頁表。
名稱 | 類型 | VA索引bit位 | 頁表項 | 存儲大小/KB | 默認頁大小 | 支持的頁大小 |
頁目錄表 | L1 | 10位 [31:22] | 1024 | 4 | xxx | xxx |
頁表 | L2 | 10位 [21:12] | 1024 | 4 | 4KB | xxx |
頁表目錄的起始物理地址由CPU中的CR3寄存器指定。
重點參考《ARM嵌入式系統(tǒng)開發(fā)-軟件設計與優(yōu)化》第14章 存儲管理單元。下面的使用的截圖是三星公司的S3C2410,這款芯片是一種很常見的采用ARM920T的芯片。
ARM920T的MMU和Cache都集成在CP15協(xié)處理器中,MMU和Cache的聯(lián)系非常密切。
下面是CP15協(xié)處理器的寄存器列表,和CPU核的r0到r15寄存器一樣,協(xié)處理器寄存器也是用0到15來編號,在指令中用4個bit來表示寄存器編號,有些協(xié)處理器寄存器有影子寄存器。
CP15:c2寄存器保存轉(zhuǎn)化表基地址TTB(Translation Table Base address)――指向L1主頁表在物理內(nèi)存中的位置。TTB地址必須與存儲器的16KB邊界對齊(寄存器的bit0 - bit13 為0,should be zero)。
對CP15協(xié)處理器的操作使用mcr和mrc兩條協(xié)處理器指令,這兩條指令的記法是從后往前看:mcr是把r(CPU核寄存器)中的數(shù)據(jù)傳送到c(協(xié)處理器寄存器)中,mrc則是把c(協(xié)處理器寄存器)中的數(shù)據(jù)傳送到r(CPU核寄存器)中。對CP15協(xié)處理器的所有操作都是通過CPU核寄存器和CP15寄存器之間交換數(shù)據(jù)來完成的。
這個過程稱為Translation Table Walk,Walk這個詞用得非常形象。從TTB走到一級頁表,又走到二級頁表,又走到物理頁面, 一次尋址其實是三次訪問物理內(nèi)存。 注意這個“走”的過程完全是硬件做的,每次CPU尋址時MMU就自動完成以上四步,不需要編寫指令指示MMU去做,前提是操作系統(tǒng)要維護頁表項的正確性,每次分配內(nèi)存時填寫相應的頁表項,每次釋放內(nèi)存時清除相應的頁表項,在必要的時候分配或釋放整個頁表。
ARM MMU硬件采用2級頁表結(jié)構:一級頁表(L1)和二級頁表(L2)。
L1頁表只有一個主頁表,也稱為L1主頁表(L1 master page table)或者段頁表(section page table)。使用VA的高12bit位索引該表,所以該表有2的12次方(4K)個頁表項(PTE,page table entry),每個頁表項4個字節(jié),一共需要占去內(nèi)存16KB。
有兩種類型的L2頁表,分別是L2粗頁表(coarse page table)和L2細頁表(fine page table)。對于L2粗頁表,使用VA的次高8bit索引該表,所以該表有2的8次方(256)個頁表項(PTE,page table entry),每個頁表項4個字節(jié),一共需要占去內(nèi)存1KB。對于L2細頁表,使用VA的次高10bit索引該表,所以該表有2的10次方(1024)個頁表項(PTE,page table entry),每個頁表項4個字節(jié),一共需要占去內(nèi)存4KB。
名稱 | 類型 | VA索引bit位 | 頁表項 | 存儲大小/KB | 默認頁大小 | 支持的頁大小 |
主頁表/段頁表 | L1 | 12位 [31:20] | 4096 | 16 | 1MB | 1MB |
細頁表 | L2 | 10位 [19:10] | 1024 | 4 | 1KB | 1/4/64KB |
粗頁表 | L2 | 8位 [19:12] | 256 | 1 | 4KB | 4/64KB |
下圖是使用L1主頁表和粗頁表實現(xiàn)的一個簡單VA到PA的轉(zhuǎn)化示意圖:
對于OS來說,頁表是進程私有的,因此各個進程的頁表被放置在不同的物理內(nèi)存中。在進程啟動或者切換時,都必須把進程的頁表的起始物理地址告訴MMU,也就是上面提到的TTB值(CP15:c2寄存器)。下面看采用單級頁表的情況。假設頁的大小為4KB,那么對于頁表的索引就需要使用VA的[31:12],也就有1M個頁表項,一個頁表項4字節(jié),可以算的頁表的大小為4M。 這意味著這4M空間必須作為進程的必備資源在啟動的時候一次分配,而且這4M的內(nèi)存必須在物理地址上連續(xù)。 這和虛擬內(nèi)存設計的理念(小內(nèi)存系統(tǒng)上運行盡量多的程序)不相符合。解決的辦法就是采用多級頁表。
多級頁表是如何解決單級頁表存在的問題呢?考慮到一個進程不需要同時訪問到4GB的內(nèi)存,因此把頁表也分散開來,一級頁表必須分配,二級頁表像物理頁面那樣在需要的時候再分配映射。當然,多級頁表需要MMU硬件支持。
待續(xù)
待續(xù)
聯(lián)系客服