遍历流程的所有物理页面 [英] Traversing all the physical pages of a process

查看:108
本文介绍了遍历流程的所有物理页面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在内核模块(2.6.32-358.el6.x86_64)中,我想打印出所有物理地址,这些地址被映射到进程的虚拟内存中.给定task->mm,我尝试遍历进程的struct page,如下所示:

In a kernel module (2.6.32-358.el6.x86_64) I'd like to print out all the physical addresses, which are mapped into a process' virtual memory. Given task->mm, I attempt to traverse the process' struct page's as follows:

int i, j, k, l;
for (i = 0; i < PTRS_PER_PGD; ++i)
{
    pgd_t *pgd = mm->pgd + i;
    if (pgd_none(*pgd) || pgd_bad(*pgd))
        continue;
    for (j = 0; j < PTRS_PER_PUD; ++j)
    {
        pud_t *pud = (pud_t *)pgd_page_vaddr(*pgd) + j;
        if (pud_none(*pud) || pud_bad(*pud))
            continue;
        for (k = 0; k < PTRS_PER_PMD; ++k)
        {
            pmd_t *pmd = (pmd_t *)pud_page_vaddr(*pud) + k;
            if (pmd_none(*pmd) || pmd_bad(*pmd))
                continue;

            for (l = 0; l < PTRS_PER_PTE; ++l)
            {
                pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd) + l;
                if (!pte || pte_none(*pte))
                    continue;
                struct page *p = pte_page(*pte);
                unsigned long phys = page_to_phys(p);
                printk(KERN_NOTICE "addr %lx", phys);
            }
        }
    }
}

输出看起来有点奇怪(特别是,有一系列相同的地址),所以从理论上讲,我想问一下以上是否正确.

The output looks a bit strange (in particular, there are serieses of identical addresses), so I'd like to ask whether the above is correct, in theory.

推荐答案

更好的方法是遍历进程的VMA,并通过页面目录将每个VMA转换为物理页面/地址:

A better approach would be to traverse process' VMAs and translate each VMA to physical pages/addresses by means of the page directory:

struct vm_area_struct *vma = 0;
unsigned long vpage;
if (task->mm && task->mm->mmap)
    for (vma = task->mm->mmap; vma; vma = vma->vm_next)
        for (vpage = vma->vm_start; vpage < vma->vm_end; vpage += PAGE_SIZE)
            unsigned long phys = virt2phys(task->mm, vpage);
//...

virt2phys如下所示:

//...
pgd_t *pgd = pgd_offset(mm, virt);
if (pgd_none(*pgd) || pgd_bad(*pgd))
    return 0;
pud = pud_offset(pgd, virt);
if (pud_none(*pud) || pud_bad(*pud))
    return 0;
pmd = pmd_offset(pud, virt);
if (pmd_none(*pmd) || pmd_bad(*pmd))
    return 0;
if (!(pte = pte_offset_map(pmd, virt)))
    return 0;
if (!(page = pte_page(*pte)))
    return 0;
phys = page_to_phys(page);
pte_unmap(pte);
return phys;

这篇关于遍历流程的所有物理页面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