Linux上的虚拟内存大小
Linux上的虚拟内存大小
我正在尝试深入理解 Linux 操作系统上的虚拟内存管理。
我真的不明白操作系统如何确定进程的虚拟内存大小。
我知道一个 32 位 x86 操作系统可以提供多达 3 GB 的虚拟内存地址空间...这总是正确的吗?
在我的情况下,我有大约 110 MB 的物理内存和 32 位 Linux,我的主要进程有大约 660 MB 的虚拟内存地址空间。然而,只有 50 MB 在物理内存中(我的进程的 RSS),所以我的物理 RAM 没有满。其余部分是空闲的,几乎全部被页缓存使用。这似乎是正常行为。
如果我检查 /proc/my_process_PID/smap,则会有几个 8 MB 的匿名 VMA。
我现在的问题是,我需要在代码中进行额外的 10 MB malloc,但不幸的是 OOM-Killer 杀死了我的进程(内存不足)...我认为在堆中已经没有更多的可用页面了,是吗?是否存在巨大的内存泄漏?
为什么操作系统不会扩展我的进程的虚拟内存大小呢?
供参考,虚拟内存大小是无限制的:ulimit -v:无限制。
在Linux系统上可用的虚拟内存空间总量大约是 RAM
+ swap space
- kernel overhead
。其中RAM是您安装的硬件,内核开销大致是一个常数(尽管在不同内核版本之间会有所变化),因此控制总VM空间可用性的唯一简单方法是添加或删除交换空间。
除了总限制之外,还有一个每个进程的VM限制。这是可配置的,在32位Linux上至多为3GB,但可能会少得多。 ulimit -v
将告诉您此限制,或可用于更改它。
当进程请求更多VM空间(通常通过malloc)时,内核将查看所有这些限制,如果任何限制将超过,则会返回0。另一方面,当您接近总VM限制时,OOM killer才会启动。但是,当OOM killer杀死您时,您只是死了--没有内存不足错误或任何机会来捕获它。
所以如果您真的遇到了总的虚拟内存限制,并且想要避免这种情况,您可以分配更多的交换空间,或者摆脱(杀死或在第一时间不启动)使用大量虚拟内存空间的其他进程,以便为您的程序释放一些空间。
每个进程可以拥有 3GB 的虚拟内存(大约,在许多 32 位 Linux 上),并继续创建新进程,占用吉字节的虚拟内存。内核有一些小的开销,但虚拟内存非常便宜。您正在使用的地址空间大小可能并不重要,并且可能不会触发 OOM killer。
然而,您的系统只有这么多的 RAM。当您开始使用地址空间中的页面(写入它们)时,内核被迫找到物理 RAM 将它们映射到。如果没有物理 RAM,内核可以从 RAM 中逐出其他页面 - 要么将它们交换出去,要么将它们丢弃。但如果它无法逐出任何页面,则会触发 OOM killer。
在我的系统上,地址空间耗尽将导致 malloc
返回 NULL
,而不是触发 OOM killer。
听起来您的进程只是使用了太多的 RAM。RSS 并不是您的进程使用的内存量,它只是当前在物理 RAM 中的内存量。如果您的进程存在内存泄漏并持续增长,RSS 最终会停止增长 - 因为对于每个新页面,内核将从您的进程中逐出一个页面。
尝试使用内存分析器,如 Valgrind。这将帮助您区分应该关注的内存(mallocs)和可以忽略的内存(共享库和其他内存映射文件)。内核(和 /proc)不会为您提供足够的详细信息。