linux禁止增加进程命令,Linux cgroups 命令简介

相关概念

Task(任务)

在 linux 系统中,内核本身的调度和管理并不对进程和线程进行区分,只是根据 clone 时传入的参数的不同来从概念上区分进程和线程。这里使用 task 来表示系统的一个进程或线程。

Cgroup(控制组)

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

Subsystem(子系统)

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

3f91f84600d4e5f165b22f1e527edafd.png

Hierarchy(层级)

层级有一系列 cgroup 以一个树状结构排列而成,每个层级通过绑定对应的子系统进行资源控制。层级中的 cgroup 节点可以包含零个或多个子节点,子节点继承父节点挂载的子系统。一个操作系统中可以有多个层级。

cgroups 的文件系统接口

cgroups 以文件的方式提供应用接口,我们可以通过 mount 命令来查看 cgroups 默认的挂载点:

$ mount | grep cgroup

59977a8442d71395ad529db25f88217f.png

第一行的 tmpfs 说明 /sys/fs/cgroup 目录下的文件都是存在于内存中的临时文件。

第二行的挂载点 /sys/fs/cgroup/systemd 用于 systemd 系统对 cgroups 的支持,相关内容笔者今后会做专门的介绍。

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

需要注意的是,在使用 systemd 系统的操作系统中,/sys/fs/cgroup 目录都是由 systemd 在系统启动的过程中挂载的,并且挂载为只读的类型。换句话说,系统是不建议我们在 /sys/fs/cgroup 目录下创建新的目录并挂载其它子系统的。这一点与之前的操作系统不太一样。

下面让我们来探索一下 /sys/fs/cgroup 目录及其子目录下都是些什么:

e3ef5de7d9b889c2f5f45ee0bcef987b.png

/sys/fs/cgroup 目录下是各个子系统的根目录。我们以 memory 子系统为例,看看 memory 目录下都有什么?

e84792f62601d68eab52f63823b9c26d.png

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

既然 cgroups 是以这些文件作为 API 的,那么我就可以通过创建或者是修改这些文件的内容来应用 cgroups。具体该怎么做呢?比如我们怎么才能限制某个进程可以使用的资源呢?接下来我们就通过简单的 demo 来演示如何使用 cgroups 限制进程可以使用的资源。

查看进程所属的 cgroups

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

de2bc36693646d64f05e041393ae51ce.png

每一行包含用冒号隔开的三列,他们的含义分别是:

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

和 cgroup 树绑定的所有 subsystem,多个 subsystem 之间用逗号隔开。这里 name=systemd 表示没有和任何 subsystem 绑定,只是给他起了个名字叫 systemd。

进程在 cgroup 树中的路径,即进程所属的 cgroup,这个路径是相对于挂载点的相对路径。

既然 cgroups 是以这些文件作为 API 的,那么我就可以通过创建或者是修改这些文件的内容来应用 cgroups。具体该怎么做呢?比如我们怎么才能限制某个进程可以使用的资源呢?接下来我们就通过简单的 demo 来演示如何使用 cgroups 限制进程可以使用的资源。

cgroups 工具

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

$ sudo apt install cgroup-bin

demo:限制进程可用的 CPU

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

$cd/sys/fs/cgroup/cpu

$sudo mkdirnick_cpu

然后查看新建的目录下的内容:

f83195ab125b543148b6d683075a0fd2.png

是不是有点吃惊,cgroups 的文件系统会在创建文件目录的时候自动创建这些配置文件!

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

$sudosu

$echo100000>nick_cpu/cpu.cfs_period_us

$echo10000>nick_cpu/cpu.cfs_quota_us

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

voidmain()

{

unsignedinti,end;

end=1024*1024*1024;

for(i=0;i

{

i++;

}

}

保存为文件 cputime.c 编译并通过不同的方式执行:

$gcccputime.c-ocputime

$sudosu

$time./cputime

$timecgexec-gcpu:nick_cpu./cputime

6fbb4ff86e36cf3c41742e6519ab10a9.png

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

demo:限制进程可用的内存

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

$cd/sys/fs/cgroup/memory

$sudo mkdirnick_memory

下面的设置把进程的可用内存限制在最大 300M,并且不使用 swap:

# 物理内存 + SWAP <= 300 MB;1024*1024*300 = 314572800

$sudosu

$echo314572800>nick_memory/memory.limit_in_bytes

$echo0>nick_memory/memory.swappiness

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

#include

#include

#include

#define CHUNK_SIZE 1024 * 1024 * 100

voidmain()

{

char*p;

inti;

for(i=0;i<5;i++)

{

p=malloc(sizeof(char)*CHUNK_SIZE);

if(p==NULL)

{

printf("fail to malloc!");

return;

}

// memset() 函数用来将指定内存的前 n 个字节设置为特定的值

memset(p,0,CHUNK_SIZE);

printf("malloc memory %d MBn",(i+1)*100);

}

}

把上面的代码保存为 mem.c 文件,然后编译:

$ gcc mem.c -o mem

执行生成的 mem 程序:

$ ./mem

此时一切顺利,然后加上刚才的约束试试:

$ cgexec -g memory:nick_memory ./mem

f41ac3563e1de1325f4bd17afb16f4cd.png

由于内存不足且禁止使用 swap,所以被限制资源的进程在申请内存时被强制杀死了。

下面再使用 stress 程序测试一个类似的场景(通过 stress 程序申请 500M 的内存):

$ sudo cgexec -g memory:nick_memory stress --vm 1 --vm-bytes 500000000 --vm-keep --verbo

e47137875f68e1ee222674fdcb252ce3.png

stress 程序能够提供比较详细的信息,进程被杀掉的方式是收到了 SIGKILL(signal 9) 信号。

实际应用中往往要同时限制多种的资源,比如既限制 CPU 资源又限制内存资源。使用 cgexec 实现这样的用例其实很简单,直接指定多个 -g 选项就可以了:

$ cgexec -g cpu:nick_cpu -g memory:nick_memory ./cpumem

总结

cgroups 是 linux 内核提供的功能,由于牵涉的概念比较多,所以不太容易理解。本文试图在介绍概念性内容的同时,用最简单的 demo 演示 cgroups 的用法。希望直观的 demo 能够帮助大家理解 cgroups。

【关于投稿】

如果大家有原创好文投稿,请直接给公号发送留言。返回搜狐,查看更多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值