☰
page_alloc post_alloc_hook
2026/10/10 6:15:47 网站建设 项目流程

post_alloc_hook()是页面分配路径上的分配后钩子函数,负责在页面从伙伴系统取出并校验通过后,执行一系列分配后的初始化与标记操作,最终把页面交给调用方。

核心作用

它的职责是在页面可用之前完成所有必要的后处理,包括:KASAN 标签处理、内存清零、页面标志设置、alloc_tag 记录等。

参数解析

参数含义
page分配到的页块首页
order分配阶数
gfp_flags分配标志(决定清零、标签等行为)

核心流程

典型实现如下:

inline void post_alloc_hook(struct page *page, unsigned int order, gfp_t gfp_flags) { bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags) && !should_skip_init(gfp_flags); bool init_tags = init && (gfp_flags & __GFP_ZEROTAGS); set_page_private(page, 0); set_page_refcounted(page); if (init_tags) { /* 清零并清除标签 */ for (i = 0; i != 1 << order; ++i) tag_clear_highpage(page + i); } else if (init) { /* 仅清零 */ kernel_init_pages(page, 1 << order); } /* KASAN 解毒(除非应跳过) */ if (!should_skip_kasan_unpoison(gfp_flags) && kasan_unpoison_pages(page, order, init)) { /* KASAN 已完成初始化 */ } else { /* 重置页面标签,确保 page_address() 安全 */ for (i = 0; i != 1 << order; ++i) page_kasan_tag_reset(page + i); } /* 设置迁移类型 */ set_pageblock_migratetype(page, MIGRATE_MOVABLE); // 视情况 /* alloc_tag 记录 */ pgalloc_tag_add(page, current, 1 << order); /* 架构相关后处理 */ arch_post_alloc_hook(page, order, gfp_flags); }

逐步说明

1. 计算初始化需求

bool init = !want_init_on_free() && want_init_on_alloc(gfp_flags) && !should_skip_init(gfp_flags); bool init_tags = init && (gfp_flags & __GFP_ZEROTAGS);
  • want_init_on_alloc():init_on_alloc内核参数要求分配时清零;

  • should_skip_init():前面讲的,HW_TAGS 下__GFP_SKIP_ZERO可跳过;

  • init_tags:额外要求__GFP_ZEROTAGS,表示清零的同时清除 KASAN 标签。

2. 清除私有字段与设置引用计数

set_page_private(page, 0); set_page_refcounted(page);
  • set_page_private(page, 0):清除private字段(可能残留 Buddy 信息);

  • set_page_refcounted(page):把引用计数设为 1(页已分配出去)。

3. 清零与标签处理

  • init_tags为真:用tag_clear_highpage()清零并清标签;

  • init为真:用kernel_init_pages()仅清零;

  • 二者都不做则跳过。

4. KASAN 解毒

if (!should_skip_kasan_unpoison(gfp_flags) && kasan_unpoison_pages(page, order, init)) { /* KASAN 完成初始化 */ } else { for (i = 0; i != 1 << order; ++i) page_kasan_tag_reset(page + i); }
  • should_skip_kasan_unpoison():前面讲的,决定是否跳过解毒;

  • kasan_unpoison_pages():标记内存可访问;

  • 若跳过或 KASAN 不处理,则重置页面标签,保证page_address()安全。

5. alloc_tag 记录

pgalloc_tag_add(page, current, 1 << order);
  • 记录分配标签,更新统计。

6. 架构相关钩子

arch_post_alloc_hook(page, order, gfp_flags);
  • 架构相关后处理(如某些架构需要特殊标记)。

在分配路径中的位置

get_page_from_freelist() └── prep_new_page(page, order, gfp_mask, alloc_flags) ├── check_new_pages(page, order) // 校验 ├── post_alloc_hook(page, order, gfp_mask) // ← 这里 │ ├── 清零/标签处理 │ ├── KASAN 解毒 │ ├── alloc_tag 记录 │ └── arch 钩子 └── ...

总结

post_alloc_hook()是页面分配路径的后处理中枢:它根据init_on_alloc、__GFP_ZERO、__GFP_ZEROTAGS等标志决定是否清零、是否清标签,处理 KASAN 解毒与标签重置,记录 alloc_tag 分配信息,并调用架构钩子。它确保了从伙伴系统取出的页在交给调用方之前,处于干净、安全、可追踪的状态。

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

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

立即咨询