Show Table of Contents
A.7. memory
memory 子系统自动生成 cgroup 任务使用内存资源的报告,并限定这些任务所用内存的大小:
- memory.stat
- 报告大范围内存统计,见下表:
表 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.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禁用 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 - 将
bluecgroup 中任务可用的内存量设定为 100MB:~]#
echo 104857600 > memory.limit_in_bytes - 进入
blue目录并确定已启用 OOM 终止程序:~]#
cd /cgroup/memory/blueblue]#cat memory.oom_controloom_kill_disable 0 under_oom 0 - 将当前 shell 进程移动到
bluecgroup 的tasks文件中,以便在这个 shell 中启动的其它所有进程会自动移至bluecgroup:blue]#
echo $$ > tasks blue]#
~/mem-hogKilled以下是测试程序实例 [1]:#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define KB (1024) #define MB (1024 * KB) #define GB (1024 * MB) int main(int argc, char *argv[]) { char *p; again: while ((p = (char *)malloc(GB))) memset(p, 0, GB); while ((p = (char *)malloc(MB))) memset(p, 0, MB); while ((p = (char *)malloc(KB))) memset(p, 0, KB); sleep(1); goto again; return 0; }- 禁用 OOM 杀手程序,然后重新运行测试程序。这次该测试程序会暂停并等待额外的内存释放:
blue]#
echo 1 > memory.oom_controlblue]#~/mem-hog - 虽然测试程序处于暂停状态,但请注意该 cgroup 的
under_oom状态已更改,表示该 cgroup 缺少可用内存:~]#
cat /cgroup/memory/blue/memory.oom_controloom_kill_disable 1 under_oom 1重启 OOM 终止程序可以立即终止该测试程序。 - 如要收到关于每一个 OOM 的通知,请创建一个 指定的程序。 例如 [2]:
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/eventfd.h> #include <errno.h> #include <string.h> #include <stdio.h> #include <stdlib.h> static inline void die(const char *msg) { fprintf(stderr, "error: %s: %s(%d)\n", msg, strerror(errno), errno); exit(EXIT_FAILURE); } static inline void usage(void) { fprintf(stderr, "usage: oom_eventfd_test <cgroup.event_control> <memory.oom_control>\n"); exit(EXIT_FAILURE); } #define BUFSIZE 256 int main(int argc, char *argv[]) { char buf[BUFSIZE]; int efd, cfd, ofd, rb, wb; uint64_t u; if (argc != 3) usage(); if ((efd = eventfd(0, 0)) == -1) die("eventfd"); if ((cfd = open(argv[1], O_WRONLY)) == -1) die("cgroup.event_control"); if ((ofd = open(argv[2], O_RDONLY)) == -1) die("memory.oom_control"); if ((wb = snprintf(buf, BUFSIZE, "%d %d", efd, ofd)) >= BUFSIZE) die("buffer too small"); if (write(cfd, buf, wb) == -1) die("write cgroup.event_control"); if (close(cfd) == -1) die("close cgroup.event_control"); for (;;) { if (read(efd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) die("read eventfd"); printf("mem_cgroup oom event received\n"); } return 0; }上述程序会探测 OOM 状态(从被命令列指定为参数的 cgroup 中),并使用mem_cgroup oom event received字符串在标准输出中报告。 - 在一个独立的控制台中运行上述通知处理程序,并将
bluecgroup 的控制文件指定为参数:~]$
./oom_notification /cgroup/memory/blue/cgroup.event_control /cgroup/memory/blue/memory.oom_control - 在另一个控制台中运行
mem_hog测试程序,以便生成 OOM 状态,并查看oom_notification程序在标准输出中的报告:blue]#
~/mem-hog

Where did the comment section go?
Red Hat's documentation publication system recently went through an upgrade to enable speedier, more mobile-friendly content. We decided to re-evaluate our commenting platform to ensure that it meets your expectations and serves as an optimal feedback mechanism. During this redesign, we invite your input on providing feedback on Red Hat documentation via the discussion platform.