原文链接:深入理解 Linux Cgroup 系列(二):玩转 CPU

上篇文章主要介绍了 cgroup 的一些基本概念,包括其在 CentOS 系统中的默认设置和控制工具,并以 CPU 为例阐述 cgroup 如何对资源进行控制。这篇文章将会通过具体的示例来演示如何通过 cgroup 来限制 CPU 的使用以及不同的 cgroup 设置对性能的影响。

1. 查看当前 cgroup 信息


有两种方法来查看系统的当前 cgroup 信息。第一种方法是通过 systemd-cgls 命令来查看,它会返回系统的整体 cgroup 层级,cgroup 树的最高层由 slice 构成,如下所示:

$ systemd-cgls --no-page
├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
├─user.slice
│ ├─user-1000.slice
│ │ └─session-11.scope
│ │   ├─9507 sshd: tom [priv]
│ │   ├─9509 sshd: tom@pts/3
│ │   └─9510 -bash
│ └─user-0.slice
│   └─session-1.scope
│     ├─ 6239 sshd: root@pts/0
│     ├─ 6241 -zsh
│     └─11537 systemd-cgls --no-page
└─system.slice├─rsyslog.service│ └─5831 /usr/sbin/rsyslogd -n├─sshd.service│ └─5828 /usr/sbin/sshd -D├─tuned.service│ └─5827 /usr/bin/python2 -Es /usr/sbin/tuned -l -P├─crond.service│ └─5546 /usr/sbin/crond -n
复制代码

可以看到系统 cgroup 层级的最高层由 user.slicesystem.slice 组成。因为系统中没有运行虚拟机和容器,所以没有 machine.slice,所以当 CPU 繁忙时,user.slicesystem.slice 会各获得 50% 的 CPU 使用时间。

user.slice 下面有两个子 slice:user-1000.sliceuser-0.slice,每个子 slice 都用 User ID (UID) 来命名,因此我们很容易识别出哪个 slice 属于哪个用户。例如:从上面的输出信息中可以看出 user-1000.slice 属于用户 tom,user-0.slice 属于用户 root。

systemd-cgls 命令提供的只是 cgroup 层级的静态信息快照,要想查看 cgroup 层级的动态信息,可以通过 systemd-cgtop 命令查看:

$ systemd-cgtop
Path                                                                                                                                       Tasks   %CPU   Memory  Input/s Output/s/                                                                                                                                            161    1.2   161.0M        -        -
/system.slice                                                                                                                                  -    0.1        -        -        -
/system.slice/vmtoolsd.service                                                                                                                 1    0.1        -        -        -
/system.slice/tuned.service                                                                                                                    1    0.0        -        -        -
/system.slice/rsyslog.service                                                                                                                  1    0.0        -        -        -
/system.slice/auditd.service                                                                                                                   1      -        -        -        -
/system.slice/chronyd.service                                                                                                                  1      -        -        -        -
/system.slice/crond.service                                                                                                                    1      -        -        -        -
/system.slice/dbus.service                                                                                                                     1      -        -        -        -
/system.slice/gssproxy.service                                                                                                                 1      -        -        -        -
/system.slice/lvm2-lvmetad.service                                                                                                             1      -        -        -        -
/system.slice/network.service                                                                                                                  1      -        -        -        -
/system.slice/polkit.service                                                                                                                   1      -        -        -        -
/system.slice/rpcbind.service                                                                                                                  1      -        -        -        -
/system.slice/sshd.service                                                                                                                     1      -        -        -        -
/system.slice/system-getty.slice/getty@tty1.service                                                                                            1      -        -        -        -
/system.slice/systemd-journald.service                                                                                                         1      -        -        -        -
/system.slice/systemd-logind.service                                                                                                           1      -        -        -        -
/system.slice/systemd-udevd.service                                                                                                            1      -        -        -        -
/system.slice/vgauthd.service                                                                                                                  1      -        -        -        -
/user.slice                                                                                                                                    3      -        -        -        -
/user.slice/user-0.slice/session-1.scope                                                                                                       3      -        -        -        -
/user.slice/user-1000.slice                                                                                                                    3      -        -        -        -
/user.slice/user-1000.slice/session-11.scope                                                                                                   3      -        -        -        -
/user.slice/user-1001.slice/session-8.scope                                                                                                    3      -        -        -        -
复制代码

