原文链接:https://0xax.gitbooks.io/linux-insides/content/Cgroups/linux-cgroups-1.html

1 引言

Cgroups是Linux内核提供的提供的一种机制,使我们能够为一组进程分配处理器时间、进程数、内存量等或多种资源的组合。控制组是分层组织的,就像进程也是分层组织的一样,子控制组可以从父控制组继承参数。但实际上他们并不相同,控制组与普通进程树的区别是,控制组的不同层次可以同时存在,而进程树始终单个的(single)。每个cgroup层次都被附加到一组cgroup上。

cgroup层次示例:(低) resources Cgroups cgroups cgroups subsystems (高)

一个control group subsystem代表一种类型的cgroup资源,比如处理器时间或进程数。Linux内核提供12种控制组子系统:

  • cpuset - 为一组任务提供单独的处理器和内存节点
  • cpu - 使用调度程序为cgroup任务提供对处理器资源的访问
  • cpuacct - 为控制组生成使用处理器的报告
  • io - 为块设备提供读写速度限制
  • memory - 为cgroup中的任务设置内存使用限制
  • devices - 允许cgroup中的任务访问设备
  • freezer - 允许cgroup中的任务暂停或继续
  • net_cls - 允许标记cgroup的网络包
  • net_prio - 提供一种方法来动态设置每个cgroup每个网络接口的网络流量优先级
  • perf_event - 提供perf事件的访问权限
  • hugetlb - 激活对cgroup的huge pages支持
  • pid - 设置一个cgroup的进程数

每个cgroup子系统都依赖于相关的配置选项,例如cpuset子系统应该通过CONFIG_CPUSETS内核配置选项启用,io子系统应该通过CONFIG_BLK_CGROUP配置启用等。所有这些选项都能在General setup → \to →Control Group support菜单中找到:

可以通过proc文件系统查看启用的cgroups:

$ cat /proc/cgroups
#subsys_name    hierarchy    num_cgroups    enabled
cpuset    8    1    1
cpu    7    66    1
cpuacct    7    66    1
blkio    11    66    1
memory    9    94    1
devices    6    66    1
freezer    2    1    1
net_cls    4    1    1
perf_event    3    1    1
net_prio    4    1    1
hugetlb    10    1    1
pids    5    69    1

或者通过sysfs

$ ls -l /sys/fs/cgroup/
total 0
dr-xr-xr-x 5 root root  0 Dec  2 22:37 blkio
lrwxrwxrwx 1 root root 11 Dec  2 22:37 cpu -> cpu,cpuacct
lrwxrwxrwx 1 root root 11 Dec  2 22:37 cpuacct -> cpu,cpuacct
dr-xr-xr-x 5 root root  0 Dec  2 22:37 cpu,cpuacct
dr-xr-xr-x 2 root root  0 Dec  2 22:37 cpuset
dr-xr-xr-x 5 root root  0 Dec  2 22:37 devices
dr-xr-xr-x 2 root root  0 Dec  2 22:37 freezer
dr-xr-xr-x 2 root root  0 Dec  2 22:37 hugetlb
dr-xr-xr-x 5 root root  0 Dec  2 22:37 memory
lrwxrwxrwx 1 root root 16 Dec  2 22:37 net_cls -> net_cls,net_prio
dr-xr-xr-x 2 root root  0 Dec  2 22:37 net_cls,net_prio
lrwxrwxrwx 1 root root 16 Dec  2 22:37 net_prio -> net_cls,net_prio
dr-xr-xr-x 2 root root  0 Dec  2 22:37 perf_event
dr-xr-xr-x 5 root root  0 Dec  2 22:37 pids
dr-xr-xr-x 5 root root  0 Dec  2 22:37 systemd

你可以已经猜到,cgroup机制并不是直接针对Linux内核的需求发明的,而是用户空间的需要。要想使用cgroup,要先通过两种方式创建它。

第一种方式是在/sys/fs/cgroup目录中的任何subsystem中创建子目录,并把任务的PID添加到tasks文件中,该文件会在创建子目录后立即自动创建。

第二种方式是通过libcgroup库创建、删除和管理cgroups。(在Fedora中使用libcgroup-tools库)

我们开始考虑简单的例子。下面的bash脚本将会打印一行到/dev/tty设备(表示当前进程的控制终端)。

#!/bin/bashwhile :
doecho "print line" > /dev/ttysleep 5
done

如果我们运行这个脚本会看到下面的输出:

