一个资源管理系统的设计--解析linux的cgroup实现

将实体打散成不可再分的微粒,这样就可以使设计灵活化,最大限度的减少数据冗余。以CRM系统为例,虽然管理是基于一组控制元素而不是一个控制元素的,设计的时候还是以一个控制元素为基础。

linux的cgroup系统可谓是一个典范,它轻量地实现了诸如solaris的“容器”的概念,也许也是对linux本身“命名空间”的一种冲击。它是分层的,也可以说是树形的结构,一个“控制组”拥有一个ROOT,每一个ROOT控制一组元素,在这个ROOT当中可以建立很多的“组”(cgroup),每一个组还可以建立下级的组...。每新建一个cgroup必须确定一组它关心的cgroup_subsys,比如cpuset,memory,ns等,怎么确定呢?这是通过文件系统的mount实现的,当你执行:

mount -t cgroup cgroup -o cpuset memory my

的时候,你就建立一个ROOT,这个ROOT包含所有的进程,然后你可以在my目录中执行mkdir group1 group2,这样就建立了两个cgroup,实际上,当你mount的时候,系统就建立了一个虚拟的组group-root,如果你执行cat my/tasks,你会发现它包含了所有的进程,如果你执行cat my/group1/tasks,你会发现它是空的,因为还没有任何的进程被加入进去。现在执行echo 761>my/group1/tasks,那么pid为761的进程将被加入到group1,通过修改group1目录下的文件就可以对这个group1中当前tasks文件中包含的所有的进程进行控制了。这一切是如何实现的?实际上linux内核代码的cgroup子系统实现了类似数据库的结构,包括表结构和查询引擎,通过阅读代码可以看出,每一个进程task包含一个css_set类型的字段:

struct css_set {

struct kref ref;

struct hlist_node hlist;

struct list_head tasks;      //解决冗余,包含所有使用这个set的进程

struct list_head cg_links;   //解决冗余,包含所有参与管理这个set的cgroup。

struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];

};

既然它被一组subsys控制,为何不直接将每个subsys本身包含在task中呢?这是为了解决数据冗余的问题,因为其他的进程也可以受这些subsys控制。

有必要说一下上面的css_set结构中的cg_links字段,它包含了所有的参与管理这个set的cgroup,为何会这样呢?难道一个set不是由一个cgroup管理的吗?不是的,要知道管理是基于“一组”subsys的,而这一组并不一定是全部的编译进内核也就是内核支持的subsys。比如你分别用-o参数cpu,memory...mount了5个cgroup文件系统,那么一个进程关联的css_set就会由5个cgroup管理,每一个mount的ROOT会管理一个,这个ROOT会用文件系统的方式管理进程分别属于该ROOT的哪个cgroup。

下面看一下cgroup_subsys_state,这个结构可以看作静态cgroup_subsys结构的动态实例,静态的cgroup_subsys中包含了一些通用的方法,而动态的cgroup_subsys_state则仅仅是一个父类,具体的数据和额外的方法通过继承它来实现,比如:

struct mem_cgroup {

struct cgroup_subsys_state css;

struct res_counter res;

struct mem_cgroup_lru_info info;

int    prev_priority;    /* for recording reclaim priority */

struct mem_cgroup_stat stat;

};

任何时候,只要你得到了一个cgroup_subsys_state,并且根据其subsys_id确认它是关于memory的,那么就可以通过:

static inline struct cgroup_subsys_state *task_subsys_state(

struct task_struct *task, int subsys_id)

{

return rcu_dereference(task->cgroups->subsys[subsys_id]);

}

container_of(task_subsys_state(p, mem_cgroup_subsys_id), struct mem_cgroup, css);

来取得这个可被称为子类实例的mem_cgroup,接下来就可以操作它的数据了。终于可以看一下cgroup_subsys_state了:

struct cgroup_subsys_state {

struct cgroup *cgroup;

atomic_t refcnt;

unsigned long flags;

};

这个结构很简单,cgroup是它绑定的一个cgroup实例,从名称上也可以看出cgroup_subsys_state结构是动态的,它表示进程的subsys的state,由于它是被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]; //这里仅包含对应ROOT相关的subsys

struct cgroupfs_root *root;     //对应的那个ROOT

struct cgroup *top_cgroup;

struct list_head css_sets;    //包含所有的它参与管理的css_set

struct list_head release_list;

}

