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