cgroups(7)— Linux中文手册页

CGROUPS(7)Linux程序员手册CGROUPS(7)

NAME         顶部

       cgroups-Linux控制组

说明         顶部

       控制组(通常称为cgroup)是Linux内核
       允许将流程组织为分层的功能
       然后可以限制其使用各种类型资源的组
       并进行监控。内核的cgroup接口通过
       伪文件系统,称为cgroupfs。分组是在
       核心cgroup内核代码,而资源跟踪和限制是
       在一组每个资源类型的子系统(内存,CPU,
       等等)。

   术语 
       一个cgroup中是进程的集合绑定到一组
       通过cgroup文件系统定义的限制或参数。

       一个子系统是一个内核组件,修改的行为
       cgroup中的进程。已经实现了各种子系统,
       使诸如限制CPU数量之类的事情成为可能
       cgroup可用的时间和内存,占CPU时间
       由cgroup使用,并冻结和恢复执行
       cgroup中的进程。子系统有时也称为
       资源控制器(或简称为控制器)。

       控制器的cgroup按层次结构排列。这个
       通过创建,删除和重命名来定义层次结构
       cgroup文件系统中的子目录。在每个级别
       可以定义层次结构,属性(例如限制)。极限
       控制和cgroup提供的会计通常有效
       在cgroup下的整个子层次结构中
       属性已定义。因此,例如,对
       层次结构中较高级别的cgroup不能超过
       后代cgroups。

   Cgroups版本1和版本2
       cgroups实现的最初版本是在Linux中
       2.6.24。随着时间的推移,各种cgroup控制器已添加到
       允许管理各种类型的资源。但是,那
       这些控制器的开发在很大程度上是不协调的,
       结果导致控制器和控制器之间出现许多不一致之处
       cgroup层次结构的管理变得相当复杂。(一个
       这些问题的详细描述可以在内核中找到。
       源文件Documentation / cgroup-v2.txt。)

       由于最初的cgroups实现存在问题
       (cgroups版本1)从Linux 3.10开始,开始了新的工作,
       正交实施来解决这些问题。最初标记
       实验性的,并隐藏在-o __DEVEL__sane_behavior挂载后面
       选项,最终制作了新版本(cgroups版本2)
       正式发布的Linux 4.5。两者之间的差异
       版本在以下文本中描述。文件
       cgroups v1中存在的cgroup.sane_behavior是此安装的遗物
       选项。该文件始终报告为“ 0”,并且仅保留用于向后
       兼容性。

       尽管cgroups v2旨在替代cgroups v1,但是
       较旧的系统继续存在(出于兼容性原因,
       不太可能被删除)。目前,cgroups v2仅实现
       cgroups v1中可用的控制器子集。两个系统
       已实现,因此v1控制器和v2控制器都可以
       安装在同一系统上。因此,例如,可以使用
       在版本2下受支持的控制器,同时
       使用版本2尚不支持的版本1控制器
       这些控制器。唯一的限制是控制器
       不能同时在cgroups v1层次结构和
       在cgroups v2层次结构中。

