从cgroup_init_early函数学习cgroup——框架

本文详细介绍了cgroup作为一种控制资源的机制,其作用是将进程分组并限制资源使用。cgroup以树状层次结构组织,每个cgroup对应特定的控制行为。文章探讨了cgroup的subsystem、框架结构、数据结构,以及进程如何与cgroup和subsystem建立联系,帮助读者理解内核如何实现资源管理。

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

一些概念的理解


cgroup
cgourp是一种机制
作用:集成各个进程,对进程分组实现进程组,分配或限制进程组使用的资源(这部分主要有个各个subsystem完成)。
另一个角度,在研究代码的时候,我们更愿意将cgroup理解为一种控制资源的行为。比如:我想要控制进程的CPU使用率为20%,那么我可以创建一个cgroup,这cgroup的作用就是控制指定进程的cpu使用率为20%。


subsystem
不同subsystem对应控制不同的资源:

cpu subsystem:指定进程组能使用的CPU;
memmory subsystem:指定进程组能使用的内存量,并编写内存使用量报告;
cpuset subsystem:指定进程组能使用的各CPU和节点集;
freezer subsystem:可停止进程组状态或启动;
cpuacct subsystem:对进程组使用的CPU资源编写报告;
blkio:设置对模块设备的输入输出限制;
devices:设置进程组能使用的设备;

查看cgroup subsystem:

yin123@yin:~$ ls /sys/fs/cgroup/
cpu  cpuacct  devices  freezer  memory

