☰
page_alloc zone_pcp_init
2026/10/18 22:40:00 网站建设 项目流程

zone_pcp_init()是 PCP(Per-CPU Pages)缓存的启动早期占位初始化函数,标记为__meminit,用于在正式 pageset 就绪之前,将 zone 指向静态的boot_pageset。

核心实现

__meminit void zone_pcp_init(struct zone *zone) { /* * per_cpu field name is historical. It is actually a per * zone, per cpu structure. We should support data from * "Per CPU pageset" in /proc/zoneinfo. */ zone->per_cpu_pageset = &boot_pageset; zone->per_cpu_zonestats = &boot_zonestats; if (populated_zone(zone)) pr_debug(" %s zone: %lu pages, LIFO batch:%u\n", zone->name, zone->present_pages, zone_batchsize(zone)); }

逐步解析

1. 指向静态 boot pageset

zone->per_cpu_pageset = &boot_pageset; zone->per_cpu_zonestats = &boot_zonestats;
  • boot_pageset和boot_zonestats是前面讲过的静态 per-CPU 占位结构。

  • 这里让 zone 暂时指向它们,使 zone 在正式 pageset 分配之前也能正常工作。

  • boot_pageset的high=0、batch=1,实际上禁用了 PCP 缓存,所有分配/释放直接走伙伴系统。

2. 打印调试信息

if (populated_zone(zone)) pr_debug(" %s zone: %lu pages, LIFO batch:%u\n", zone->name, zone->present_pages, zone_batchsize(zone));
  • 只有 populated zone 才打印信息。

  • 输出 zone 名称、当前页数、以及由zone_batchsize()计算的初始批量大小。

  • pr_debug只在调试配置下输出。

在 PCP 初始化流程中的位置

启动早期: free_area_init_core() └── zone_pcp_init(zone) // ← 这里,指向 boot_pageset 稍后: setup_per_cpu_pageset() └── setup_zone_pageset(zone) // 分配正式 pageset,替换 boot_pageset
  • zone_pcp_init():第一阶段,用静态占位结构让 zone 可用;

  • setup_zone_pageset():第二阶段,动态分配正式 pageset,真正启用 PCP 缓存。

__meminit的含义

  • 函数放在.meminit.text段。

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

  • 内存热插拔时,新上线的 zone 也可能调用它进行早期占位。

与boot_pageset的关系

boot_pageset是所有 zone 在启动早期共享的占位结构(每 CPU 一份)。由于high=0,它实际上不缓存任何页,所有操作直接转交伙伴系统。这避免了在内存子系统完全就绪前引入 PCP 缓存带来的复杂性。

总结

zone_pcp_init()是 PCP 机制的启动早期占位初始化:它让 zone 的per_cpu_pageset指向静态的boot_pageset,使 zone 在正式 pageset 分配前也能正常工作;同时为 populated zone 打印调试信息。它由free_area_init_core()在 zone 初始化时调用,是setup_per_cpu_pageset()之前的第一阶段初始化,标志着 PCP 机制从“未启用”进入“占位就绪”状态。

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

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

立即咨询