,,linux cgroups详细介绍

,,linux cgroups详细介绍

Cgroups(控制组)是linux内核提供的一种机制,可以根据需求将一系列系统任务及其子任务集成(或分离)到不同的组中,从而为系统资源管理提供统一的框架。本文主要介绍linux cgroups的介绍,有需要的朋友可以参考一下。

Cgroups是什么?

Cgroups(控制组)是linux内核提供的一种机制,可以根据需求将一系列系统任务及其子任务集成(或分离)到不同的组中,从而为系统资源管理提供统一的框架。简单地说,cgroups可以限制和记录任务团队使用的物理资源。本质上,cgroups是内核附加在程序上的一系列钩子,在程序运行时由资源的调度触发相应的钩子,达到资源跟踪和限制的目的。

本文以Ubuntu 16.04系统为例介绍cgroups,所有演示都在该系统中演示。

为什么要了解 cgroups

在以容器技术为代表的虚拟化技术大行其道的时代,了解cgroups技术是非常必要的!例如,我们可以很容易地限制一个容器可以使用的CPU、内存和其他资源。这是如何实现的?通过了解cgroups技术,我们可以看到linux系统中整个资源限制系统的脉络。从而帮助我们更好地理解和使用linux系统。

cgroups 的主要作用

cgroups的主要目的是为不同用户级别的资源管理提供一个统一的界面。从单个任务的资源控制到操作系统级别的虚拟化,cgroups提供了四种功能:

资源限制:cgroups可以限制任务所需的资源总量。

比如设置任务运行时使用的内存上限,一旦超过就发送OOM。

优先级:分配的CPU时间片数和磁盘IO带宽实际上相当于控制任务运行的优先级。

资源统计:cgoups可以统计系统的资源使用情况,比如CPU使用时间,内存使用情况。该功能非常适合目前云产品的计费方式。

任务控制:cgroups可以暂停和恢复任务。

相关概念

任务在linux系统中,内核本身的调度和管理并不区分进程和线程,而是根据克隆时传入的参数不同,在概念上区分进程和线程。这里,任务用于指示系统的进程或线程。

Cgroup(控制组)cgroups中的资源控制是以CGroups为单位实现的。Cgroup表示按照一定的资源控制标准划分的任务组,包含一个或多个子系统。任务可以加入一个cgroup或从一个cgroup迁移到另一个cgroup。

子系统(subsystem)cgroups中的子系统是资源调度控制器(也称为控制器)。例如,CPU子系统可以控制CPU的时间分配,内存子系统可以限制内存的使用量。以笔者使用的Ubuntu 16.04.3为例,其内核版本为4.10.0,支持的子系统如下(cat /proc/cgroups):

BlkIO限制块设备的IO。

cpu时间片的分配是有限制的,和cpuacct挂载在同一个目录下。

Cpuacct生成cgroup中任务占用cpu资源的报告,该报告与CPU挂载在同一个目录中。

Cpuset将独立的CPU(多处理器系统)和内存节点分配给cgroup中的任务。

设备允许或禁止cgroup中的任务访问设备。

冷冻机暂停/恢复cgroup中的任务。

Hugetlb限制了使用的内存页数。

限制内存组中任务的可用内存,自动生成资源利用报告。

Net_cls用类标识符(classid)标记网络数据包,这允许Linux流量控制器(tc指令)识别来自特定cgroup任务的数据包,并进行网络限制。

Net_prio允许根据组设置网络流量的优先级。

Perf_event允许使用Perf工具来监控cgroup。

Pids限制了任务的数量。

层次结构有一系列以树形结构排列的cgroup,每个层次结构通过绑定相应的子系统来控制资源。层次结构中的cgroup节点可以包含零个或多个子节点,子节点继承父节点安装的子系统。一个操作系统中可以有多个级别。

cgroups 的文件系统接口

Cgroups以文件的形式提供应用程序接口。我们可以通过mount命令检查cgroups的默认挂载点:

复制代码如下:$ mount | grepcroup

第一行中的tmpfs表示/sys/fs/cgroup目录中的所有文件都是内存中的临时文件。

第二行的挂载点/sys/fs/cgroup/systemd是用来支持systemd系统中的cgroups的,以后作者会专门介绍相关内容。

其余的挂载点是内核支持的每个子系统的根层次结构。

需要注意的是,在使用systemd系统的操作系统中,/sys/fs/cgroup目录是systemd在系统启动过程中挂载的,是只读类型。换句话说,系统不建议我们在/sys/fs/cgroup目录中创建新目录,并挂载其他子系统。这和以前的操作系统不一样。

让我们探索一下/sys/fs/cgroup目录及其子目录中的内容:

/sys/fs/cgroup目录是每个子系统的根目录。我们以内存子系统为例,看看内存目录里有什么。

这些文件是cgroups的内存子系统中的根设置。例如,memory.limit_in_bytes中的数字用于限制进程的最大可用内存,使用swap的权重保存在memory.swappiness中,等等。

