file:///C:\Users\郭曉娟\AppData\Local\Temp\ksohtml\wpsF282.tmp.png 先上一張arm mmu的頁(yè)表結構的通用框圖(以下的論述都由該圖來(lái)逐漸展開(kāi)): file:///C:\Users\郭曉娟\AppData\Local\Temp\ksohtml\wpsF293.tmp.jpgfile:///C:\Users\郭曉娟\AppData\Local\Temp\ksohtml\wpsF2A3.tmp.png 以上是arm的頁(yè)表框圖的典型結構:即是二級頁(yè)表結構: 其中第一級頁(yè)表(L1)是由虛擬地址的高12bit(bits[31:20])組成,所以第一級頁(yè)表有4096個(gè)item,每個(gè)item占4個(gè)字節,所以一級頁(yè)表的大小為16KB,而在第一級頁(yè)表中的每個(gè)entry的最低2bit可以用來(lái)區分具體是什么種類(lèi)的頁(yè)表項,2bit可以區分4種頁(yè)表項,具體每種頁(yè)表項的結構如下: file:///C:\Users\郭曉娟\AppData\Local\Temp\ksohtml\wpsF2B4.tmp.jpg 簡(jiǎn)而言之L1頁(yè)表的頁(yè)表項主要有兩大類(lèi): 第一大類(lèi)是指向第二級頁(yè)表(L2頁(yè)表)的基地址; 第二類(lèi)直接指向1MB的物理內存。 在L1頁(yè)表中每個(gè)表項可以覆蓋1MB的內存,由于有4096K個(gè)選項(item),所以總計可以覆蓋4096K*1MB=4GB的內存空間。 具體對應到Linux,由于linux 的軟件架構是支持3級頁(yè)表結構,而arm架構實(shí)際只有2級的頁(yè)表結構,所以linux代碼中的中間級頁(yè)表的實(shí)現是空的。在linux代碼中,第一級的頁(yè)表的頁(yè)目錄表項用pgd表示,中間級的頁(yè)表的頁(yè)目錄表項用pud表示(arm架構其實(shí)不需要),第三級的頁(yè)表的頁(yè)目錄表項用pmd表示(由于中間pud是空的,所以pgd=pmd),另外目前arm體系的移動(dòng)設備中RAM的page大小一般都是4KB/page,所以L(fǎng)1頁(yè)表中的頁(yè)表項都是指向fine page table的 信盈達嵌入式企鵝要妖氣嗚嗚吧就零久要。 但在linux內核啟動(dòng)的初始化階段,臨時(shí)建立頁(yè)表(initial page tables)以供linux內核初始化提供執行環(huán)境,這時(shí)L1的頁(yè)表項使用的就是第二種頁(yè)表項(section enty),他直接映射的是1M的內存空間。具體的可以參考arch/arm/kernel/head.S中的__create_page_tables函數,限于篇幅,這里就不展開(kāi)說(shuō)了。 針對這種section page translation,mmu硬件執行虛擬地址轉物理地址的過(guò)程如下: file:///C:\Users\郭曉娟\AppData\Local\Temp\ksohtml\wpsF2C5.tmp.jpg 以上在初始化過(guò)程使用的臨時(shí)頁(yè)表(initial page tables),在內核啟動(dòng)的后期會(huì )被覆蓋掉,即在paging_init--->map_lowmem函數中會(huì )重新建立頁(yè)表,該函數為物理內存從0地址到低端內存(lowmem_limit)建立一個(gè)一一映射的映射表。所謂的一一映射就是物理地址和虛擬地址就差一個(gè)固定的偏移量,該偏移量一般就是0xc0000000(呵呵,為什么是0xc0000000?) 說(shuō)到這里引入一個(gè)重要的概念,就是與低端內存相對的高端內存,什么是高端內存?為什么需要高端內存?為了解析這個(gè)問(wèn)題,我們假設我們使用的物理內存有2GB大小,另外由于我們內核空間的地址范圍是從3G-4G的空間,并且前面也說(shuō)到了,linux內核的低端內存空間都是一一映射的,如果不引入高端內存這個(gè)概念,全部都使用一一映射的方式,那內核只能訪(fǎng)問(wèn)到1GB的物理內存,但實(shí)際上,我們是需要內核在內核空間能夠訪(fǎng)問(wèn)所有的4GB的內存大小的,那怎么做到呢? 方法就是我們不讓3G-4G的空間都使用一一映射,而是將物理地址的[0x00,fix_addr](fix_addr<1GB)映射到內核空間虛擬地址[0x00+3G,fix_addr+3G],然后將[fix_addr+3G,4G]這段空間保留下來(lái)用于動(dòng)態(tài)映射,這樣我們可以通過(guò)這段虛擬地址來(lái)訪(fǎng)問(wèn)從fix_addr到4GB的物理內存空間。怎么做到的呢? 譬如我們想要訪(fǎng)問(wèn)物理地址[fix_addr,4GB]這段區間中的任何一段,我就用寶貴的內核虛擬地址[fix_addr+3G,4G]的一段去映射他,建立好mmu硬件使用的頁(yè)表,訪(fǎng)問(wèn)完后,將映射清除,將內核的這段虛擬地址釋放,以供下次訪(fǎng)問(wèn)其他的物理內存使用。這樣就可以達到訪(fǎng)問(wèn)所有4GB的物理內存的目的。
|