systemd-cgtop 提供的统计数据和控制选项与 top 命令类似,但该命令只显示那些开启了资源统计功能的 service 和 slice。比如:如果你想开启 sshd.service 的资源统计功能,可以进行如下操作:

$ systemctl set-property sshd.service CPUAccounting=true MemoryAccounting=true
复制代码

该命令会在 /etc/systemd/system/sshd.service.d/ 目录下创建相应的配置文件:

$ ll /etc/systemd/system/sshd.service.d/
总用量 8
4 -rw-r--r-- 1 root root 28 5月  31 02:24 50-CPUAccounting.conf
4 -rw-r--r-- 1 root root 31 5月  31 02:24 50-MemoryAccounting.conf$ cat /etc/systemd/system/sshd.service.d/50-CPUAccounting.conf
[Service]
CPUAccounting=yes$ cat /etc/systemd/system/sshd.service.d/50-MemoryAccounting.conf
[Service]
MemoryAccounting=yes
复制代码

配置完成之后,再重启 sshd 服务:

$ systemctl daemon-reload
$ systemctl restart sshd
复制代码

这时再重新运行 systemd-cgtop 命令,就能看到 sshd 的资源使用统计了:

开启资源使用量统计功能可能会增加系统的负载,因为资源统计也要消耗 CPU 和内存,大多数情况下使用 top 命令来查看就足够了。当然了,这是 Linux 系统嘛,一切的控制权都在你自己手里,你想怎么做就怎么做。

2. 分配 CPU 相对使用时间


通过上篇文章的学习我们知道了 CPU shares 可以用来设置 CPU 的相对使用时间,接下来我们就通过实践来验证一下。

下面所做的实验都是在单核 CPU 的系统上进行的,多核与单核的情况完全不同,文末会单独讨论。

测试对象是 1 个 service 和两个普通用户,其中用户 tom 的 UID 是 1000,可以通过以下命令查看:

$ cat /etc/passwd|grep tom
tom:x:1000:1000::/home/tom:/bin/bash
复制代码

创建一个 foo.service

$ cat /etc/systemd/system/foo.service
[Unit]
Description=The foo service that does nothing useful
After=remote-fs.target nss-lookup.target[Service]
ExecStart=/usr/bin/sha1sum /dev/zero
ExecStop=/bin/kill -WINCH ${MAINPID}[Install]
WantedBy=multi-user.target
复制代码

/dev/zero 在 linux 系统中是一个特殊的设备文件,当你读它的时候,它会提供无限的空字符,因此 foo.service 会不断地消耗 CPU 资源。现在我们将 foo.service 的 CPU shares 改为 2048

$ mkdir /etc/systemd/system/foo.service.d
$ cat << EOF > /etc/systemd/system/foo.service.d/50-CPUShares.conf
[Service]
CPUShares=2048
EOF
复制代码

由于系统默认的 CPU shares 值为 1024,所以设置成 2048 后,在 CPU 繁忙的情况下,foo.service 会尽可能获取 system.slice 的所有 CPU 使用时间。

现在通过 systemctl start foo.service 启动 foo 服务,并使用 top 命令查看 CPU 使用情况:

目前没有其他进程在消耗 CPU,所以 foo.service 可以使用几乎 100% 的 CPU。

现在我们让用户 tom 也参与进来,先将 user-1000.slice 的 CPU shares 设置为 256

$ systemctl set-property user-1000.slice CPUShares=256
复制代码

使用用户 tom 登录该系统,然后执行命令 sha1sum /dev/zero,再次查看 CPU 使用情况:

现在是不是感到有点迷惑了?foo.service 的 CPU shares 是 2048,而用户 tom 的 CPU shares 只有 256,难道用户 tom 不是应该只能使用 10% 的 CPU 吗?回忆一下我在上一节提到的,当 CPU 繁忙时,user.slicesystem.slice 会各获得 50% 的 CPU 使用时间。而这里恰好就是这种场景,同时 user.slice 下面只有 sha1sum 进程比较繁忙,所以会获得 50% 的 CPU 使用时间。

最后让用户 jack 也参与进来,他的 CPU shares 是默认值 1024。使用用户 jack 登录该系统,然后执行命令 sha1sum /dev/zero,再次查看 CPU 使用情况:

