Linux cgroup:目录结构与子系统

一、cgroup目录结构深度解析

1.1 默认挂载点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# cgroup v1的典型目录结构(子系统独立)
/sys/fs/cgroup/
├── cpu,cpuacct
├── memory
├── devices
├── blkio
├── net_cls
└── ...

# cgroup v2的统一层级结构(现代系统)
/sys/fs/cgroup/
├── system.slice
├── user.slice
├── unified/ # 所有控制器统一挂载
├── cgroup.controllers
├── cgroup.subtree_control
└── ...

1.2 核心目录说明

路径 作用描述
/sys/fs/cgroup/ 默认挂载根目录
cpu,cpuacct/ (v1) CPU资源控制与统计子系统
memory/ (v1) 内存限制与统计
unified/ (v2) v2的统一控制目录,包含所有可用控制器
cgroup.procs 当前cgroup包含的进程ID
cgroup.controllers (v2) 显示当前层级可用的控制器列表
cgroup.subtree_control (v2) 控制子目录可用的控制器

二、cgroup子系统全解(v1/v2对比)

2.1 CPU控制类

cpu子系统(v1)

1
2
3
4
5
6
7
8
9
/sys/fs/cgroup/cpu/
├── cpu.shares # CPU时间片权重(相对值)
├── cpu.cfs_period_us # 周期时长(默认100000μs)
├── cpu.cfs_quota_us # 周期内最大可用时间(设置50%限制:50000)
└── cpu.stat # 使用统计(nr_periods, nr_throttled)

# 示例:限制50% CPU
echo 100000 > cpu.cfs_period_us
echo 50000 > cpu.cfs_quota_us

cpuacct子系统(v1)

1
2
3
/sys/fs/cgroup/cpu,cpuacct/
├── cpuacct.usage # 累计CPU时间(纳秒)
└── cpuacct.stat # 用户/系统态时间统计

v2的CPU控制

1
2
3
4
/sys/fs/cgroup/unified/
├── cpu.max # 替代cfs_quota(格式:$MAX $PERIOD)
├── cpu.weight # 替代cpu.shares(1-10000)
└── cpu.stat # 增强统计(包含pressure信息)

2.2 内存控制类

memory子系统(v1)

1
2
3
4
5
6
/sys/fs/cgroup/memory/
├── memory.limit_in_bytes # 内存硬限制
├── memory.soft_limit_in_bytes # 软限制(优先回收)
├── memory.usage_in_bytes # 当前使用量
├── memory.oom_control # OOM控制(0/1禁用OOM killer)
└── memory.stat # 详细统计(cache, swap, pgfault等)

v2内存控制

1
2
3
4
5
/sys/fs/cgroup/unified/
├── memory.max # 最大内存(含swap)
├── memory.swap.max # 单独swap限制
├── memory.high # 软限制阈值
└── memory.pressure # 内存压力状态信息

2.3 块设备I/O控制

blkio子系统(v1)

1
2
3
4
/sys/fs/cgroup/blkio/
├── blkio.throttle.read_bps_device # 读速率限制(设备号:限速值)
├── blkio.throttle.write_iops_device # 写IOPS限制
└── blkio.time # 设备I/O时间统计

v2的IO控制

1
2
3
/sys/fs/cgroup/unified/
├── io.max # 设备限速(格式:major:minor rbps=... wiops=...)
└── io.stat # 增强统计(包含延迟百分位数据)

2.4 其他关键子系统

devices(v1)

1
2
3
/sys/fs/cgroup/devices/
├── devices.allow # 允许的设备访问规则(格式:类型 主设备号:次设备号 权限)
└── devices.deny # 禁止访问规则(如拒绝所有:a *:* rwm)

freezer(v1/v2)

1
2
/sys/fs/cgroup/freezer/
└── freezer.state # 进程冻结状态(可设置:FROZEN/THAWED)

net_cls(v1)

1
2
/sys/fs/cgroup/net_cls/
└── net_cls.classid # 设置网络流量分类ID(用于tc过滤)

三、v1与v2的目录结构对比

3.1 v1的多层级结构

1
2
3
4
5
6
7
8
/sys/fs/cgroup/
├── cpu,cpuacct/ # 独立挂载的子系统
│ ├── user.slice
│ └── system.slice
├── memory/
│ ├── user.slice
│ └── system.slice
└── ...

特点:

  • 每个子系统独立层级
  • 允许不同子系统组合挂载
  • 结构复杂,存在资源竞争可能性

3.2 v2的统一层级

1
2
3
4
5
6
7
8
9
10
/sys/fs/cgroup/
├── cgroup.controllers # 可用控制器列表
├── cgroup.subtree_control # 子目录启用控制器
├── system.slice/ # 所有控制器统一生效
│ ├── cpu.max
│ ├── memory.max
│ └── ...
└── user.slice/
├── user-1000.slice
└── ...

特点:

  • 单一层级树结构
  • 控制器必须统一启用
  • 避免资源竞争,增强一致性

四、核心配置文件详解

4.1 v1的关键控制文件

文件路径 功能描述
cpu.shares CPU时间片权重(默认1024)
memory.kmem.limit_in_bytes 内核内存限制(需要开启CONFIG_MEMCG_KMEM
blkio.weight 块设备I/O权重(100-1000)
cpuset.cpus 允许使用的CPU核心(如0-3,5)
net_prio.ifpriomap 设置网络接口优先级(eth0 5)

4.2 v2新增关键文件

文件路径 功能描述
cgroup.type 显示cgroup类型(domain, threaded等)
memory.reclaim 手动触发内存回收(echo 1G > reclaim 回收1G内存)
io.pressure 显示I/O压力指标(avg60, avg300等)
cpu.pressure CPU调度延迟压力信息

五、子系统组合使用示例

5.1 创建复合资源限制组(v1)

1
2
3
4
5
6
# 创建同时限制CPU和内存的cgroup
cgcreate -g cpu,memory:/myapp_group

# 设置参数
echo 50000 > /sys/fs/cgroup/cpu/myapp_group/cpu.cfs_quota_us
echo 2G > /sys/fs/cgroup/memory/myapp_group/memory.limit_in_bytes

5.2 v2统一控制示例

1
2
3
4
5
6
7
8
9
# 启用子目录的cpu和memory控制器
echo "+cpu +memory" > /sys/fs/cgroup/unified/cgroup.subtree_control

# 创建子cgroup
mkdir /sys/fs/cgroup/unified/myapp_v2

# 设置限制
echo "50000 100000" > myapp_v2/cpu.max
echo "2G" > myapp_v2/memory.max

六、调试技巧:查看cgroup归属

1
2
3
4
5
6
7
8
# 查看进程所属cgroup
cat /proc/<PID>/cgroup

# 示例输出:
0::/user.slice/user-1000.slice/session-2.scope

# 使用systemd-cgls查看层级
systemd-cgls --all

七、高级特性解析

7.1 内存压力通知(v2)

1
2
3
4
5
6
# 监控内存压力事件
cat /sys/fs/cgroup/unified/memory.pressure

# 输出示例:
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

7.2 权重分配策略(v2)

1
2
3
4
5
# 设置CPU权重(默认100)
echo 300 > cpu.weight

# 设置IO权重(默认100)
echo 500 > io.weight

欢迎关注我的其它发布渠道