当前位置: 首页 > news >正文

Docker 核心技术:Linux Cgroups

在这里插入图片描述
大家好,我是费益洲。Linux Cgroups 作为 Docker 的技术核心之一,主要作用就是限制、控制和统计进程的系统资源 ​​(如 CPU、内存、磁盘 I/O 等)。容器的本质其实就是 Linux 的一个进程,限制、控制和统计容器的系统资源,其实就是限制、控制和统计进程的系统资源,本文将从 Linux 内核源码的层面,谈谈如何通过 Cgroups 实现限制系统资源。

本文中的的内核源码版本为linux-5.10.1,具体的源码可以自行下载查看,本文只列举关键代码。

🔗 内核源码官方地址:www.kernel.org,linux-5.10.1 源码下载地址:linux-5.10.1.tar.xz

概念

Cgroups 的全称是 Control Groups,是 Linux 内核提供的一种机制,用于限制、控制和统计一组进程所使用的物理资源。它最早由 Google 工程师在 2006 年发起,最初称为"进程容器"(Process Containers),后来在 2007 年更名为 Cgroups,并在 2008 年合并到 Linux 2.6.24 内核中,2016 年 Linux 4.5 内核引入第二代(cgroup v2)。

特性 cgroup v1 cgroup v2
设计 多层级树,子系统独立管理 单一层级树,统一资源管理
​​ 内存 memory 子系统独立 整合内存、swap、内核内存
CPU cpu 与 cpuacct 分离 统一通过 cpu 控制权重和上限
启动 旧版内核 Linux 4.5+ 内核

与 Cgroups 相关的关键概念如下:

  1. 层级结构(Hierarchy)

    • 树形组织,子级 cgroup 进程继承父级 cgroup 的限制(如/sys/fs/cgroup/memory/father/childchild 初始继承 father 的限制)
  2. 子系统(Subsystem)

    • 每个子系统管理一类资源,具体可以通过ls -al /sys/fs/cgroup/mygroup查看,常用的子系统包括:
      子系统 功能
      blkio 限制块设备 I/O 带宽(如磁盘读写)
      cpu 控制 cpu 时间分配
      cpuacct 统计 CPU 使用情况
      devices 控制设备访问权限(如禁止容器访问磁盘)
      freezer 挂起或恢复进程
      memory 限制内存使用量,统计内存消耗
      net_cls 标记网络数据包,配合 tc 实现网络限速
      pids 限制进程数
  3. 任务(Task)

    • 进程或线程,可加入多个 cgroup(每个子系统层级仅属一个 cgroup)
  4. 文件系统接口

    • 通过虚拟文件系统(挂载于 /sys/fs/cgroup)配置参数:
    # 限制内存为 1GB
    echo 1G > /sys/fs/cgroup/memory/mygroup/memory.limit_in_bytes
    # 将进程加入 cgroup
    echo 1234 > /sys/fs/cgroup/memory/mygroup/cgroup.procs
    
    • 子级文件系统接口可以通过mkdir命令在父级文件系统接口目录下创建,并会自动创建并继承父级文件系统接口的配置
    [root@master01 ~]# cd /sys/fs/cgroup/memory
    [root@master01 memory]# mkdir mygroup
    [root@master01 memory]# ls mygroup/
    cgroup.clone_children           memory.kmem.tcp.failcnt             memory.numa_stat
    cgroup.event_control            memory.kmem.tcp.limit_in_bytes      memory.oom_control
    cgroup.kill                     memory.kmem.tcp.max_usage_in_bytes  memory.pressure_level
    cgroup.procs                    memory.kmem.tcp.usage_in_bytes      memory.qos_level
    memory.events                   memory.kmem.usage_in_bytes          memory.reclaim
    memory.events.local             memory.ksm                          memory.soft_limit_in_bytes
    memory.failcnt                  memory.limit_in_bytes               memory.stat
    memory.flag_stat                memory.low                          memory.swapfile
    memory.force_empty              memory.max_usage_in_bytes           memory.swap.max
    memory.force_swapin             memory.memfs_files_info             memory.swappiness
    memory.high                     memory.memsw.failcnt                memory.usage_in_bytes
    memory.high_async_ratio         memory.memsw.limit_in_bytes         memory.use_hierarchy
    memory.kmem.failcnt             memory.memsw.max_usage_in_bytes     memory.wb_blkio_ino
    memory.kmem.limit_in_bytes      memory.memsw.usage_in_bytes         notify_on_release
    memory.kmem.max_usage_in_bytes  memory.min                          tasks
    memory.kmem.slabinfo            memory.move_charge_at_immigrate
    

