LINUX常见问题之oom kill

这篇具有很好参考价值的文章主要介绍了LINUX常见问题之oom kill。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、OOM含义

OOM(Out Of Memory)机制为Linux内核中一种自我保护机制,当系统分配不出内存时(触发条件)会触发这个机制,由系统在已有进程中挑选一个占用内存较多,回收内存收益最大的进程杀掉来释放内存。
Linux下允许程序申请比系统可用内存更多的内存(如malloc函数),这个特性叫Overcommit。这么做是出于优化系统的考虑,因为并不是所有的程序申请了内存就立刻使用,当使用的时候说不定系统已经回收了一些内存资源了。不过当需要真正使用内存资源而系统已经没有多余的内存资源可用时,OOM机制就被触发了。

二、OOM相关参数

参数:panic_on_oom

含义:用来控制当内存不足时该如何做。
查看:cat /proc/sys/vm/panic_on_oom
取值:0/1/2
值为0:内存不足时,启动 OOM killer。
值为1:内存不足时,有可能会触发 kernel panic(系统重启),也有可能启动 OOM killer。
值为2:内存不足时,表示强制触发 kernel panic,内核崩溃GG(系统重启)。

参数:oom_kill_allocating_task

含义:用来决定触发OOM时先杀掉哪种进程
查看:cat /proc/sys/vm/oom_kill_allocating_task
取值:0或者非0
值为0:会 kill 掉得分最高的进程。
值为非0:会kill 掉当前申请内存而触发OOM的进程。
当然,一些系统进程(如init)或者被用户设置了oom_score_adj的进程等可不是说杀就杀的。

参数:oom_dump_tasks

含义:用来决定触发OOM时是否进行日志dump记录
查看:cat /proc/sys/vm/oom_dump_tasks
取值:0或者非0
值为0:关闭oom日志信息dump打印
值为非0:调用dump_tasks来打印系统中所有task的内存状况

参数:oom_adj、oom_score_adj和oom_score

含义:都是和具体进程相关的oom参数,和进程得分计算相关
查看:cat /proc/xxx/目录下(xxx是进程ID)
取值:0、正值、负值(-1000到1000之间)
0表示接受默认值,负值表示要在实际打分值上减去一个折扣,正值表示要惩罚该task

参数:  overcommit_memory

含义:允许程序申请比系统可用内存更多的内存特性
查看:cat  /proc/sys/vm/overcommit_memory取值:0、1和2三个值,默认是0:
1、取值0:启发式策略,比较多的内存申请可能会被拒绝,如当前内存2G,突然申请1T的内存(一般当系统启动selinux模块时有效,其他情况等同取值1);
2、取值1:允许分配比当前内存资源多的内存;
3、取值2:系统所能分配的内存资源不能超过swap+内存资源*系数(/proc/sys/vm/overcommit_ratio,默认50%,可调整)。如果资源已经用光,再有内存申请请求时,都会返回错误。

三、OOM工作过程

内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参考内核源代码linux/mm/oom_kill.c,当系统内存不足的时候,out_of_memory()被触发,然后调用select_bad_process()选择进程杀,再通过oom_kill_process()杀掉进程。

OOM-killer策略就是发生OOM时,系统会选择一些进程来杀掉以释放一部分缓存资源。 
Linux下每个进程都有一个OOM权重,在/proc/<pid>/oom_adj里面,取值是-17到+15(为-17此进程不会被杀掉),取值越高,越容易被杀掉。
最终OOM-Killer是通过/proc/<pid>/oom_score这个值来决定哪个进程被杀死。这个值是系统综合进程的内存消耗量、CPU时间(utime+stime)、存活时间(utime - start_time)和oom_adj计算出的,消耗内存越多oom_score值越高,存活时间越长值越低。另外,Linux在计算进程的内存消耗的时候,会将子进程所耗内存的一半算到父进程中。
总之,OOM-Killer策略是:损失最少的工作,释放最大的内存;同时不伤及无辜的用了很大内存的进程,并且杀掉的进程数尽量少。

