什么是Linux Overcommit和OOM
overcommit_memory是一个内核对内存分配的一种策略,它有三个可选值:0、1、2。
0. 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,
并把错误返回给应用进程。
1. 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2. 表示内核允许分配超过所有物理内存和交换空间总和的内存。
Linux对大部分申请内存的请求都回复"yes",以便能跑更多更大的程序。因为申请内存后,并不会马上使用内存。
这种技术叫做 Overcommit。
当linux发现内存不足时,会发生OOM killer(OOM=out-of-memory)。它会选择杀死一些进程
(用户态进程,不是内核线程),以便释放内存。
例如Linux下发现有如下报错信息,则说明系统发生了OOM killer
# dmesg | grep redis | grep "oom-killer"
redis-server invoked oom-killer: gfp_mask=0x280da, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0x200da, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0x200da, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0x200da, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0x280da, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0x200da, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0x200da, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0xd0, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0x280da, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0x280da, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0xd0, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0x280da, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0xd0, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0xd0, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0xd0, order=0, oom_adj=0, oom_score_adj=0
redis-server invoked oom-killer: gfp_mask=0x280da, order=0, oom_adj=0, oom_score_adj=0
当oom-killer发生时,linux会选择杀死该进程,例如:
Out of memory: Kill process 21809 (redis-server) score 951 or sacrifice child
Killed process 21809, UID 0, (redis-server) total-vm:33466920kB, anon-rss:32324096kB, file-rss:100kB
具体杀死哪个进程取决于选择进程的函数,选择进程的函数是oom_badness函数(在mm/oom_kill.c中),该函数
会计算每个进程的点数(0~1000)。
点数越高,这个进程越有可能被杀死。每个进程的点数跟oom_score_adj有关,而且 oom_score_adj可以被
设置(-1000最低,1000最高)。
理解memory overcommit的关键:commit(或overcommit)针对的是内存申请,内存申请不等于内存分配,内存
只在实际用到的时候才分配。
备注:
如何修改Linux vm.overcommit_memory的值,可用的方法有以下三种:
1).以root身份登录Linux,编辑/etc/sysctl.conf ,改vm.overcommit_memory=1,然后sysctl -p使配置文件生效
2).sysctl vm.overcommit_memory=1
3).echo 1 > /proc/sys/vm/overcommit_memory