Cgroup-memory子系统分析(1)

文章介绍了Linux Cgroup内存子系统(memcg)的原理和功能,包括其在内存统计、限制、回收等方面的作用。主要内容包括:概述了memcg的背景和功能,详细阐述了Memcg的总体设计,如Memcg结构、Page与Swap的管理,以及Hierarchical结构。文章还深入探讨了内存charge和uncharge的过程,以及如何在内存超出限制时进行回收。最后,文章提到了Hierarchy的概念,解释了memcg在层级结构中的工作方式。
摘要由CSDN通过智能技术生成

1      概述

1.1      应用背景

Cgroup的memory子系统,即memory cgroup(本文以下简称memcg),提供了对系统中一组进程的内存行为的管理,从而对整个系统中对内存有不用需求的进程或应用程序区分管理,实现更有效的资源利用和隔离。

在实际业务场景中,为了防止一些应用程序对资源的滥用(可能因为应用本身的bug,如内存泄露),导致对同一主机上其他应用造成影响,我们往往希望可以控制应用程序的内存使用量,这是memcg提供的主要功能之一,当然它还可以做的更多。

Memcg的应用场景,往往来自一些虚拟化的业务需求,所以memcg往往作为cgroup的一个子系统与容器方案一起应用。在容器方案中,与一般的虚拟化方案不同,memcg在管理内存时,并不会在物理内存上对每个容器做区分,也就是说所有的容器使用的是同一个物理内存(有一种例外情况,如果存在多个内存节点,则可以通过cgroup中的cpuset子系统将不同的内存节点应用到不同的容器中)。对于共用的物理内存,memcg也不会对不同的容器做物理页面的预分配,也就是说同一个内存page,可能会被容器A使用,也可能被容器B使用。

所以memcg应用在容器方案中,虽然没有实现真正意义上的内存虚拟化,但是通过内核级的内存管理,依然可以实现某种意义上的虚拟化的内存管理,而且是真正的轻量级的。

(注:本文的功能及代码基于Linux 3.4)

1.2      功能简介

Memcg的主要应用场景有:

a.     隔离一个或一组应用程序的内存使用

对于内存饥渴型的应用程序,我们可以通过memcg将其可用内存限定在一定的数量以内,实现与其他应用程序内存使用上的隔离。

b.    创建一个有内存使用限制的控制组

比如在启动的时候就设置mem=XXXX。

c.     在虚拟化方案中,控制虚拟机的内存大小

比如可应用在LXC的容器方案中。

d.    确保应用的内存使用量

比如在录制CD/DVD时,通过限制系统中其他应用可以使用的内存大小,可以保证录制CD/DVD的进程始终有足够的内存使用,以避免因为内存不足导致录制失败。

e.     其他

各种通过memcg提供的特性可应用到的场景。

 

为了支撑以上场景,这里也简单列举一下memcg可以提供的功能特性:

a.     统计anonymous pages, file caches, swap caches的使用并限制它们的使用;

b.    所有page都链接在per-memcg的LRU链表中,将不再存在global的LRU;

c.     可以选择统计和限制memory+swap的内存;

d.    对hierarchical的支持;

e.     Soft limit;

f.     可以选择在移动一个进程的时候,同时移动对该进程的page统计计数;

g.     内存使用量的阈值超限通知机制;

h.    可以选择关闭oom-killer,并支持oom的通知机制;

i.      Root cgroup不存在任何限制;

2      总体设计

2.1      Memcg

Memcg在cgroup体系中提供memory隔离的功能,它跟cgroup中其他子系统一样可以由admin创建,形成一个树形结构,可以将进程加入到这些memcg中管理。

Memcg设计的核心是一个叫做res_counter的结构体,该结构体跟踪记录当前的内存使用和与该memcg关联的一组进程的内存使用限制值,每个memcg都有一个与之相关的res_counter结构。

 

而mem_cgroup结构体中通常会有两个res_counter结构,这是因为为了实现memory隔离,每个memcg主要要有两个维度的限制:

a.     Res – 物理内存;

b.    Memsw – memory + swap,即物理内存 + swap内存;

其中,memsw肯定是大于等于memory的。

 

另外,从res_counter结构中可以看出,每个维度又有三个指标:

a.     Usage – 组内进程已经使用的内存;

b.    Soft_limit – 软限制,非强制内存上限,usage超过这个上限后,组内进程使用的内存可能会加快步伐进行回收;

c.     Hard_limit – 硬限制,强制内存上限,usage不能超过这个上限,如果试图超过,则会触发同步的内存回收,或者触发OOM(详见OOM章节)。

其中,soft_limit和hard_limit都是admin在memcg的配置文件中进行配置的(soft_limit必须要小于hard_limit才能发挥作用),hard_limit是真正的内存限制,soft_limit只是为了实现更好的内存使用效果而做的辅助,而usage则是内核实时统计该组进程内存的使用值。

 

对于统计功能的实现,可以用一个简单的图表示:

概括为三点:

a.     统计针对每一个cgroup进行;

b.    每个cgroup中的进程,它的mm_struct知道自己属于哪个cgroup;

c.     每个page对应一个page_cgroup,而page_cgroup知道自己属于哪个memcg;

 

而整个统计和限制的实现过程可简单描述为:

某进程在需要统计的地方调用mem_cgroup_charge()来进行必要的结构体设置(增加计数等),判断增加计数后进程所在的cgroup的内存使用是否超过限制,如果超过了,则触发reclaim机制进行内存回收,如果回收后依然超过限制,则触发oom或阻塞机制等待;如果增加计数后没有超过限制,则更新相应page对应的page_cgroup,完成统计计数的修改,并将相应的page放到对应的LRU中进行管理。

该过程中涉及的各种实现细节,将在后面的章节进行分解描述。

2.2      Page & swap

讨论memcg,必然涉及对内存的管理和统计,而这些操作都是针对page来做的,所以一些针对page的设计需要先理清楚。

首先,在memcg的内存统计逻辑中,有几个基本思想:

a.     一个page最多只会被charge一次,并且一般就charge在第一次使用这个page的那个进程所在的memcg上。

b.    如果有多个memcg的进程引用了同一个page,该page也只会被统计在一个memcg中。

c.     Unchage往往跟page的释放相对应,所以可能存在某个进程不再使用某个page,但是对该page的统计还是记录在进程所在的memcg中,因为可能还有其他memcg中的进程在使用这个page,只要page无法释放,memcg就无法unchage。

 

那么对于usage的统计来说,当进程使用到新的page时,怎么知道这个page有没有chage过,是否该chage相应的memcg呢?而当进程释放page时,又需要知道这个page是由哪个memcg chage的,以便给它uncharge呢?

内核的做法是,给page安排一个指向memcg的指针,非NULL的指针表示这个page已经charge过了,而page释放时也可以通过该指针得知应该uncharge哪个memcg。不过实际上这个指向memcg的指针并不存在于page结构中,而是在对

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值