内核内存管理:分配、回收与 OOM
2026/8/9大约 3 分钟内核Android 14内核内存OOM
内核内存管理:分配、回收与 OOM
上一章看了 Binder 驱动。这一章回答:内核怎么分配内存,回收怎么触发,OOM 如何 兜底,与 Android 的 lmkd 是什么关系?
回收发生在 OOM 之前
| 常见误解 | 正确理解 |
|---|---|
| 内核内存和用户内存分开 | 用户内存由内核页分配器管理,共享同一套机制 |
| 内存不足直接杀进程 | 先回收(LRU/页缓存),杀进程是最后手段 |
| OOM Killer 是 Android 主力 | 主力是 lmkd,内核 OOM 是兜底 |
核心结论
- 页分配器(Buddy)管理物理页,slab 管理内核对象。
- 回收优先清页缓存与 LRU 页,减少杀进程。
- PSI 上报内存压力,供 lmkd 决策。
- 内核 OOM Killer 按 oom_score 兜底,Android 主力仍是 lmkd。
- 内存问题先看压力与回收,再谈杀进程。
内存管理主链
逐步解释:
- 分配:Buddy 与 slab 满足请求。
- 压力:可用内存下降。
- 回收:先清缓存与 LRU 页。
- 上报:PSI 通知用户空间。
- 兜底:lmkd 或 OOM。
与 lmkd 的分工
内核负责“分配、回收、上报”,lmkd 负责“决策杀谁”。内核 OOM 只在压力极端且 lmkd 来不及或失效时触发。理解分工,才能解释“为什么被杀的是它”。
源码证据
阅读目标:确认分配与回收入口。
正文指针:mm/page_alloc.c(页分配);mm/vmscan.c(回收);mm/oom_kill.c。
// mm/vmscan.c(伪代码,行号以 r75 为准)
// 内存回收:LRU 页与页缓存这段代码证明: 回收与 OOM 是内核机制;Android 的 lmkd 通过 PSI 与内核协作, 形成“内核兜底 + 用户空间决策”的体系。
验证与排障
环境:开发设备或模拟器;部分命令需要 root。
adb shell cat /proc/meminfo
adb shell cat /proc/pressure/memory
adb shell su 0 dmesg | grep -iE "oom|lowmem"先看内存水位与压力,再看回收与 OOM 记录。内存问题先分清“压力高未回收”还是 “已杀进程”,再进入 lmkd/排障专题。
常见误区
- “内核内存和用户内存分开”:共享页分配器。
- “内存不足直接杀”:先回收后兜底。
- “OOM 是 Android 主力”:lmkd 才是。
- “杀进程看单一指标”:结合 adj、分组与压力。
延伸问题
- LRU 回收如何选择被回收的页?
- PSI 与 vmpressure 的差异是什么?
- slab 泄漏如何定位?
- 内核 OOM 日志如何解读?
源码入口
| 文件 | 关键位置 | 作用 |
|---|---|---|
mm/page_alloc.c | 页分配 | Buddy |
mm/vmscan.c | 回收 | LRU |
mm/oom_kill.c | OOM | 兜底 |
/proc/pressure/memory | PSI | 压力 |
公共路径:内核 mm/。行号以 r75 检索为准。
线程何时获得 CPU,见 内核调度。