![為什麼 Linux 預設會過量使用記憶體?](https://rvso.com/image/154458/%E7%82%BA%E4%BB%80%E9%BA%BC%20Linux%20%E9%A0%90%E8%A8%AD%E6%9C%83%E9%81%8E%E9%87%8F%E4%BD%BF%E7%94%A8%E8%A8%98%E6%86%B6%E9%AB%94%EF%BC%9F.png)
與超級用戶問題相關的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
我認為原因是並非所有人都有足夠的資源來購買內存,因此在這種情況下所有應用程式都應該正常運行,這有助於以低資源運行應用程式。