容器——Cgroup详解(一)

实验 1:Cgroup 树的基本操作

参考文档

参考文档

实验目标

  • 本次实验将创建并挂载一颗不与任何 subsystem 绑定的 cgroup 树,演示如何创建、删除子 cgroup,以及如何向 cgroup 中添加和删除进程。
  • 由于不和任何subsystem绑定,所以这棵树没有任何实际的功能,但这不影响我们的演示,还有一个好处就是我们不会受subsystem功能的影响,可以将精力集中在cgroup树上。

实验步骤

1. 挂载 Cgroup 树

#准备需要的目录
kevin@ZB-PF4WQHKS:~$ mkdir cgroup && cd cgroup
kevin@ZB-PF4WQHKS:~/cgroup$ mkdir demo

#由于name=demo的cgroup树不存在,所以系统会创建一颗新的cgroup树,然后挂载到demo目录
kevin@ZB-PF4WQHKS:~/cgroup$ sudo mount -t cgroup -o none,name=demo demo ./demo

#挂载点所在目录就是这颗cgroup树的root cgroup,在root cgroup下面,系统生成了一些默认文件
kevin@ZB-PF4WQHKS:~/cgroup$ ls ./demo/
cgroup.clone_children  cgroup.procs  cgroup.sane_behavior  notify_on_release  release_agent  tasks

#cgroup.procs里包含系统中的所有进程,因为挂载cgroup树时系统会自动将所有进程加入其中。
#wc命令是用于统计行数的
kevin@ZB-PF4WQHKS:~/cgroup$ wc -l ./demo/cgroup.procs
36 ./demo/cgroup.procs
  • cgroup.clone_children
    • 这个文件只对cpuset(subsystem)有影响,当该文件的内容为1时,新创建的cgroup将会继承父cgroup的配置,即从父cgroup里面拷贝配置文件来初始化新cgroup
  • cgroup.procs
    • 当前cgroup中的所有进程ID,系统不保证ID是顺序排列的,且ID有可能重复
  • notify_on_release
    • 该文件的内容为1时,当cgroup退出时(不再包含任何进程和子cgroup),将调用release_agent里面配置的命令。新cgroup被创建时将默认继承父cgroup的这项配置。
  • release_agent
    • 里面包含了cgroup退出时将会执行的命令,系统调用该命令时会将相应cgroup的相对路径当作参数传进去。 注意:这个文件只会存在于root cgroup下面,其他cgroup里面不会有这个文件。
  • tasks
    • 当前cgroup中的所有线程ID,系统不保证ID是顺序排列的

2. 创建和删除cgroup

#创建子cgroup很简单,新建一个目录就可以了
kevin@ZB-PF4WQHKS:~/cgroup/demo$ sudo mkdir cgroup1

#在新创建的cgroup里面,系统默认也生成了一些文件,这些文件的意义和root cgroup里面的一样
kevin@ZB-PF4WQHKS:~/cgroup/demo$ ls cgroup1/
cgroup.clone_children  cgroup.procs  notify_on_release  tasks

#新创建的cgroup里没有任何进程和线程
kevin@ZB-PF4WQHKS:~/cgroup/demo$ wc -l cgroup1/cgroup.procs
0 cgroup1/cgroup.procs
kevin@ZB-PF4WQHKS:~/cgroup/demo$ wc -l cgroup1/tasks
0 cgroup1/tasks

#删除cgroup也很简单,删除掉相应的目录就可以了
kevin@ZB-PF4WQHKS:~/cgroup/demo$ sudo rmdir cgroup1/

3. 添加、删除进程

  • 创建新的cgroup后,就可以往里面添加进程了。注意下面几点:
    • 在一颗cgroup树里面,一个进程必须要属于一个cgroup。
    • 新创建的子进程将会自动加入父进程所在的cgroup。
    • 从一个cgroup移动一个进程到另一个cgroup时,只要有目的cgroup的写入权限就可以了,系统不会检查源cgroup里的权限。
    • 用户只能操作属于自己的进程,不能操作其他用户的进程,root账号除外。
#--------------------------第一个shell窗口----------------------
#创建一个新的cgroup
kevin@ZB-PF4WQHKS:~/cgroup/demo$ sudo mkdir test && cd test

#这个命令的意思是输出当前 Shell 进程的 PID。
kevin@ZB-PF4WQHKS:~/cgroup/demo$/test$ echo $$
581
#向cgroup中添加进程
#注意:一次只能往这个文件中写一个进程ID,如果需要写多个的话,需要多次调用这个命令
kevin@ZB-PF4WQHKS:~/cgroup/demo/test$ sudo sh -c 'echo 581 > cgroup.procs'

#--------------------------第二个shell窗口----------------------
#重新打开一个shell窗口,避免第一个shell里面运行的命令影响输出结果
#这时可以看到cgroup.procs里面包含了上面的第一个shell进程
kevin@ZB-PF4WQHKS:~/cgroup/demo/test$ cat cgroup.procs
1421

#--------------------------第一个shell窗口----------------------
#回到第一个窗口,运行top命令
#top 命令会实时显示系统中各个进程的资源占用情况,包括 CPU、内存、进程数等。
#top 是一个交互式命令,默认会动态更新显示内容。
#top 命令会启动一个top进程,该进程是shell的子进程
kevin@ZB-PF4WQHKS:~/cgroup/demo/test$ top
#这里省略输出内容