上面我们已经提到,这种场景下 user.slicesystem.slice 会各获得 50% 的 CPU 使用时间。用户 tom 的 CPU shares 是 256,而用户 jack 的 CPU shares 是 1024,因此用户 jack 获得的 CPU 使用时间是用户 tom 的 4 倍。

3. 分配 CPU 绝对使用时间


上篇文章已经提到,如果想严格控制 CPU 资源,设置 CPU 资源的使用上限,即不管 CPU 是否繁忙,对 CPU 资源的使用都不能超过这个上限,可以通过 CPUQuota 参数来设置。下面我们将用户 tom 的 CPUQuota 设置为 5%

$ systemctl set-property user-1000.slice CPUQuota=5%
复制代码

这时你会看到用户 tom 的 sha1sum 进程只能获得 5% 左右的 CPU 使用时间。

如果此时停止 foo.service,关闭用户 jack 的 sha1sum 进程,你会看到用户 tom 的 sha1sum 进程仍然只能获得 5% 左右的 CPU 使用时间。

如果某个非核心服务很消耗 CPU 资源,你可以通过这种方法来严格限制它对 CPU 资源的使用,防止对系统中其他重要的服务产生影响。

4. 动态设置 cgroup


cgroup 相关的所有操作都是基于内核中的 cgroup virtual filesystem,使用 cgroup 很简单,挂载这个文件系统就可以了。系统默认情况下都是挂载到 /sys/fs/cgroup 目录下,当 service 启动时,会将自己的 cgroup 挂载到这个目录下的子目录。以 foo.service 为例:

先进入 system.slice 的 CPU 子系统:

$ cd /sys/fs/cgroup/cpu,cpuacct/system.slice
复制代码

查看 foo.service 的 cgroup 目录:

$ ls foo.*
zsh: no matches found: foo.*
复制代码

因为 foo.service 没有启动,所以没有挂载 cgroup 目录,现在启动 foo.service,再次查看它的 cgroup 目录:

$ ls foo.serice
cgroup.clone_children  cgroup.procs  cpuacct.usage         cpu.cfs_period_us  cpu.rt_period_us   cpu.shares  notify_on_release
cgroup.event_control   cpuacct.stat  cpuacct.usage_percpu  cpu.cfs_quota_us   cpu.rt_runtime_us  cpu.stat    tasks
复制代码

也可以查看它的 PID 和 CPU shares:

$ cat foo.service/tasks
20225$ cat foo.service/cpu.shares
2048
复制代码

理论上我们可以在 /sys/fs/cgroup 目录中动态改变 cgroup 的配置,但我不建议你在生产环境中这么做。如果你想通过实验来深入理解 cgroup,可以多折腾折腾这个目录。

5. 如果是多核 CPU 呢?


上面的所有实验都是在单核 CPU 上进行的,下面我们简单讨论一下多核的场景,以 2 个 CPU 为例。

首先来说一下 CPU shares,shares 只能针对单核 CPU 进行设置,也就是说,无论你的 shares 值有多大,该 cgroup 最多只能获得 100% 的 CPU 使用时间(即 1 核 CPU)。还是用本文第 2 节的例子,将 foo.service 的 CPU shares 设置为 2048,启动 foo.service,这时你会看到 foo.service 仅仅获得了 100% 的 CPU 使用时间,并没有完全使用两个 CPU 核:

再使用用户 tom 登录系统,执行命令 sha1sum /dev/zero,你会发现用户 tom 的 sha1sum 进程和 foo.service 各使用 1 个 CPU 核:

再来说说 CPUQuota,这个上篇文章结尾已经提过了,如要让一个 cgroup 完全使用两个 CPU 核,可以通过 CPUQuota 参数来设置。例如:

$ systemctl set-property foo.service CPUQuota=200%
复制代码

至于进程最后能不能完全使用两个 CPU 核,就要看它自身的设计支持不支持了。

6. 总结


本文通过具体的示例来观察不同的 cgroup 设置对性能的影响,下面一篇文章将会演示如何通过 cgroup 来限制内存的使用。

转载于:https://juejin.im/post/5cf251d751882566d9269bb3

