ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

page_alloc __bitwise fpi_t

2026/10/5 19:32:06 拓冰建站 浏览量
page_alloc __bitwise fpi_t fpi_t——即Free Page Internal flags释放页面的内部标志专门用于free_pages()的内部、非 PCPPer-CPU Pages变体。1. 类型定义__bitwisetypedef int __bitwise fpi_t;底层类型是int但加上了__bitwise注解。__bitwise是sparse内核的静态分析工具用的标记用来做强类型检查不同__bitwise类型之间不能随意混用普通的int也不能直接赋给fpi_t必须显式转换。这样做的目的是把fpi_t和普通整数、其他 bitwise 类型如gfp_t区分开防止误用。类比gfp_t也是typedef unsigned int __bitwise gfp_t;同样用__bitwise保证类型安全。2. 第一个标志FPI_NONE/* No special request */ #define FPI_NONE ((__force fpi_t)0)FPI_NONE表示没有特殊请求即普通的、无任何附加语义的释放操作。值就是0所有标志位都不置位。__force fpi_t是sparse 的显式转换告诉编译器我知道我在把一个普通0转成fpi_t这是有意的不要报类型警告。因为__bitwise类型不允许隐式转换所以这里必须用__force强制转。3. 为什么需要这个类型free_pages()有几个变体内部走不同路径变体说明PCP 变体走 Per-CPU 缓存快速释放如free_unref_page()非 PCP 变体直接走伙伴系统需要区分释放时的特殊语义非 PCP 变体在释放时需要知道一些附加信息例如这个 page 是不是要直接归还伙伴系统还是走别的路径是否要跳过某些检查如 debug 检查是否是bulk free批量释放的一部分是否来自page frag / net pool等特殊来源这些信息就通过fpi_t标志传递。FPI_NONE是最基础的无特殊要求。4. 后续会出现的其他FPI_*标志上下文补充在实际内核代码中fpi_t通常还会定义更多值例如#define FPI_NONE ((__force fpi_t)0) #define FPI_SKIP_REPORT_NOT_FREE /* 跳过 page not free 报告 */ #define FPI_TAIL_PAGE /* 释放的是 tail page */ #define FPI_BULK_FREE /* 批量释放 */ #define FPI_SKIP_KASAN_POISON ...具体有哪些取决于内核版本。这些标志让同一个free_pages_prepare()/__free_pages_ok()核心函数能根据不同调用场景调整行为而不必写多个几乎相同的函数。5. 调用链示意free_pages() // 对外 API可能走 PCP └── __free_pages() // 非 PCP 变体传入 fpi_t └── free_the_page() └── __free_pages_ok(page, order, fpi_flags) └── free_pages_prepare(page, order, fpi_flags) └── __free_one_page(...) // 伙伴系统合并fpi_flags一路向下传递最终影响free_pages_prepare()里的检查和__free_one_page()的行为。一句话总结fpi_t是释放物理页时使用的内部标志位类型用__bitwise做类型隔离FPI_NONE表示无特殊请求即最普通的释放。它让非 PCP 路径的free_pages()能通过标志位灵活适配不同释放场景而不必分裂出大量重复函数。