一 進(jìn)程介紹
安卓基于Linux內(nèi)核揽乱,設(shè)備開(kāi)機(jī)后,第一個(gè)安卓進(jìn)程為zygote進(jìn)程憋肖,隨后fork system_server(上層)萌衬,其他上層進(jìn)程需要通過(guò)fork system-server進(jìn)程來(lái)創(chuàng)建。因此進(jìn)程的創(chuàng)建毕源、調(diào)度浪漠、銷(xiāo)毀是進(jìn)程篇的核心內(nèi)容。
- 進(jìn)程的創(chuàng)建[四大組件通過(guò)ams啟動(dòng)進(jìn)程]
- 進(jìn)程的調(diào)度[前臺(tái)進(jìn)程霎褐、后臺(tái)進(jìn)程址愿、可見(jiàn)/不可見(jiàn)進(jìn)程、緩存進(jìn)程]
- 當(dāng)進(jìn)程查殺[根據(jù)進(jìn)程當(dāng)前狀態(tài)來(lái)決定查殺內(nèi)容]
用戶打開(kāi)app/切換app冻璃,都希望能夠快速的完成這個(gè)操作必盖。應(yīng)用數(shù)據(jù)未被加載時(shí)拌牲,進(jìn)程不存在,需要冷啟動(dòng)歌粥。當(dāng)啟動(dòng)了大量的進(jìn)程后塌忽,系統(tǒng)內(nèi)存空間吃緊,那么如何查殺進(jìn)程又是一個(gè)問(wèn)題失驶。因此在進(jìn)程啟動(dòng)時(shí)需要根據(jù)啟動(dòng)意圖來(lái)更新lru進(jìn)程的重要性土居,在查殺時(shí)有策略的查殺。
這個(gè)進(jìn)程重要性的更新機(jī)制就是OomAdjuster
二 進(jìn)程調(diào)度介紹
oomadj官方文檔
https://android.googlesource.com/platform/frameworks/base/+/master/services/core/java/com/android/server/am/OomAdjuster.md
重點(diǎn)總結(jié):
The Android OS runs with limited hardware resources, i.e. CPU/RAM/Power. To strive for the better performance, Oom Ajuster is introduced to tweak the following 3 major factors:
- Process State
- Wildly used by the System Server, i.e., determine if it's foreground or not, change the GC behavior, etc.
- Defined in ActivityManager#PROCESS_STATE_*
- Oom Adj score
- Used by the lmkd to determine which process should be expunged on memory pressure.
- Defined in ProcessList#*_ADJ
- Scheduler Group
- Used to tweak the process group, thread priorities.
- Top process is scheduled to be running on a dedicated big core, while foreground processes take the other big cores; background processes stay with LITTLE cores instead.
翻譯一下重點(diǎn)在于三個(gè)值的更新
- 更新進(jìn)程狀態(tài).
[computeOomAdjLSP]
state.setCurProcState(procState);
- 更新oom分?jǐn)?shù).
[computeOomAdjLSP]
state.setCurAdj(adj);
- 更新進(jìn)程所屬的進(jìn)程組.
switch (curSchedGroup) {
case SCHED_GROUP_BACKGROUND:
processGroup = THREAD_GROUP_BACKGROUND;
break;
case SCHED_GROUP_TOP_APP:
case SCHED_GROUP_TOP_APP_BOUND:
processGroup = THREAD_GROUP_TOP_APP;
break;
case SCHED_GROUP_RESTRICTED:
processGroup = THREAD_GROUP_RESTRICTED;
break;
default:
processGroup = THREAD_GROUP_DEFAULT;
break;
}
4.1 computeOomAdjLSP更新oomadj與procState
// Do final modification to adj. Everything we do between here and applying
// the final setAdj must be done in this function, because we will also use
// it when computing the final cached adj later. Note that we don't need to
// worry about this for max adj above, since max adj will always be used to
// keep it out of the cached vaues.
state.setCurAdj(adj);
state.setCurCapability(capability);
state.setCurrentSchedulingGroup(schedGroup);
state.setCurProcState(procState);
state.setCurRawProcState(procState);
state.updateLastInvisibleTime(hasVisibleActivities);
state.setHasForegroundActivities(foregroundActivities);
state.setCompletedAdjSeq(mAdjSeq);
state.setCurBoundByNonBgRestrictedApp(boundByNonBgRestricted);
// if curAdj or curProcState improved, then this process was promoted
return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
|| state.getCurCapability() != prevCapability;
4.2 applyOomAdjLSP設(shè)置進(jìn)程所屬狀態(tài)組
computeOomAdjLSP更新完oomadj與procState后通過(guò)applyOomAdjLSP來(lái)更新凍結(jié)情況與設(shè)置進(jìn)程狀態(tài)組
/** Applies the computed oomadj, procstate and sched group values and freezes them in set* */
@GuardedBy({"mService", "mProcLock"})
private boolean applyOomAdjLSP(ProcessRecord app, boolean doingAll, long now,
long nowElapsed, @OomAdjReason int oomAdjReson) {
// 省略嬉探。擦耀。
switch (curSchedGroup) {
case SCHED_GROUP_BACKGROUND:
processGroup = THREAD_GROUP_BACKGROUND;
break;
case SCHED_GROUP_TOP_APP:
case SCHED_GROUP_TOP_APP_BOUND:
processGroup = THREAD_GROUP_TOP_APP;
break;
case SCHED_GROUP_RESTRICTED:
processGroup = THREAD_GROUP_RESTRICTED;
break;
default:
processGroup = THREAD_GROUP_DEFAULT;
break;
}
mProcessGroupHandler.sendMessage(mProcessGroupHandler.obtainMessage(
0 /* unused */, app.getPid(), processGroup, app.processName));
---分割線
【OomAdjuster-mProcessGroupHandler】
mProcessGroupHandler = new Handler(adjusterThread.getLooper(), msg -> {
final int pid = msg.arg1;
final int group = msg.arg2;
if (pid == ActivityManagerService.MY_PID) {
// Skip setting the process group for system_server, keep it as default.
return true;
}
if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setProcessGroup "
+ msg.obj + " to " + group);
}
try {
//調(diào)用native方法設(shè)置進(jìn)程組
setProcessGroup(pid, group);
} catch (Exception e) {
if (DEBUG_ALL) {
Slog.w(TAG, "Failed setting process group of " + pid + " to " + group, e);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
return true;
});
---分割線
【Process.java】
/**
* Sets the scheduling group for a process and all child threads
* @hide
* @param pid The identifier of the process to change.
* @param group The target group for this process from THREAD_GROUP_*.
*
* @throws IllegalArgumentException Throws IllegalArgumentException if
* <var>tid</var> does not exist.
* @throws SecurityException Throws SecurityException if your process does
* not have permission to modify the given thread, or to use the given
* priority.
*
* group == THREAD_GROUP_DEFAULT means to move all non-background priority
* threads to the foreground scheduling group, but to leave background
* priority threads alone. group == THREAD_GROUP_BACKGROUND moves all
* threads, regardless of priority, to the background scheduling group.
* group == THREAD_GROUP_FOREGROUND is not allowed.
*
* Always sets cpusets.
*/
@UnsupportedAppUsage
public static final native void setProcessGroup(int pid, int group)
throws IllegalArgumentException, SecurityException;
每個(gè)進(jìn)程計(jì)算oom時(shí)機(jī),計(jì)算oom過(guò)程涩堤,計(jì)算oom結(jié)果保存眷蜓,計(jì)算結(jié)果應(yīng)用則是幾個(gè)重點(diǎn)的分析方向。
進(jìn)程重要性
2.1 Process State
[ActivityManager.java]
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT;
import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
2.2 OOM_ADJ
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ACTIVITY;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ALLOWLIST;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BACKUP;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_BIND_SERVICE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_COMPONENT_DISABLED;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_EXECUTING_SERVICE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_FINISH_RECEIVER;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_GET_PROVIDER;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_NONE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_BEGIN;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_PROCESS_END;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_PROVIDER;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_REMOVE_TASK;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_RESTRICTION_CHANGE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHELL;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHORT_FGS_TIMEOUT;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_RECEIVER;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_START_SERVICE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_STOP_SERVICE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SYSTEM_INIT;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UID_IDLE;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UI_VISIBILITY;
import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UNBIND_SERVICE;
2.3 Scheduler Group
import static android.os.Process.SCHED_OTHER;
import static android.os.Process.THREAD_GROUP_BACKGROUND;
import static android.os.Process.THREAD_GROUP_DEFAULT;
import static android.os.Process.THREAD_GROUP_RESTRICTED;
import static android.os.Process.THREAD_GROUP_TOP_APP;
import static android.os.Process.THREAD_PRIORITY_DISPLAY;
import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST;
import static android.os.Process.setProcessGroup;
import static android.os.Process.setThreadPriority;
import static android.os.Process.setThreadScheduler;