Linux内核揭秘:深入理解Cgroups机制(第一部分)
linux-insides-zh Linux 内核揭秘 项目地址: https://gitcode.com/gh_mirrors/li/linux-insides-zh
引言
在Linux系统中,资源管理和进程隔离是至关重要的功能。Cgroups(Control Groups)作为Linux内核提供的一种强大机制,允许系统管理员对系统资源进行细粒度的分配和控制。本文将深入探讨Cgroups的核心概念、工作原理及其在内核中的实现方式。
Cgroups基础概念
什么是Cgroups?
Cgroups是Linux内核提供的一种机制,用于将进程分组并进行资源限制、优先级分配、资源统计等操作。通过Cgroups,我们可以:
- 限制进程组使用的CPU时间
- 控制内存使用量
- 限制磁盘I/O带宽
- 控制网络访问权限
- 冻结/恢复进程组
Cgroups的核心特性
Cgroups具有几个关键特性:
- 层级结构:类似于进程树,但更灵活
- 子系统支持:每个层级可以附加不同的资源控制子系统
- 继承性:子cgroup会继承父cgroup的部分属性
- 多层级共存:不同于单一进程树,多个不同cgroup层级可以同时存在
Cgroups子系统详解
Linux内核支持多种cgroup子系统,每种子系统负责管理特定类型的资源:
| 子系统名称 | 功能描述 | |------------|----------| | cpuset | 分配独立的CPU和内存节点 | | cpu | 控制CPU时间分配 | | cpuacct | 统计CPU使用情况 | | memory | 限制内存使用量 | | devices | 控制设备访问权限 | | freezer | 挂起/恢复进程组 | | net_cls | 标记网络数据包 | | net_prio | 设置网络流量优先级 | | perf_event | 访问性能事件 | | hugetlb | 管理大页内存 | | pid | 限制进程数量 |
实践:手动使用Cgroups
为了更好地理解Cgroups,让我们通过一个实际例子来演示如何使用它。
示例场景
假设我们有一个持续向终端输出信息的脚本:
#!/bin/bash
while :; do
echo "print line" > /dev/tty
sleep 5
done
我们希望限制这个脚本对终端设备的访问权限。
操作步骤
-
创建cgroup:
cd /sys/fs/cgroup/devices mkdir cgroup_test_group
-
查看自动生成的控制文件:
ls cgroup_test_group
会看到自动生成的多个控制文件,包括:
tasks
:管理属于该cgroup的进程devices.deny
:定义拒绝访问的设备
-
限制设备访问:
echo "c 5:0 w" > devices.deny
这条命令表示禁止对主设备号5、次设备号0的字符设备(即/dev/tty)进行写操作。
-
将进程加入cgroup:
echo $(pidof -x script.sh) > tasks
-
验证效果: 脚本将无法再向终端输出信息,并会收到"Operation not permitted"错误。
Cgroups在内核中的实现
关键数据结构
Linux内核使用几个核心数据结构来实现Cgroups机制:
-
cgroup_subsys:表示一个cgroup子系统
struct cgroup_subsys { int (*css_online)(struct cgroup_subsys_state *css); void (*css_offline)(struct cgroup_subsys_state *css); bool early_init; int id; const char *name; struct cgroup_root *root; // ... 其他字段 };
-
cgroup:表示一个控制组
struct cgroup { struct cgroup_subsys_state self; struct cgroup *parent; // ... 其他字段 };
-
css_set:连接进程和cgroup的桥梁
struct css_set { struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; // ... 其他字段 };
初始化过程
Cgroups的初始化分为早期和晚期两个阶段。早期初始化主要完成以下工作:
-
初始化默认的cgroup层级结构
init_cgroup_root(&cgrp_dfl_root, &opts);
-
为init进程分配初始css_set
RCU_INIT_POINTER(init_task.cgroups, &init_css_set);
-
初始化标记为"early_init"的子系统
for_each_subsys(ss, i) { if (ss->early_init) cgroup_init_subsys(ss, true); }
总结
本文介绍了Linux Cgroups机制的基本概念、使用方法和内核实现的基础知识。我们了解到:
- Cgroups提供了强大的资源管理和隔离能力
- 通过sysfs可以手动管理cgroup
- 内核使用层级化的数据结构实现cgroup
- 初始化过程分为早期和晚期两个阶段
在下一部分中,我们将继续深入探讨Cgroups更高级的功能和实现细节,包括:
- 晚期初始化过程
- 动态cgroup管理
- 子系统交互机制
- 性能考量
通过深入理解Cgroups的工作原理,系统管理员和开发者可以更好地利用这一机制来优化系统资源分配,提高系统稳定性和安全性。
linux-insides-zh Linux 内核揭秘 项目地址: https://gitcode.com/gh_mirrors/li/linux-insides-zh
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考