☰
page_alloc migratetype_names
2026/10/6 2:50:21 网站建设 项目流程

定义了几个与迁移类型、内存水位、内存规整(defrag)、NUMA 节点相关的全局变量。逐块拆解。


一、migratetype_names[]—— 迁移类型名称表

const char * const migratetype_names[MIGRATE_TYPES] = { "Unmovable", "Movable", "Reclaimable", "HighAtomic", #ifdef CONFIG_CMA "CMA", #endif #ifdef CONFIG_MEMORY_ISOLATION "Isolate", #endif };

作用

和zone_names[]类似,这是迁移类型索引到可读名称的映射表,用于打印、/proc/pagetypeinfo等。

类型

  • const char * const [...]:

    • 指向const char的常量指针数组;

    • 指针本身和字符串内容都不可修改;

    • 比zone_names[]的char * const更严格(zone_names指向的字符串也是字面量,但类型上没标const char)。

各项含义

索引名字含义
MIGRATE_UNMOVABLE"Unmovable"不可移动页(内核数据结构、页表等),最容易造成碎片
MIGRATE_MOVABLE"Movable"可移动页(用户态匿名页、文件页缓存),可规整迁移
MIGRATE_RECLAIMABLE"Reclaimable"可回收页(如 slab 缓存),可被回收而非迁移
MIGRATE_HIGHATOMIC"HighAtomic"高优先级原子分配保留区,供GFP_ATOMIC等紧急分配
MIGRATE_CMA"CMA"连续内存分配器(Contiguous Memory Allocator)区域,条件编译
MIGRATE_ISOLATE"Isolate"被隔离的页块,用于内存热插拔/规整,条件编译

反碎片的核心思想

  • 内核把空闲页按迁移类型分到不同链表;

  • 分配时尽量同类型分配,避免可移动页混进不可移动页块;

  • 这样可移动页块保持连续、可整块迁移/回收,减少碎片。

  • 当某类型不够时,__rmqueue_fallback()才去"偷"其他类型的页块(可能破坏反碎片,所以尽量少用)。

与sysctl_lowmem_reserve_ratio的对比

数组索引维度用途
zone_names[]zone打印 zone 名
sysctl_lowmem_reserve_ratio[]zone低端保留比例
migratetype_names[]迁移类型打印迁移类型名

三者都是"按枚举索引的配置/名字表"。


二、内存水位与 min_free_kbytes

int min_free_kbytes = 1024; int user_min_free_kbytes = -1; static int watermark_boost_factor __read_mostly = 15000; static int watermark_scale_factor = 10;

这几个变量控制zone 水位(watermark)的计算,即"保留多少空闲内存"。

1.min_free_kbytes = 1024

  • 全局最小值:系统至少要保留1024 KB(1 MB)空闲内存。

  • 是WMARK_MIN的基础:

    • 每个 zone 的WMARK_MIN按 zone 大小比例分配min_free_kbytes;

    • 再基于WMARK_MIN计算WMARK_LOW、WMARK_HIGH。

  • 用户可通过/proc/sys/vm/min_free_kbytes调整。

2.user_min_free_kbytes = -1

  • 用户显式设置的值,初始-1表示"用户未设置"。

  • 用于区分:

    • 内核根据内存大小自动计算的min_free_kbytes;

    • 用户通过 sysctl手动设定的值。

  • 若用户设过,重启/热插拔时不应被自动计算覆盖,所以单独存一份用户意图。

3.watermark_boost_factor = 15000(__read_mostly)

  • 水位提升因子,默认 15000(即150%,因为单位是百分比 ×100)。

  • 用于在内存碎片化严重/规整失败时,临时抬高水位,让回收更积极,给规整留出空间。

  • 相关机制:boost_watermark(),在should_compact_retry()等路径触发。

  • /proc/sys/vm/watermark_boost_factor可调。

4.watermark_scale_factor = 10(默认)

  • 水位间距因子,默认 10(即0.1%)。

  • 决定WMARK_LOW与WMARK_MIN、WMARK_HIGH与WMARK_LOW之间的间距:

    间距 ≈ zone_managed_pages * watermark_scale_factor / 10000
  • 间距越大,kswapd 越早被唤醒、回收越积极,但空闲内存保留也越多。

  • /proc/sys/vm/watermark_scale_factor可调。

水位三档回顾

free pages ^ | WMARK_HIGH ── 高于此,kswapd 停止回收 | WMARK_LOW ── 低于此,kswapd 开始回收 | WMARK_MIN ── 低于此,直接回收/规整,甚至 OOM +-------------------------------->
  • min_free_kbytes决定WMARK_MIN的基准;

  • watermark_scale_factor决定三档之间的间距;

  • watermark_boost_factor在需要时临时抬高水位。


三、defrag_mode

int defrag_mode;
  • 控制内存规整(compaction)行为模式的开关。

  • 相关 sysctl:/proc/sys/vm/compaction_proactiveness等(不同版本语义有差异)。

  • 用于决定是否启用主动规整、规整的积极程度等。

  • 默认 0,表示默认行为。

(不同内核版本defrag_mode的具体含义略有不同,但都属于"内存规整策略"的全局配置。)


四、movable_zone—— ZONE_MOVABLE 的来源 zone

/* movable_zone is the "real" zone pages in ZONE_MOVABLE are taken from */ int movable_zone; EXPORT_SYMBOL(movable_zone);

含义

  • ZONE_MOVABLE是一个虚拟 zone:它的页不是独立物理内存,而是从某个"真实 zone"里划出来的。

  • movable_zone记录这个真实 zone 的索引(通常是ZONE_NORMAL或ZONE_HIGHMEM)。

  • 注释说得很清楚:"real" zone pages in ZONE_MOVABLE are taken from。

为什么需要它?

  • ZONE_MOVABLE用于:

    • 内存热插拔:可移动页能整块迁移走,方便下线内存;

    • 减少碎片:可移动页集中管理,便于规整;

    • hugetlb 大页:需要连续内存,放 MOVABLE 更易满足。

  • 但它的物理页来自真实 zone,所以分配/统计时需要知道来源 zone。

  • 例如迁移类型 fallback、水位计算、页归属判断都要用到movable_zone。

设置时机

  • 内核启动参数kernelcore=/movablecore=指定 MOVABLE 大小;

  • 初始化时据此从某个真实 zone 划出 MOVABLE,并记录movable_zone。

EXPORT_SYMBOL

  • 导出给模块(如 CMA、hugetlb 相关模块可能需要知道来源 zone)。


五、NUMA 节点数量变量(MAX_NUMNODES > 1)

#if MAX_NUMNODES > 1 unsigned int nr_node_ids __read_mostly = MAX_NUMNODES; unsigned int nr_online_nodes __read_mostly = 1; EXPORT_SYMBOL(nr_node_ids); EXPORT_SYMBOL(nr_online_nodes); #endif

条件编译MAX_NUMNODES > 1

  • 只在可能多节点(NUMA 或CONFIG_NODES_SHIFT > 0)时才定义。

  • 单节点(MAX_NUMNODES == 1)时不需要,编译期就确定只有一个节点。

1.nr_node_ids

unsigned int nr_node_ids __read_mostly = MAX_NUMNODES;
  • 实际存在的节点 ID 数量上限(稀疏节点编号下的最大 ID + 1)。

  • 初始为MAX_NUMNODES(最宽松),启动时根据固件探测收紧。

  • 用途:

    • 分配node_data[]、node_states等数组时确定大小;

    • 遍历节点时作为边界;

    • 允许节点 ID 稀疏(比如只有 node 0 和 node 3),此时nr_node_ids = 4,但nr_online_nodes = 2。

2.nr_online_nodes

unsigned int nr_online_nodes __read_mostly = 1;
  • 在线节点数量(实际有内存/CPU 且已上线的节点个数)。

  • 初始 1(至少 node 0),启动时随节点上线增加。

  • 用途:

    • 判断是否真的多节点(nr_online_nodes > 1);

    • 决定是否启用 NUMA 相关优化(如 per-node 分配、NUMA balancing);

    • 统计信息展示。

两者区别

变量含义例子(node 0,3 在线)
nr_node_ids最大节点 ID + 1(数组维度)4
nr_online_nodes实际在线节点数2

__read_mostly+EXPORT_SYMBOL

  • 启动时确定、运行期几乎只读,放 read-mostly 段。

  • 导出给模块使用。


六、小结表

变量类型/默认作用
migratetype_names[]const char * const []迁移类型名称表
min_free_kbytesint/ 1024系统保留的最小空闲内存(KB)
user_min_free_kbytesint/ -1用户显式设置值,-1 表示未设
watermark_boost_factorint/ 15000临时抬高水位的因子
watermark_scale_factorint/ 10水位间距因子
defrag_modeint/ 0内存规整模式
movable_zoneint/ 未初始化ZONE_MOVABLE 页的真实来源 zone
nr_node_idsunsigned int/ MAX_NUMNODES最大节点 ID + 1
nr_online_nodesunsigned int/ 1在线节点数

一句话总结

这段定义了迁移类型名称表migratetype_names[],以及一组控制内存水位与规整的全局参数(min_free_kbytes、user_min_free_kbytes、watermark_boost_factor、watermark_scale_factor、defrag_mode)、记录ZONE_MOVABLE来源真实 zone 的movable_zone,以及多节点下的nr_node_ids(最大节点 ID+1)和nr_online_nodes(在线节点数)——它们共同构成 zone/迁移类型/水位/NUMA 的基础配置,多数在启动时确定、运行期只读。

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

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

立即咨询