Linux 检查页面是否在任务中';s VMA

Linux 检查页面是否在任务中';s VMA,linux,memory-management,linux-kernel,kernel,Linux,Memory Management,Linux Kernel,Kernel,是否有办法检查指定进程是否使用了相关页面? i、 e.我有一个指向struct page和struct task_struct的指针,我想获得一个布尔值,指示页面是否在进程的VMA中。目前,我一直在获取进程的VMA中页面的虚拟地址。如果我得到它,我将能够遍历pgd,看看它是否在那里 我尝试过在vma_address()(在mm/rmap.c)中采用的方法,但是在任务的mm_struct->mmap上循环时,列表中每个vm_area_struct的虚拟地址似乎都不同。这与find_vma()(位于

是否有办法检查指定进程是否使用了相关页面? i、 e.我有一个指向
struct page
struct task_struct
的指针,我想获得一个布尔值,指示页面是否在进程的VMA中。目前,我一直在获取进程的VMA中页面的虚拟地址。如果我得到它,我将能够遍历
pgd
,看看它是否在那里

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


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

事实证明,只有这样才能通过
页面大小来扫描整个VMA,如下所示:

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;
}
struct page*page\u by\u address(const struct mm\u struct*const mm,
常量(无符号长地址)
{
pgd_t*pgd;
布丁;
pmd_t*pmd;
私人有限公司;
结构页面*page=NULL;
pgd=pgd_偏移量(毫米,地址);
如果(!pgd_存在(*pgd))
去做你回来;
pud=pud_偏移量(pgd,地址);
如果(!pud_存在(*pud))
去做你回来;
pmd=pmd_偏移量(pud,地址);
如果(!pmd_存在(*pmd))
去做你回来;
pte=pte_偏移量_内核(pmd,地址);
如果(!pte_存在(*pte))
去做你回来;
第页=第页(*pte);
是否返回:
返回页面;
}
int包含_页(常量结构mm_结构*常量mm,结构页*常量页)
{
int=0;
如果(mm!=NULL){
const struct vm_area_struct*vma=mm->mmap;
while(vma!=NULL){
无符号长地址;
对于(地址=vma->vm_开始;!包含和地址vm_结束;地址+=页面大小){
包含=(逐页地址(mm,地址)==第页);
}
vma=vma->vm\u下一步;
}
}
返回包含;
}

.

那么大而透明的大页面呢?在这种情况下,你的
逐页地址
实现是虚假的。@IlyaMatveychikov如果你能对这个问题有更多的了解,我鼓励你写下答案。我的解决方案是在大学的“操作系统设计”课程中作为家庭任务实施的。所以它可能会犯错误。但那是我当时能做的最好的了。这是一个很好的例子。你可以读到透明的hugepages和@IlyaMatveychikov内核版本可能是造成误解的关键:我们正在探索版本2.6.32。无论如何,谢谢你提供的信息。
for vma in task_struct:
    call page_address_in_vma(page, vma)