1.2. cgroup 的默认层级
默认情况下,systemd 会自动创建 slice、scope 和 service 单位的层级,来为 cgroup 树提供统一结构。使用
systemctl
指令,您可以通过创建自定义 slice 进一步修改此结构,详情请参阅〈第 2.1 节 “创建控制群组”〉。systemd 也自动为 /sys/fs/cgroup/
目录中重要的 kernel 资源管控器(参见〈Red Hat Enterprise Linux 7 中可用的管控器〉)挂载层级。
警告
虽然不推荐使用
libcgroup
软件包中的 cgconfig
工具,但它可以为 systemd (尤其是 net-prio
管控器)暂不支持的管控器挂载、处理层级。永远不要使用 libcgropup
工具去修改 systemd 默认挂载的层级,否则可能会导致异常情况。在 Red Hat Enterprise Linux 后续版本中,libcgroup
软件库将会被移除。更多关于如何使用 cgconfig
的信息,请参考〈第 3 章 使用 libcgroup 工具〉。
systemd 的单位类型
系统中运行的所有进程,都是 systemd init 进程的子进程。在资源管控方面,systemd 提供了三种单位类型(如需
systemd
单位类型完整列表,请参阅《Red Hat Enterprise Linux 7 系统管理员指南 · 使用 systemd 管理 service》):
- service —— 一个或一组进程,由
systemd
依据单位配置文件启动。service 对指定进程进行封装,这样进程可以作为一个整体被启动或终止。service 参照以下方式命名:name.
service
其中,name 代表服务名称。 - scope —— 一组外部创建的进程。由强制进程通过
fork()
函数启动和终止、之后被 systemd 在运行时注册的进程,scope 会将其封装。例如:用户会话、 容器和虚拟机被认为是 scope。scope 的命名方式如下:name.
scope
其中,name 代表 scope 名称。 - slice —— 一组按层级排列的单位。slice 并不包含进程,但会组建一个层级,并将 scope 和 service 都放置其中。真正的进程包含在 scope 或 service 中。在这一被划分层级的树中,每一个 slice 单位的名字对应通向层级中一个位置的路径。小横线("
-
")起分离路径组件的作用。例如,如果一个 slice 的名字是:parent-name.
slice
这说明 parent-name.slice
是 parent.slice
的一个子 slice。这一子 slice 可以再拥有自己的子 slice,被命名为:parent-name-name2.slice
,以此类推。根 slice 的表示方式:-.slice
service、scope 和 slice 单位直接映射到 cgroup 树中的对象。当这些单位被激活,它们会直接一一映射到由单位名建立的 cgroup 路径中。例如,ex.service 属于 test-waldo.slice,会直接映射到 cgroup
test.slice/test-waldo.slice/ex.service/
中。
service、scope 和 slice 是由系统管理员手动创建或者由程序动态创建的。默认情况下, 操作系统会定义一些运行系统必要的内置 service。另外,默认情况下,系统会创建四种 slice:
- -.slice —— 根 slice;
- system.slice —— 所有系统 service 的默认位置;
- user.slice —— 所有用户会话的默认位置;
- machine.slice —— 所有虚拟机和 Linux 容器的默认位置。
请注意,所有的用户会话、虚拟机和容器进程会被自动放置在一个单独的 scope 单元中。而且,所有的用户会分得一个隐含子 slice(implicit subslice)。除了上述的默认配置,系统管理员可能会定义新的 slice,并将 service 和 scope 置于其中。
以下是一个 cgroup 树的简化例子。使用〈第 2.4 节 “获得关于控制群组的信息”〉中记述的
systemd-cgls
指令,这一输出就会出现:
├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 20 ├─user.slice │ └─user-1000.slice │ └─session-1.scope │ ├─11459 gdm-session-worker [pam/gdm-password] │ ├─11471 gnome-session --session gnome-classic │ ├─11479 dbus-launch --sh-syntax --exit-with-session │ ├─11480 /bin/dbus-daemon --fork --print-pid 4 --print-address 6 --session │ ... │ └─system.slice ├─systemd-journald.service │ └─422 /usr/lib/systemd/systemd-journald ├─bluetooth.service │ └─11691 /usr/sbin/bluetoothd -n ├─systemd-localed.service │ └─5328 /usr/lib/systemd/systemd-localed ├─colord.service │ └─5001 /usr/libexec/colord ├─sshd.service │ └─1191 /usr/sbin/sshd -D │ ...
如您所见,service 和 scope 包含进程,但被放置在不包含它们自身进程的 slice 里。唯一例外是位于特殊 systemd.slice 中的 PID 1。请注意,-.slice 未被显示,因为它被整体树的根隐性识别。
service 和 slice 单位可通过〈第 2.3.2 节 “修改单位文件”〉中的永久单位文件来配置;或者对 PID 1 进行 API 调用(如需要 API 的详细信息,请参阅〈“在线文档 ”一节〉),在运行时动态创建。scope 单位只能以第一种方式创建。API 调用动态创建的单位是临时的,并且仅在运行时存在。一旦结束、被关闭或者系统重启,临时单位会被自动释放。