☰
page_alloc get_pfnblock_migratetype
2026/10/6 16:13:17 网站建设 项目流程

读取某个 pageblock 的迁移类型(migratetype)。它是反碎片机制的核心读取接口。


一、函数签名

__always_inline enum migratetype get_pfnblock_migratetype(const struct page *page, unsigned long pfn)

参数

参数类型含义
pageconst struct page *目标 pageblock 内的某一页(用于定位位图)
pfnunsigned long目标页帧号

返回值

  • enum migratetype:该 pageblock 的迁移类型(MIGRATE_UNMOVABLE、MIGRATE_MOVABLE、MIGRATE_RECLAIMABLE、MIGRATE_CMA等)。

__always_inline

  • 强制内联。这个函数在分配/释放/规整的热路径上频繁调用,内联后零调用开销。

  • 与前面的get_pfnblock_bit()(普通函数)不同,这里因为是简单读取+移位,适合强制内联。

注释的关键点

* Use get_pfnblock_migratetype() if caller already has both @page and @pfn * to save a call to page_to_pfn().
  • 提示:如果调用方已经有page和pfn,就用这个双参数版本,省去page_to_pfn()的开销。

  • 还存在一个单参数版本(通常叫get_pageblock_migratetype(page)),内部会调用page_to_pfn(page)把 page 转成 pfn。

  • 所以这是性能优化接口:已知 pfn 时避免重复转换。


二、典型实现(补充)

__always_inline enum migratetype get_pfnblock_migratetype(const struct page *page, unsigned long pfn) { unsigned long flags; flags = __get_pfnblock_flags_mask(page, pfn, PB_migrate_mask); return (enum migratetype)((flags >> PB_migrate) & ((1 << PB_migratetype_bits) - 1)); }

逐步说明

1. 读取迁移类型字段

flags = __get_pfnblock_flags_mask(page, pfn, PB_migrate_mask);
  • PB_migrate_mask:迁移类型字段的掩码,覆盖PB_migrate到PB_migrate_end的位。

  • 典型定义:

    #define PB_migrate_mask (((1 << PB_migratetype_bits) - 1) << PB_migrate)

    即"从PB_migrate开始的PB_migratetype_bits位全 1"。

  • __get_pfnblock_flags_mask():前面讲的读取实现,返回按 mask 过滤后的位。

  • 结果flags是原始位模式(可能还带偏移,取决于__get_pfnblock_flags_mask是否右移对齐)。

2. 提取迁移类型值

return (enum migratetype)((flags >> PB_migrate) & ((1 << PB_migratetype_bits) - 1));
  • flags >> PB_migrate:把字段右移到最低位。

  • & ((1 << PB_migratetype_bits) - 1):只保留PB_migratetype_bits位,得到纯数值。

  • 强转为enum migratetype返回。

注意:具体移位方式取决于__get_pfnblock_flags_mask()的实现约定:

  • 如果它返回的是已右移对齐的值((flags & mask) >> __ffs(mask)),那么这里只需& ((1 << PB_migratetype_bits) - 1),不用再>> PB_migrate。

  • 如果它返回未移位的原始位,则这里需要>> PB_migrate。

不同内核版本实现略有差异,但语义一致:取出迁移类型字段的数值。


三、单参数版本对比

典型的单参数版本:

static inline enum migratetype get_pageblock_migratetype(const struct page *page) { return get_pfnblock_migratetype(page, page_to_pfn(page)); }
  • 调用page_to_pfn(page)把页转成 pfn。

  • page_to_pfn()本身是(page - vmemmap) + ...或类似计算,在CONFIG_SPARSEMEM_VMEMMAP下是简单减法,但仍是一步运算。

  • 如果调用方已经知道 pfn,直接用双参数版本可以省掉这一步。

  • 这就是注释所说的 "save a call to page_to_pfn()"。

使用建议

