ARTICLE DETAIL

建站实战干货

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

hotplug MAX_BLOCK_SIZE

2026/9/29 4:51:50 拓冰建站 浏览量
hotplug MAX_BLOCK_SIZE 内存热插拔Memory Hotplug机制中允许的最大内存块大小。核心含义#define MAX_BLOCK_SIZE (2UL 30) // 2GBMAX_BLOCK_SIZE被定义为2GB2UL 30 2 × 2³⁰ 字节 2GB。这是内存热插拔/热移除操作中单个内存块可以拥有的最大尺寸。与MIN_MEMORY_BLOCK_SIZE的关系注释明确指出块大小block size必须满足两个条件是 2 的幂便于位运算和地址对齐。大于等于MIN_MEMORY_BLOCK_SIZE这是块大小的下限。MIN_MEMORY_BLOCK_SIZE通常与架构的页表层级有关。例如在 x86-64 上它可能被定义为PMD_SIZE2MB因为内存热插拔的粒度不能小于页表映射的粒度。因此块大小的合法范围是MIN_MEMORY_BLOCK_SIZE ≤ block_size ≤ MAX_BLOCK_SIZE。在内存热插拔中的作用内存热插拔以“块”为单位进行操作。每个块对应一个memory_block设备在/sys/devices/system/memory/下可见。块大小的选择需要在两个目标之间平衡块太小管理开销大memory_block设备数量多sysfs 节点爆炸。块太大无法精细地热插拔例如用户可能只想移除 4GB 内存但块大小是 8GB就无法精确操作。MAX_BLOCK_SIZE设为 2GB 是一个合理的上限既允许足够大的热插拔粒度又不会因为单个块过大而失去灵活性。这个值也与section的大小通常 128MB形成倍数关系便于 SPARSEMEM 模型管理。历史背景在早期内核中MAX_BLOCK_SIZE曾被定义为(1UL 30)1GB。后续补丁将其扩大到 2GB以支持更大的内存热插拔场景如大型虚拟化环境。这个变更也伴随着对block_size_bytes默认值的调整确保在支持大块的同时默认行为仍然合理。主要调用位置probe_memory_block_size()MAX_BLOCK_SIZE在 Linux 内核中的调用非常集中主要围绕x86 架构内存块大小的探测与决策。它的使用场景可以清晰地分为两类。这是MAX_BLOCK_SIZE最核心的使用场景位于arch/x86/mm/init_64.c。这个函数负责在启动时为 x86 系统决定内存热插拔块的大小。调用逻辑随着内核版本演进主要包含以下判断1. 裸机Bare Metal场景在较新的内核中如果系统运行在裸机上X86_HYPER_NATIVE或!cpu_feature_enabled(X86_FEATURE_HYPERVISOR)MAX_BLOCK_SIZE会被直接用作内存块大小。/* 来自 arch/x86/mm/init_64.c 的典型逻辑 */ if (hypervisor_is_type(X86_HYPER_NATIVE)) { bz MAX_BLOCK_SIZE; goto done; }2. 内存末端未对齐时的回退方案如果系统运行在虚拟化环境中且物理内存的末端boot_mem_end没有对齐到任何允许的块大小如 128MB、256MB 等内核会回退使用MAX_BLOCK_SIZE。这样做的目的是避免因使用过小的块如 128MB而导致在大型系统上生成海量的 sysfs 目录从而严重拖慢启动速度。/* 如果内存末端未对齐则使用最大块大小以最小化开销 */ if (!IS_ALIGNED(boot_mem_end, MIN_MEMORY_BLOCK_SIZE)) { bz MAX_BLOCK_SIZE; goto done; }3. 作为对齐搜索的起点在标准的对齐查找循环中MAX_BLOCK_SIZE被用作搜索的初始值从最大块开始向下寻找第一个能整除内存末端的块大小。/* 寻找能对齐内存末端的最大的允许块大小 */ for (bz MAX_BLOCK_SIZE; bz MIN_MEMORY_BLOCK_SIZE; bz 1) { if (IS_ALIGNED(boot_mem_end, bz)) break; }间接调用通过memory_block_size_bytes()MAX_BLOCK_SIZE本身是一个宏它不会直接被其他子系统调用。其他子系统如drivers/base/memory.c中的内存块设备管理代码是通过架构实现的memory_block_size_bytes()函数来获取块大小的。在 x86 架构上memory_block_size_bytes()的返回值正是由probe_memory_block_size()计算出来的而MAX_BLOCK_SIZE是这个计算过程中的关键上限。调用集中的原因MAX_BLOCK_SIZE的调用点如此集中是因为它本质上是 x86 架构的一个内部实现细节。内存热插拔的核心逻辑如offline_and_remove_memory需要知道“块”有多大但它们只调用抽象的memory_block_size_bytes()。具体的“块有多大”这个策略完全由 x86 的probe_memory_block_size()在启动时决定而MAX_BLOCK_SIZE就是这个决策过程中的一个重要参数。