CGROUPS版本1         顶部

       在cgroups v1下,每个控制器可以单独安装
       cgroup文件系统,提供了自己的层次结构
       系统上的进程。也可以合并多个
       (甚至所有)cgroup v1控制器针对同一cgroup
       文件系统,这意味着共同安装的控制器可以管理相同的文件系统
       流程的分层组织。

       对于每个已安装的层次结构,目录树都会镜像该控件
       组层次结构。每个对照组均由一个目录表示,
       每个子控件cgroup都表示为一个子控件
       目录。例如,/ user / joe / 1.session表示控件
       group 1.session,它是cgroup joe的子级,后者是/ user的子级
        。每个cgroup目录下都有一组文件,可以
       读或写,反映了资源限制和一些常规
       cgroup属性。

   任务(线程)与进程 
       之间的关系在cgroups v1中,对进程task进行了区分。
       在此视图中,一个流程可以包含多个任务(更常见的是
       从用户空间的角度来看,称为线程,并且在
       此手册页的其余部分)。在cgroups v1中,可以
       独立地处理线程中的cgroup成员资格
       处理。

       cgroups v1能够在不同cgroup之间拆分线程
       在某些情况下造成了问题。例如,对于
       内存控制器,因为进程的所有线程共享一个
       单个地址空间。由于这些问题,
       独立地处理线程中的cgroup成员资格
       最初的cgroups v2实施中删除了该流程,并且
       随后以更有限的形式恢复(请参见
       下面的“线程模式”。

   挂载v1控制器要 
       使用cgroup,需要使用CONFIG_CGROUP构建的内核
       选项。此外,每个v1控制器都有一个关联的
       必须设置才能使用该配置选项
       控制器。

       为了使用v1控制器,必须将其安装在cgroup上
       文件系统。此类挂载的通常位置是
       在/ sys / fs / cgroup挂载的tmpfs(5)文件系统下。因此,可能会挂载CPU
       控制器如下:

           挂载-t cgroup -o cpu无/ sys / fs / cgroup / cpu

       可以将多个控制器安装在同一个层次上
       拱形。例如,这里的cpucpuacct控制器是
       与单个层次结构共同安装:

           挂载-t cgroup -o cpu,cpuacct无/ sys / fs / cgroup / cpu,cpuacct

       挂载控制器的作用是使一个进程处于同一状态
       所有组合控制器的cgroup。分开安装
       控制器允许一个控制器的进程位于cgroup / foo1中
       而在另一个/ foo2 / foo3中。

       可以将所有v1控制器安装在同一层级上
       希

           挂载-t cgroup -o全部cgroup / sys / fs / cgroup

       (通过省略-o all可以达到相同的结果,因为它是
       如果未明确指定任何控制器,则为默认值。)

       无法将同一控制器安装在多个
       cgroup层次结构。例如,不可能同时安装两个
       将cpucpuacct控制器针对一个层次结构进行安装单独针对另一个层次结构
       的cpu控制器。有可能的
       创建完全相同的一组安装点
       共装控制器。但是,在这种情况下,所有结果都是
       提供了相同层次结构视图的多个安装点。

       请注意,在许多系统上,v1控制器会自动
       安装在/ sys / fs / cgroup下;特别是systemd(1)自动
       创建此类安装点。

   卸载v1控制器 
       可以使用umount(8) com 卸载已安装的cgroup文件系统。
       命令,如以下示例所示:

           卸载/ sys / fs / cgroup / pids

       但请注意:cgroup文件系统只有在未卸载时才被卸载
       忙,也就是说,它没有子cgroup。如果不是这样,
       那么umount(8)的唯一作用是使安装不可见。
       因此,要确保真正删除安装点,必须
       首先删除所有子cgroup,然后依次删除
       所有成员进程都已从这些cgroup移到了根目录
       cgroup。

   Cgroups版本1控制器
       每个cgroups版本1控制器均由内核控制。
       配置选项(在下面列出)。此外,可用性
       cgroups功能的功能由CONFIG_CGROUPS内核con-控制
       图形化选项。

       cpu(自Linux 2.6.24起; CONFIG_CGROUP_SCHED)
              可以保证Cgroup的“ CPU共享”数量最少
              系统繁忙时。这不限制cgroup的CPU
              CPU不忙时的使用率。有关更多信息,请参见
              Documentation / scheduler / sched-design-CFS.txt。

              在Linux 3.2中,此控制器已扩展为提供CPU
              “带宽”控制。如果内核配置有CON- 
              FIG_CFS_BANDWIDTH,则每个调度周期内(定义
              通过cgroup目录中的文件),可以定义
              分配给一个进程中的CPU时间的上限
              cgroup。即使没有其他限制,此上限也适用
              争夺CPU。有关更多信息,请参见
              内核源文件Documentation / scheduler / sched-bwc.txtcpuacct(从Linux 2.6.24开始; CONFIG_CGROUP_CPUACCT)
              这样可以按进程组统计CPU使用率。

              可以在内核源文件中找到更多信息。
              Documentation / cgroup-v1 / cpuacct.txtcpuset(从Linux 2.6.24开始; CONFIG_CPUSETS)
              该cgroup可用于将cgroup中的进程绑定到
              指定的一组CPU和NUMA节点。

              可以在内核源文件中找到更多信息。
              Documentation / cgroup-v1 / cpusets.txt内存(从Linux 2.6.25开始; CONFIG_MEMCG)
              内存控制器支持报告和限制
              cgroup使用的进程内存,内核内存和交换。

              可以在内核源文件中找到更多信息。
              Documentation / cgroup-v1 / memory.txt设备(自Linux 2.6.26起;CONFIG_CGROUP_DEVICE)
              这支持控制可能创建的进程(mknod)
              设备以及打开它们以进行读取或写入。的
              可以将策略指定为允许列表和拒绝列表。
              强制实施层次结构,因此新规则不得违反现有规则
              目标或祖先cgroup的规则。

              可以在内核源文件中找到更多信息。
              Documentation / cgroup-v1 / devices.txt冷冻机(自Linux 2.6.28起; CONFIG_CGROUP_FREEZER)
              该冷冻 cgroup中可以暂停和恢复(恢复)所有亲
              cgroup中的成功。冻结cgroup / A也会导致
              例如,/ A / B中的子进程将被冻结。

              可以在内核源文件中找到更多信息。
              Documentation / cgroup-v1 / freezer-subsystem.txtnet_cls(从Linux 2.6.29开始; CONFIG_CGROUP_NET_CLASSID)
              这会将为cgroup指定的classid放置在网络上
              由cgroup创建的数据包。然后可以使用这些classid
              在防火墙规则中,以及
              tc(8)。这仅适用于离开cgroup的数据包,不适用于
              到达cgroup的流量。

              可以在内核源文件中找到更多信息。
              Documentation / cgroup-v1 / net_cls.txtblkio(因为Linux 2.6.33; CONFIG_BLK_CGROUP)
              所述blkio cgroup中控制和限制访问指定的块
              通过以节流和
              叶节点和中间节点的上限
              存储层次结构。

              有两种策略。首先是成比例的
              CFQ实现的基于权重的磁盘时间划分。这个
              对于使用CFQ的叶节点有效。第二个是a
              调整策略,该策略指定对服务器的I / O速率上限
              设备。

              可以在内核源文件中找到更多信息。
              Documentation / cgroup-v1 / blkio-controller.txtperf_event(从Linux 2.6.39开始; CONFIG_CGROUP_PERF)
              此控制器允许PERF监视所述一组处理的
              分组在cgroup中。

              可以在内核源文件中找到更多信息。
              tools / perf / Documentation / perf-record.txtnet_prio(从Linux 3.3开始; CONFIG_CGROUP_NET_PRIO)
              这样就可以为每个网络接口指定优先级,
              对于cgroups。

              可以在内核源文件中找到更多信息。
              Documentation / cgroup-v1 / net_prio.txthugetlb(从Linux 3.5开始; CONFIG_CGROUP_HUGETLB)
              这支持限制cgroup使用大页面。

              可以在内核源文件中找到更多信息。
              Documentation / cgroup-v1 / hugetlb.txtpids(从Linux 4.3开始; CONFIG_CGROUP_PIDS)
              该控制器允许限制处理数量
              可以在cgroup(及其后代)中创建。

              可以在内核源文件中找到更多信息。
              Documentation / cgroup-v1 / pids.txtrdma(从Linux 4.11开始; CONFIG_CGROUP_RDMA)
              RDMA控制器允许限制RDMA / IB-spe-的使用
              每个cgroup的重要资源。

              可以在内核源文件中找到更多信息。
              Documentation / cgroup-v1 / rdma.txt创建cgroup和移动进程
       一个cgroup文件系统最初包含一个根cgroup,“ /”,
       所有进程都属于哪个 通过创建一个新的cgroup
       cgroup文件系统中的目录:

           mkdir / sys / fs / cgroup / cpu / cg1

       这将创建一个新的空cgroup。

       通过将其PID写入进程,可以将进程移至该cgroup。
       cgroup的cgroup.procs文件:

           回声$$> /sys/fs/cgroup/cpu/cg1/cgroup.procs

       一次只能将一个PID写入该文件。

       将值0 写入cgroup.procs文件会导致写入过程
       移到相应的cgroup。

       将PID写入cgroup.procs时,进程中的所有线程
       立即移到新的cgroup中。

       在层次结构中,一个进程可以恰好是一个cgroup的成员。
       将进程的PID写入cgroup.procs文件会自动删除
       它来自以前是其成员的cgroup。

       该cgroup.procs文件可以被阅读,以便获取进程的列表
       是cgroup的成员。返回的PID列表不安全
       事前要有条理。也不能保证没有重复
       牛。(例如,当从
       清单。)

       在cgroups v1中,可以通过以下方式将单个线程移至另一个cgroup:
       写入其线程ID(即,由返回的内核线程ID
       clone(2)和gettid(2))到cgroup目录中的任务文件。
       可以读取此文件以发现属于成员的线程集
       cgroup的

   删除cgroup
       要删除cgroup,它必须首先没有子cgroup并且包含
       没有(非僵尸)进程。只要是这种情况,就可以
       删除相应的目录路径名。请注意
       cgroup目录不能也不需要删除。

   Cgroups v1发布通知
       可以使用两个文件来确定内核是否提供通知。
       cgroup变空时发生故障。一个cgroup被认为是
       当它不包含子cgroup和成员进程时为空。

       每个cgroup层次结构的根目录中的一个特殊文件,
       release_agent,可用于注册程序的路径名
       当层次结构中的cgroup变为空时可以调用。的
       新的空cgroup的路径名(相对于cgroup安装
       点)作为唯一的命令行参数,当
       release_agent程序被调用。该release_agent程序可能
       删除cgroup目录,或者用一个进程重新填充它。
release_agent文件
       的默认值为空,表示没有
       释放代理被调用。
也可以通过以下方式指定release_agent文件
       的内容:
       挂载cgroup文件系统时的挂载选项:

           安装-o release_agent =路径名...

       无论是否release_agent程序被调用时,一个特定的
       cgroup变为空是由
       相应cgroup目录中的notify_on_release文件。如果
       该文件包含值0,则release_agent程序不是
       调用。如果包含值1,则release_agent程序为
       调用。根cgroup中此文件的默认值为0。
       在创建新的cgroup时,此文件中的值为
       从父cgroup中的相应文件继承。

   Cgroup v1命名层次结构
       在cgroups v1中,可以挂载一个没有
       连接的控制器:

           mount -t cgroup -o none,name = somename none / some / mount / point

       可以安装此类层次结构的多个实例。每个层次
       必须具有唯一的名称。这种层次结构的唯一目的是
       跟踪流程。(请参阅下面的发布通知讨论。)
       这样的一个示例是使用的name = systemd cgroup层次结构
       通过systemd(1)来跟踪服务和用户会话。

       从Linux 5.0开始,cgroup_no_v1内核引导选项(已描述
       如下所示)可用于通过指定方式禁用名为cgroup v1的层次结构
       fying cgroup_no_v1 =命名

CGROUPS版本2         顶部

       在cgroups v2中,所有安装的控制器都驻留在一个统一的控制器中
       层次结构。虽然(不同的)控制器可以同时
       安装在v1和v2层次结构下,则无法安装
       在v1和v2下同时使用同一控制器
       层次结构。

       下面总结了cgroups v2中的新行为。
       以下小节中将详细阐述这些案例。

       1. Cgroups v2提供了一个统一的层次结构,所有
          控制器已安装。

       2.不允许“内部”过程。除了
          根cgroup,进程只能驻留在叶节点(
          本身不包含子cgroup)。详细是
          比这更微妙的,将在下面进行描述。

       3.必须通过文件cgroup.controllerscgroup.subtree_control指定活动的cgroup 。

       4. 任务文件已被删除。此外,
           cgroup.clone_children由所使用的文件cpuset
          控制器已被删除。

       5.通知空cgroup的一种改进机制是
          由cgroup.events文件提供。

       有关更多更改,请参阅以下文档中的Documentation / cgroup-v2.txt文件:
       内核源代码。

       上面列出的一些新行为进行了后续修改
       在Linux 4.14中增加了“线程模式”(如下所述)。

   Cgroups v2统一层次结构
       在cgroups v1中,可以挂载不同控制器的功能
       不同的层次结构旨在为
       应用程序设计。但是,实际上,灵活性
       比预期的有用,并且在许多情况下增加了复杂性。
       因此,在cgroups v2中,将安装所有可用的控制器。
       针对单个层次结构。可用的控制器是
       自动安装,这意味着没有必要(或可能)
       在挂载cgroup v2文件系统时指定控制器
       使用如下命令:

           挂载-t cgroup2无/ mnt / cgroup2

       仅当cgroup v2控制器不在当前位置时才可用
       通过针对cgroup v1层次结构的安装使用。或者,放东西
       换句话说,不可能采用相同的控制器
       v1层次结构和统一的v2层次结构。这意味着
       可能首先需要卸载v1控制器(如前所述)
       以上)在v2中可用该控制器之前。由于systemd(1)
       默认情况下大量使用某些v1控制器,在某些情况下
       使用选定的v1控制器启动系统的情况更简单
       能够。为此,请在ker‐上指定cgroup_no_v1 = list选项。
       nel boot命令行;list是逗号分隔的名称列表
       控制器以禁用,或单词all禁用所有v1 con-
       拖钓者。(这种情况已由systemd(1)正确处理,
       在没有指定控制器的情况下恢复运行。)

       请注意,在许多现代系统上,在引导过程中,systemd(1)会自动将
        cgroup2文件系统挂载在/ sys / fs / cgroup / unified上Cgroups v2挂载选项挂载Cgroups v2时,可以指定以下选项(mount -o)
       组v2文件系统:

       nsdelegate(从Linux 4.15开始)
              将cgroup名称空间视为委托边界。对于
              详细信息,请参见下文。

       memory_localevents(从Linux 5.2开始)
              该memory.events应该显示的统计数据只针对该cgroup
              本身,而不适用于任何后代cgroup。这是
              Linux 5.2之前的行为。从Linux 5.2开始,默认
              行为是要包括以下方面的统计信息:
              memory.events,此安装选项可用于还原为
              传统行为。此选项是系统范围的,可以
              设置为挂载或仅从初始开始通过重新挂载进行修改
              挂载命名空间;它在非初始名称中被静默忽略-
              步伐。

   的cgroup v2的控制器 
       下面控制器,内核源文件中记录Docu- 
       心理状态/ cgroup中-v2.txt,在cgroup中版本2的支持:

       cpu(自Linux 4.15起)
              这是后继版本1 的CPUcpuacct CON组
              拖钓者。

       cpuset(从Linux 5.0开始)
              这是版本1 cpuset控制器的后继产品。

       冷冻机(自Linux 5.2起)
              这是版本1 冷冻机控制器的后继产品。

       hugetlb(自Linux 5.6起)
              这是版本1 Hugetlb控制器的后继产品。

       io(从Linux 4.5开始)
              这是版本1 blkio控制器的后继产品。

       内存(自Linux 4.5起)
              这是版本1 内存控制器的后继产品。

       perf_event(从Linux 4.11开始)
              这与版本1 perf_event控制器相同。

       pids(从Linux 4.5开始)
              这与版本1 pids控制器相同。

       rdma(从Linux 4.11开始)
              这与版本1 rdma控制器相同。

       没有直接等效的net_clsnet_prio控制器
       从cgroups版本1开始。相反,已将支持添加到
       iptables(8)允许挂钩在cgroup v2路径名上的eBPF过滤器
       根据每个cgroup决定网络流量。

       v2 设备控制器不提供接口文件。代替,
       通过连接eBPF(BPF_CGROUP_DEVICE)pro 门来控制设备控制
       克到v2 cgroup。

   Cgroups v2子树控件
       v2层次结构中的每个cgroup包含以下两个文件:

       cgroup.controllers
              此只读文件公开了以下控制器的列表:
              在此cgroup中可用。该文件的内容与父级中cgroup.subtree_control文件的
              内容
              cgroup。

       cgroup.subtree_control 
              这是控制器中处于活动状态启用)的控制器的列表。
              cgroup。此文件中的控制器集是以下内容的子集此cgroup 
              的cgroup.controllers中的集合。一套
              通过将字符串写入此文件来修改活动控制器
              包含以空格分隔的控制器名称,每个名称前都有
              “ +”(启用控制器)或“-”(禁用控制器),
              如以下示例所示:

                  回声'+ pids -memory'> x / y / cgroup.subtree_control

              尝试启用不存在的控制器
              写入时,cgroup.controllers导致ENOENT错误
              该cgroup.subtree_control文件。

       因为cgroup.subtree_control中的控制器列表是一个子集
       这些cgroup.controllers中的一个,已在
       层次结构中的一个cgroup永远不能在子树中重新启用
       低于该cgroup。

       cgroup的cgroup.subtree_control文件确定con-的集合
       在 cgroup 中行使的拖钓者。当控制器
       (例如pids)存在于par-的cgroup.subtree_control文件中
       ent cgroup,然后输入相应的控制器接口文件(例如,
       pids.max)是在该cgroup的子级中自动创建的
       并且可用于在子cgroup中施加资源控制。

   Cgroups v2“没有内部流程”规则
       Cgroups v2强制执行所谓的“无内部流程”规则。
       粗略地说,这条规则意味着,除了
       根cgroup,进程只能驻留在叶节点(
       本身不包含子cgroup)。这样就避免了
       决定如何在属于成员的进程之间分配资源
       cgroup A的过程和A的子cgroup中的进程。

       例如,如果cgroup / cg1 / cg2存在,则进程可以驻留在/ cg1 / cg2中,但不能驻留
        在/ cg1中。这是为了避免cgroups中的歧义
       v1关于流程之间的资源委派
       / cg1及其子cgroup。cgroups v2中推荐的方法
       是为任何非叶子 cgroup 创建一个名为leaf的子目录,
       应该包含进程,但不能包含子cgroup。因此,流程
       以前本来应该进入/ cg1的内容,现在应该进入
        / cg1 / leaf。这具有使关系明确的优点-
       在/ cg1 / leaf/ cg1的其他子进程之间传送。

       实际上,“没有内部流程”规则比规定的要微妙得多
       以上。更确切地说,规则是(非根)cgroup不能
       两者(1)具有成员流程,并且(2)将资源分配到
       子cgroup-即具有一个非空的cgroup.subtree_control文件。
       因此,它可能的cgroup中同时具有构件的过程和
       子cgroup,但在可以为该cgroup启用控制器之前,
       成员进程必须移出cgroup(例如,也许
       进入子cgroup)。

       在Linux 4.14中增加了“线程模式”(如下所述)后,
       在某些情况下,“无内部流程”规则已经放宽。

   Cgroups v2 cgroup.events文件
       v2层次结构中的每个非根cgroup都包含一个只读文件,
       cgroup.events,其内容为键值对(以new-分隔
       行字符,键和值之间用空格隔开)provid-
       有关cgroup的状态信息:

           $ cat mygrp / cgroup.events
           填充1
           冻结的0

       以下密钥可能会出现在此文件中:

       填充
              如果此cgroup或以下任意一项,则此键的值为1
              它的后代具有成员进程,否则为0。

       冻结的(自Linux 5.2起)
              如果此cgroup当前处于冻结状态,则此密钥的值为1,
              否则为0。

       该cgroup.events文件可以被监控,以便接收notifi-
       当其键之一的值更改时出现阳离子。这样的监控
       可以用做inotify的(7) ,该通知改变为IN_MODIFY 
       事件或轮询(2) ,通过返回其通知变化POLLPRIPOLLERR位在revents中字段。

   Cgroup v2发布通知
       Cgroups v2提供了一种新的机制,可以在以下情况下获取通知:
       cgroup变为空。V1中的cgroup release_agentnotify_on_release文件将被删除,并通过更换填充 
       在关键cgroup.events文件。该密钥的值为0,
       表示cgroup(及其后代)不包含(非僵尸)
       成员进程,或1,表示cgroup(或其其中之一)
       后代)包含成员进程。

       cgroups v2发行通知机制提供以下内容
       与cgroups v1 release_agent机制相比的优势:

       *它允许更便宜的通知,因为单个过程可以
          监视多个cgroup.events文件(使用该技术
          如前所述)。相比之下,cgroups v1机制
          需要花费为每个通知创建流程的费用。

       *可以委派不同cgroup子层次结构的通知
          到不同的过程。相比之下,cgroups v1机制
          整个层次结构仅允许一个发布代理。

   Cgroups v2 cgroup.stat文件 
       v2层次结构中的每个cgroup都包含一个只读cgroup.stat文件
       (在Linux 4.14中首次引入),由包含以下内容的行组成
       键值对。当前在文件中显示以下密钥:

       nr_descendants
              这是可见(即活着的)后代的总数
              该cgroup下的cgroup。

       nr_dying_descendants
              这是在以下情况下垂死的后代cgroup的总数:
              在这个cgroup中。一个cgroup在进入死亡状态后
              被删除。保持该状态的时间未定义
              期间(取决于系统负载)
              在销毁cgroup之前将其释放。注意存在
              处于垂死状态的某些cgroup是正常的,不是
              指示任何问题。

              进程不能成为垂死的cgroup的成员,并且
              垂死的cgroup无法重生。

   限制后代cgroup的数量
       v2层次结构中的每个cgroup包含以下文件,这些文件
       可用于查看和设置后代数量限制
       该cgroup下的cgroup:

       cgroup.max.depth(从Linux 4.14开始)
              该文件定义了降序嵌套深度的限制
              dant cgroups。该文件中的值为0表示没有降序
              可以创建dant cgroup。尝试创建降序
              嵌套级别超出限制的dant失败(mkdir(2)
              失败,并显示错误EAGAIN)。

              将字符串“ max”写入此文件意味着没有限制
              施加。该文件的默认值为“ max”cgroup.max.descendants(从Linux 4.14开始)
              该文件定义了活后代的数量限制
              该cgroup可能具有的cgroup。尝试创造更多
              子孙超出限制所允许的数量失败(mkdir(2)失败
              错误EAGAIN)。

              将字符串“ max”写入此文件意味着没有限制
              施加。该文件的默认值为“ max”CGROUPS委派:将层次结构委托给较少的特权用户

        最佳

       在cgroup的上下文中,委派意味着通过对
       cgroup层次结构的某些子树提供给非特权用户。
       Cgroups v1提供基于文件权限的委派支持
       在cgroup层次结构中,但包含规则不如
       v2(如下所述)。Cgroups v2支持包含约束的委派
       通过明确的设计。本节中的讨论重点是
       关于在cgroups v2中的委派,对于cgroups v1有一些区别
       一路注意到。

       为了描述委派,需要一些术语。一个
       委托者是拥有父级cgroup的特权用户(即root)。
       一个代理方是谁将会被授予一个非特权用户
       在该父级下管理某些子层次结构所需的权限
       cgroup,称为委托子树。

       要执行委派,委派者创建某些目录并
       代表可写的文件,通常是通过更改所有权
       的对象作为委托者的用户ID。假设我们
       想委托植根于(例如)/ dlgt_grp的层次结构,
       该cgroup下还没有任何子cgroup,所有权
       以下内容更改为委托人的用户ID:

       / dlgt_grp
              更改子树根的所有权意味着
              在子树下创建的任何新cgroup(及其文件
              包含)也将由代表所有。

       /dlgt_grp/cgroup.procs
              更改此文件的所有权意味着委托人
              可以将进程移到委托子树的根中。

       /dlgt_grp/cgroup.subtree_control(仅限cgroups v2)
              更改此文件的所有权意味着委托人
              可以启用控制器(存在于
              /dlgt_grp/cgroup.controllers),以便进一步重新分发
              子树中较低级别的资源。(作为备选
              要更改此文件的所有权,委托者可能
              而是将选定的控制器添加到此文件中。)

       /dlgt_grp/cgroup.threads(仅限cgroups v2)
              如果有线程,则必须更改此文件的所有权
              委托子树(请参阅“线程的描述
              模式”,以下)。这允许委托人编写线程ID
              到文件。(此文件的所有权也可以更改
              委派域子树时,但目前这没有用
              目的,因为如下所述,无法移动
              通过将其线程ID写入域cgroup之间的线程
              该cgroup.threads文件。)

              在cgroups v1中,相应的文件应为
              委托的是任务文件。

       该delegater应该不会改变任何的所有权
       控制器接口文件(例如,pids.maxmemory.high)在
        dlgt_grp。这些文件是从
       委托子树以便将资源分配到子树中,
       并且代表不应该有权更改资源
       分布到委托子树中。

       另请参阅/ sys / kernel / cgroup / delegate文件中的讨论
       有关有关cgroups v2中其他可删除文件的信息的注释。

       执行上述步骤后,代表可以
       在委托子树中创建子cgroup(cgroup
       子目录及其包含的文件将归
       委托),并在子树中的cgroup之间移动进程。如果dlgt_grp / cgroup.subtree_control 
       中存在某些控制器,或者
       该文件的所有权已传递给委托人,委托人
       也可以控制相应的进一步重新分配
       资源放入委托的子树中。

   Cgroups V2委派:nsdelegate和cgroup命名空间
       从Linux 4.13开始,还有另一种执行cgroup的方法
       cgroups v2层次结构中的委派。这是通过安装或
       使用nsdelegate挂载选项重新挂载cgroup v2文件系统。
       例如,如果已经安装了cgroup v2文件系统,则我们
       可以使用nsdelegate选项将其重新挂载,如下所示:

           挂载-t cgroup2 -o重新挂载,nsdelegate \
                            无/ sys / fs / cgroup / unified

       该安装选项的作用是使cgroup名称空间
       自动成为委派界限。更具体地说,
       以下限制适用于cgroup名称中的进程
       步伐:

       *写入控制器接口文件的根目录中
          名称空间将失败,并显示错误EPERM。内部流程
          cgroup名称空间仍可以写入根目录中的可代理文件
          cgroup名称空间的目录,例如cgroup.procscgroup.subtree_control,并且可以在以下目录下创建子层次结构
          根目录。

       *尝试跨名称空间边界迁移进程
          被拒绝(错误ENOENT)。cgroup内部的进程
          命名空间仍然可以(取决于所描述的包含规则
          下面)在子层次结构的cgroup之间移动进程
          在名称空间根目录下。

       将cgroup命名空间定义为委托边界的能力
       使cgroup命名空间更有用。要了解原因,假设
       我们已经有一个cgroup层次结构已委派给
       非特权用户cecilia,使用旧的委托技术
       如上所述。进一步假设塞西莉亚想进一步消除
       在现有的委托层次结构下划分一个子层次结构。(对于
       例如,委派的层次结构可能与非特权cecilia 
       运行的有条件的容器。)即使cgroup命名空间是
       之所以使用,是因为这两个层次结构均由非特权用户拥有
       塞西莉亚,可以执行以下非法操作:

       *较低层级中的流程可能会更改资源配置
          该层次结构的根目录中的Troller设置。(这些
          资源控制器设置旨在允许进行控制
          从上级 cgroup 行使;孩子内心的过程
          cgroup不允许修改它们。)

       *下级层次结构中的流程可能会将流程移入
          如果上级的cgroups不在下级中
          层次结构以某种方式可见。

       使用nsdelegate挂载选项可以防止这两种情况
       能力。

       该nsdelegate在执行时安装选项只有一个效果
       初始安装名称空间;在其他安装名称空间中,该选项是
       默默无视。

       注意:在某些系统上,systemd(1)自动挂载cgroup v2
       文件系统。为了试验nsdelegate操作,它
       使用以下命令行启动内核可能会很有用
       选项:

           cgroup_no_v1 =所有systemd.legacy_systemd_cgroup_controller

       这些选项导致内核使用cgroups v1 con-引导。
       拖曳器已禁用(这意味着控制器在
       v2层次结构),并告诉systemd(1)不要安装和使用cgroup
       v2层次结构,以便可以手动安装v2层次结构
       启动后所需的选项。

   Cgroup委派遏制规则 
       一些委派遏制规则可确保代表可以移动
       委托子树中cgroup之间的进程,但不能
       将过程从委托子树的外部移到子树中,或者
       反之亦然。非特权进程(即,委托人)可以编写
       仅在以下情况下,“目标”进程的PID 才进入cgroup.procs文件:
       以下是正确的:

       *作者具有对cgroup.procs文件中的写权限。
          目标cgroup。

       *作者具有对cgroup.procs文件中的写权限。
          源和目标cgroup的最接近的共同祖先。
          请注意,在某些情况下,最接近的共同祖先可能是
          源或目标cgroup本身。这个要求不是
          对cgroups v1层次结构强制执行,结果是
          v1中的限制不如v2中严格。(例如,在
          cgroups v1拥有两个不同的委托子级别的用户
          chies可以在层次结构之间移动流程。)

       *如果使用nsdelegate挂载了cgroup v2文件系统
          选项,编写者必须能够查看源和目标
          cgroup名称空间中的cgroups。

       *在cgroups v1中:编写者的有效UID(即delega-
          tee)匹配tar的真实用户ID或保存的set-user-ID
          得到过程。在Linux 4.11之前,此要求也适用于
          cgroups v2(这是继承自
          cgroups v1,后来被认为是不必要的,因为另一个
          规则足以将其包含在cgroups v2中。)

       注意:这些委派遏制规则的后果之一是:
       无特权的代表不能将第一个过程放入
       委托子树 相反,委托人必须将第一个
       流程(委托人拥有的流程)进入委托子流程
       树。

