1. pfn的基础概念
linux系统使用分页机制,将物理内存分成每个大小为4K的页。PFN,即page frame number的缩写,取值范围是0--(memory size >> 12)
但是由于物理内存映射的关系,物理内存的0地址对应到系统上并不是物理地址的0.
例如,s3c2440上,内存的地址是从0x30000000开始的。当连接ram后,ram的0地址在s3c2440看来,就是0x30000000。所以在系统中pfn的值应该等于(physical address - memory base address)>> 12
在linux中,cpu看到的都是虚拟地址。所以虚拟地址转换为pfn,需要先将虚拟地址转换为物理地址,内核提供了下面两个宏,可以将内核线性空间的虚拟地址和pfn转换:
#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) //__pa() 将虚拟地址转化成物理地址
#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT)
所以pfn在linux内核中应该对应的是页帧号。可以通过简单的转换找到对应的物理地址。
每个物理上的页,内核给与之分配了一个描述符来描述: page。 pfn可以和page进行转换:
#define page_to_pfn __page_to_pfn
#define pfn_to_page __pfn_to_page
虚拟地址也可以和page进行转换:
#define virt_to_page(addr) (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT))
#define page_to_virt(page) ((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET)
所有的page结构存放在mem_map中,方便进行管理。
评论