与超级用户问题相关的https://superuser.com/questions/200387/linux-overcommit-memory我的问题是他们允许过度使用默认值的原因是什么?
从 2.5.30 开始,这些值是: 0(默认):和以前一样:猜测多少超额使用是合理的,
答案1
Linux(以及整个 Unix 系统)中过量使用内存的大部分需求来自于实现fork()
系统调用的需要,这会复制调用进程的地址空间。
大多数情况下,该系统调用后面跟着exec()
,这两者的组合会导致生成一个单独的程序作为当前进程的子进程,在这种情况下,大多数重复的地址空间最终将不会被使用。
为了提高效率,Linux 使用写时复制来避免复制调用的应用程序的内存fork()
,在这种情况下,它可以避免复制所有页面,而只是在exec()
调用后不久丢弃它们。
但在被叫的时候fork()
,没有办法知道是否有人exec()
来。这很可能被用来生成子进程,并且重用父进程的地址空间正是我们所期望的。 (这种技术在使用预分叉工作进程来处理连接的守护进程中非常流行。)在这种情况下,分叉子进程将存在大部分或至少部分内存需求(可能不是 100% 的父进程内存,但可以假设其中大部分。)
fork()
但总是为这种情况保留内存对于+情况来说很麻烦exec()
,特别是如果父进程是一个长时间运行的进程,它保留了多个 GB 的内存并分叉了许多子进程。如果不是为了过度使用,您必须保留父级以及每个分叉子级使用的总容量。但这些都不会(或几乎不会)被真正使用,因为exec()
会立即刷新该保留。最终结果是,这样的工作负载要么需要大量的交换空间(为了处理预留,其中大部分都未使用,但在最坏的情况下需要存在)或诸如过度使用之类的东西。
虽然fork()
这个例子很好地说明了这一点,但 Linux/Unix 中的其他 API 也导致需要过度使用。例如,当malloc()
被调用时(或更准确地说是实现它的系统调用),在被进程“触及”之前,实际上不会分配内存,因此分配一个非常大的千兆字节块并稀疏地使用它是完全有效的,这样只有实际使用了几兆字节。事实上,这些 API 以这种方式工作意味着程序会利用这些属性,这意味着它们很可能在没有过度使用的情况下崩溃(除非您确实有大量内存或通过支持这些预留而浪费了交换空间。)
关于这个问题的有趣讨论fork()
可以在LWN 发布的有关 Microsoft Research 的一篇文章。当然,这篇文章本身很有趣。但您可以看到这些评论如何立即导致过度使用以及随之而来的问题。
文章名为岔路口()。
答案2
我认为原因是并非所有人都有足够的资源来购买内存,因此在这种情况下所有应用程序都应该正常运行,这有助于以低资源运行应用程序。