前面提到过,进程要显式加入一个ROOT的cgroup,在加入的时候可能会为进程绑定一个新的css_set(必须保证css_set的subsys数组完全相同才能重用,如果之前没有这样的css_set建立,只好新建立一个),只要绑定了一个新的css_set,这个set就要加入到cgroup的css_sets链表中,最简单的可以在css_set中添加一个字段用于此目的,与此同时cgroup中也要增加一个list_head结构用来链接css_set的cg_links字段,这样做为何不好呢?它增加了两个数据结构的耦合性,同时也增加了数据的冗余性,因为一个cgroup的ROOT负责一组subsys,一个进程也是和一组subsys关联,因此只需要一个进程的一组subsys中被同一个ROOT管理的第一个加入到cgroup链表中就可以表示一个进程受到了这个cgroup的管理,比如进程p1加入group1,该group1的ROOT管理cpu和memory,那么其css_set的subsys数组中只需要cpu_id的这个subsys加入cgroup的css_sets链表就可以了,为了代码的简单,因此引入了一个中间结构,那就是cg_cgroup_link:

struct cg_cgroup_link {

struct list_head cgrp_link_list;    //代表一个css_set加入到cgroup

struct list_head cg_link_list;        //代表一个cgroup加入到css_set

struct css_set *cg;            //指回css_set

...  //后续的内核还要指回cgroup,这里的内核是2.6.26

};

在此必须说一下为何要有cg_cgroup_link这个结构体。如果在css_set中和cgroup中直接加入链表元素是解决不了多对多问题的,比如所有参与管理一个css_set的cgroup都将其链表元素加入 css_set的链表,反过来css_set的链表元素也应该加入一个cgroup的链表,代表它是该cgroup管理的css_set之一,现在问题来了,前面说过一个css_set可以属于很多ROOT,那么它到底加入哪个cgroup的链表呢?毕竟css_set和cgroup之间是如此单项一对多的关系耦合,因此解除耦合的办法就是设计一个中间结构,那就是cg_cgroup_link。

很多时候,很多人在网上写了一大堆关于分析“linux内核”的文章,很多文章都是仅仅分析代码流程,但是很少有文章能说明为何这么做(除非文章的作者着手提交一个补丁或者其它...)。其实linux内核就是一个数据库设计的教程,它不但展示了表结构,而且还有查询引擎,故而linux内核绝对是绝妙的哦!比如在input子系统中,input_handle这个结构体也是和cg_cgroup_link意义一样的,也是为了解决多对多的问题而设置的,还有一个明显的例子,那就是linux内核中的总线驱动架构。

由此看来,学习linux内核可以学到两大当今时髦的东西,一个就是OO,另一个就是数据库的设计,千万不要以为linux内核仅仅是底层的东西,搞应用的人不用学习,其实各个领域是相通的,我相信,当一个顶级的文学家听说了广义相对论的时候,他也一定会提出一些自己的看法的。我经常看历史著作,那些作者们看起来对任何领域都很感兴趣...

附:看一下cgroup的静态数据结构们吧

首先看一下一个静态的超类,那就是cgroup_subsys,它包含了一系列的接口,但是没有实现!

struct cgroup_subsys {

struct cgroup_subsys_state *(*create)(struct cgroup_subsys *ss,

struct cgroup *cgrp);

...//类似的接口

int subsys_id;

int active;

int disabled;

int early_init;

#define MAX_CGROUP_TYPE_NAMELEN 32

const char *name;

struct cgroupfs_root *root;

struct list_head sibling; //用于挂载一系列的state

void *private;            //用于扩展

};

每一个挂载(mount)的cgroup文件系统都有一个cgroupfs_root实例:

struct cgroupfs_root {

struct super_block *sb;

unsigned long subsys_bits;

unsigned long actual_subsys_bits;

struct list_head subsys_list;      //本ROOT关注的subsys

struct cgroup top_cgroup;

int number_of_cgroups;

struct list_head root_list;

unsigned long flags;

char release_agent_path[PATH_MAX];

};

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

原文地址:https://www.cnblogs.com/ksiwnhiwhs/p/10390229.html

时间: 2024-10-09 20:42:56

一个资源管理系统的设计--解析linux的cgroup实现的相关文章

一个缺陷管理系统数据库设计和界面设计分析

在Winform方面,基于业务的不同,我们可以利用工具的效率,快速做很多不同的业务系统,前期做了一个缺陷管理系统,想把单位的测试业务规范下,也好统计和分析每个版本的缺陷信息,本篇整理这些数据库设计和界面设计的相关内容,做一个介绍,希望给大家一个对比参照的案例进行学习了解. 1.缺陷管理系统的业务分析 在很多缺陷管理系统里面,我们往往需要管理的就是缺陷信息的记录,以及缺陷记录的开闭过程,从而实现了测试人员->开发人员->测试人员的整个闭环过程. 一般情况下,缺陷管理系统可以部署在局域网内,或者公

