Android的程序都是通過Zygote fork而來的,那這些程序的啟動流程都是怎樣的呢?本文将基于Android P的源碼來分析Android系統架構程序SystemServer和應用程式程序的建立過程,力求完整和簡潔,隻關注關鍵流程。
Android系統中的程序(這裡不包括init等底層的程序)都是通過Zygote fork而來的,那這些程序的啟動流程都是怎樣的呢?
這裡将Android程序分為兩個部分:
(1)系統架構程序SystemServer程序。它是Zygote建立的第一個程序,是在系統啟動過程中,Zygote程序啟動時直接fork而來的。
(2)應用程式程序。比如Launcher、SystemUI,其它應用程式等的程序。這些應用程式程序的啟動大緻包含兩個步驟:
1)AMS向Zygote程序發送建立程序的請求;
2)Zygote接受請求,建立并啟動應用程式程序。
本文将圍繞上述幾點,基于Android P(API28)的源碼,來梳理Android程序的建立與啟動過程。内容的主要對象是應用開發者,是以力求簡潔和完整,内容大體如下:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL2czNxUDMwczMtEzN1EjMwITOwYTM5ADMyAjMtIDMwIzN08CX5ADMyAjMvwlMwAjM3QzLcd2bsJ2Lc12bj5ycn9Gbi52YuAjMwIzZtl2Lc9CX6MHc0RHaiojIsJye.png)
1、Zygote程序啟動簡述
在了解這一部分前,建議先閱讀【系統之音】Android系統啟動篇。
系統在啟動時,會啟動一個名為“init”的系統程序,然後該程序會建立并啟動Zygote程序。建立和啟動Zygote程序的過程,先後從Nativie層跨入Java層,在Native層會建立虛拟機執行個體(即ART執行個體),然後通過JNI的方式調用ZygoteInit類的main方法。Native層的代碼咱們不深究,這裡看看main方法:
1 //(代碼1.1)=========ZygoteInit.java=====
2 public static void main(String argv[]) {
3 ZygoteServer zygoteServer = new ZygoteServer();
4 ......
5 String socketName = "zygote";
6 ......
7 //建立一個名為“zygote”的Server端Socket,在後續會一直監聽AMS發起的建立新程序的請求。
8 zygoteServer.registerServerSocketFromEnv(socketName);
9 ......
10 //①通過fork方式建立SystemServer程序并啟動
11 if (startSystemServer) {
12 Runnable r = forkSystemServer(abiList, socketName, zygoteServer);//fork建立SystemServer程序
13 ......
14 if (r != null) {
15 r.run();//啟動SystemServer程序
16 return;
17 }
18 }
19 //②該方法中使用了一個while(true)的無限循環來實作一直監聽AMS的請求
20 caller = zygoteServer.runSelectLoop(abiList);
21 ......
22 //③這裡是會執行子程序(應用程式程序)的ActivityThread的main方法,後文會講到
23 if (caller != null) {
24 caller.run();
25 }
26 }
我抽取了關鍵的代碼,主要是關注Zygote啟動期間所做的主要工作,這裡先給出結論(有必要牢記于心):
(1)建立虛拟機執行個體;
(2)建立一個名為“zygote”的Server端Socket,用于後續監聽AMS的請求;
(3)通過fork的方式建立SystemServer程序并啟動它,該過程會啟動各種系統服務,AMS就是在這個階段啟動的;
(4)在runSelectLoop方法中通過一個while(true)無限循環來實作對AMS的監聽;
(5)啟動非SystemServer程序。
2、Zygote建立與啟動SystemServer
實際上SystemServer是Zygote建立出的第一個程序,我們從代碼1.1中的注釋②處的forkSystemServer方法來深入了解:
1 //代碼2.1==========ZygoteInit.java=======
2 private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {
3 ......
4 int pid;
5 ......
6 //fork的過程發生在Native層
7 pid = Zygote.forkSystemServer(...);
8 ......
9 //④pid為0表示子程序(即SystemServer程序)建立成功,邏輯進入到子程序中。下面的邏輯會啟動SystemServer程序
10 if (pid == 0) {
11 ......
12 return handleSystemServerProcess(parsedArgs);
13 }
14 }
15
16 public static int forkSystemServer(...){
17 ......
18 int pid = nativeForkSystemServer(...);
19 ......
20 }
21
22 native private static int nativeForkSystemServer(...)
可見,forkSystemServer程序是發生在Native層的,接着繼續從注釋④處看看SystemServer程序的啟動:
1 //代碼2.2 =========ZygoteInit.java========
2 private static Runnable handleSystemServerProcess(...){
3 ......
4 return ZygoteInit.zygoteInit(...);
5 }
6
7 public static final Runnable zygoteInit(...) {
8 ......
9 //該處用于建立Binder線程池,此後SystemServer程序就可以使用Binder來實作IPC了。該過程也是在Native層實作,Binder在ServiceManager中進行注冊。
10 ZygoteInit.nativeZygoteInit();
11 return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
12 }
13
14 private static final native void nativeZygoteInit();
15
16 //==========RuntimeInit.java=======
17 protected static Runnable applicationInit(...){
18 ......
19 //通過上下文可以得知這裡的args.startClass值為“com.android.server.SystemServer”
20 return findStaticMain(args.startClass, args.startArgs, classLoader);
21 }
22
23 /**
24 * Invokes a static "main(argv[]) method on class "className".
25 * ......
26 */
27 protected static Runnable findStaticMain(String className, String[] argv,
28 ClassLoader classLoader) {
29 Class<?> cl;
30 try {
31 cl = Class.forName(className, true, classLoader);
32 } catch (ClassNotFoundException ex) {
33 throw new RuntimeException(
34 "Missing class when invoking static main " + className,
35 ex);
36 }
37 Method m;
38 try {
39 m = cl.getMethod("main", new Class[] { String[].class });
40 } catch (NoSuchMethodException ex) {
41 throw new RuntimeException(
42 "Missing static main on " + className, ex);
43 } catch (SecurityException ex) {
44 throw new RuntimeException(
45 "Problem getting static main on " + className, ex);
46 }
47 int modifiers = m.getModifiers();
48 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
49 throw new RuntimeException(
50 "Main method is not public and static on " + className);
51 }
52 ...... //毫無疑問,這裡的m就是SystemServer類的main方法了
53 return new MethodAndArgsCaller(m, argv);
54 }
55
56 static class MethodAndArgsCaller implements Runnable {
57 /** method to call */
58 private final Method mMethod;
59 /** argument array */
60 private final String[] mArgs;
61 public MethodAndArgsCaller(Method method, String[] args) {
62 mMethod = method;
63 mArgs = args;
64 }
65 public void run() {
66 try {
67 mMethod.invoke(null, new Object[] { mArgs });
68 }
69 ......
70 }
71 }
一步步跟進時,我們會發現該過程中主線都是傳回的Runnable類型的對象,回到代碼1.1的注釋②處的第12行,這裡的 r 就是MethodAndArgsCaller對象,第13行r.run()執行,就是調用的上述代碼第67行,跟蹤上下文可知這裡就是執行的SystemServer.main方法。緊接着第14行是return,Zygote就完成了建立和啟動SystemServer程序。此時你是否會有疑問:這裡就return了,那後面監聽AMS請求和啟動非SystemServer程序的邏輯又如何實作呢?這裡我們需要了解“fork”,後面我們會詳細介紹。
這裡進一步看看SystemServer程序中都做了些什麼:
1 //=========SystemServer.java===========
2 public static void main(String[] args) {
3 new SystemServer().run();
4 }
5 private void run() {
6 ......
7 //建立消息Looper
8 Looper.prepareMainLooper();
9 // 加載動态庫libandroid_servers.so,初始化native服務
10 System.loadLibrary("android_servers");
11 ......
12 //初始化系統context
13 createSystemContext();
14 //建立SystemServiceManager
15 mSystemServiceManager = new SystemServiceManager(mSystemContext);
16 ......
17 //啟動引導服務,如AMS等
18 startBootstrapServices();
19 //啟動核心服務
20 startCoreServices();
21 //啟動其它服務,如WMS,SystemUI等
22 startOtherServices();
23 ....
24 // Loop forever.
25 Looper.loop();
26 }
到這裡Zygote就建立并啟動了SystemServe程序,總結一下這個過程中主要做了些什麼工作:
(1)通過fork得到一個虛拟機執行個體副本;
(2)建立Binder線程池,SystemServer可以通過Binder來實作IPC(跨程序通信);
(3)啟動系統服務,比如AMS,WMS等;
(4)建立消息循環,Looper.loop()中是一個無限循環,SystemServer将持續運作。
3、fork簡介
在前文中提到了使用fork的方式來建立程序,也提到了一個疑問:
“此時你是否會有疑問:這裡就return了,那後面監聽AMS請求和啟動非SystemServer程序的邏輯又如何實作呢?”
這裡先看看百度百科的介紹:
“複刻(英語:fork,又譯作派生、分支)是UNIX或類UNIX中的分叉函數,fork函數将運作着的程式分成2個(幾乎)完全一樣的程序,
每個程序都啟動一個從代碼的同一位置開始執行的線程。這兩個程序中的線程繼續執行,就像是兩個使用者同時啟動了該應用程式的兩個副本。
fork系統調用用于建立一個新程序,稱為子程序,它與程序(稱為系統調用fork的程序)同時運作,此程序稱為父程序。建立新的子程序後,
兩個程序将執行fork()系統調用之後的下一條指令。子程序使用相同的pc(程式計數器),相同的CPU寄存器,在父程序中使用的相同打開檔案。”
是以,在代碼1.1中forkSystemServer時,Zygote程序會分化為兩個一模一樣的程序來,其中一個是父程序,另外一個是子程序,它是主程序的副本。當SystemServer fork成功後其流程就進入到了子程序中,即代碼1.1中的第15、16行是在子程序中執行的。而與此同時,父程序還會繼續往下執行,不斷監聽AMS的請求以及啟動新的程序。
要更好地了解fork後Zygote程序和子程序的工作,可以參考閱讀:https://www.cnblogs.com/jiangzhaowei/p/11023098.html。
4、Zygote監聽AMS的請求
在代碼1.1中注釋②處,會通過調用runSelectLoop方法來監聽AMS的請求,我們看看該方法的實作:
1 //代碼4.1======ZygoteServer.java======
2 Runnable runSelectLoop(String abiList) {
3 ......
4 ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
5 ......
6 while (true) {
7 ......
8 //⑤當監聽到AMS請求的資料時會執行這裡
9 ZygoteConnection connection = peers.get(i);
10 final Runnable command = connection.processOneCommand(this);
11 ......
12 return command;
13 }
14 }
這其中包含了一個while(true)的無限循環,以此來一直監聽AMS的請求,直到注釋⑤處監聽到了AMS的請求,fork出新的子程序(應用程式程序),随後在子程序中return,結束監聽。和fork SystemServer一樣,父程序Zygote仍然繼續監聽着,繼續相應AMS新的請求,fork出新的子程序。
5、AMS向Zygote程序發起建立程序的請求
要啟動一個程式時,系統首先會判斷該程式所在的程序是否存在,如果不存在就需要先建立并啟動目标程式對應的程序。這一點在四大元件元件啟動流程的源碼中都有展現,當發現目标程序還不存在時,AMS都會向Zygote程序申請建立目标程序。這個過程分為兩步:(1)AMS向Zygote程序發起建立程序的請求;(2)Zygote收到請求,建立并啟動程序。這一節我們先看看第(1)步:
1 //==============ActivityManagerService.java============
2 private final boolean startProcessLocked(ProcessRecord app, String hostingType,
3 String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
4 ......
5 final String entryPoint = "android.app.ActivityThread";
6 return startProcessLocked(hostingType, hostingNameStr, entryPoint...);
7 }
8 private boolean startProcessLocked(...String entryPoint...) {
9 ......
10 final ProcessStartResult startResult = startProcess(...entryPoint...);
11 }
12 private ProcessStartResult startProcess(...String entryPoint...){
13 ......
14 final ProcessStartResult startResult;
15 ......
16 startResult = Process.start(entryPoint,
17 app.processName, uid, uid, gids, runtimeFlags, mountExternal,
18 app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
19 app.info.dataDir, invokeWith,
20 new String[] {PROC_START_SEQ_IDENT + app.startSeq});
21 ......
22 }
23 //================Process.java==============
24 public static final ZygoteProcess zygoteProcess = new ZygoteProcess(ZYGOTE_SOCKET, SECONDARY_ZYGOTE_SOCKET);
25 public static final ProcessStartResult start(final String processClass,...) {
26 return zygoteProcess.start(processClass, ...);
27 }
28 //==============ZygoteProcess.java==========
29 public final Process.ProcessStartResult start(final String processClass...) {
30 try {
31 return startViaZygote(processClass...);
32 }......
33 }
34 private Process.ProcessStartResult startViaZygote(final String processClass...){
35 argsForZygote.add(processClass);
36 ......
37 return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
38 }
39 private ZygoteState primaryZygoteState;
40 ......
41 private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
42 ......
43 //追蹤代碼,容易得知mSocket值為"zygote",這裡的作用是連接配接名為“zygote”的Socket
44 primaryZygoteState = ZygoteState.connect(mSocket);
45 ......
46 }
從上述代碼可以看出,該過程的邏輯其實挺簡單,通過層層調用後走到第50行。這一行的作用就是和名為“zygote”的Socket服務端建立連接配接,這樣就向Zygote程序發起了請求。這裡的ZygoteState類中的
6、Zygote收到AMS的請求,建立并啟動程序
在代碼4.1中,我們講過,其中while(true)循環一直監聽AMS的請求,直到收到請求。
1 //===========ZygoteConnection.java=======
2 Runnable processOneCommand(ZygoteServer zygoteServer) {
3 ......
4 //⑥fork方式建立應用程式程序
5 pid = Zygote.forkAndSpecialize(...);
6 ......
7 //pid為0表示目前的代碼邏輯運作在新建立的子程序(即應用程式程序)中
8 if (pid == 0) {
9 // in child
10 ......
11 //處理應用程式程序
12 return handleChildProc(parsedArgs, descriptors, childPipeFd,
13 parsedArgs.startChildZygote);
14 } else {
15 ......
16 }
17 }
18
19 private Runnable handleChildProc(...){
20 ......
21 return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,null /* classLoader */);
22 }
23 //=====ZygoteInit.java========
24 public static final Runnable zygoteInit(...) {
25 ......
26 //建立Binder線程池,此後新的子程序就能夠使用Binder進行IPC了
27 ZygoteInit.nativeZygoteInit();
28 return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
29 }
30
31 //============Zygote.java==========(補充注釋⑥處)
32 public static int forkAndSpecialize(...) {
33 ........
34 int pid = nativeForkAndSpecialize(...);
35 ......
36 return pid;
37 }
38 native private static int nativeForkAndSpecialize(...);
流程走到第26行就比較清晰了,和代碼2.2中啟動SystemServer程序一緻了,隻不過這裡啟動的是ActivityThread的main方法。
1 //=======ActivityThread.java=====
2 static volatile Handler sMainThreadHandler;
3
4 public static void main(String[] args) {
5 ......
6 Looper.prepareMainLooper();
7 ......
8 ActivityThread thread = new ActivityThread();
9 ......
10 if (sMainThreadHandler == null) {
11 sMainThreadHandler = thread.getHandler();
12 }
13 ......
14 Looper.loop();
15 }
16
17 final Handler getHandler() {
18 return mH;
19 }
20
21 final H mH = new H();
22
23 class H extends Handler {
24 ......
25 }
ActivityThread類是主線程的管理類,其main方法中會建立消息循環,其中Looper.loop()方法中通過無限循環的方式,保持主線程一直運作。同時還會建立主線程的H類,這是一個包含主線程looper的Handler,四大元件啟動過程中都需要通過這個H類對象來從Binder線程中切換到主線程中。
這裡總結一下普通應用程式程序建立時的關鍵工作:
(2)建立Binder線程池,應用程式程序就可以通過Binder來實作IPC;
(3)建立消息循環,建立主線程的H類。
7、疑問
(1)為什麼AMS(SystemServer程序)與Zygote程序通訊采用Socket而不是Binder?
答:因為fork不允許存在多線程,而Binder通信偏偏就是多線程。(不知道該答案是否準确,目前還沒找到權威答案)。
可以參考:https://blog.csdn.net/qq_39037047/article/details/88066589
參考及推薦閱讀:
https://www.cnblogs.com/andy-songwei/p/11429421.html
https://www.cnblogs.com/jiangzhaowei/p/11023098.html
https://www.jianshu.com/p/ab9b83a77af6
https://blog.csdn.net/qq_39037047/article/details/88066589
劉望舒《Android進階解密》