CPU只能访问虚拟内存,而实际的数据都存放在物理内存上面,
这就需要将虚拟内存映射到物理内存上面去,然后在物理内存上获取数
据传送到CPU中进行运算,而这个地址的映射就通过页表来完成的。
---------------------------------------------------------------------------------
一,linux内核的四级页表。
内核为什么要设计四级页表呢?主要是为了支持多种硬件平台,
---------------------------------------------------------------------------------
一,linux内核的四级页表。
内核为什么要设计四级页表呢?主要是为了支持多种硬件平台,
各种CPU提供的硬件支持不一样,还有要支持64位机。内核的4级页表可
以退化为3级页表,还可以退化到2级页表。四级页表也就是把一个虚拟
地址分为了5部分,分别是PGD,PUD,PMD,PTE,offset
示意图如下:
------------------------------------------------------------------------------
二,实战,将一个用vmalloc开辟的地址映射为物理地址。
模块运行结果:(环境:linux.2.6.36,intel 32位系统)
可以看出pud和pmd的偏移量均为0,说明在这儿就只使用了二级页表,
示意图如下:
------------------------------------------------------------------------------
二,实战,将一个用vmalloc开辟的地址映射为物理地址。
- static unsigned long vaddr_to_paddr(unsigned long va)
- {
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *pte;
- unsigned long paddr;
- unsigned long page_addr;
- unsigned long page_offset;
-
- pgd = pgd_offset(current->mm,va);
- printk("pgd_val = 0x%lx\n",pgd_val(*pgd));
- printk("pgd_index = %lu\n",pgd_index(va));
- if (pgd_none(*pgd)) {
- printk("not mapped in pgd!\n");
- return -1;
- }
-
- pud = pud_offset(pgd,va);
- printk("pud_val = 0x%lx\n",pud_val(*pud));
- printk("pud_index = %lu\n",my_pud_index(va));
- if (pud_none(*pud)) {
- printk("not mapped in pud!\n");
- return -1;
- }
-
- pmd = pmd_offset(pud,va);
- printk("pmd_val = 0x%lx\n",pmd_val(*pmd));
- printk("pmd_index = %lu\n",pmd_index(va));
- if (pmd_none(*pmd)) {
- printk("not mapped in pmd!\n");
- return -1;
- }
-
- pte = pte_offset_kernel(pmd,va);
- printk("pte_val = 0x%lx\n",pte_val(*pte));
- printk("pte_index = %lu\n",pte_index(va));
- if (pte_none(*pte)) {
- printk("not mapped in pte!\n");
- return -1;
- }
-
-
- page_addr = pte_val(*pte) & PAGE_MASK;
- page_offset = va & ~PAGE_MASK;
- paddr = page_addr | page_offset;
-
- printk("vaddr = %lx,paddr = %lx\n",va,paddr);
- printk("page_addr = %lx\n",page_addr);
-
- return paddr;
- }
- [263298.365202] pgd_val = 0x5e18067
- [263298.365207] pgd_index = 995
- [263298.365210] pud_val = 0x5e18067
- [263298.365213] pud_index = 0
- [263298.365216] pmd_val = 0x5e18067
- [263298.365218] pmd_index = 0
- [263298.365221] pte_val = 0x63c0163
- [263298.365223] pte_index = 127
- [263298.365226] vaddr = f8c7f000,paddr = 63c0000
- [263298.365229] page_addr = 63c0000
将pud和pmd都“折叠”起来了。代码的过程完全可以由上面的图解释。
-----------------------------------------------------------------------------------------
三,模块完整代码
vaddr_to_paddr.rar
------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
三,模块完整代码
vaddr_to_paddr.rar
------------------------------------------------------------------------------------------