这个文件包含了内核虚拟内存计数模式。取值为:
0:启用启发式内存超限(默认情况)
1:总是超限,不进行检查
2:总是检查,不超限
在模式 0 中,对于使用 MAP_NORESERVE 的 mmap(2) 调用不会检查,而且默认的检查非常弱,存在进程“OOM-killed”的风险。
在模式 1 中,内核假装始终有足够的内存,直到实际内存耗尽。这种模式的一种用途是使用大型稀疏数组的科学计算应用程序。在 Linux 内核版本 2.6.0 之前的任何非零值都会暗示模式 1。
在模式 2 中(自 Linux 2.6 起可用),可以分配的总虚拟地址空间(/proc/meminfo 中的 CommitLimit)的计算公式为:
CommitLimit = (total_RAM - total_huge_TLB) * overcommit_ratio / 100 + total_swap
其中:
total_RAM是系统上的RAM总量;
total_huge_TLB是为巨大页面分配的内存大小;
overcommit_ratio是/proc/sys/vm/overcommit_ratio中的值;以及
total_swap是交换空间的大小。
例如,在物理RAM为16GB,交换空间为16GB,没有专门用于巨大页面的空间,并且overcommit_ratio为50的系统上,此公式会产生24GB的CommitLimit。
自Linux 3.14以来,如果/proc/sys/vm/overcommit_kbytes中的值非零,则CommitLimit将计算为:
CommitLimit = overcommit_kbytes + total_swap
请参见/proc/sys/vm/admiin_reserve_kbytes和/proc/sys/vm/user_reserve_kbytes的描述。
在5.2.1内核树中,Documentation/vm/overcommit-accounting.rst也提供了一些信息,尽管略少:
Linux内核支持以下过度承诺处理模式
0 启发式的过度承诺处理。地址空间的明显过度承诺被拒绝。用于典型系统。它确保一个严重的野外分配失败,同时允许过度承诺减少交换使用。在此模式下,root被允许稍微分配更多的内存。这是默认值。
1 总是过度承诺。适用于某些科学应用程序。经典例子是使用稀疏数组的代码,并依赖于虚拟内存几乎完全由零页面组成。
2 不要过度承诺。不允许系统的总地址空间提交超过交换+可配置数量(默认为物理RAM的50%)。根据您使用的数量,在大多数情况下,这意味着在访问页面时不会杀死进程,但会适当地接收有关内存分配的错误。
适用于希望保证其内存分配将来可用而无需初始化每个页面的应用程序。
最小实验
我们可以轻松看到允许的最大值:
main.c
#define _GNU_SOURCE
#include
#include
#include
#include
#include
int main(int argc, char **argv) {
char *chars;
size_t nbytes;
/* Decide how many ints to allocate. */
if (argc < 2) {
nbytes = 2;
} else {
nbytes = strtoull(argv[1], NULL, 0);
}
/* Allocate the bytes. */
chars = mmap(
NULL,
nbytes,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS,
-1,
0
);
/* This can happen for example if we ask for too much memory. */
if (chars == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
/* Free the allocated memory. */
munmap(chars, nbytes);
return EXIT_SUCCESS;
}
GitHub上游。
编译并运行以分配1GiB和1TiB:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out 0x40000000
./main.out 0x10000000000
我们可以尝试调整分配值来查看系统允许的情况。
我找不到关于 0(默认值)的精确文档,但在我的32GiB RAM机器上,它不允许1TiB的分配:
mmap: Cannot allocate memory
如果我启用无限制的过度承诺:
echo 1 | sudo tee /proc/sys/vm/overcommit_memory
那么,如果分配1 TiB的空间,就可以正常工作。
模式2有很好的文档说明,但我懒得进行精确计算来验证它。但是我只想指出,在实践中,我们被允许分配大约:
overcommit_ratio / 100
总共RAM的大小,overcommit_ratio默认为50,因此我们可以分配大约一半的总RAM。
VSZ和RSS以及内存不足杀手
到目前为止,我们只是分配了虚拟内存。
然而,在某个时刻,如果你使用了足够多的这些页面,Linux将不得不开始杀死一些进程。
我在这里详细说明了这一点:Linux内存管理中的RSS和VSZ是什么