四、内核源码出处

 out_of_memory()函数

__alloc_pages  //内存分配时调用

    |-->__alloc_pages_nodemask

       |--> __alloc_pages_slowpath

           |--> __alloc_pages_may_oom

              | --> out_of_memory   //触发

check_panic_on_oom

void check_panic_on_oom(enum oom_constraint constraint, gfp_t gfp_mask,
            int order, const nodemask_t *nodemask)
{
    if (likely(!sysctl_panic_on_oom))
        return;
    if (sysctl_panic_on_oom != 2) {
        if (constraint != CONSTRAINT_NONE)
            return;                                                 

 killer
    }
    dump_header(NULL, gfp_mask, order, NULL, nodemask);
    panic("Out of memory: %s panic_on_oom is enabled\n",
        sysctl_panic_on_oom == 2 ? "compulsory" : "system-wide");

 select_bad_process

/*
* Simple selection loop. We choose the process with the highest number of
 * 'points'. In case scan was aborted, oc->chosen is set to -1.
 */
static void select_bad_process(struct oom_control *oc)
{
    if (is_memcg_oom(oc))
        mem_cgroup_scan_tasks(oc->memcg, oom_evaluate_task, oc);
    else {
        struct task_struct *p;

        rcu_read_lock();
        for_each_process(p)
            if (oom_evaluate_task(p, oc))
                break;
        rcu_read_unlock();
    }

    oc->chosen_points = oc->chosen_points * 1000 / oc->totalpages;

 oom_kill_process

static void oom_kill_process(struct oom_control *oc, const char *message)
{
    struct task_struct *victim = oc->chosen;
    struct mem_cgroup *oom_group;
    static DEFINE_RATELIMIT_STATE(oom_rs, DEFAULT_RATELIMIT_INTERVAL,
                          DEFAULT_RATELIMIT_BURST);

    /*
     * If the task is already exiting, don't alarm the sysadmin or kill
     * its children or threads, just give it access to memory reserves
     * so it can die quickly
     */
    task_lock(victim);
    if (task_will_free_mem(victim)) {
        mark_oom_victim(victim);
        wake_oom_reaper(victim);
        task_unlock(victim);
        put_task_struct(victim);
        return;
    }
    task_unlock(victim);

    if (__ratelimit(&oom_rs))
        dump_header(oc, victim);

    /*
     * Do we need to kill the entire memory cgroup?
     * Or even one of the ancestor memory cgroups?
     * Check this out before killing the victim task.
     */
    oom_group = mem_cgroup_get_oom_group(victim, oc->memcg);

    __oom_kill_process(victim, message);

    /*
     * If necessary, kill all tasks in the selected memory cgroup.
     */
    if (oom_group) {
        mem_cgroup_print_oom_group(oom_group);
        mem_cgroup_scan_tasks(oom_group, oom_kill_memcg_member,
                      (void*)message);
        mem_cgroup_put(oom_group);
    }
}
}文章来源地址https://www.toymoban.com/news/detail-787179.html

到了这里,关于LINUX常见问题之oom kill的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux常见问题-打deb包流程

    Deb打包目的:将程序打包成.deb格式是为了在Debian和Ubuntu等基于Debian的Linux发行版上进行方便的安装和管理。以下是一个简要的流程,以一个输出 \\\"Hello World\\\" 的C++程序为例。 确保你的系统安装了构建工具,如g++(用于编译C++程序)和dpkg-deb(用于创建.deb文件)。在项目目录中,

    2024年02月14日
    浏览(26)
  • linux查看WWN号及常见问题解决

    要查看CentOS 6.7版本的WWN号,可以执行以下步骤: 1.确保已经连接了存储设备。 2.在终端中输入命令:lsscsi,然后按 Enter 键。该命令会显示已连接的存储设备的信息。 3.找到你想查看WWN号的存储设备,并查看其 WWN 号。WWN 号通常在类似于[X:X:X:X]格式的信息中给出,其中 X 是一

    2024年02月05日
    浏览(21)
  • 常见Linux 命令,可以解决日常99%的问题

    1、基本命令 2、关机 3、文件和目录 4、文件搜索 5、挂载一个文件系统 6、磁盘空间 7、用户和群组 8、文件的权限 9、文件的特殊属性 使用 “+” 设置权限,使用 “-” 用于取消 10、打包和压缩文件 11、RPM 包 (Fedora, Redhat及类似系统) 12、YUM 软件包升级器 (Fedora, RedHat及类

    2024年01月22日
    浏览(31)
  • Linux 服务器文件名乱码常见问题

    在 Linux 服务器中,文件名乱码是一个常见的问题,特别是当涉及到多语言字符集时。这可能导致文件名显示异常,无法正确识别和处理文件。本文将介绍一些常见的文件名乱码问题以及相应的解决方法。 字符集问题 文件名乱码的一个常见原因是字符集不匹配。当文件名包含

    2024年02月05日
    浏览(43)
  • Linux--使用VM创建虚拟机步骤及常见问题

    1.1 安装linux步骤   此处选择安装CentOS 7 64位            硬件配置完毕后 ,直接点关闭就OK,最后点完成 创建完毕后是以上界面,点击CentOS 7first 开启此虚拟机即可(启动需要一些时间,稍等片刻...) 接下来就会出现以下界面,选择你要使用的语言   点击安装位置,设置默认

    2024年02月07日
    浏览(29)
  • 《基于Linux物联网综合项目》常见问题汇总fae

    关于该课程说明 1)本课程目标 通过web浏览器访问服务器,实现登录、注册、数据库操作、远程操控硬件、采集环境信息、远程监控、拍照、图片显示等功能。 将单片机、linux、html、摄像头、数据库等知识点融入到一个项目中。 2)什么群体适合学习该课程? 急需嵌入式项目

    2024年02月10日
    浏览(35)
  • linux安装mysql-8.0.33正确方式及常见问题

    目录 获取mysql下载地址链接  解压安装包  复制文件到安装目录  添加用户和用户属组修改权限  创建存储数据的文件夹/usr/local/mysql 初始化安装 修改配置文件  创建日志文件并赋予对应权限  启动成功​编辑 创建软链接 之前安装过mysql,时间比较长忘记安装步骤了今天就记

    2024年02月12日
    浏览(30)
  • 【Linux】Ubuntu基本使用与配置, 以及常见问题汇总(一)

      大学期间,感觉很多时候学习课外知识都是被推着往前走,很多内容并没有深入去学习,知识的记录受限于所学比较片面,如今渐渐意识到似乎并没有建立起相关知识的体系架构,缺乏一个系统学习并整理的过程。本文将以 Ubuntu系统 为例,来整理一些Linux使用过程中常用

    2024年02月15日
    浏览(31)
  • MYSQL 8.0.32linux 本地安装步骤及常见问题

    1.下载安装包,根据各自系统选择对应系统版本及mysql安装包MySQL :: Download MySQL Community Server, 服务器可联网可用​wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz  2.上传安装包至linux 目录下,常用/usr/local/mysql  3. 解压安装包:tar -xvf /安装包目录/安装包

    2024年02月09日
    浏览(33)
  • Linux ❀ Yum源安装RPM包常见问题与解决方法

    404错误多为yum源无法访问导致,检查yum仓库是否配置正确,同时确认baseurl连通性。 yum install为安装包命令,使用yum安装软件包时触发rpm包缺失、进程锁定、未完成事务等多个场景均会导致安装失败错误发生,本章节主要讲述常见安装错误及其解决方法。 使用yum安装软件包时

    2024年02月14日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包