cgroup从2.6.4引入linux内核主线,目前默认已启用该特性。在cgroup出现之前,只能对一个进程做资源限制,比如通过sched_setaffinity设置进程cpu亲和性,使用ulimit限制进程打开文件上限、栈大小等。

cgroups是Linux下控制一个(或一组)进程的资源限制机制,全称是control groups,可以对cpu、内存等资源做精细化控制,比如目前很多的Docker在Linux下就是基于cgroups提供的资源限制机制来实现资源控制的;除此之外,开发者也可以指直接基于cgroups来进行进程资源控制,比如8核的机器上部署了一个web服务和一个计算服务,可以让web服务仅可使用其中6个核,把剩下的两个核留给计算服务。cgroups cpu限制除了可以限制使用多少/哪几个核心之外,还可以设置cpu占用比(注意占用比是各自都跑满情况下的使用比例,如果一个cgroup空闲而另一个繁忙,那么繁忙的cgroup是有可能占满整个cpu核心的)。

本文主要讨论下cgroups概念及原理,然后分析下cgroups文件系统概念,最后对cgroups做个总结,关于cgroups的使用实践可以参考网上资料,这里不再赘述。

cgroups概念

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

cgroups子系统

cgroups为每种资源定义了一个子系统,典型的子系统如下:

  • 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 子系统来配合完成。

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的数据结构图示如下:

cgroups 层级结构

在cgrups中一个task任务就是一个进程,一个进程可以加入到某个cgroup,也从一个进程组迁移到另一个cgroup。一个进程组的进程可以使用 cgroups 以控制族群为单位分配的资源,同时受到 cgroups 以控制族群为单位设定的限制。多个cgroup形成一个层级结构(树形结构),cgroup树上的子节点cgroup是父节点cgroup的孩子,继承父cgroup的特定的属性。注意:cgroups层级只会关联某个子系统之后才能进行对应的资源控制,一个子系统附加到某个层级以后,这个层级上的所有cgroup都受到这个子系统的控制。cgroup典型应用架构图如下:

cgroups文件系统

Linux 使用了多种数据结构在内核中实现了 cgroups 的配置,关联了进程和 cgroups 节点,那么 Linux 又是如何让用户态的进程使用到 cgroups 的功能呢? Linux内核有一个很强大的模块叫 VFS (Virtual File System)。 VFS 能够把具体文件系统的细节隐藏起来,给用户态进程提供一个统一的文件系统 API 接口。 cgroups 也是通过 VFS 把功能暴露给用户态的,cgroups 与 VFS 之间的衔接部分称之为 cgroups 文件系统。通过cgroups适配VFS,用户可以使用VFS接口来操作cgroup功能。

VFS 是一个内核抽象层(通用文件模型),能够隐藏具体文件系统的实现细节,从而给用户态进程提供一套统一的 API 接口。VFS 使用了一种通用文件系统的设计,具体的文件系统只要实现了 VFS 的设计接口,就能够注册到 VFS 中,从而使内核可以读写这种文件系统。 这很像面向对象设计中的抽象类与子类之间的关系,抽象类负责对外接口的设计,子类负责具体的实现。其实,VFS本身就是用 c 语言实现的一套面向对象的接口。

小结

cgroups是Linux下控制一个(或一组)进程的资源限制机制,cgroup通过关联单个/多个子系统定义了一套限制策略来限制CPU/内存等资源,子系统上限制策略相当于一套配置,需要内核中对应模块配合来完成资源限制功能,比如对 cpu 资源的限制是通过进程调度模块根据 cpu 子系统的配置来完成的等。

注意cgroups资源限制是针对cgroup为单位的,不管cgroup下是有一个进程还是多个进程。Docker下的容器内所有进程就是属于同一组cgroup管理之下的,比如限制CPU使用,限制内存大小等。

推荐阅读

