【系統之音】Android進程的創建及啓動簡述 【系統之音】Android系統啓動篇

       Android系統中的進程(這裏不包括init等底層的進程)都是通過Zygote fork而來的,那這些進程的啓動流程都是怎樣的呢?

       這裏將Android進程分爲兩個部分:

    (1)系統框架進程SystemServer進程。它是Zygote創建的第一個進程,是在系統啓動過程中,Zygote進程啓動時直接fork而來的。

    (2)應用程序進程。比如Launcher、SystemUI,其它應用程序等的進程。這些應用程序進程的啓動大致包含兩個步驟:

            1)AMS向Zygote進程發送創建進程的請求;

            2)Zygote接受請求,創建並啓動應用程序進程。

        本文將圍繞上述幾點,基於Android P(API28)的源碼,來梳理Android進程的創建與啓動過程。內容的主要對象是應用開發者,所以力求簡潔和完整,內容大體如下:

 

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線程中切換到主線程中。

       這裏總結一下普通應用程序進程創建時的關鍵工作:

    (1)通過fork得到一個虛擬機實例副本;

    (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進階解密》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章