• 使用cgroup进行系统资源使用限制


    环境:Centos 7 64

    一、对某个进程限制它使用cpu为50%

    1、先写一个占用cpu较高的脚本

    x=0
    while [ True ];do
        x=$x+1
    done;

    2、可以看到运行后cpu使用到了100%

      PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                              
    20369 root      20   0  113452   1664   1196 R  100.0  0.0   0:10.73 sh  

    3、创建控制组

    mkdir /sys/fs/cgroup/cpu/foo

    4、下面用cgroups控制这个进程的cpu资源

    echo 50000 > /sys/fs/cgroup/cpu/foo/cpu.cfs_quota_us #将cpu.cfs_quota_us设为50000,相对于cpu.cfs_period_us的100000是50%
    echo 20369 >/sys/fs/cgroup/cpu/foo/tasks

    5、我们看到大概限制到了50%左右

      PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                              
    20369 root      20   0  113828   1908   1196 R  49.8  0.0   0:33.75 sh

    6、cgroup控制组下还有很多对于cpu其他的一些控制

    [root@foreman ~]# ls /sys/fs/cgroup/cpu/foo/
    cgroup.clone_children  cpuacct.usage          cpu.rt_period_us       notify_on_release
    cgroup.event_control   cpuacct.usage_percpu   cpu.rt_runtime_us      tasks
    cgroup.procs           cpu.cfs_period_us      cpu.shares             
    cpuacct.stat           cpu.cfs_quota_us       cpu.stat 

    ls /sys/fs/cgroup/memory/cgtest/*

     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相关的内存

    写一个内存占用的c程序,每秒申请1MB内存 

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    #define MB (1024 * 1024)
    
    int main(int argc, char *argv[])
    {
        char *p;
        int i = 0;
        while(1) {
            p = (char *)malloc(MB);
            memset(p, 0, MB);
            printf("%dM memory allocated
    ", ++i);
            sleep(1);
        }
    
        return 0;
    }

    #gcc mem-allocate.c  -o  mem-allocate

     cgroup限制内存使用50M(强制限制 memory.limit_in_bytes)

    [root@foreman cgtest]# pwd
    /sys/fs/cgroup/memory/cgtest
    [root@foreman cgtest]# echo 50M > memory.limit_in_bytes 
    [root@foreman cgtest]# echo 0 > memory.oom_control 
    [root@foreman cgtest]# pgrep mem-allocate
    35190
    [root@foreman cgtest]# echo 35190 > tasks  #只对一个线程ID做限制 ,如果需要对一个线程组做限制,需要将PID放到cgroup.procs中。
                              这样这个PID本身以及所衍生的进程整体会限制在memory.limit_in_bytes中设置的大小内存
                              同时包括这个PID调用所产生的进程也会受到限制。想查看某个进程所属线程组使用如下命令
                              #cat /proc/<PID>/cgroup 来进行查看

    限制效果:

    [root@foreman ~]# ./mem-allocate 
    1M memory allocated
    2M memory allocated
    3M memory allocated
    4M memory allocated
    ...
    ...
    49M memory allocated
    50M memory allocated
    51M memory allocated
    Killed
    如果达到限制不想直接kill进程,而是挂起进程需要将oom_kill_disable 设置为1
    [root@foreman cgtest]#cat memory.oom_control #默认
    oom_kill_disable 0
    under_oom 0
    [root@foreman cgtest]# echo 1 > memory.oom_control 
    [root@foreman cgtest]# cat memory.oom_control 
    oom_kill_disable 1
    under_oom 0

    跑一个脚本使其产生多个子线程去疯狂吃内存(提前将memory.limitxxxxx设置为300MB,oom_kill 设置为0)

    [root@foreman ~]# cat cgtest.sh 
    sleep 20
    x=0
    while [ True ];do
        nohup /root/mem-allocate >>/root/mem.log 2>&1 &
        sleep 1
        proc_num=$(pgrep mem-allocate | wc -l)
        if [ $proc_num -eq 50 ];then
            sleep 1000000
        fi
        x=$(($x+1))
    done;

    跑起来后用systemd-cgtop查看限制情况:

    #systemd-cgtop #使用此命令查看cgroup限制的资源情况
    /cgtest                                                               25      -   295.8M
    通过上面可以清晰的看到tasks 25个 内存限制到了300MB

    概念理解:

    就把 5678 进程加入到了 /foo 控制组。那么 tasks 和 cgroups.procs 有什么区别呢?前面说的对“进程”的管理限制其实不够准确。系统对任务调度的单位是线程。
    在这里,tasks 中看到的就是线程 id。而 cgroups.procs 中是线程组 id,也就是一般所说的进程 id 。
    将一个一般的 pid 写入到 tasks 中,只有这个 pid 对应的线程,以及由它产生的其他进程、线程会属于这个控制组,原有的其他线程则不会。
    而写入 cgroups.procs 会把当前所有的线程都加入进去。如果写入 cgroups.procs 的不是一个线程组 id,而是一个一般的线程 id,那会自动找到所对应的线程组 id 加入进去。
    进程在加入一个控制组后,控制组所对应的限制会即时生效。想知道一个进程属于哪些控制组,可以通过 cat /proc/<pid>/cgroup 查看。 要把进程移出控制组,把 pid 写入到根 cgroup 的 tasks 文件即可。因为每个进程都属于且只属于一个 cgroup,加入到新的 cgroup 后,原有关系也就解除了。
    要删除一个 cgroup,可以用 rmdir 删除相应目录。不过在删除前,必须先让其中的进程全部退出,对应子系统的资源都已经释放,否则是无法删除的。 前面都是通过文件系统访问方式来操作 cgroups 的。实际上,也有一组命令行工具。
      没有英汉互译结果
      请尝试网页搜索

  • 相关阅读:
    指针数组和数组指针表示二维数组
    scanf与getchar()区别
    选择循环
    朴素的思想
    asp.net中word转html碰到的权限异常问题(转)
    MAC下安装Fiddler抓包工具
    抓包工具charles的使用
    mysql 命令大全
    利用反射拼接SQL查询条件字符串
    赚自己的淘宝佣金,让返利网无路可走
  • 原文地址:https://www.cnblogs.com/yooma/p/8513313.html
Copyright © 2020-2023  润新知