CGROUPS版本2螺纹模式         top

       在cgroups v2施加的限制中不存在
       cgroups v1如下:

       *   没有线程粒度控制:进程的所有线程
          必须在同一cgroup中。

       *   没有内部进程:cgroup不能都具有成员进程
          在子cgroup上行使控制权。

       由于缺少这些限制,因此添加了这两个限制
       限制已导致cgroups v1中的问题。特别是
       cgroups v1允许cgroup线程级粒度的能力
       对于某些控制器,成员资格没有任何意义。(一个明显的例子
       是内存控制器:由于线程共享一个地址空间,因此它
       在不同的内存 cgroup中拆分线程是没有意义的。)

       尽管cgroups v2中有最初的设计决策,但仍有
       某些控制器(尤其是cpu控制器)的用例用于
       哪种线程级控制粒度是有意义和有用的。
       为了适应这样的使用情况下,Linux的4.14增加线程模式为
       cgroups v2。

       线程模式允许以下操作:

       *创建线程子树,其中一个线程
          进程可能分散在树内的cgroup中。(一个线程
          子树可能包含多个多线程进程。)

       * 可以分布的线程控制器的概念
          线程子树中cgroup上的资源。

       *放宽“无内部流程规则”,以便在
          一个线程子树,一个cgroup既可以包含成员线程,又可以包含
          对子cgroup进行资源控制。

       添加了线程模式后,每个非根cgroup现在都包含一个公开的
       新文件cgroup.type,在某些情况下可以是
       用于更改cgroup的“类型”。此文件包含以下内容之一
       以下类型值:

       这是一个正常的v2 cgroup,可提供过程粒度
              控制。如果某个进程是该cgroup的成员,则所有
              进程的线程(根据定义)在同一cgroup中。
              这是默认的cgroup类型,并提供相同的
              为初始cgroup中的cgroup提供的行为
              v2实施。

       螺纹的
              此cgroup是线程子树的成员。线程可以是
              添加到此cgroup中,并且可以为
              cgroup。

       域线程化
              这是一个域cgroup,用作线程的根
              子树。这种cgroup类型也称为“线程根”。

       域无效
              这是线程子树中的一个cgroup
              “无效”状态。进程无法添加到cgroup,并且
              无法为cgroup启用控制器。唯一的事情
              可以使用此cgroup进行操作(而不是删除它)是
              将其转换为一个线程写入字符串cgroup的
               “线程”cgroup.type文件。

              在此期间,这种“临时”类型存在的理由
              创建线程子树(而不是内核)
              只需立即在线程下转换所有cgroup线程 
              类型的根)是为了将来可能
              线程模式模型的扩展

   线程与域控制器
       通过添加线程模式,cgroups v2现在可以区分两个
       资源控制器的类型:

       *   线程控制器:这些控制器支持线程粒度
          用于资源控制,并且可以在线程子树中启用,
          结果是相应的控制器接口文件
          出现在线程子树的cgroup中。截至Linux
          在4.19中,以下控制器是线程化的:cpuperf_eventpids。

       *   控制器:这些控制器仅支持进程
          资源控制的粒度。从一个角度
          域控制器,一个进程的所有线程总是在同一个
          cgroup。无法在线程内部启用域控制器
          子树。

   创建一个线程子树
       有两种途径可导致创建线程
       子树。第一条途径如下:

       1.我们将字符串“ threaded”写入当前具有类型cgroup y / zcgroup.type文件
           。这具有以下
          效果:

          * cgroup y / z的类型变为线程化。

          *父cgroup的类型y成为域线程。的
             父cgroup是线程子树的根(也称为
             “线程根”)。

          * y下的所有其他cgroup 尚未被
              线程化(因为它们在已经存在的线程内)
             新线程根目录下的子树)转换为type
             域无效。随后在y下创建的cgroup 将
             也有类型域无效。

       2.我们将字符串“ threaded”写入y 
          下的每个域无效 cgroup ,以便将它们转换为threaded类型。
          作为此步骤的结果,线程根下的所有线程
          现在具有线程类型,并且线程子树现在已完全
          可用的。要求为每个线程“线程化”
          cgroups有点麻烦,但可以考虑将来的发展
          线程模式模型的扩展。

       创建线程子树的第二种方法如下:

       1.在现有的cgroup z中,当前的cgroup 类型为domain,我们
          (1)启用一个或多个线程控制器,以及(2)进行处理z 
          的成员。(这两个步骤可以按任何顺序完成。)
          这具有以下后果:

          * z的类型成为域线程。

          *所有的后裔cgroup中的X是不是已经是
             类型线程转换为类型域无效。

       2.和以前一样,我们通过编写
          字符串“线程化”y下每个域无效的 cgroup ,
          为了将它们转换为threaded类型。

       以上创建线程的途径的后果之一
       子树是线程根cgroup只能是父节点
       线程化(且域无效)的cgroup。线程根cgroup
       不能是 cgroup 的父级,而线程化 cgroup不能
       有一个 cgroup 的兄弟姐妹。

   使用线程子树
       在线程子树中,可以在以下位置启用线程控制器
       每个类型更改为线程的子组; 这样做后
       相应的控制器接口文件出现在子级中
       该cgroup的。

       通过将进程的PID写入以下内容,可以将其移动到线程子树中:树内cgroup之一中
       的cgroup.procs文件。这个
       具有使所有线程成为该进程的成员的作用
       相应的cgroup并使该进程成为
       线程子树。然后可以传播进程的线程
       通过写入线程子树的线程ID来遍历线程子树(请参阅
       gettid(2))到内部不同cgroup中的cgroup.threads文件
       子树。进程的线程必须全部驻留在同一线程中
       线程子树。

       与写入cgroup.procs一样,某些包含规则在以下情况下适用
       写入cgroup.threads文件:

       *作者必须对cgroup.threads文件具有写权限
          在目标cgroup中。

       *作者必须对以下位置的cgroup.procs文件具有写许可权:
          源和目标cgroup的共同祖先。(在
          在某些情况下,共同祖先可能是来源或目的地
          cgroup本身。)

       *源cgroup和目标cgroup必须在同一线程中
          子树。(在线程子树之外,尝试移动线程
          通过将其线程ID写入另一个 cgroup中的cgroup.threads文件
           失败,错误为EOPNOTSUPP。)

       该cgroup.threads文件存在于每个cgroup中(包括
       cgroups)并可以读取以发现线程组
       在cgroup中。在以下情况下获得的一组线程ID
       不保证阅读此文件是有序的或免费的
       重复。

       该cgroup.procs在螺纹根文件显示所有的PID
       线程子树成员的进程。该cgroup.procs
       子树中其他cgroup中的文件不可读。

       无法在线程子树中启用域控制器。没有
       控制器接口文件显示在
       螺纹根。从域控制器的角度来看,
       线程子树是不可见的:内部的一个多线程进程
       线程子树在域控制器中显示为一个进程,
       驻留在线程根cgroup中。

       在线程子树中,“无内部进程”规则不
       适用:一个cgroup可以同时包含成员进程(或线程)和
       在儿童cgroup上行使控制权。

   写入cgroup.type和创建线程子树 
       的规则写入cgroup.type文件时,有许多规则适用:

       *只能写入字符串“ threaded”。换句话说,
          唯一可能的显式转换是将 
          cgroup 转换为threaded类型。

       *编写“线程”的效果取决于cgroup.type中的当前值
           ,如下所示:

          ·   域线程化:开始创建线程
             通过第一个子树(其根是此cgroup的父树)
             上述途径;

          ·   域无效:转换此cgroup(位于线程内部)
             子树)到可用(即线程化)状态;

          ·   线程化:无效(“无操作”)。

       * 如果父级的类型是domain invalid,则无法写入cgroup.type文件
           。换句话说,线程子树的cgroup
          必须以自顶向下的方式转换为线程状态。

       为了满足以下条件,还必须满足一些约束条件:
       创建一个以cgroup x为根的线程子树:

       * x的后代cgroup中没有成员进程。
          (cgroup x本身可以具有成员进程。)

       *不能在xcgroup.subtree_control中启用域控制器
          文件。

       如果违反了上述任何约束,则尝试写
       “线程化”cgroup.type文件失败,并显示错误ENOTSUP“域线程化” cgroup类型
       根据上述途径,cgroup的类型可以在以下两种情况下,请
       更改为域线程:

       *字符串“ threaded”被写入子cgroup。

       *在cgroup和进程内部启用了线程控制器
          成为cgroup的成员。

       如果域线程 cgroup x可以恢复为类型,
       上述条件不再成立-也就是说,如果所有线程子代x的 
       cgroup 被删除,并且x不再具有线程关系
       控制器已启用或不再具有成员进程。

       当域线程化的 cgroup x恢复为类型domain时:

       * x的所有域无效后代不在较低级别
          线程化的子树还原为类型domain。

       *任何较低级别的线程子树中的根cgroup都还原为
          类型域线程化根cgroup的例外
       v2层次结构的根cgroup受到特殊对待:它可以
       是线程 cgroup 的父级。如果将字符串
        “ threaded”写入项之一的cgroup.type文件中
       根cgroup的

       *该cgroup的类型变为线程化。

       *不属于该cgroup的任何后代的类型
          低级线程子树更改为域invalid。

       请注意,在这种情况下,没有cgroup的类型变为domain 
       threaded。(通常,根cgroup可被视为
       类型更改为threaded的cgroup的线程根。)

       对根cgroup的这种特殊处理的目的是允许
       使用cpu控制器的线程cgroup 放置为
       在层次结构中尽可能地高,以最小化(小)成本
       遍历cgroup层次结构的过程。

   cgroups v2“ cpu”控制器和实时线程 
       从Linux 4.19开始,cgroups v2 cpu控制器不支持
       控制实时线程(特别是在任何
       政策的SCHED_FIFOSCHED_RR,描述SCHED_DEADLINE ; 参见
        sched(7))。因此,可以在根目录中启用cpu控制器
       仅当所有实时线程都在根cgroup中时,才使用cgroup。(如果
       有实时线程在非根的cgroup,则写(2)的
       字符串“ + cpu”cgroup.subtree_control文件失败,并显示错误
        EINVAL。)

       在某些系统上,systemd(1)将某些实时线程放置在
       v2层次结构中的非根cgroup。在此类系统上,这些线程
       必须先将其移至根cgroup,然后才能使用cpu控制器
       被启用。

