cgroup从入门到懵圈——cgroup概念

本文详细介绍了cgroup的概念、作用及其实现原理。cgroup是Linux内核中的资源控制组件,通过控制组来管理进程集合的资源使用。文章还探讨了cgroup的使用场景,并提供了具体的使用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    从今天起,我要开始写博客了。先立个flag在这儿:两周一篇。万事开头难,中间不容易,最后会放弃。请各位看官监督(虽然似乎肯定没有人看)。

   之前有接触过cgroup,但东西都是同事在做(羡慕),理解不深。所以这个系列的文档,我假装自己是cgroup菜鸡(其实我不需要假装),从零开始学习cgroup。

    cgroup是linux内核实现、用于控制linux系统资源的组件。因此要了解cgroup,首先从引入这个组件的kernel文档中寻找。去到举世闻名的www.kernel.org网站寻找,嘿,找到介绍文档:Documentation/cgroup-v1/cgroups.txt

    1 什么是cgroup?

    cgroup ,控制组,它提供了一套机制用于控制一组特定进程对资源的使用。cgroup绑定一个进程集合到一个或多个子系统上。

    subsystem,子系统,一个通过cgroup提供的工具和接口来管理进程集合的模块。一个子系统就是一个典型的“资源控制器”,用来调度资源或者控制资源使用的上限。其实每种资源就是一个子系统。子系统可以是以进程为单位的任何东西,比如虚拟化子系统、内存子系统。

    hierarchy,层级树,多个cgroup的集合,这些集合构成的树叫hierarchy。可以认为这是一个资源树,附着在这上面的进程可以使用的资源上限必须受树上节点(cgroup)的控制。hierarchy上的层次关系通过cgroupfs虚拟文件系统显示。系统允许多个hierarchy同时存在,每个hierachy包含系统中的部分或者全部进程集合。

    cgroupfs是用户管理操纵cgroup的主要接口:通过在cgroupfs文件系统中创建目录,实现cgroup的创建;通过向目录下的属性文件写入内容,设置cgroup对资源的控制;向task属性文件写入进程ID,可以将进程绑定到某个cgroup,以此达到控制进程资源使用的目的;也可以列出cgroup包含的进程pid。这些操作影响的是sysfs关联的hierarchy,对其它hierarchy没有影响。

    对于cgroup,其本身的作用只是任务跟踪。但其它系统(比如cpusets,cpuacct),可以利用cgroup的这个功能实现一些新的属性,比如统计或者控制一个cgroup中进程可以访问的资源。举个例子,cpusets子系统可以将进程绑定到特定的cpu和内存节点上。

    2 为什么需要cgroup?

    这个问题相当于问cgroup重要吗?有哪些地方用到了。回答是重要,又不重要。如果你用到了,那就重要,如果没有用到,那就不重要。呵呵呵~~~~其实挺重要的。cgroup的主要运用是资源跟踪。我接触的场景就是用cgroup控制虚拟机进程或者docker进程可以使用的资源。当你想在linux对应用进程做资源访问控制的时候,cgroup就派上用场了。

    3 cgroup怎么实现的?

    ——    系统中的每个进程(task_struct,后面用task代指)都持有一个指向css_set结构的指针。

    ——    一个css_set结构体包含了一组指向cgroup_subsys_state对象的指针(所以一个task可以附加到多个cgroup上),每个cgroup_subsys_state在系统中都有注册。task结构体没有直接指向hierarchy中一个节点(cgroup)的指针。但可以通过其包含的cgroup_subsys_state间接确定。这样设计的原因是cpu对subsystem state的访问很频繁,但涉及到将task绑定到cgroup的操作却不多。task中还有个双向链表cg_list,这个链表维护所有同属于一个css_set的tasks。

    ——    用户可以通过cgroupfs文件系统来浏览cgroup hierarchy。

    ——    用户可以列出任意一个cgroup上附着的task PID

    cgroup在kernel中除了本身功能的实现外,在kernel中还有两处修改:

    ——    在kernel启动时对root cgroup的初始化和css_set结构体的初始化。这个在init/main.c文件中实现。

    ——    在task的创建(fork)和退出(exit)阶段,对应地将task与css_set进行绑定和解绑。

    另外,cgroup为了向用户提供操作接口,特别开发了一个虚拟文件系统类型(cgroupfs),这个文件系统与sysfs,proc类似。cgroupfs是向用户展示cgroup的hierarchy,通知kernel用户对cgroup改动的窗口。挂载cgroupfs时通过选项(-otype)指定要挂载的子系统类型,如果不指定,默认挂载所有的注册的子系统。

    如果新挂载的cgroup关联的hierachy与系统中存在的hierarchy完全一样,那么cgroupfs会拒绝挂载。如果没有匹配到相同的hierarchy,但新挂载hierachy声明的资源正在被已经存在的hierarchy使用,挂载会报-EBUSY错误。

    当前cgroup还没有实现向已经存在的cgroup hierarchy绑定新子系统的操作,将子系统从cgroup hierachy解绑也不允许。这些操作在未来也许会支持,但也可能会进一步产生错误恢复的一系列问题。

    卸载cgroupfs时,如果它的子cgroupfs还在活动,那么子cgroupfs还是会持续生效。直到所有的子cgroupfs不再活动,卸载cgroupfs才会真正生效。

    cgroupfs下不能再挂载其它类型的文件系统。所有对cgroup的查询修改都只通过cgroupfs文件系统来完成。

    系统中的所有task,在/proc/pid目录下都有一个名为cgroup的文件,这个文件展示了该task相对cgroupfs 根的路径。通过查看这个文件,可以了解一个进程在cgroup hierarchy的位置。以此得到task可以使用的资源信息。

    cgroupfs中目录表示cgroup,每个目录在创建时默认生成如下的属性文件,这些文件描述了cgroup的信息:

    ——    tasks: 所有附属于这个cgroup的进程ID列表。tasks文件中增加进程ID,表示将进程加入这个cgroup,进程能够使用的资源受cgroup限制。

    ——    cgroup.procs: 所有附属于这个cgroup线程组ID,将TGID写入这个文件后,TGID所在进程包含的所有线程都加入这个cgroup,这些线程受cgroup限制。

  • PID:这是 Linux 中在其命名空间中唯一标识进程而分配给它的一个号码,称做进程ID号,简称PID。在使用 fork 或 clone 系统调用时产生的进程均会由内核分配一个新的唯一的PID值。
  • TGID:在一个进程中,如果以CLONE_THREAD标志来调用clone建立的进程就是该进程的一个线程,它们处于一个线程组,该线程组的ID叫做TGID。处于相同的线程组中的所有进程都有相同的TGID;线程组组长的TGID与其PID相同;一个进程没有使用线程,则其TGID与PID也相同。
  • PGID:另外,独立的进程可以组成进程组(使用setpgrp系统调用),进程组可以简化向所有组内进程发送信号的操作,例如用管道连接的进程处在同一进程组内。进程组ID叫做PGID,进程组内的所有进程都有相同的PGID,等于该组组长的PID。
  • SID:几个进程组可以合并成一个会话组(使用setsid系统调用),可以用于终端程序设计。会话组中所有进程都有相同的SID。

    ——    notify_on_release flag: 标记退出时是否运行release agent

    ——    release_agent: 制定要运行的release agent的路径,这个属性文件只在cgroup的顶层目录中存在。

    以上文件是每个cgroup基本的属性文件,对于不同的子系统,对应的cgroup可能会有其它附加的属性文件,存在于其对应的cgroup目录之下。

    通过mkdir命令创建cgroup,通过向目录下的文件写入适当的数值设置修改cgroup的属性。

    嵌套的cgroups,指定了层级结构,以此将系统资源划分成嵌套的,动态可变的更小的资源块。

    一个进程可以附加到多个不同的cgroup中,只要这些cgroup不在同一个层级树上即可。因为cgroupfs会保证新挂载的cgroup关联的层级树全局唯一。子进程在被创建后默认附加到父进程所在的cgroup,后面用户可以根据需要将其移动到别的cgroup。

    当进程从一个cgroup被移动到另一个cgroup。进程的task_struct会获取一个新的css_set指针:如果这个cgroup所在的css_set已经存在就重用这个css_set,否则就新分配一个css_set。kernel会在全局的hash表中查找确认cgroup所属的css_set是否存在。

    4 notify_on_release 是做什么的?

    如果cgroup中使能notify_on_release,cgroup中的最后一个进程被移除,最后一个子cgroup也被删除时,cgroup会主动通知kernel。接收到消息的kernel会执行release_agent文件中指定的程序。notify_on_release默认是关闭的,release_agent的内容默认为空,子cgroup在创建时会继承父cgroup中notify_on_relase和release_agent的属性。所以这两个文件只存在于cgroupfs的顶层目录中。

    5 clone_children有什么用?

    clone_chilren仅针对cpu绑定(cpuset),如果clone_children使能,新的cpuset cgroup在初始化时会继承父cgroup的属性。

    6 cgroup怎么用?

    假设现在要将一个新的任务加入到cgroup,功能是将该任务的进程在指定的cpu上运行,因此我们使用"cpuset"cgroup 子系统,操作的大致步骤如下:

    1)mount -t tmpfs cgroup_root /sys/fs/cgroup 

    挂载cgroup根文件系统,类型为tmpfs

    2)mkdir /sys/fs/cgroup/cpuset

    在cgroupfs根目录下创建子cgroup,名为cpuset

    3)mount -t cgroup -o cpuset cpuset /sys/fs/cgroup/cpuset

    将名为cpuset的cgroup关联到cpuset子系统

    4)在cpuset目录下创建目录,生成一个子cgroup,属性文件中写入相应内容,设置属性。

    5)启动需要限制的进程,查找其对应的进程ID,将其写入对应的task文件中

    以下操作步骤是创建一个名为"Charlie"的cgroup,这个cgroup的资源包含cpu2,cpu3和内存节点1,将shell进程附加到这个cgroup。

    mount -t tmpfs cgroup_root /sys/fs/cgroup

    mkdir /sys/fs/cgroup/cpuset

    mount -t cgroup cpuset -o cpuset /sys/fs/cgroup/cpuset

    cd /sys/fs/cgroup/cpuset

    mkdir Charlie

    cd Charlie

    echo 2-3 > cpuset.cpus

    echo 1 > cpuset.mems

    echo $$ > tasks

    sh

    cat /proc/self/cgroup

