Open arthur-zhang opened 3 years ago
有文件背景的内存页;例如: 代码段、mmap读写的文件等
没有文件背景的内存页(匿名内存页);例如:栈、malloc的内存。内存紧张的时候,可以交换到swapfile或者硬盘的swap分区。(给没有文件背景的内存找个存放的地方)
基于性能考虑,服务器端建议关闭(时延敏感建议关闭,不敏感可以不关闭,可以延缓OOM)。
(开关swap命令:swapoff -a; swapon -a;vm.swappiness 设置倾向于回收有文件背景的内存页还是匿名文件页)
源码位置:mm/oom_kill.c
oom score决定因素:
实验1环境:
结果:第一个calloc进程申请成功;第二个calloc进程申请失败;
实验2环境:
结果:第一个calloc进程申请成功;第二个calloc进程申请成功,且第一个calloc进程被杀死;
实验3环境:
结果:前3个calloc 进程正常执行;第四个calloc进程申请内存失败;
如果vm.overcommit_memory=1。则第四个calloc进程申请成功,且前三个calloc进程中有一个被杀死
实验4环境:
结果:进程被内核杀死
实验5环境:
结果:申请内存失败
swapoff -a 关闭swap, 将不再使用内存和磁盘文件交换
swapon -a 开启swap
sar 性能监控命令 https://shockerli.net/post/linux-tool-sar/
sar -r -S 1 查看内存变化
#include<stdio.h>
#include<stdlib.h>
#define GB (1024 * 1024 * 1024)
#define MB (1024 * 1024)
int main (){
size_t t = 1 * GB;
char *array = (char *)calloc(1,t);
if(array == NULL){
printf("ERROR allocation fail !!!!");
getchar();
}else{
printf("success %p\n",array);
getchar();
free(array);
}
return 0;
}
系统内存:1.8G 空闲:1.4G
[root@centos-7 oom]# sysctl -w vm.overcommit_memory=0
vm.overcommit_memory = 0
[root@centos-7 oom]# swapoff -a
执行上面的demo,分配内存成功
[root@centos-7 oom]# ./a.out
success 0x7f9999a97010
开启另外的会话窗口执行上面的代码,分配失败
[parallels@centos-7 oom]$ ./a.out
ERROR allocation fail !!!!
系统内存:1.8G 空闲:1.4G
[root@centos-7 oom]# sysctl -w vm.overcommit_memory=0
vm.overcommit_memory = 1
[root@centos-7 oom]# swapoff -a
执行上面的demo,分配内存成功
会话窗口1:
[root@centos-7 oom]# ./a.out
success 0x7f9999a97010
已杀死
开启另外的会话窗口执行上面的代码,分配成功,但是会发现会话窗口1的进程 被杀死
会话窗口2:
[parallels@centos-7 oom]$ ./a.out
success 0x7efe33981010
系统内存:1.8G 空闲:1.4G
[root@centos-7 oom]# sysctl -w vm.overcommit_memory=1
vm.overcommit_memory = 0
[root@centos-7 oom]# swapon -a
开启4个会话窗口分别执行上面的demo,前3个显示分配内存成功
前3个会话窗口:
[root@centos-7 oom]# ./a.out
success 0x7f9999a97010
开启第4个会话窗口,显示分配失败, 如下图内存变化
会话窗口4:
[parallels@centos-7 oom]$ ./a.out
success 0x7efe33981010
1. vm.overcommit_memory = 0 和 vm.overcommit_memory = 1 的区别,就是当 = 1的时候在内存不足的时候,会杀掉其他的进程用来释放内存,但是 当 = 0的时候,会在内存分配不足的时候,返回NULL,分配失败,不会干掉其他的进程
2. 当swap关闭的时候,内存不足会直接分配失败,但是当swap开启的时候会将swap区使用完才会分配失败
3. 一定要free,不然的话直接退出函数,内存会释放不掉
vm.swappiness :决定优先回收File-backed-page,还是 Anonymous Page
vm.min_free_kbytes
sysctl -w vm.overcommit_memory=1
swapoff -a
#include<stdio.h>
#include<stdlib.h>
#define GB (1024 * 1024 * 1024)
#define MB (1024 * 1024)
int main(){
size_t t = 3L * GB;
char *array = (char *)malloc(t);
int i;
for(i = 0; i < t; i++){
if(i % (100 * MB) == 0){
printf("allocation %d MB.....\n",(i/MB) );
}
array[i] = 'a';
}
free(array);
getchar();
return 0;
}
dmesg -T
决定进程杀死哪一个进程的代码逻辑被称为OOM Kiiler, 会给每个进程打分,得分被称为oom_score, Linux内存紧张的时候 OOM killer会遍历所有的进程,找到最高分数的进程将其杀掉
查看 com_score的值
cat /proc/pid/oom_score
oom_score的计算逻辑在oom_kill.c 文件中
sudo -c "echo 500 > oom_score_obj"
- 进程rss,pagetable, swap区域的大小
- root特权用户进程减去3%的分数
- 加上oom_score_obj
- 范围 -1000 ~ 1000
- 查看 cat /proc/$(pidof a.out)/oom_score_adj
- 只能设置为改进程设置的历史oom_score_adj的最小值
top :
e: MB 显示
M: 按照内存排序
(1)swap分区 Linux内核为了提高读写效率与速度,会将文件在内存中进行缓存,当系统的物理内存不够用的时候,就需要将物理内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间被临时保存到Swap空间中,等到那些程序要运行时,再从Swap分区中恢复保存的数据到内存中 (2)设置 使用free命令可以查看swap分区的大小 swapoff -a 关闭swap swapon -a 打开swap (3)开启swap后,需要进行swap分区交换,会影响系统性能,所以对于性能要求比较高的,例如http服务器等,可以选择关闭,对于对性能要求不高,或者需要保证程序可用的,可以开启swap分区 (4)命令 sar 性能监控 dmesg -T 查看内核日志 (5)OOM killer策略 linux系统会为每个进程分配一个oom_score,这个值跟内存大小有关系,也跟oom_score_adj有关系,可以通过修改oom_score_adj来修改进程的oom_score,当系统内存不足时,会优先清理oom_score分数比较大的进程
主要内容: