Linux

碎片整理 RAM / OOM 失敗

  • August 1, 2014

這個問題相當長,所以我會在頂部提出問題,然後通過我的方法來回答問題:

  1. (基於 Busybox 的)rm 是否因為沒有足夠的連續 RAM 而沒有執行?
  2. 如果是這樣,是否有一種對 DMA 進行碎片整理的輕量級方法 - 無需重新啟動系統?
  3. 如果不是,是什麼原因造成的?我怎樣才能防止它在未來發生?

在我們的測試系統在過去幾天中相當密集地執行之後 - 我 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

回顧一下,我的問題是:

  1. rm 沒有執行是因為沒有足夠的連續 RAM 嗎?
  2. 如果是這樣,是否有一種對 DMA 進行碎片整理的輕量級方法 - 無需重新啟動系統?
  3. 如果不是,是什麼原因造成的?我怎樣才能防止它在未來發生?

我正在使用執行 uClinux 版本 2.6.30 的 Lantronix 的 XPort Pro(8MB,Linux 作業系統)。使用中的外殼很安靜。

這花了一些時間,但我想我會推遲回答,直到我對所有 3 個子問題都有答案。

不過,在開始之前,我會提到“去碎片化”工作記憶的正確術語是“壓縮”工作記憶。

  1. rm 沒有執行是因為沒有足夠的連續 RAM 嗎?

我的結論是正確的 - rm 沒有執行,因為沒有足夠的連續 RAM。系統一直在獲取 RAM 並將其分段,從而使其無法回收。

  1. 如果是這樣,是否有一種輕量級的 DMA 碎片整理方法 - 無需重新啟動系統?

事實證明,除了重新啟動嵌入式系統之外,沒有辦法壓縮記憶體。對於無 MMU 系統,預防是遊戲的名稱。

我的一部分考慮是否有可能破解 linux 核心以在軟體中模擬 MMU。我想如果可能的話,早就有人這麼做了。我無法想像它是一個全新的概念;)

  1. 我怎樣才能防止它在未來發生?

對於這個項目,我每次需要時都使用 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 版本上,這可能會使核心崩潰…

引用自:https://unix.stackexchange.com/questions/44481