A.7. memory
memory 子系统自动生成 cgroup 任务使用内存资源的报告,并限定这些任务所用内存的大小:
- memory.stat
- 报告大范围内存统计,见下表:
Expand 表 A.2. memory.stat 报告的值 统计数据 描述 cache缓存页,包括 tmpfs(shmem),单位为字节rss匿名和 swap 缓存,“不”包括 tmpfs(shmem),单位为字节mapped_filememory-mapped 映射文件大小,包括 tmpfs(shmem),单位为字节pgpgin读入内存的页数 pgpgout从内存中读出的页数 swapswap 用量,单位为字节 active_anon激活的“近期最少使用”(least-recently-used,LRU)列表中的匿名和 swap 缓存,包括 tmpfs(shmem),单位为字节inactive_anon未激活的 LRU 列表中的匿名和 swap 缓存,包括 tmpfs(shmem),单位为字节active_file激活的 LRU 列表中的 file-backed 内存,以字节为单位 inactive_file未激活 LRU 列表中的 file-backed 内存,以字节为单位 unevictable无法收回的内存,以字节为单位 hierarchical_memory_limit包含 memorycgroup 层级的内存限制,单位为字节hierarchical_memsw_limit包含 memorycgroup 层级的内存加 swap 限制,单位为字节另外,这些文件除hierarchical_memory_limit和hierarchical_memsw_limit之外,都有一个对应前缀total,它不仅可在该 cgroup 中报告,还可在其子 cgroup 中报告。例如:swap报告 cgroup 的 swap 用量,total_swap报告该 cgroup 及其所有子群组的 swap 用量总和。当您解读memory.stat报告的数值时,请注意各个统计数据之间的关系:active_anon+inactive_anon= 匿名内存 +tmpfs文件缓存 + swap 缓存因此,active_anon+inactive_anon≠rss,因为rss不包括tmpfs。active_file+inactive_file= 缓存 -tmpfs大小
- memory.usage_in_bytes
- 报告 cgroup 中进程当前所用的内存总量(以字节为单位)。
- memory.memsw.usage_in_bytes
- 报告该 cgroup 中进程当前所用的内存量和 swap 空间总和(以字节为单位)。
- memory.max_usage_in_bytes
- 报告 cgroup 中进程所用的最大内存量(以字节为单位)。
- memory.memsw.max_usage_in_bytes
- 报告该 cgroup 中进程的最大内存用量和最大 swap 空间用量(以字节为单位)。
- memory.limit_in_bytes
- 设定用户内存(包括文件缓存)的最大用量。如果没有指定单位,则该数值将被解读为字节。但是可以使用后缀代表更大的单位 ——
k或者K代表千字节,m或者M代表兆字节 ,g或者G代表千兆字节。您不能使用memory.limit_in_bytes限制 root cgroup;您只能对层级中较低的群组应用这些值。在memory.limit_in_bytes中写入-1可以移除全部已有限制。 - memory.memsw.limit_in_bytes
- 设定内存与 swap 用量之和的最大值。如果没有指定单位,则该值将被解读为字节。但是可以使用后缀代表更大的单位 ——
k或者K代表千字节,m或者M代表兆字节,g或者G代表千兆字节。您不能使用memory.memsw.limit_in_bytes来限制 root cgroup;您只能对层级中较低的群组应用这些值。在memory.memsw.limit_in_bytes中写入-1可以删除已有限制。重要
在设定memory.memsw.limit_in_bytes参数“之前”设定memory.limit_in_bytes参数非常重要:顺序颠倒会导致错误。这是因为memory.memsw.limit_in_bytes只有在消耗完所有内存限额(之前在memory.limit_in_bytes中设定)后方可用。请参考下列例子:为某一 cgroup 设定memory.limit_in_bytes = 2G和memory.memsw.limit_in_bytes = 4G, 可以让该 cgroup 中的进程分得 2GB 内存,并且一旦用尽,只能再分得 2GB swap。memory.memsw.limit_in_bytes参数表示内存和 swap 的总和。没有设置memory.memsw.limit_in_bytes参数的 cgroup 的进程可以使用全部可用 swap (当限定的内存用尽后),并会因为缺少可用 swap 触发 Out of Memory(内存不足) 状态。/etc/cgconfig.conf文件中memory.limit_in_bytes和memory.memsw.limit_in_bytes参数的顺序也很重要。以下是正确的配置示例:memory { memory.limit_in_bytes = 1G; memory.memsw.limit_in_bytes = 1G; }memory { memory.limit_in_bytes = 1G; memory.memsw.limit_in_bytes = 1G; }Copy to Clipboard Copied! Toggle word wrap Toggle overflow - memory.failcnt
- 报告内存达到
memory.limit_in_bytes设定的限制值的次数。 - memory.memsw.failcnt
- 报告内存和 swap 空间总和达到
memory.memsw.limit_in_bytes设定的限制值的次数。 - memory.force_empty
- 当设定为
0时,该 cgroup 中任务所用的所有页面内存都将被清空。这个接口只可在 cgroup 没有任务时使用。如果无法清空内存,请在可能的情况下将其移动到父 cgroup 中。移除 cgroup 前请使用memory.force_empty参数以免将废弃的页面缓存移动到它的父 cgroup 中。 - memory.swappiness
- 将 kernel 倾向设定为换出该 cgroup 中任务所使用的进程内存,而不是从页高速缓冲中再生页面。这与
/proc/sys/vm/swappiness为整体系统设定的倾向、计算方法相同。默认值为60。低于60会降低 kernel 换出进程内存的倾向;高于0会增加 kernel 换出进程内存的倾向。高于100时,kernel 将开始换出作为该 cgroup 中进程地址空间一部分的页面。请注意:值0不会阻止进程内存被换出;系统内存不足时,换出仍可能发生,因为全局虚拟内存管理逻辑不读取该 cgroup 值。要完全锁定页面,请使用mlock()而不是 cgroup。您不能更改以下群组的 swappiness:- root cgroup,它使用
/proc/sys/vm/swappiness设定的 swappiness。 - 有子群组的 cgroup。
- memory.use_hierarchy
- 包含标签(
0或者1),它可以设定是否将内存用量计入 cgroup 层级的吞吐量中。如果启用(1),内存子系统会从超过其内存限制的子进程中再生内存。默认情况下(0),子系统不从任务的子进程中再生内存。 - memory.oom_control
- 包含标签(
0或者1),它可以为 cgroup 启用或者禁用“内存不足”(Out of Memory,OOM) 终止程序。如果启用(0),尝试消耗超过其允许内存的任务会被 OOM 终止程序立即终止。默认情况下,所有使用memory子系统的 cgroup 都会启用 OOM 终止程序。要禁用它,请在memory.oom_control文件中写入1:echo 1 > /cgroup/memory/lab1/memory.oom_control
~]# echo 1 > /cgroup/memory/lab1/memory.oom_controlCopy to Clipboard Copied! Toggle word wrap Toggle overflow 禁用 OOM 杀手程序后,尝试使用超过其允许内存的任务会被暂停,直到有额外内存可用。memory.oom_control文件也在under_oom条目下报告当前 cgroup 的 OOM 状态。如果该 cgroup 缺少内存,则会暂停它里面的任务。under_oom条目报告值为1。memory.oom_control文件可以使用 API 通知来报告 OOM 情况的出现。 。
A.7.1. 示例应用 复制链接链接已复制到粘贴板!
复制链接链接已复制到粘贴板!
例 A.3. OOM 控制和通知
以下示例将演示当 cgroup 中任务尝试使用超过其允许的内存时, OOM 终止程序的工作过程,以及通知处理程序是如何报告 OOM 状态的:
- 在层级中附加
memory子系统,并创建一个 cgroup:mount -t memory -o memory memory /cgroup/memory mkdir /cgroup/memory/blue
~]# mount -t memory -o memory memory /cgroup/memory ~]# mkdir /cgroup/memory/blueCopy to Clipboard Copied! Toggle word wrap Toggle overflow - 将
bluecgroup 中任务可用的内存量设定为 100MB:echo 104857600 > memory.limit_in_bytes
~]# echo 104857600 > memory.limit_in_bytesCopy to Clipboard Copied! Toggle word wrap Toggle overflow - 进入
blue目录并确定已启用 OOM 终止程序:cd /cgroup/memory/blue
~]# cd /cgroup/memory/blue blue]# cat memory.oom_control oom_kill_disable 0 under_oom 0Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 将当前 shell 进程移动到
bluecgroup 的tasks文件中,以便在这个 shell 中启动的其它所有进程会自动移至bluecgroup:blue]# echo $$ > tasks
blue]# echo $$ > tasksCopy to Clipboard Copied! Toggle word wrap Toggle overflow blue]# ~/mem-hog Killed
blue]# ~/mem-hog KilledCopy to Clipboard Copied! Toggle word wrap Toggle overflow 以下是测试程序实例 [1]:Copy to Clipboard Copied! Toggle word wrap Toggle overflow - 禁用 OOM 杀手程序,然后重新运行测试程序。这次该测试程序会暂停并等待额外的内存释放:
blue]# echo 1 > memory.oom_control blue]# ~/mem-hog
blue]# echo 1 > memory.oom_control blue]# ~/mem-hogCopy to Clipboard Copied! Toggle word wrap Toggle overflow - 虽然测试程序处于暂停状态,但请注意该 cgroup 的
under_oom状态已更改,表示该 cgroup 缺少可用内存:~]# cat /cgroup/memory/blue/memory.oom_control oom_kill_disable 1 under_oom 1
~]# cat /cgroup/memory/blue/memory.oom_control oom_kill_disable 1 under_oom 1Copy to Clipboard Copied! Toggle word wrap Toggle overflow 重启 OOM 终止程序可以立即终止该测试程序。 - 如要收到关于每一个 OOM 的通知,请创建一个 指定的程序。 例如 [2]:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 上述程序会探测 OOM 状态(从被命令列指定为参数的 cgroup 中),并使用mem_cgroup oom event received字符串在标准输出中报告。 - 在一个独立的控制台中运行上述通知处理程序,并将
bluecgroup 的控制文件指定为参数:./oom_notification /cgroup/memory/blue/cgroup.event_control /cgroup/memory/blue/memory.oom_control
~]$ ./oom_notification /cgroup/memory/blue/cgroup.event_control /cgroup/memory/blue/memory.oom_controlCopy to Clipboard Copied! Toggle word wrap Toggle overflow - 在另一个控制台中运行
mem_hog测试程序,以便生成 OOM 状态,并查看oom_notification程序在标准输出中的报告:blue]# ~/mem-hog
blue]# ~/mem-hogCopy to Clipboard Copied! Toggle word wrap Toggle overflow