碎片整理 RAM / OOM 失敗
這個問題相當長,所以我會在頂部提出問題,然後通過我的方法來回答問題:
- (基於 Busybox 的)rm 是否因為沒有足夠的連續 RAM 而沒有執行?
- 如果是這樣,是否有一種對 DMA 進行碎片整理的輕量級方法 - 無需重新啟動系統?
- 如果不是,是什麼原因造成的?我怎樣才能防止它在未來發生?
在我們的測試系統在過去幾天中相當密集地執行之後 - 我 telnet 進入系統並檢查了測試結果。當我來刪除一些數據時,系統返回命令行(好像命令執行正確)。當我來檢查目錄以獲取另一組結果時,我看到該文件仍然存在(使用 ls)。
在此之後,我注意到越來越多的 shell 命令沒有按預期執行。
在 rm 無法正確執行後,我將從dmesg的輸出開始:
從程序 6821 (rm) 分配長度 61440 失敗
每個 CPU 的 DMA:
CPU 0: hi: 0, btch: 1 usd: 0
Active_anon:0 active_file:1 inactive_anon:0 inactive_file:0 unevictable:6dirty:0 writeback:0不穩定:0 free:821slab:353 mapped:0 pagetables:0bounce:0
DMA free:3284kB min:360kB low:448kB high:540kB active_anon:0kB inactive_anon:0kB active_file:4kB inactive_file:0kB unevictable:24kB present:8128kB pages_scanned:0 all_unreclaimable?不
lowmem_reserve
$$ $$: 0 0 0 DMA:314kB 478kB 4216kB 6432kB 164kB 0128kB 0256kB 0512kB 01024kB 02048kB 0*4096kB = 3284kB
總共 14 個頁面記憶體頁面
無法為程序數據分配 RAM,errno 12
最初,我認為我無法在最大部分的連續記憶體中執行該程序。這意味著 DMA 過於碎片化,我必須找到一種方法讓系統對記憶體進行碎片整理。
然後我做了一個快速的數學/健全性檢查,並意識到該程序應該能夠在唯一的 64kB 連續記憶體插槽中執行。Rm 請求 61440 字節 (60kB)。
我做了一個很好的舊“手動碎片整理”並重新啟動了系統。當我重新啟動系統時,我輸出 /proc/buddyinfo:
Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0
我懷疑映射到:
- 2 x 4 KB
- 8 x 8 KB
- 3 x 16 KB
- 12 x 32 KB
- 1 x 128 KB
- 1 x 512 KB
但是,如果對上面的值列表求和,它與/proc/meminfo的輸出不匹配:
MemTotal: 6580 kB MemFree: 3164 kB Buffers: 0 kB Cached: 728 kB SwapCached: 0 kB Active: 176 kB Inactive: 524 kB Active(anon): 0 kB Inactive(anon): 0 kB Active(file): 176 kB Inactive(file): 524 kB` Unevictable: 0 kB Mlocked: 0 kB MmapCopy: 844 kB SwapTotal: 0 kB SwapFree: 0 kB Dirty: 0 kB Writeback: 0 kB AnonPages: 0 kB Mapped: 0 kB Slab: 1268 kB SReclaimable: 196 kB SUnreclaim: 1072 kB PageTables: 0 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 3288 kB Committed_AS: 0 kB VmallocTotal: 0 kB VmallocUsed: 0 kB VmallocChunk: 0 kB
回顧一下,我的問題是:
- rm 沒有執行是因為沒有足夠的連續 RAM 嗎?
- 如果是這樣,是否有一種對 DMA 進行碎片整理的輕量級方法 - 無需重新啟動系統?
- 如果不是,是什麼原因造成的?我怎樣才能防止它在未來發生?
我正在使用執行 uClinux 版本 2.6.30 的 Lantronix 的 XPort Pro(8MB,Linux 作業系統)。使用中的外殼很安靜。
這花了一些時間,但我想我會推遲回答,直到我對所有 3 個子問題都有答案。
不過,在開始之前,我會提到“去碎片化”工作記憶的正確術語是“壓縮”工作記憶。
- rm 沒有執行是因為沒有足夠的連續 RAM 嗎?
我的結論是正確的 - rm 沒有執行,因為沒有足夠的連續 RAM。系統一直在獲取 RAM 並將其分段,從而使其無法回收。
- 如果是這樣,是否有一種輕量級的 DMA 碎片整理方法 - 無需重新啟動系統?
事實證明,除了重新啟動嵌入式系統之外,沒有辦法壓縮記憶體。對於無 MMU 系統,預防是遊戲的名稱。
我的一部分考慮是否有可能破解 linux 核心以在軟體中模擬 MMU。我想如果可能的話,早就有人這麼做了。我無法想像它是一個全新的概念;)
- 我怎樣才能防止它在未來發生?
對於這個項目,我每次需要時都使用 cron 手動啟動程序。一個更好的方法是在啟動時呼叫程序,然後強製程序休眠直到需要它。這樣,不需要在每次使用時分配記憶體。從而減少碎片。
在項目的第一次迭代中,我們依靠我的 shell 腳本呼叫來執行關鍵功能(例如 rm)。如果我們不需要,我們認為沒有必要重新發明輪子。
但是,對於無 MMU 的系統,我建議盡可能避免使用 shell -
(問題,如果你執行會發生什麼
ls -la /path/to/directory/ | grep file-i-seek
?)(答案:它啟動一個新的子程序)
如果您需要在 C 程序中實現一些核心 shell 腳本功能,我建議您查看BusyBox中使用的原始碼。您可能會在嵌入式系統中使用 C..
關於您的問題 2(對記憶體進行碎片整理),引用自https://www.kernel.org/doc/Documentation/sysctl/vm.txt:
compact_memory
僅在設置了 CONFIG_COMPACTION 時可用。當 1 被寫入文件時,所有區域都被壓縮,以便在可能的情況下以連續塊的形式提供可用記憶體。這在分配大頁面時可能很重要,儘管程序也會根據需要直接壓縮記憶體。
這意味著以下命令(以 root 權限執行並且如果啟用了上述核心選項)
echo 1 > /proc/sys/vm/compact_memory
應該告訴核心盡可能多地嘗試對記憶體進行碎片整理。請注意,例如在某些 RHEL6 版本上,這可能會使核心崩潰…