1. Overcommit策略 和 OOM killer
Linux中malloc返回非空指针,并不一定意味着指向的内存就是可用的,Linux下允许程序申请比系统可用内存更多的内存,这个特性叫Overcommit。
这样做是出于优化系统考虑,因为不是所有的程序申请了内存就立刻使用的,当你使用的时候说不定系统已经回收了一些资源了。
Linux下有3种Overcommit的策略(参考内核文档:vm/overcommit-accounting),可以在/proc/sys/vm/overcommit_memory配置。取0,1和2三个值,默认是0。
- 0:启发式策略,比较严重的Overcommit将不能得逞,比如你突然申请了128TB的内存。而轻微的Overcommit将被允许。另外,root能Overcommit的值比普通用户要稍微多些。
- 1:永远允许Overcommit,这种策略适合那些不能承受内存分配失败的应用,比如某些科学计算应用。
- 2:永远禁止Overcommit,在这个情况下,系统所能分配的内存不会超过swap+RAM*系数(/proc/sys/vm/overcmmit_ratio,默认50%,你可以调整),如果这么多资源已经用光,那么后面任何尝试申请内存的行为都会返回错误,这通常意味着此时没法运行任何新程序。
Overcommit导致的问题,如果申请的内存多余系统的RAM+swap,当真正使用的内存也超过RAM+swap时,内存不足怎么处理?
linux会启动OOM killer,挑选进程杀死,释放内存,来解决内存不足的问题;
OOM killer
OOM(out-of-memory) killer是通过/proc//oom_score这个值来决定哪个进程被干掉的。
这个值是系统综合进程的内存消耗量、CPU时间(utime + stime)、存活时间(uptime - start time)和oom_adj计算出的,消耗内存越多分越高,存活时间越长分越低。
总之,总的策略是:损失最少的工作,释放最大的内存同时不伤及无辜的用了很大内存的进程,并且杀掉的进程数尽量少。
如何排查oom
日志:/var/log/messages
通过分析日志关键词,思路大致为:先确定当时进程的内存情况,再确定是swap不足还是物理内存不足。
Sep 19 14:58:00 test08 kernel: [ pid ] uid tgid total_vm rss cpu oom_adj oom_score_adj name
Sep 19 14:58:00 test08 kernel: [18871] 0 18871 502855 5227 0 0 0 mc-exe
Sep 19 14:58:00 test08 kernel: [18872] 0 18872 1842475 148013 1 0 0 mc-exe
Sep 19 14:58:00 test08 kernel: [18873] 0 18873 502855 3176 1 0 0 mc-exe
#这一条能确定被kill的进程pid,当时的score值(该值上边有介绍)
Sep 19 14:58:00 test08 kernel: Out of memory: Kill process 18872 (mc) score 43 or sacrifice child
#被kill时候的内存情况: total-vm:进程虚拟内存大小,rss:常驻内存集,实际使用的内存,包括共享内存,anon-rss:实际已经分配出去的内存块(包括分配的很已经使用的),file-rss:rss内存块映射到设备和文件
Sep 19 14:58:00 test08 kernel: Killed process 18872, UID 0, (mc) total-vm:7369900kB, anon-rss:558044kB, file-rss:34008kB
...
...
#gfp_mask=0x280da的低2位bit是2,表示此次申请内存是从Normal空间内存块申请内存,
Sep 18 09:19:15 test08 kernel: mc invoked oom-killer: gfp_mask=0x280da, order=0, oom_adj=0, oom_score_adj=0
#上面的free表示Normal空间的空闲内存,min、low、high是三个阈值, 当free小于min时,会触发OOM
...
...
#当时的内存状态
Sep 19 14:58:00 test08 kernel: Free swap = 3000364kB
Sep 19 14:58:00 test08 kernel: Total swap = 4194300kB
Sep 19 14:58:00 test08 kernel: 1048575 pages RAM
Sep 19 14:58:00 test08 kernel: 67932 pages reserved
Sep 19 14:58:00 test08 kernel: 275848 pages shared
Sep 19 14:58:00 test08 kernel: 907335 pages non-shared
=
参考:https://blog.csdn.net/sbjiesbjie/article/details/52624467