1 android 作为移动设备的 *** 作系统,可能出现管理的内部不足的情况,为了尽量保证程序继续运行,需要有机制处理相关的内存问题。
2 Android *** 作系统是基于linux的,linux 系统具有缓存内存的功能,即为了加快下次的速度,打开文件后放到内存中,再关闭后不会自动释放掉该内存,所以是cache memory。
会出现linux设备内存有多大,linux系统就会尽量多占用内存,减少下次启动的时间。再内存不够用的时候才会去释放。
Android 设备延用了linux的这个机制,但做了部分的优化,不是缓存文件等,而是缓存进程,但打开一个app后,会创建该app的进程,退出app时不会立刻关掉该进程,所以该进程会占用部分内存。这样的优点是加快下次打开apk的速度。
3 Linux 有oom的机制,在内存不足时释放以让当前程序跑下去。android 同样也有oom处理机制(low memory killer).
4 内存不足时,杀掉谁腾出内存空间是有定义一个rule, 正常理解肯定是先杀手无用的且占内存较大的进程,保证前台显示的进程正常使用。
如driver中有一个数组,
如下,当内存少爷16 * 1024 (64m)时会杀手adj > 12的进程。
kernel 4.12 之前lmk 在内核中
drivers/staging/android/lowmemorykiller.c
static u32 lowmem_debug_level = 1; static short lowmem_adj[6] = { 0, 1, 6, 12, }; static int lowmem_adj_size = 4; static int lowmem_minfree[6] = { 3 * 512, 2 * 1024, 4 * 1024, 16 * 1024, };
5 kernel 4.12之后lmk 已经在内核中删除,使用用户空间的lmkd 执行该功能。
https://source.android.com/devices/tech/perf/lmkd
Historically, Android monitored system memory pressure using an in-kernel low memory killer (LMK) driver, a rigid mechanism that depends on hard-coded values. As of kernel 4.12, the LMK driver is removed from the upstream kernel and the userspace lmkd performs memory monitoring and process killing tasks.
用户空间的lmkd的code路径
system/memory/lmkd/
https://source.android.com/devices/tech/perf/lmkd
6 android 定义了adj,lmkd就是根据这个adj值去判断杀手哪个进程, adj就是rule的体现。
如下面重要的process,有些adj值比较小,lmkd 一般不会杀掉,大的值lmkd就会有被杀手的风险。
/proc/1/oom_score_adj 值为-1000 --- NATIVE_ADJ
/proc/2/oom_score_adj 值为0 --- FOREGROUND_APP_ADJ
/proc/1571/oom_score_adj 值为-800 ---PERSISTENT_PROC_ADJ
/proc/1711/oom_score_adj 值为200 --- PERCEPTIBLE_APP_ADJ
/proc/4283/oom_score_adj 值为100 -- VISIBLE_APP_ADJ
/proc/1608/oom_score_adj 值为600 --- HOME_APP_ADJ
/proc/2846/oom_score_adj 值为700 -- PREVIOUS_APP_ADJ
/proc/5155/oom_score_adj 值为900 --- CACHED_APP_MIN_ADJ
这边定义得adj值
frameworks/base/services/core/java/com/android/server/am/ProcessList.java
7 android 提供方法,方便apk 和 bin档调整优先级,针对重要的apk或进程防止被lmk给杀掉。
android 如何设置adj
系统同时也会动态设置apk 的adj值,当打开一个apk,前台时 adj为FOREGROUND_APP_ADJ, 退出到后台adj就变成了PREVIOUS_APP_ADJ。
Android AMS的OomAdjuster 就是专门处理这个事情,有对四大组件activity/service/broadcast receiver/content provider分别根据不同的情况设置相应的adj值。
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.md
这边给了OOM调节的设计原理及主要功能
frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
逻辑较多
private boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj, ProcessRecord topApp, boolean doingAll, long now, boolean cycleReeval, boolean computeClients) { 。。。。 // important to least, and assign an appropriate OOM adjustment. int adj; int schedGroup; int procState; int cachedAdjSeq; int capability = 0; boolean foregroundActivities = false; boolean hasVisibleActivities = false; if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) { 。。。 } else if (state.isRunningRemoteAnimation()) { 。。。 } else if (app.getActiveInstrumentation() != null) { 。。。 } else if (state.getCachedIsReceivingBroadcast(mTmpBroadcastQueue)) { 。。。 } else if (psr.numberOfExecutingServices() > 0) { 。。。 } else if (app == topApp) { 。。。 } else { 。。。 } 。。。 // Examine all activities if not already foreground. if (!foregroundActivities && state.getCachedHasActivities()) { 。。。 schedGroup = state.getCachedSchedGroup(); } if (procState > PROCESS_STATE_CACHED_RECENT && state.getCachedHasRecentTasks()) { 。。。 } if (adj > ProcessList.PERCEPTIBLE_APP_ADJ || procState > PROCESS_STATE_FOREGROUND_SERVICE) { if (psr.hasForegroundServices()) { 。。。 } else if (state.hasOverlayUi()) { 。。。 } } // If the app was recently in the foreground and moved to a foreground service status, // allow it to get a higher rank in memory for some time, compared to other foreground // services so that it can finish performing any persistence/processing of in-memory state. if (psr.hasForegroundServices() && adj > ProcessList.PERCEPTIBLE_RECENT_FOREGROUND_APP_ADJ && (state.getLastTopTime() + mConstants.TOP_TO_FGS_GRACE_DURATION > now || state.getSetProcState() <= PROCESS_STATE_TOP)) { 。。。 } if (adj > ProcessList.PERCEPTIBLE_APP_ADJ || procState > PROCESS_STATE_TRANSIENT_BACKGROUND) { 。。。 } if (state.getCachedIsHeavyWeight()) { 。。。 } if (state.getCachedIsHomeProcess()) { 。。。 } if (state.getCachedIsPreviousProcess() && state.getCachedHasActivities()) { 。。。 } 。。。 for (int is = psr.numberOfRunningServices() - 1; is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > PROCESS_STATE_TOP); is--) { ServiceRecord s = psr.getRunningServiceAt(is); if (s.startRequested) { 。。。 } 。。。 } final ProcessProviderRecord ppr = app.mProviders; for (int provi = ppr.numberOfProviders() - 1; provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > PROCESS_STATE_TOP); provi--) { ContentProviderRecord cpr = ppr.getProviderAt(provi); for (int i = cpr.connections.size() - 1; i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > PROCESS_STATE_TOP); i--) { 。。。 } 。。。 } 。。。 if (s.isForeground) {
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)