news 2026/10/17 2:44:12

page_alloc pageset_update

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
page_alloc pageset_update

pageset_update()是 PCP(Per-CPU Pages)缓存配置的底层写入函数,负责在运行时安全地更新某个 CPU 的 PCP 参数(batch、high_min、high_max)。

核心实现

static void pageset_update(struct per_cpu_pages *pcp, unsigned long high_min, unsigned long high_max, unsigned long batch) { WRITE_ONCE(pcp->batch, batch); WRITE_ONCE(pcp->high_min, high_min); WRITE_ONCE(pcp->high_max, high_max); }

逐行解析

1. 三个字段的含义

字段含义
pcp->batch批量补充/归还的页数
pcp->high_min高水位下限(自动调节的下界)
pcp->high_max高水位上限(自动调节的上界)

2.WRITE_ONCE的作用

  • 防止编译器优化:确保每次写入都真实发生,不被优化掉或重排。

  • 保证原子性:对于对齐的unsigned long,WRITE_ONCE保证写入是单次、不可分割的,读者不会看到"写了一半"的值。

  • 避免数据竞争:并发读者(如nr_pcp_alloc、nr_pcp_free、nr_pcp_high)用READ_ONCE读取这些字段,WRITE_ONCE与READ_ONCE配对,符合内核的并发访问规范。

3. 为什么不加锁?

  • 这些字段是单个unsigned long,WRITE_ONCE保证单次写入的原子性。

  • 读者读取时即使看到旧值,也只是暂时的——不影响正确性,只影响性能决策(如 batch 用旧值,下次更新就生效)。

  • 加锁会引入不必要的开销,而这些字段的更新是低频的(zone 初始化、CPU 热插拔、sysctl 修改时)。

在 PCP 调节机制中的位置

它被__zone_set_pageset_high_and_batch()调用,后者负责更新 zone 内所有 CPU的 PCP 参数:

static void __zone_set_pageset_high_and_batch(struct zone *zone, unsigned long high_min, unsigned long high_max, unsigned long batch) { struct per_cpu_pages *pcp; int cpu; for_each_possible_cpu(cpu) { pcp = per_cpu_ptr(zone->per_cpu_pageset, cpu); pageset_update(pcp, high_min, high_max, batch); } }

调用链:

zone_set_pageset_high_and_batch(zone, cpu_online) ├── new_batch = zone_batchsize(zone) ├── new_high = zone_highsize(zone, new_batch, cpu_online) └── __zone_set_pageset_high_and_batch(zone, new_high, new_high, new_batch) └── for each cpu: pageset_update(pcp, high_min, high_max, batch) // ← 这里

更新时机的考量

pageset_update()在以下场景被调用:

  1. zone 初始化:zone_pcp_init()/setup_per_cpu_pageset()时首次设置。

  2. CPU 热插拔:CPU 上线/下线时,需要重新分配 PCP 份额。

  3. 内存热插拔:zone 大小变化时,重新计算high。

  4. sysctl 修改:用户调整vm.percpu_pagelist_high_fraction时。

  5. 自动调节:pcp->high在high_min和high_max之间动态变化,但high_min/high_max/batch本身的更新走这里。

与自动调节机制的配合

2023 年引入的high_min/high_max机制让pcp->high可以在运行时自动增长和衰减:

  • nr_pcp_alloc()在分配压力大时抬高pcp->high(不超过high_max);

  • decay_pcp_high()在压力小时降低pcp->high(不低于high_min);

  • pageset_update()则更新调节的边界(high_min/high_max),以及batch。

这样,pcp->high的具体值可以频繁变化(由自动调节逻辑处理),而调节范围只在配置变化时才由pageset_update()更新。

总结

pageset_update()是 PCP 配置的原子写入接口:它用WRITE_ONCE安全地更新某个 CPU 的batch、high_min、high_max三个字段,避免数据竞争,同时不加锁以保持轻量。它被__zone_set_pageset_high_and_batch()在 zone 初始化、CPU/内存热插拔、sysctl 修改时调用,是 PCP 自动调节机制中更新"调节边界"的底层函数。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 2:44:08

从零开始学 Agent 开发:小白程序员转行的进阶指南

本文针对想转行做 Agent 开发的程序员,强调 Agent 开发首先是一项工程工作,重点不在模型调用本身,而在于模型调用前后。文章建议通过一个完整项目实践,深入理解运行时、工具、上下文、技能等核心概念,熟练掌握至少一个…

作者头像 李华
网站建设 2026/10/17 2:42:42

变频水泵控制器原理选型与应用指南

摘要:变频水泵控制器是泵房自动化改造中的核心硬件,依托闭环 PID 变频调速,改变传统阀门节流调压模式,实现按需调速与节能运行。本文从工作原理、核心功能、硬件参数、行业应用、选型安装维护几个角度做技术梳理,适合给…

作者头像 李华
网站建设 2026/10/17 2:42:28

每个孩子都左小右大,为什么还不是BST?2022年408的祖先约束

这道题要判断一棵二叉树是不是二叉搜索树。原题用数组存树,结点值都是正整数,-1表示空位。 我先想到的是逐个检查:左孩子比当前结点小,右孩子比当前结点大。一路检查下去,哪里不满足,就返回false。 这个办…

作者头像 李华
网站建设 2026/10/17 2:41:29

基于MP2642GR-Z与MKV58F1M0VLQ24的两串电池被动均衡方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 2:39:40

从终端到桌面:Kimi Code Desktop如何重构AI编程工作流

AI编程工具这两年的变化,快得有点超出预期。2023年大家还在讨论Copilot式的代码补全,2024年终端里的Agent开始能自己读仓库、改文件、跑命令,到了2025年,这类工具已经从终端往桌面迁移了——Kimi Code Desktop的发布,就…

作者头像 李华
网站建设 2026/10/17 2:39:04

Java 8 Map与Stream实战:从视图原理到collect收集器避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华