#--------------------------第二个shell窗口----------------------
#这时再在第二个窗口查看,发现top进程自动和它的父进程(581)属于同一个cgroup
kevin@ZB-PF4WQHKS:~/cgroup/demo/test$ cat cgroup.procs
581
16515
# 查找与 top 相关的进程信息。
# ps -ef:列出系统中所有进程的详细信息。
# grep top:过滤出包含 top 的行。
kevin@ZB-PF4WQHKS:~/cgroup/demo/test$ ps -ef|grep top
dev      16515  581  0 04:02 pts/0    00:00:00 top
kevin@ZB-PF4WQHKS:~/cgroup/demo/test$

#在一颗cgroup树里面,一个进程必须要属于一个cgroup,
#所以我们不能凭空从一个cgroup里面删除一个进程,只能将一个进程从一个cgroup移到另一个cgroup,
#这里我们将581移动到root cgroup
kevin@ZB-PF4WQHKS:~/cgroup/demo/test$ sudo sh -c 'echo 1421 > ../cgroup.procs'
kevin@ZB-PF4WQHKS:~/cgroup/demo/test$ cat cgroup.procs
16515
#移动581到另一个cgroup之后,它的子进程不会随着移动,这是cgroup进程管理规则

#--------------------------第一个shell窗口----------------------
##回到第一个shell窗口,进行清理工作
#先用ctrl+c退出top命令
kevin@ZB-PF4WQHKS:~/cgroup/demo/test$ cd ..
#然后删除创建的cgroup
kevin@ZB-PF4WQHKS:~/cgroup/demo$ sudo rmdir test

4. cgroup.procs vs tasks

#创建两个新的cgroup用于演示
kevin@ZB-PF4WQHKS:~/cgroup/demo$ sudo mkdir c1 c2
# 寻找一个多线程的进程
kevin@ZB-PF4WQHKS:~/cgroup/demo$ ps -ef
systemd+   610     1   610  0    2 01:52 ?        00:00:00 /lib/systemd/systemd-timesyncd
systemd+   610     1   616  0    2 01:52 ?        00:00:00 /lib/systemd/systemd-timesyncd
#进程610有两个线程,分别是610和616

#将616线程加入c1/cgroup.procs(本来应该放进程的地方)
#这样会把616所属进程放入c1/cgroup.procs,并且进程所属的全部线程放入c1/tasks
kevin@ZB-PF4WQHKS:/home/dev/cgroup/demo# echo 616 > c1/cgroup.procs
#由于cgroup.procs存放的是进程ID,所以这里看到的是616所属的进程ID(610)
kevin@ZB-PF4WQHKS:/home/dev/cgroup/demo# cat c1/cgroup.procs
610
#从tasks中的内容可以看出,虽然只往cgroup.procs中加了线程616,
#但系统已经将这个线程所属的进程的所有线程都加入到了tasks中,
kevin@ZB-PF4WQHKS:/home/dev/cgroup/demo# cat c1/tasks
610
616

#将616线程加入c2/tasks中(本来应该放线程的地方)
#这样会把616所属进程放入c2/cgroup.procs,但是不会把该进程所属的全部线程放入c2/tasks
root@ubuntu:/home/dev/cgroup/demo# echo 616 > c2/tasks
#这时我们看到虽然在c1/cgroup.procs和c2/cgroup.procs里面都有610,
#但c1/tasks和c2/tasks中包含了不同的线程,说明这个进程的两个线程分别属于不同的cgroup
root@ubuntu:/home/dev/cgroup/demo# cat c1/cgroup.procs
610
root@ubuntu:/home/dev/cgroup/demo# cat c1/tasks
610
root@ubuntu:/home/dev/cgroup/demo# cat c2/cgroup.procs
610
root@ubuntu:/home/dev/cgroup/demo# cat c2/tasks
616
#通过tasks,我们可以实现线程级别的管理,但通常情况下不会这么用,
#并且在cgroup V2以后,将不再支持该功能,只能以进程为单位来配置cgroup

  • 在cgroup V2以后,将不再支持该功能,只能以进程为单位来配置cgroup

5. 相关Linux命令解释

  • echo $$
    • 输出当前 Shell 进程的 PID(进程 ID)。
    • $$ 是一个特殊变量,表示当前 Shell 进程的 PID。
    1. top
    • 实时显示系统中各个进程的资源占用情况,包括 CPU、内存、进程数等。
    • top 是一个交互式命令,默认会动态更新显示内容。
    • 按 q:退出 top。
    • 按 k:杀死指定进程。
    • 按 P:按 CPU 使用率排序。
    • 按 M:按内存使用率排序。
    1. ps -ef | grep top
    • 查找与 top 相关的进程信息。
    • ps -ef:列出系统中所有进程的详细信息。
    • grep top:过滤出包含 top 的行。
    1. wc -l ./demo/cgroup.procs
    • wc:word count 的缩写,用于统计文件中的行数、单词数和字节数。
    • -l:–lines 的缩写,表示只统计行数。
    • ./demo/cgroup.procs:要统计的文件路径。
    1. ps 命令
    • ps 命令可以显示进程的详细信息,结合 -eLf 参数可以列出所有线程。
    • ps -ef

请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值