⚠️ 不要直接修改根目录(/sys/fs/cgroup)下的子系统配置

Cgroups 的生命周期和回收策略

Cgroups 的创建过程

进程结构体task_struct的定义在文件linux-5.10.1/include/linux/sched.h中,与 Cgroups 相关的关键数据结构如下所示:

struct task_struct {
// ...(省略部分代码)/* Control Group info protected by css_set_lock: */struct css_set __rcu		*cgroups;/* cg_list protected by css_set_lock and tsk->alloc_lock: */struct list_head		cg_list;// ...(省略部分代码)
}
  • css_set:
    • 包含进程组共享的子系统状态数组(subsys[CGROUP_SUBSYS_COUNT])
    • 通过 tasks 链表关联所有绑定至此的进程
  • list_head: 链入 css_set 的 tasks 链表

接下来从进程创建的过程,来说明进程的创建过程中,创建 Cgroups 的过程。创建进程的系统调用函数有三个:fork()、vfork()、clone()。当调用 fork()、vfork()、clone()时,最终都会调用同一个函数 kernel_clone(),和 Cgroups 创建关联的关键函数调用是 copy_process()

pid_t kernel_clone(struct kernel_clone_args *args)
{// ...(省略部分代码)// line 2456p = copy_process(NULL, trace, NUMA_NO_NODE, args);// ...(省略部分代码)
}

copy_process()函数和 Cgroups 创建关联的关键函数调用是有三个,cgroup_fork()、cgroup_can_fork()、cgroup_post_fork():

static __latent_entropy struct task_struct 
http://www.dtcms.com/a/341707.html

相关文章:

  • GDB 的多线程调试
  • 针对具有下垂控制光伏逆变器的主动配电网络的多目标分层协调电压/无功控制方法的复现
  • 音频读写速度优化 音频格式
  • Transformer内容详解(通透版)
  • pip install -e中e 参数解释
  • 八辊矫平机·第三篇
  • 卸载win10/win11系统里导致磁盘故障的补丁
  • 广东省省考备考(第八十二天8.20)——资料分析、数量、言语(强化训练)
  • 【蒸蒸日上】军八武将篇——标1
  • 8 webUI中-Controlnet(控制与约束)的应用分类与使用方法
  • 【语法】markdown非常用场景
  • Netty HashedWheelTimer设计原理:从时间轮算法到源码实现
  • 跨平台 RTSP/RTMP 播放器工程化实践:低延迟与高稳定性的挑战与突破
  • 【数据分享】东北大鼠疫传播与死亡空间数据
  • Vue透传 Attributes(详细解析)2
  • 恶补DSP:2.F28335的定时器系统
  • 买返商城网站源码多平台购物返现搭建图解源码二开
  • 万象生鲜配送系统 2025 年 8 月 15 日更新日志
  • 八月月报丨MaxKB在教育及教学科研领域的应用进展
  • Hadoop学习
  • 达梦数据库-实时主备集群部署详解(附图文)手工搭建一主一备数据守护集群DW
  • HyDE vs HyPE:AI检索界的‘假想敌’革命,如何让RAG系统从‘找资料’变成‘懂你心’?”
  • Firefox 142 引入 CRLite 用于私有证书撤销
  • 【AI应用】部署AI向量数据库Milvus
  • Oracle:配置让插入语句时id自动输入
  • Sora网页打不开怎么办?常见原因与解决方法
  • 从零开始:打造一个现代化的BMI计算器Web应用
  • JVM面试精选 20 题(终)
  • 数据结构之排序大全(2)
  • 【科研绘图系列】R语言绘制平滑曲线折线图