错误         顶部

mount(2)        可能发生以下错误:

       EBUSY  尝试挂载指定的cgroup版本1文件系统
              无论是名称=选项(安装一个名为层次),也不是
              控制器名称(或全部)。

笔记         顶部

       通过fork(2)创建的子进程继承其父级的cgroup
       会员资格。进程的cgroup成员资格保留在
       execve(2)。

       该clone3(2) CLONE_INTO_CGROUP标志可用于创建一个子
       进程开始于与版本2 cgroup不同的版本
       父进程。

   / proc文件
       / proc / cgroups(从Linux 2.6.24开始)
              该文件包含有关以下控制器的信息:
              编译到内核中。这个内容的一个例子
              文件(经过重新格式化以提高可读性)如下:

                  #subsys_name层次结构num_cgroups已启用
                  cpuset 4 1 1
                  CPU 8 1 1
                  cpuacct 8 1 1
                  blkio 6 1 1
                  内存3 1 1
                  设备10 84 1
                  冷冻柜7 1 1
                  net_cls 9 1 1
                  perf_event 5 1 1
                  net_prio 9 1 1
                  巨大的磅0 1 0
                  pids 2 1 1

              该文件中的字段从左到右为:

              1.控制器的名称。

              2.此操作所在的cgroup层次结构的唯一ID
                 拖钓器已安装。如果有多个cgroup v1控制器
                 绑定到相同的层次结构,那么每个将显示相同
                 此字段中的层次结构ID。该字段中的值将
                 如果为0,则为0

                   a)控制器未安装在cgroups v1层级上
                      chy

                   b)控制器绑定到cgroups v2单个uni-
                      严格的等级制度;要么

                   c)控制器被禁用(见下文)。

              3.在此层次结构中使用此控件的控件组数
                 控制器。

              4.如果此控制器是,则此字段包含值1。
                 启用,或者0,如果它已被禁用(通过cgroup_dis- 
                 能够内核命令行启动参数)。

       / proc / [pid] / cgroup(从Linux 2.6.24开始)
              该文件描述了处理过程所涉及的控制组
              相应的PID属于。显示的信息不同
              cgroups版本1和版本2层次结构的fers。

              对于该进程所属的每个cgroup层次结构,
              有一个条目包含三个冒号分隔的字段:

                  层次结构ID:控制器列表:cgroup-path

              例如:

                  5:cpuacct,cpu,cpuset:/守护程序

              冒号分隔的字段是从左到右:

              1.对于cgroups版本1层次结构,此字段包含一个
                 可以与层级匹配的唯一层次结构ID号
                 chy ID在/ proc / cgroups中。对于cgroups 2 hierar‐
                 chy,此字段包含值0。

              2.对于cgroups版本1层次结构,此字段包含一个
                 以逗号分隔的绑定到层次结构的控制器列表
                 拱形。对于cgroups版本2层次结构,此字段为
                 空的。

              3.此字段包含以下位置的控制组的路径名
                 进程所属的层次结构。这个路径名
                 相对于层次结构的安装点。

   / sys / kernel / cgroup文件
       / sys / kernel / cgroup / delegate(从Linux 4.15开始)
              此文件导出cgroups v2文件的列表(每个
              可转让的(即其所有权应为
              更改为代表的用户ID)。将来,
              可代理文件集可能会更改或增长,并且此文件
              为内核提供了一种通知用户空间应用程序的方法
              必须委派哪些文件。在Linux 4.15上,
              检查此文件时看到以下内容:

                  $ cat / sys / kernel / cgroup / delegate
                  cgroup.procs
                  cgroup.subtree_control
                  cgroup.threads

       / sys / kernel / cgroup / features(从Linux 4.15开始)
              随着时间的流逝,由以下人员提供的一组cgroups v2功能
              内核可能会更改或增长,或者某些功能可能无法更改
              默认情况下启用。该文件为用户空间提供了一种方法
              应用程序以发现正在运行的内核具有哪些功能
              端口并已启用。每行列出一项功能:

                  $ cat / sys / kernel / cgroup / features
                  nsdelegate
                  memory_localevents

              可以显示在此文件中的条目是:

              memory_localevents(从Linux 5.2开始)
                     内核支持memory_localevents挂载
                     选项。

              nsdelegate(从Linux 4.15开始)
                     内核支持nsdelegate挂载选项。

另请参阅         顶部

       prlimit(1),systemd(1),systemd-cgls(1),systemd-cgtop(1),clone(2),
        ioprio_set(2),perf_event_open(2),setrlimit(2),
        cgroup_namespaces(7),cpuset (7),namespaces(7),sched(7),
        user_namespaces(7)

       内核源文件Documentation / admin-guide / cgroup-v2.rst

COLOPHON         上衣

       该页面是Linux 手册页项目5.07版一部分。一个
       项目说明,有关报告错误的信息以及
       该页面的最新版本,可以在以下位置找到
       https://www.kernel.org/doc/man-pages/。

Linux 2020年4月11日CGROUPS(7)

你可能感兴趣的:(虚拟化技术,操作系统)