$ sudo chmod +x cgroup_test_script.sh
~$ ./cgroup_test_script.sh
print line
print line
print line
...
...
...

现在我们转到cgroupfs在计算机上挂载的位置,正是/sys/fs/cgroup目录,但是你也可以挂载到任意位置。

$ cd /sys/fs/cgroup

现在我们前往devices子目录,该目录代表一种资源,控制cgroup中的任务对设备的访问权限。

$ cd devices

然后在这创建cgroup_test_group目录:

$ mkdir cgroup_test_group

在创建完cgroup_test_group文件夹之后,下面的文件会自动创建:

/sys/fs/cgroup/devices/cgroup_test_group$ ls -l
total 0
-rw-r--r-- 1 root root 0 Dec  3 22:55 cgroup.clone_children
-rw-r--r-- 1 root root 0 Dec  3 22:55 cgroup.procs
--w------- 1 root root 0 Dec  3 22:55 devices.allow
--w------- 1 root root 0 Dec  3 22:55 devices.deny
-r--r--r-- 1 root root 0 Dec  3 22:55 devices.list
-rw-r--r-- 1 root root 0 Dec  3 22:55 notify_on_release
-rw-r--r-- 1 root root 0 Dec  3 22:55 tasks

现在,我们对tasksdevices.deny文件感兴趣。首先,tasks文件应该包含要添加到该组的进程的PID。devices.deny文件应该包含拒绝设备的列表。默认情况下,新建的cgroup对资源没有任何限制。要阻止一个设备(例如/dev/tty),我们应该向devices.deny文件中写入下面一行:

$ echo "c 5:0 w" > devices.deny

现在一步一步地看这一行。第一个字母c表示设备类型,在我们的例子中,/dev/tty是字符设备。我们可以用ls命令的输出中进行验证:

$ ls -l /dev/tty
crw-rw-rw- 1 root tty 5, 0 Dec  3 22:48 /dev/tty

可以看到权限列表的第一个字母是c。第二个部分是5:0,设备的主序号和次序号,ls的输出也能看到这些数字。最后一个字母w禁止任务向特定的任务写入数据。现在我们执行cgroup_test_script.sh脚本试试:

$ ./cgroup_test_script.sh
print line
print line
print line
...
...

然后把这个进程的pid添加到devices/tasks文件中:

$ echo $(pidof -x cgroup_test_script.sh) > /sys/fs/cgroup/devices/cgroup_test_group/tasks

结果会变成这样:

$ ./cgroup_test_script.sh
print line
print line
print line
print line
print line
print line
./cgroup_test_script.sh: line 5: /dev/tty: Operation not permitted

相同情况在启动docker容器的时候也能出现,docker会为容器中的进程创建一个cgroup

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
fa2d2085cd1c        mariadb:10          "docker-entrypoint..."   12 days ago         Up 4 minutes        0.0.0.0:3306->3306/tcp   mysql-work
$ cat /sys/fs/cgroup/devices/docker/fa2d2085cd1c8d797002c77387d2061f56fefb470892f140d0dc511bd4d9bb61/tasks | head -3
5501
5584
5585
...
...
...

所以,在启动docker容器的时候,docker会为容器中的进程们创建一个cgroup

$ docker exec -it mysql-work /bin/bash
$ topPID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                   1 mysql     20   0  963996 101268  15744 S   0.0  0.6   0:00.46 mysqld71 root      20   0   20248   3028   2732 S   0.0  0.0   0:00.01 bash77 root      20   0   21948   2424   2056 R   0.0  0.0   0:00.00 top

然后我们可以在主机上看见这个:

$ systemd-cglsControl group /:
-.slice
├─docker
│ └─fa2d2085cd1c8d797002c77387d2061f56fefb470892f140d0dc511bd4d9bb61
│   ├─5501 mysqld
│   └─6404 /bin/bash

现在我们对cgroup机制和如何使用它有了一些了解,现在该看一下内核源代码, 开始深入探索cgroup机制的实现。

2 控制组的早期初始化

刚才我们还几乎完全不了解cgroup在Linux内核的实现机制,现在我们开始深入研究Linux内核的源代码。与往常一样,我们将从cgroup的早期初始化开始,cgroup的初始化在内核中分为earlylate两部分。

cgroup的早期初始化起源于Linux内核的早期初始化init/main.c

