在linux中,pfn全稱“page frame number”,是物理內(nèi)存區(qū)域編號。“page frame”是針對物理內(nèi)存而言的,把物理內(nèi)存分成一個個的page size的區(qū)域,并且給每一個page編號,而這個編號就是PFN。
本教程操作環(huán)境:linux5.9.8系統(tǒng)、Dell G3電腦。
1、什么是page frame?
操作系統(tǒng)最重要的作用之一就是管理計算機系統(tǒng)中的各種資源,做為最重要的資源:內(nèi)存,我們必須管理起來。在linux操作系統(tǒng)中,物理內(nèi)存是按照page size來管理的,具體page size是多少是和硬件以及l(fā)inux系統(tǒng)配置相關(guān)的,4k是最經(jīng)典的設(shè)定。因此,對于物理內(nèi)存,我們將其分成一個個按page size排列的page,每一個物理內(nèi)存中的page size的內(nèi)存區(qū)域我們稱之page frame。我們針對每一個物理的page frame建立一個struct page的數(shù)據(jù)結(jié)構(gòu)來跟蹤每一個物理頁面的使用情況:是用于內(nèi)核的正文段?還是用于進(jìn)程的頁表?是用于各種file cache還是處于free狀態(tài)……
每一個page frame有一個一一對應(yīng)的page數(shù)據(jù)結(jié)構(gòu),系統(tǒng)中定義了page_to_pfn和pfn_to_page的宏用來在page frame number和page數(shù)據(jù)結(jié)構(gòu)之間進(jìn)行轉(zhuǎn)換,具體如何轉(zhuǎn)換是和memory modle相關(guān),我們會在第三章詳細(xì)描述linux kernel中的3種內(nèi)存模型。
2、什么是PFN?
對于一個計算機系統(tǒng),其整個物理地址空間應(yīng)該是從0開始,到實際系統(tǒng)能支持的最大物理空間為止的一段地址空間。在ARM系統(tǒng)中,假設(shè)物理地址是32個bit,那么其物理地址空間就是4G,在ARM64系統(tǒng)中,如果支持的物理地址bit數(shù)目是48個,那么其物理地址空間就是256T。當(dāng)然,實際上這么大的物理地址空間并不是都用于內(nèi)存,有些也屬于I/O空間(當(dāng)然,有些cpu arch有自己獨立的io address space)。因此,內(nèi)存所占據(jù)的物理地址空間應(yīng)該是一個有限的區(qū)間,不可能覆蓋整個物理地址空間。不過,現(xiàn)在由于內(nèi)存越來越大,對于32位系統(tǒng),4G的物理地址空間已經(jīng)無法滿足內(nèi)存的需求,因此會有high memory這個概念,后續(xù)會詳細(xì)描述。
PFN是page frame number的縮寫,所謂page frame,就是針對物理內(nèi)存而言的,把物理內(nèi)存分成一個個的page size的區(qū)域,并且給每一個page 編號,這個編號就是PFN。假設(shè)物理內(nèi)存從0地址開始,那么PFN等于0的那個頁幀就是0地址(物理地址)開始的那個page。假設(shè)物理內(nèi)存從x地址開始,那么第一個頁幀號碼就是(x>>PAGE_SHIFT)。
PFN的取值范圍是 0—-(memory size >> 12)。
但是由于物理內(nèi)存映射的關(guān)系,物理內(nèi)存的0地址對應(yīng)到到系統(tǒng)上并不是物理地址的0。 例如:s3c2440上,內(nèi)存的地址是從0x30000000開始的。當(dāng)連接ram后,ram的0地址在s3c2440看來,就是0x30000000. 所以在系統(tǒng)中 pfn的值 應(yīng)該等于 (physical address – memory base address) >> 12 。
但是linux中,用的又都是虛擬地址,所以要先將 virtual address轉(zhuǎn)換成 physical address 才行。 所以在linux中有個宏定義 將內(nèi)核線性空間的虛擬地址和pfn轉(zhuǎn)換:
#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) //__pa() 將虛擬地址轉(zhuǎn)化成物理地址 #define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
所以pfn在linux內(nèi)核中應(yīng)該對應(yīng)的是頁幀號??梢酝ㄟ^簡單的轉(zhuǎn)換找到對應(yīng)的物理地址。
每個物理上的頁,內(nèi)核給與之分配了一個描述符來描述: page。 pfn可以和page進(jìn)行轉(zhuǎn)換:
#define page_to_pfn __page_to_pfn #define pfn_to_page __pfn_to_page
所有的page結(jié)構(gòu)存放在mem_map中,方便進(jìn)行管理。
由于linux是將物理內(nèi)存分成4K大小的頁來進(jìn)行管理的。所以在軟件上也會設(shè)置MMU進(jìn)行匹配對應(yīng)。后面敘述。
linux將4G的虛擬空間分成了用戶空間和內(nèi)核空間。用戶空間是0—3G,內(nèi)核空間是3G—4G。 從內(nèi)核空間可以訪問到用戶空間,但是從用戶空間必須通過系統(tǒng)調(diào)用來能訪問內(nèi)核空間。