oom_score_adj

作者: 欧阳_z | 来源:发表于2020-09-09 21:00 被阅读0次

    1、在 linux 系统下,内存不足会触发 OOM killer 去杀进程
    下面模拟一下,几秒之后显示被Killed了:

    $ cat oom.c
    #include <stdlib.h>
    #include <stdio.h>
    
    #define BYTES (8 * 1024 * 1024)
    
    int main(void) 
    {
        printf("hello OOM \n");
        while(1)
        {
            char *p = malloc(BYTES);
            if (p == NULL)
            {
                return -1;
            }
        }
        return 0;
    }
    $ gcc oom.c 
    $ ./a.out 
    hello OOM 
    Killed
    $ 
    

    dmesg 命令可以看到相关 log:

    a.out invoked oom-killer: gfp_mask=0x26084c0, order=0, oom_score_adj=0
    Out of memory: Kill process 97843 (a.out) score 835 or sacrifice child
    

    2、oom_score_adj
    上面打印了oom_score_adj=0以及score 835,OOM killer 给进程打分,把 oom_score 最大的进程先杀死。
    打分主要有两部分组成:
    一是系统根据该进程的内存占用情况打分,进程的内存开销是变化的,所以该值也会动态变化。
    二是用户可以设置的 oom_score_adj,范围是 -10001000,定义在:
    https://elixir.bootlin.com/linux/v5.0/source/include/uapi/linux/oom.h#L9

    /*
     * /proc/<pid>/oom_score_adj set to OOM_SCORE_ADJ_MIN disables oom killing for
     * pid.
     */
    #define OOM_SCORE_ADJ_MIN   (-1000)
    #define OOM_SCORE_ADJ_MAX   1000
    

    如果用户将该进程的 oom_score_adj 设定成 -1000,表示禁止OOM killer 杀死该进程(代码在 https://elixir.bootlin.com/linux/v5.0/source/mm/oom_kill.c#L222 )。比如 sshd 等非常重要的服务可以配置为 -1000
    如果设置为负数,表示分数会打一定的折扣,
    如果设置为正数,分数会增加,可以优先杀死该进程,
    如果设置为0 ,表示用户不调整分数,0 是默认值。

    3、测试设置 oom_score_adjoom_score 的影响

    #include <stdlib.h>
    #include <stdio.h>
    
    #define BYTES (8 * 1024 * 1024)
    #define N (10240)
    
    int main(void) 
    {
        printf("hello OOM \n");
        int i;
        for (i = 0; i < N; i++)
        {
            char *p = malloc(BYTES);
            if (p == NULL)
            {
                return -1;
            }
        }
        printf("while... \n");
        while(1);
        return 0;
    }
    

    下面是初始的分数:

    $ cat /proc/$(pidof a.out)/oom_score_adj
    0
    $ cat /proc/$(pidof a.out)/oom_score
    62
    

    下面修改 oom_score_adjoom_score 也随之发生了变化:

    $ sudo sh -c "echo -50 > /proc/$(pidof a.out)/oom_score_adj"
    $ cat /proc/$(pidof a.out)/oom_score_adj
    -50
    $ cat /proc/$(pidof a.out)/oom_score
    12
    $ sudo sh -c "echo -60 > /proc/$(pidof a.out)/oom_score_adj"
    $ cat /proc/$(pidof a.out)/oom_score_adj
    -60
    $ cat /proc/$(pidof a.out)/oom_score
    2
    $ sudo sh -c "echo -500 > /proc/$(pidof a.out)/oom_score_adj"
    $ cat /proc/$(pidof a.out)/oom_score_adj
    -500
    $ cat /proc/$(pidof a.out)/oom_score
    0
    

    4、测试设置 oom_score_adj 设置为-1000 对系统的影响
    如果把一个无限申请内存的进程设置为-1000,会发生什么呢:

    $ sudo sh -c "echo -1000 > /proc/$(pidof a.out)/oom_score_adj"
    
    $ dmesg | grep "Out of memory"
    Out of memory: Kill process 1000 (mysqld) score 67 or sacrifice child
    Out of memory: Kill process 891 (vmhgfs-fuse) score 1 or sacrifice child
    Out of memory: Kill process 321 (systemd-journal) score 1 or sacrifice child
    Out of memory: Kill process 1052 ((sd-pam)) score 1 or sacrifice child
    Out of memory: Kill process 1072 (bash) score 0 or sacrifice child
    

    因为 bash 挂了,所以 a.out 也挂了。
    如果 ./a.out & 在后台运行,就可以看到用更多进程的 score 是 0 仍然挂掉了,比如 sshd、dhclient、systemd-logind、systemd-timesyn、dbus-daemon 等,所以设置错误的 oom_score_adj 后果比较严重。

    相关文章

      网友评论

        本文标题:oom_score_adj

        本文链接:https://www.haomeiwen.com/subject/fxfyektx.html