1. Linux内存碎片化问题背景
在长期运行的Linux服务器上,内存碎片化是个绕不开的痛点。想象你有一盒乐高积木,虽然总块数足够拼出想要的模型,但散落着大量1x1的小颗粒,就是找不到需要的4x2基础块——这就是典型的内存碎片场景。内核伙伴系统(buddy allocator)虽然能高效管理页框,但无法避免外部碎片问题。当系统需要分配连续物理内存时(比如DMA设备或大页内存),可能因碎片导致分配失败,即使系统显示还有足够空闲内存。
我曾在生产环境遇到过这样的案例:某数据库服务器free显示剩余8GB内存,但申请4MB连续内存时直接触发OOM。用cat /proc/buddyinfo查看伙伴系统状态,发现高阶内存块(order>=3)几乎耗尽,而低阶块大量存在。这就是内存碎片化的典型表现。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 内存压缩原理与核心流程
2.1 内存压缩基本概念
内存压缩(compaction)是内核解决碎片问题的主要手段,其核心思想像玩俄罗斯方块——把分散的内存块向一端移动,在另一端形成连续空闲区域。整个过程分为三个关键阶段:
- 隔离扫描:通过迁移扫描器(migration scanner)从zone头部开始,识别可移动页(用户进程页、页缓存等)
- 空闲扫描:通过空闲扫描器(free scanner)从zone尾部开始,寻找合适的目标位置
- 页面迁移:将可移动页复制到空闲位置,更新页表映射,释放原页面
2.2 compact_zone函数框架
compact_zone()是内存压缩的核心函数,其简化逻辑如下:
c复制static enum compact_result compact_zone(...) {
// 初始化扫描器
init_migration_scanner();
init_free_scanner();
// 主循环
while (!finished) {
// 扫描可迁移页面
isolate_migratepages();
// 如果没有隔离到页面,推进迁移扫描器
if (no_isolated_pages)
advance_
