Linux 6.12 内存管理深度剖析:out_of_memory核心机制与跨模块协同📌 技术点速览out_of_memory函数是 Linux 内核内存管理系统 (MemoryManagement)在物理内存极度匮乏、且通过常规页面回收(Reclaim)无法释放足够空间时的“最后防线”与“终极裁决者”。它位于内存分配路径的末端,负责评估系统当前的内存危机程度,并根据特定算法(如 OOM Score)选择并终止一个或多个最合适的进程,以释放其占用的物理内存,防止系统陷入无响应或死锁状态。该函数属于内核的MemoryManagement (内存管理系统)模块,但其调用链和影响范围跨越了Arch_Generic (通用体系结构支撑)、Drivers_Block (块设备驱动)以及进程调度与信号处理等多个核心模块。🗺️ 软件功能架构图🔍 核心源码硬核解析 (基于 Linux 6.12)在 Linux 6.12 内核中,out_of_memory函数定义于mm/oom_kill.c。以下是该函数的完整核心源码及逐行硬核解析:/** * out_of_memory - 触发 OOM Killer 的核心入口函数 * @oc: 指向 oom_control 结构体的指针,包含了触发 OOM 的上下文信息(如 gfp_mask、order、nodemask 等) * * 返回值: * true - 成功选择并杀死了某个进程,或者当前进程正在退出以释放内存。 * false - OOM Killer 被禁用,或者无法执行 OOM 操作。 */ bool out_of_memory(struct oom_control *oc) { unsigned long freed = 0; ​ /* * 1. 检查 OOM Killer 是否被全局禁用。 * 在系统休眠(Suspend/Hibernate)或某些特定的系统初始化阶段, * 为了防止误杀关键进程,oom_killer_disabled 会被置为 true。 */ if (oom_killer_disabled) return false; ​ /* * 2. 如果当前不是 Memcg(内存控制组)触发的 OOM,而是全局 OOM, * 则调用通知链(Notifier Chain)。 * 允许注册了 oom_notify_list 的驱动或子系统(如 GPU 驱动、虚拟化气球驱动) * 在此时紧急释放一些缓存。如果释放成功(freed 0),且不是 SysRq 强制触发的 OOM, * 则直接返回 true,暂不杀进程。 */ if (!is_memcg_oom(oc)) { blocking_notifier_call_chain(oom_notify_list, 0, freed); if (freed 0 !is_sysrq_oom(oc)) /* 最后一秒成功回收了部分内存,暂缓死刑 */ return true; } ​ /* * 3. 检查当前进程(current)是否已经处于退出流程(exiting) * 或者已经收到了 pending 的 SIGKILL 信号。 * 如果是,说明它即将释放内存。此时我们直接将其标记为 OOM 受害者, * 并加入 oom_reaper 队列,允许其临时使用内存保留区(Memory Reserves)以快速退出。 * 这体现了内存管理系统与进程生命周期管理的紧密协同。 */ if (task_will_free_mem(current)) { mark_oom_victim(current); queue_oom_reaper(current); return true; } ​ /* * 4. 关键安全阀:处理无文件系统参与(IO-less)的内存回收限制。 * 如果分配掩码中没有携带 __GFP_FS(例如在文件系统写回、日志提交等关键路径中), * 并且这不是一个 Memcg OOM,我们必须直接返回 true 而不杀进程。 * 原因:在没有 __GFP_FS 的情况下杀进程,可能会因为等待文件系统锁而导致系统彻底死锁。 */ if (!(oc-gfp_mask __GFP_FS) !is_memcg_oom(oc)) return true; ​ /* * 5. 评估内存分配的约束条件(如 NUMA 节点限制、Memcg 限制)。 * constrained_alloc 会判断当前 OOM 是由于全局内存不足, * 还是由于 cpuset、NUMA 策略(CONSTRAINT_MEMORY_POLICY)或 Memcg 限制引起的。 */ oc-constraint = constrained_alloc(oc); if (oc-constraint != CONSTRAINT_MEMO