内存管理-57-系统零页

基于 msm-5.4

一、简介

匿名页面缺页异常处理 do_anonymous_page() 中使用了系统零页,因为对于 malloc() 来说。分配的内存仅仅是进程地址空间中的虚拟地址。若此时用户程序需要读这个 malloc() 分配的虚拟内存,那么系统会返回全 0 的数据。因此Linux内核不必为这种情况单独分配物理内存,而是使用系统零页。使用系统零页来映射 malloc() 分配的虚拟地址。当程序需要写入这个页面时就会触发一个缺页异常,于是缺页异常就变成了写时复制的缺页异常了。

malloc()分配虚拟内存有以下几种情况:

(1) malloc后直接读

此时内核会进入匿名页面缺页异常,即 do_anonymous_page() 中使用系统零页进行映射。此时映射的PTE属性是只读的。

(2) malloc后先读后写

先读的操作会导致使用系统零页进行映射,此时映射的PTE属性是只读的。当写入时触发另外一个写时复制缺页异常。

(3) malloc后直接写

进入匿名页面缺页异常,调用 alloc_zeroed_user_highpage_movable() 来分配一个新页面,使用该页面来设置PTE,此时这个PTE的属性是可写的。


Arm64建构中 empty_zero_page 被定义成一个全局数组。

//msm-5.4/arch/arm64/mm/mmu.c
unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)] __page_aligned_bss;
EXPORT_SYMBOL(empty_zero_page);


系统提供了一些辅助宏来使用这个系统零页:

//msm-5.4/arch/arm64/include/asm/pgtable.h

#define ZERO_PAGE(vaddr)    phys_to_page(__pa_symbol(empty_zero_page))

static inline int is_zero_pfn(unsigned long pfn)
{
    return pfn == zero_pfn;
}
static inline unsigned long my_zero_pfn(unsigned long addr)
{
    return zero_pfn;
}

//msm-5.4/mm/memory.c

unsigned long zero_pfn __read_mostly;
EXPORT_SYMBOL(zero_pfn);

static int __init init_zero_pfn(void)
{
    zero_pfn = page_to_pfn(ZERO_PAGE(0));
    return 0;
}
early_initcall(init_zero_pfn);


二、使用位置

1. 匿名页读类型缺页异常

见上文简介部分。

 

posted on 2026-01-13 17:16  Hello-World3  阅读(1)  评论(0)    收藏  举报

导航