当前位置:首页>Linux>linux斩杀线OOM之“制度设计”

linux斩杀线OOM之“制度设计”

  • 2026-10-21 13:28:38
linux斩杀线OOM之“制度设计”
上一篇文章我们总结了OOM的各种操作用法,会用和深入理解还有一段距离。本次就深入源码,来好好研究一下斩杀线OOM是如何设计的。
接下来我们以5.10内核为分析对象
第一步必然是走到触发斩杀线OOM的函数,out_of_memory,即当前超出内存资源限制了,怎么办
注意:以下源码属于类伪代码,非全部源码,***里面说明了对应上一篇文章的哪一部分
out_of_memory(mm/oom_kill.c)[     if (oom_killer_disabled)            return false;    if (!is_memcg_oom(oc) && !oom_cpuset_eligible(task, oc)) {            // 不是memcg_oom且未被选中,忽略            mem_cgroup_account_oom_skip(task, oc);            return 0;    }    if (!is_memcg_oom(oc) && sysctl_oom_kill_allocating_task &&            current->mm && !oom_unkillable_task(current) &&            oom_cpuset_eligible(current, oc) &&            current->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) {	      // 不是memcg oom且sysctl_oom_kill_allocating_task非0且不是不可杀进程且且被选中且未设置oom_score_adj为-1000              // ***谁触发的OOM,就杀谁,上篇文章表中第五项oom_kill_allocating_task***                get_task_struct(current);                oc->chosen = current;                **oom_kill_process(oc, "Out of memory (oom_kill_allocating_task)");**                return true;    }    //内存配置相关查询,不同配置走不同策略尝试回收部分内存    select_bad_process(oc)(mm/oom_kill.c)    [        if cgroup mem oom:           mem_cgroup_select_bad_process(oc)(mm/memcontrol.c)           [ // ***cgroup优先级策略,上篇文章表中第一项cgoup优先级***               if(oc->use_priority_oom)               {                   mem_cgroup_select_victim_cgroup                   [                       if (!memcg->use_hierarchy)                           return memcg                       // 迭代遍历选择优先级最低的memcg                       return 优先级最低的memcg                   ]                }                mem_cgroup_scan_tasks(victim, **oom_evaluate_task**, oc)                // 计算分数的逻辑与非cgroup的oom一致           ]         else:             for_each_process(p)                    if (oom_evaluate_task(p, oc))(mm/oom_kill.c)                    [	                    ...	                    if (oom_task_origin(task)) {		                // 设置了kill触发者,固选择将触发oom的进程kill                                // ***谁触发的OOM,就杀谁,上篇文章表中第五项oom_kill_allocating_task***	                    }	                    points = oom_badness(task, oc->totalpages);	                    [                              // ***上篇文章表中第三项oom_score_adj***                              adj = (long)p->signal->oom_score_adj;                              if task是不可杀死的进程 or task是锁定内存的进程                                  return LONG_MIN                              if oom_score_adj == -1000:                                  return LONG_MIN                              points = 常驻内存集(rss)+页表+swap内存比例                              adj *= 总页表 / 1000                              points += adj                              return points	                    ]                            if (points == LONG_MIN) {                                // 忽略该进程,不进行oom kill                            }                    ]                    break;    ]    ...    // 杀掉被选择的进程    oom_kill_process ]
还有两个重要的策略,主要集中在内存策略是否有交集,所以还需要看一下重要的函数oom_cpuset_eligible,即判断内存是否有交集来决定杀死谁
oom_cpuset_eligible(struct task_struct *start, struct oom_control *oc)[    const nodemask_t *mask = oc->nodemask    if (is_memcg_oom(oc))        return true;    for_each_thread(start, tsk) {        if (mask) {             // 如果这是由内存策略(mempolicy)约束的 OOM(内存耗尽)情况,那么任务(tsk)的 cpuset(CPU 集)是无关紧要的。仅当任务的内存策略与当前内存策略存在交集时才返回 true(真),否则它可能会被不必要地终止             // ***上篇文章表中第四项***            ret = mempolicy_nodemask_intersects(tsk, mask);            [               // 如果任务(tsk)的内存策略为“default”NULL,则返回“true”表示采用默认策略。  否则,对于“bind”或“interleave”策略,检查掩码与策略节点掩码是否存在交集。对于“perferred”或“local”策略,由于回退时可能在其他地方分配内存,因此始终返回 true               mempolicy = tsk->mempolicy               if (!mempolicy)                   return true	             switch(mempolicy->mode){	                  ....	                  nodes_intersects(mempolicy->v.nodes, \*mask)		                [	                       bitmap_intersects()	                       // 判断两个位图(bitmap)是否存在交集,即两个位图中是否有至少一个相同的位被设置为1		                ]	               }             ]        } else {            // 这不是一个由内存策略(mempolicy)约束的 OOM(内存耗尽)情况,因此仅检查任务(tsk)的 cpuset(CPU 集)所允许的内存节点(mems)            // ***上篇文章表中第二项***           ret = cpuset_mems_allowed_intersects(current, tsk);           [                // 内存分配范围与当前触发 OOM 的进程有重叠                // 1. 获取两个任务的 `mems_allowed`(cpuset 允许的内存节点掩码)                // 2. 对两个掩码进行按位与(AND)操作                // 3. 如果结果非零,则表示有交集                // 4. 有交集返回true           ]        }       if (ret)           break;    }    return ret]

最新文章

随机文章