【问题标题】:Check if the page is in the task's VMA检查页面是否在任务的 VMA 中
【发布时间】:2012-01-19 07:46:56
【问题描述】:

有没有办法检查相关页面是否被指定进程使用? 即我有一个指向struct pagestruct task_struct 的指针,我想获得一个布尔值,表示页面是否在进程的VMA 中。目前,我一直在获取进程 VMA 中页面的虚拟地址。如果我得到它,我将能够遍历pgd 并查看它是否存在。

我已经尝试过在vma_address()mm/rmap.c)中采用的方法,但是在循环任务的mm_struct->mmap 时,列表中每个vm_area_struct 的虚拟地址似乎都不同。这与find_vma()(在'mm/mmap.c`)相矛盾,后者使用作为参数提供的固定地址扫描任务的VMA(尽管搜索相应的rb-tree)。

那么,做这些事情的正确方法是什么?

【问题讨论】:

    标签: linux memory-management linux-kernel kernel


    【解决方案1】:

    事实证明,只有像这样扫描整个 VMA 跳跃 PAGE_SIZE 的唯一方法:

    struct page *page_by_address(const struct mm_struct *const mm,
                                 const unsigned long address)
    {
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;
        struct page *page = NULL;
    
        pgd = pgd_offset(mm, address);
        if (!pgd_present(*pgd))
            goto do_return;
    
        pud = pud_offset(pgd, address);
        if (!pud_present(*pud))
            goto do_return;
    
        pmd = pmd_offset(pud, address);
        if (!pmd_present(*pmd))
            goto do_return;
    
        pte = pte_offset_kernel(pmd, address);
        if (!pte_present(*pte))
            goto do_return;
    
        page = pte_page(*pte);
    do_return:
        return page;
    }
    
    int contains_page(const struct mm_struct *const mm, struct page *const page)
    {
        int contains = 0;
    
        if (mm != NULL) {
            const struct vm_area_struct *vma = mm->mmap;
            while (vma != NULL) {
                unsigned long address;
                for (address = vma->vm_start; !contains && address < vma->vm_end; address += PAGE_SIZE) {
                    contains = (page_by_address(mm, address) == page);
                }
    
                vma = vma->vm_next;
            }
        }
    
        return contains;
    }
    

    【讨论】:

    • 巨大透明的巨页怎么样?在这种情况下,您的 page_by_address 实现是虚假的。
    • @IlyaMatveychikov 如果您能够更清楚地了解这个问题,我鼓励您写下您的答案。我的解决方案是作为大学“操作系统设计”课程的家庭任务实施的。所以它可能会犯错误。但那是我当时能做的最好的了。
    • follow_page 是一个很好的例子。
    • 您可以阅读有关透明大页面herethere
    • @IlyaMatveychikov 可能内核版本是误解的关键:我们正在探索版本 2.6.32。无论如何,谢谢你的信息。
    【解决方案2】:
    for vma in task_struct:
        call page_address_in_vma(page, vma)
    

    Refer to this link.

    【讨论】:

      猜你喜欢
      • 2016-03-22
      • 2011-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多