Linux CGroup 原理

article/2025/10/14 11:10:40

Linux CGroup 原理

1、CGroup简介

cgroups是Linux下控制一个(或一组)进程的资源限制机制,全称是control groups,可以对cpu、内存等资源做精细化控制。

开发者可以直接基于cgroups来进行进程资源控制,比如8核的机器上部署了一个web服务和一个计算服务,可以让web服务仅可使用其中6个核,把剩下的两个核留给计算服务。cgroups cpu限制除了可以限制使用多少/哪几个核心之外,还可以设置cpu占用比(注意占用比是各自都跑满情况下的使用比例,如果一个cgroup空闲而另一个繁忙,那么繁忙的cgroup是有可能占满整个cpu核心的)。

2、CGroup子系统

从实现角度来看,cgroups实现了一个通用的进程分组框架,不同资源的具体管理工作由各cgroup子系统(subsystem)来实现,一个子系统就是一个资源控制器。当需要多个限制策略,比如同时针对cpu和内存进行限制,则同时关联多个cgroup子系统即可。

cgroups子系统

cgroups为每种资源定义了一个子系统,在/sys/fs/cgroup/这个目录下可以看到cgroup子系统,典型的子系统如下:

  • cpu 子系统,主要限制进程的 cpu 使用率。
  • cpuacct 子系统,可以统计 cgroups 中的进程的 cpu 使用报告。
  • cpuset 子系统,可以为 cgroups 中的进程分配单独的 cpu 节点或者内存节点。
  • memory 子系统,可以限制进程的 memory 使用量。
  • blkio 子系统,可以限制进程的块设备 io。
  • devices 子系统,可以控制进程能够访问某些设备。
  • net_cls 子系统,可以标记 cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制。
  • freezer 子系统,可以挂起或者恢复 cgroups 中的进程。
  • ns 子系统,可以使不同 cgroups 下面的进程使用不同的 namespace。

每个子系统都是定义了一套限制策略,它们需要与内核的其他模块配合来完成资源限制功能,比如对 cpu 资源的限制是通过进程调度模块根据 cpu 子系统的配置来完成的;对内存资源的限制则是内存模块根据 memory 子系统的配置来完成的,而对网络数据包的控制则需要 Traffic Control 子系统来配合完成。

hierarchy:控制族群可以组织成 hierarchical 的形式,既一颗控制族群树。控制族群树上的子节点控制族群是父节点控制族群的孩子,继承父控制族群的特定的属性;

3、CGroup的层级结构

在cgrups中一个进程可以加入到某个cgroup,也从一个进程组迁移到另一个cgroup。一个进程组的进程可以使用 cgroups 以控制族群为单位分配的资源,同时受到 cgroups 以控制族群为单位设定的限制。

多个cgroup形成一个层级结构(树形结构),cgroup树上的子节点cgroup是父节点cgroup的孩子,继承父cgroup的特定的属性。注意:cgroups层级只会关联某个子系统之后才能进行对应的资源控制,一个子系统附加到某个层级以后,这个层级上的所有cgroup都受到这个子系统的控制。

他们之间的互相关系是:

  • 每次在系统中创建新层级时,该系统中的所有任务都是那个层级的默认 cgroup(我们称之为 root cgroup,此 cgroup 在创建层级时自动创建,后面在该层级中创建的 cgroup 都是此 cgroup 的后代)的初始成员;

  • 一个子系统最多只能附加到一个层级;

  • 一个层级可以附加多个子系统;

  • 一个任务可以是多个 cgroup 的成员,但是这些 cgroup 必须在不同的层级;

  • 系统中的进程(任务)创建子进程(任务)时,该子任务自动成为其父进程所在 cgroup 的成员。然后可根据需要将该子任务移动到不同的 cgroup 中,但开始时它总是继承其父任务的 cgroup。

4、CGroup文件子系统

Linux 使用了多种数据结构在内核中实现了 cgroups 的配置,关联了进程和 cgroups 节点(见第5节),并使用VFS将cgroups功能暴露用户态的进程,VFS给用户态进程提供一个统一的文件系统 API 接口,cgroups 与 VFS 之间的衔接部分称之为 cgroups 文件系统。通过cgroups适配VFS,用户可以使用VFS接口来操作cgroup功能。

以freezer子系统为例,这个子系统可以对一组线程批量冻结,使用下面命令将打开freezer子系统:

mount cgroup none /dev/freezer freezer

该命令将子系统挂载于/dev/freezer目录,接下来可以在/dev/freezer目录下创建若干个目录,例如目录top、background,每个目录代表一组线程的资源分配行为,以cgroup实例描述,那么多级的目录以cgroup实例的形式组成了一个树形结构。接下来,可以给top组或者background组配置组内进程,

echo 1199 > /dev/freezer/top/cgroup.procs

当前cgroup版本已经不支持同一进程组内不同线程分属于子系统内不同cgroup。配置完top组内的线程后,可以通过操作freezer.state节点配置组内所有线程冻结:

echo FROZEN > /dev/freezer/top/freezer.state

解冻组内所有线程:

echo THAW > /dev/freezer/top/freezer.state

5、cgroups原理

关于cgroups原理,可以从进程角度来剖析相关数据结构之间关系,Linux 下管理进程的数据结构是 task_struct,其中与cgrups相关属性如下:

// task_struct代码
#ifdef CONFIG_CGROUPS 
/* Control Group info protected by css_set_lock */ 
struct css_set *cgroups; 
/* cg_list protected by css_set_lock and tsk->alloc_lock */ 
struct list_head cg_list; 
#endif

每个进程对应一个css_set结构,css_set存储了与进程相关的cgropus信息。cg_list是一个嵌入的 list_head 结构,用于将连到同一个 css_set 的进程组织成一个链表。进程和css_set的关系是多对一关系,tasks表示关联的多个进程。

struct css_set { atomic_t refcount;struct hlist_node hlist; struct list_head tasks; struct list_head cg_links; struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; struct rcu_head rcu_head; 
};

subsys 是一个指针数组,存储一组指向 cgroup_subsys_state 的指针,通过这个指针进程可以获取到对应的cgroups信息,一个 cgroup_subsys_state 就是进程与一个特定子系统相关的信息,cgroup_subsys_state结构体如下:

struct cgroup_subsys_state {struct cgroup *cgroup;atomic_t refcnt;unsigned long flags;struct css_id *id;
};

cgroup 指针指向了一个 cgroup 结构,也就是进程属于的 cgroup,进程受到子系统控制就是加入到特定的cgroup来实现的,就是对应这里的cgroup,由此看出进程和cgroup的关系是多对多关系。

struct cgroup {unsigned long flags; atomic_t count; struct list_head sibling; struct list_head children; struct cgroup *parent; struct dentry *dentry; struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; struct cgroupfs_root *root;struct cgroup *top_cgroup; struct list_head css_sets; struct list_head release_list; struct list_head pidlists;struct mutex pidlist_mutex; struct rcu_head rcu_head; struct list_head event_list; spinlock_t event_list_lock; 
};

sibling、children 和 parent 三个嵌入的 list_head 负责将统一层级的 cgroup 连接成一棵 cgroup 树。subsys 是一个指针数组,存储一组指向 cgroup_subsys_state 的指针。这组指针指向了此 cgroup 跟各个子系统相关的信息,也就是说一个cgroup可以关联多个子系统,二者关系是多对多关系。

Linux下的cgroups的数据结构图示如下:

[外链图片转存失败,源站可能有防盗]!链机制,建(htps://luoxn28.github.io/2020/01/04/cgroup-yuan-li-jie-xi/cgroup%E5%8E%9F%E7%90%86%E8%A7%A3%E6%9E%90/image-20200104135253154.png)]

6、以冷冻子系统为例梳理CGroup的核心逻辑

当某个子系统被挂载使能后,系统中所有线程默认处于子系统根目录所代表的cgroup实例中。

1. 配置task到目标cgroup

用户或者应用程序通过往cgroup.procs节点写入pid,cgroup.procs节点的write函数对应到cgroup_procs_write。

Image

cgroup_kn_lock_live函数根据当前节点目录解析到该目录所对应的cgroup实体,通过写权限检查以后,进入到主逻辑cgroup_attach_task函数里。

Image

cgroup_migrate_prepare_dst函数利用保存的当前css_set,查找是否存在满足条件的目标css_set,如果不存在满足条件的目标css_set,则创建一个新的css_set,插入多对多二维关系链表中。接下来cgroup_migrate函数将task从源css_set迁移到目标css_set中。

2. 操控cgroup属性

以freezer子系统为例,通过freezer.state节点控制cgroup组的冻结与解冻,这个节点对应到freezer_write函数,实际的逻辑在freezer_change_state函数中。(freezer.c)

Image

freezer_change_state函数第一个参数属于freezer结构体,它通过内嵌的cgroup_subsys_state结构与cgroup关联,也就是说每个freezer结构体直接对应到freezer子系统的一个目录。接下来看函数逻辑,css_for_each_descendant_pre循环体里对当前目录以及每个子孙目录所代表cgroup实体执行freezer_apply_state函数。freezer_apply_state函数通过调用freeze_cgroup和unfreeze_cgroup函数实际操作cgroup内每个task的冻结与解冻。

参考文章:

深入浅出cgroup_cgroup.procs_码出钞能力的博客-CSDN博客

Cgroup原理及使用 - zhrx - 博客园 (cnblogs.com)

https://luoxn28.github.io/2020/01/04/cgroup-yuan-li-jie-xi/

https://gaozhipeng.me/posts/freezer/


http://chatgpt.dhexx.cn/article/jmv0gjyi.shtml

相关文章

LINUX CGROUP总结

简介: Linux CGroup全称Linux Control Group, 是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU、内存、磁盘输入输出等)。这个项目最早是由Google的工程师在2006年发起(主要是Paul Men…

cgroup 简介

cgroup 的功能在于将一台计算机上的资源(CPU,memory,network)进行分片,来防止进程间不利的资源抢占。 术语 cgroup:关联一组 task 和一组 subsystem 的配置参数。 一个 task 对应一个进程,cg…

cgroup基础介绍

一项新概念的产生,必然有其原因,cgroup也不例外,最初由谷歌工程师Paul Menage和Rohit Seth提出【1】:因为计算机硬件能力越来越强大,为了提高机器的使用效率,可以在同一台机器上运行不同运算模型的工作。开…

深入浅出cgroup

一、什么是cgroup Cgroup是linux内核用来控制系统资源的机制,它将操作系统中的所有进程以组为单位划分,给这一组进程定义对某一类资源特定的访问权限。Cgroup用子系统(subsystem)来描述所能控制的系统资源,子系统具有多…

Cgroup概述

一、Cgroup的目的 Cgroup和namespa类似,也是将进程进程分组,但是目的与namespace不一样,namespace是为了隔离进程组之前的资源,而Cgroup是为了对一组进程进行统一的资源监控和限制。 二、为什么需要Cgroup 在Linux里&#xf…

Cgroup是什么(相关概念、功能、作用、特点、怎么用)

文章目录 Cgroup 什么是CgroupCgroup的相关概念相互关系Cgroup的功能Cgroup的作用Cgroup的层级图及特点Cgroup怎么用 什么是Cgroup cgroups,其名称源自控制组群(control groups)的简写,是Linux内核的一个功能,用来限…

Cgroup简介-概述

Cgroup(Control Groups)是这样一种机制:它以分组的形式对进程使用系统资源的行为进行管理和控制。也就是说,用户通过cgroup对所有进程进行分组,再对该分组整体进行资源的分配和控制。 1 Cgroup的结构 cgroup中的每个分…

J2EE技术架构

一、简介 J2EE(Java 2 Platform, Enterprise Edition)是一个为大企业主机级的计算类型而设计的Java平台。Sun微系统(与其工业伙伴一起,例如IBM)设计了J2EE,以此来简化在受客户级环境下的应用开发。由于创造…

J2EE架构模型

从开始学Java Web到现在,使用的J2EE架构一步一步的在改变,从最简单的到越来越复杂,刚开始都是完全就照着每个架构的形式去开发项目,很少自己会想为什么用这样的架构好?好在哪里?现在学了这么久,…

java开发系统架构_Java开发:ECP系统J2EE架构开发平台

一 体系结构 ECP平台是一个基于J2EE架构设计的大型分布式企业协同管理平台,通过采用成熟的J2EE的多层企业架构体系,充分保证了系统的健壮性、开放性和扩展性。可选择部署于多种系统环境,满足不同类型、不同规模企业的需要。企业可以根据自己的…

J2EE的体系架构

转载自:http://zengbo0710.iteye.com/blog/79490 J2EE 即Java2平台企业版,它提供了基于组件的方式来设计、开发、组装和部署企业应用。J2EE使用多层分布式的应用模型,这个多层通常通过三层或四层来实现: 1、客户层&…

J2EE体系架构

J2EE是Java2平台企业版(Java 2 Platform,Enterprise Edition),它的核心是一组技术规范与指南,提供基于组件的方式来设计、开发、组装和部署企业应用。J2EE使用多层分布式的应用模型。 J2EE分层 客户层,执行在客户计算…

基于J2EE架构的在线考试系统-Java(报告+源码+PPT

目前国内基于B/S、C/S结构的在线考试系统产品已经有许多,本文首先介绍了这些考试系统的形成和发展过程,大致结构。然后通过仔细分析,提出了目前的这些系统还存有系统更新和维护等种种弊端,仍不够成熟。基于对现有产品的思考,结合J…

Spring 架构图

http://it.100xuexi.com/view/otdetail/20130426/38b9d40a-138b-4b24-963c-ac029b034fe7.html 1.Spring 架构图 Spring 是一个开源 框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件…

Scala安装教程

1.Scala官网滑到最下面如图: 选择Allversions 2.我们将下载2.12.16版本,如图下 3.选scala-2.12.16.zip安装 4.先将scala-2.12.16zip解压为文件夹我解压到了D盘的scalal文件夹下面 D:\scalal\scala-2.12.16

linux上安装scala教程

Scala教程 一、介绍 cala 是 Scalable Language 的简写,是一门多范式的编程语言,Scala 语言可以运行在Window、Linux、Unix、 Mac OS X等系统上。 安装scala之前,需要在linux上安装jdk,如果没有安装jdk,可以参考这篇…

Scala教程之:可变和不变集合

文章目录 mutable HashMapimmutable HashMap 集合在程序中是非常有用的,只有用好集合才能真正感受到该语言的魅力。在scala中集合主要在三个包里面:scala.collection, scala.collection.immutable和scala.collection.mutable。 scala中引入不…

Scala语法教程

第一章 Scala入门 1.1概述 Scala是一门以Java虚拟机(JVM)为运行环境并将面向对象和函数式编程的最佳特性结合在一起的 静态类型编程语言(静态语言需要提前编译的如:Java、c、c等,动态语言如:js&#xff0…