Linux cgroup

前言

Cgroup和namespace类似,也是将进程进程分组,但是目的与namespace不一样,namespace是为了隔离进程组之前的资源,而Cgroup是为了对一组进程进行统一的资源监控和限制。

Cgroup的组成

在这里插入图片描述

subsystem

一个subsystem就是一个内核模块(例如:图中的cpu,memory).它被关联到一颗Cgroup树之后,它就会对树的每个节点(进程组) 调度和限制资源,监控,及观察进程组的状态.
目前Linux支持12中system,比如限制CPU的使用时间,限制使用内存,统计CPU使用情况,冻结和恢复一组进程等。

subsystem 作用
cpu 主要限制进程CPU使用率
cpuacct 统计cgroups中进程的cpu使用率
cpuset 为cgroups中进程分配单独的CPU节点(多核)或内存节点
blkio 限制进程的块设备IO
memory 限制进程的memory使用量
devices 可以控制进程能够访问某些设备
freezer 挂起或者恢复cgrops中进程
net_cls 可以标记cgroups中进程的网络数据包,然后可以使用tc(traffic control)对数据包进程控制
ns 可以使不同cgroups下面的进程使用不同的namespace
Hierachy

cgroup结构体可以组成一棵树,每一颗cgroup结构体组成的的树称为cgroup层级结构(hierarchy)在这里插入图片描述
当前层级结构可以对其子的cgroups进行资源限制, 如图所示

  • cgroup1 中限制了使用 cpu 及 内存资源,它将控制子节点的 CPU 周期和内存分配(即,限制 cgroup2、cgroup3、cgroup4 中的cpu及内存资源分配)。
  • cgroup2 中启用了内存限制,但是没有启用cpu的资源限制,这就导致了 cgroup3 和 cgroup4 的内存资源受 cgroup2中的 mem 设置内容的限制;
  • cgroup3 和 cgroup4 会自由竞争在 cgroup1 的 cpu 资源限制范围内的 cpu 资源。

也可以明显的看出 cgroup 资源是自上而下分布约束的。只有当资源已经从上游 cgroup 节点分发给下游时,下游的 cgroup 才能进一步分发约束资源。

Task

任务即系统的一个进程。一个进程可以加入到某个cgroups,也可以从一个cgroups迁移到另一个cgroups。一个进程组的进程可以使用cgroups为单位分配资源,同时受到cgroups为单位设定限制。

三者关系
  1. 同一个task不能属于同一个hierarchy的不同的cgroup
  2. 同一个hierarchy可以附加到一个或者多个subsystem
  3. 一个subsystem可以附加到多个hierarchy,当且仅当这个hierarchy只有这一个subsystem。
  4. fork出的子进程在初始化状态与其父进程处于同一个cgroup。

2,3 可以理解为,当hierarchy有能力管理多个资源的时候,让别的hierarchy,分担你其中一资源。当仅仅当你一个资源的管理不过来的时候可以分担

实操

要想使用cgroup,要先通过两种方式创建

  1. 在/sys/fs/cgroup目录中的任何subsystem中创建子目录,并把任务的PID添加到tasks文件中,该文件会在创建子目录后立即自动创
  2. 通过libcgroup库创建、删除和管理cgroups

这里我们使用第一种。

  1. 现在我们前往memory子目录
cd memory
  1. 创建cgroup_test_group目录
mkdir cgroup_test_group
  1. 在创建完cgroup_test_group文件夹之后,下面的文件会自动创建:
/sys/fs/cgroup/memory/cgroup_test_group$ ls -l
total 0
-rw-r--r-- 1 root root 0 May  7 01:00 cgroup.clone_children
--w--w--w- 1 root root 0 May  7 01:00 cgroup.event_control
-rw-r--r-- 1 root root 0 May  7 01:00 cgroup.procs
-r--r--r-- 1 root root 0 May  7 01:00 memory.stat
-rw-r--r-- 1 root root 0 May  7 01:00 memory.swappiness
-rw-r--r-- 1 root root 0 May  7 01:18 memory.limit_in_bytes
-r--r--r-- 1 root root 0 May  7 01:00 memory.usage_in_bytes
-rw-r--r-- 1 root root 0 May  7 01:00 memory.use_hierarchy
-rw-r--r-- 1 root root 0 May  7 01:00 notify_on_release
-rw-r--r-- 1 root root 0 May  7 01:00 tasks
  1. 设置最大内内存
echo 1048576 > memory.limit_in_bytes
  1. 关闭虚拟内存swap
echo 0 > memory.swappiness
  1. 编写java程序
public class Demo {

    public static void main(String[] args) throws InterruptedException {
        byte[][] a = new byte[10000][];
        for (int i = 0; i < 10000; i++) {
            a[i] = new byte[1024 * 5];
            System.out.println("创建了" + (i+1) * 5  + "K" );
            Thread.sleep(300);
        }
    }
}
  1. 运行java并将pid加入task
echo ${pid} > tasks

在这里插入图片描述
发现创建到645K就被kill了,因为Java虚拟机本生运行要内存

主要参考

Cgroup概述
memory cgroup

扫描二维码关注公众号,回复: 16330352 查看本文章

猜你喜欢

转载自blog.csdn.net/y3over/article/details/127667877