news 2026/10/23 3:06:27

page_alloc is_check_pages_enabled

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
page_alloc is_check_pages_enabled

开关查询函数,用于判断"页分配/释放的调试检查是否启用"。它配合free_page_is_bad()、check_new_page()等使用。


一、函数签名

static inline bool is_check_pages_enabled(void)

参数

  • 无参数。

返回值

  • bool:true表示启用页检查;false表示不启用。

static inline

  • 文件内私有 + 强制/建议内联。

  • 在分配/释放热路径上被调用,必须零开销。


二、背景:页检查(check_pages)

什么是"页检查"?

free_page_is_bad()、page_expected_state()、check_new_page()、bad_page()等,都属于"页检查"机制:

  • 分配新页后:检查页是否处于干净、可用的初始状态;

  • 释放页前:检查页是否处于可安全释放的状态(refcount 为 0、无异常标志等);

  • 发现问题 →bad_page()报错 → 阻止操作,避免损坏扩散。

为什么需要开关?

页检查是调试功能:

  • 在开发/调试内核(CONFIG_DEBUG_VM)上启用,帮助发现 bug;

  • 在生产内核上禁用,避免热路径上的额外开销(每次分配/释放都要读refcount、mapcount、flags等,成本不小)。

所以需要一个运行期/编译期的开关,让代码能根据配置决定是否执行检查。


三、典型实现

版本 A:基于静态键

static inline bool is_check_pages_enabled(void) { return static_branch_unlikely(&check_pages_enabled); }
  • 用静态键check_pages_enabled控制。

  • static_branch_unlikely():

    • 运行期绝大多数时间为 false(生产内核);

    • 用静态键实现"关闭时零开销"。

  • 开启时分支变成真实检查;关闭时被优化掉。

版本 B:基于编译配置

#ifdef CONFIG_DEBUG_VM static inline bool is_check_pages_enabled(void) { return true; } #else static inline bool is_check_pages_enabled(void) { return false; } #endif
  • 直接在编译期决定。

  • CONFIG_DEBUG_VM=y→ 总是 true;

  • CONFIG_DEBUG_VM=n→ 总是 false(甚至被编译器优化掉,if (is_check_pages_enabled())整段删除)。

版本 C:基于静态键 + 默认值

#ifdef CONFIG_DEBUG_VM DEFINE_STATIC_KEY_TRUE(check_pages_enabled); #else DEFINE_STATIC_KEY_FALSE(check_pages_enabled); #endif static inline bool is_check_pages_enabled(void) { return static_branch_unlikely(&check_pages_enabled); }
  • 结合两者:编译期决定默认值,运行期可通过静态键动态开关(如调试时临时开启)。

  • 这是较灵活的设计。

实际内核常见形式

现代内核中,类似函数常写作:

static inline bool is_check_pages_enabled(void) { return static_branch_unlikely(&check_pages_enabled); }

配合:

#ifdef CONFIG_DEBUG_VM DEFINE_STATIC_KEY_TRUE(check_pages_enabled); #else DEFINE_STATIC_KEY_FALSE(check_pages_enabled); #endif

或直接用IS_ENABLED(CONFIG_DEBUG_VM)之类的编译期常量。


四、典型调用场景

1.free_pages_prepare()—— 释放前检查

static bool free_pages_prepare(struct page *page, unsigned int order, fpi_t fpi_flags) { ... if (is_check_pages_enabled()) { if (free_page_is_bad(page)) return false; /* 坏页,阻止释放 */ } ... }
  • 只有启用检查时,才做free_page_is_bad()。

  • 关闭时直接跳过,零开销。

2.check_new_page()—— 分配后检查

static inline void check_new_page(struct page *page) { if (is_check_pages_enabled()) { if (!page_expected_state(page, PAGE_FLAGS_CHECK_AT_PREP)) bad_page(page, page_bad_reason(page, PAGE_FLAGS_CHECK_AT_PREP)); } }
  • 分配新页时校验。

3.check_pages_enabled静态键的开启/关闭

  • 可能通过内核参数或 sysfs 动态控制:

    static_branch_enable(&check_pages_enabled); static_branch_disable(&check_pages_enabled);
  • 典型场景:

    • CONFIG_DEBUG_VM下默认开启;

    • 生产内核默认关闭,调试时可临时开。

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

Chroma实战:用轻量级向量数据库快速构建本地化RAG系统

做 RAG 项目这几年,我最大的感受是:真正决定系统上限的,往往不是大模型本身,而是你背后那套知识检索链路。而这条链路的起点,就是向量数据库。在尝试过好几款产品之后,我长期留在项目里的,是开源…

作者头像 李华
网站建设 2026/10/21 19:50:05

MySQL Windows服务启动失败1067错误根因与实战修复指南

简介:本资源是一份针对Windows环境下MySQL服务启动失败(错误代码1067)的实战排错指南,面向数据库初学者、运维人员及开发工程师,聚焦服务无法启动这一高频故障场景。内容基于真实问题排查过程展开,详细还原…

作者头像 李华
网站建设 2026/10/22 13:12:44

函数递归知识

函数递归知识 文章目录函数递归知识一.什么是递归(一)递归的思想(二)递归的限制条件二.递归举例(一)举例1:求n的阶乘1.分析和代码实现2.画图推演(二)举例2:顺…

作者头像 李华
网站建设 2026/10/20 10:02:39

11_给RAG建baseline_别被看起来不错骗了

给 RAG 建 baseline:别被"看起来不错"骗了 RAG 做到能跑、能答,很容易——跑几条查询,模型答得挺顺,就觉得自己做完了。但没有 baseline,后面所有优化都是自说自话:你不知道自己在进步还是退步&a…

作者头像 李华
网站建设 2026/10/19 4:37:52

游戏引擎基础架构深度解析:从分层设计到资源管理

有朋友私信问我,刚接手一个自研引擎项目,几千个源文件摆在眼前,该从哪里看起。我给的答案一直是同一个:先看引擎的基础架构,也就是引擎的“骨架”。这有点像你拿到一栋复杂的建筑,先得搞清楚承重墙在哪、管…

作者头像 李华
网站建设 2026/10/22 0:22:41

自动测角原理和方法(同时波瓣)

同时波瓣法,单脉冲自动测角系统。即多个波瓣同时存在,理论上可以通过发射一个脉冲测得目标角度信息。单脉冲自动测角系统,主要包括两种方法:1.振幅和差式单脉冲2.相位和差式单脉冲以下介绍振幅和差式单脉冲相关内容振幅和差式单脉…

作者头像 李华