page_alloc is_check_pages_enabled 开关查询函数用于判断页分配/释放的调试检查是否启用。它配合free_page_is_bad()、check_new_page()等使用。一、函数签名static inline bool is_check_pages_enabled(void)参数无参数。返回值booltrue表示启用页检查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_VMy→ 总是 trueCONFIG_DEBUG_VMn→ 总是 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下默认开启生产内核默认关闭调试时可临时开。