当前位置: 首页 > news >正文

网站后台和移动开发越南做网站服务器

网站后台和移动开发,越南做网站服务器,学习电子商务网站建设与管理的收获6,网站运营论文文章目录 Cgroup(Control Group)引言简介Cgroup v1通用接口文件blkio子系统cpu子系统cpuacct子系统cpuset子系统devices子系统freezer子系统hugetlb子系统memory子系统net_cls子系统net_prio子系统perf_event子系统pids子系统misc子系统 Cgroup V2基础操作组织进程和线程popula… 文章目录 Cgroup(Control Group)引言简介Cgroup v1通用接口文件blkio子系统cpu子系统cpuacct子系统cpuset子系统devices子系统freezer子系统hugetlb子系统memory子系统net_cls子系统net_prio子系统perf_event子系统pids子系统misc子系统 Cgroup V2基础操作组织进程和线程populated 通知cgroup.controllers 委派指南资源分配模型约定已弃用的 v1 核心功能核心接口文件cgroup.typecgroup.procscgroup.threadscgroup.controllerscgroup.subtree_controlcgroup.eventcgroup.max.descendantscgroup.max.deepcgroup.statcgroup.freezecgroup.killcgroup.pressureirq.pressure 控制器接口文件CPUmemoryIOPIDcpusetdevicehugetlbMISC 术语CPUNUMA架构 内存Page CacheSlabswap 内存回收磁盘SCSI硬盘设备块设备 文件系统tmpfs 网络QoS简介队列规则pfifoHTB(Hierarchical Token Bucket)使用 设备misc设备RDMA 内核配置 Cgroup(Control Group) 引言 tst-cgroup是用来测试cgroup v1/v2大部分接口文件的测试套用shell编写共有118个测试用例涵盖了CPU/内存/IO/网络/进程功能的接口文件测试可以用来了解cgroup v1/v2大部分接口文件的基础用法。 参考 Control Groups version 1 — The Linux Kernel documentationControl Group v2 — The Linux Kernel documentationlinux/tools/testing/selftests/cgroup at master · torvalds/linux[译] Control Group v2cgroupv2 权威指南KernelDoc, 2021第 3 章 子系统和可调参数 | Red Hat Product Documentationcgroup 子系统之 net_cls 和 net_prio | ggaaooppeenngg 简介 概述 Cgroups允许限制、优先处理、隔离和监控系统资源如CPU、内存、磁盘I/O、网络带宽等在进程或进程组之间的使用。这对于多租户环境、资源隔离和容器技术尤为重要是linux内核自带的工具。 cgroup v1/v2 cgroup有两个版本 cgroup v1 使用的是层级式结构将子系统接口文件分开放在单独的目录进程可能会在不同的子系统中参与不同的资源管理。 cgroup v2 设计上更加简化和统一所有的核心和控制器接口文件共享同一个目录 实例对比 Cgroup V1示例 # 创建CPU和内存控制组 mkdir /sys/fs/cgroup/cpu/my_cgroup mkdir /sys/fs/cgroup/memory/my_cgroup# 设置CPU和内存限制 echo 50000 /sys/fs/cgroup/cpu/my_cgroup/cpu.cfs_quota_us echo 100M /sys/fs/cgroup/memory/my_cgroup/memory.limit_in_bytes# 将进程添加到控制组 echo PID /sys/fs/cgroup/cpu/my_cgroup/tasks echo PID /sys/fs/cgroup/memory/my_cgroup/tasks Cgroup V2示例 # 挂载Cgroup v2 mount -t cgroup2 none /sys/fs/cgroup/unified# 创建控制组 mkdir /sys/fs/cgroup/unified/my_cgroup# 设置CPU和内存限制 echo 50000 /sys/fs/cgroup/unified/my_cgroup/cpu.max echo 100M /sys/fs/cgroup/unified/my_cgroup/memory.max# 将进程添加到控制组 echo PID /sys/fs/cgroup/unified/my_cgroup/cgroup.procsCgroup V2在设计上更加简洁和统一提供了更一致的资源控制和监控接口。 如何切换cgroup版本 切换到cgroup v1在/etc/default/grub的GRUB_CMDLINE_LINUX添加systemd.unified_cgroup_hierarchy0切换到cgroup v1在/etc/default/grub的GRUB_CMDLINE_LINUX添加systemd.unified_cgroup_hierarchy1 然后更新配置 sudo update-grab # ubuntu22 sudo grub2-mkconfig -o /boot/grub2/grub.cfg # opencloudos 8.8/9.2/Stream 23最后重启系统即可 rebootCgroup v1 通用接口文件 tasks 包含一系列在cgroup中运行的进程由它们的PID表示。PID列表不一定是有序的也不一定是特有的。将PID写入一个cgroup的tasks文件可将此进程移动至cgroup 跟下面的cgroup.procs功能一样cgroup v2取消了这个接口文件只保留了cgroup.procs cgroup.procs 包含在cgroup中运行的进程组列表由它们的TGID表示。TGID列表不一定有序的也不一定是特有的。将TGID写入cgroup的cgroup.procs文件可将此线程组群移至该cgroup cgroup.event_control 与cgroup的通知API一起允许cgroup的变更状态通知被发送 notify_on_release 包含Boolean值1或者0分别可以启动和禁用释放代理的指令。如果notify_on_release启用当cgroup不再包含任何任务时即cgroup的tasks文件包含PID而PID被移除致使文件变空kernel会执行release_agent文件的内容。通向此空cgroup的路径会作为release_agent的参数被提供。notify_on_realease参数的默认值在root cgroup中是0。所有非root cgroup从其父cgroup处继承notify_on_realese的值 release_agent仅在root cgroup中出现 当notify on realeas被触发它包含要执行的指令。一旦cgroup的所有进程被清空并且notify_on_realease标记被启用kernel会运行release_agent文件中的指令并且提供通向被清空cgroup的相关路径与root cgroup相关作为参数。例如可以用来自动移除空cgroup 自动移除空cgroup的例子可将空cgroup从cpu cgroup中自动移除 创建一个shell脚本用来移除空cpu cgroups, 将其放入/usr/local/bin并使其可运行 cat /usr/local/bin/remove-empty-cpu-cgroup.sh output: #!/bin/sh # $1变量包含到达已清空cgroup的相对路径 rmdir /cgroup/cpu/$1 chmod x /usr/local/bin/remove-empty-cpu-cgroup.sh在cpu cgroup启动notify_on_release标签 echo 1 notify_on_release在cpu cgroup中指定一个可用的释放代理 echo /usr/local/bin/remove-empty-cpu-cgroup.sh /cgroup/cpu/release_agent测试配置 cpu]# pwd; ls /cgroup/cpu cgroup.event_control cgroup.procs cpu.cfs_period_us cpu.cfs_quota_us cpu.rt_period_us cpu.rt_runtime_us cpu.shares cpu.stat libvirt notify_on_release release_agent tasks cpu]# cat notify_on_release 1 cpu]# cat release_agent /usr/local/bin/remove-empty-cpu-cgroup.sh cpu]# mkdir blue; ls blue cgroup.event_control cgroup.procs cpu.cfs_period_us cpu.cfs_quota_us cpu.rt_period_us cpu.rt_runtime_us cpu.shares cpu.stat libvirt notify_on_release release_agent tasks cpu]# cat blue/notify_on_release 1 cpu]# cgexec -g cpu:blue dd if/dev/zero of/dev/null bs1024k [1] 8623 cpu]# cat blue/tasks 8623 cpu]# kill -9 8623 cpu]# ls cgroup.event_control cgroup.procs cpu.cfs_period_us cpu.cfs_quota_us cpu.rt_period_us cpu.rt_runtime_us cpu.shares cpu.stat libvirt notify_on_release release_agent tasks【可以看到blue cgroup已经被自动移除】blkio子系统 概述 限制cgroup对IO的使用两种控制策略weight和throttling。 需要开启的[内核配置](# 内核配置) CONFIG_BLK_CGROUP启用blkio子系统 CONFIG_IOSCHED_BFQ支持weight控制策略 CONFIG_BLK_DEV_THROTTLING支持throttling控制策略 CONFIG_BFQ_CGROUP_DEBUG如果启用了这个选项在cgroup中会显示一些额外的统计文件和控制文件blkio.bfg.weightblkio.bfg.weight_device) weight控制策略接口文件 blkio.bfq.weight读写文件。指定每个cgroup组的权重。这是组在所有设备上的默认权重除非被blkio.bfq.weight_device覆盖。目前允许的范围是1到1000 blkio.bfq.weight_device: 读写文件。指定每个cgroup中每个设备的权重覆盖blkio.bfq.weight echo dev_maj:dev_minor weight blkio.bfq.weight_device # 设置权重 echo 8:16 300 blkio.bfq.weight_device # 移除权重 echo 8:16 0 blkio.bfq.weight_deviceblkio.bfq.io_service_bytes只读文件。cgroup传输到磁盘/从磁盘传输的字节数 blkio.bfq.io_serviced: 只读文件。cgroup向磁盘发出的 IObio数量。 throttling控制策略接口文件 控制文件 blkio.throttle.read_bps_device读写文件。设置从设备读取速率的上限。单位是byets/s echo major:minor rate_bytes_per_second blkio.throttle.read_bps_deviceblkio.throttle.write_bps_device读写文件。设置对设备的写速率上限。单位是byets/s echo major:minor rate_bytes_per_second blkio.throttle.write_bps_deviceblkio.throttle.read_iops_device读写文件。设置从设备读取速率的上限。单位是IO/s echo major:minor rate_io_per_second blkio.throttle.read_iops_deviceblkio.throttle.write_iops_device读写文件。设置对设备的写速率上限。单位是IO/s echo major:minor rate_io_per_second blkio.throttle.write_iops_device注意如果为设备制定了BW和IOPS规则那么IO将同时受到这两个约束 blkio.throttle.io_serviced只读文件。记录自从cgroup创建以来对于每种操作的已完成的I/O操作数。按操作类型进一步划分——读或写同步或异步。 第一个字段设备的主号第二个字段设备的副号第三个字段操作类型第四个字段IOs数量 bklio.throttle.io_service_bytes只读文件。记录自从cgroup创建以来对于每种操作的已完成的向磁盘传输/从磁盘传输的字节数。按操作类型进一步划分——读或写同步或异步。 第一个字段设备的主号第二个字段设备的副号第三个字段操作类型第四个字段字节数 其他接口文件 blkio.reset_stats读写文件。向该文件写入int将导致重置该cgroup中的所有统计信息 blkio.time读写文件。每个设备分配给cgroup的磁盘时间以ms为单位前两个字段指定设备的主号和副号第三个字段指定分配给cgroup的磁盘时间 blkio.sectors读写文件。组从磁盘传输或传输到磁盘的扇区数。前两个字段指定设备的主扇区号和副扇区号第三个字段指定与设备之间传输的扇区数 blkio.io_service_time只读文件。由该cgroup组完成的IOs的请求分派和请求完成之间的总时间。以ns为单位对闪存设备也有意义。对于队列深度为1的设备该时间表示实际服务时间。当队列深度大于1时这种情况就不再成立因为请求可能被乱序处理这可能会导致给定的IO服务时间包括多个IO的服务时间但服务无序时这可能会导致总io_service_time大于实际经过的时间。这段时间根据操作类型进一步划分——读或写、同步或异步。前两个字段表示操作类型第四个字段表示io_service_time单位为ns blkio.io_wait_time只读文件。此cgroup组的IOs在调度程序队列中等待服务的总时间。这可能大于总时间因为它是所有IOs的累积io_wait_time不是cgroup等待总时间的度量而是单个IOs的等待时间的度量。对于队列深度大于1的设备这个指标不包括IO被分配到设备后等待服务的时间而是直到它真正得到服务这里可能有一个时间延迟因为设备重新排序请求以ns为单位。这对闪存设备也有意义这段时间根据操作类型进一步划分——读或写、同步或异步吗。前两个字段指定设备的主、副编号第三个字段指定设备的主、副编号 blkio.io_merged只读文件。IOs请求合并到属于该cgroup的总数。进一步划分操作类型——读或写同步或异步 blkio.io_queued只读文件。在任何给定时刻为该cgroup排队的请求总数。进一步划分操作类型——读或写同步或异步 blkio.avg_queue_size只读文件。只有当CONFIG_BFQ_CGROUP_DEBUGEy时才启用调试辅助功能。该cgroup存在的整数时间内该cgroup的平均队列大小。每当此cgroup的一个队列获得一个时间片时就会获取队列大小样本 blkio.group_wait_time只读文件。CONFIG_BFQ_CGROUP_DEBUGEy时才启用调试辅助功能。这是cgroup从忙起即从0到1个排队请求为它的一个队列获取时间片需要等待的时间。这与io_wait_time不同io_wait_time是该cgroup中每个IO在调度程序队列中等待所花费的时间的累计总和。单位是ns如果在cgroup处理等待状态时读取该值则stat将只报告直到最后一次获取时间片为止累积的group_wait_time而不包括当前增量 blkio.empty_time只读文件。CONFIG_BFQ_CGROUP_DEBUGEy时才启用调试辅助功能。这是一个cgroup在没有被服务的情况下没有任何挂起的请求的时间也就是说它不包括cgroup的某个队列的空闲时间。单位是ns如果在cgroup处于空状态时读取该值则stat将只报告截至上次有待处理请求为止累积的empty_time而不包括当前增量 blkio.idle_time只读文件。CONFIG_BFQ_CGROUP_DEBUGEy时才启用调试辅助功能。这是IO调度器为给定的cgroup等待一个比其他队列/cgroup的现有请求更好的请求所花费的时间。单位时ns如果在cgroup处于空闲状态读取此值则stat将只报告截至最后一个空闲时间段累积的idle_time而不包括当前增量 blkio.dequeue只读文件。CONFIG_BFQ_CGROUP_DEBUGEy时才启用调试辅助功能。这提供了关于一个cgroup从设备的服务树中退出队列的次数的统计信息。前两个字段指定设备的主号和副号第三个字段指定cgroup从特定设备退出队列的次数 blkio.*_recursive只读文件各种统计的递归版本这些文件显示的信息与他们的非递归对应项相同但包括来自所有子cgroups的统计信息 cpu子系统 概述 主要是限制cgroup对CPU的使用三种控制策略权重比例设置、周期使用时间上限和RT调度策略。 按权重比例设定CPU的分配 cpu.shares读写文件。CPU比重分配通过一个整数的数值调节cgroup所占用的CPU时间。例如有两个cgroupC1和C2其中C1的cpu.shares设定为100另一个设定为200那么C2所使用的cpu时间将是C1所用时间的2倍 设定CPU使用周期使用时间上限 cpu.cfs_period_us读写文件。规定CPU的时间周期微秒最大值是1s最小值是1000微妙。例如如果在一个单CPU的系统内要保证一个cgroup内的任务在1s的CPU周期内占用0.2s的CPU时间可以通过设置cpu.cfs_quota_us为200000和cpu.cfs_period_us为1000000cpu.cfs_quota_us读写文件。在单位时间内即cpu.cfs_period_us设定值可用的CPU最大时间单位是微秒。cpu.cfs_quota_us值可以大于cpu.cfs_period_us的值例如在一个双CPU的系统内想要一个cgroup内的进程充分地利用2个CPU可以设定cpu.cfs_quota_us为200000及cpu.cfs_period_us为100000cpu.stat只读文件。统计信息包含 nr_periods经历了几个cfs_period_us周期nr_throttledtask被限制的次数throtled_time表示task被限制的总时长 **RT调度策略下的配置**实时调度策略与公平调度策略中的按周期分配时间的方法类似也是在周期内分配一个固定的运行时间 cpu.rt_period_us以微妙为单位在某个时间段中cgroup对CPU资源访问重新分配的频率。如果某个cgroup中的任务应该每5s有4s可访问CPU资源则请将rt_runtime_us设定4000000并将rt_period_us设定为5000000cpu.rt_runtime_us以微妙为单位指定某个时间段中cgroup中的任务对CPU资源的最长连续访问时间建立这个限制是为了防止一个cgroup中的任务独占CPU时间。注意父cgroup中的rt_runtime_us一定要大于等于子cgroup中的rt_runtime_us不让会报参数错误的错误信息。 cpuacct子系统 概述 显示cgroup中任务所使用的CPU资源其中包括子群组任务报告有两大类 usage统计cgroup中进程使用CPU的时间单位为纳秒stat统计cgroup中进程使用CPU的时间单位为USER_HZ 需要开启的内核配置: CONFIG_CGROUP_CPUACCT 接口文件 cpuacct.usage只读文件。记录该cgroup中所有进程的CPU使用总时间以纳秒为单位cpuacct.usage_percpu只读文件。记录该cgroup中所有进程在每个CPU上的使用时间以纳秒为单位cpuacct.usage_user只读文件。报告一个cgroup中所有任务使用用户态CPU的总时间以纳秒为单位cpuacct.usage_percpu_user只读文件。报告一个cgroup中所有任务在每个CPU上使用用户态CPU的时间以纳秒为单位cpuacct.usage_sys只读文件。报告一个cgroup中所有任务在CPU上使用内核态CPU的时间以纳秒为单位cpuacct.usage_percpu_sys只读文件。报告一个cgroup中所有任务在每个CPU上使用内核态CPU的时间cpuacct.usage_all只读文件。详细输出文件cpuacct.usage_percpu_user和cpuacct.usage_percpu_sys的内容cpuacct.stat只读文件。报告cgroup的所有任务使用的用户和内核CPU时间单位为USER_HZ cpuset子系统 概述 为一组进程分配指定的CPU和[NUAM节点](# NUMA架构) 以下规则适用每个cgroup 它的 CPU 和[NUAM节点](# NUMA架构)必须是其父级的子集。除非其父级被标记为exclusive否则它不能被标记为exclusive。如果其 CPU 或内存是独占的则它们可能不会与任何兄弟cgroup重叠必须指定当前cgroup的cpuset.mems和cpuset.cpus才能将进程移入当前cgroup CPU相关的接口文件 cpuset.cpus: 读写文件。允许cgroup中的进程使用的CPU列表。如0-2, 16代表01216这4个CPUcpuset.effective_cpus: 只读文件。显示了当前cgroup中实际可用于分配给进程的CPU核心列表它考虑了上级cgroup的限制和当前cgroup的cpuset.cpus配置从而提供了一个最终的、实际可用的CPU核心集合cpuset.cpu_exclusive: 读写文件。cgroup是否独占cpuset.cpus中分配的cpu。默认值为0表示共享1表示独占。如果设置为1其他cgroup内的cpuset.cpus值不能包含有该cpuset.cpus内的值cpuset.sched_load_balance: 读写文件。cgroup的cpu压力是否会被平均到cpuset中的多个cpu上。默认值1启用负载均衡0表示禁用。注意如果任意上级cgroup中启用负载均衡则在cgroup中设定这个标签没有任何效果因为已经在较高一级cgroup中处理了负载均衡。因此要在cgroup中禁用负载平衡还要在每个上级cgroup中禁用负载平衡。cpuset.sched_relax_domain_level包含-1到小正数间的整数它代表内核应该尝试平衡负载的CPU宽度范围如果禁用了cpuset.sched_load_balance则该值毫无意义。 cpuset.sched_relax_domain_level值 值效果-1为负载平衡使用系统默认值0不执行直接负载平衡负载平衡只是阶段性的1在同一核中的跨线程直接负载平衡2在同一软件包中的跨线程直接负载平衡3在同一节点或刀片中的跨线程直接负载平衡4在不使用NUMA架构中跨多个CPU的直接负载平衡5在使用NUMA架构中跨多个CPU的直接负载平衡 Memory相关的接口文件 cpuset.mems: 读写文件。允许cgroup中的进程使用的内存节点列表。如0-2, 16代表0,1,2,16这4个可用节点。 cpuset.effective_mems: 只读文件。显示当前cgroup中实际可用于分配给进程的内存节点列表同样考虑了上级cgroup的限制和当前cgrouop的cpuset.mems配置 cpuset.mem_exclusive: 读写文件。是否独占memory。默认值0表示共享1表示独占。如果设置为1其他cgroup内的cpuset.mems值不能包含有该cpuset.mems内的值 cpuset.memory_migrate: 读写文件。用来指定当cpuset.mems中的值更改时是否应该将内存中的页迁移到新节点。默认情况下是0表示禁止内存迁移且页就保留在原来分配的节点中即使在cpuset.mems中现已不再指定这个节点。如果设置为1则该系统会将页迁移到由cpuset.mems指定的新参数中的内存节点中。 cpuset.memory_spread_page: 读写文件。如果被设置了将该cpuset中进程上下文是申请的page cache平均分布到cpuset中的各个节点中。默认值是0表示不启用。设置为1表示启用 cpuset.mem_hardwall主要用于控制内存分配的行为开启该选项后内存只能从指定的节点中分配而不能从其他节点获取。默认情况下为0即不启用 cpuset.memory_pressure_enabled包含指定系统是否应该计算这个cgroup中进程所生成的内存压力的标签0或1。计算出的值输出到cpuset.memory_pressure且代表进程试图释放使用中内存的比例报告为尝试每秒再生内存的整数值再乘1000【这个文件只在cpuset根目录中出现cpuset下的cgroup组中是没有这个文件的】【这个内存压力是回收内存的速度也就是在进程用完内存之后回收进程内存的速度】 cpuset.memory_spread_page如果被设置了将该cpuset中进程上下文是申请的page cache平均分布到cpuset中的各个节点中I/O磁盘读写会用到page cache cpuset.memory_spread_slab如果被设置了将该cpuset中进程上下文申请的slab对象平均分配到cpuset的各个节点中缓存文件I/O也就是目录和inode会用到slab【经过测试这个标识符好像被弃用了】 cpuset.memory_pressure包含运行在这个cpuset中产生的平均内存压力的只读文件。启用cpuset.memory_perssure_enabled时这个伪文件中的值会自动更新否则伪文件包含的值为0 devices子系统 概述 来跟踪和执行对设备文件的打开和关闭限制。设备cgroup为每个cgroup关联一个设备接入白名单白名单有四个字段 typea(all), c(char), b(block)主设备号副设备号访问权限(r ,w, m(mknod)) 需要开启的内核配置 CONFIG_CGROUP_DEVICE **层次结构**设备组通过确保子cgroup永远不会拥有比其父cgroup更多的访问权限来维护层次结构。每次将条目写入cgroup的devices.deny文件时它的所有子cgroup都会从白名单中删除该条目并且所有本地设置的白名单条目都会被重新评估。如果某个本地设置的白名单条目提供了比父cgroup更多的访问权限它将从白名单中删除 接口文件 devices.allow允许访问的设备。文件包含4个字段type设备类型major主设备号minor次设备号access访问方式 typea——适用所有设备包括字符设备和块设备b——块设备c——字符设备major/minor9:* * 8:1accessr——读w——写m——创建不存在的设备 devices.deny禁止访问的设备格式如devices.allowdevices.list显示目前允许被访问的设备列表 示例1 A/ \Bgroupwhitelistdenied devicesAall the rest“b 8:* rwm”, “c 116:1 rw”B“c 1:3 rwm”, “c 116:2 rwm”, “b 3:* rwm”all the rest 将c 116:* r写入A组的禁用设备 echo c 116:* r A/devices.deny它将向下传播在重新验证B的条目后白名单条目c 116:2 rwm将被删除 groupwhitelistdenied devicesAall the rest“b 8:* rwm”, “c 116:* rw”B“c 1:3 rwm”, “b 3:* rwm”all the rest 如果父cgroup不允许访问某设备那子cgroup也没有权限访问 示例2 A/ \Bgroupwhitelistdenied devicesA“c *:3 rwm”, “c 1:5 r”all the restB“c 1:3 rwm”, “c 1:5 r”all the rest 可以在B中添加新的条目 echo c 2:3 rwm B/devices.allow echo c 50:3 r B/devices.allowfreezer子系统 概述 可以启动和停止cgroup中的进程 需要开启的内核配置 CONFIG_CGROUP_FREEZER 接口文件 freezer.state: 读写文件 cgroup的三种状态 FROZEN挂起该cgroup中的任务FREEZING该系统正在挂起该cgroup中的任务THAWED已经恢复该cgroup中的任务 当被读取时返回该group的有效状态也就是上面三种状态。这是自己和父cgroup状态的结合。如果有FREEZING则cgroup的状态为FREEZING当属于cgroup及其子cgroup所有任务被冻结时cgroup转换为FROZEN。注意当一个新任务被添加到cgroup或它的子cgroup中cgroup会从FROZEN状态恢复到FREZING状态直到新任务被冻结写入时设置cgroup的self-state。允许两个值FROZEN和THAWED。如果写了FROZEN则cgroup和它的所有子cgroup一起进入FROZEN状态如果写入THAWED则cgroup的self-state更改为THAWED。注意如果父cgroup状态仍处于FROZEN则有效状态可能不会被更改为THAWED。如果cgroup的有效状态变为THAWED则由于cgroup而冻结的所有子cgroup将离开FROZEN状态 freezer.self_freezing: 只读文件。显示self-state。如果是0则为THAWED状态否则为1。如果最后一次写入了FORZEN这个值为1freezer.parent_freezing: 只读文件。显示parent-state。如果cgroup的父cgroup不是FROZEN则为0否则为1 注意事项 挂起进程时会连同子进程一同挂起不能将进程移动到处于FROZEN状态的cgroup中只有FROZEN状态和THAWED状态可以被写进freezer.state中FREEZING状态则不能只能读取它root cgroup是不可冻结的 示例 mkdir /sys/fs/cgroup/freezer mount -t cgroup -ofreezer freezer /sys/fs/cgroup/freezer mkdir /sys/fs/cgroup/freezer/0 echo $some_pid /sys/fs/cgroup/freezer/0/tasks获取子系统的状态 cat /sys/fs/cgroup/freezer/0/freezer.state output: THAWED冻结子系统 echo FROZEN /sys/fs/cgroup/freezer/0/freezer.state cat /sys/fs/cgroup/freezer/0/freezer.state output: FREEZING cat /sys/fs/cgroup/freezer/0/freezer.state output: FROZEN解冻子系统 echo THAWED /sys/fs/cgroup/freezer/0/freezer.state cat /sys/fs/cgroup/freezer/0/freezer.state output: THAWEDlinux kernel文档原文 对于批处理作业管理系统来说cgroup freeze是非常有用的它可以启动和停止任务集以便根据系统管理员的需要调度机器的资源。这种类型的程序通常用于HPC集群以调度对整个集群的访问。cgroup freezer使用cgroups来描述处理作业管理系统要启动/停止的任务集。它还提供了启动和停止组成作业的任务的方法。 freezer对于检查点运行中的任务组也很有用。freezer允许检查点代码通过尝试强制cgroup中的任务进入静止状态来获得任务的一致映像。一旦任务处于静止状态另一个任务就可以walk /proc或调用内核接口来收集关于静止状态的任务的信息。如果发生可恢复的错误可以稍后重新启动检查点任务。这还允许通过将收集到的信息复制到另一个节点并重新启动任务在集群中的节点之间迁移检查点任务。 SIGSTOP和SIGCONT序列并不总是足以停止和恢复用户空间中的任务这两个信号都可以从我们希望冻结的任务中观察到虽然SIGSTOP不能被捕获、阻塞或忽略但可以通过等待或跟踪父任务来查看它。SIGCONT尤其不合适因为它可能被任务捕获。任何旨在监视SIGSTOP和SIGCONT的程序都可能被试图使用SIGSTOP和SIGCONT来停止和恢复任务而破坏。我们可以用嵌套的bash shell来演示这个问题 $ echo $$ 16644 $ bash $ echo $$ 16690From a second, unrelated bash shell: $ kill -SIGSTOP 16690 $ kill -SIGCONT 16690at this point 16690 exits and causes 16644 to exit toohugetlb子系统 概述 允许限制cgroup的hugepage使用量和hugepage预留。 需要的内核配置 CONFIG_CGROUP_HUGETLBCONFIG_HUGETLB_PAGECONFIG_HUGETLBFS hugepage使用量接口文件 hugetlb.2MB.limit_in_bytes: 读写文件。设置hugepage大小为2MB的hugepage使用量限制hugetlb.1GB.limit_in_bytes: 读写文件。设置hugepage大小为1GB的hugepage使用量限制hugetlb.2MB.max_usage_in_bytes: 只读文件。显示hugepage大小为2MB最大hugepages使用记录hugetlb.1GB.max_usage_in_bytes: 只读文件。显示hugepage大小为1GB最大hugepages使用记录hugetlb.2MB.usage_in_bytes: 只读文件。显示hugepages大小为2MB的hugepage的当前使用量hugetlb.1GB.usage_in_bytes: 只读文件。显示hugepages大小为1GB的hugepage的当前使用量hugetlb.2MB.failcnt: 只读文件。显示hugepage大小为2MB由于hugepage使用限制导致的分配失败hugetlb.1GB.failcnt: 只读文件。显示hugepage大小为1GB由于hugepage使用限制导致的分配失败 hugepage预留接口文件 接口文件: hugetlb.2MB.rsvd.limit_in_bytes: 读写文件。设置hugepage大小为2MB的hugepage预留限制hugetlb.1GB.rsvd.limit_in_bytes: 读写文件。设置hugepage大小为1GB的hugepage预留限制hugetlb.2MB.rsvd.max_usage_in_bytes: 只读文件。显示hugepage大小为2MB最大hugepages预留记录hugetlb.1GB.rsvd.max_usage_in_bytes: 只读文件。显示hugepage大小为1GB最大hugepages预留记录hugetlb.2MB.rsvd.usage_in_bytes: 只读文件。显示hugepages大小为2MB的hugepage的当前预留量hugetlb.1GB.rsvd.usage_in_bytes: 只读文件。显示hugepages大小为1GB的hugepage的当前预留量hugetlb.2MB.rsvd.failcnt: 只读文件。显示hugepage大小为2MB由于hugepage预留限制导致的分配失败hugetlb.1GB.rsvd.failcnt: 只读文件。显示hugepage大小为1GB由于hugepage预留限制导致的分配失败 查看hugepage使用情况 cat /proc/meminfo | grep Huge修改系统中hugepage大小 在/etc/default/grub中增加default_hugepagesz1G hugepagesz1G配置然后更新grub配置 然后更新配置 sudo update-grab # ubuntu22 sudo grub2-mkconfig -o /boot/grub2/grub.cfg # opencloudos 8.8/9.2/Stream 23最后重启系统即可 rebootmemory子系统 概述 限制cgroup所能使用的内存上限 需要的内核配置 CONFIG_MEMCGCONFIG_SWAP 接口文件 memory.usage_in_bytes: 只读文件。显示当前内存使用情况单位为字节 memory.memsw.usage_in_bytes: 只读文件。显示当前内存交换的使用情况单位为字节 memory.max_uasge_in_bytes: 只读文件。显示记录的最大内存使用量单位为字节 memory.memsw.max_usage_in_bytes: 只读文件。显示记录的最大内存交换使用量单位为字节 memory.failcnt: 只读文件。显示内存达到memory.limit_in_bytes设定的限制值的次数 memory.memsw.failcnt: 只读文件。显示内存swap空间限制达到在memory.memsw.limit_in_bytes设定的值的次数 memory.limit_in_bytes: 读写文件。设定最大的内存使用量包括文件缓存可以加单位(k/K, m/M, g/G)不加单位默认为bytes。不能限制root cgroup。写入-1删除现有的限制 memory.soft_limit_in_bytes: 读写文件。和memory.limit_in_bytes的差异是这个限制并不会阻止进程使用超过限额的内存只是在系统内存不足时会优先回收超过限额的进程占用的内存使之向限定值靠拢。该值应小于memory.limit_in_bytes设定值【在有CONFIG_PREEMPT_RT系统中不可用】 memory.memsw.limit_in_bytes: 读写文件。设定最大的内存swap的用量之和。可以加单位(k/K, m/M, g/G)不加单位默认为bytes。不能限制根cgroup。写入-1删除现有的限制 memory.force_empty: 只写文件。当写入0时清空该group的所有内存页。该选项只有在当前group没有tasks才可以使用。删除cgroup前请使用memory.force_empty以避免将不再使用的页面缓存移动到它的上级cgroup中 memory.swappiness: 读写文件。将内核倾向设定为换出这个cgroup中任务所使用的进程内存而不是从页缓冲中再生页面。这也是在/proc/sys/vm/swappiness中设定的使用同一方法为整个系统设定的内核倾向。默认值为60低于这个值会降低内核换出进程内存的倾向将其设定为0则完成不会为cgroup中的任务换出进程内存。高于这个值将提高内核换出进程内存的倾向等于100时内核将开始换出作为这个cgroup中进程的地址空间的一部分页面。不能更改以下群组的swappniess根cgroup它使用在/proc/sys/vm/swappiness中设定的swappiness。 cgroup.event_control: 只写文件。event_fd()的接口【在有CONFIG_PREEMPT_RT系统中不可用】 memory.pressure_level: 读写文件。设置内存压力通知。压力级别通知用于监控内存分配成本基于压力应用程序可以实现不同的内存资源管理策略。 压力等级定义 low level意味着系统正在为新的分配回收内存。监视此回收活动可能有助于维护缓存级别。收到通知后程序通常是Activity Manger可能会分析vmstat并提前采取行动medium level意味着系统正经历中等内存压力系统可能正在进行交换、分页出活动文件缓存等。在此事件发生后应用程序可能决定进一步分析vmstat/zoneinfo/memcg或内部内存使用统计数据并释放任何可以轻松重构或从磁盘重新读取的资源critical level意味着系统处于主动抖动状态即将内存不足(OOM)甚至内核内的OOM killer即将触发。应用程序应该尽其所能帮助系统。咨询vmstat或其他统计信息可能为时已晚因此建议立即采取行动 三种事件传播方式 default事件向上传播直到事件被处理。比如有A-B-C现在C承受一些压力在ABC上设置了事件监听器则只有C会收到通知。如果只在AB上设置了事件监听器则只有B会受到通知hierarchy事件总是向上传播到根节点。类似default模式但是这个模式无论每个级别是否有事件监听器传播都会继续进行直到到达根节点local事件只在注册通知的memcg中遇到内存压力时接收通知。在上面的例子中如果C组注册了本地通知则该组将受到通知并且改组经历内存压力。但是如果B注册了本地通知则无论C组是否有事件监听器B组都将不会受到通知 级别和事件通知模式由逗号分隔的字符串指定。例如“low, hierarchy” 要注册通知应用程序必须 使用eventfd(2)创建一个eventfd打开memory.pressure_level将字符串写入cgroup.event_control字符串格式如event_fd net_cls子系统 **概述**使用等级标识符(classid)标记网络数据包可允许linux流量控制程序(traffic controller, tc)识别从具体cgroup中生成的数据包为来自不同cgroup的报文分配不同的优先级 需要开启的内核配置 CONFIG_CGROUP_NET_CLASSID 接口文件 net_cls.classid: 读写文件。包含一个说明流量控制句柄的十六进制的值初始值为0。。这些句柄的格式为0xAAAABBBB其中AAAA是十六进制主设备号BBBB是十六进制副设备号。 net_pero.ifpriomap配置网卡的优先级映射 net_prio.priodx显示当前cgroup的优先级索引 示例 mkdir /sys/fs/cgroup/net_cls mount -t cgroup -onet_cls net_cls /sys/fs/cgroup/net_cls mkdir /sys/fs/cgroup/net_cls/0 # 设置10:1的句柄 echo 0x100001 net_cls.classidcat net_cls.classid output: 1048577配置tc tc qdisc add dev lo root handle 10: htb # 创建新 tc class add dev lo parent 10: classid 10:1 htb rate 5mbit创建过滤器 tc filter add dev lo parent 10: protocol ip prio 10 handle 1: cgroup删除规则 tc qdisc del dev lo root查看类具体情况 tc -s class show dev ens33net_prio子系统 **概述**允许设置各种应用程序产生的网络流量的优先级 接口文件 net_prio.ifpriomap: 读写文件。该文件包含分配给来自该组进程的流量的优先级映射。这些流量从不同的接口流出系统。它包含一个形式为ifname priority的元组列表。可以通过使用相同的元组格式将字符串回显到文件中来修改文件内容。 echo eth0 5 /sys/fs/cgroups/net_prio/iscsi/net_prio.ifpriomap该命令将强制从属于iscsi net_prio group的进程发出从eth0接口出接口的任何流量将所述流量的优先级设置为5。父cgroup也会有一个可写的net_prio.ifpriomap文件用于设置系统默认优先级优先级是在将帧排队到qdisc之前设置的net_prio的一种用法是与mqprio qdisc一起使用允许将应用程序流量引导到基于硬件/驱动程序的流量类。然后可以由管理员或其他网络协议管理这些映射 net_prio.proidx只读文件。它包含一个唯一的整数值内核使用它作为cgroup的内部表示 perf_event子系统 概述 该层级中的所有cgroup可以使用perf工具对这些进程和线程监控没有可供调节的参数 pids子系统 概述 允许cgroup在达到一定限制后阻止任何新任务被fork()或clone() 需要开启的内核配置 CONFIG_CGROUP_PIDS 接口文件: pids.max: 读写文件。设置最大任务数不能在root cgroup中使用。默认值是maxpids.current: 只读文件。目前cgroup运行的任务数pids.current有可鞥大于pids.max通过设置pids.max小于pids.current实现但是不可能通过fork和clone实现pids.events: 只读文件。包含事件计数器 max: 由于自身或父cgroup达到限制cgroup 中 fork 失败的次数 misc子系统 概述 misc控制器提供了资源限制和跟踪机制 需要开启的内核配置 CONFIG_CGROUP_MISC 接口文件 misc.capacity只读文件。显示了平台上可用的各种标量资源及其数量 cat misc.capacity output: res_a 50 res_b 10misc.current只读文件。显示了cgroup及其子cgroup中资源的当前使用情况 cat misc.current res_a 3 res_b 0misc.max读写文件。非根cgroup存在允许最大限度地使用cgroup及其子cgroup中的资源 cat misc.max output: res_a max res_b 4Limit can be set by echo res_a 1 misc.max echo res_a max misc.maxmisc.event只读文件。定义了以下条目。除非另有指定否则此文件中的值更改将生成文件修改事件该文件中的所有字段都是分层的 maxcgroup的资源使用超过最大边界的次数 迁移和所有权 一个杂项的标量资源被分配给第一个使用它的cgroup并一直分配给该cgroup直到该资源被释放。将进程迁移到不同的cgroup不会将费用迁移到进程已移动的目标cgroup Cgroup V2 基础操作 组织进程和线程 进程 最初只存在所有进程所属的根cgroup。子cgroup可以通过创建子目录来创建 mkdir $CGROUP_NAME一个给定的cgroup可以有多个子cgroup形成树形结构。每个cgroup都有一个可读写的接口文件cgroup.procs。读取时它每行列出属于cgroup的所有进程的PID。PID不是有序的如果进程被移动到另一个cgroup然后返回或者PID在读取时被回收同一个PID可能会出现不止一次 通过将进程的PID写入目标cgroup的cgroup.procs可以将进程迁移到cgroup中。一个write(2)掉哦那个只能迁移一个进程如果一个进程由多个线程组成写入任何线程的PID偶会迁移该进程的所有线程 当一个进程派生一个子进程时新进程在操作时出生在该分支进程所属的cgroup中。退出后进程与退出时所属的cgroup保持关联直到它被回收。但是 cgroup.procs不会出现僵尸进程因此不能移动到另一个cgroup 没有任何子进程或活动进程的cgroup可以通过删除目录来销毁。请注意没有任何子进程且只与僵尸进程相关联的cgroup被认为是空的可以删除 rmdir $CGROUP_NAME/proc/$PID/cgroup列出了进程的cgroup成员。如果系统中使用的是cgroup v1则该文件可能包含多行每个层次一个。cgroup v2的条目格式是$PATH cat /proc/$PID/cgroup output: 0::/test-cgroup/test-cgroup-nested如果进程变成僵尸进程并且它所关联的cgroup随后被删除。“(deleted)”被附加到路径中 cat /proc/$PID/cgroup output: 0::/test-cgroup/test-cgroup-nested(deletd)线程 cgroup v2支持控制器子集的线程粒度以支持需要在进程线程之间进行分配资源分配的用例。默认情况下进程的所有线程都属于同一个cgroup该cgroup还充当资源域用于承载不特定于进程或线程的资源小号。线程模式允许线程分布在子树中同时仍为它们维护公共资源域 支持线程模式的控制器被称为线程控制器不支持线程模式的控制器被称为域控制器 将cgroup标记为线程化会使其作为线程化cgroup加入其父级的资源域。父级可能是另一个线程化cgroup其资源域在层次结构上更靠上。线程化子树的根即最近的非线程化祖先可互换地称为线程域或线程根并充当整个子树的资源域 在线程子树内部进程的线程可以放在不同的cgroup中并且不受内部进程约束——无论非叶cgroup中是否是有线程都可以在非叶cgroup上启用线程控制器 由于线程域cgroup承载子树的所有域资源消耗因此无论其中是否有进程它都被视为具有内部资源消耗并且不能包含未线程化的已填充子cgroup。由于根cgroup不受任何内部进程约束因此它既可以充当线程域也可以充当域cgroup的父级 cgroup当前的运行模式或类型在cgroup.type中显示该文件表明该cgroup是普通域、作为线程子树的域的域还是线程cgroup 在创建时cgroup始终是域cgroup可以通过将threaded写入cgroup.type文件来实现线程化操作是单向的 echo threaded cgroup.types一旦线程化cgroup就不能再次称为域。要启用线程模式必须满足以下条件 因为cgroup将加入父级的资源域。父级必须是有效(线程)域或线程cgroup当父域为非线程域时它不得启用任何域控制器或填充任何子域。根域不受此要求限制 从拓扑角度来看cgroup可能处于无效状态请考虑以下拓扑 A (threaded domain) - B (threaded) - C (domain, just created)C创建为域但未连接到可托管子域的父域。C无法使用直到它变成线程cgroup。在这些情况下cgroup.type文件将报告domain (invalid)。由于拓扑无效而失败的操作使用EOPNOTSUPP作为errno 当域cgroup的某个子cgroup变成线程化或cgroup.subtree_control文件中启用线程控制器且cgroup中有进程时域cgroup将变成线程化域。当条件清除时线程化域变为普通域 读取时cgroup.threads包含cgroup中所有线程的线程ID列表。除了操作是针对每个线程而不是每个进程之外“cgroup.threads具有相同的格式并且行为方式与cgroup.procs相同。虽然可以在任何cgroup中写入cgroup.threads”因为它只能在同一个线程域内移动线程但其操作仅限于每个线程子树内 线程域cgroup充当整个子树的资源域虽然线程可以分散在子树但所有进程都被视为位于线程域cgroup中线程域cgroup中的cgroup.procs包含子树所有进程的PID在子树中无法读取。但是cgroup.procs可以从子树中的任何位置写入以将匹配进程的所有线程迁移到cgroup 线程子树中只能启动线程控制器。在线程子树中启用线程控制器时它仅考虑和控制与cgroup及其后代中的线程相关的资源消耗。所有不与特定线程绑定的消耗都属于线程域cgroup 由于线程子树不受任何内部进程约束的约束线程控制器必须处理非叶cgroup及其子cgroup中的线程之间的竞争每个线程控制器都定义了如何处理此类竞争 目前以下控制器是线程化的可以在线程cgroup中启用 - cpu - cpuset - perf_event - pidspopulated 通知 每个非根cgroup都有一个cgroup.events文件其中包含polutated指示cgroup的子层次结构中是否有活动进程。如果cgroup及其后代中没有活动进程则其值为0否则为1。当值更改时会触发poll和notify事件。例如这可用于在给定子层次结构的所有进程退出启动清理操作。populated状态更新和通知是递归的。考虑以下子层次结构其中括号中的数字表示每个cgroup中的进程数 A(4) - B(0) - C(1)\ D(0)A、B和C的populated字段将为1而D为0。在C中的一个进程退出后B和C的populated字段将翻转为0并且两个cgroups的cgroup.events文件上都会生成文件修改事件 cgroup.controllers 启用和禁用 每个cgroup都有一个cgroup.controllers文件其中列出了该cgroup可以启用的所有控制器 cat cgroup.controllers默认情况下不启用任何控制器可以通过写入cgroup.subtree_control文件来启用和禁用控制器 echo cpu memory -io cgroup.subtree_control仅可启用cgroup.controllers中列出的控制器当指定多个上述操作时它们要么全部成功要么全部失败。如果对同一个控制器指定了多个操作则最后一个操作有效 在cgroup中启用控制器表示将控制目标资源在其直属子级之间的分布。请考虑以下子层次结构已启用的控制器在括号中 A(cpu,memory) - B(memory) - C()\ D()由于A启用了cpu和memoryA将控制向其子进程本例为B分配CPU周期和内存。由于B启用了memory但未启用CPUC和D可以自由竞争CPU周期但对B可用内存的分配将受到控制 由于控制器负责调节目标资源向cgroup子节点的分配因此启用它会在子cgroup中创建控制器的接口文件。在上面的例子中在B上启用cpu会在C和D中创建以cpu.为前缀的控制器接口文件。同样在B上禁用memory会从C和D中删除以memory.为前缀的控制器接口文件。这意味着控制器接口文件任何不以cgroup.开头的文件都归父节点所有而不是cgroup本身 自上而下的约束 资源自上而下分配并且只有当资源已从父级分配给cgroup时cgroup才能进一步分配资源。这意味着所有非根cgroup.subtree_control文件只能包含在父级cgroup.subtree_control文件中启用的控制器。 无内部进程约束 非根cgroup只有在没有自己的进程时才能将域资源分配给其子cgroup换句话说只有不包含任何进程的域cgroup才能在其cgroup.subtree_control文件中启用域控制器 这可以保证当域控制器查看已启用它的层次结构部分时进程始终只位于叶子上。这排除了子cgroup与父cgroup的内部进程竞争的情况 根cgroup不受此限制。根包含进程和匿名资源消耗这些资源消耗不能与任何其他cgroup关联并且需要大多数控制器的特殊处理。如何管理根cgroup中的资源消耗取决于每个控制器 注意如果cgroup的cgroup.subtree_control中没有启用控制器则限制不会起作用。这很重要否则就无法创建已polutated cgroup的子项。要控制cgroup的资源分配cgroup必须创建子项并将其所有基础南横转移到子项然后才能在其cgroup.subtree_control文件中启用控制器 委派 委派模型 cgroup可以通过两种方式委派。首先通过向用户授予目录及其cgroup.procscgroup.threads和cgroup.subtree_control文件的写入权限委派给权限较低的用户。其次如果设置了nsdelegate挂载选项则在创建命名空间时自动委派给cgroup命名空间 由于给定目录中的资源控制接口文件控制父级资源的分配因此不应允许委托人写入这些文件 。对于第一种方法这是通过不授予对这些文件的访问权限来实现的。对于第二种方法内核拒绝从命名空间内部写入命名空间根目录上除cgroup.procs和cgroup.subtree_control之外的所有文件 两种委派类型的最终结果是相同的。一旦委派用户可以在目录下建立子层次结构根据需要组织其中的进程并进一步分配从父级获得的资源。所有资源控制器的控制和其他设置都是分层的无论委派的子层次结构中发生上面都无法逃脱父级施加的资源限制。 目前cgrou对委派子层次结构中的cgroup数量或嵌套深度没有任何限制。但是将来可能会明确限制 委派控制 委派子层次结构被包含在某种意义上则被委派者不能将进程移入或移出子层次结构 对于授权给较低权限用户的委派这是通过要求具有非root euid的进程满足以下条件来将目标进程迁移到cgroup中方法是将其PID写入cgroup.procs文件 写入者必须具有cgroup.procs文件的写权限写入者必须对源和目标cgroups的共同祖先的cgroup.procs文件具有写入权限 上述两个约束确保了虽然被委派者可以在委派的子层次结构中自由迁移流程但不能从子层次结构外部拉入或推出。 举例来说假设cgroup C0和C1已委派给用户U0该用户在C0下创建了C00、C01在C1下创建了C10如下所示且C0和C1下的所有进程都属于U0 ~~~~~~~~~~~~~ - C0 - C00 ~ cgroup ~ \ C01 ~ hierarchy ~ ~~~~~~~~~~~~~ - C1 - C10假设U0想要将当前位于C10中的进程的PID写入C00/cgroup.procs。U0具有该文件的写入访问权限但是源cgroup C10 和目标cgroup C00的共同祖先位于委派点之上U0不具有其cgroup.procs的文件写访问权限因此将使用-EACCESS拒绝该写入 对于命名空间的委托遏制是通过要求源cgroup和目标cgroup都可从尝试迁移的进程的命名空间的访问来实现的。如果其中一个不可访问则迁移将被拒绝并返回-ENOENT 指南 组织一次并控制 跨cgroup迁移进程是一项相对昂贵的操作并且内存等有状态资源不会随进程一起移动。这是一个明确的设计决策因为在同步成本方面迁移和各种热路径之间通常存在固有的权衡 因此不建议频繁地跨cgroup迁移进程以应用不同的资源限制。启动时应根据系统的逻辑和资源结构将工作负载分配给cgroup可以通过接口文件更改控制器配置来动态调整资源分配 避免名称冲突 cgroup及其子cgroup的接口文件占用同一目录因此可能会创建与接口文件冲突的子cgroup 所有cgroup的核心接口文件都以cgroup.“作为前缀每个控制器的接口文件都以控制器名称和点作为前缀。控制器的名称由小写字母和”_“组成但从不以”_开头因此可以将其作为前缀字符以比避免冲突。此外接口文件名不会以通常用于对工作负载进行分类的术语例如作业、服务、切片、单元或工作负载开头或结尾 资源分配模型 权重 父母的资源分配方式是将所有活跃子女的权重相加并为每个子女分配与其权重与总和之比相匹配的分数。由于只有当前可以使用资源的子女参与分配因此这是节省工作的。由于其动态特性此模型通常用于无状态资源 所有权重都在[1, 10000]范围内默认值为100。这允许在足够细的粒度下在两个方向上进行对称乘性偏差同时保持在直观范围内。 值要权重在范围内所有配置组合都是有效的没有理由拒绝配置更改或流程迁移 cpu.weight按比例将CPU周期分配给活跃子进程 就是这种类型的一个例子 限制 子进程最多只能消耗配置的资源量。限制可能会过大——子进程的总限制可能会超过父进程的资源量 限制在范围[0 max]内默认为max 由于限制可能被过度承诺所有配置组合都是有效的没有理由拒绝配置更改或流程迁移 io.max限制cgroup在IO设备上可以消耗的最大BPS或IOPS是此类型的一个示例 保护措施 只要cgroup的所有祖先的使用量都低于其保护级别则cgroup受到的保护量最高可达配置的资源量。保护可以硬性保证也可以是尽力而为的软性边界。保护也可以过度承诺在这种情况下只有父级可用的资源在子级中受到保护 保护范围是[0, max]默认为0即无操作 由于保护措施可能被过度承诺所有配置组合都是有效的没有理由拒绝配置更改或流程迁移 memory.low实现尽力内存保护 分配 一个cgroup被专门分配一定数量的有效资源分配不能过度承诺——子组的分配总和不能超过父组的可用资源量 分配范围是[0, max]默认为0表示没有资源 由于分配不能过度承诺因此某些配置组合无效应予以拒绝。此外如果资源对于流程的执行是必需的则流程迁移可能会被拒绝 cpu.rt.max硬分配实时切片就是此类型的一个例子 约定 单个功能的设置应包含在单个文件中 根cgroup应免于资源控制因此不应该具有资源控制接口文件 默认时间单位是微妙。如果使用其他单位则必须提供明确的单位后缀 每单位数量的零件应使用百分比小数且小数部分至少为两位数 如果控制器实现基于权重的资源分配其接口文件应命名为权重范围为[1, 10000]默认值为100选择这些值是为了在两个方向上允许足够且对称的偏差同时保持直观性 如果控制器实现了绝对资源保证或限制则接口文件应分别命名为min和max。如果控制器实现了尽力资源保证或限制则接口文件应分别命名为low和high。在上述四个文件的应使用特殊标记max来表示读写向上无穷大 如果设置具有可配置的默认值和键入的特定覆盖则默认条目应以default键入并作为文件中的第一个条目出现。可以通过写入defaul VAL 或 $VAL来更新默认值。当写入以更新特定覆盖时可以使用defaul值来指示删除覆盖。读取时不得出现以default作为值的覆盖条目 cat cgroup-example-interface-file output: default 150 8:0 300 echo default 125 cgroup-example-interface-file echo 8:16 170 cgroup-example-interface-file cat cgroup-example-interface-file output: default 125 8:16 170对于频率不是很高的事件应创建一个接口文件events列出事件键值对。每当发生可通知的事件时应在文件上生成文件修改事件 已弃用的 v1 核心功能 不支持包括命名层次在内的多重层次。不支持所有 v1 挂载选项。“tasks”文件被删除并且“cgroup.procs”未排序。“cgroup.clone_children” 已被删除。/proc/cgroups 对于 v2 来说毫无意义。请改用根目录中的“cgroup.controllers”文件。 核心接口文件 所有cgroup核心接口文件都以cgroup为前缀 cgroup.type 存在于非root cgroup上的读写单值文件 读取时表示该cgroup当前的类型可以是下列值之一 domain正常有效的域cgroupdomain threaded作为线程子树根的线程域cgroupdomain invalid处于无效状态的cgroup无法填充或启用控制器可能允许其成为线程cgroupthreaded线程cgroup是线程子树的成员 通过将threaded写入此文件可以将cgroup转变为线程cgroup cgroup.procs 所有cgroup上都存在的读写换行分隔值文件 读取时它会列出属于该cgroup的所有进程的PID每行一个。PID不是按顺序排序的如果进程被移动到另一个cgroup后又移回来或者读取时PID被回收则同一个PID可能会出现多次 可以写入PID以将与PID关联的进程迁移到cgroup。写入者应满足以下所有条件 它必须对cgroup.procs文件具有写权限它必须对源和目标cgroups 的共同祖先的cgroup.procs文件具有写访问权限 当委派子层次结构时应与包含目录一起授予对此文件的写访问权限 在线程cgroup中的 由于所有进程都属于线程根因此读取此文件失败并出现EOPNOTSUPP。支持写入并将进程的每个线程移至cgroup cgroup.threads 所有cgroup上都存在的读写换行分隔值文件 读取时它会以每行一个的方式列出属于该cgroup的所有线程的TID。TID是无序的如果线程被移动到另一个cgroup然后又移回或者读取时TID被回收则同一个TID可能回出现多次 可以写入TID以将与TID关联的线程迁移到cgroup写入者应满足以下所有条件 它必须对cgroup.threads文件具有写权限线程当前所在的cgroup必须与目标cgroup位于同一资源域中它必须对源和目标cgroups共同祖先的cgroup.procs文件具有写访问权限 cgroup.controllers 所有cgroup上都存在的只读空格分隔值文件 它显示了cgroup可用的所有控制器的空格分隔值列表。控制器没有排序 cgroup.subtree_control 所有cgroup上都存在的可读写空格分隔值文件。初始为空 读取时它会显示以空格分割的控制器列表这些控制器被启用来控制从cgroup到其子组的资源分配 可以写入以空格分隔的带有或-前缀的控制器列表来启用或禁用控制器。带有前缀的控制器名称将启用该控制器带有-前缀的控制器名称将禁用该控制器。如果控制器在列表中出现多次则最后一个有效。当指定多个启用和禁用操作时要么全部成功要么全部失败 cgroup.event 存在于非root cgroup上的只读平键文件。定义了以下条目。除非另有说明否则此文件中的值更改会生成文件修改事件 populated如果cgroup或其他后代包含任何活动进程则为1否则为0frozen如果cgroup被冻结则为1否则为0 cgroup.max.descendants 读写单值文件。默认值为max 允许的最大后代cgroup数量。如果实际后代数量相等或更大则在层次结构中创建新cgroup的尝试将失败 cgroup.max.deep 读写单值文件。默认值为max 当前cgroup下允许的最大下降深度。如果实际下降深度等于或大于该值则尝试创建新的子cgroup将失败 cgroup.stat 具有以下条目的只读平键文件 nr_descendants可见后代cgroup的总数nr_dying_descendants濒临消亡的后代cgroup总数。cgroup在被用户删除后将处于濒临消亡状态。cgroup将在一段未定义的时间内可能取决于系统负载保持濒临消亡状态然后才会被彻底销毁。任何情况下进程都不能进入正在垂死的cgroup正在垂死的cgroup也无法复活。正在消亡的cgroup所消耗的系统资源不得超过其删除cgroup时所允许的限制 cgroup.freeze 存在于非root cgroup中的读写单值文件。允许的值为0和1。默认值为0 将1写入文件会导致cgroup及其所有后代cgroup被冻结。这意味着所有附属进程都将停止直到cgroup明确解冻后才会运行。cgroup的冻结可能需要一些时间此操作完成后cgroup.events控制文件中的frozen值将更新为1并发出相应的通知 cgroup可以通过其自身设置或任何祖先cgroup的设置进行解冻。如果任何祖先cgroup被解冻则cgroup将保持冻结状态 冻结cgroup中的进程可以通过致命信号终止。它们还可以进入和离开冻结cgroup要么通过用户的明确移动要么冻结cgroup与fork()竞争。如果将进程移动到冻结cgroup它将停止如果将进程移出冻结cgroup它将变为运行状态 cgroup的冻结状态不会影响任何cgroup树操作可以删除冻结的cgroup也可以创建新的子cgroup cgroup.kill 存在于非root cgroup中的只写单值文件。唯一允许的值是1 将1写入文件会导致cgroup及其所有后代cgroup被终止。这意味着受影响的cgroup树种的所有进程都将通过SIGKILL终止 终止cgroup树将适当地处理并发分叉并防止迁移 在线程cgroup中由于终止cgroup是一个进程定向操作即它会影响整个线程组因此写入此文件会因EOPNOTSUPP而失败 cgroup.pressure 允许值为0和1的读写单值文件。默认值为1 向文件写入0将禁用cgroup PSI记。向文件写入1将重新启用cgroup PSI。 此控制属性不是分层的因此在cgroup中禁用或启用PSI不会影响后代中的PSI并且不需要通过来自root cgroup传递启用 irq.pressure 读写嵌套键文件 显示IRQ/SOFTIRQ的压力失速信息。有关详细信息请参阅https://www.kernel.org/doc/html/latest/accounting/psi.html#psi 控制器接口文件 CPU 警告 cgroup2尚不支持实时进程的控制。对于启用了CONFIG_RT_GROUP_SCHED选项以对实时进程进行组调度的内核只有当所有RT进程都在根cgroup中时才能启用cpu控制器。如果禁用了CONFIG_RT_GROUP_SCHED则此限制不适用。请注意系统管理软件可能已在系统启动过程中将RT进程放入非root cgroup并且可能需要将这些进程移动到root cgroup然后才能使用启用了CONFIG_RT_GROUP_SCHED的内核启用cpu控制器 注意 所有时间长度均以微妙为单位 cpu.stat 只读平键文件。无论控制器是否启用此文件都存在 它始终报告以下三个统计数据 usage_usecCPU使用时间user_usecCPU用户态时间system_usecCPU内核态时间 当控制器启用时还有以下五个统计数据 nr_periods调度周期的总数nr_throttled进程被限制(throttled)的次数throttled_usec进程被限制的总时间nr_bursts发生的burst事件的次数。burst事件是指在短时间内CPU使用率突然增加的情况burst_usecburst事件的总时间 cpu.weight 存在于非root cgroup上的读写单值文件。默认值为100 对于非空闲组(cpu.idle 0)权重在范围内[1, 10000] 如果cgroup已配置为SCHED_IDLE(cpu.idle 1)则权重将显示为0 cpu.weight.nice 存在于非root cgroup上的读写单值文件。默认值为0 nice值的范围是[-20, 19] 此接口文件是cpu.weight的替代接口允许使用 nice(2)使用的相同值读取和设置权重。由于nice值的范围较小粒度较粗因此读取的值是当前权重的最接近近似值 nice(2)是一个系统调用用于设置进程的优先级优先级决定了进程在系统资源特别是CPU时间分配中的优先顺序。nice值的范围通常是从-20到19值越小表示越高优先级 cpu.max 存在于非root cgroup上的读写双值文件。默认值为 max 100000 最大带宽限制。其格式如下 $MAX $PERIOD表示该组在每个$PERIOD期间最多可以消费$MAX。$MAX中的max表示没有限制如果只写一个数字则更新$MAX cpu.max.burst 存在于非root cgroup上的读写单值文件。默认值为0 burst范围在[0, $MAX]内 cpu.pressure 读写嵌套键文件 显示CPU的压力失速信息。有关详细信息请参阅https://www.kernel.org/doc/html/latest/accounting/psi.html#psi cpu.uclamp.min 存在于非root cgroup上的读写单值文件。默认值为0即不提高利用率 所请求的最低利用率保护以百分比的有理数表示例如12,34表示12.34% 此接口允许读取和设置类似于sched_setattr(2)的最小利用率限制值。此最小利用率值用于限制特定任务的最小利用率限制 请求的最小利用率(保护)始终受最大利用率(限制)的当前值限制即cpu.uclamp.max cpu.uclamp.max 存在于非root cgroup上的读写单值文件。默认值为max 请求的最大利用率限制以百分比有理数表示例如98.76表示98.76% 此接口允许读取和设置类似于sched_setatrt(2)的最大利用率限制值此最大利用率值用于限制特定任务的最大利用率限制 cpu.idle 存在于非root cgroup上的读写单值文件。默认值为0 这是cgroup中每个任务的SCHD_IDLE调度策略的模拟。将此值设置为1将使cgroup的调度策略成为SCHED_IDLE。cgroup中的线程将保留其自己的相对优先级但cgroup本身将被视为相对于其他同类而言优先级非常低 memory memory控制器调节内存的分配。内存是有效状态的并实现限制和保护模型。由于内存使用和回收压力相互交织以及内存的状态特性分配模型相对复杂 虽然并非完全无懈可击但特定cgroup的所有主要内存使用情况都会得到跟踪以便可以合理地计算和控制总内存消耗。目前会跟踪以下类型的内存使用情况 Userland memory页面缓存和匿名内存Kernel data structuresdentry和inodeTCP套接字缓存区 为了覆盖范围更广上述列表将来可能会扩大 所有内存量均以字节为单位。如果写入的值为与PAGE_SIZE对齐则读回该值可能会向上舍入为最接近的PAGE_SIZE倍数 memory.current 存在于非root cgroup上的只读单值文件 该cgroup及其后代当前正在使用的内存总量 memory.min 存在于非root cgroup上的读写单值文件。默认值为0 硬内存保护。如果cgroup的内存使用量在其有效最小边界内则在任何情况下都不会回收该cgroup的内存。如果没有可用的不受保护的可回收内存则会调用OOM终止程序。如果超过出有效最小边界(或有效低边界如果有效低边界更高)则会按超额比例回收页面从而减少超额较小的回收压力 有效最小边界受到所有祖先cgroup的memory.min值限制。如果存在memory,min过量使用子cgroup或cgroup需要的受保护内存多于父cgroup允许的内存则每个子cgroup将获得父cgroup的保护部分该部分保护与其实际内存使用量低于memory.min的比例成正比 不鼓励在此保护下放置超过通常可用的内存并且可能会导致持续的OOM 如果memory cgroup中没有进程 则会忽略其memory.min memory.low 存在于非root cgroup上的读写单值文件。默认值为0 尽力保护内存如果cgroup的内存使用量在其有效低边界内则除非未受保护的cgroup中没有可回收内存否则不会回收该cgroup的内存。如果超出有效低边界或有效最小边界如果有效最小边界更高则会根据超额部分按比例回收页面从而减少超额部分的回收压力 有效低边界受所有祖先cgroup的memory.low值限制。如果存在memory.low过度使用字cgroup或cgorup需要的受保护内存多于父cgroup允许的内存则每个子cgroup将获得与其实际内存使用量低于memory.low成比例的父cgroup保护部分 不鼓励在此保护下放置超过通常可用的内存 memory.high 存在于非root cgroup上的读写单值文件。默认值为max 内存使用限制如果cgroup的使用量超出上限则cgroup的进程将受到限制并承受巨大的回收压力 超过上限不会调用OOM终止程序在极端情况下可能会突破限制。在外部进程监控受限cgroup以缓解沉重的回收压力的情况下应使用上限 memory.max 存在于非root cgroup上的读写单值文件。默认值为max 内存使用硬限制。这是限制cgroup内存使用的主要机制。如果cgroup的内存使用量达到此限制且无法降低则会在cgroup中调用OOM killer。在某些情况下 使用量可能会暂时超过限制 在默认配置下常规0阶分配总是会成功。调用者可以以不同的方式重试它们以-ENOMEM的形式返回到用户空间或者在磁盘预读等情况下默默忽略 memory.reclaim 所有cgroup都存在的只写嵌套键文件 这是一个在目标cgroup中触发内存回收的简单接口 此文件接受单个键即要回收的字节数目前不支持嵌套键 例子 echo 1G memory.reclaim稍后可以使用嵌套键扩展接口以配置回收行为。例如指定要回收的内存类型匿名、文件等 注意内核可能会从目标cgroup中过度或不足地回收。如果回收的字节数少于指定的数量则返回-EAGAIN 注意主动回收由此接口触发并不意味着指示内存cgroup上的内存压力。因此在这种i情况下通常不会执行由内存回收触发的套接字内存平衡。这意味着网络层不会根据由memory.reclaim引起的回收进行调整 memory.peak 存在于非root cgroup上的只读单值文件 自cgroup创建以来记录的cgroup及其后代的最大内存使用量 memory.oom.group 存在于非root cgroup上的读写单值文件。默认值为0 确定OOM终止程序是否应将cgroup视为不可分割的工作负载。如果设置则属于该cgroup或其后代如果内存cgroup不是叶cgroup的所有任务都会一起终止或根本不终止。这可用于避免部分终止以保证工作负载的完整性 具有OOM保护oom_score_adj设置为-1000的任务被视为异常并且永远不会被终止 如果在cgroup中调用OOM终止程序它将不会终止该cgroup之外的任何任务无论祖先cgroup的memory.oom,group值如何 memory.events 存在于非root cgroup上的只读平键文件。定义了以下条目。除非另有说明否则此文件中的值更改会生成文件修改事件。 注意此文件中的所有字段都是分层的文件修改事件可能由于层次结构下方的事件而生成。有关cgroup级别的本地事件请参阅memory.events.local low尽管cgroup的使用率低于低限但由于内存压力过大而被回收的次数。这通常表示低限已过度使用high由于超出高内存边界cgroup的进程被限制并路由以执行直接内存回收的次数。对于内存使用量受高限而非全局内存压力限制的cgroup此事件的发生是意料之中的maxcgroup的内存使用量即将超过最大边界的次数。如果直接回收无法降低内存使用量则cgroup会进入oom状态oomcgroup内存使用量达到限制且分配即将失败的次数。如果不将oom killer视为一个选项例如高阶分配失败或要求调用者不要重试则不会引发此事件。oom_kill属于此cgroup的被任何类型的OOM终止程序终止的进程数记录的是尝试杀死的进程数量而不是实际被杀死的进程数量oom_group_kill发生组oom的次数 memory.events.local 与memory.events类似但文件中的字段是cgroup本地的即不是分层的。在此文件上生成的文件修改仅反映本地事件 memory.stat 存在于非root cgroup上的只读平键文件 这将cgroup的内存占用分解为不同类型的内存、特定于类型的详细信息以及有关内存管理系统的状态和过去事件的其他信息 所有内存量均以字节为单位 条目按顺序排列便于阅读新条目可以显示在中间。不要依赖保持在固定位置的项目使用键来查找特定值 如果条目没有每个节点的计数器或者没有显示在memory.numa_stat中。使用npn(non-per-node)作为标记表示它不会显示在memory.numa_stat中 anon匿名映射如brk()、sbrk()和mmap(MAP_ANONYMOUS)中使用的内存量file用于缓存文件系统数据的内存量包括tmpfs和共享内存kernel(npn)内核总内存总量包括(kernel_stack、pagatables、percpu、vmalloc、slab)以及其他内核内存用例kernerl_stack分配给内核栈的内存量pagetables为页表分配的内存量sec_pagetables为辅助页表分配的内存量目前包括x86和arm64的KVM页表分配以及IOMMU页表percpu(npn)用于存储每个cpu内核数据结构的内存量sock(npn)网络传播缓冲区使用的内存量vmalloc(npn)用于vmap支持内存的内存量shmem由交换支持的缓存文件系统数据量例如tmpfs、shm段、共享匿名mmap()zswapzswap压缩后端消耗的内存量zswapped换出zswap的应用程序内存量file_mapped使用mmap()映射的缓存文件系统数据量file_dirty已修改但尚未写回磁盘的缓存文件系统数据量file_writeback已修改且当前正在写回磁盘的缓存文件系统数据量swapcached内存中缓存的交换空间量 交换缓存会考虑内存和交换空间的使用情况anon_thp透明hugepage支持的匿名映射中的内存量file_thp透明hugepage支持的缓存文件系统数据量shmem_thp透明hugepage支持吃的shm、tmpgs和共享匿名mmap()的数量inactive_anonactive_anoninactive_fileactive_file unevictable页面回收算法使用的内部内存管理列表上的内存量交换支持和文件系统支持。由于这些代表内部列表状态例如shmem页面位于匿名内存管理列表上inactive_foo active_foo可能不等于foo计数器的值因为foo计数器是基于类型的不是基于列表的slab_reclaimable可能被回收的slab的一部分例如dentry和inodeslab_unreclaimable由于内存压力部分slab无法被回收slab(npn)用于存储内核数据结构的内存量workingset_refault_anon先前驱动的匿名页面的错误数workingset_refault_file先前逐出的文件页面的错误数workingset_activate_anon立即激活的匿名页面的数量workingset_activate_file立即激活的默认文件页面数workingset_restore_anon在回收之前被检测为活动工作集的已恢复匿名页面的数量workingset_restore_file在回收之前被检测为活动工作集的已还原文件页面的数量wokingset_noderecalim影子节点被回收的次数pgscan(npn)扫描页面的数量在非活动LRU列表中pgsteal(npn)回收页面数量pgscan_kswapd(npn)按kswapd扫描的页面数量在非活动LRU列表中pgscan_direct(npn)直接扫描的页面数量在非活动LRU列表中pgscan_khugepaged(npn)按khugepage扫描的页面数量在非活动LRU列表中pgsteal_kswapd(npn)按kswapd计算的回收页面数量pgsteal_direct(npn)直接回收的页面数量pgsteal_khugepaged(npn)按khugepage计算的回收页面数量pgfault(npn)发生的页面错误总数pgmajfault(npn)发生的主要页面错误的数量pgrefill(npn)扫描页面的数量在非活动LRU列表中pgactivate(npn)移动到活动LRU列表的页面数量pgdeactivate(npn)移动到非活动LRU列表的页面数量pglazyfree(npn)在内存压力下延迟释放的页面数量pglazyfreed(npn)回收无惰性页面的数量zswpin从zswap移动到内存中的页面数zswpout从内存移动到zswap的页面数zswpwb从zswap写入到swap的页面数thp_fault_alloc (npn)为满足页面错误而分配的透明hugepage数。当CONFIG_TRANSPARENT_HUGEPAGE未设置时此计数器不存在thp_collapse_alloc (npn)为允许折叠现有页面范围而分配的透明hugepage数。当CONFIG_TRANSPARENT_HUGEPAGE未设置时此计数器不存在thp_swpout (npn)透明hugepage的数量在一块交换而不分裂thp_swpout_fallback (npn)在交换之前被分割的透明hugepage的数量。通常是一因为没有巨大的页面分配一些连续的交换空间 memory.numa_stat 存在于非root cgroup上的只读嵌套键文件 这会将cgroup的内存占用分解未不同类型的内存、特定于类型的详细信息以及有关内存管理系统状态的每个节点的其他信息 这对于提供memcg中的NUMA位置信息的可见性非常有用因为允许从任何物理节点分配页面。其中一个用例是通过将这些信息与应用程序的CPU分配相结合来评估应用程序性能 所有内存量均以字节为单位 memory.numa_stat的输出格式为 type N0bytes in node 0 N1bytes in node 1 ...memory.swap.current 存在于非root cgroup上的只读单值文件 该cgroup及其后代当前正在使用的交换总量 memory.swap.high 存在于非root cgroup上的读写单值文件。默认值为max 交换使用限制如果cgroup的交换使用量超出此限制。则其所有进一步的分配都将受到限制以允许用户空间实施自定义的内存不足程序 此限制标志着cgroup的不可逆转点。它并非设置用于管理工作负载在正常运行期间进行的交换量。与memory.swap.max相比后者进制交换量超过设定值但只要其他内存可以回收cgroup就可以不受阻碍地继续运行 memory.swap.peak 存在于非root cgroup上的只读单值文件 自cgroup创建以来记录的cgroup及其后代的最大交换使用情况 memory.swap.max 存在于非root cgroup上的读写单值文件默认值为max 交换使用硬限制。如果cgroup的交换使用量达到此限制则不会将cgroup的匿名内存换出 memory.swap.events 存在于非root cgroup上的只读平键文件。定义了以下条目。除非另有说明否则此文件中的值更改会生成文件修改事件 highcgroup的交换使用量超出高阈值的次数maxcgroup的交换使用量即将超出最大边界且交换分配失败的次数fail由于系统范围内的交换空间用尽或最大限制而导致交换分配失败的次数 当在当前使用率下减少时现有的交换条目将逐渐被回收并且交换使用率可能在较长时间内保持高于限制着减少了对工作负载和内存管理的影响 memory.zswap.current 存在于非root cgroup上只读单值文件 zswap压缩后端消耗的内存总量 memory.zswap.max 存在于非root cgroup上的读写单值文件。默认值为max zswap使用硬限制。如果cgroup的zswap池达到此限制它将拒绝在现有条目故障恢复或写入磁盘之前接受任何存储 memory.zswap.writeback 可读写的单值文件。默认值为1。root cgroup的初始值为1当创建新的cgroup时它会继承其父级的当前值。 当设置为0时所有交换设备的尝试都被禁用。这包括zswap写回和由于zswap存储失败而进行的交换。如果zswap存储失败重复曾发生例如如果页面不可压缩用户可以在禁用写回后观察到回收效率低下因为相同的页面可能会一次又一次被拒绝 注意这与设置memory.swap.max为0有细微的差别因为它仍然允许页面写入zswap池 memory.pressure 只读的嵌套键文件 显示内存的压力失速信息。详情看https://www.kernel.org/doc/html/latest/accounting/psi.html#psi 使用指南 memory.high是控制内存使用的主要机制。在上限上过度承诺上限总和 可用内存并让全局内存压力根据使用情况分配内存是一种可行的策略 由于违反高限制不会触发OOM killer但会限制有问题的cgroup因此管理代理有充足的机会监控并采取适当的措施例如授予更多的内存或终止工作负载 确定cgroup是否有足够的内存并非易事因为内存使用情况并不能表明工作负载是否可以从更多内存中受益。例如将从网络接收的数据写入文件的工作负载可以使用所有可用内存但也可以使用少量内存运行。内存压力的衡量标准由于内存不足、工作负载受到的影响有多大对于确定工作负载是否需要更多内存是必要的不幸的是内存压力监控机制尚未实现 内存所有权 内存区域由实例化它的 cgroup 占用并保持由该 cgroup 占用的状态直到该区域被释放。将进程迁移到其他 cgroup 不会将其在前一个 cgroup 中实例化的内存使用量移动到新 cgroup。 一个内存区域可能被属于不同 cgroup 的进程使用。该区域将归属于哪个 cgroup 尚不确定但是随着时间的推移该内存区域很可能会归属于具有足够内存余量的 cgroup以避免高回收压力。 如果一个 cgroup 清除了大量的内存而这些内存预计会被其他 cgroup 重复访问那么使用 POSIX_FADV_DONTNEED 放弃受影响文件的内存区域的所有权以确保正确的内存所有权可能是有意义的。 IO io控制器控制io资源的分配。此控制器可实现基于权重和绝对带宽或IOPS限制的分配但是只有使用cfq-iosched时才可以使用基于权重的分配并且这两种方案都不适用于blk-mq设备 io.stat 只读的嵌套键文件 行由$MAJ:$MIN设备编号键控且无序。定义了以下嵌套键 rbytes读取的字节数wbytes写入的字节数rios读取IO数量wios写IO次数dbytes丢弃的字节数dios丢弃IO数 io.cost.qos 仅存在于root cgroup上的读写嵌套键文件 此文件配置基于IO成本模型的控制器(CONFIG_BLK_CGROUP_IOCOST)的服务质量该控制器当前实施io.weight比例控制。行由$MAX:$MIN设备编号键控且无序。给定设备的行在io.cost.qos或io.cost.model上首次写入设备时填充。定义了 以下嵌套键 enable是否开启blk-iocost控制器ctrl“auto或user”rpct读取延迟百分位数[0, 100]rlat读取延迟阈值wpct写入延迟百分位数[0, 100]wlat写入延迟阈值min最小速率调整比例[1, 10000]max最大缩放百[1, 10000] 该控制器默认是禁用的 可以通过enable设置为1来启用它。rcpt和wpct参数默认是0控制器使用内部设备饱和状态在max和min之间调整整体IO速率 当需要更好地控制质量时可以配置延迟QoS参数。例如 8:16 enable1 ctrlauto rpct95.00 rlat75000 wpct95.00 wlat150000 min50.00 max150.0显示在sdb上控制器已启用如果读取完成延迟的第95个百分位数高于75毫秒或写入150毫秒则将认为设备已饱和并相应地将整体IO发出率调整为50%到150%之间 饱和点越低延迟QoS越好但代价是总带宽。max和min之间允许的调整范围越窄IO行为越符合成本模型。注意IO发出基本速率可能远离100%盲目设置min和max可能会导致设备容量或控制质量的显著损失。min和max对于调节表现出广泛临时行为变化的设备很有用——例如ssd以线路速度接受写入一段时间然后完全停止数秒 当“ctrl”为“auto”时参数由内核控制可能会自动更改。将“ctrl”设置为“user”或设置任何百分位数和延迟参数都会将其置于“user”模式并禁用自动更改。可以通过将“ctrl”设置为“auto”来恢复自动模式。 io.cost.model 仅存在于root cgroup 上的读写嵌套键文件。 此文件配置基于 IO 成本模型的控制器 (CONFIG_BLK_CGROUP_IOCOST) 的成本模型该控制器当前实施“io.weight”比例控制。行由 $MAJ:$MIN 设备编号作为键且无序。给定设备的行在“io.cost.qos”或“io.cost.model”上首次写入设备时填充。定义了以下嵌套键 ctrl“auto” or “user”model使用的成本模型 - “linear” 当“ctrl”为“auto”时内核可以动态更改所有参数。当“ctrl”设置为“user”或写入任何其他参数时“ctrl”变为“user”自动更改将被禁用。 当“模型”为“线性”时定义以下模型参数 [r|w]bps最大连续 IO 吞吐量[r|w]seqiops每秒最大 4k 顺序 IO[r|w]randiops每秒最大 4k 随机 IO 从上文可以看出内置线性模型确定了顺序和随机 IO 的基本成本以及 IO 大小的成本系数。虽然简单但该模型可以令人满意地覆盖大多数常见设备类别。 IO 成本模型不一定绝对准确并且会根据设备行为动态缩放。 如果需要可以使用 tools/cgroup/iocost_coef_gen.py 来生成特定于设备的系数。 io.weight 存在于非 root cgroup 上的读写平键文件。默认值为“default 100”。 第一行是应用于设备的默认权重没有特定的覆盖。其余的覆盖由 $MAJ:$MIN 设备编号键入且无序。权重在 [1, 10000] 范围内指定 cgroup 相对于其同级可以使用的相对 IO 时间量。 可以通过写入“default $WEIGHT”或简单的“​$WEIGHT”来更新默认权重。可以通过写入“$MAJ:$MIN ​$WEIGHT”来设置覆盖并通过写入“​$MAJ:$MIN default”来取消设置。 注意需要先在root cgroup启用特定设备的io.cost.qos才能将设备填充到io.weight例如 ehco 8:0 enabled1 ctrlauto io.cost.qosio.max 存在于非 root cgroup 上的读写嵌套键文件。 基于 BPS 和 IOPS 的 IO 限制。行由 $MAJ:$MIN 设备编号键控且无序。定义了以下嵌套键: rbps每秒最大读取字节数wbps每秒最大写入字节数riops每秒最大读取 IO 操作数wiops每秒最大写入 IO 操作数 写入时可以以任意顺序指定任意数量的嵌套键值对。可以指定“max”作为值来删除特定限制。如果多次指定相同的键则结果不确定。 在每个 IO 方向上测量 BPS 和 IOPS如果达到限制IO 会延迟。允许临时突发。 将读取限制设置为 2M BPS并将写入限制设置为 120 IOPS设备为 8:16 echo 8:16 rbps2097152 wiops120 io.max可以通过写入以下内容来消除写入 IOPS 限制 echo 8:16 wiopsmax io.maxio.pressure 只读的嵌套键文件。 显示 IO 的压力失速信息。有关详细信息请参阅 Documentation/accounting/psi.rst。 写回 页面缓存通过缓冲写入和共享 mmap 被弄脏并通过写回机制异步写入到后备文件系统。写回位于内存和 IO 域之间通过平衡弄脏和写入 IO 来调节脏内存的比例。 io 控制器与内存控制器一起实现对页面缓存写回 IO 的控制。内存控制器定义计算和维护脏内存比率的内存域io 控制器定义写出内存域脏页的 io 域。系统范围和每个 cgroup 的脏内存状态都会被检查并强制执行两者中限制性更强的那个。 cgroup 写回需要底层文件系统的明确支持。目前cgroup 写回已在 ext2、ext4、btrfs、f2fs 和 xfs 上实现。在其他文件系统上所有写回 IO 都归属于根 cgroup。 内存和写回管理存在固有差异这会影响跟踪 cgroup 所有权的方式。内存按页跟踪而写回按 inode 跟踪。为了进行写回将 inode 分配给 cgroup并且从 inode 写入脏页的所有 IO 请求都归属于该 cgroup。 由于内存的 cgroup 所有权是按页跟踪的因此可能存在与 inode 所关联的 cgroup 不同的页面。这些页面称为外部页面。写回会不断跟踪外部页面如果某个外部 cgroup 在一段时间内成为多数则会将 inode 的所有权切换为该 cgroup。 虽然此模型足以满足大多数用例即即使主写入 cgroup 随时间发生变化给定的 inode 也主要被单个 cgroup 弄脏但多个 cgroup 同时写入单个 inode 的用例无法得到很好的支持。在这种情况下很大一部分 IO 可能会被错误地归因。由于内存控制器在第一次使用时分配页面所有权并且在页面释放之前不会更新它即使写回严格遵循页面所有权多个 cgroup 弄脏重叠区域也不会按预期工作。建议避免这种使用模式。 影响写回行为的 sysctl 旋钮应用于 cgroup 写回如下所示 vm.dirty_background_ratiovm.dirty_ratio这些比率同样适用于 cgroup 写回其中可用内存量受内存控制器和系统范围的干净内存所施加的限制。vm.dirty_background_bytesvm.dirty_bytes对于 cgroup 写回这是根据总可用内存的比例计算的并且以与vm.dirty[_background]_ratio 相同的方式应用。 IO延迟 这是用于 IO 工作负载保护的 cgroup v2 控制器。您为组提供一个延迟目标如果平均延迟超过该目标控制器将限制任何延迟目标低于受保护工作负载的对等体。 这些限制仅适用于层次结构中的同级级别。这意味着在下图中只有组 A、B 和 C 会相互影响组 D 和 F 会相互影响。组 G 不会影响任何人 [root]/ | \A B C/ \ | D F G因此配置此设置的理想方法是在 A、B 和 C 组中设置 io.latency。通常您不希望设置低于设备支持的延迟的值。通过实验找到最适合您的工作负载的值。从高于设备预期延迟开始观察 io.stat 中工作负载组的 avg_lat 值以了解正常运行期间看到的延迟。使用 avg_lat 值作为实际设置的基础设置为比 io.stat 中的值高 10-15%。 IO延迟节流如何工作 io.latency 是节省工作量的因此只要每个人都达到其延迟目标控制器就不会做任何事情。一旦某个组开始未达到其目标它就会开始限制任何目标比其更高的对等组。这种限制有两种形式 Queue depth throttling这是允许一个组拥有的未完成 IO 数量。我们将相对较快地进行限制从无限制开始一直到每次 1 个 IO。Artificial delay induction某些类型的 IO 无法节流否则可能会对更高优先级的组产生不利影响。这包括交换和元数据 IO。这些类型的 IO 可以正常发生但它们会被“收取”到原始组的费用。如果原始组受到节流您将看到 io.stat 中的 use_delay 和 delay 字段增加。延迟值是添加到此组中运行的任何进程的微秒数。由于如果发生大量交换或元数据 IO这个数字可能会变得非常大因此我们将单个延迟事件限制为每次 1 秒。 一旦受害组再次开始满足其延迟目标它将开始解除之前被限制的任何对等组的限制。如果受害组只是停止执行 IO全局计数器将适当解除限制。 IO延迟接口文件 io.latency这采用与其他控制器类似的格式。“MAJOR:MINOR target目标时间微秒”io.stat如果启用了控制器除了正常的统计数据之外您还将在 io.stat 中看到额外的统计数据。 depth这是该组的当前队列深度。avg_lat这是一个指数移动平均数衰减率为 1/exp受采样间隔限制。衰减率间隔可以通过将 io.stat 中的 win 值乘以基于 win 值的相应采样数来计算。win采样窗口大小以毫秒为单位。这是评估事件之间的最短持续时间。窗口只会随着 IO 活动而流逝。空闲期会延长最近的窗口。 IO优先级 单个属性控制 I/O 优先级 cgroup 策略的行为即 io.prio.class 属性。该属性接受以下值 no-change请勿修改 I/O 优先级类。promote-to-rt对于具有非 RT I/O 优先级类的请求将其更改为 RT。同时将这些请求的优先级更改为 4。不要修改优先级类为 RT 的请求的 I/O 优先级。restrict-to-be对于没有 I/O 优先级类别或 I/O 优先级类别为 RT 的请求将其更改为 BE。同时将这些请求的优先级更改为 0。不要修改优先级类别为 IDLE 的请求的 I/O 优先级类别。idle将所有请求的 I/O 优先级类别更改为最低的 I/O 优先级类别 IDLE。none-to-rt已弃用。只是promote-to-rt的别名 以下数值与 I/O 优先级策略相关 no-change0promote-to-rt1restrict-to-be2idle3 每个 I/O 优先级对应的数值如下 IOPRIO_CLASS_NONE0IOPRIO_CLASS_RT实时1IOPRIO_CLASS_BE尽力而为2IOPRIO_CLASS_IDLE3 设置请求的 I/O 优先级的算法如下 若I/O优先级类别策略为promote-to-rt则将请求I/O优先级类别更改为IOPRIO_CLASS_RT并将请求I/O优先级更改为4。如果 I/O 优先级类别策略不是promote-to-rt则将 I/O 优先级类别策略转换为数字然后将请求 I/O 优先级类别更改为 I/O 优先级类别策略编号和数值 I/O 优先级类别中的最大值。 PID 进程号控制器用于允许 cgroup 在达到指定的限制后停止对任何新任务进行 fork() 或 clone()。 cgroup 中的任务数量可能会以其他控制器无法阻止的方式耗尽因此需要自己的控制器。例如fork 炸弹很可能在达到内存限制之前耗尽任务数量。 请注意此控制器中使用的 PID 指的是内核使用的 TID进程 ID。 pids.max 存在于非 root cgroup 上的读写单值文件。默认值为“max”。进程数量的硬性限制。 pids.current 存在于非 root cgroup 上的只读单值文件。cgroup 及其后代中当前的进程数。 pids.peak 存在于非 root cgroup 上的只读单值文件。该 cgroup 及其后代进程数曾达到的最大值。 pids.events 存在于非 root cgroup 上的只读平键文件。除非另有说明否则此文件中的值更改会生成文件修改事件。定义了以下条目 maxcgroup 的总进程数达到 pids.max 限制的次数另请参阅 pids_localevents。 pids.events.local 与 pids.events 类似但文件中的字段是 cgroup 本地的即不是分层的。在此文件上生成的文件修改事件仅反映本地事件。 组织操作不受 cgroup 策略的阻止因此 pids.current pids.max 是可能的。这可以通过将限制设置为小于 pids.current 或将足够多的进程附加到 cgroup 以使 pids.current 大于 pids.max 来实现。但是不可能通过 fork() 或 clone() 违反 cgroup PID 策略。如果创建新进程会导致违反 cgroup 策略则这些将返回 -EAGAIN。 cpuset “cpuset”控制器提供了一种机制用于将任务的 CPU 和内存节点放置限制为仅任务当前 cgroup 中的 cpuset 接口文件中指定的资源。这在大型 NUMA 系统中尤其有用在这些系统中将作业放置在适当大小的系统子集上并仔细放置处理器和内存以减少跨节点内存访问和争用可以提高整体系统性能。 “cpuset” 控制器是分层的。这意味着控制器不能使用其父级中不允许的 CPU 或内存节点。 cpuset.cpus 存在于非 root cpuset 启用的 cgroup 上的读写多值文件。 它列出了此 cgroup 内的任务所请求的 CPU。但实际授予的 CPU 列表受其父级施加的限制可能与请求的 CPU 不同。 CPU 编号是用逗号分隔的数字或范围。例如 cat cpuset.cpus output: 0-4,6,8-10空值表示 cgroup 使用与具有非空“cpuset.cpus”的最近的 cgroup 祖先相同的设置如果未找到任何可用 CPU则使用所有可用的 CPU。 “cpuset.cpus” 的值保持不变直到下次更新不会受到任何 CPU 热插拔事件的影响。 cpuset.cpus.effective 所有启用 cpuset 的 cgroup 上都存在的只读多值文件。 它列出了此 cgroup 的父级实际授予其的在线 CPU。这些 CPU 允许由当前 cgroup 中的任务使用。 如果“cpuset.cpus”为空“cpuset.cpus.effective”文件将显示父 cgroup 中可供此 cgroup 使用的所有 CPU。否则它应该是“cpuset.cpus”的子集除非“cpuset.cpus”中列出的 CPU 均无法授予。在这种情况下它将被视为空的“cpuset.cpus”。 其值会受到CPU热插拔事件的影响。 cpuset.mems 存在于非 root cpuset 启用的 cgroup 上的读写多值文件。 它列出了此 cgroup 内的任务所请求的内存节点。但实际授予的内存节点列表受其父级施加的限制可能与请求的内存节点不同。 内存节点号是用逗号分隔的数字或范围。例如 cat cpuset.mems output: 0-1,3空值表示 cgroup 使用与最近的 cgroup 祖先相同的设置并且具有非空的“cpuset.mems”或所有可用的内存节点如果未找到任何内存节点。 “cpuset.mems” 的值保持不变直到下次更新不会受到任何内存节点热插拔事件的影响。 如果“cpuset.mems”当前正在使用指定节点之外的内存则将 cgroup 内的任务的内存迁移到指定节点。 这种内存迁移是有代价的。迁移可能不完整可能会遗留一些内存页。因此建议在将新任务生成到 cpuset 之前正确设置“cpuset.mems”。即使需要使用活动任务更改“cpuset.mems”也不应该频繁进行。 cpuset.mems.effective 所有启用 cpuset 的 cgroup 上都存在的只读多值文件。 它列出了此 cgroup 的父级实际授予其的在线内存节点。这些内存节点允许由当前 cgroup 内的任务使用。 如果“cpuset.mems”为空则显示父 cgroup 中可供此 cgroup 使用的所有内存节点。否则它应该是“cpuset.mems”的子集除非“cpuset.mems”中列出的任何内存节点都无法授予。在这种情况下它将被视为空的“cpuset.mems”。 其值会受到内存节点热插拔事件的影响。 cpuset.cpus.exclusive 存在于非 root cpuset 启用的 cgroup 上的读写多值文件。 它列出了允许用于创建新 cpuset 分区的所有独占 CPU。除非 cgroup 成为有效的分区根否则不会使用它的值。有关 cpuset 分区的描述请参阅下面的“cpuset.cpus.partition”部分。 当 cgroup 成为分区根时分配给该分区的实际独占 CPU 列在“cpuset.cpus.exclusive.effective”中它可能与“cpuset.cpus.exclusive”不同。如果之前已设置“cpuset.cpus.exclusive”则“cpuset.cpus.exclusive.effective”始终是其子集。 用户可以手动将其设置为不同于“cpuset.cpus”的值。设置时的一个限制是CPU 列表必须相对于其同级 cgroup 的“cpuset.cpus.exclusive”具有排他性。如果未设置同级 cgroup 的“cpuset.cpus.exclusive”则其“cpuset.cpus”值如果已设置不能是其子集以便在独占 CPU 被拿走时至少留有一个 CPU 可用。 对于父 cgroup其任何一个独占 CPU 只能分配给最多一个子 cgroup。不允许两个或多个子 cgroup 中出现独占 CPU独占性规则。违反独占性规则的值将被拒绝并出现写入错误。 根 cgroup 是分区根其所有可用 CPU 都位于其独有的 CPU 集中。 cpuset.cpus.exclusive.effective 所有启用非 root cpuset 的 cgroup 上都存在的只读多值文件。 此文件显示可用于创建分区根的有效独占 CPU 集。如果其父级不是根 cgroup则此文件的内容将始终是其父级的“cpuset.cpus.exclusive.effective”的子集。如果已设置它也将是“cpuset.cpus.exclusive”的子集。如果未设置“cpuset.cpus.exclusive”则在形成本地分区时它将被视为具有“cpuset.cpus”的隐式值。 cpuset.cpus.isolated 一个只读且仅有 root cgroup 的多个值文件。 该文件显示现有隔离分区中使用的所有隔离 CPU 的集合。如果未创建隔离分区则该文件为空。 cpuset.cpus.partition 文档说明 存在于启用非 root cpuset 的 cgroup 上的读写单值文件。此标志归父 cgroup 所有不可委托。 写入时它仅接受以下输入值 member分区的非根成员root分区根isolated无负载平衡的分区根 cpuset 分区是启用了 cpuset 的 cgroup 的集合其中分区根位于层次结构的顶部其后代除了那些本身就是独立分区根的 cgroup 及其后代位于层次结构的顶部。分区对分配给它的一组独占 CPU 具有独占访问权限。该分区之外的其他 cgroup 不能使用该组中的任何 CPU。 有两种类型的分区 - 本地分区和远程分区。本地分区的父 cgroup 也是有效的分区根。远程分区的父 cgroup 本身不是有效的分区根。对于创建本地分区写入“cpuset.cpus.exclusive”是可选的因为其“cpuset.cpus.exclusive”文件将假定一个隐式值如果未设置则该值与“cpuset.cpus”相同。对于创建远程分区必须在目标分区根之前将正确的“cpuset.cpus.exclusive”值写入 cgroup 层次结构。 目前不支持在本地分区下创建远程分区远程分区根的所有祖先根 cgroup 除外均不能成为分区根。 根 cgroup 始终是分区根其状态无法更改。所有其他非根 cgroup 都以“成员”身份开始。 当设置为“root”时当前 cgroup 是新分区或调度域的根。独占 CPU 集由其“cpuset.cpus.exclusive.effective”的值决定。 当设置为“isolated”时该分区中的 CPU 将处于隔离状态不会从调度程序进行任何负载平衡也不会被排除在未绑定的工作队列之外。放置在具有多个 CPU 的此类分区中的任务应谨慎分配并绑定到每个单独的 CPU以实现最佳性能。 分区根“根”或“隔离”可能处于两种状态之一 - 有效或无效。无效分区根处于降级状态其中可能保留一些状态信息但行为更像“成员”。 允许“成员”、“根”和“隔离”之间的所有可能的状态转换。 读取时“cpuset.cpus.partition”文件可以显示以下值 member分区的非根成员root分区根isolated无负载平衡的分区根root invalid ()分区根目录无效isolated invalid ()隔离分区根无效 如果分区根无效则会在括号内包含有关分区无效原因的描述性字符串。 为了使本地分区根有效必须满足以下条件。 父 cgroup 是有效的分区根。“cpuset.cpus.exclusive.effective”文件不能为空尽管它可能包含离线 CPU。除非没有与此分区关联的任务“cpuset.cpus.effective”不能为空。 为了使远程分区根有效必须满足除第一个条件之外的所有上述条件。 热插拔等外部事件或“cpuset.cpus”或“cpuset.cpus.exclusive”的更改可能会导致有效分区根变为无效反之亦然。请注意无法将任务移动到“cpuset.cpus.effective”为空的 cgroup。 有效的非根父分区可以在没有关联任务的情况下将其所有 CPU 分配给其子本地分区。 将有效分区根更改为“成员”时必须小心谨慎因为其所有子本地分区如果存在都将变为无效从而导致在这些子分区中运行的任务中断。如果将其父分区切换回具有“cpuset.cpus”或“cpuset.cpus.exclusive”中正确值的分区根则可以恢复这些停用的分区。 每当“cpuset.cpus.partition”的状态发生变化时就会触发 poll 和 inotify 事件。这包括写入“cpuset.cpus.partition”、CPU 热插拔或修改分区有效性状态的其他更改所导致的更改。这将允许用户空间代理监视“cpuset.cpus.partition”的意外更改而无需进行连续轮询。 用户可以使用“isolcpus”内核启动命令行选项在启动时将某些 CPU 预先配置为隔离状态并禁用负载平衡。如果要将这些 CPU 放入分区则必须在隔离分区中使用它们。 具体解释 这个文件可以被设置为root或member主要功能是用来设置当前的cgroup是不是作为一个独立的scheduling domain进行调度。这个功能其实就是可以理解为在root模式下所有分配给当前cgroup的cpu都是独占这些cpu的而member模式则可以在多个cgroup之间共享这些cpu。设置为root将使当前cgroup使用的cpu从上级cgroup的cpuset.cpus.effective列表中拿走。即上一级不能使用这个被独占的CPU了。设置为root后如果这个cgroup有下一级的cgroup这个cgroup也将不能再切换回member状态。在这种模式下上一级的cgroup不可以把自己所有的cpu都分配给其下一级的cgroup其自身至少给自己留一个cpu 设置为root需要当前cgroup符合以下条件 cpuset.cpus中设置不为空且设置的cpu list中的cpu都是独立的。就是说这些cpu不会共享给其他平级cgroup上一级cgroup是partion root配置当前cgroup的cpuset.cpus作为集合是上一级cgroup的cpuset.cpus.effective集合的子集下一级cgroup没有启用cpuset资源隔离 device 设备控制器管理对设备文件的访问。它包括创建新设备文件使用 mknod以及访问现有设备文件。 Cgroup v2 设备控制器没有接口文件是在 cgroup BPF 之上实现的。为了控制对设备文件的访问用户可以创建 BPF_PROG_TYPE_CGROUP_DEVICE 类型的 bpf 程序并使用 BPF_CGROUP_DEVICE 标志将它们附加到 cgroup。在尝试访问设备文件时将执行相应的 BPF 程序并且根据返回值尝试将成功或失败并显示 -EPERM。 BPF_PROG_TYPE_CGROUP_DEVICE 程序接受指向 bpf_cgroup_dev_ctx 结构的指针该结构描述了设备访问尝试访问类型mknod/read/write和设备类型、主编号和次编号。如果程序返回 0则尝试失败并出现 -EPERM否则尝试成功。 可以在内核源代码树中的 tools/testing/selftests/bpf/progs/dev_cgroup.c 中找到 BPF_PROG_TYPE_CGROUP_DEVICE 程序的示例。 “rdma”控制器调节RDMA资源的分配和核算。 rdma.max 除 root 之外的所有 cgroup 中都存在的读写嵌套键文件用于描述 RDMA/IB 设备当前配置的资源限制。 行按设备名称键入且无序。每行包含空格分隔的资源名称及其可分配的配置限制。 定义了以下嵌套键 hca_handle最大 HCA 句柄数hca_objectHCA 对象的最大数量 以下是 mlx4 和 ocrdma 设备的示例 mlx4_0 hca_handle2 hca_object2000 ocrdma1 hca_handle3 hca_objectmaxrdma.current 描述当前资源使用情况的只读文件。除 root 外所有 cgroup 均有此文件。 以下是 mlx4 和 ocrdma 设备的示例 mlx4_0 hca_handle1 hca_object20 ocrdma1 hca_handle1 hca_object23hugetlb HugeTLB 控制器允许限制每个控制组的 HugeTLB 使用情况并在页面错误期间强制执行控制器限制。 **hugetlb.2MB.max: ** 读写文件。设置hugepage大小为2MB的hugepage使用量限制 **hugetlb.1GB.max: ** 读写文件。设置hugepage大小为1GB的hugepage使用量限制 **hugetlb.2MB.current: ** 只读文件。显示hugepages大小为2MB的hugepage的当前使用量 **hugetlb.1GB.current: ** 只读文件。显示hugepages大小为1GB的hugepage的当前使用量 **hugetlb.2MB.rsvd.max: ** 读写文件。设置hugepage大小为2MB的hugepage预留限制 **hugetlb.1GB.rsvd.max: ** 读写文件。设置hugepage大小为1GB的hugepage预留限制 **hugetlb.2MB.rsvd.current: ** 只读文件。显示hugepages大小为2MB的hugepage的当前预留量 **hugetlb.1GB.rsvd.current: ** 只读文件。显示hugepages大小为1GB的hugepage的当前预留量 **hugetlb…2MB.events: ** 存在于非 root cgroup 上的只读平键文件包含以下字段 max由于 HugeTLB 限制导致分配失败的次数 **hugetlb.1GB.events: ** 存在于非 root cgroup 上的只读平键文件包含以下字段 max由于 HugeTLB 限制导致分配失败的次数 hugetlb.巨大页面大小.events.local 与 hugetlb.hugepagesize.events 类似但文件中的字段是 cgroup 本地的即不是分层的。在此文件上生成的文件修改事件仅反映本地事件。 hugetlb.巨大页面大小.numa_stat 与memory.numa_stat类似它显示此cgroup中hugepagesize的hugetlb页面的numa信息。仅包含正在使用的hugetlb页面。每个节点的值以字节为单位。 MISC 杂项 cgroup 为无法像其他 cgroup 资源一样抽象的标量资源提供资源限制和跟踪机制。控制器由 CONFIG_CGROUP_MISC 配置选项启用。 可以通过 include/linux/misc_cgroup.h 文件中的 enum misc_res_type{} 将资源添加到控制器并通过 kernel/cgroup/misc.c 文件中的 misc_res_name[] 将相应名称添加到控制器。资源提供者必须在使用资源之前通过调用 misc_cg_set_capacity() 设置其容量。 一旦设置了容量就可以使用charge和uncharge API 来更新资源使用情况。与 misc 控制器交互的所有 API 都位于 include/linux/misc_cgroup.h 中。 misc.capacity 仅在根 cgroup 中显示的只读平键文件。它显示平台上可用的各种标量资源及其数量 cat misc.capacity output: res_a 50 res_b 10misc.current 所有 cgroup 中显示的只读平面键控文件。它显示 cgroup 及其子组中资源的当前使用情况 cat misc.current output: res_a 3 res_b 0misc.max 所有 cgroup 中显示的只读平面键控文件。它显示 cgroup 及其子组中资源的历史最大使用量: cat misc.max output: res_a max res_b 4可以通过以下方式设置限制 echo res_a 1 misc.max可以通过以下方式将限制设置为最大值 echo res_a max misc.max可以将限制设置得高于 misc.capacity 文件中的容量值。 misc.events 存在于非 root cgroup 上的只读平键文件。定义了以下条目。除非另有说明否则此文件中的值更改会生成文件修改事件。此文件中的所有字段都是分层的。 maxcgroup 的资源使用量即将超出最大边界的次数 misc.events.local 与 misc.events 类似但文件中的字段是 cgroup 本地的即非层次化的。在此文件上生成的文件修改事件仅反映本地事件。 杂项标量资源将由最先使用该资源的 cgroup 负责并且会一直由该 cgroup 负责直到该资源被释放。将进程迁移到其他 cgroup 不会将资源转移到进程移动的目标 cgroup。 术语 CPU NUMA架构 概述 NUMA这是一种内存设计架构全称是非一致性内存访问(Non-Uniform Memory Access)。与传统的一致性访问内存UMA不同在NUMA中每个处理器都有自己专属的本地内存也可以访问其他处理器的内存但是访问本地内存比访问其他处理器的内存快。 核心概念 NUMA节点每个处理器都有直接连接本地内存节点一个或多个处理器和它们的本地内存节点可以构成一个NUMA节点NUMA节点间通过高速互通如QPI、Infinity Fabric等相连 内存亲和性处理器对内存访问的倾向性尽量使用本地内存以减少访问延迟处理器访问本地内存和远程内存其他NUMA节点的内存的延迟不同这就是非一致性内存访问架构 优点 性能优化 处理器访问本地内存的速度更快减少了内存访问的瓶颈特别是在内存密集型应用中 扩展性NUMA架构允许系统通过增加更多的NUMA节点来扩展适合大型多处理器系统。 内存 Page Cache 概述 page caches是操作系统上用于缓存磁盘数据的内存区域这样后续访问相同数据时可以直接从内存读取而不必再次进行磁盘IO从而提高系统性能。 工作原理 缓存读取操作从磁盘读取数据时会缓存到page cache如果下次访问相同数据块直接从内存读取。延迟写入操作 首先将数据写入page cache并标记为dirty page表示这些page需要同步到磁盘OS会在适当的时候将这些dirty pages写回磁盘比如系统闲置时或者内存压力较大时 内存管理 内存不足时OS会释放掉部分page cachemaybe LRU算法在重新被需要时这些page会被加载到page cache中 如何查看page cache(linux系统) free -hbuff/cache就是page cache Slab 概述 是一种内存管理机制主要用于在内核中高效地管理小块内存的分配和释放。Slab分配器的设计目标是通过减少内存碎片加速内存分配和释放的过程以及缓存对象来提高系统性能。 核心概念 cache是slab分配器的核心结构cache中包含了特定类型object的多个slabslab是由多个连续内存页组成的内存块每个slab包含了多个相同类型object的内存空间slab的状态可以是full、partial、freeobject是分配给内核的内存单位slab分配器的目标是高效地分配和释放这些object 工作流程 初始化cache系统启动时或需要某种类型的object时内核会初始化一个对应类型的cache分配object当内核需要分配一个object时slab分配器会从对应类型的cache的partial slab中找到一个空闲的object如果没有就去free slab找如果还是没有slab分配器就会给该cache分配一个新的slab释放object当内核释放一个object时slab分配器会将这个object标记为free并将其所在的slab的状态更新。 优点 减少内存碎片slab分配器在分配和释放相同大小对象时会尽量重用内存减少了内存碎片提高分配效率slab分配器在分配和释放内存时使用预分配的slab速度非常快对象初始化object可以在cache中保持初始化状态使得后续分配更加高效 swap 概述 swap是一种扩展内存容量的机制。它允许OS将内存中不活跃的页面内存中的数据块移动到预先设置的swap空间中这个空间可以是硬盘上的一个特定分区或一个文件。swap是处理内存不足的一种有用方法但由于硬盘的访问速度远低于RAM使用swap会降低系统性能 特点 内存管理当RAM使用接近上限时swap可以提供额外的虚拟内存帮助管理内存压力灵活性可以动态调整swap空间大小性能影响访问速度低于RAM过度依赖会降低系统性能 使用场景 内存不足时的缓冲休眠在休眠模式下OS会将当前内存保存到swap空间然后关闭电源当OS唤醒时再从swap空间恢复数据。 启动或关闭系统上的交换空间 swapoff -a # 关闭 swapon -a # 开启 一开一关就可以清空缓存 cat /proc/swaps # 查看系统是否开启了交换空间 swapon --show # 查看系统是否开启了交换空间内存回收 概述 一个在系统内存变得紧张时释放内存的过程涉及多个组件和策略。 页面回收机制 linux使用分页内存管理当系统需要更多内存时页面回收机制会尝试回收未使用或最少使用的页面。 活跃/非活跃列表linux将内存页面分为活跃和非活跃两个列表经常访问的页面被认为是活跃的而不常访问的页面会被移动到非活跃列表页面回收当内存紧张时系统首先回收非活跃列表中的页面这些页面可能被直接回收或者写回磁盘然后回收 **OOM Killer**当linux系统极度缺乏内存无法通过常规页面回收机制获得足够内存时OOM Killer会被出发。OOM Killer会选择并终止占用大量内存的进程来释放内存 **cgroup 内存限制**可以为cgroup设置内存限制当进程组尝试使用超过限制的内存时它们的一些进程可能会被终止以保持内存使用在限制之下 磁盘 SCSI硬盘设备 概述 SCSI(Small Computer System Interface)是一种用于计算机硬盘和其他设备的接口标准。SCSI接口支持硬盘扫描仪打印机等多种类型的外围设备。通常sda是linux上第一个SCSI硬盘设备 特点 高性能高数据传输速率和低CPU占用率多设备支持通过一个SCSI接口可以连接多个设备灵活性和可扩展性SCSI系统支持宽广设备类型和大量设备的连接兼容性支持多种类型和大小的设备 块设备 常见的块设备 sda是第一个SCSI硬盘设备在现代linux系统中SATA和USB存储设备也被视为SCSI设备因此它们的设备名以sda、sdb等开头sr0这通常代表第一个SCSI光驱设备比如CD-ROM或DVD-ROM驱动器dm-0dm-1这些是设备映射设备常用于LVM逻辑卷管理、加密磁盘或提供软件RAID功能loop0, loop1, …这些是循环设备用于将文件映射为块设备这在挂载ISO文件创建虚拟文件系统等场景中非常有用nbd0, nbd1, …这些是网络块设备允许系统通过网络访问块设备就像它们直接连接到本地系统一样 sda和vda sda 物理硬盘sda通常代表系统中的第一个SCSI或SATA硬盘。直接访问sda通常用于直接访问物理硬盘这意味着操作系统直接与硬件通信没有虚拟化层 vda 虚拟硬盘vda代表的是虚拟环境中的第一个虚拟磁盘设备这种命名通常出现在使用KVM、QEMU或其他虚拟化技术的环境中优化性能虚拟磁盘可以针对虚拟化环境进行优化提高性能和灵活性 文件系统 tmpfs 概述 是linux中的一种临时文件系统它使用内存或swap来存储文件和目录。因为数据存储在RAM中使得tmpfs非常适合临时数据的存储。比如系统启动过程中的临时文件或者应用程序需要频繁读写的临时数据 主要特性 速度快访问速度快于磁盘灵活性可以动态调整大小数据易失性重启系统或卸载tmpfs后存储在其中的数据会丢失 使用场景 /tmp目录许多linux发行版使用tmpfs挂载/tmp目录以提高临时文件处理的速度缓存和会话数据web服务器和数据库可以使用tmpfs来存储缓存数据提高访问速度编译过程中的临时文件编译大型软件项目时使用tmpfs可以减少磁盘IO加快编译速度 挂载tmpfs mkdir -p /mnt/tmp mount -t tmpfs -o size1G tmpfs /mnt/tmp查看是否挂载成功 df -h /mnt/tmp卸载tmpfs umount /mnt/tmp系统启动自动挂载tmpfs 在/etc/fstab文件中添加一行配置 tmpfs /mnt/tmp tmpfs defaults,size1G 0 0网络 QoS 简介 概述 是一种控制网络资源使用的机制以确保关键业务或流量类型 (如视频、语音通话)获得必要的带宽和延迟要求从而提高网络的整体性能和用户体验。QoS通过对网络流量进行分类、排队、调度和流量整形等机制实现对不同类型流量的差别化处理。linux使用了tc来进行流量控制。 核心概念 流量识别与分类 流量识别是QoS的第一步通过检查数据包的头部信息(如源/目的IP地址端口号协议类型等)来识别流量类型分类是根据识别的结果将流量分入不同的类别或队列。每个类别可以根据其服务质量需求进行不同的处理 流量标记涉及数据包的头部信息以反应其QoS优先级。例如在IP数据包中可以使用DSCP(differentiated Services Code Point)字段来标记优先级排队排队策略决定了不同类型的流量如何被存储和转发。不同的排队策略如FIFO、优先队列、循环队列等可以根据流量的优先级和需求进行选择拥塞避免当网络出现拥塞时拥塞避免机制通过丢弃一些数据包来减轻网络负载常见的算法有TCP的拥塞控制算法RED等流量整形通过控制数据流的发送速率来调整流量的传输以符合网络策略或避免网络拥塞。它通常通过延迟额外的数据包实现流量调度决定了不同流量队列中的数据包何时以及以何种顺序被发送。调度算法如加权公平队列低延迟队列等。确保高优先级的流量获得快速处理带宽管理涉及分配网络资源确保关键应用和服务获得足够的带宽。这通常涉及带宽上限和保证来实现 **协议栈的QoS主要由三部分组成**qdisc(队列规则queueing discipline)class控制策略 filter根据filter划入具体的控制策略 一般流程是这样当一个qdisc被入队的时候会循环匹配其中的filter如果匹配到了的话就会将packet入队到对应的class当中大部分情况下被class的所有者代表的qdisc入队。一些没有匹配的packet会进入默认的class 队列规则 pfifo 默认的qdisc就是pfifo实现在net/sched/sch_prio.c 设置有三个优先级的队列从高到低分别是 0 interactive1 best effort2 bulk 先消费0队列在消费1队列最后消费2队列 实现依赖如下结构 struct prio_sched_data {int bands;struct tcf_proto __rcu *filter_list;u8 prio2band[TC_PRIO_MAX1];struct Qdisc *queues[TCQ_PRIO_BANDS]; };bands一般是3个代表三个不同优先级的队列然后filter_list是他的过滤器列表最后prio2band就是ToS To Queue的映射中linux priority 到 band的部分queues保存的是三个fifo的qdisc也就是三个队列 pfifo enqueue的时候会调用prio_classify根据skb-priority来选择队列进行入队dequeue的时候则round robin每次依次从优先级高到低取出一个packet HTB(Hierarchical Token Bucket) HTB是一个层级令牌桶的qdsic而且能加入class 使用 qdisc 参数parent major:minor或者root 一个qdisc是根节点就是root否则其他的情况指定parent。其中major:minor是class的handle id每个class都要指定一个id用于标识 handle major: 这个语法有点奇怪是可选的如果 qdisc 下面还要分类多个 class)则需要指定这个 hanlde。对于 root通常是”1:” # handle是一组用户指定的标识符格式为major:minor # 如果是一条queueing discipline, minor需要一直为0即不写 tc qdisc add dev eth0 root handle 1: htb # 具体作用在eth0网卡上添加一个根队列规则 # qdisc表示要添加一个新的队列规则 # dev指定网络设备名称 # root表示这个队列规则被添加到设备的根位置。在TC中每个设备都有一个队列规则的层次结构 # handle 1:为这个队列规则指定一个句柄句柄用于后续操作中引用这个规则 # htb是一种队列规则算法。允许对不同的流量进行分层控制为每个类比额分配不同的带宽# classis指明该class handle的唯一IDminor需要是非零值 tc class add dev eth0 parent 1:1 classid 1:6 htb rate 256kbit ceil 512kbit # 具体作用在之前配置的队列规则下添加一个新的类 # class表示要添加一个类 # parent指定这个类的父类挂载在1:1下而不是直接挂载在根队列规则下 # classid为这个新类指定一个类ID # rate指定这个类的保证带宽 # ceil指定这个类的最大带宽# 新建一个带宽为100kbps的root class其classid为1:1 tc class add dev eth0 parent 1: classid 1:1 htb rate 100kbps ceil 100kbps # parent直接挂载在根队列规则下 # 接着建立两个子class指定其parent为1:1ceil用来限制子类最大的带宽 tc class add dev eth0 parent 1:1 classid 1:10 htb rate 40kbps ceil 100kbps tc class add dev eth0 parent 1:1 classid 1:11 htb rate 60kbps ceil 100kbps # 随后建立filter指定哪些类型的packet进入哪个class tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 match ip dport 80 0xffff flowid 1:10 # 具体作用添加一个过滤器用于匹配特定IP流量并将其分配到指定的类 # protocol ip指定过滤器应用于IP协议的数据包 # parent 1:0指定过滤器的父级队列规则表示根队列规则 # prio 1指定过滤器的优先级为1数值越低优先级越高 # u32使用u32过滤器这是一个通用、功能强大的过滤器 # match ip src 1.2.3.4匹配源IP地址为1.2.3.4的数据包 # match ip dport 80 0xffff匹配目标端口为80的数据包0xffff是掩码表示完全匹配 # flowid 1:10指定匹配的数据包将被分配到类ID为1:10的类 tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip src 1.2.3.4 flowid 1:11 # 最后为这些class添加queuing disciplines tc qdisc add dev eth0 parent 1:10 handle 20: pfifo limit 5 tc qdisc add dev eth0 parent 1:11 handle 30: sfq perturb 10设备 misc设备 **概述**通常指代miscellaneous(杂项)设备。它们是一类特殊的字符设备主要用于子系统中不容易归类到其他设备类别的小设备。misc’设备由’misc’子系统管理这个子系统简化了创建和管理这些杂项设备的过程 特点和管理 字符设备misc设备通常是字符设备这意味着它们处理数据的方式是按字符而不是块来操作子系统管理通过misc子系统可以简化创建和管理这些设备的步骤共享主设备号所有misc设备共享一个主设备号但每个设备都有自己独立的次设备号设备注册设备驱动程序通过调用’misc_register’函数注册一个misc设备 常见的misc设备 /dev/urandom和/dev/random 提供伪随机数和真随机数生成给常用于密码学、密钥生成等随机数的场景 /dev/tty 代表当前终端设备的别名用于进程与当前终端进行交互 /dev/null 被称为位桶或空设备写入数据会被丢弃读取数据时会返回EOF常用于丢弃不需要的数据或测试 /dev/zero 提供无限量的零字节常用于内存初始化或创建空文件 /dev/full 提供一个总是返回满的设备写入时返回ENOSPC错误常用于测试错误处理 /dev/loopX 环回设备(Loopback device)用于将文件作为块设备使用常用于创建文件系统映像 /dev/kmsg 内核消息设备用于从用户空间向内核日志发送消息 /dev/hpet 高精度时间计数器提供高精度的定时功能 /dev/input/mice和/dev/input/mouseX 提供对连接到系统的鼠标设备的访问常用于捕获和处理鼠标输入事件 /dev/watchdog 看门狗设备用于系统监控和恢复如果系统挂起未及时重置看门狗计时器将触发系统重启 RDMA **概述**Remote Direct Memory Access 设备是一类允许直接在不同计算机之间传输数据的网络设备而不需要经过CPU的干预或传统的操作系统网络栈。RDMA的主要目标是提供低延迟、高带宽的数据传输能力特别适用于高性能计算、分布式存储系统、大规模数据中心以及金融服务等领域 基本概念 RDMARDMA是一种技术允许在不同主机之间直接传输数据从而绕过传统的网络协议栈如TCP/IP。通过直接访问远程主机的内存RDMA能够大幅减少数据传输的延迟并减轻CPU的负担RDMA设备是一种支持RDMA技术的网络设备通常是专用的网卡如InfiniBand适配器、RoCE网卡或iWARP设备。这些设备通常包含硬件加速器可以直接处理内存传输和网络数据包而不需要经过操作系统内核的处理 关键优势 低延迟由于跳过了内核的网络协议栈并且可以直接在网络设备上处理数据传输RDMA显著降低了数据传输的延迟高带宽RDMA设备通常支持非常高的网络带宽适合大规模数据传输任务低CPU开销在传统的网络通信中数据包的处理需要占用大量CPU资源。而RDMA技术让数据传输直接在网卡上处理释放了CPU资源零拷贝传输即数据可以从一台机器的内存直接传输到另一台机器的内存而不需要中间的内存拷贝操作 **工作原理**通过一组硬件来直接访问远程系统的内存 Queue Pair(QP)有发送队列和接收队列组成。它们用于处理数据的发送和接收操作Memory Region(MR)MR是RDMA设备访问内存区域的方式。内存区域被注册到RDMA设备中使其能够直接访问这些区域的物理内存Completion Queue(CQ)用于通知操作完成的队列。每当一个发送或接收操作完成时CQ会产生一个完成事件供应用程序处理RDMA OperationsSend/Receive、RDMA Read和RDMA Write。Send/Receive类似于传统的消息传递而RDMA Read和Write操作则允许直接从远程内存中读取或写入数据 内核配置 如何查看 cat /boot/config-$(uname -r) | grep $CONFIG_NAMECONFIG_NAME某个具体的内核配置名称 配置状态 y表示该功能已启用并且是静态编译到内核中的即直接编译到内核映像内不会作为模块存在。 m表示该功能被配置为内核模块module也就是该功能会作为一个单独的模块被编译出来加载时才会启用。 n表示该功能没有启用也就是说该功能在内核中被禁用既不编译到内核也不作为模块编译。
http://www.dnsts.com.cn/news/81929.html

