当前位置: 首页 > Linux

LinuxCgroup系列(03):限制cgroup进程数(子系统pids)

时间:2023-04-06 11:11:13 Linux

上一篇介绍了如何管理cgroups。从本文开始,我们将介绍具体的子系统。本文将介绍一个名为pids的简单子系统,其作用是限制cgroup及其所有后代中可以创建的任务总数。注意:这里的任务指的是fork和clone函数创建的进程。由于clone函数也可以创建线程(在Linux中,线程是一个特殊的进程),所以这里的任务也包括线程。本文统一由进程来表示任务,即本文中的进程分别代表进程和线程本文所有示例均在ubuntu-server-x86_6416.04下执行通过在ubuntu16.04中创建子cgroup,systemd有帮我们绑定挂载了各个subsystem和cgrouptree好了,我们用现成的就可以了。#从这里的输出我们可以看到pids已经挂载到/sys/fs/cgroup/pids上了,也就是dev@dev:~$mount|greppidscgroupon/sys/fs/cgroup/pidstypemadebysystemdcgroup(rw,nosuid,nodev,noexec,relatime,pids)createsachildcgroup,namedtest#进入目录/sys/fs/cgroup/pids/新建目录,即创建子cgroupdev@dev:~$cd/sys/fs/cgroup/pids/dev@dev:/sys/fs/cgroup/pids$sudomkdirtest#这里设置test目录的属主为dev账号,这样就不用后续操作每次都输入sudo。省事dev@dev:/sys/fs/cgroup/pids$sudochown-Rdev:dev./test/看看test目录下的文件#除了上一篇介绍的文件,这里还有两个A文件dev@dev:/sys/fs/cgroup/pids$cdtestdev@dev:/sys/fs/cgroup/pids/test$lscgroup.clone_childrencgroup.procsnotify_on_releasepids.currentpids.maxtasks是这两个文件的含义:pids.current:表示当前cgroup及其所有后代cgroup中存在的进程总数#因为这是新创建的cgroup,所以里面没有进程dev@dev:/sys/fs/cgroup/pids/test$catpids.current0pids.max:当前cgroup及其所有后代cgroup中允许创建的最大进程总数。根cgroup下没有这个文件。原因很明显,因为我们不需要限制整个系统。创建的进程数。#max表示不限制dev@dev:/sys/fs/cgroup/pids/test$catpids.maxmax限制进程数下面我们演示如何使限制功能生效#-------------------------第一个shell窗口--------------------#Setpids.maxto1,即当前cgroup只允许一个进程dev@dev:/sys/fs/cgroup/pids/test$echo1>pids.max#将当前bash进程添加到这个cgroupdev@dev:/sys/fs/cgroup/pids/test$echo$$>cgroup.procs#------------------------第二个shell窗口----------------------#重新打开一个bash窗口,查看里面cgroup"test"的一些数据#因为这是新开的bash,与cgroup"test"无关没有关系,所以这里运行命令不会影响cgroup"test"dev@dev:~$cd/sys/fs/cgroup/pids/test#设置的最大进程数为1dev@dev:/sys/fs/cgroup/pids/test$catpids.max1#目前已经有一个进程在test中,也就是说不能在fork或者clone进程中dev@dev:/sys/fs/cgroup/pids/test$catpids.current1#这个进程是第一个bashdev@dev:/sys/fs/cgroup/pids/test$catcgroup.procs3083#-------------------------ofawindow第一个shell窗口--------------------#回到第一个窗口,运行一个命令即可,因为当前的pids.current已经是等于pids.max,#所以创建新进程失败,所以命令运行失败,说明限制生效dev@dev:/sys/fs/cgroup/pids/test$ls-bash:fork:retry:没有子进程-bash:fork:retry:Nochildpprocesses-bash:fork:retry:Nochildprocesses-bash:fork:retry:Nochildprocesses-bash:fork:Resourcetemporaryunavailable当前cgroup和子cgroup的关系当前的pids.current和pids.maxcgroup代表当前cgroup和所有后代cgroup中的所有进程,所以后代cgroup中pids.max的大小不能超过父cgroup中的大小。如果子cgroup中的pids.max设置大于父cgroup中的大小,会发生什么情况?请看下面的demo#继续使用上面的两个窗口#----------------------------第二个shell窗口---------------------#设置pids.max为2dev@dev:/sys/fs/cgroup/pids/test$echo2>pids.max#CreateundertestAchildcgroupdev@dev:/sys/fs/cgroup/pids/test$mkdirsubtestdev@dev:/sys/fs/cgroup/pids/test$cdsubtest/#设置subtest的pids.max为5dev@dev:/sys/fs/cgroup/pids/test/subtest$echo5>pids.max#将当前bash进程添加到subtestdev@dev:/sys/fs/cgroup/pids/test/subtest$echo$$>cgroup.procs#------------------------第三个shell窗口---------------------#重新打开一个bash窗口,查看test和subtest中的数据#test中的数据如下:dev@dev:~$cd/sys/fs/cgroup/pids/testdev@dev:/sys/fs/cgroup/pids/test$catpids.max2#这里是2,表示test和subtest的进程总数为2dev@dev:/sys/fs/cgroup/pids/test$catpids.current2dev@dev:/sys/fs/cgroup/pids/test$catcgroup.procs3083#subtest里面的数据如下:dev@dev:/sys/fs/cgroup/pids/测试$catsubtest/pids.max5dev@dev:/sys/fs/cgroup/pids/test$catsubtest/pids.current1dev@dev:/sys/fs/cgroup/pids/test$catsubtest/cgroup.procs3185#------------------------第一个外壳窗口--------------------#回到第一个窗口,随机运行一个命令。由于测试中的pids.current已经等于pids.max,#so创建新进程失败,所以命令运行失败,说明限制生效dev@dev:/sys/fs/cgroup/pids/test$ls-bash:fork:retry:没有子进程-bash:fork:retry:没有子进程-bash:fork:retry:没有子进程-bash:fork:retry:没有子进程-bash:fork:资源暂时不可用#------------------------第二个shell窗口---------------------#回到第二个窗口,随便跑个命令,虽然subtest中的pids.max还是大于pids.current,#但是因为parentcgroup"test"中的pids.current有已经等于pids.max,#所以创建新进程失败,所以命令运行失败,说明子cgroup的进程数不仅受限于自身的pids.max,#也是受限的通过祖先cgroupdev@dev:/sys/fs/cgroup/pids/test/subtest$ls-bash:fork:retry:Nochildprocesses-bash:fork:retry:没有子进程-bash:fork:retry:没有子进程-bash:fork:retry:没有子进程-bash:fork:Resourcetemporaryunavailablepids.current>pids.max不是所有情况都是pids.max>=pids.current。以下两种情况会出现pids.maxpids.maxdev@dev:/sys/fs/cgroup/pids/test$catpids.max1#此时pids.current>pids.max会出现dev@dev:/sys/fs/cgroup/pids/test$catpids.current2#----------------------------第一个shellwindow--------------------#回到第一个shell#仍然运行失败,说明虽然pids.current>pids.max,但是函数限制创建新进程仍然会生效:retry:Nochildprocesses-bash:fork:retry:Nochildprocesses-bash:fork:Resourcetemporaryunavailablepids.max只会在当前cgroup中的进程中k和clone时才会生效。在当前cgroup中添加其他进程时,不会检测到pids.max,所以在当前cgroup中添加其他进程可能会导致pids.current>pids.max#继续使用以上三个窗口#------------------------第三个shell窗口--------------------#Movetheprocessinsubtest到根cgroup,然后删除subtestdev@dev:/sys/fs/cgroup/pids/test$sudosh-c'echo3185>/sys/fs/cgroup/pids/cgroup.procs'#里面没有进程,说明移动成功dev@dev:/sys/fs/cgroup/pids/test$catsubtest/cgroup.procs#移除成功dev@dev:/sys/fs/cgroup/pids/test$rmdirsubtest/#此时test下的pids.max等于pids.currentdev@dev:/sys/fs/cgroup/pids/test$catpids.max1dev@dev:/sys/fs/cgroup/pids/test$catpids.current1#------------------------第二个shell窗口----------------------#添加当前bash测试dev@dev:/sys/fs/cgroup/pids/test/subtest$cd..dev@dev:/sys/fs/cgroup/pids/test$echo$$>cgroup.procs#------------------------第三个shell窗口---------------------#回到第三个窗口,查看相关信息#第一个和第二个窗口的bash属于testdev@dev:/sys/fs/cgroup/pids/test$catcgroup.procs30833185dev@dev:/sys/fs/cgroup/pids/test$catpids.max1#appearedpids.current>pids在.max的情况下,这是因为我们将第二个窗口的shell添加到testdev@dev:/sys/fs/cgroup/pids/test$catpids.current2#-------------------------第二个shell窗口--------------------#fork调用的限制仍然有效dev@dev:/sys/fs/cgroup/pids/test$ls-bash:fork:retry:没有子进程-bash:fork:retry:没有子进程-bash:fork:retry:没有子进程-bash:fork:retry:Nochildprocesses-bash:fork:Resourcetemporaryunavailablecleanup#------------------------第三个shell窗口----------------------dev@dev:/sys/fs/cgroup/pids/test$sudosh-c'echo3185>/sys/fs/cgroup/pids/cgroup.procs'dev@dev:/sys/fs/cgroup/pids/test$sudosh-c'echo3083>/sys/fs/cgroup/pids/cgroup.procs'dev@dev:/sys/fs/cgroup/pids/test$cd..dev@dev:/sys/fs/cgroup/pids$sudormdirtest/结语本文介绍了如何使用pids子系统来限制一个cgroup中的进程数,以及一些需要注意的点一般说起来,pid比较简单。下一篇会介绍稍微复杂一点的内存控制。请参阅进程号控制器