2017-02-23 103 views
6

我有一個在32GB機器上分配大約20GB RAM的進程。在發生一些事件後,我將來自父進程的數據流式傳輸到子進程的標準輸入。當孩子產卵時,必須將20GB數據保存在父進程中。爲什麼使用`clone`創建進程會導致內存不足失敗?

該應用程序是在Rust中編寫的,我打電話給Command::new('path/to/command')來創建子進程。

當我產生子進程時,操作系統陷入了內存不足的錯誤。

strace的輸出:

[PID 747] 16:04:41.128377克隆(child_stack = 0,標誌= CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD,child_tidptr = 0x7ff4c7f87b10)= -1 ENOMEM(無法分配存儲器)

爲什麼會發生陷阱?子進程不應超過1GB,在clone()之後立即調用exec()

+1

請分享代碼,爲什麼不使用分叉? –

+1

這可能是一個過度使用的問題。嘗試以root用戶身份執行'echo「1」>/proc/sys/vm/overcommit_memory'。 – user4815162342

+1

您可以在流程生命週期的早期階段培育孩子,並將其保留,直到您需要爲止。 – Shepmaster

回答

3

的問題

當除鏽調用創建一個子進程,幾件事情發生在C/C++水平。這是一種簡化,但它有助於解釋困境。

  1. 的流被複制(用DUP2或類似的呼叫)
  2. 父進程分叉(與叉或克隆系統調用)
  3. 叉形進程執行子(與來自execvp呼叫家庭)

父母和孩子現在是併發進程。你目前使用的Rust調用似乎是一個克隆調用,它的行爲非常像純粹的fork,所以你只需要20G x 2 - 32G = 8G,而不考慮操作系統所需的空間以及其他任何可能的運行。克隆調用返回一個負的返回值,通過調用ENOMEM errno來設置errno。

如果在任何時候添加物理內存,壓縮數據或通過一個不需要全部內存的進程流式傳輸的體系結構解決方案都不是選項,那麼傳統解決方案相當簡單。

建議

設計父進程爲稀。然後產生兩個工人孩子,一個處理20GB的需求,另一個處理1 GB的需求,需要。這些孩子可以通過管道,文件,共享內存,套接字,信號量,信令和/或其他通信機制相互連接,就像父母和孩子一樣。

許多從Apache httpd到嵌入式單元塔式路由守護程序的成熟軟件包均使用此設計模式。它是可靠的,可維護的,可擴展的和便攜的。

32G可能足以滿足20G和1G處理需求,以及操作系統和精益父流程。

儘管這個解決方案肯定能解決您的問題,但如果代碼將在以後重用或擴展,那麼在研究涉及數據幀或多維片的潛在過程設計更改時可能有價值,以支持數據流和內存需求的減少。

內存過量始終

設置overcommit_memory 1消除問題所引用的克隆錯誤的情形,因爲鐵鏽電話呼叫LINUX克隆呼叫讀取設置。但是這個解決方案有幾點需要注意上面的建議,因爲它的優點是1的值很危險,特別是在生產環境中。

背景

內核有關的OpenBSD rfork和克隆電話討論結果在90年代末和21世紀初。這些討論產生的特徵允許不像流程那樣極端分叉,這就像在pthread之間提供更廣泛的獨立性那樣對稱。其中一些討論已經擴展了進入POSIX標準化的傳統進程產卵。

在二十一世紀初,Linux Torvalds提出了一個標誌結構來確定執行模型的哪些組件被共享,哪些在執行分支時被複制,模糊了進程和線程之間的區別。從此,克隆電話出現了。

過度提交的內存在這些線程中沒有討論太多。設計目標是對分叉結果的更多控制,而不是將內存使用優化委託給操作系統啓發式,這是默認設置overcommit_memory = 0的作用。

注意事項

內存過量超越了這些擴展,增加了它的模式的取捨,設計潮流警告的複雜性,實際運行時間限制和性能的影響。

