利用cgroup限制cpu和memory利用率


  我們環境使用的Linux內核版本是4.4,已支持cgroup,只要在內核配置中選上cgroup,並勾選自己想要的配置(general setup->control group support->)

網上有各種資料介紹cgroup,這里我就不詳述了,直接mount cgoup

mkdir cgroup
mkdir cgroup/cpu
mkdir cgroup/memory
mount -t cgroup -ocpu cpu cgroup/cpu
mount -t cgroup -omemory memory cgroup/memory > /dev/util 2>&1

mkdir cgroup/cpu/cgroup0

1、限制cpu利用率

  通過cfs_period_us和cpu.cfs_quota_us配合實現,cfs_period_us默認值是100ms,代表周期時間是100ms,cpu.cfs_quota_us是進程在100ms周期內所能占用的最大時間,可以設置為95ms,即cpu利用率是95%,注意這個單個cpu的利用率;對於多核系統,如果想設置95%利用率,cpu.cfs_quota_us應該是N*cfs_period_us*95%,N是cpu的核數,通過cat proc/cpuinfo查看(CpuNum=`cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c | awk -F ' ' '{print $1}'`)

#set cpu ratio 98%
cfs_quota_us=`expr $CpuNum \* $cfs_period_us \* 98 / 100`
echo $cfs_quota_us > /cgroup/cpu/cgroup0/cpu.cfs_quota_us
echo $rcSPid > /cgroup/cpu/cgroup0/cgroup.procs

  對於運行了實時進程的環境來說,需要根據cpu.rt_period_us設置cpu.rt_runtime_us,cpu.rt_period_us是實時進程的周期時間,默認1s;cpu.rt_runtime_us是在一個周期時間內,實時進程占用的最大時間,默認是0;一開始沒有注意到這個,我們的環境一配置上cgroup,就會異常導致重啟,后來發現是rt_runtime_us為0;可以設置成內核默認值950ms(cat /proc/sys/kernel/sched_rt_runtime_us),或者再cgroup的內核配置中去掉sched_rt項。這樣RT進程就不會被cgroup限制,即cgroup0目錄下沒有cpu.rt_runtime_us這一項

  將cpu利用率設置好之后,才可以將需要限制的進程pid加入cgroup.procs;由於我們環境中的進程由rcS中起的,因此只需要將一開始只需要將rcS的pid加入cgroup.procs,后續創建的子進程都會被自動加入到cgroup.procs中(獲取pid rcSPid=`ps -o pid,comm | grep -o "[0-9]*.rcS" | grep -o [0-9]*`)

2、限制memory利用率

  為了避免某些進程的bug導致內存泄露,可以使用memory.limit_in_bytes限制cgroup0組中所有進程所能使用的最大內存,單位是字節;由於我們環境中的進程由rcS中起的,因此只需要將一開始只需要將rcS的pid加入cgroup.procs,后續創建的子進程都會被自動加入到cgroup.procs中。我的環境設置memory.limit_in_bytes為MemFree-200M(留下200M給內核使用已足夠)

MemFree=`cat /proc/meminfo | grep 'MemFree' | awk -F ' ' '{print $2}'`
MemRatioKB=`expr $MemFree - 204800`
MemRatio=`expr $MemRatioKB \* 1024`#config memory ratio

mkdir cgroup/memory/cgroup0 > /dev/util 2>&1
echo $MemRatio >
/cgroup/memory/cgroup0/memory.limit_in_bytes
  進程占用的內存超出設置的閾值,會怎么樣呢?會被kill!!如果你不想被kill,那就要置memory.oom_control為1,這樣在進展占用內存超出閾值時,進程會被加入等待隊列直到有內存分配給他;
#disable kill
echo 1 >
cgroup/memory/cgroup0/memory.oom_control

memory目錄下其他項:

cgroup.event_control #用於eventfd的接口
memory.usage_in_bytes #顯示當前已用的內存
memory.limit_in_bytes #設置/顯示當前限制的內存額度
memory.failcnt #顯示內存使用量達到限制值的次數
memory.max_usage_in_bytes #歷史內存最大使用量
memory.soft_limit_in_bytes #設置/顯示當前限制的內存軟額度
memory.stat #顯示當前cgroup的內存使用情況
memory.use_hierarchy #設置/顯示是否將子cgroup的內存使用情況統計到當前cgroup里面
memory.force_empty #觸發系統立即盡可能的回收當前cgroup中可以回收的內存
memory.pressure_level #設置內存壓力的通知事件,配合cgroup.event_control一起使用
memory.swappiness #設置和顯示當前的swappiness
memory.move_charge_at_immigrate #設置當進程移動到其他cgroup中時,它所占用的內存是否也隨着移動過去
memory.oom_control #設置/顯示oom controls相關的配置
memory.numa_stat #顯示numa相關的內存

附上cpu利用率消耗程序和內存消耗程序,也是參考別人的。

1、cpu消耗,入參是創見的進程個數,(一個進程消耗一個cpu核)

int main(int argc, char *argv[]){
pid_t pid;
int i, pn=4;
if(argc==2){
pn=atoi(argv[1]);
}
for(i=0;i<pn;i++){
pid=fork();
if(pid<=0)break;
}
if(pid<0){
printf("fork() error\n");
return -1;
}else if(pid==0){
//sub process works
for(;;);
}else{
//wait for the sub process's termination
wait(NULL);
}
return 0;
}

2、內存消耗

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

#define MB (1024 * 1024 * 1024)

int main(int argc, char *argv[])
{
char *p;
int i = 0;
system("cat /cgroup/cpu/cgroup0/cgroup.procs");
while(1) {
p = (char *)malloc(MB);
memset(p, 0, MB);
printf("%dG memory allocated\n", ++i);
sleep(1);
}

return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM