cgroup可以对一个进程或者一组进程使用的资源进行限制,可以限制的资源包括cpu、memory、io等。其中memory可以对内存资源进行限制,比如我们限制进程所能使用的内存最大是1G,那么当进程已经使用了1G的内存的时候,这个时候进程再申请内存会怎么样呢 ?
内存使用超过限制的时候有如下两种结果:
(1)默认情况下,内存使用超过限制,会oom(out of memory),oom的时候系统会使用SIGKILL信号将进程杀死。
(2)cgroup中也可以进行配置,oom的时候不杀死进程,此时进程进入D状态。D状态是一种睡眠态,不同于普通的睡眠态,普通的睡眠态可以被资源唤醒,也可以被信号唤醒,而D状态只能被资源唤醒,也就是说只有有内存可以使用的时候进程才会被唤醒。
参考:
1 实验代码
如下代码,每秒申请4KB的内存,内存不释放,这样随着时间的推移,进程所占有的内存就会越来越多。在代码中 p[0]=1;和p[4000]=1;写内存,之所以写内存,是因为使用malloc() 申请的内存是懒加载的,malloc()之后,内存并没有真正分配,只有写内存的时候,操作系统才会真正分配内存。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main() {
int count = 0;
while (1) {
printf("before malloc\n");
char *p = (char *)malloc(4096);
if (p) {
p[0] = 1;
p[4000] = 1;
} else {
printf("p is nullptr\n");
}
count++;
printf("malloced memory %dKB\n", 4 * count);
sleep(1);
}
return 0;
}
2 cgroup操作
cgroup memory 的操作在如下目录进行。
/sys/fs/cgroup/memory
在该目录下使用mkdir创建一个文件夹就相当于创建了一个cgroup,如下图所示,创建了一个 memory的controller,名字为hello。
在cgroup文件系统下创建的文件夹,并不是一个普通的空的文件夹,而是默认会生成如下的文件,这些文件也不是磁盘文件,而是可以用于配置cgroup的参数。linux内核的功能,通过文件的形式提供给用户态来使用,体现了linux“一切皆文件”的设计思想。
参数 | 说明 |
memory.limit_in_bytes | 进程可以使用的内存的最大值 |
memory.memsw.limit_in_bytes | 进程可以使用的内存和swap之和的最大值。 swap的意思是,当内存不够用的时候,将内存交换到磁盘上,使用LRU算法,将需要“淘汰”的内存交换到磁盘上,使用这块内存的时候再将数据从磁盘加载到内存。 memory.memsw.limit_in_bytes不能小于memory.limit_in_bytes。 对于加到cgroup中的进程,进程使用的内存总量超过memory.memsw.limit_in_bytes才算超过限制。默认情况下memory.memsw.limit_in_bytes是很大的,如果只配置了memory.limit_in_bytes,那么内存消耗完之后,便会使用swap,观察不到oom的现象。 |
memory.oom_control | oom开关,默认情况下当使用内存超限的时候,系统会将进程杀死;通过这个配置文件可以将oom关闭,当进程使用的内存超限的时候,进程不会被杀死,而是会切换为D状态。 |
memory.oom_control配置文件oom_kill_disable默认是0,也就是oom没有关闭,当使用的内存超限的时候,便会把进程杀死。如果使用如下的命令将配置设置为1,那么当内存超限时,进程不会被杀死,而是会进入D状态。
echo 1 > memory.oom_control
3 测试过程
3.1oom开启
默认情况下oom_kill_disable为0,说明oom没有disable,也就是enable的,即oom是开启的。
实验代码编译运行,可以看到进程号是3299。
设置memory.limit_in_bytes为1048576,也就是内存限制为1MB,然后将进程加到cgroup中。
可以看到当申请1044KB的时候,进程被kill了。
3.2 oom disable
通过echo 1 > memory.oom_control来禁止oom。oom_kill是oom计数,即发生过几次oom,系统将进程kill的次数。
可以看到,当申请1052KB的时候,进程就不在运行了,但是这个时候,进程也没有杀死。
查看memory.oom_controol,其中under_oom显示为1,说明现在处于oom状态。
查看进程当前状态为D状态。
进程的内核栈如下。
此时如果通过配置将允许的内存配置改大,有了新的内存资源,这个时候进程会从D状态切换出来会继续运行。如果修改配置,比当前已经使用的内存还小,那么设置不成功,返回错误。
标签:oom,使用,内存,cgroup,memory,进程,怎样 From: https://blog.csdn.net/weixin_38184628/article/details/140224576