深入理解 Linux Cgroup 系列(二):玩转 CPU相关推荐

  1. Linux学习系列二:Linux中的常用命令

    这个系列的Linux教程主要参考刘遄老师的<Linux就该这么学>.用的系统是RHEL8,如果遇见一些命令出现问题,请首先检查自己的系统是否一致,如果不一致,可网上查一下系统间某些命令之间 ...

  2. 笔记:深入理解Linux内核(二)

    笔记:深入理解Linux内核(二) 二零二一年十月二十四日 文章目录 笔记:深入理解Linux内核(二) 第二章:内存寻址 内存地址 硬件中的分段 段选择符和段选择器 段描述符 快速访问段描述符 分段 ...

  3. Linux Rootkit 系列二:基于修改 sys_call_table 的系统调用挂钩

    与第一篇文章作者所想象的不同,本文不打算给大家介绍三种不同的系统调用挂钩技术,相反,本文仅详细讲解最简单的系统调用挂钩方案,并且基于这个方案实现最基本的文件监视工具.这样,既可以让读者轻松上手进行实际 ...

  4. linux技术理解,技术|理解 Linux 链接(二)

    我们继续这个系列,来看一些你所不知道的微妙之处. 在本系列的第一篇文章中,我们认识了硬链接.软链接,知道在很多时候链接是非常有用的.链接看起来比较简单,但是也有一些不易察觉的奇怪的地方需要注意.这就是 ...

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

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

  6. linux cgoup内存限制,Linux Cgroup系列(05):限制cgroup的CPU使用(subsystem之cpu)

    在cgroup里面,跟CPU相关的子系统有cpusets.cpuacct和cpu. 其中cpuset主要用于设置CPU的亲和性,可以限制cgroup中的进程只能在指定的CPU上运行,或者不能在指定的C ...

  7. linux cgroup限制cpu,Linux Cgroup系列(05):限制cgroup的CPU使用(subsystem之cpu)

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 描述 在cgroup里面,跟CPU相关的子系统有cpusets.cpuacct和cpu. 其中cpuset主要用于设置C ...

  8. 深入理解Linux虚拟内存管理(二)

    系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核(一) 深入理解 Linux 内核(二) Linux 设备驱动程序(一) Linux 设备驱动程序(二) Linux 设备驱动程序( ...

  9. 深入理解 Linux 内核

    Linux 内核系列文章 Linux 内核设计与实现 深入理解 Linux 内核 深入理解 Linux 内核(二) Linux 设备驱动程序 Linux设备驱动开发详解 文章目录 Linux 内核系列 ...

最新文章

  1. win10 窗口无边框
  2. IOS学习之路五(代码实现UITableView)
  3. 活动 | 参与《我的 ,2019 不一样》投稿,千元奖品,等你拿!
  4. 导出excel 后 页面按钮失效(页面假死)
  5. 实战系列-IDEA中Spring MVC实现接口功能
  6. 零基础入门语义分割-Task6 分割模型模型集成
  7. yolox-keras的源码,超越YOLOv5,可以用于训练自己的模型
  8. linux删除win分区工具,Win 10 和 Linux 双系统,从硬盘删除Linux分区,Win 10引导修复...
  9. 14.深入分布式缓存:从原理到实践 --- 典型电商应用与缓存
  10. 无限分级函数 简单 引用绑值
  11. 关于for in和for循环的遍历
  12. ES 经纬度距离 php,php 根据两点的经纬度计算距离
  13. jconsole远程连接linux,JConsole远程连接
  14. 离散时间傅里叶变换(DTFT)与离散傅里叶级数(DFS)
  15. 拼多多如何引流推广产品?拼多多新产品如何推广?
  16. 学习笔记 | 零基础平面设计入门
  17. V-Play 使用粗体验
  18. 创业期间,应该怎么样坚持下去?如何从容面对困难?
  19. 浅谈游戏中BOSS设计的思路
  20. nacosk8s部署_k8s部署nacos - osc_vh89klm7的个人空间 - OSCHINA - 中文开源技术交流社区...

热门文章

  1. shell中符号使用
  2. 【微软公有云系列】(七)SCVMM模板--Windows server 2012 虚拟机模板
  3. centos5 db_load 命令无法使用
  4. 易宝典文章——如何在Exchange Server 2010 SP1下将用户邮箱导出到PST中
  5. Base64编码原理与实现
  6. 程序员难逃二八法则,如何晋升为头部20%玩家?
  7. Android 源码分析之 EventBus 的源码解析
  8. 买粮油也能玩出新花样?京东超市携手金龙鱼带来狗年礼盒!
  9. 大数据时代 安全与应用的博弈
  10. 传海思砍台积电第三季度一半手机订单