因为cgroups使用这些文件作为API,所以我可以通过创建或修改这些文件的内容来应用cgroups。具体应该怎么做?例如,我们如何限制一个进程可以使用的资源?接下来,我们将通过一个简单的演示演示如何使用cgroups来限制一个进程可以使用的资源。

查看进程所属的 cgroups

可以通过/proc/[pid]/cgroup检查指定的进程属于哪些cgroup:

每行包含由冒号分隔的三列。它们的含义是:

cgroup树的ID和/proc/cgroups文件中的ID是一一对应的。

和多个子系统之间用逗号分隔。这里name=systemd的意思是不绑定任何子系统,只是把他命名为systemd。

进程组树中的路径,即进程所属的组,是到挂载点的相对路径。

因为cgroups使用这些文件作为API,所以我可以通过创建或修改这些文件的内容来应用cgroups。具体应该怎么做?例如,我们如何限制一个进程可以使用的资源?接下来,我们将通过一个简单的演示演示如何使用cgroups来限制一个进程可以使用的资源。

cgroups 工具

在通过systemd介绍cgroups的应用之前,我们先用cgroup-bin toolkit中的cgexec来演示demo。Ubuntu默认没有安装cgroup-bin工具包。请通过以下命令安装它:

复制代码如下:$ sudo apt安装cgroup-bin

demo:限制进程可用的 CPU

当我们使用cgroups时,最好不要直接在每个子系统的根目录中修改它的配置文件。推荐的方法是在子系统树中为不同的需求定义不同的节点。例如,我们可以在/sys/fs/cgroup/cpu目录中创建一个名为nick_cpu的新目录:

$ cd /sys/fs/cgroup/cpu

$ sudo mkdir nick_cpu

然后检查新创建的目录的内容:

创建文件目录时,cgroups的文件系统会自动创建这些配置文件,你不觉得奇怪吗!

让我们通过以下设置将CPU周期限制为总周期的十分之一:

$ sudo su $ echo 100000 nick _ CPU/CPU . CFS _ period _ us

$ echo 10000 nick _ CPU/CPU . CFS _ quota _ us

以上两个参数大家熟悉吗?是的,作者在文章《Docker: 限制容器可用的 CPU》中介绍的'-CPU-period=100000-CPU-quota=200000 '就是他们实现的。

然后创建一个CPU密集型程序:

void main()

{无符号int i,end

end=1024 * 1024 * 1024

for(I=0;我结束;

){我;}}

保存文件cputime.c,以不同的方式编译和执行它:

$ gcc cputime.c -o cputime

$ sudo su$ time。/cputime

$ time cgexec -g cpu:nick_cpu。/cputime

time命令可以为我们报告程序执行所消耗的时间,真正的是我们实际收到的时间。使用cgexec应用我们添加到运行cputime程序的进程中的cgroup配置nick_cpu。上图显示默认执行只需要2s左右。通过cgroups限制CPU资源后,需要运行23s。

demo:限制进程可用的内存

这一次,让我们限制进程可用的最大内存,并在/sys/fs/cgroup/memory下创建目录nick_memory:

$ cd /sys/fs/cgroup/memory

$ sudo mkdir nick_memory

以下设置将进程的可用内存限制为最大300M,并且不使用交换:

#物理内存交换=300mb1024 * 1024 * 300=314572800 $ sudo su $ echo 314572800 nick _ memory/memory . limit _ in _ bytes $ echo 0 nick _ memory/memory . swappiness

然后创建一个不断分配内存的程序。它分五次分配内存,每次申请100M:

# includesdio . h # includestdlib . h # includestring . h # define CHUNK _ SIZE 1024 * 1024 * 100 void main(){ char * p;int I;for(I=0;i5;I){ p=malloc(sizeof(char)* CHUNK _ SIZE);if(p==NULL){ printf(' fail to malloc!);返回;}//memset()函数用于将指定内存的前N个字节设置为特定值memset(p,0,CHUNK _ SIZE);printf('内存分配%d MB\n ',(I 1)* 100);}}

将上面的代码保存为mem.c文件并编译它:

$ gcc mem.c -o mem

生成的mem程序:

$ ./mem

至此,一切顺利,然后尝试添加刚才的约束:

$ cgexec -g内存:nick_memory。/mem

由于内存不足和禁止使用swap,资源受限的进程在申请内存时被强行杀死。

接下来,使用压力程序测试一个类似的场景(通过压力程序申请500M内存):

$ sudo CG exec-g memory:nick _ memory stress-VM 1-VM-bytes 500000000-VM-keep-verbose

应力程序可以提供更详细的信息,进程通过接收SIGKILL(signal 9)信号而被杀死。

在实际应用中,需要同时限制多种资源,如CPU资源和内存资源。使用cgexec实现这样一个用例其实很简单,直接指定多个-g选项即可:

$ cgexec -g cpu:nick_cpu -g内存:nick_memory。/cpumem

总结

Cgroups是linux内核提供的一个函数,因为涉及到很多概念,所以不太好理解。本文试图通过最简单的演示来介绍概念内容和演示cgroups的用法。希望直观的演示能帮助你了解cgroups。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: