cgroup限制内存

news2024/10/6 4:05:28

首先简单介绍下cgroup限制cpu的使用率,写一段代码如下:

#include <stdio.h>
#include <pthread.h>


int main()
{
int i = 0;
for(;;)i++;
return 0;
}

很明显,这里面是单核拉满,然后top看下进程的cpu使用率,如下所示:
在这里插入图片描述
很明显,截图中的cpu使用率是正常的,现在限制cpu的使用率。
进入到目录/sys/fs/cgroup/cpu,创建目录cputest,进入到cputest,执行命令:
echo 200000 > cpu.cfs_quota_us
echo 1000000 > cpu.cfs_period_us
echo 25120 > tasks

这三句话中,前两句是限制cpu使用率为20%,第三句是设置进程,设置后的截图如下:
在这里插入图片描述
很明显,截图符合咱们的预期。

现在来限制内存:
写代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
int i = 0;
int size = 500 * 1024 * 1024;
char *p = (char *)malloc(size);
memset(p, 0, size);
while(1)
{
for(i = 0; i < size; i++)
p[i]=i;
sleep(1);
}
return 0;
}

运行效果如下,很明显,占用物理内存大概为500M
在这里插入图片描述

现在限制该进程使用的物理内存为20M,进入到目录/sys/fs/cgroup/memory,创建目录memtest,进入到该目录。执行下列命令:
echo 20M > memory.limit_in_bytes
echo 18604 > tasks
这两句中,第一句是设置内存限制为20M,第二个是设置进程号。此时再看top截图,如下所示:
在这里插入图片描述
可以看到物理内存依然是500M的样子,没有减少,这跟想象中完全不一样,然后排查了几个小时,没有进展,后面尝试先在cgroup中设置进程的内存限制,再使进程开辟内存,代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
int i = 0;
int size = 500 * 1024 * 1024;
sleep(60);
char *p = (char *)malloc(size);
memset(p, 0, size);
while(1)
{
for(i = 0; i < size; i++)
p[i]=i;
sleep(1);
}
return 0;
}

可以看到,这里面在开辟内存之前,sleep 60秒,为此,咱们需要在这60秒之内,将进程id设置到cgroup中。
运行程序,产生进程号18837,执行命令echo 18837 > tasks,然后等待60秒结束,top信息如下所示:
在这里插入图片描述
很明显,这次有效果,占用的物理内存接近20M,咱们在top界面按下f,将swap选中,再次截图如下:
在这里插入图片描述
此时看到SWAP内存为480M多点,这个结果完全符合咱们的期望。
以上表明,在设置进程的内存限制时,要在进程尚未开辟物理内存时设置,一旦进程开辟了很多的物理内存,再限制物理内存,使得物理内存使用量下降,已经为时已晚。

咱们再考虑多进程的情况,正常来说多进程架构比较稳,一个服务程序可能产生多个进程,而我们想控制的是这个服务程序总的内存使用量,即其产生的所有子进程的内存占用之和不要超过某个值,这该如何设置。
写一个多进程应用,代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
int i = 0;
int size = 500 * 1024 * 1024;
int childpid = 0;
char *p = NULL;
sleep(60);
childpid = fork();

p = (char *)malloc(size);
memset(p, 0, size);
while(1)
{
for(i = 0; i < size; i++)
p[i]=i;
sleep(1);
}
return 0;
}

可以看出,这里面创建了一个子进程,父进程和子进程都占用了500M内存,咱们等到60s后,执行top命令:
在这里插入图片描述
这里咱们未设置内存限制,情况完全正确。
现在限制这个应用程序(两个进程)的内存限制为20M。

重新运行该程序,查看进程号19920,注意代码中的fork在sleep之后,故而此时只有一个进程号, 在60s内。
echo 19920 > tasks。
60s之后,子进程产生了,top命令截图如下:
在这里插入图片描述
可以看到这两个进程占用的物理内存加起来大概20M。
但是咱们刚才只将父进程的id 19920设置到tasks文件中。
我们现在看下这个tasks文件里面的内容,截图如下:
在这里插入图片描述
可以看到,这里面有两个进程号,但是我只设置了19920到tasks中,另外一个是cgroup内部设置进去。
查原因,发现是有个进程组的概念,将进程组的首id设置进去,后续产生的进程id都会被cgroup设置进去。

截图如下,可以查看进程组,注意我敲的是两个命令,可以看出19931不是一个进程组,19920既是进程组id,也是该进程组的第一个进程id。子进程默认会继承父进程的进程组id。
在这里插入图片描述

