考虑以下代码:
pgd_t *pgd;
pte_t *ptep;
pud_t *pud;
pmd_t *pmd;
char *addr;
struct page *page = NULL;
struct mm_struct *mm = current->mm;
pgd = pgd_offset(mm, addr);
if (pgd_none(*pgd) || pgd_bad(*pgd))
goto out;
printk(KERN_NOTICE "Valid pgd");
pud = pud_offset(pgd, addr);
if (pud_none(*pud) || pud_bad(*pud))
goto out;
printk(KERN_NOTICE "Valid pud");
pmd = pmd_offset(pud, addr);
if (pmd_none(*pmd) || pmd_bad(*pmd))
goto out;
printk(KERN_NOTICE "Valid pmd");
ptep = pte_offset_map(pmd, addr);
if (!ptep)
goto out;
addr = ptep->pte;
printk(KERN_INFO "byte = %d\n", *(char *)__va(addr));
pte_unmap(ptep);
如果我理解正确,
addr
应该是对应于用户空间虚拟地址的物理地址。然后,我应该能够使用__va
取消引用它。但是,它不起作用。但是,如果我使用pte_page
和kmap
,那么它应该可以正常工作。为什么会这样?我在x86-64上,所以高内存应该不是问题吗? kmap
还有其他功能吗? 最佳答案
感谢TonyTannous,我解决了这个问题。页表条目不仅包含物理地址,还包含用于访问权限等的其他一些位。可以通过使用PTE_PFN_MASK
屏蔽它来获得物理地址:
addr = ptep->pte & PTE_PFN_MASK
然后,我可以使用
__va
取消引用它。关于c - Linux中的页表遍历,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46782797/