一尘不染

Linux中进程的步行页面表

linux

我正在尝试浏览Linux中某个进程的页表。在内核模块中,我实现了以下功能:

static struct page *walk_page_table(unsigned long addr)
{
    pgd_t *pgd;
    pte_t *ptep, pte;
    pud_t *pud;
    pmd_t *pmd;

    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;
    pte = *ptep;

    page = pte_page(pte);
    if (page)
        printk(KERN_INFO "page frame struct is @ %p", page);

 out:
    return page;
}

此函数是从调用的ioctl,它addr是进程地址空间中的虚拟地址:

static int my_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long addr)
{
   struct page *page = walk_page_table(addr);
   ...
   return 0;
}

奇怪的是,ioctl在用户空间进程中调用时,此段错误…但是似乎我在寻找页表条目的方式是正确的,因为dmesg我可以通过每次ioctl调用获取例如:

[ 1721.437104] Valid pgd
[ 1721.437108] Valid pud
[ 1721.437108] Valid pmd
[ 1721.437110] page frame struct is @ c17d9b80

那么,为什么该过程无法正确完成“ ioctl”调用?也许我必须在浏览页面表之前锁定一些东西?

我正在使用内核2.6.35-22和三级页表。

谢谢你们!


阅读 258

收藏
2020-06-03

共1个答案

一尘不染

pte_unmap(ptep);

标签刚好消失了。尝试以这种方式更改代码:

    ...
    page = pte_page(pte);
    if (page)
        printk(KERN_INFO "page frame struct is @ %p", page);

    pte_unmap(ptep);

out:
2020-06-03