相关文章:

  • 广告设计公司简介内容西宁seo快速排名
  • 怎样设网站郑州全面恢复正常
  • 建各公司网站要多少钱廊坊网站建设团队
  • 网站站建设免费空间浏览量
  • 网站建设数据库怎么选择济南网站建设 小程序
  • linux做网站方便吗成都公司注册流程及需要的材料
  • 什么网站可以做问卷软件技术和计算机应用技术哪个好
  • 中山市网站建设小璇seo优化网站
  • 中英文网站建设方案求好的设计网站
  • 网站制作 成都网络营销的销售方式
  • 什么是网站上线检测懒人模板网站
  • 如何用手机做网站高校信息化建设 网站
  • 网站推广手段有哪些上海公司注册网上查询
  • 学院做网站的意义seo推广怎么学
  • wp风格网站升学宴ppt免费模板下载
  • 给企业建设网站的意义深圳市住房和建设局公众号
  • 网站建设需求分析调查表淘宝网网页版登录官网登录
  • 制作网站什么制作js网站效果
  • 支付网站开发费可以做无形资产广告制作合同
  • 柳州网站推广最好的公司密云建设银行招聘网站
  • 广东企业建网站网页设计总结体会
  • 吴江建网站百度知道首页登录
  • 简单的seo网站优化排名网站建设团队分工
  • 农产品电商网站建设的总体目标江苏seo技术教程
  • 户县建设局网站机电建设有限公司网站
  • 网站建设资源定制做网站报价
  • 运城网站建设多少钱有哪些建筑设计网站
  • 接视频做的网网站怎么查看一个网站页面的seo优化情况
  • 网络广告网站怎么做网站分析培训班
  • 迅雷网站做爰视频前端开发工程师的工作内容