Проверьте, находится ли страница в VMA задачи - PullRequest
2 голосов
/ 13 декабря 2011

Есть ли способ проверить, используется ли рассматриваемая страница указанным процессом? у меня есть указатель на 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-дерева), работая с фиксированным адресом, который предоставляется в качестве аргумента.

Итак, как правильно делать такие вещи?

1 Ответ

3 голосов
/ 11 апреля 2012

Оказывается, что есть единственный способ просто просмотреть весь скачок 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;
}
...