vmalloc()
__vmalloc_node()
__vmalloc_node_range()
__get_vm_area_node()
__vmalloc_area_node()
kmalloc_node()
vmap_pages_range()
(x86_64) 如果进程 A 陷入内核空间,通过 vmalloc() 分配内存 memA,如上解释不会出现 Page Fault。 但是进程 B 后面再陷入内核空间,并且也访问内存 memA,这时候内核会发生 Page Fault 来同步内核页表, 而不是发生 Page Fault 来申请物理内存。
# cat /proc/vmallocinfo
0x00000000d4d806e4-0x00000000e109dff2 20480 start_kernel+0x478/0x690 pages=4 vmalloc N0=4
0x00000000e109dff2-0x00000000caa5ddd3 8192 gicv2m_init_one+0xa8/0x224 phys=0x0000000008020000 ioremap
0x00000000fa4bd407-0x00000000777a02db 20480 kernel_clone+0x5c/0x3b8 pages=4 vmalloc N0=4
0x00000000777a02db-0x00000000802411ee 8192 bpf_prog_alloc_no_stats+0x3c/0x1b8 pages=1 vmalloc N0=1
0x00000000916f1123-0x000000007c459509 16187392 paging_init+0x130/0x60c phys=0x0000000040210000 vmap
static struct vm_struct *__get_vm_area_node(unsigned long size,
unsigned long align, unsigned long shift, unsigned long flags,
unsigned long start, unsigned long end, int node,
gfp_t gfp_mask, const void *caller)
{
...
if (!(flags & VM_NO_GUARD))
size += PAGE_SIZE;
...
}
static inline size_t get_vm_area_size(const struct vm_struct *area)
{
if (!(area->flags & VM_NO_GUARD))
/* return actual size without guard page */
return area->size - PAGE_SIZE;
else
return area->size;
}