Android low memory killer 机制
Android中,進程的生命周期都是由系統控制的。即使用戶在界面上關掉一個應用,切換到了別的應用,那個應用的進程依然是存在于內存之中的。這樣設計的目的是為了下次啟動應用能更加快速。當然,隨著系統運行時間的增長,內存中的進程可能會越來越多,而可用的內存則將會越來越少。Android Kernel會定時執行一次檢查,殺死一些進程,釋放掉內存。
那么,如何來判斷,哪些進程是需要殺死的呢?答案就是:low memory killer 機制。
Android 的 low memory killer 是基于 linux 的OOM(out of memory)規則改進而來的。OOM 通過一些比較復雜的評分機制,對進程進行打分,然后將分數高的進程判定為 bad進程,殺死進程并釋放內存。OOM 只有當系統內存不足的時候才會啟動檢查,而 low memory killer 則不僅是在應用程序分配內存發現內存不足時啟動檢查,它也會定時地進行檢查。
Low memory killer 主要是通過進程的 oom_adj 來判定進程的重要程度的。oom_adj 的大小和進程的類型以及進程被調度的次序有關。
Low memory killer 的具體實現在 kernel,比如對于 android 4.4.3 所用的 kernel_3.4,代碼在:linux/kernel/drivers/staging/android/lowmemorykiller.c。
其原理很簡單,?在 linux 中,存在一個名為 kswapd 的內核線程,當linux回收存放分頁的時候,kswapd 線程將會遍歷一張 shrinker 鏈表,并執行回調,或者某個app分配內存,發現可用內存不足時,則內核會阻塞請求分配內存的進程分配內存的過程,并在該進程中去執行lowmemorykiller來釋放內存。
struct shrinker 的定義在 linux/kernel/include/linux/shrinker.h,具體如下:
struct shrinker {int (*shrink)(struct shrinker *, struct shrink_control *sc);int seeks;/* seeks to recreate an obj */long batch;/* reclaim batch size, 0 = default *//* These are for internal use */struct list_head list;atomic_long_t nr_in_batch; /* objs pending delete */ }; #define DEFAULT_SEEKS 2 /* A good number if you don't know better. */ extern void register_shrinker(struct shrinker *); extern void unregister_shrinker(struct shrinker *); #endif?所以,只要注冊 shrinker,就可以在內存分頁回收時根據規則釋放內存。下面我們來看看lowmemorykiller 的具體實現。首先是定義 shrinker 結構體,lowmem_shrink 為回調函數的指針,當有內存分頁回收的時候,獲其他有需要的時機,這個函數將會被調用。
static struct shrinker lowmem_shrinker = {.shrink = lowmem_shrink,.seeks = DEFAULT_SEEKS * 16 };初始化模塊時進行注冊,模塊退出時注銷。
static int __init lowmem_init(void) {register_shrinker(&lowmem_shrinker);return 0; } static void __exit lowmem_exit(void) {unregister_shrinker(&lowmem_shrinker); }Android 中,存在著一張內存閾值表,這張閾值表是可以在 init.rc 中進行配置的,合理配置這張表,對于小內存設備有非常重要的作用。我們來看 lowmemorykiller.c 中這張默認的閾值表:
static int lowmem_adj[6] = {0,1,6,12, }; static int lowmem_adj_size = 4; static int lowmem_minfree[6] = {3 * 512,/* 6MB */2 * 1024,/* 8MB */4 * 1024,/* 16MB */16 * 1024,/* 64MB */ }; static int lowmem_minfree_size = 4;lowmem_adj 中各項數值代表閾值的警戒級數,lowmem_minfree 代表對應級數的剩余內存。也就是說,當系統的可用內存小于6MB時,警戒級數為0;當系統可用內存小于8M而大于6M時,警戒級數為1;當可用內存小于64M大于16MB時,警戒級數為12。Low memory killer的規則就是根據當前系統的可用內存多少來獲取當前的警戒級數,如果進程的oom_adj大于警戒級數并且最大,進程將會被殺死(具有相同omm_adj的進程,則殺死占用內存較多的)。omm_adj越小,代表進程越重要。一些前臺的進程,oom_adj會比較小,而后臺的服務,omm_adj會比較大,所以當內存不足的時候,Low memory killer必然先殺掉的是后臺服務而不是前臺的進程。
OK,現在我們來看具體代碼,也就是lowmem_shrink這個回調函數,先來:
static int lowmem_minfree_size = 4;static unsigned long lowmem_deathpending_timeout;#define lowmem_print(level, x...)\do {\if (lowmem_debug_level >= (level))\printk(x);\} while (0)static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc) {struct task_struct *tsk;struct task_struct *selected = NULL;int rem = 0;int tasksize;int i;int min_score_adj = OOM_SCORE_ADJ_MAX + 1;int selected_tasksize = 0;int selected_oom_score_adj;int array_size = ARRAY_SIZE(lowmem_adj);int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;int other_file = global_page_state(NR_FILE_PAGES) - global_page_state(NR_SHMEM);if (lowmem_adj_size < array_size)array_size = lowmem_adj_size;if (lowmem_minfree_size < array_size)array_size = lowmem_minfree_size;for (i = 0; i < array_size; i++) {if (other_free < lowmem_minfree[i] &&other_file < lowmem_minfree[i]) {min_score_adj = lowmem_adj[i];break;}}if (sc->nr_to_scan > 0)lowmem_print(3, "lowmem_shrink %lu, %x, ofree %d %d, ma %d\n",sc->nr_to_scan, sc->gfp_mask, other_free,other_file, min_score_adj);rem = global_page_state(NR_ACTIVE_ANON) +global_page_state(NR_ACTIVE_FILE) +global_page_state(NR_INACTIVE_ANON) +global_page_state(NR_INACTIVE_FILE);if (sc->nr_to_scan <= 0 || min_score_adj == OOM_SCORE_ADJ_MAX + 1) {lowmem_print(5, "lowmem_shrink %lu, %x, return %d\n",sc->nr_to_scan, sc->gfp_mask, rem);return rem;}selected_oom_score_adj = min_score_adj;rcu_read_lock();for_each_process(tsk) {struct task_struct *p;int oom_score_adj;if (tsk->flags & PF_KTHREAD)continue;p = find_lock_task_mm(tsk);if (!p)continue;if (test_tsk_thread_flag(p, TIF_MEMDIE) &&time_before_eq(jiffies, lowmem_deathpending_timeout)) {task_unlock(p);rcu_read_unlock();return 0;}oom_score_adj = p->signal->oom_score_adj;if (oom_score_adj < min_score_adj) {task_unlock(p);continue;}tasksize = get_mm_rss(p->mm);task_unlock(p);if (tasksize <= 0)continue;if (selected) {if (oom_score_adj < selected_oom_score_adj)continue;if (oom_score_adj == selected_oom_score_adj &&tasksize <= selected_tasksize)continue;}selected = p;selected_tasksize = tasksize;selected_oom_score_adj = oom_score_adj;lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",p->pid, p->comm, oom_score_adj, tasksize);}if (selected) {lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",selected->pid, selected->comm,selected_oom_score_adj, selected_tasksize);lowmem_deathpending_timeout = jiffies + HZ;send_sig(SIGKILL, selected, 0);set_tsk_thread_flag(selected, TIF_MEMDIE);rem -= selected_tasksize;}lowmem_print(4, "lowmem_shrink %lu, %x, return %d\n",sc->nr_to_scan, sc->gfp_mask, rem);rcu_read_unlock();return rem; }第22行至第35行。通過global_page_state()函數獲取系統當前可用的內存大小,然后根據可用內存大小及內存閾值表,來計算系統當前的警戒等級。
第40行,計算rem值。
第44行至第48行這個if-block,發現此時系統的內存狀況還是很不錯的,于是就什麼也不做,直接返回了。
第49行至第90行,遍歷系統中所有的進程,選中將要殺掉的那個進程。第56行,跳過內核線程,內核線程不參加這個殺進程的游戲。第69行至第73行,進程的oom_score_adj小于警戒閾值,則無視。第74行,獲取進程所占用的內存大小,RSS值。第78行至第84行,如果這個進程的oom_score_adj小于我們已經選中的那個進程的oom_score_adj,或者這個進程的oom_score_adj等于我們已經選中的那個進程的oom_score_adj,但其所占用的內存大小tasksize小于我們已經選中的那個進程所占用內存大小,則繼續尋找下一個進程。第85至第89行,選中正在遍歷的這個的進程,更新selected_tasksize為這個進程所占用的內存大小tasksize,更新selected_oom_score_adj為這個進程的oom_score_adj。
第91行至第99行,殺死選中的進程。先是更新lowmem_deathpending_timeout,然后便是給進程發送一個signal SIGKILL,接下來是設置進程的標記為TIF_MEMDIE,最后則是更新一下rem的值。
adj值的設置
在 lowmemorykiller 的code中我們有看到一個默認的閾值表。如我們前面所提到的那樣,各種各樣的設備、產品也可以自己定制這個值。這種定制主要是通過導出一些內核變量來實現的,具體代碼如下:
#ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES static int lowmem_oom_adj_to_oom_score_adj(int oom_adj) {if (oom_adj == OOM_ADJUST_MAX)return OOM_SCORE_ADJ_MAX;elsereturn (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE; }static void lowmem_autodetect_oom_adj_values(void) {int i;int oom_adj;int oom_score_adj;int array_size = ARRAY_SIZE(lowmem_adj);if (lowmem_adj_size < array_size)array_size = lowmem_adj_size;if (array_size <= 0)return;oom_adj = lowmem_adj[array_size - 1];if (oom_adj > OOM_ADJUST_MAX)return;oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj);if (oom_score_adj <= OOM_ADJUST_MAX)return;lowmem_print(1, "lowmem_shrink: convert oom_adj to oom_score_adj:\n");for (i = 0; i < array_size; i++) {oom_adj = lowmem_adj[i];oom_score_adj = lowmem_oom_adj_to_oom_score_adj(oom_adj);lowmem_adj[i] = oom_score_adj;lowmem_print(1, "oom_adj %d => oom_score_adj %d\n",oom_adj, oom_score_adj);} }static int lowmem_adj_array_set(const char *val, const struct kernel_param *kp) {int ret;ret = param_array_ops.set(val, kp);/* HACK: Autodetect oom_adj values in lowmem_adj array */lowmem_autodetect_oom_adj_values();return ret; }static int lowmem_adj_array_get(char *buffer, const struct kernel_param *kp) {return param_array_ops.get(buffer, kp); }static void lowmem_adj_array_free(void *arg) {param_array_ops.free(arg); }static struct kernel_param_ops lowmem_adj_array_ops = {.set = lowmem_adj_array_set,.get = lowmem_adj_array_get,.free = lowmem_adj_array_free, };static const struct kparam_array __param_arr_adj = {.max = ARRAY_SIZE(lowmem_adj),.num = &lowmem_adj_size,.ops = ¶m_ops_int,.elemsize = sizeof(lowmem_adj[0]),.elem = lowmem_adj, }; #endifmodule_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR); #ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES __module_param_call(MODULE_PARAM_PREFIX, adj,&lowmem_adj_array_ops,.arr = &__param_arr_adj,S_IRUGO | S_IWUSR, -1); __MODULE_PARM_TYPE(adj, "array of int"); #else module_param_array_named(adj, lowmem_adj, int, &lowmem_adj_size,S_IRUGO | S_IWUSR); #endif module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,S_IRUGO | S_IWUSR); module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);lowmemorykiller 在此處總共導出了4個內核變量,其中兩個是內核數組。我們可以在如下位置訪問到這些內核變量:/sys/module/lowmemorykiller/parameters。在 init.rc 文件中會設置這些內核變量的屬性(system/core/rootdir/init.rc),以便于后面系統對這些值進行修改:
281 chown root system /sys/module/lowmemorykiller/parameters/adj 282 chmod 0664 /sys/module/lowmemorykiller/parameters/adj 283 chown root system /sys/module/lowmemorykiller/parameters/minfree 284 chmod 0664 /sys/module/lowmemorykiller/parameters/minfree那通常情況下,比如在Nexus 7或類似的設備上,adj值又是在什麼時候設置的呢?設置的那些值依據是什麼呢,是一個經驗值呢還是有什麼算法來算出那些值?
搜索android4.4.3_r1.1的整個codebase,我們發現lowmemorykiller所導出的那些值只在ProcessList.updateOomLevels()方法中被修改了。接著我們就來具體看一下這個方法的實現(實現此方法的文件位置為frameworks/base/services/java/com/android/server/am/ProcessList.java):
// OOM adjustments for processes in various states:// Adjustment used in certain places where we don't know it yet.// (Generally this is something that is going to be cached, but we// don't know the exact value in the cached range to assign yet.)static final int UNKNOWN_ADJ = 16;// This is a process only hosting activities that are not visible,// so it can be killed without any disruption.static final int CACHED_APP_MAX_ADJ = 15;static final int CACHED_APP_MIN_ADJ = 9;// The B list of SERVICE_ADJ -- these are the old and decrepit// services that aren't as shiny and interesting as the ones in the A list.static final int SERVICE_B_ADJ = 8;// This is the process of the previous application that the user was in.// This process is kept above other things, because it is very common to// switch back to the previous app. This is important both for recent// task switch (toggling between the two top recent apps) as well as normal// UI flow such as clicking on a URI in the e-mail app to view in the browser,// and then pressing back to return to e-mail.static final int PREVIOUS_APP_ADJ = 7;// This is a process holding the home application -- we want to try// avoiding killing it, even if it would normally be in the background,// because the user interacts with it so much.static final int HOME_APP_ADJ = 6;// This is a process holding an application service -- killing it will not// have much of an impact as far as the user is concerned.static final int SERVICE_ADJ = 5;// This is a process with a heavy-weight application. It is in the// background, but we want to try to avoid killing it. Value set in// system/rootdir/init.rc on startup.static final int HEAVY_WEIGHT_APP_ADJ = 4;// This is a process currently hosting a backup operation. Killing it// is not entirely fatal but is generally a bad idea.static final int BACKUP_APP_ADJ = 3;// This is a process only hosting components that are perceptible to the// user, and we really want to avoid killing them, but they are not// immediately visible. An example is background music playback.static final int PERCEPTIBLE_APP_ADJ = 2;// This is a process only hosting activities that are visible to the// user, so we'd prefer they don't disappear.static final int VISIBLE_APP_ADJ = 1;// This is the process running the current foreground app. We'd really// rather not kill it!static final int FOREGROUND_APP_ADJ = 0;// This is a system persistent process, such as telephony. Definitely// don't want to kill it, but doing so is not completely fatal.static final int PERSISTENT_PROC_ADJ = -12;// The system process runs at the default adjustment.static final int SYSTEM_ADJ = -16;// Special code for native processes that are not being managed by the system (so// don't have an oom adj assigned by the system).static final int NATIVE_ADJ = -17;// Memory pages are 4K.static final int PAGE_SIZE = 4*1024;// These are the various interesting memory levels that we will give to// the OOM killer. Note that the OOM killer only supports 6 slots, so we// can't give it a different value for every possible kind of process.private final int[] mOomAdj = new int[] {FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,BACKUP_APP_ADJ, CACHED_APP_MIN_ADJ, CACHED_APP_MAX_ADJ};// These are the low-end OOM level limits. This is appropriate for an// HVGA or smaller phone with less than 512MB. Values are in KB.private final long[] mOomMinFreeLow = new long[] {8192, 12288, 16384,24576, 28672, 32768};// These are the high-end OOM level limits. This is appropriate for a// 1280x800 or larger screen with around 1GB RAM. Values are in KB.private final long[] mOomMinFreeHigh = new long[] {49152, 61440, 73728,86016, 98304, 122880};// The actual OOM killer memory levels we are using.private final long[] mOomMinFree = new long[mOomAdj.length];private final long mTotalMemMb;private void updateOomLevels(int displayWidth, int displayHeight, boolean write) {// Scale buckets from avail memory: at 300MB we use the lowest values to// 700MB or more for the top values.float scaleMem = ((float)(mTotalMemMb-300))/(700-300);// Scale buckets from screen size.int minSize = 480*800; // 384000int maxSize = 1280*800; // 1024000 230400 870400 .264float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize);if (false) {Slog.i("XXXXXX", "scaleMem=" + scaleMem);Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth+ " dh=" + displayHeight);}StringBuilder adjString = new StringBuilder();StringBuilder memString = new StringBuilder();float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp;if (scale < 0) scale = 0;else if (scale > 1) scale = 1;int minfree_adj = Resources.getSystem().getInteger(com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAdjust);int minfree_abs = Resources.getSystem().getInteger(com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAbsolute);if (false) {Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs);}for (int i=0; i<mOomAdj.length; i++) {long low = mOomMinFreeLow[i];long high = mOomMinFreeHigh[i];mOomMinFree[i] = (long)(low + ((high-low)*scale));}if (minfree_abs >= 0) {for (int i=0; i<mOomAdj.length; i++) {mOomMinFree[i] = (long)((float)minfree_abs * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]);}}if (minfree_adj != 0) {for (int i=0; i<mOomAdj.length; i++) {mOomMinFree[i] += (long)((float)minfree_adj * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1]);if (mOomMinFree[i] < 0) {mOomMinFree[i] = 0;}}}// The maximum size we will restore a process from cached to background, when under// memory duress, is 1/3 the size we have reserved for kernel caches and other overhead// before killing background processes.mCachedRestoreLevel = (getMemLevel(ProcessList.CACHED_APP_MAX_ADJ)/1024) / 3;for (int i=0; i<mOomAdj.length; i++) {if (i > 0) {adjString.append(',');memString.append(',');}adjString.append(mOomAdj[i]);memString.append((mOomMinFree[i]*1024)/PAGE_SIZE);}// Ask the kernel to try to keep enough memory free to allocate 3 full// screen 32bpp buffers without entering direct reclaim.int reserve = displayWidth * displayHeight * 4 * 3 / 1024;int reserve_adj = Resources.getSystem().getInteger(com.android.internal.R.integer.config_extraFreeKbytesAdjust);int reserve_abs = Resources.getSystem().getInteger(com.android.internal.R.integer.config_extraFreeKbytesAbsolute);if (reserve_abs >= 0) {reserve = reserve_abs;}if (reserve_adj != 0) {reserve += reserve_adj;if (reserve < 0) {reserve = 0;}}//Slog.i("XXXXXXX", "******************************* MINFREE: " + memString);if (write) {writeFile("/sys/module/lowmemorykiller/parameters/adj", adjString.toString());writeFile("/sys/module/lowmemorykiller/parameters/minfree", memString.toString());SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));}// GB: 2048,3072,4096,6144,7168,8192// HC: 8192,10240,12288,14336,16384,20480}adj值是一組寫死的固定的值,具體可以參考mOomAdj的定義。
第123行至第127行,是第一輪計算各個adj所對應的minimum free memory閾值。計算各個值的算式為(long)(low + ((high-low)*scale))。low值和high值都是預定義的固定的經驗值,比較關鍵的是那個scale值。在前面計算scale的部分,我們可以看到,它會先計算一個memory的scale值(為((float)(mTotalMemMb-300))/(700-300)),再計算一個屏幕分辨率的scale值(((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize)),首先取scale值為這兩個scale值中較大的那一個。再然后是一些容錯處理,將scale值限制在0~1之間,以防止設備內存小于300MB,同時設備分辨率小于480*800;或者,設備內存大于700MB,或設備分辨率大于1280*800的情況出現時,出現太不合理的閾值。
第129行至133行,是第二輪計算各個adj所對應的minimum free memory閾值。計算各個值的算式為(long)((float)minfree_abs * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1])。此處給了各設備對low memory閾值進行定制的機會。各個設備可以在framework的config文件中定義config_lowMemoryKillerMinFreeKbytesAbsolute,以指定最大的adj所對應的free memory閾值,其他各個adj所對應的free memory閾值將依比例算出。
第135行至第142行,是第三輪計算各個adj所對應的minimum free memory閾值。計算各個值的算式為mOomMinFree[i] += (long)((float)minfree_adj * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1])。此處是給特定設備微調low memory的閾值提供機會。不過我們仔細來看第二輪和第三輪的計算,這兩輪計算似乎是可以合并為:(long)((float)(minfree_abs + minfree_adj) * mOomMinFree[i] / mOomMinFree[mOomAdj.length - 1])。
后面則是構造適合設置給lowmemorykiller導出參數的字符串,并最終將構造的這組參數設置進去。
那這個ProcessList.updateOomLevels()方法又是在什麼時候會被調用到呢?是在ProcessList.applyDisplaySize()方法中:
void applyDisplaySize(WindowManagerService wm) {if (!mHaveDisplaySize) {Point p = new Point();wm.getBaseDisplaySize(Display.DEFAULT_DISPLAY, p);if (p.x != 0 && p.y != 0) {updateOomLevels(p.x, p.y, true);mHaveDisplaySize = true;}}}在這個方法中,當能夠從WMS中獲取有效的屏幕分辨率時,會去更新oom levels,并且更新之后就不會再次去更新。我們再來追查ProcessList.applyDisplaySize(),是在ActivityManagerService.updateConfiguration():
public void updateConfiguration(Configuration values) {enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,"updateConfiguration()");synchronized(this) {if (values == null && mWindowManager != null) {// sentinel: fetch the current configuration from the window managervalues = mWindowManager.computeNewConfiguration();}if (mWindowManager != null) {mProcessList.applyDisplaySize(mWindowManager);}final long origId = Binder.clearCallingIdentity();if (values != null) {Settings.System.clearConfiguration(values);}updateConfigurationLocked(values, null, false, false);Binder.restoreCallingIdentity(origId);}}我們總結一下OOM levels的更新:時機是在系統啟動后,第一個configuration change的消息到AMS的時候;adj值為一組固定的預定義的值;各個adj所對應的min free閾值則根據系統的內存大小和屏幕的分辨率計算得出,各個設備還可以通過framework的config config_lowMemoryKillerMinFreeKbytesAdjust和config_lowMemoryKillerMinFreeKbytesAbsolute來定制最終各個adj所對應的min free閾值。
我們可以根據系統所吐出來的log看一下,事實是否如我們上面對code的分析那樣。由某個設備抓到的系統內核吐出來的log,可以發現如下的這些行(只出現一次):
I/KERNEL ( 609): [ 14.064905] lowmemorykiller: lowmem_shrink: convert oom_adj to oom_score_adj: I/KERNEL ( 609): [ 14.064932] lowmemorykiller: oom_adj 0 => oom_score_adj 0 I/KERNEL ( 609): [ 14.064938] lowmemorykiller: oom_adj 1 => oom_score_adj 58 I/KERNEL ( 609): [ 14.064942] lowmemorykiller: oom_adj 2 => oom_score_adj 117 I/KERNEL ( 609): [ 14.064947] lowmemorykiller: oom_adj 3 => oom_score_adj 176 I/KERNEL ( 609): [ 14.064951] lowmemorykiller: oom_adj 9 => oom_score_adj 529 I/KERNEL ( 609): [ 14.064956] lowmemorykiller: oom_adj 15 => oom_score_adj 1000由前面lowmemorykiller的code不難看出,這些log在lowmem_autodetect_oom_adj_values()函數中吐出,是在內核空間吐出來的。吐出這些log的進程的pid為609。我們再來看一下這個進程到底是何方神圣:
desktop:~/develop_tools$ adb shell ps | grep 609 system 609 235 1031532 94240 ffffffff ffffe430 S system_server謎底揭曉,是system_server。不難推測出來,這應當是在系統啟動之后,AMS第一次接到configuration change的消息,去更新OOM level,lowmemorykiller的lowmem_autodetect_oom_adj_values()函數被調到,更新lowmemorykiller的lowmem_adj時而吐出來的。與我們前面對AMS code的分析基本一致。
還需要我們厘清的問題,lowmemorykiller的lowmem_shrink具體在什麼時機會被執行?
Done。
總結
以上是生活随笔為你收集整理的Android low memory killer 机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV4Android JavaC
- 下一篇: PyCairo简介