📖 推荐阅读:《Yocto项目实战教程:高效定制嵌入式Linux系统》
🎥 更多学习视频请关注 B 站:嵌入式Jerry
Linux 内存分配理论与水位机制全解
—— /proc/buddyinfo
、Buddy分配器、水位线原理与调优建议
一、为什么要理解 Linux 的内存分配?
无论嵌入式还是服务器领域,“内存分配异常”“UI卡顿”“假死”等问题,往往根源在物理内存管理。掌握内核的 buddy 分配机制、水位判断、buddyinfo 的含义,是定位与优化分配瓶颈的必修课。
二、内存分配的基本单元与管理结构
- 页(Page):Linux 以 4KB(或 8KB)为最小物理内存分配单位。
- Zone:物理内存根据用途分区,如 DMA、Normal、HighMem。
- Node:NUMA 架构下每个物理内存节点。
- Buddy分配器:内核以“2 的幂次方”合并/拆分页块,高效支持多种粒度的分配与回收。
三、/proc/buddyinfo 文件怎么看?
每行代表一个 zone,每列代表一个 order(阶),数值为该阶空闲块数量:
例(Normal zone):
Node 0, zone Normal 150 57 53 25 10 8 5 6 3 4
- order 0: 150 × 4KB = 600KB(最小块)
- order 1: 57 × 8KB = 456KB
- order 9: 4 × 2MB = 8MB(最大块)
- 高阶空闲块数量决定了大块内存(如图像 buffer、DMA)能否顺利分配
快速计算公式
order N 数量 × 4KB × 2^N = 当前阶总空闲字节数
四、水位线机制(Watermark)原理
内核每个 zone 都有三条水位线,用于平衡“安全与性能”:
水位线 | 含义 | 作用 |
---|---|---|
min | 最低空闲页,安全底线 | 低于该线多分配失败,触发OOM或紧急回收 |
low | 触发后台回收线 | 低于该线唤醒kswapd回收页 |
high | 目标安全线 | 回收努力补充到此线 |
- 水位判断函数:
zone_watermark_ok()
- 作用:每次分配前先比较当前空闲页数与这三条线,决定能否直接分配,还是需要回收/整理。
min_free_kbytes 的作用
-
/proc/sys/vm/min_free_kbytes
是三条水位线的全局基准。 -
提高 min_free_kbytes,会同步提高 min、low、high 三条线,让系统始终预留更多空闲页(所有 zone 会按比例分摊这个总值)。
-
效果:减少分配慢、卡顿、碎片,但可用内存量略减,分配更“保守”。
-
实际操作(如 64MB):
echo 65536 > /proc/sys/vm/min_free_kbytes
五、Buddy分配器与分配全流程
-
分配请求到达(如 malloc/驱动 buffer/应用大缓存)
-
Buddy分配器按阶(order)查找连续空闲块
- 优先满足大块,高阶->低阶依次拆分
-
水位判断
- 空闲页满足 high/low/min 线?能直接分配就“快路径”,否则进入慢路径
-
快路径:
- 空闲页充足,直接分配(微秒级完成)
-
慢路径:
- 空闲页不足,触发 kswapd 回收、compact_zone 碎片整理,等待时间变长
-
释放流程
- 页释放时,Buddy自动尝试合并相邻空闲块,减少碎片
六、卡顿、碎片与监控指标
/proc/buddyinfo 常见分析场景
- order 0/1/2 持续为 0: 小内存分配慢,频繁触发回收
- order 8/9 持续为 0: 大内存分配失败/卡顿(如 UI 图像 buffer)
- 低阶与高阶空闲同步减少: 说明压力大,碎片加重
perf/ftrace 联合分析
- perf/ftrace 发现
kswapd
、compact_zone
、try_to_free_pages
频繁占用CPU,正是慢路径和回收成为瓶颈的直接证据。
七、调优建议
- 监控 buddyinfo,及时发现高阶碎片或低阶页枯竭。
- 提前分配/复用大块缓存,减少反复分配释放
- 提升 min_free_kbytes,提高所有 zone 水位线,让分配更安全、卡顿概率降低。
- 优化代码结构,避免不必要的内存分配/释放循环
八、理论结构图
分配请求
↓
Buddy分配器(按阶查找空闲块)
↓
[水位判断](min/low/high,受 min_free_kbytes 影响)
↓ ↘
足够? 否→ kswapd 回收/compact_zone 整理
↓
成功分配/失败回滚
九、结语
- /proc/buddyinfo 是内存健康、分配能力、碎片趋势的首要监控指标。
- 三条水位线(min/low/high)由 min_free_kbytes 决定,是内存分配是否安全/高效的“闸门”。
- 理论打牢基础后,再结合 perf/ftrace、buddyinfo 等实战工具,你就能高效定位和解决各种“UI卡顿”“假死”等实际瓶颈问题。
下篇预告:
配套真实代码、压力测试脚本、perf report 分析 UI 卡顿,从现象到定位、到优化一站式搞定!
📖 推荐阅读:《Yocto项目实战教程:高效定制嵌入式Linux系统》
🎥 更多学习视频请关注 B 站:嵌入式Jerry