流通與長壽

另外,沒有標準化,使用內存過量的代碼可能不是便攜式的,和壽命的問題是相關的,特別是當設置控制的功能的行爲。如果設置系統發生變化,則不能保證向後兼容性,甚至不能保證執行退化的警告。

危險

的linuxdevcenter文檔說,「1總是overcommits。也許你現在意識到這種模式的危險。」,而且有危險其他指徵總是過量使用6,7

LINUX,Windows和VMWare上的overcommit實現者可能會保證可靠性,但它是一種統計遊戲,結合許多其他複雜的過程控制,可能會在某些條件下導致某些不穩定的特性。即使這個名字過度使用也會告訴我們一些關於它作爲一種實踐的真實性質。

一個非默認overcommit_memory模式,其中有幾個警告是問題,但立即試用立即案件可能會導致間歇性可靠性。

無法預測及其對系統可靠性和響應時間的一致性

在類UNIX操作系統,從貝爾實驗室開始的過程的觀念的影響,是一個過程,使一個具體請求其容器,操作系統。結果既可預測又二元。請求被拒絕或授予。一旦被授予,該過程就被完全控制並直接訪問資源,直到過程放棄使用它爲止。

虛擬內存的交換空間方面違反了這個原則,當內存大量消耗時,這種原則顯示爲工作站上活動的大幅減速。例如,在開發過程中有時會按下一個按鍵,而且必須等待十秒才能看到顯示屏上的字符。

結論

有很多方法可以最有效地利用物理內存,而是希望利用分配將是稀疏可能會引入負面影響內存這樣做。當overcommit過度使用時,性能從交換中獲得是有據可查的例子。如果您將20G數據保存在RAM中,則情況尤其如此。

只需分配需要的東西,以智能的方式分配,使用線程,釋放內存,而這些內存肯定不再需要,從而導致內存節儉而不影響可靠性,在交換磁盤使用中產生尖峯,並且無需注意即可運行系統資源的限制。

Command::new調用的設計者的位置可能基於這個觀點。在這種情況下,調用exec之後的多久不是決定產生期間請求多少內存的決定性因素。

註釋和參考文獻

[1]產卵工人的孩子可能需要一些代碼重構,似乎是在膚淺的層面太麻煩,但重構可能是出奇的簡單,顯著有益。

[2] http://www.linuxdevcenter.com/pub/a/linux/2006/11/30/linux-out-of-memory.html?page=2

[3] https://www.etalabs.net/overcommit.html

[4] http://www.gabesvirtualworld.com/memory-overcommit-in-production-yes-yes-yes/

[5] https://labs.vmware.com/vmtj/memory-overcommitment-in-the-esx-server

[6] https://github.com/kubernetes/kubernetes/issues/14452

[7] http://linuxtoolkit.blogspot.com/2011_08_01_archive.html

+0

步驟2中是否有COW機制? 「內存翻倍」是什麼意思?哪些內存,物理或虛擬? PC上的overcommit_memory設置有什麼問題? – osgx

+0

「分配虛擬內存時,它必須對應於物理內存空間」 - 並非如此。在Linux中有過量使用,默認情況下啓用:9.6 Overcommit和OOM https://www.win.tue.nl/~aeb/linux/lk/lk-9.html&http://stackoverflow.com/questions/ 38688824 /。 – osgx

+1

不是。 Linux通常允許分配比物理內存大小(RAM +交換)更多的虛擬內存。這個內存沒有被映射到某個真實的東西上,在訪問每個頁面時都會出現中斷「Page Fault」,內核會分配真實的物理頁面,安裝正確的映射並重新啓動失敗的指令。當沒有醫生會從那裏分配OOM。這可以在overcommit_memory中關閉(並且THP可能有更復雜的任務)。請添加對答案的引用,閱讀一些文檔,並儘量不要在完全不瞭解問題時發帖。 – osgx

相關問題