• 认真理解 oom killer 备忘


    最近项目测试,发现一个oom killer问题,所以搜集了一些文章,理解并做记录。

    现象:做性能测试时,程序自己退出,记录"killed"日志。查了下syslog发现详细记录了问题原因,应用程序进程占满了自己的虚拟地址空间,没法再分配内存了。后来从新做,pmap了一下,结果果真很吓人。

    原因:与测试组测试程序同学没沟通好,导致每条链接申请的内存不会释放。

    原理:

      OOM发生的条件一般有两个:

      1. VM里面分配不出更多的page

      2. 用户地址空间不足

     
      按照资料,找到了oom_kill.c​文件中的out_of_memory() pagefault_out_of_memory()及调用函数__out_of_memory()
      转换思维,要自己设计这样的功能,无碍乎也是 ”找到一个需要被kill的进程“ ”杀掉要被kill的进程“,按照步骤来:
      1:”找到一个需要被kill的进程“
        策略:跳过kernel thread、没有占用mem的进程、INIT进程、以及被设置为OOM_DISABLE的进程(附1),检测其它进程得到一个得分。
        得分:影响因素有以下几个:     
            a) score起始为该进程占用的total_vm;
                        points = mm->total_vm;
     
            b) 如果该进程有子进程,子进程独自占用的total_vm/2加到本进程score;
                        points += child->mm->total_vm/2 + 1;
     
            c) score和进程的cpu_time以及run_time成反比;(实现方式着重记录)
                         points /= int_sqrt(cpu_time);
                         points /= int_sqrt(int_sqrt(run_time));
     
            d) nice大于0的进程,score翻倍;
                        if (task_nice(p) > 0) points *= 2;
     
            e) 对设置了超级权限的进程和直接磁盘交互的进程降低score;
                        if (CAP_SYS_ADMIN | CAP_SYS_RESOURCE | CAP_SYS_RAWIO) points /= 4;
     
            f) 如果和current进程在内存上没有交集的进程降低score;
                        if (!has_intersects_mems_allowed(p)) points /= 8;
     
            g) 最后是根据该进程的oom_adj计算最终的score;
                        points <<= abs(oom_adj);
     
      2:“杀掉要被kill的进程”
        方法:发出一个SIGKILL信号
     
    OOM 策略调整:
      
      可以通过下面两个参数来配置OOM策略:
        /proc/sys/vm/overcommit_memory 
        /proc/sys/vm/overcommit_ratio
      overcommit_memory取值为[0-2]:
        0:表示按启发模式进行overcommit(可以提交超过物理内存大小的alloc page申请),也是默认的设置;
        1:表示总是允许overcommit,这种模式最容易触发oom;
        2:表示不能overcommit。这种模式下,最大的User Space限制在:SS + RAM*(r/100),SS是swap大小,r就是overcommit_ratio设置的值,范围为:[0-100];
     
    附1:可以通过设置进程的 /proc/<pid>/oom_adj ​来调整oom_adj的值,oom_adj范围是[-17, 15],值越大越容易被oom kill掉,设为OOM_DISABLE(-17)的进程不会被oom。
      
  • 相关阅读:
    在一个字符串中找到第一个只出现一次的字符
    声明数组变量/// 计算所有元素的总和/打印所有元素总和/输出/foreach循环/数组作为函数的参数/调用printArray方法打印
    intellij idea 如何更改编辑器文本字体和大小
    称砝码算法//输入与算法分开
    invalid types 'int[int]' for array subscript// EOF 输入多组数据//如何键盘输入EOF
    scanf和gets的差别
    输入3行字符串/定义flag/while/字符串后要加空格符
    ‘'的单引号/输入字符串/输出单个字符
    窗口迅速关闭的解决办法/scanf/if/for/break
    【笔记】【VSCode】Windows下VSCode编译调试c/c++
  • 原文地址:https://www.cnblogs.com/claresun/p/3803158.html
Copyright © 2020-2023  润新知