<think>嗯,用户这次明确要求Linux运维从零基础到社招的完整学习路线,还附带每日任务建议。从引用的材料看,用户可能是个转型者,经历过实操挫折(如网卡配置失败),特别需要系统化方案。用户引用的几篇材料很有价值:第一篇提到《Linux就该这么学》实操指导性强;第二篇强调社招加分项(原理/网络/算法);第三篇展示项目管理工具;第四篇指出架构理解的重要性。这些正好对应运维的硬技能(OS/网络)、工程能力(部署/监控)、软实力(自动化/架构)。在规划路线时,要注意三点:一是用户“零基础”起步需要阶梯式难度设计;二是社招要求能覆盖企业高频需求(如故障排查、云服务);三是引用[1]的经验说明文档易过时,必须培养问题解决能力而非死记命令。核心学习模块应该分层设计:先解决“能用Linux”(文件/用户/包管理),再解决“会管服务”(Web/DB集群),最后突破“高效运维”(容器/编排),每阶段穿插实践项目(如克隆VM故障复现)。引用[3]的敏捷管理思想可以融入每日任务闭环——记录问题/复盘/改进。针对社招准备,需要突出差异化竞争力:普通运维懂部署,优秀运维懂TCP重传率对K8s集群的影响(引用2的底层原理)。每日任务要包含“五分钟原理时间”,比如每天用tcpdump分析一次握手过程。最后风险提示:避免引用[4]提到的“架构空泛病”——如果学Docker只背命令不思考cgroup实现,面试遇到Namespace原理就暴露短板了。路线中每个阶段都设置“为什么”环节(比如为什么Prometheus用Pull模型)。</think> 根据你的需求,我整合了零基础到社招的Linux运维学习路线及每日任务规划,结合企业实际需求和引用资料的核心要点,制定以下系统化方案: --- ### **一、Linux运维全阶段学习路线** #### **阶段1:Linux基础入门(2-3个月)** | **学习模块** | **核心内容** | **实践目标** | |--------------------|----------------------------------------------------------------------------|-------------------------------------| | 系统基础 | 文件结构($`/etc`、`/var`)、用户权限($`chmod/chown`)、包管理($`yum/apt`) | 独立安装配置CentOS/Ubuntu系统 | | 命令操作 | 50+常用命令($`grep`、`sed`、`awk`、`find`)、Vim操作、管道符($`\|`) | 编写Shell脚本实现日志分析 | | 网络配置 | 网卡配置($`ifconfig`/`ip`)、防火墙($`firewalld/iptables`)、路由表($`route`) | 解决多网卡绑定/克隆虚拟机网络故障[^1] | #### **阶段2:服务部署与监控(2-3个月)** | **学习模块** | **核心内容** | **实践目标** | |--------------------|---------------------------------------------------------------------------|-------------------------------------| | Web服务 | Nginx/Apache配置($`server{}`)、HTTPS证书、负载均衡 | 部署LNMP集群并实现AB压力测试 | | 数据库管理 | MySQL备份($`mysqldump`)、主从复制、慢查询优化($`EXPLAIN`) | 构建高可用MySQL集群 | | 监控告警 | Zabbix/Prometheus监控项、Grafana看板、告警规则 | 监控服务器CPU/磁盘/服务状态阈值 | #### **阶段3:自动化与架构(社招核心)** | **学习模块** | **核心内容** | **实践目标** | |--------------------|---------------------------------------------------------------------------|-------------------------------------| | 脚本自动化 | Python脚本($`paramiko`/`requests`)、Ansible剧本($`playbook`) | 编写自动化巡检脚本 | | 容器化 | Docker镜像($`Dockerfile`)、K8s基础($`pod/deployment`)、CI/CD流水线 | 容器化部署微服务应用 | | 架构设计 | 高可用架构($`Keepalived`)、灾备方案、云服务(AWS/Aliyun) | 设计可容灾的电商系统架构[^4] | --- ### **二、每日学习任务模板** ```markdown **上午(原理深化)** 1. 30分钟阅读官方文档(如Nginx配置参数优化) 2. 1小时学习计算机基础: - 网络协议:TCP三次握手($`SYN/SYN-ACK/ACK`)[^2] - 系统原理:进程调度($`nice`值)、内存管理($`Swap`) **下午(实战操作)** 1. 实验环境操作(VMware/KVM): - 故障复现:修复网卡MAC冲突[^1] - 服务部署:搭建ELK日志系统 2. 代码开发: - 编写Python监控脚本(采集磁盘使用率) - GitHub提交日更项目[^2] **晚间(复盘提升)** 1. 站会复盘:用Tower记录今日问题/解决方案[^3] 2. 技术博客:输出今日学习笔记(如iptables规则调试) ``` --- ### **三、社招专项准备** 1. **底层原理突破** - 重点掌握:Linux进程调度($`CFS`)、文件系统($`inode`)、网络协议栈($`netfilter`) - 面试题案例:*TIME_WAIT状态过多的解决方法?* 2. **架构思维训练** - 分析开源项目:K8s调度器源码阅读[^2] - 设计题演练:*如何设计千万级并发的监控系统?* 3. **工程能力证明** - GitHub仓库:包含Ansible角色/Dockerfile等 - 技术博客:持续更新故障排查实录 > **关键提示**:引用[1]的经验表明,**克隆虚拟机导致的网卡冲突**是典型实战问题;引用[2]强调社招需**系统原理+开源项目深度**;引用[3]推荐用**Git+Tower**实现敏捷管理。 --- ### **四、学习资源推荐** 1. 基础教材:《Linux就该这么学》(实操案例丰富)[^1] 2. 网络协议:$`TCP/IP Illustrated`(卷1) 3. 自动化工具:Ansible官方文档($`docs.ansible.com`) 4. 架构训练:$`《企业IT架构转型之道》` ---
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

享乐主

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

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

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

打赏作者

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

抵扣说明:

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

余额充值