Linux Out of Memory
OOM 基础
Linux有一个特性:OOM Killer,一个保护机制,用于避免在内存不足的时候不至于出现严重问题,把一些无关的进程优先杀掉,即在内存严重不足时,系统为了继续运转,内核会挑选一个进程,将其杀掉,以释放内存,缓解内存不足情况,不过这种保护是有限的,不能完全的保护进程的运行。log 文件 /var/log/messages 。
Out of Memory: Killed process [PID] [process name].
内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参考内核源代码 linux/mm/oom_kill.c,当系统内存不足的时候,out_of_memory() 被触发,然后调用 select_bad_process() 选择一个 “bad” 进程杀掉,如何判断和选择一个 “bad” 进程呢,总不能随机选吧?挑选的过程由 oom_badness() 决定,挑选的算法和想法都很简单很朴实:最 bad 的那个进程就是那个最占用内存的进程。但是程序只申请内存不做映射使用不会触发OOM,只有映射后的内存不足才会触发OOM。
RSS 是常驻内存集(Resident Set Size),表示该进程分配的内存大小。
VSZ 包括进程可以访问的所有内存,包括进入交换分区的内容,以及共享库占用的内存。这里分配的内存并没有做实际的物理映射,只有在RSS中的内存大小才是真实分配物理内存的大小。
[root@ip-172-16-1-245 ~]# ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.7 186216 13512 ? Ss Oct30 0:55 /usr/lib/systemd/
OOM 日志
Aug 11 10:06:53 ip-172-16-1-245 kernel: oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=/,mems_allowed=0,global_oom,task_memcg=/user.slice/user-1000.slice/session-1.scope,task=node,pid=1559,uid=1000Aug 11 10:06:53 ip-172-16-1-245 kernel: Out of memory: Killed process 1559 (node) total-vm:834880kB, anon-rss:62436kB, file-rss:33956kB, shmem-rss:0kB, UID:1000
Aug 11 10:06:53 ip-172-16-1-245 kernel: oom_reaper: reaped process 1559 (node), now anon-rss:0kB, file-rss:0kB, shmem-rss:0kB
Aug 11 10:06:57 ip-172-16-1-245 systemd-logind[721]: New session 4 of user ec2-user.
Aug 11 10:06:57 ip-172-16-1-245 systemd[1]: Started Session 4 of user ec2-user.
对于进程是否会被Kill,进程本身会有一个值,默认是0,会优先kill 值为0 的进程。ssh 为了保证登录是 -1000
[root@ip-172-16-1-245 ~]# ps -ef | grep sshd
root 489873 1 0 03:16 ? 00:00:00 sshd: root [priv]
root 489876 489873 0 03:16 ? 00:00:01 sshd: root@notty
root 530510 1 0 03:30 ? 00:00:00 /usr/sbin/sshd -D -oCiphers=aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes256-cbc,aes128-gcm@openssh.com,aes128-ctr,aes128-cbc -oMACs=hmac-sha2-256-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha1,umac-128@openssh.com,hmac-sha2-512 -oGSSAPIKexAlgorithms=gss-curve25519-sha256-,gss-nistp256-sha256-,gss-group14-sha256-,gss-group16-sha512-,gss-gex-sha1-,gss-group14-sha1- -oKexAlgorithms=curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1 -oHostKeyAlgorithms=ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com,ssh-rsa,ssh-rsa-cert-v01@openssh.com -oPubkeyAcceptedKeyTypes=ecdsa-sha2-nistp256,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com,ssh-rsa,ssh-rsa-cert-v01@openssh.com -oCASignatureAlgorithms=ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,rsa-sha2-256,rsa-sha2-512,ssh-rsa
root 576884 490115 0 08:25 pts/1 00:00:00 grep --color=auto sshd
[root@ip-172-16-1-245 ~]# cat /proc/530510/oom_score_adj
-1000
触发OOM方式
echo f > /proc/sysrq-trigger
https://github.com/torvalds/linux/blob/master/mm/oom_kill.c
https://access.redhat.com/solutions/2612861
Overcommit_memory
overcommit_memory是一个内核对内存分配的一种策略。针对内存每次 malloc,并不针对每个应用程序来看。
overcommit_memory=0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
overcommit_memory=1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
overcommit_memory=2, 表示内核允许分配超过所有物理内存和交换空间总和的内存
[root@ip-172-16-1-245 ~]# sysctl -a | grep overcommit
vm.nr_overcommit_hugepages = 0
vm.overcommit_kbytes = 0
vm.overcommit_memory = 0
vm.overcommit_ratio = 50
https://access.redhat.com/solutions/68612
mcelog 可以查看内存的校验错误。翻译成人可以看懂的内容
https://access.redhat.com/solutions/18723
Segmentation fault
应用申请的内存空间小,但是用的多。数组越界
/var/log/messages
Cannot allocate memory
- 用户的进程数量到了上线, ulimit 限制
- 连续内存页不足
/proc/buddyinfo 从左到右代表 2的几次幂,如果不够的话就会反内存碎片。
http://underpop.online.fr/l/linux/en/centos/s2-proc-buddyinfo.htm
[root@ip-172-16-1-245 ~]# cat /proc/buddyinfo
Node 0, zone DMA 11 10 15 12 20 13 5 6 2 2 0
Node 0, zone DMA32 1550 1425 793 481 330 188 26 22 11 68 16
https://www.supportsages.com/what-is-proc-buddyinfo/
https://www.kernel.org/doc/
https://www.kernel.org/doc/gorman/html/understand/understand005.html