c - Linux 中的页表遍历

标签 c linux memory operating-system kernel

考虑以下代码:

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_pagekmap,它会按预期工作。为什么会这样?我在 x86-64 上,所以高内存应该不是问题? kmap 还有其他功能吗?

最佳答案

感谢 TonyTannous,我解决了这个问题。页表条目不仅包含物理地址,还包含一些用于访问权限等的其他位。物理地址可以通过用PTE_PFN_MASK屏蔽得到:

    addr = ptep->pte & PTE_PFN_MASK

然后我可以使用 __va 取消引用它。

关于c - Linux 中的页表遍历,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46782797/

相关文章:

c - 有没有办法获取数组的内容并将其存储到指针中?

c - 循环未在指定时间内运行

c循环双向链表删除节点-删除后第一次迭代遍历删除的节点

linux - 自定义 Liquibase 控制表(DATABASECHANGELOG 和 DATABAEECHANGELOGLOCK)

c++ - 使用 std::vector 添加和删除大量数据

c - 如何为从 c 中的文件读取的一行文本分配足够的内存

c - 用 C 语言编写字数统计程序

php - linux 作业的命令无法从 php 运行

python - 在 dbus 中模拟网络存在

performance - 对于磁盘/RAM,访问时间和读/写速度之间的关系是什么?