场景用哪个
只有pageget_pageblock_migratetype(page)
已有page和pfnget_pfnblock_migratetype(page, pfn)(更快)
在遍历 pfn 的循环里双参数版本,避免反复转换

四、迁移类型回顾

enum migratetype的值(与前面的migratetype_names[]对应):

值名字含义
MIGRATE_UNMOVABLE"Unmovable"不可移动(内核结构、页表)
MIGRATE_MOVABLE"Movable"可移动(用户态页)
MIGRATE_RECLAIMABLE"Reclaimable"可回收(slab 缓存)
MIGRATE_HIGHATOMIC"HighAtomic"高优先级原子分配保留
MIGRATE_CMA"CMA"连续内存分配器区域
MIGRATE_ISOLATE"Isolate"被隔离(热插拔/规整)

这些值编码在 pageblock 的PB_migrate字段里,本函数就是读出这个编码。


五、典型用途

1. 伙伴系统分配

  • __rmqueue_smallest()根据迁移类型从对应空闲链表取页。

  • 取之前/之后可能需要读 pageblock 的迁移类型。

2. 释放页时

  • free_one_page()/__free_one_page()需要知道页块的迁移类型,决定放回哪个链表。

  • 尤其合并(merge)伙伴时,迁移类型影响合并策略。

3. 反碎片 fallback

  • __rmqueue_fallback():当目标迁移类型没有空闲块时,找其他类型的页块"偷"。

  • 需要读取各 pageblock 的迁移类型来判断/更新。

4. 内存规整(compaction)

  • 判断哪些 pageblock 可移动,决定是否迁移。

5. 内存热插拔

  • 设置/读取 pageblock 迁移类型为MIGRATE_ISOLATE,隔离待下线内存。

6./proc/pagetypeinfo

  • 展示各迁移类型的空闲页统计,底层会读这些信息。


六、与前面内容的呼应

前面出现过的这里的关联
migratetype_names[]enum migratetype的名字表
PB_migrate/PB_migrate_end/PB_migratetype_bits迁移类型字段的位置和位数
PB_migrate_mask本函数传给__get_pfnblock_flags_mask()的 mask
__get_pfnblock_flags_mask()本函数的底层读取
is_standalone_pb_bit()本函数读的是非独立的迁移类型字段,正好与之相对
get_pfnblock_bit()读独立位;本函数读迁移类型字段,两者互补
page_group_by_mobility_disabled控制是否按迁移类型分组,影响本函数结果的使用

调用链:

get_pfnblock_migratetype(page, pfn) // 双参数,热路径 ├── __get_pfnblock_flags_mask(page, pfn, PB_migrate_mask) │ ├── get_pageblock_bitmap() │ └── pfn_to_bitidx() └── 移位 + 掩码 → enum migratetype get_pageblock_migratetype(page) // 单参数,便捷 └── get_pfnblock_migratetype(page, page_to_pfn(page))

七、小结表

项说明
函数名get_pfnblock_migratetype
作用读取某 pageblock 的迁移类型
参数page用于定位位图
参数pfn目标页帧号
返回值enum migratetype
关键优化__always_inline;已知 pfn 时省去page_to_pfn()
实现依赖__get_pfnblock_flags_mask(page, pfn, PB_migrate_mask)+ 移位/掩码
单参数版get_pageblock_migratetype(page)= 本函数 +page_to_pfn()
典型用途伙伴系统分配/释放、反碎片 fallback、规整、热插拔、/proc/pagetypeinfo

一句话总结

get_pfnblock_migratetype(page, pfn)是读取 pageblock迁移类型的强制内联接口:它通过__get_pfnblock_flags_mask(page, pfn, PB_migrate_mask)取出PB_migrate字段并按PB_migratetype_bits解码成enum migratetype;因为已知 pfn 可省去page_to_pfn(),它是伙伴系统、反碎片、规整、内存热插拔等热路径上的关键读取函数,与读取独立位的get_pfnblock_bit()互补。

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

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

立即咨询