关于vmalloc缺页异常的一个问题

本文探讨了进程在新建时如何复制页表及其内核部分,并解析了vmalloc为何会导致缺页异常,而持久映射和固定映射则不会。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进程页表和vmalloc缺页异常

在新建进程时,新的线程会复制老的线程的页表,复制老线程的文件映射,匿名映射等,而且会复制页表项的全局页表项的内核部分,因为内核部分的页表的映射(除vmalloc)在启动内核时就已经建立好了,因此复制了全局页表项页就相当于复制了内核的页表。

pgd_t *pgd_alloc(struct mm_struct *mm)
{
pgd_t *pgd;
pmd_t *pmds[PREALLOCATED_PMDS];

pgd = (pgd_t *)__get_free_page(PGALLOC_GFP);

if (pgd == NULL)
goto out;

mm->pgd = pgd;

if (preallocate_pmds(pmds) != 0)
goto out_free_pgd;

if (paravirt_pgd_alloc(mm) != 0)
goto out_free_pmds;

/*
 * Make sure that pre-populating the pmds is atomic with
 * respect to anything walking the pgd_list, so that they
 * never see a partially populated pgd.
 */
spin_lock(&pgd_lock);

pgd_ctor(mm, pgd);
pgd_prepopulate_pmd(mm, pgd, pmds);

spin_unlock(&pgd_lock);

return pgd;

out_free_pmds:
free_pmds(pmds);
out_free_pgd:
free_page((unsigned long)pgd);
out:
return NULL;
}
static void pgd_ctor(struct mm_struct *mm, pgd_t *pgd)
{
/* If the pgd points to a shared pagetable level (either the
   ptes in non-PAE, or shared PMD in PAE), then just copy the
   references from swapper_pg_dir. */
if (PAGETABLE_LEVELS == 2 ||
    (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD) ||
    PAGETABLE_LEVELS == 4) {
clone_pgd_range(pgd + KERNEL_PGD_BOUNDARY,
swapper_pg_dir + KERNEL_PGD_BOUNDARY,
KERNEL_PGD_PTRS);
}

/* list required to sync kernel mapping updates */
if (!SHARED_KERNEL_PMD) {
pgd_set_mm(pgd, mm);
pgd_list_add(pgd);
}
}


因此当进程在内核态运行时不需要切换页表,因此也不需要刷新tlb,高速缓存等。


vmalloc会产生缺页异常而持久映射和固定映射不会产生映射的原因。
主要原因就在于vmalloc映射的地址区域过大,不在一个PMD的范围内才会产生缺页异常。因为进程在内核态使用的本身的页表,而页表的内核部分的从TASK_SIZE到max_low_pn<<PAGE_SHIFT,持久映射和原子的持久映射的部分的PMD在内核启动时就确定了,因此内核的全局页表项中和这些PMD相关的部分已经固定好了不会改变的,因此只要进程copy了pgd就相当于复制了内核的页表。
由于持久映射一次映射一页,持久映射的大小LASK_PKMAP为1024或者512个页,而且PKMAP_BASE是PMD_MASK对齐的,在32位4K页下也就是4M内存对齐的,刚好在pgd中占一项,因此持久映射不会影响到内核的全局页表项,因此每个进程的pgd的内核部分都是有效的,每个进程都能看到新的映射,因此不会产生缺页异常,而固定映射的大小也不会超过1024,因此修改都是全局可见的,再说了固定的地址都保存在tlb不会被刷出的,因此固定映射页不会产生缺页异常。所以,若产生了缺页异常,且地址在内核部分,只有可能是在vmalloc区域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值