☰
page_alloc setup_zone_pageset
2026/10/17 2:44:15 网站建设 项目流程

setup_zone_pageset()是 PCP(Per-CPU Pages)缓存初始化流程中的关键函数,负责为一个 populated zone动态分配并初始化正式的 per-CPU pageset 结构,替换掉启动阶段使用的boot_pageset占位结构。

核心实现

void __meminit setup_zone_pageset(struct zone *zone) { struct per_cpu_zonestat *pzstats; int cpu; /* 分配正式的 per_cpu_pages 数组 */ zone->per_cpu_pageset = alloc_percpu(struct per_cpu_pages); zone->per_cpu_zonestats = alloc_percpu(struct per_cpu_zonestat); for_each_possible_cpu(cpu) { struct per_cpu_pages *pcp; struct per_cpu_zonestat *pzstats; pcp = per_cpu_ptr(zone->per_cpu_pageset, cpu); pzstats = per_cpu_ptr(zone->per_cpu_zonestats, cpu); per_cpu_pages_init(pcp, pzstats); } zone_set_pageset_high_and_batch(zone, 0); }

逐步解析

1. 动态分配 per-CPU pageset

zone->per_cpu_pageset = alloc_percpu(struct per_cpu_pages); zone->per_cpu_zonestats = alloc_percpu(struct per_cpu_zonestat);
  • alloc_percpu():为每个可能的 CPU 分配一份struct per_cpu_pages和struct per_cpu_zonestat。

  • 在此之前,zone 使用的是静态定义的boot_pageset/boot_zonestats(前面讲过的)。

  • 现在内存子系统已就绪,可以分配真正的 per-CPU 结构了。

2. 初始化每个 CPU 的 PCP

for_each_possible_cpu(cpu) { pcp = per_cpu_ptr(zone->per_cpu_pageset, cpu); pzstats = per_cpu_ptr(zone->per_cpu_zonestats, cpu); per_cpu_pages_init(pcp, pzstats); }

前面讲过的per_cpu_pages_init():清零结构体、初始化锁和空闲链表、设置 boot 安全的batch/high值。

3. 设置 PCP 的 batch/high 配置

zone_set_pageset_high_and_batch(zone, 0);

前面讲过的zone_set_pageset_high_and_batch():计算该 zone 的batch、high_min、high_max,并分发到所有 CPU。参数cpu_online = 0表示这是初始化阶段,没有额外的 CPU 上线事件。

调用场景

它被zone_pcp_init()或free_area_init_core()等初始化路径调用,为每个 populated zone建立正式的 pageset:

free_area_init_core() └── for each zone: if (populated_zone(zone)) setup_zone_pageset(zone) // ← 这里 ├── alloc_percpu(per_cpu_pages) ├── alloc_percpu(per_cpu_zonestat) ├── per_cpu_pages_init() for each cpu └── zone_set_pageset_high_and_batch(zone, 0)

__meminit的含义

  • 函数标记为__meminit,表示它主要用于内存初始化/热插拔阶段。

  • 函数体在内存初始化完成后可被卸载(如果 CONFIG_MEMORY_HOTPLUG 允许)。

  • 内存热插拔时,新上线的 zone 也会调用它来建立 pageset。

与启动阶段的对比

阶段pagesetbatch/high
启动早期boot_pageset(静态占位)HIGH=0,BATCH=1(禁用 PCP)
setup_zone_pageset()后动态分配的正式 pageset由zone_set_pageset_high_and_batch()计算

总结

setup_zone_pageset()是 PCP 缓存的正式初始化函数:它为 populated zone 动态分配 per-CPU 的per_cpu_pages和per_cpu_zonestat数组,用per_cpu_pages_init()初始化每个 CPU 的结构,最后通过zone_set_pageset_high_and_batch()计算出该 zone 的 batch/high 配置并分发。它标志着 zone 从启动阶段的boot_pageset占位切换到真正的 PCP 缓存管理,是内存子系统初始化的重要步骤。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询