现在再考虑下应用程序里面有多个进程组的情况,默认情况下子进程会继承父进程的进程组id。但是子进程的进程组id也可以进行修改,代码如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
int i = 0;
int size = 500 * 1024 * 1024;
int childpid = 0;
char *p = NULL;
sleep(60);
childpid = fork();
if(childpid==0)
{
setpgid(0, getpid());
}
p = (char *)malloc(size);
memset(p, 0, size);
while(1)
{
for(i = 0; i < size; i++)
p[i]=i;
sleep(1);
}
return 0;
}

代码中,子进程的逻辑块中,用setpgid设置其进程组id为其自身id,在sleep 60秒内,产生的进程id是20098,然后执行命令: echo 20098 > tasks

过60秒后,查看进程如下:
在这里插入图片描述
可以看到,此时有两个进程组,top截图如下:
在这里插入图片描述
可以看出,两个进程的物理内存之和大概是20M,由此推断就算父进程和子进程是不同的进程组,进程限制也对整个应用程序有效。

我们再查看下tasks里面的内容:
在这里插入图片描述
发现父子进程就算是位于不同的进程组,只要设置第一个进程id进去,cgroup会自动将子进程的id设置进去。

其实笔者在更复杂的环境中测试过,一个应用程序产生大量的进程,也是这些所有的进程的内存加起来,大致满足cgroup的受限条件,而这些进程id也会被写入到tasks中。

注意,我这里说的是所有的进程的内存加起来,大致满足,有个大致,其实我遇到过所有子进程内存加起来,超过设置的20M的情况,但是超出的不多,大概超出2M。具体原因未能明白。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1015612.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【深度学习】Pytorch 系列教程(十四):PyTorch数据结构:6、模块(Module):前向传播

目录 一、前言 二、实验环境 三、PyTorch数据结构 0、分类 1、张量&#xff08;Tensor&#xff09; 2、张量操作&#xff08;Tensor Operations&#xff09; 3、变量&#xff08;Variable&#xff09; 4、数据集&#xff08;Dataset&#xff09; 5、数据加载器&#x…

科学计算器网站Desmos网站

科学计算器网站Desmos网站 有时在学习工作或者生活中&#xff0c;需要用到计算问题&#xff0c;但由于电脑上没有安装相应的专业软件&#xff0c;难以计算有的问题&#xff0c;因而&#xff0c;本文推荐一种免费的在线计算网站Desmos。 一、Desmos网址 Desmos官网的地址为&a…

[管理与领导-96]:IT基层管理者 - 扩展技能 - 5 - 职场丛林法则 -10- 七分做,三分讲,完整汇报工作的艺术

目录 前言&#xff1a; 一、汇报工作的重要性 1.1 汇报的重要性&#xff1a;汇报工作是工作重要的一环 1.2 向上司汇报工作状态具有重要的意义 1.2 汇报工作存在一些误解 1.3 汇报工作中的下错误做法 1.4 汇报工作与做实际工作的关系 二、工作汇报的内容与艺术 2.1 工…

【深度学习】- NLP系列文章之 1.文本表示以及mlp来处理分类问题

系列文章目录 1. 文本分类与词嵌入表示&#xff0c;mlp来处理分类问题 2. RNN、LSTM、GRU三种方式处理文本分类问题 3. 评论情绪分类 还是得开个坑&#xff0c;最近搞论文&#xff0c;使用lstm做的ssd的cache prefetching&#xff0c;意味着我不能再划水了。 文章目录 系列文章…

js创建动态key的对象ES6和ES5的方法

前提&#xff1a; 有个场景&#xff0c;循环数组&#xff0c;根据每一项的值&#xff0c;往一个数组中push一个新对象&#xff0c;对象的key不同要从数组中获取 情况解析&#xff1a;push没有什么问题&#xff0c;问题就是创建一个动态key的对象。下面就说一下如何以参数为key…

【pwn入门】基础知识

声明 本文是B站你想有多PWN和星盟安全学习的笔记&#xff0c;包含一些视频外的扩展知识。 工具和命令 常见的工具 pwntools安装checksec安装pwndbg的安装和gdb使用ubuntu没有使用全部磁盘空间 sudo lvextend -l 100%FREE /dev/mapper/ubuntu--vg-ubuntu--lv sudo resize2f…

Vue中一键批量注册全局组件

文件目录如下 1. component文件夹中编写所有的公共组件 注意&#xff1a;之后一键注册的全局组件名就是每个公共组件&#xff08;xxx.vue&#xff09;文件的文件名 xxx 2. plugins/components.js中批量注册组件 import Vue from "vue"let requireFile require.con…

关于阿里云服务器Ubuntu编译jdk8中遇到的坑及解决方案

