Linux内存碎片真实存在,分为内部碎片(因页大小和对象对齐导致的页内浪费)和外部碎片(伙伴系统中高阶连续页缺失,表现为/proc/buddyinfo中order≥3列长期为0)。

是的,Linux 内存碎片真实存在,且分为两类:内部碎片(internal fragmentation)和外部碎片(external fragmentation),二者在物理内存层面均可观测、可量化、可触发故障。
怎么看有没有外部碎片?用 /proc/buddyinfo 直接验证
外部碎片的核心表现是:系统空闲内存总量充足,但无法满足高阶连续页(如 order=3 即 8×4KB = 32KB)分配请求。这是伙伴系统(buddy allocator)层级化管理的直接结果。
- 运行
cat /proc/buddyinfo,观察各 zone 各 order 的空闲页数:若低阶(order=0~2)页充足,但order>=3列长期为 0 或极低,说明外部碎片已严重 - 典型故障现象:
dma_alloc_coherent失败、__alloc_pages_slowpath告警、网卡驱动报Cannot allocate DMA memory - 注意:该文件反映的是**物理页连续性**,与用户态
malloc或虚拟内存无关;即使free -h显示大量空闲,也不代表能分配大块连续物理内存
内部碎片为什么躲不掉?从页大小和 slab 对齐说起
内部碎片不是 bug,而是设计权衡的结果——它由 Linux 内存管理的两个硬性约束决定:固定页大小(PAGE_SIZE)和内核对象对齐要求。
- 用户申请 5KB,内核必须分配 2 个
4KB页(共 8KB),多出的 3KB 就是内部碎片;这部分内存虽空闲,但无法单独再分给其他请求 - 内核小对象(如
struct sk_buff、struct inode)走slub分配器,按预设缓存大小(如 192B、256B)对齐;一个 120B 对象占 192B 缓存块,浪费 72B - 这类碎片不会导致分配失败,但会抬高内存水位,间接加剧外部碎片压力——比如本可用于合并成
order=2块的页,因被 slab 拆散而闲置
碎片整理(memory compaction)不是万能的,得看页是否可移动
Linux 自 2.6.32 起支持在线内存整理(CONFIG_COMPACTION=y),但它只对“可迁移页”(movable page)有效,很多页天生不可动。
- 可移动页:用户进程匿名页(堆、栈)、文件页(clean page)、slab 中部分缓存页
- 不可移动页:内核线性映射区(
ZONE_NORMAL低地址)、DMA 保留页、vmalloc区域、某些驱动锁定的页(如 GPU pinned memory) - 执行整理:写
1到/proc/sys/vm/compact_memory,或通过echo 1 > /proc/sys/vm/compact_node指定 node;但若不可移动页占比高(如数据库常驻页、实时任务锁页),整理效果极弱
真正容易被忽略的是:碎片问题往往在业务稳定运行数周后才暴露,且症状分散(延迟毛刺、偶发超时、dmesg 出现 page allocation failure)。不要等 OOM 才查 /proc/buddyinfo,定期采集并监控高阶空闲页趋势,比事后调优更有效。






