Android10.0應用進程創建過程以及Zygote的fork流程


Android10.0應用進程創建過程以及Zygote的fork流程

閱讀本文大約需要花費1小時。

文章的內容主要還是從源碼進行分析,雖然又臭又長,但是如果想要學習Android系統源碼,這是必要走的路,沒有捷徑。

相對於碎片學習,我更傾向於靜下心來花費1個小時認真的學習一段內容。

專注於Android系統級源碼分析,Android的平臺設計,歡迎關注我,謝謝!

上一節我們講完了Launcher的啟動流程,這一節來看看應用進程的創建過程以及Zygote的fork流程。

系列文章:

1.概述

上一節我們學習了Launcher的啟動流程。這一節來介紹下應用進程的創建過程以及Zygote Fork的過程。

點擊桌面圖標啟動應用概述:

在上一節Launcher的啟動中我們知道了,手機的桌面其實就是Launcher進程,裡面的應用圖標都是Launcher通過ListView進行展示。

那麼我們點擊一個桌面圖標,比如微信,這個應用是如何啟動的呢,這一節我們從系統級的源碼來一步步的進行分析。

在分析之前,我們簡單區分一下進程和線程的概念。

在Android中通過Logcat抓取log時,存在PID和TID兩個概念。

PID:Process ID,進程ID

TID: Thread ID,線程ID

每個Android都是一個進程,每個進程有一個或多個線程

進程:

是併發執行的程序在執行過程中分配和管理資源的基本單位,是一個動態概念,競爭計算機系統資源的基本單位。

當我們點擊某個應用的圖標時,必須創建一個進程,該進程是由Zygote fork出來的,進程具有獨立的資源空間,用於承載App上運行的各種Activity/Service等組件。


線程:

是進程的一個執行單元,是進程內科調度實體。比進程更小的獨立運行的基本單位。線程也被稱為輕量級進程。

每個應用有多個線程,例如UI展示屬於UI主線程,一些通信過程屬於獨立線程,通常JAVA中使用new Thread().start()來創建一個新的線程。

該線程並沒有自己獨立的地址空間,而是與其所在進程之間資源共享。


進程線程的區別

  1. 地址空間:同一進程的線程共享本進程的地址空間,而進程之間則是獨立的地址空間。
  2. 資源擁有:同一進程內的線程共享本進程的資源,但是進程之間的資源是獨立的。
  3. 一個進程崩潰後,在保護模式下不會對其他進程產生影響,但是一個線程崩潰整個進程都死掉。所以多進程要比多線程健壯。
  4. 進程切換時,消耗的資源大,效率高。所以涉及到頻繁的切換時,使用線程要好於進程。同樣如果要求同時進行並且又要共享某些變量的併發操作,只能用線程不能用進程。
  5. 執行過程:每個獨立的進程有一個程序運行的入口、順序執行序列和程序入口。但是線程不能獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
  6. 線程是處理器調度的基本單位,但是進程不是。
  7. 兩者均可併發執行。

2.核心源碼


Android10.0應用進程創建過程以及Zygote的fork流程

3.架構

App發起進程:點擊一個桌面應用(例如微信),Launcher 加載應用, LauncherActivity收到觸發事件,組裝Intent,通過binder發送消息給SystemServer進程,調用Activity的startActivity()來啟動進程,啟動Activity時,受ActivityManagerService-AMS的服務控制,AMS屬於SystemServer進程,因此SystemServer進行會通過Process 來向Zygote發送一個Socket。

Zygote有一個無限循環,一直在等待Socket請求,收到SystemServer發來新的Socket請求後,Zygote調用系統的fork函數來孵化一個新的進程,比如這裡的微信。

再把啟動的入口交給ActivityThread,進入微信的進程中,進行詳細的UI展示。


3.1 進程創建圖

從點擊Launcher中的圖標,到啟動Activity,再到Zygote Fork操作,最終進入新的進行進行UI繪製。


Android10.0應用進程創建過程以及Zygote的fork流程

3.2 Zygote Fork圖

Zygote調用系統的fork()函數,孵化出一個新的進程,fork()採用copy-on-write機制,有些類如果不做改變,甚至都不用複製,子進程可以和父進程共享這部分數據,從而省去不少內存的佔用。

圖片來源Gityuan


Android10.0應用進程創建過程以及Zygote的fork流程

4.源碼分析

應用的啟動共分以下四個步驟完成:

  1. 點擊桌面的圖標,Launcher調用系統的startActivity進行啟動Activity,此時的動作在Launcher進程中
  2. ATM\\AMS 進行Activity的處理,組裝message,通過socket發送給Socket
  3. Zygote收到SystemServer發來的消息,進行消息拆分,再調用系統的fork()函數,進行進行孵化操作。
  4. 進入ActivityThread的main(),完成最終應用進程的的onCreate操作

接下來我們根據這四個步驟來進行詳細的源碼分析.


4.1 第一階段,點擊桌面圖標,觸發點擊事件

觸發Launcher listview的點擊事件 onListItemClick()