关于阿里云服务器Ubuntu系统安装jdk8中遇到的坑及解决方案 记录一下困扰了很多天、到处查资料最后终于成功安装的过程 关于阿里云服务器无法登录的问题 基本反馈是这样的&#xff1a; 如果你添加了ip之后仍然登不进去&#xff0c;有一种方法是直接从第三个选项进去登录之后修…

十天学完基础数据结构-第一天(绪论)

1. 数据结构的研究内容 数据结构的研究主要包括以下核心内容和目标&#xff1a; 存储和组织数据&#xff1a;数据结构研究如何高效地存储和组织数据&#xff0c;以便于访问和操作。这包括了在内存或磁盘上的数据存储方式&#xff0c;如何将数据元素组织成有序或无序的集合&…

浅谈C++|多态篇

1.多态的基本概念 多态是C面向对象三大特性之一多态分为两类 1. 静态多态:函数重载和运算符重载属于静态多态&#xff0c;复用函数名 2.动态多态:派生类和虚函数实现运行时多态 静态多态和动态多态区别: 静态多态的函数地址早绑定–编译阶段确定函数地址 动态多态的函数地址晚绑…

浅谈C++|类的继承篇

引子&#xff1a; 继承是面向对象三大特性之一、有些类与类之间存在特殊的关系&#xff0c;例如下图中: 我们发现&#xff0c;定义这些类时&#xff0c;下级别的成员除了拥有上一级的共性&#xff0c;还有自己的特性。 这个时候我们就可以考虑利用继承的技术&#xff0c;减少…

Learn Prompt-人工智能基础

什么是人工智能&#xff1f;很多人能举出很多例子说这就是人工智能&#xff0c;但是让我们给它定义一个概念大家又觉得很难描述的清楚。实际上&#xff0c;人工智能并不是计算机科学领域专属的概念&#xff0c;在其他学科包括神经科学、心理学、哲学等也有人工智能的概念以及相…

机器学习第六课--朴素贝叶斯

朴素贝叶斯广泛地应用在文本分类任务中&#xff0c;其中最为经典的场景为垃圾文本分类(如垃圾邮件分类:给定一个邮件&#xff0c;把它自动分类为垃圾或者正常邮件)。这个任务本身是属于文本分析任务&#xff0c;因为对应的数据均为文本类型&#xff0c;所以对于此类任务我们首先…

Jprofiler的使用查看oom

一、安装 idea安装插件 安装客户端 链接 IDEA配置Jprofiler执行文件 二、产生oom import java.util.ArrayList; import java.util.List;//测试代码 public class TestHeap {public static void main(String[] args) {int num 0;List<Heap> list new ArrayList&l…

【深度学习实验】线性模型(一):使用NumPy实现简单线性模型:搭建、构造损失函数、计算损失值

目录 一、实验介绍 二、实验环境 三、实验内容 0. 导入库 1. linear_model函数 2. loss_function函数 3. 定义数据 4. 调用函数 一、实验介绍 使用Numpy实现 线性模型搭建构造损失函数进行模型前向传播并计算损失值 二、实验环境 conda create -n DL python3.7 cond…

Learn Prompt-什么是ChatGPT?

ChatGPT&#xff08;生成式预训练变换器&#xff09;是由 OpenAI 在2022年11月推出的聊天机器人。它建立在 OpenAI 的 GPT-3.5 大型语言模型之上&#xff0c;并采用了监督学习和强化学习技术进行了微调。 ChatGPT 是一种聊天机器人&#xff0c;允许用户与基于计算机的代理进行对…

LVS+Haproxy

LVSHaproxy 一、Haproxy简介1.1、Haproxy应用分析1.2、Haproxy的特性1.3、常见负载均衡策略1.4、LVS、Haproxy、Nginx区别1.5、 Haproxy的优点1.6、常见的Web集群调度器 二、Haproxy部署实例四、日志定义优化 一、Haproxy简介 Haproxy 是一个使用C语言编写的自由及开放源代码软…

ES6中新增加的Proxy对象及其使用方式

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ Proxy对象的基本概念Proxy对象的主要陷阱&#xff08;Traps&#xff09; ⭐ 使用Proxy对象⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来…

Hugging Face使用Stable diffusion Diffusers Transformers Accelerate Pipelines

Diffusers A library that offers an implementation of various diffusion models, including text-to-image models. 提供不同扩散模型的实现的库&#xff0c;代码上最简洁&#xff0c;国内的问题是 huggingface 需要翻墙。 Transformers A Hugging Face library that pr…

log4j2漏洞复现

log4j2漏洞复现 漏洞原理 log4j2框架下的lookup查询服务提供了{}字段解析功能&#xff0c;传进去的值会被直接解析。例如${sys:java.version}会被替换为对应的java版本。这样如果不对lookup的出栈进行限制&#xff0c;就有可能让查询指向任何服务&#xff08;可能是攻击者部署…