Android應用程式的程序建立過程
阿新 • • 發佈:2021-03-17
[toc]
# 前言
我們知道當startActivity的時候,除了建立Activity相關實體,系統會根據需要是否建立程序,此程序就是指的Linux層面的程序實體;後面會說到,其實建立的過程是fork,意為從父程序“copy”出一個新的程序。此過程必定經歷啟動者、ams、zygote等相互的程序間通訊,本文主要梳理ams在此過程的重要環節,涉及虛擬機器的繼承、Binder執行緒池、訊息迴圈是怎麼建立的等等,而Activity的啟動細節則放在其他章節另作探討。
# 步驟
## step1 Ams發起請求startProcessLocked
*ActivityManagerService.java*
直接從Ams中向zygote發起請求的入口開始分析,當然真正的開始是Ams收到其他應用的Binder請求,所以應該在onTransact裡面才是真正的開始,待會兒會打出trace看。(這兒一個小細節,原始碼中有很多方法帶Locked字尾,說明使用該方法需要加鎖,因為其是非執行緒安全的)。
```
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
checkTime(startTime, "startProcess: returned from zygote!");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
```
比較重要的是這一段話,呼叫Process類的start方法,並指定了入口類為ActivityThread。
```
system 671 641 2348412 179992 0 0000000000 S Binder:641_1
641-671/system_process W: at android.os.Process.zygoteSendArgsAndGetResult(Process.java:605)
641-671/system_process W: at android.os.Process.startViaZygote(Process.java:738)
641-671/system_process W: at android.os.Process.start(Process.java:521)
641-671/system_process W: at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:4214)
641-671/system_process W: at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:4069)
641-671/system_process W: at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3909)
641-671/system_process W: at com.android.server.am.ActivityStackSupervisor.startSpecificActivityLocked(ActivityStackSupervisor.java:1441)
641-671/system_process W: at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:2741)
641-671/system_process W: at com.android.server.am.ActivityStack.resumeTopActivityUncheckedLocked(ActivityStack.java:2213)
641-671/system_process W: at com.android.server.am.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java:1859)
641-671/system_process W: at com.android.server.am.ActivityStack.completePauseLocked(ActivityStack.java:1393)
641-671/system_process W: at com.android.server.am.ActivityStack.activityPausedLocked(ActivityStack.java:1237)
641-671/system_process W: at com.android.server.am.ActivityManagerService.activityPaused(ActivityManagerService.java:7393)
641-671/system_process W: at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:571)
641-671/system_process W: at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3169)
641-671/system_process W: at android.os.Binder.execTransact(Binder.java:565)
```
從如上的trace可以直接看出,在收到startActivity的請求後,執行了對當前Activity的pause操作,然後通過Process.java這個類對Zygote程序發起請求。注意,通過對執行緒號的觀察可以看到,這一切都在一次binder執行緒中操作的。
注意Ams與Zygote之間是通過socket連線的,封裝了zygoteState類去做通訊相關的任務。從下圖fd的佔用可以明確地看到,zygote程序是不使用binder的。
```
device:/proc/341/fd # ls -l
ls -l
total 0
lrwx------ 1 root root 64 2021-03-16 17:49 0 -> /dev/null
lrwx------ 1 root root 64 2021-03-16 17:49 1 -> /dev/null
lr-x------ 1 root root 64 2021-03-16 17:49 10 -> /system/framework/core-oj.jar
lr-x------ 1 root root 64 2021-03-16 17:49 11 -> /system/framework/core-libart.jar
lr-x------ 1 root root 64 2021-03-16 17:49 12 -> /system/framework/conscrypt.jar
lr-x------ 1 root root 64 2021-03-16 17:49 13 -> /system/framework/okhttp.jar
lr-x------ 1 root root 64 2021-03-16 17:49 14 -> /system/framework/core-junit.jar
lr-x------ 1 root root 64 2021-03-16 17:49 15 -> /system/framework/bouncycastle.jar
lr-x------ 1 root root 64 2021-03-16 17:49 16 -> /system/framework/ext.jar
lr-x------ 1 root root 64 2021-03-16 17:49 17 -> /system/framework/framework.jar
lr-x------ 1 root root 64 2021-03-16 17:49 18 -> /system/framework/telephony-common.jar
lr-x------ 1 root root 64 2021-03-16 17:49 19 -> /system/framework/voip-common.jar
lrwx------ 1 root root 64 2021-03-16 17:49 2 -> /dev/null
lr-x------ 1 root root 64 2021-03-16 17:49 20 -> /system/framework/ims-common.jar
lr-x------ 1 root root 64 2021-03-16 17:49 21 -> /system/framework/apache-xml.jar
lr-x------ 1 root root 64 2021-03-16 17:49 22 -> /system/framework/org.apache.http.legacy.boot.jar
lrwx------ 1 root root 64 2021-03-16 17:49 23 -> socket:[9842]
lr-x------ 1 root root 64 2021-03-16 17:49 24 -> /system/framework/framework-res.apk
lr-x------ 1 root root 64 2021-03-16 17:49 25 -> /dev/urandom
l-wx------ 1 root root 64 2021-03-16 17:49 5 -> /sys/kernel/debug/tracing/trace_marker
lrwx------ 1 root root 64 2021-03-16 17:49 6 -> /dev/null
lrwx------ 1 root root 64 2021-03-16 17:49 7 -> /dev/null
lrwx------ 1 root root 64 2021-03-16 17:49 8 -> /dev/null
lrwx------ 1 root root 64 2021-03-16 17:49 9 -> socket:[9289]
```
Ams的呼叫棧到上面就截止了,接下來進入到Zygote程序中。
## step2 Zygote收到請求
猜想Zygote程序初始化完成後,一定有個無限迴圈在等待其他程序的請求,直接定位到程式碼。
```
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
A