說明:桌面圖標按照5*5或者6*6的方式進行排列,這其實是Launcher進程展示的ListView,每個應用圖標填入其中,點擊圖標進入Launcher的點擊事件處理

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.1.1 [Activity.java]

startActivity()

說明:這裡比較簡單,調用

startActivityForResult()

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.1.2 [Activity.java]

startActivityForResult()

說明:不難發現,不論有沒有父Activity,最終都交給了 Instrumentation 來開啟

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.1.3 [Instrumentation.java]

execStartActivity()

說明:Binder 調用 ActivityTaskManagerService-ATM 來啟動 Activity

源碼:


Android10.0應用進程創建過程以及Zygote的fork流程

從下面代碼可以看到,IActivityTaskManager其實獲得的是activity_task對應服務的Binder對象,

即是ActivityTaskManagerService-ATM

Android10.0應用進程創建過程以及Zygote的fork流程

4.2 第二階段:ATM\\AMS 進行Activity的處理

調用棧如下:

Android10.0應用進程創建過程以及Zygote的fork流程

4.2.1 [ActivityTaskManagerService.java]

startActivity()

說明:

這裡很簡單,直接調用startActivityAsUser()

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.2.2 [ActivityTaskManagerService.java]

startActivityAsUser()

說明:獲取 ActivityStarter 對象,最終調用ActivityStarter的execute()

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.2.3 [ActivityStarter.java] execute()

說明:根據[4.2.2]中調用了setMayWait,因此這裡的mRequest.mayWait為true

源碼

Android10.0應用進程創建過程以及Zygote的fork流程

4.2.4 [ActivityStarter.java]

startActivityMayWait()

說明:調用startActivity()來啟動Activity

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.2.5 [ActivityStarter.java]

startActivity()

說明:延時佈局,然後通過startActivityUnchecked()來處理啟動標記 flag ,要啟動的

Android10.0應用進程創建過程以及Zygote的fork流程

4.2.6 [RootActivityContainer.java]

resumeFocusedStacksTopActivities()

說明:獲取棧頂的Activity,恢復它

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.2.7 [ActivityStackSupervisor.java]

startSpecificActivityLocked()

說明:

發佈消息以啟動進程,以避免在ATM鎖保持的情況下調用AMS時可能出現死鎖,最終調用到ATM的startProcess()

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.2.8 [ActivityManagerService.java]

startProcess()

說明:

一路調用Process start(),最終到ZygoteProcess的

attemptUsapSendArgsAndGetResult(),用來fork一個新的Launcher的進程

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

調用棧如下:

Android10.0應用進程創建過程以及Zygote的fork流程

4.2.9 [ZygoteProcess.java]

attemptZygoteSendArgsAndGetResult()

說明:通過Socket連接Zygote進程,把之前組裝的msg發給Zygote,其中processClass ="android.app.ActivityThread",通過Zygote進程來Fork出一個新的進程,

並執行 "android.app.ActivityThread"的main方法

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3 第三階段 Zygote Fork 應用進程

說明:Zygote的啟動過程我們前面有詳細講到過。

SystemServer的AMS服務向啟動Home Activity發起一個fork請求,Zygote進程通過Linux的fork函數,孵化出一個新的進程。

由於Zygote進程在啟動時會創建Java虛擬機,因此通過fork而創建的Launcher程序進程可以在內部獲取一個Java虛擬機的實例拷貝。

fork採用copy-on-write機制,有些類如果不做改變,甚至都不用複製,子進程可以和父進程共享這部分數據,從而省去不少內存的佔用。

調用棧如下:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.1 [ZygoteInit.java] main()

說明:Zygote先fork出SystemServer進程,接著進入循環等待,用來接收Socket發來的消息,用來fork出其他應用進程,比如Launcher

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.2 [ZygoteConnection.java]

processOneCommand()

說明:通過 forkAndSpecialize()來fork出Launcher的子進程,並執行handleChildProc,進入子進程的處理

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.3 [Zygote.java] forkAndSpecialize

說明:主要是調用dalvik中ZygoteHooks的preFrok進行預處理,再調用postForkCommon進行完成的進程fork

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.3.1 [ZygoteHooks.java] preFork()

說明:Zygote進程有4個Daemon子線程分別是

HeapTaskDaemon、

ReferenceQueueDaemon、

FinalizerDaemon、

FinalizerWatchdogDaemon

preFork()預處理主要是先停止4個子線程,等待所有的子線程結束,最後完成gc堆的初始化工作

Zygote子線程如下圖所示:

Android10.0應用進程創建過程以及Zygote的fork流程

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.3.2 [Daemons.java] stop()

說明:此處守護線程Stop方式是先調用目標線程interrrupt()方法,然後再調用目標線程join()方法,等待線程執行完成

停止4個子線程,分別是:Java堆整理線程;引用隊列線程;析構線程;析構監控線程

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.3.3 [ZygoteHooks.java]

waitUntilAllThreadsStopped()

說明:等待所有子線程結束

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.4 [ZygoteHooks.java]

nativePreFork()

通過JNI最終調用的是以下方法:

[dalvik_system_ZygoteHooks.cc] ZygoteHooks_nativePreFork()

說明:進行堆的一些預處理

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.4.1 [runtime.cpp] PreZygoteFork()