CGroup(控制组)相关推荐

  1. Linux Cgroup 系列:CentOS 7 Systemd Cgroup 层级

    CentOS 7 Systemd Cgroup 层级 Systemd单元类型 默认slice类型 systemd-cgls Reference List Cgroup控制组可以进行嵌套,但是为了能够更 ...

  2. linux cgroup 死循环,Linux CGroup 基础

    CGroup V1 1. CGroup 概念Task: 任务,也就是进程,但这里的进程和我们通常意义上的 OS 进程有些区别,在后面会提到. CGroup: 控制组,一个 CGroup 就是一组按照某 ...

  3. Docker Cgroups

    Docker中利用namespace来做权限控制,用cgroups来做资源控制,这两个都是非常重要的,下面是整理了一些关于cgroups相关的. cgroups全称control groups ,是L ...

  4. Docker核心原理之cgroups

    cgroups资源限制 上一篇文章中,我们了解了Docker的资源隔离技术namespace,通过系统调用构建了一个相对隔离的shell环境.也可以称之为一个简单的容器.接下来将讲解另一个强大的内核工 ...

  5. 树莓派开始玩转linux pdf_用树莓派构建 Kubernetes 集群 | Linux 中国

    将 Kubernetes 安装在多个树莓派上,实现自己的"家庭私有云"容器服务. • 来源:linux.cn • 作者:Chris Collins • 译者:Xingyu.Wang ...

  6. 查看pod网络范围_K8S Pod 内抓包快速定位网络问题

    前言 在使用 Kubernetes 时,可能会遇到一些网络问题.当通过检查配置与日志无法排查错误时,这时就需要抓取网络数据包,但是Pod内一般不会安装tcpdump命令,那有没有方法可以直接通过宿主机 ...

  7. redis 集群 实操 (史上最全、5w字长文)

    文章很长,建议收藏起来慢慢读! 总目录 博客园版 为大家准备了更多的好文章!!!! 推荐:尼恩Java面试宝典(持续更新 + 史上最全 + 面试必备)具体详情,请点击此链接 尼恩Java面试宝典,34 ...

  8. Page Cache:为什么我的容器内存使用量总是在临界点?

    Memory Cgroup 是如何控制一个容器的内存的.我们已经知道了,如果容器使用的物理内存超过了 Memory Cgroup 里的 memory.limit_in_bytes 值,那么容器中的进程 ...

  9. 容器性能测验 调研报告

    研究背景 https://aijishu.com/a/1060000000206531#item-4-9 An Updated Performance Comparison of Virtual Ma ...

最新文章

  1. iptables使用方法
  2. win7 storm搭建
  3. spark-submit提交参数说明以及与yarn-site.xml中参数的相互约束关系+spark运行架构图解(持续更新中)
  4. linux下的SSHD被连接端口修改
  5. BugkuCTF-MISC题blind_injection
  6. hive The specified datastore driver (“com.mysql.jdbc.Driver“) was not found
  7. 【李宏毅2020 ML/DL】P16 PyTorch Tutorial | 最后提及了 apex.amp
  8. 【渝粤题库】陕西师范大学200021现代汉语 作业(高起本、高起专)
  9. c语言输出字符串需要取地址吗,char *str;……printf(%p,str);是输出地址吗?还是只与str说占空间大 - C语言论坛 - 编程论坛...
  10. 2020科目一考试口诀_2020驾考技巧科目一考试口诀答题法
  11. Python 实现超级玛丽游戏
  12. (转)CGJ02、BD09、西安80、北京54、CGCS2000常用坐标系详解
  13. PayPal取消了连连支付快捷提现,我是如何提现到国内的?
  14. 18年华为没有一项原创的发明
  15. 关于示波器是否必须要接地线的疑问
  16. Java IO 序列化与反序列化
  17. 嵌入式IDE-MRS入手使用分享
  18. 服务器部署基于chatgpt的服务
  19. SpringBoot 实现 QQ 邮箱注册和登录
  20. IT规划如何更加务实(zt)

热门文章

  1. python网络编程(基础含实现简易服务器代码)
  2. 本地无需安装数据库,实现plsql远程连接数据库
  3. 使用inet_aton报错
  4. 5.2 odex文件
  5. Android 关于RemoteViews的理解(二)
  6. 【Web项目】点餐系统
  7. Windows留后门--教程(二)——Windows计划任务后门
  8. 2014年北京、广州区域赛总结
  9. 邮件发送技巧:TO, CC, BCC(收件人、抄送、密送)
  10. CF1341B Nastya and Door 题解