CGroup(控制组)
原文链接: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
现在,我们对tasks
和devices.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
的初始化在内核中分为early
和late
两部分。
cgroup
的早期初始化起源于Linux内核的早期初始化init/main.c
CGroup(控制组)相关推荐
- Linux Cgroup 系列:CentOS 7 Systemd Cgroup 层级
CentOS 7 Systemd Cgroup 层级 Systemd单元类型 默认slice类型 systemd-cgls Reference List Cgroup控制组可以进行嵌套,但是为了能够更 ...
- linux cgroup 死循环,Linux CGroup 基础
CGroup V1 1. CGroup 概念Task: 任务,也就是进程,但这里的进程和我们通常意义上的 OS 进程有些区别,在后面会提到. CGroup: 控制组,一个 CGroup 就是一组按照某 ...
- Docker Cgroups
Docker中利用namespace来做权限控制,用cgroups来做资源控制,这两个都是非常重要的,下面是整理了一些关于cgroups相关的. cgroups全称control groups ,是L ...
- Docker核心原理之cgroups
cgroups资源限制 上一篇文章中,我们了解了Docker的资源隔离技术namespace,通过系统调用构建了一个相对隔离的shell环境.也可以称之为一个简单的容器.接下来将讲解另一个强大的内核工 ...
- 树莓派开始玩转linux pdf_用树莓派构建 Kubernetes 集群 | Linux 中国
将 Kubernetes 安装在多个树莓派上,实现自己的"家庭私有云"容器服务. • 来源:linux.cn • 作者:Chris Collins • 译者:Xingyu.Wang ...
- 查看pod网络范围_K8S Pod 内抓包快速定位网络问题
前言 在使用 Kubernetes 时,可能会遇到一些网络问题.当通过检查配置与日志无法排查错误时,这时就需要抓取网络数据包,但是Pod内一般不会安装tcpdump命令,那有没有方法可以直接通过宿主机 ...
- redis 集群 实操 (史上最全、5w字长文)
文章很长,建议收藏起来慢慢读! 总目录 博客园版 为大家准备了更多的好文章!!!! 推荐:尼恩Java面试宝典(持续更新 + 史上最全 + 面试必备)具体详情,请点击此链接 尼恩Java面试宝典,34 ...
- Page Cache:为什么我的容器内存使用量总是在临界点?
Memory Cgroup 是如何控制一个容器的内存的.我们已经知道了,如果容器使用的物理内存超过了 Memory Cgroup 里的 memory.limit_in_bytes 值,那么容器中的进程 ...
- 容器性能测验 调研报告
研究背景 https://aijishu.com/a/1060000000206531#item-4-9 An Updated Performance Comparison of Virtual Ma ...
最新文章
- iptables使用方法
- win7 storm搭建
- spark-submit提交参数说明以及与yarn-site.xml中参数的相互约束关系+spark运行架构图解(持续更新中)
- linux下的SSHD被连接端口修改
- BugkuCTF-MISC题blind_injection
- hive The specified datastore driver (“com.mysql.jdbc.Driver“) was not found
- 【李宏毅2020 ML/DL】P16 PyTorch Tutorial | 最后提及了 apex.amp
- 【渝粤题库】陕西师范大学200021现代汉语 作业(高起本、高起专)
- c语言输出字符串需要取地址吗,char *str;……printf(%p,str);是输出地址吗?还是只与str说占空间大 - C语言论坛 - 编程论坛...
- 2020科目一考试口诀_2020驾考技巧科目一考试口诀答题法
- Python 实现超级玛丽游戏
- (转)CGJ02、BD09、西安80、北京54、CGCS2000常用坐标系详解
- PayPal取消了连连支付快捷提现,我是如何提现到国内的?
- 18年华为没有一项原创的发明
- 关于示波器是否必须要接地线的疑问
- Java IO 序列化与反序列化
- 嵌入式IDE-MRS入手使用分享
- 服务器部署基于chatgpt的服务
- SpringBoot 实现 QQ 邮箱注册和登录
- IT规划如何更加务实(zt)