内存管理-5-物理内存数据结构-2-struct zone

基于msm-5.4


一、struct zone简介

描述一个内存区。内存可以按照不同的用途与类型划分为不同的区域,zone结构表示内存区域,系统存在的zone见 enum zone_type 成员。

ZONE_DMA: 表示这片区域用于DMA,一般是给x86使用的,64位上将其取消掉了,arm系统上也没有使用这个zone,因为划分了这个区域若不使能的话它就会一直空着,造成内存浪费。arm使用另外一机制,叫做cma,它能充分利用不浪费一片内存。

使用哪些zone区域是可以配置的。

水位是每内存区的。


二、成员介绍

//include/linux/mmzone.h
struct zone {
    /* Read-mostly fields */
    unsigned long _watermark[NR_WMARK];
    unsigned long watermark_boost;

    unsigned long nr_reserved_highatomic;
    long lowmem_reserve[MAX_NR_ZONES]; //2
    struct pglist_data    *zone_pgdat;
    struct per_cpu_pageset __percpu *pageset;
    bool            cma_alloc; //CONFIG_CMA
    unsigned long        *pageblock_flags; //CONFIG_SPARSEMEM
    unsigned long        zone_start_pfn;

    atomic_long_t        managed_pages;
    unsigned long        spanned_pages;
    unsigned long        present_pages;

    const char        *name;
    unsigned long        nr_isolate_pageblock; //CONFIG_MEMORY_ISOLATION
    seqlock_t        span_seqlock; //CONFIG_MEMORY_HOTPLUG
    int initialized;
    ZONE_PADDING(_pad1_) //cache aligned, size=0, Write-intensive
    struct free_area    free_area[MAX_ORDER];
    unsigned long        flags;
    spinlock_t        lock;
    ZONE_PADDING(_pad2_) //cache aligned, size=0, Write-intensive
    unsigned long percpu_drift_mark;
#if defined CONFIG_COMPACTION || defined CONFIG_CMA //both-enabled
    unsigned long        compact_cached_free_pfn;
    unsigned long        compact_cached_migrate_pfn[2];
    unsigned long        compact_init_migrate_pfn;
    unsigned long        compact_init_free_pfn;
#endif
#ifdef CONFIG_COMPACTION //enabled
    unsigned int        compact_considered;
    unsigned int        compact_defer_shift;
    int                    compact_order_failed;
#endif
#if defined CONFIG_COMPACTION || defined CONFIG_CMA //both-enabled
    bool            compact_blockskip_flush;
#endif
    bool            contiguous;
    ZONE_PADDING(_pad3_) //cache aligned, size=0, Write-intensive
    /* Zone statistics */
    atomic_long_t        vm_stat[NR_VM_ZONE_STAT_ITEMS];
    atomic_long_t        vm_numa_stat[NR_VM_NUMA_STAT_ITEMS];
} ____cacheline_internodealigned_in_smp;

_watermark[]: 当前zone的水位,使用 min/low/high_wmark_pages(zone) 宏访问,此宏会考虑boost水位。超出水位后会触发内存回收等机制。

zone_pgdat: zone_init_internals() 中进行初始化,指向 NODE_DATA(nid), 即 &contig_page_data

pageset: zone_pcp_init() 中进行初始化,指向全局 boot_pageset 变量,定义在page_alloc.c中。

lowmem_reserve[]: 我们不知道要分配的内存是否可释放或/以及最终是否会被释放,因此为了避免完全浪费几GB的RAM,我们必须保留一些较低区域内存(否则,尽管较高区域有大量可释放的 RAM,我们仍有在较低区域运行 OOM 的风险)。如果 sysctl_lowmem_reserve_ratio sysctl 发生变化,则在运行时重新计算此数组。它相当于一个备胎,分配内存的时候可以指定参数来决定去哪个zone里面去分,若目标zone中已经没有内存了,它会去其它zone里面去找,若其它zone中也没有内存了,就会启用 lowmem_reserve[] 中预留的内存。

pageblock_flags: pageblock_nr_pages 块的标志,使用的是ifndef,默认没有这个参数,实际使用的是 mem_section->usage中 的这个参数,请参阅 pageblock-flags.h,在 SPARSEMEM 中,此映射存储在 struct mem_section 中。

zone_start_pfn: 此zone管理的物理内存的起始页帧号,在 init_currently_empty_zone() 中赋值,ZONE_NORMAL的是物理内存的起始页帧号,ZONE_MOVEABLE的是0,zone_start_pfn == zone_start_paddr >> PAGE_SHIFT

spanned_pa​​ges: 是此zone所跨越的总页面数,包括空洞(holes),在 calculate_node_totalpages() 中赋值,其计算方式为:spanned_pa​​ges = zone_end_pfn - zone_start_pfn;

present_pages: 是此zone中实际存在的物理页面数量,在 calculate_node_totalpages() 中赋值,其计算方式为:present_pages = spanned_pa​​ges - 空洞页面

managed_pa​​ges: 此zone实际管理的页面数,zone_init_internals() 中赋值为 present_pages - memmap使用的页面。三者的关系是: spanned_pages > present_pages > managed_pages.

name: 此zone的名字,zone_init_internals() 中让其指向全局 zone_names[zone_idx].

nr_isolate_pageblock: 孤立页块的数量。它用于解决由于检索页块的迁移类型不当而导致的空闲页计数不正确的问题。受 zone->lock 保护。

initialized: zone初始化后在 init_currently_empty_zone() 中将其设置为1。

free_area[]: 不同大小的可用区域,MAX_ORDER定义为11,即0-10,一次能从buddy系统中分配出来的最大连续内存块的大小是4MB. 下标 i 中存放的是页数为2^i个页面的分组。每个数组元素里面的每一个迁移类型都有一个链表。

flags: zone的标志位。

lock: 主要保护free_area[]

percpu_drift_mark: 当可用页面低于此值时,读取可用页面数量时会采取额外步骤,以避免每个 CPU 计数器漂移导致水位被突破。

compact_cached_free_pfn: 指示pfn无压缩扫描仪器应从何处开始。

compact_cached_migrate_pfn[]: pfn异步和同步压缩迁移扫描器应开始的位置。

compact_defer_shift/compact_considered: 如果压缩失败,则在重试之前会跳过 1<<compact_defer_shift 进行压缩。自上次失败以来尝试的次数会通过 compact_considered 进行跟踪。

compact_blockskip_flush: 当应清除 PG_migrate_skip 位时,设置为 true

vm_stat/vm_numa_stat: zone的统计信息。

free_area[]: 当前zone空闲可用的物理页帧。free_area.free_list: 随着物理页的申请与释放,page在这些链表上动态移动。


三、struct free_area

1. 简介

描述固定大小的空余内存块,zone中不同大小的空闲内存块使用数组进行描述。

2. 成员介绍

//include/linux/mmzone.h
struct free_area {
    struct list_head    free_list[MIGRATE_TYPES];
    unsigned long        nr_free;
};

free_list[]: 一个链表数组,同一个zone中的同一大小同一迁移属性的内存块挂在同一个链表上。

nr_free: 链表中元素的个数。

 

posted on 2026-04-02 10:34  Hello-World3  阅读(3)  评论(0)    收藏  举报

导航