Linux内核揭秘:深入理解Cgroups机制(第一部分)

Linux内核揭秘:深入理解Cgroups机制(第一部分)

linux-insides-zh Linux 内核揭秘 linux-insides-zh 项目地址: https://gitcode.com/gh_mirrors/li/linux-insides-zh

引言

在Linux系统中,资源管理和进程隔离是至关重要的功能。Cgroups(Control Groups)作为Linux内核提供的一种强大机制,允许系统管理员对系统资源进行细粒度的分配和控制。本文将深入探讨Cgroups的核心概念、工作原理及其在内核中的实现方式。

Cgroups基础概念

什么是Cgroups?

Cgroups是Linux内核提供的一种机制,用于将进程分组并进行资源限制、优先级分配、资源统计等操作。通过Cgroups,我们可以:

  1. 限制进程组使用的CPU时间
  2. 控制内存使用量
  3. 限制磁盘I/O带宽
  4. 控制网络访问权限
  5. 冻结/恢复进程组

Cgroups的核心特性

Cgroups具有几个关键特性:

  1. 层级结构:类似于进程树,但更灵活
  2. 子系统支持:每个层级可以附加不同的资源控制子系统
  3. 继承性:子cgroup会继承父cgroup的部分属性
  4. 多层级共存:不同于单一进程树,多个不同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

我们希望限制这个脚本对终端设备的访问权限。

操作步骤

  1. 创建cgroup

    cd /sys/fs/cgroup/devices
    mkdir cgroup_test_group
    
  2. 查看自动生成的控制文件

    ls cgroup_test_group
    

    会看到自动生成的多个控制文件,包括:

    • tasks:管理属于该cgroup的进程
    • devices.deny:定义拒绝访问的设备
  3. 限制设备访问

    echo "c 5:0 w" > devices.deny
    

    这条命令表示禁止对主设备号5、次设备号0的字符设备(即/dev/tty)进行写操作。

  4. 将进程加入cgroup

    echo $(pidof -x script.sh) > tasks
    
  5. 验证效果: 脚本将无法再向终端输出信息,并会收到"Operation not permitted"错误。

Cgroups在内核中的实现

关键数据结构

Linux内核使用几个核心数据结构来实现Cgroups机制:

  1. 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;
        // ... 其他字段
    };
    
  2. cgroup:表示一个控制组

    struct cgroup {
        struct cgroup_subsys_state self;
        struct cgroup *parent;
        // ... 其他字段
    };
    
  3. css_set:连接进程和cgroup的桥梁

    struct css_set {
        struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
        // ... 其他字段
    };
    

初始化过程

Cgroups的初始化分为早期和晚期两个阶段。早期初始化主要完成以下工作:

  1. 初始化默认的cgroup层级结构

    init_cgroup_root(&cgrp_dfl_root, &opts);
    
  2. 为init进程分配初始css_set

    RCU_INIT_POINTER(init_task.cgroups, &init_css_set);
    
  3. 初始化标记为"early_init"的子系统

    for_each_subsys(ss, i) {
        if (ss->early_init)
            cgroup_init_subsys(ss, true);
    }
    

总结

本文介绍了Linux Cgroups机制的基本概念、使用方法和内核实现的基础知识。我们了解到:

  1. Cgroups提供了强大的资源管理和隔离能力
  2. 通过sysfs可以手动管理cgroup
  3. 内核使用层级化的数据结构实现cgroup
  4. 初始化过程分为早期和晚期两个阶段

在下一部分中,我们将继续深入探讨Cgroups更高级的功能和实现细节,包括:

  • 晚期初始化过程
  • 动态cgroup管理
  • 子系统交互机制
  • 性能考量

通过深入理解Cgroups的工作原理,系统管理员和开发者可以更好地利用这一机制来优化系统资源分配,提高系统稳定性和安全性。

linux-insides-zh Linux 内核揭秘 linux-insides-zh 项目地址: https://gitcode.com/gh_mirrors/li/linux-insides-zh

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牧丁通

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值