說明:堆的初始化工作,屬於虛擬機的範疇,想理解的可以深挖一下

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.5 [Zygote.java]

nativeForkAndSpecialize()

通過JNI最終調用的是以下方法:

[com_android_internal_os_Zygote.cpp] com_android_internal_os_Zygote_nativeForkAndSpecialize

說明: fork 子進程

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.5.1 [com_android_internal_os_Zygote.cpp]

ForkCommon()

說明:調用系統的fork()進行 應用進程的孵化操作,採用copy-on-write的機制,使得應用進程與Zygote共享部分數據,減少內存的佔用

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.5.2 [com_android_internal_os_Zygote.cpp]

SpecializeCommon()

說明:進行進程的一些資源處理,selinux權限處理,並調用Zygote的callPostForkChildHooks()

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.5.3 [Zygote.java]

callPostForkChildHooks()

說明:JAVA堆線程的一些處理

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

創建JAVA的線程池,設置信號處理,啟動JDWP線程

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.6 [ZygoteHooks.java] postForkCommon()

說明:在fork新進程後,啟動Zygote的4個Daemon線程,java堆整理,引用隊列,以及析構線程。

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

啟動Zygote的4個新的子線程

Android10.0應用進程創建過程以及Zygote的fork流程

4.3.7 [ZygoteConnection.java]

handleChildProc()

說明:進行子進程的操作,最終獲得需要執行的ActivityThread的main()

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

zygoteInit 進行一些環境的初始化、啟動Binder進程等操作

Android10.0應用進程創建過程以及Zygote的fork流程

把之前傳來的"android.app.ActivityThread" 傳遞給findStaticMain

Android10.0應用進程創建過程以及Zygote的fork流程

通過反射,拿到ActivityThread的main()方法

Android10.0應用進程創建過程以及Zygote的fork流程

把反射得來的ActivityThread main()入口返回給ZygoteInit的main,通過caller.run()進行調用

Android10.0應用進程創建過程以及Zygote的fork流程

至此,Zygote fork進程的操作全部完成,下一步進入JAVA世界,進行真正的Activity的啟動流程。


4.4 第四階段 進入應用進程,啟動Activity的onCreate()

調用棧如下:

Android10.0應用進程創建過程以及Zygote的fork流程

4.4.1 [ActivityThread.java] main()

說明: 主線程處理, 創建ActivityThread對象,調用attach進行處理,最終進入Looper循環

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

調用ActivityThread的attach進行處理

Android10.0應用進程創建過程以及Zygote的fork流程

4.4.2 [ActivityManagerService.java]
attachApplication()

說明:清除一些無用的記錄,最終調用ActivityStackSupervisor.java的 realStartActivityLocked(),進行Activity的啟動

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.4.3 [ActivityStackSupervisor.java]

realStartActivityLocked()

說明:真正準備去啟動Activity,通過clientTransaction.addCallback把LaunchActivityItem的obtain作為回調參數加進去,再調用

ClientLifecycleManager.scheduleTransaction()得到LaunchActivityItem的execute()方法進行最終的執行

參考上面的第四階段的調用棧流程:

Android10.0應用進程創建過程以及Zygote的fork流程

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.4.4 [TransactionExecutor.java] execute()

說明:執行之前realStartActivityLocked()中的

clientTransaction.addCallback

調用棧:

Android10.0應用進程創建過程以及Zygote的fork流程

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.4.5 [ActivityThread.java]

handleLaunchActivity()

說明:主要乾了兩件事,第一件:初始化WindowManagerGlobal;第二件:調用performLaunchActivity方法

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

4.4.6 [ActivityThread.java]

performLaunchActivity()

說明:獲取ComponentName、Context,反射創建Activity,設置Activity的一些內容,比如主題等;

最終調用callActivityOnCreate()來執行Activity的onCreate()方法

源碼:

Android10.0應用進程創建過程以及Zygote的fork流程

callActivityOnCreate先執行activity onCreate的預處理,再去調用Activity的onCreate,最終完成Create創建後的內容處理

Android10.0應用進程創建過程以及Zygote的fork流程

performCreate()主要調用Activity的onCreate()

Android10.0應用進程創建過程以及Zygote的fork流程

至此,看到了我們最熟悉的Activity的onCreate(),應用啟動的啟動完成,應用程序被真正的調用起來。


5.總結

通過上面一系列的流程,我們理解了應用進程的創建流程,以及Zygote fork這些應用進程的流程。

主要分為4步完成

  1. 點擊桌面的圖標,Launcher調用系統的startActivity進行啟動Activity,此時的動作在Launcher進程中
  2. 通過Binder向SystemServer進行發送消息,讓ATM\\AMS 進行Activity的處理,組裝message,通過socket發送給Socket,此時動作在SystemServer進程中
  3. Zygote收到SystemServer發來的消息,進行消息拆分,再調用系統的fork()函數,進行進行孵化操作,此時動作在Zygote進程中
  4. 進入ActivityThread的main(),完成最終應用進程的的onCreate操作,該步動作處於新創建的應用進程中



分享到:


相關文章: