OOM 机制与实现详解

OOM 机制与实现详解

源码路径rk3588/kernel-6.1/mm/oom_kill.c
内核版本:Linux 6.1(RK3588)
文档目录linuxDoc/mm/


目录


一、原理

1.1 何时触发 OOM

__alloc_pages 慢路径 在以下手段后仍失败:

  • direct reclaim
  • compaction
  • (可能)多次重试

则调用 __alloc_pages_may_oom()out_of_memory()

OOM 不是「物理 RAM 为 0」,而是 在给定 gfp/zone/cpuset 约束下无法满足分配

1.2 设计目标

在系统崩溃与随机杀进程之间,选择 oom_score 最高的进程终止,释放其 RSS + 页表 + 缓存引用,使后续分配成功。

1.3 与回收的区别

机制 行为
reclaim 回收 可丢弃 的 cache 或 swap 匿名页
OOM 终止 整个进程,回收其独占匿名页等

二、实现方式

2.1 入口:out_of_memory()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool out_of_memory(struct oom_control *oc)
{
if (oom_killer_disabled)
return false;
// notifier 可能释放内存
if (task_will_free_mem(current)) {
mark_oom_victim(current);
queue_oom_reaper(current);
return true;
}
// GFP_NOFS 等约束可能跳过全局 OOM
oc->constraint = constrained_alloc(oc);
check_panic_on_oom(oc);
// sysctl: oom_kill_allocating_task
select_bad_process(oc);
oom_kill_process(oc, ...);
return !!oc->chosen;
}

2.2 struct oom_control

记录本次 OOM 上下文:

  • gfp_maskorderzonelist
  • memcg(若为 cgroup OOM)
  • chosen:选中 victim
  • constraint:NUMA / cpuset / policy 限制

2.3 选择 victim:select_bad_process

遍历进程(for_each_process 或 memcg 子树):

  • 计算 oom_badness:RSS、swap、调度类、硬件损坏等
  • 加上 oom_score_adj/proc/<pid>/oom_score_adj,-1000 永不杀)
  • 跳过 内核线程PF_KTHREADOOM_SCORE_ADJ_MIN

2.4 杀进程:oom_kill_process

  1. mark_oom_victim:设置 TIF_MEMDIE
  2. 发送 SIGKILL(或依赖 oom reaper)
  3. oom_reaper 内核线程加速释放 victim 的 mm(unmap、释放页)

2.5 分配进程优先退出

若当前进程 task_will_free_mem(已有 SIGKILL、正在 exit),直接选为 victim,便于 快速释放 而不搜全局。

2.6 pagefault OOM

pagefault_out_of_memory():缺页路径无 gfp 上下文,主要处理 memcg OOM;全局 OOM 仍由分配上下文触发。

2.7 panic 路径

  • panic_on_oom:OOM 时内核 panic
  • 无可杀进程:panic("System is deadlocked on memory")

三、关键数据结构与接口

接口 说明
out_of_memory 全局/约束 OOM 入口
register_oom_notifier 第三方在杀进程前尝试释放内存
oom_killer_disable/enable 暂停 OOM(危险)
/proc/<pid>/oom_score 只读分数

四、memcg OOM 与全局 OOM

类型 范围 典型场景
全局 OOM 全系统 物理内存耗尽
memcg OOM 超过 cgroup limit 容器/Android 应用组

memcg 路径 mem_cgroup_out_of_memory → 仍调用 out_of_memoryis_memcg_oom(oc) 为真,仅杀组内进程。


五、RK3588 平台说明

  • 编码服务 + 多客户端:建议用 memcg 限制单应用,避免一次全局 OOM 杀掉编码守护进程。
  • lmkd(Android)根据 adj 与 vmpressure 杀应用,与内核 OOM 互补。
  • oom_score_adj 保护关键进程(如 mediaserver、自定义编码器)。

六、调试与观测

手段 说明
dmesg Out of memory: Kill process ...
/proc/<pid>/oom_score_adj 调整优先级
sysctl vm.panic_on_oom 2=panic
sysctl vm.oom_kill_allocating_task 杀当前分配者

附录:源码索引

主题 文件 约略行号
out_of_memory oom_kill.c 1106
oom_badness oom_kill.c 搜索 select_bad
pagefault OOM oom_kill.c 1185

文章互动

阅读 --

留言

0 条留言

正在加载留言…