Android中的Low Memory Killer
在現有的技術條件下,記憶體永遠都是一個吃緊的資源,不用說是PC上會出現記憶體不足的可能,更不必說在行動裝置上了。一旦出現記憶體不足就會導致系統卡頓,影響使用者體驗。而Android運行在Linux的基礎之上,Linux的記憶體的使用原則就是不要浪費記憶體,所以在程式退出時在一段時間內還停留在記憶體中,這也是我們下一次開啟程式時發現快一些的原因;但是這樣帶來的壞處就是如果駐留在記憶體中的程式多了,容易導致OOM的可能。
在Linux中有一個記憶體監控機制OOMKiller,一旦發現記憶體使用量進入一個臨界值就會自動按照一定的策略來清理,它的核心思想是:
1 按照優先順序,從低到高來殺死進程,回收記憶體資源 2 一方面要考慮殺死進程給系統帶來的損壞要盡量小,另一方面要釋放盡量多的記憶體 具體的做法是OOMKiller會根據一些參考因素如進程消耗記憶體,已耗用時間,OOM權重等指標計算出一個oom_score分數,這個分數越低,進程被殺死的機率越小,被殺死的時間越晚。 而對於Android系統來說是實現一個不同層級的killer,這個模組名稱為Low Memory Killer,代碼在drivers/staging/android/LowMemoryKiller.c檔案中
static int __init lowmem_init(void) { register_shrinker(&lowmem_shrinker); return 0;}
代碼中註冊一個shrinker監聽器,如果系統空間頁面低於一定的閾值,執行這個lowmem_shrinker函數
該檔案中定義了兩個重要的數組:
static int lowmem_adj[6] = { 0, 1, 6, 12, }; static int lowmem_adj_size = 4; static size_t lowmem_minfree[6] = { 3 * 512, /* 6MB */ 2 * 1024, /* 8MB */ 4 * 1024, /* 16MB */ 16 * 1024, /* 64MB */ }; static int lowmem_minfree_size = 4;
上面定義的兩個數組時一一對應的,其中lowmem_adj表示的是被處理某一個層級的adj的值,lowmen_minfree則表示該層級對應的記憶體閾值。比如說adj=0的層級,它對應的記憶體閾值是6M,也就是在可用記憶體小於6M時,會清除adj大於等於0的所有進程。所以可以看出adj越小,它被殺死的可能越小。 上面定義的是系統預設的,可以通過設定相應的檔案來修改這兩組值: /sys/module/lowmemorykiller/parameters/adj /sys/module/lowmemorykiller/parameters/minfree (以頁為單位,一般是4KB大小)
在Android系統中定義了幾個adj的值,他的意義分別如下:
這些是系統提供的adj,我們還可以改變自己進程的adj值,有以下兩種方式:
1 寫檔案 寫/proc/pid/oom_adj 值,在init.rc檔案中就經常看到這種語句 on early-init write /proc/1/oom_adj -16 設定init進程的adj 值為-16,屬於系統進程永遠不會被殺死
2 設定persistent屬性。 在AndroidManifest.xml檔案中設定這個屬性為true,即可將其adj的值設定為-12,處於這個層級的進程基本上也不會被殺死,比如電話。