框架
概括描述cgroup框架
在这部分,我们试图用一种比较形象的描述和思维来概括cgroup的框架,不涉及代码。
为了方便理解,在开始所有的分析之前,必须要明确一点:cgroup是有层次结构的
所有的cgroup以树状分层(hierarchy)的形式被组织在一起。
你自然会觉得疑问,既然每个cgroup对应一种控制行为或者说功能,那么father cgroup和children cgroups是什么关系呢?
还是拿上面的例子: 整个cpu占用为100%.这就是根,也就是hierarchy.然后,cgroup A设置cpu占用20%,cgroup B点用50%,cgroup A和cgroup B就是它下面的子层cgroup.(这个问题的解答摘录自http://blog.chinaunix.net/uid-23010930-id-2974762.html

OK,现在假设在我们面前有这样的一些cgroup

        group A                                 group 1                        

group B          group C                group 2          group 3

A和1分别代表不同的控制行为,BC和23分别是A和1的children group。
为了更好的组织所有的cgroup,我们建立了一个top_cgroup,作为A和1的father cgroup,于是就成了这样:

                            top_cgroup

        group A                                 group 1                        

group B          group C                group 2          group 3

这样,所有的cgroup就建立了联系。

还有一个问题,试想,groupB作为一个控制行为,它可能想控制进程的CPU使用率和内存使用量,那么就涉及到了两个subsyste

<think>我们正在讨论的是`mem_cgroup_soft_limit_reclaim`函数的作用。根据引用[2],当一个memcg的usage大于soft_limit时,系统会把memcg的per node加入到全局的soft_limit_tree红黑树,这样当触发memcg的soft limit时,会从soft_limit_tree以此回收memcg的内存。因此,这个函数与memcg的软限制回收有关。 函数作用: `mem_cgroup_soft_limit_reclaim`是Linux内核中用于处理内存控制组(memcg)软限制(soft limit)的内存回收函数。当某个memcg的内存使用量超过其设置的软限制时,内核会触发该函数,尝试回收该memcg中部分内存,使其使用量回到软限制以下。 具体过程: 1. **触发条件**:当memcg的内存使用量(usage)超过其软限制(soft_limit)时,该memcg会被加入到全局的soft_limit_tree红黑树中(每个节点对应一个红黑树)。 2. **回收时机**:在内存回收路径(如kswapd或直接回收)中,会检查这些红黑树,并调用`mem_cgroup_soft_limit_reclaim`函数进行回收。 3. **回收目标**:该函数会扫描memcg的LRU链表,回收不活跃的页面,以减小该memcg的内存使用量。 函数特点: - 软限制回收是一种后台回收机制,不会像硬限制(hard limit)那样强制阻止内存分配,而是尽量将内存使用量控制在软限制以下。 - 回收过程中,函数会按照LRU顺序选择页面进行回收,并考虑页面的活跃程度。 引用关系: 根据引用[2]的描述,我们可以知道软限制回收的触发和实现机制。而引用[1]则提供了如何通过cgroup_subsys_state找到mem_cgroup的细节,这在memcg的处理中是一个基础操作。引用[3]虽然提到了内存管理和释放的问题,但与当前问题关联不大。 因此,我们可以总结如下: ### `mem_cgroup_soft_limit_reclaim`函数的作用 `mem_cgroup_soft_limit_reclaim`是Linux内核中**内存控制组(memcg)软限制回收的核心函数**。当某个memcg的内存使用量(`usage`)超过其设定的软限制(`soft_limit`)时,该函数会被触发,负责回收该memcg中符合条件的内存页面,使其使用量回落到软限制以内[^2]。 --- ### 核心机制 #### 1. **软限制触发条件** - 每个memcg的软限制通过`memory.soft_limit_in_bytes`设置。 - 当`usage > soft_limit`时,内核将该memcg的`struct mem_cgroup_per_node`结构体插入到全局的`soft_limit_tree`红黑树中(每个NUMA节点一个红黑树)[^2]。 - 红黑树按`usage - soft_limit`的差值排序,差值最大的memcg优先被回收。 #### 2. **回收执行流程** 函数调用路径示例: ```mermaid graph TD A[kswapd回收线程] --> B[balance_pgdat] B --> C[shrink_node] C --> D[shrink_node_memcgs] D --> E[mem_cgroup_soft_limit_reclaim] ``` - 在内存回收过程中,当扫描到某个NUMA节点时,会检查该节点的`soft_limit_tree`。 - 对树中的每个memcg,调用`mem_cgroup_soft_limit_reclaim`进行回收。 #### 3. **回收策略细节** | 关键步骤 | 说明 | |------------------------|----------------------------------------------------------------------| | **扫描LRU链表** | 从memcg的不活跃LRU链表(inactive list)开始扫描 | | **选择回收目标** | 优先回收非活动且未被引用的页面 | | **回收数量控制** | 每次回收的页面数量由`swappiness`参数和系统内存压力动态决定 | | **退出条件** | 当memcg的`usage <= soft_limit`或达到最大扫描页数时停止回收[^2] | #### 4. **与硬限制回收的区别** | 特性 | 软限制回收 (`soft_limit_reclaim`) | 硬限制回收 (`hard_limit_reclaim`) | |--------------|------------------------------------------|----------------------------------------| | **触发条件** | `usage > soft_limit` | `usage > hard_limit` | | **紧迫性** | 后台异步回收,不影响进程运行 | 同步回收,可能阻塞进程 | | **目标** | 维持内存使用在软限制附近 | 防止内存使用超过硬限制 | --- ### 实际应用场景 #### 1. **容器内存控制** ```bash # 为容器设置软限制(例如:1.5GB) echo 1500000000 > /sys/fs/cgroup/memory/<容器ID>/memory.soft_limit_in_bytes ``` - 当容器内存使用超过1.5GB时,`mem_cgroup_soft_limit_reclaim`会被触发,在后台回收容器内缓存。 #### 2. **避免突发性OOM** - 软限制回收作为硬限制的缓冲层,可减少因瞬时内存超限导致的OOM(Out-Of-Memory)杀死进程。 --- ### 性能影响 - **开销可控**:回收在后台进行,默认使用非阻塞模式(`GFP_KERNEL | __GFP_HIGH`),避免影响前台进程。 - **优先级调整**:通过`/proc/sys/vm/memcg_soft_limit_priority`可调整软限制回收的优先级(值越高回收越积极)。 --- ### 代码示例(简化逻辑) ```c // mm/vmscan.c unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order, gfp_t gfp_mask, unsigned long *total_scanned) { struct mem_cgroup *memcg; unsigned long reclaimed = 0; // 1. 从soft_limit_tree中获取需要回收的memcg memcg = pick_next_soft_limit_memcg(pgdat); while (memcg) { // 2. 回收该memcg的内存 reclaimed += reclaim_memcg(memcg, gfp_mask, total_scanned); // 3. 检查是否达到回收目标 if (mem_cgroup_usage(memcg, false) <= memcg->soft_limit) remove_from_soft_limit_tree(memcg); // 4. 获取下一个memcg memcg = pick_next_soft_limit_memcg(pgdat); } return reclaimed; } ``` --- ### 监控与调试 #### 1. 查看软限制回收统计 ```bash cat /proc/vmstat | grep soft ``` - `soft_limit_reclaim`:软限制回收总次数 - `soft_limit_reclaim_pages`:回收的总页面数 #### 2. 跟踪函数调用 ```bash echo 'mem_cgroup_soft_limit_reclaim' > /sys/kernel/debug/tracing/set_ftrace_filter echo function > /sys/kernel/debug/tracing/current_tracer cat /sys/kernel/debug/tracing/trace_pipe ``` --- ### 相关问题 1. 如何调整memcg软限制回收的优先级? 2. 软限制回收与硬限制回收在LRU扫描策略上有何异同? 3. 为什么软限制回收使用红黑树组织待回收memcg? 4. 在NUMA系统中,软限制回收如何保证跨节点内存平衡? 5. 如何通过`/proc/vmstat`监控软限制回收的效率? [^1]: 通过`container_of`宏从`cgroup_subsys_state`获取`mem_cgroup`结构体。 [^2]: 软限制回收通过红黑树管理超限memcg,并按需回收内存。 [^3]: 内存释放后指针置空是避免UAF漏洞的常见方法,但该内容与软限制回收无直接关联。</think>### `mem_cgroup_soft_limit_reclaim` 函数的作用 `mem_cgroup_soft_limit_reclaim` 是 Linux 内核中**实现内存控制组(memcg)软限制回收的核心函数**。当某个 memcg 的内存使用量(`usage`)超过其设定的软限制(`soft_limit`)时,该函数会被触发,负责回收该 memcg 中的内存页面,使其使用量回落到软限制以内[^2]。 --- ### 核心机制 #### 1. **软限制触发条件** - 每个 memcg 的软限制通过 `memory.soft_limit_in_bytes` 设置 - 当检测到 `usage > soft_limit` 时: ```c if (mem_cgroup_usage(memcg) > memcg->soft_limit) { add_to_soft_limit_tree(memcg); // 加入全局红黑树[^2] } ``` - 超限的 memcg 会被加入全局的 `soft_limit_tree` 红黑树(每个 NUMA 节点一个树) #### 2. **回收执行流程** ```mermaid graph TD A[内存压力事件] --> B{检查soft_limit_tree} B -->|存在超限memcg| C[调用mem_cgroup_soft_limit_reclaim] C --> D[扫描memcg的LRU链表] D --> E[回收非活动页面] E --> F{usage≤soft_limit?} F -->|是| G[从红黑树移除] F -->|否| D ``` #### 3. **关键操作** | 操作 | 说明 | |--------------------------|----------------------------------------------------------------------| | **LRU链表扫描** | 从 memcg 的不活跃 LRU 链表(inactive list)开始扫描 | | **页面回收策略** | 优先回收非活动且未被引用的页面 | | **回收数量控制** | 每次回收的页面数量由 `swappiness` 和系统内存压力动态决定 | | **红黑树管理** | 使用 `soft_limit_tree` 高效管理待回收的 memcg[^2] | #### 4. **与硬限制的区别** | 特性 | 软限制回收 (`soft_limit_reclaim`) | 硬限制回收 (`hard_limit_reclaim`) | |--------------|------------------------------------------|----------------------------------------| | **触发条件** | `usage > soft_limit` | `usage > hard_limit` | | **紧迫性** | 后台异步回收,不影响进程运行 | 同步回收,可能阻塞进程 | | **目标** | 维持内存使用在软限制附近 | 防止内存使用超过硬限制 | --- ### 实际应用场景 #### 1. **容器内存控制** ```bash # 为容器设置软限制(例如:1.5GB) echo 1500000000 > /sys/fs/cgroup/memory/<容器ID>/memory.soft_limit_in_bytes ``` - 当容器内存使用超过 1.5GB 时,`mem_cgroup_soft_limit_reclaim` 自动触发回收 #### 2. **避免突发性 OOM** - 软限制回收作为硬限制的缓冲层,减少瞬时内存超限导致的 OOM(Out-Of-Memory)杀死进程 #### 3. **混合工作负载优化** - 在数据库+应用容器的场景中,通过软限制确保关键服务不被回收中断 --- ### 性能影响 1. **开销可控** - 回收在后台进行(通常由 `kswapd` 线程执行) - 默认使用非阻塞模式(`GFP_KERNEL | __GFP_HIGH`),避免影响前台进程 2. **优先级调整** ```bash # 调整软限制回收的积极程度(值越高越积极) echo 50 > /proc/sys/vm/memcg_soft_limit_priority ``` --- ### 代码逻辑(简化版) ```c unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order, gfp_t gfp_mask, unsigned long *total_scanned) { struct mem_cgroup *memcg; unsigned long reclaimed = 0; // 1. 从红黑树获取待回收的memcg memcg = pick_next_soft_limit_memcg(pgdat); while (memcg) { // 2. 回收该memcg的内存 reclaimed += reclaim_memcg(memcg, gfp_mask, total_scanned); // 3. 检查是否满足退出条件 if (mem_cgroup_usage(memcg, false) <= memcg->soft_limit) { remove_from_soft_limit_tree(memcg); // 从红黑树移除[^2] } // 4. 获取下一个memcg memcg = pick_next_soft_limit_memcg(pgdat); } return reclaimed; } ``` --- ### 监控与调试 #### 1. 查看软限制回收统计 ```bash cat /proc/vmstat | grep soft # 输出示例: soft_limit_reclaim 1285 # 触发次数 soft_limit_reclaim_pages 102400 # 回收总页数 ``` #### 2. 跟踪函数调用 ```bash echo 'mem_cgroup_soft_limit_reclaim' > /sys/kernel/debug/tracing/set_ftrace_filter echo function > /sys/kernel/debug/tracing/current_tracer cat /sys/kernel/debug/tracing/trace_pipe ``` --- ### 相关问题 1. 如何调整 memcg 软限制回收的优先级? 2. 软限制回收与硬限制回收在 LRU 扫描策略上有何异同? 3. 为什么软限制回收使用红黑树组织待回收 memcg? 4. 在 NUMA 系统中,软限制回收如何保证跨节点内存平衡? 5. 如何通过 `/proc/vmstat` 监控软限制回收的效率? [^1]: 通过 `container_of` 宏从 `cgroup_subsys_state` 获取 `mem_cgroup` 结构体 [^2]: 软限制回收通过红黑树管理超限 memcg,并按需回收内存 [^3]: 内存释放后指针置空是避免 UAF 漏洞的常见方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值