Linux Cgroup浅析的更多相关文章

  1. SQL Server on Linux 理由浅析

    SQL Server on Linux 理由浅析 今天的爆炸性新闻<SQL Server on Linux>基本上在各大科技媒体上刷屏了 大家看到这个新闻都觉得非常震精,而美股,今天微软开 ...

  2. [转载] linux cgroup

    原文: http://coolshell.cn/articles/17049.html 感谢左耳朵耗子的精彩文章. 前面,我们介绍了Linux Namespace,但是Namespace解决的问题主要 ...

  3. Docker基础技术:Linux CGroup

    前面,我们介绍了Linux Namespace,但是Namespace解决的问题主要是环境隔离的问题,这只是虚拟化中最最基础的一步,我们还需要解决对计算机资源使用上的隔离.也就是说,虽然你通过Name ...

  4. 【转载】Linux cgroup资源隔离各个击破之 - io隔离

    Linux Cgroup blkio子系统的用法.   blkio子系统支持的两种IO隔离策略 .1. (Completely Fair Queuing 完全公平队列)cfq io调度策略,支持按权重 ...

  5. 【转载】Linux cgroup资源隔离各个击破之 - cpu隔离1

    Linux cgroup 有两个子系统支持CPU隔离.一个是cpu子系统,另一个是cpuset子系统. cpu子系统根据进程设置的调度属性,选择对应的CPU资源调度方法 .1. 完全公平调度 Comp ...

  6. Linux CGroup

    catalog . 引言 . Cgroup安装配置 . Cgroup使用方式 . CGroup的子系统 1. 引言 我们已经讨论了Linux下命名空间(Namespace)的基本知识,详情请参阅另一篇 ...

  7. linux网桥浅析

    linux网桥浅析 原文链接:http://hi.baidu.com/_kouu/item/25787d38efec56637c034bd0 什么是桥接?简单来说,桥接就是把一台机器上的若干个网络接口 ...

  8. 深入理解 Linux Cgroup 系列(二):玩转 CPU

    原文链接:深入理解 Linux Cgroup 系列(二):玩转 CPU 上篇文章主要介绍了 cgroup 的一些基本概念,包括其在 CentOS 系统中的默认设置和控制工具,并以 CPU 为例阐述 c ...

  9. 深入理解 Linux Cgroup 系列(一):基本概念

    原文链接:深入理解 Linux Cgroup 系列(一):基本概念 Cgroup 是 Linux kernel 的一项功能:它是在一个系统中运行的层级制进程组,你可对其进行资源分配(如 CPU 时间. ...

随机推荐

  1. data-属性的作用

    data-用于存储页面或应用程序的私有自定义数据,赋予我们在所有HTML元素上嵌入自定义data属性的能力,存储的数据能被页面的JS利用,以创建更好的用户体验. <div id="bo ...

  2. Codeforces Round #176 (Div. 1 + Div. 2)

    A. IQ Test 模拟. B. Pipeline 贪心. C. Lucky Permutation 每4个数构成一个循环. 当n为偶数时,n=4k有解:当n为奇数时,n=4k+1有解. D. Sh ...

  3. 2013-10-6 datagridview实现换行并自动设置行高

    datagridview设置换行,如下,文本设置\r\n即可换行 dv4.DefaultCellStyle.WrapMode = DataGridViewTriState.True; dv4.Auto ...

  4. Python--day41--thread1.join()

    在 Python 的多线程编程中,在实例代码中经常有 thread1.join()这样的代码.那么今天咱们用实际代码来解释一下 join 函数的作用. join的原理就是依次检验线程池中的线程是否结束 ...

  5. Redux action 状态

    action  不同的状态,设置不同的action.type [就是一个名字],返回对应的数据 不同的状态返回不同的  接口数据

  6. C# 多线程的等待所有线程结束

      //前台线程和后台线程唯一区别就是:应用程序必须运行完所有的前台线程才可以退出://而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,//所有的后台线程在应用程序退出时都会自动结束 ...

  7. 为什么我们要使用DTO

    基础结构解释 UI-表现层-与控制器打交道(UI向Controller 传递数据时使用DTO(数据传输对象)) Service-应用服务层 Domain 领域对象 DTO 数据传输对象,一般只包含基础 ...

  8. 2017.5.11 昨天晚上看fview直播坚果pro回放

      对话1 彭林: 我以前也是产品经理,身为产品经理,你有没有感觉我们做出过什么之前不被人接受的东西,但是我们却坚持做了,并且得到的反响非常好. 朱萧木: 没有吧,我们没有做颠覆用户认知或者三观的特别 ...

  9. 纵我不往,知识不来--学习Java第一周心得

    暑假第一周,也是开始学习java的第一周. 本周的主要时间花在了小学期的任务上,但也草草开始了java的学习.首先安装好了所需要的软件,然后在网上下载了一份<Java基础笔记>,看了前五章 ...

  10. 安卓APP动态调试(IDA实用攻略)

    转自:http://drops.wooyun.org/mobile/5942 0x00 前言 随着智能手机的普及,移动APP已经贯穿到人们生活的各个领域.越来越多的人甚至已经对这些APP应用产生了依赖 ...