使用Django开发一个图书管理系统 05---改造界面

BOOKMS是一个公司内部的图书管理系统. 本系列用多次迭代方法,逐步实现一个图书管理系统BOOKMS. 本文主要介绍使用bootstrap美化前台页面和修改admin模块的添加图书模块时使用豆瓣api获取数据. 再前一节里我们一件可以管理model(增删改查).但是界面是在是太简陋,简陋到但凡是个正常人估计都无法接受.项目组里没有专业的前端的话,页面美化是一个痛苦的事,但是有了bootstrap的帮助之后,我们的页面也能像模像样. 一.Bootstrap介绍 Bootstrap是Twitter

基于Bootstrap框架的临床数据管理系统的设计与开发

    基于Bootstrap框架的临床数据管理系统的设计与开发     2018年11月10日 目  录 第一章绪论... 6 1.1 选题背景及其意义... 6 1.2国内外研究现状... 7 1.2.1 临床大数据管理系统发展现状... 7 1.2.2医疗电子表单管理发展现状... 8 1.3研究目标... 9 1.4 研究内容... 10 1.5论文整体结构... 10 第二章相关技术研究... 12 2.1 AngularJS技术简述... 12 2.2 RESTful API +sw

基于JavaEE的网新恒天人事管理系统的设计与实现

获取项目源文件,技术交流与指导联系Q:1225467431 摘要:随着网络技术的不断发展及其在企业管理工作中的应用,在企业建立企业人事管理系统就显得十分必要.所以设计一个企业人事管理系统可以更方便的帮助管理者管理一家企业.本系统的开发正是适应了这一需求,经过实际的需求分析,本系统采用了JavaEE平台中最为流行的Spring+Spring MVC+MyBatis框架,以Tomcat作为应用并选择MySQL数据库管理系统作为工具进行开发.系统包含管理员.HR.领导.普通员工四种不同的用户.操作简便

Kafka设计解析(三)- Kafka High Availability (下)

本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/06/08/KafkaColumn3 摘要 本文在上篇文章基础上,更加深入讲解了Kafka的HA机制,主要阐述了HA相关各种场景,如Broker failover,Controller failover,Topic创建/删除,Broker启动,Follower从Leader fetch数据等详细处理过程.同时介绍了Kafka提供的与Replication相关的工具,如重新分配Partition等

设备资源管理系统-数据字典

设备资源管理系统-数据字典 数据库设计 用户信息表: 用户ID(主键)    姓名     年龄      性别        所属单位      住址           是否在职 1            张三     23         1           1        北京上地环岛          1 2            李四     22         2           2        上海浦东              1 3            王五 

设备资源管理系统-分页

设备资源管理系统-分页 分页设计 userindex.jsp userList.jsp Ajax框架 要求: 1.需要2个页面(XXXindex.jsp,XXXlist.jsp) 2.一个jsp页面中使用2个form对象,分别为Form1和Form2. 3.另一个jsp的页面中第一个jsp页面的form2的内容. 原理: 提交过程,实质是提交Form1的参数,使用Fom1的参数,查询后台数据,返回结果,将结果在XXXlist.jsp上显示,用XXXlist.jsp的内容替换XXXIndex.js

大学辅导员工作管理系统的设计与实现

一.基本信息 标题: 时间:2013 出版源:电子科技大学 关键词:B/S结构; 数据挖掘技术; 高校辅导员; 管理系统; 二.研究背景 问题定义:现在一些高校中没有专门针对大学辅导员管理工作的完善系统,辅导员面对各个部门都是自成模块,各个模块之间都没有很好的结合起来,各自只处理着自己部门相关工作,没有有效的沟通和合作.有些工作在多个部门之间有很多重复,冗余的工作 难点:不同的信息管理系统,开发技术手段不同,功能呢也不同,由于有些高校中,还未实现辅导员工作系统的使用,所以好的.合适的开发技术选择

基于UML的高校教务管理系统的设计与实现

一.基本信息 标题:基于UML的高校教务管理系统的设计与实现 时间:2018 出版源:南昌航空大学 领域分类:教育信息化:教务管理系统:UML:SSH:Oracle 二.研究背景 问题定义:高校教务管理系统的设计与实现 难点:想出新的数据录入方式,采用面向对象的分析方法和设计思路来逐步实现一个较为完善的高校教务管理系统 相关工作:了解并掌握相关技术,进行系统分析.设计,实现系统,测试系统可行性. 三.创新方法 1.多种技术构成的体系结构.平台.开发框架.交互技术的综合的系统 四.实验 实验1:相