在電腦啟動過程和Linux內核Kernel啟動過程介紹了電腦啟動和內核載入,本篇文章主要介紹Android系統是如何啟動的。 一、Android啟動流程 Android系統的啟動流程與Linux接近: sequenceDiagram participant Bootloader as 引導載入程 ...
在
電腦啟動過程
和Linux內核Kernel啟動過程
介紹了電腦啟動和內核載入,本篇文章主要介紹Android系統是如何啟動的。
一、Android啟動流程
Android系統的啟動流程與Linux接近:
sequenceDiagram participant Bootloader as 引導載入程式 participant Kernel as 內核 participant Init as init 進程 participant Zygote as Zygote 進程 participant SystemServices as 系統服務 participant Launcher as 應用程式(桌面) Bootloader->>Kernel: 載入內核 Kernel->>Kernel: 初始化 Kernel->>Init: 啟動 init 進程 Init->>Init: 讀取系統配置文件 Init->>Zygote: 啟動 Zygote 進程 Zygote->>Zygote: 預載入常用的 Java 類和資源 Zygote->>SystemServices: 啟動系統服務 SystemServices->>Launcher: 啟動桌面程式- 1.引導載入程式(Bootloader)啟動: 當設備上電或者重啟時,首先會由引導載入程式負責啟動。引導載入程式通常存儲在設備的固件中,它的主要任務是初始化硬體,並載入並啟動操作系統內核。引導載入程式會首先運行自身的初始化代碼,然後載入操作系統內核到記憶體中。
- 2.內核載入: 引導載入程式會根據預定義的配置從設備存儲中載入操作系統內核。在Android設備中,通常使用的是Linux內核。引導載入程式將內核載入到記憶體中的指定位置。
- 3.內核初始化: 一旦內核載入到記憶體中,引導載入程式會將控制權轉交給內核。內核開始執行初始化過程,包括對硬體進行初始化、建立虛擬文件系統、創建進程和線程等。
- 4.啟動 init 進程: 內核初始化完成後,會啟動名為init的用戶空間進程。init進程是Android系統的第一個用戶空間進程,它負責系統的進一步初始化和啟動。init進程會讀取系統配置文件(例如 init.rc),並根據其中的指令啟動系統服務和應用程式。
- 5.啟動 Zygote 進程: 在init進程啟動後,會啟動名為Zygote的進程。Zygote進程是Android應用程式的孵化器,它會預載入常用的Java類和資源,以加速應用程式的啟動。
- 6.啟動系統服務: 在Zygote進程啟動後,還會啟動一系列系統服務,例如SurfaceFlinger、ActivityManager、PackageManager等。這些系統服務負責管理系統的各個方面,包括顯示、應用程式生命周期、包管理等。
- 7.啟動桌面程式: 一旦系統服務啟動完成,Android系統就處於可用狀態。就會啟動桌面程式,用戶可以開始啟動應用程式並使用設備進行各種操作了。
在電腦啟動過程
和Linux內核Kernel啟動過程
已經介紹了電腦啟動和內核載入,所以本篇文章從Zygote進程
開始介紹。
二、Zygote進程(孵化器進程)
1.Zygote簡介
- Zygote進程是一個用戶進程,由init進程(1號進程)fork而來。
- Zygote進程的主要任務是載入系統的核心類庫(如Java核心庫和Android核心庫)和安卓系統服務(SystemService),然後進入一個迴圈,等待請求來創建新的 Android 應用程式進程。
- Zygote進程通過fork的方式創建新的應用程式進程。
2.Zygote進程的創建
Zygote進程在系統啟動時由init進程創建。init進程是Linux系統中的第一個用戶空間進程,它通過解析init.rc文件來啟動各種服務和進程,包括Zygote。具體流程如下:
2.1 啟動init進程:
- 系統啟動後,內核會載入並運行
init進程
。 init進程
讀取並解析init.rc
配置文件。
init進程的啟動可參考Linux內核Kernel啟動過程
2.2 init.rc
腳本:
init.rc
文件中包含啟動Zygote的指令腳本的主要代碼:
// 創建zygote服務
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
// 創建zygote socket,與系統和應用程式做通信
socket zygote stream 660 root system
// 定義了zygote服務重啟時的一些操作
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server:
- service zygote: 定義一個名為zygote的服務
- /system/bin/app_process:這是啟動Zygote進程的可執行文件,64位系統為
app_process64
。 - -Xzygote:標誌表明這是一個Zygote進程啟動的特殊模式。
- /system/bin:指定進程的工作目錄。
- --zygote:告訴app_process以Zygote模式啟動。
- --start-system-server:Zygote啟動時還要啟動System Server進程,這是Android系統中管理關鍵系統服務的核心進程。
class main:
- 將Zygote服務歸類為main類別。
- Android系統在啟動過程中會啟動所有“main”類別的服務。
socket zygote stream 660 root system:
創建了一個名為zygote的UNIX域Socket套接字,用於其他進程與Zygote進程通信。
onrestart write /sys/android_power/request_state wake:
當zygote服務重啟時,系統應該將“/sys/android_power/request_state”文件的內容設置為“wake”,以喚醒設備。
onrestart write /sys/power/state on:
當zygote服務重啟時,系統應該將“/sys/power/state”文件的內容設置為 “on”,以打開電源。
onrestart restart media:
當zygote服務重啟時,系統應該重啟媒體服務(如音頻、視頻等),以恢復媒體功能。
onrestart restart netd:
當zygote服務重啟時,系統應該重啟網路守護進程(netd),以恢復網路功能。
2.3 app_process
文件
/system/bin/app_process是Android中的一個關鍵可執行文件,負責啟動Zygote進程和應用進程。
2.3.1 main
方法
app_process
主入口點是main
方法,它是整個進程啟動流程的起點。以下是其主要代碼和解釋:
以下是關鍵代碼說明:
int main(int argc, char* const argv[])
{
// 創建並初始化AppRuntime對象runtime
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// 初始化參數zygote,startSystemServer,application,niceName,className
// 代碼見源碼,此處略
// 解析命令行參數
// 代碼見源碼,此處略
// 構建傳遞給 Java 初始化類的參數列表
// 代碼見源碼,此處略
if (zygote) {
// 調用AppRuntime的start方法,開始載入ZygoteInit類
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (!className.isEmpty()) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
2.3.2 AppRuntime
類(AndroidRuntime)
AppRuntime繼承自AndroidRuntime(ART),是Android中的一個關鍵類,負責管理和啟動 Android 應用程式或系統服務的 Java 虛擬機 (JVM)。
2.3.2.1 AndroidRuntime
類的start
方法
app_process
的main方法調用了AppRuntime
的start方法,也就是AppRuntime
的父類AndroidRuntime
的start方法
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
// 初始化Java Native Interface (JNI)。JNI是Java和C/C++之間的介面,它允許Java代碼和C/C++代碼相互調用
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env; // JNIEnv環境指針
// 初始化虛擬機
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
// 註冊JNI方法
if (startReg(env) < 0) {
return;
}
/*
* 以下代碼執行後,當前線程(即運行 AndroidRuntime::start 方法的線程)將成為Java虛擬機(JVM)的主線程,並且在調用env->CallStaticVoidMethod啟動指定的Java類的 main 方法後,這個方法不會返回,直到 JVM 退出為止。(官方文檔說明)
*/
// 將"com.android.internal.os.ZygoteInit"轉換為"com/android/internal/os/ZygoteInit"
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
// 沒有找到ZygoteInit.main()方法
} else {
// 通過JNI調用ZygoteInit.main()方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
}
}
- 創建虛擬機
- 註冊JNI方法
- 通過JNI調用ZygoteInit.main()
3.Zygote進程
在AndroidRuntime
的start方法,通過JNI調用ZygoteInit.main(),系統第一次進入Java層(ZygoteInit是系統運行的第一個Java類),當前線程也正式成為Java虛擬機(JVM)的主線程。
3.1 ZygoteInit.main()
通過main方法完成資源預載入、啟動系統服務等功能,為Launcher桌面程式做準備。
public static void main(String[] argv) {
// 創建ZygoteServer
ZygoteServer zygoteServer = null;
...
// 預載入資源
preload(bootTimingsTraceLog);
...
// 初始化ZygoteServer
zygoteServer = new ZygoteServer(isPrimaryZygote);
...
// 通過fork的形式初始化SystemServer
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
r.run();
return;
}
...
// 啟動Loop,監聽消息
caller = zygoteServer.runSelectLoop(abiList);
...
}
3.2 ZygoteInit.preload()預載入
通過preload方法預載入系統常用的類、資源和庫,能夠顯著減少應用啟動時的延遲,並通過共用這些預載入的內容來降低記憶體使用,提高系統性能。
static void preload(TimingsTraceLog bootTimingsTraceLog) {
preloadClasses(); //載入常用的Java類
preloadResources(); //載入常用的資源(如佈局、圖片等)
preloadOpenGL(); //載入OpenGL庫
preloadSharedLibraries(); //載入常用的本地共用庫
preloadTextResources(); //載入常用的文本資源
...
}
3.2.1 常用類
- Android框架中的基礎類,如Activity、Service、BroadcastReceiver等。
- 常用的UI組件類,如TextView、Button、ImageView等。
3.2.2 常用資源
常用佈局文件(layout)。
常用圖片資源(drawable)。
常用字元串(strings.xml)。
3.2.3 常用庫
標準C庫(libc.so)。
圖形處理庫(libskia.so)。
OpenGL ES庫(libGLESv2.so)。
3.3 啟動System Server
System Server是Android系統中的關鍵進程,負責啟動和管理核心系統服務。
啟動過程的核心代碼:
public static void main(String argv[]) {
// 初始化ZygoteServer
ZygoteServer zygoteServer = new ZygoteServer();
// 啟動System Server
if (startSystemServer) {
startSystemServer(abiList, socketName, zygoteServer);
}
// 進入Zygote的主迴圈,等待新進程的啟動請求
zygoteServer.runSelectLoop();
}
private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) {
/* 調用native方法fork系統伺服器 */
int pid = Zygote.forkSystemServer(...);
if (pid == 0) {
// 在子進程中執行System Server的main方法
handleSystemServerProcess(parsedArgs);
}
}
private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
// 通過反射調用SystemServer的main方法
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class<?> clz = cl.loadClass("com.android.server.SystemServer");
Method m = clz.getMethod("main", new Class[] { String[].class });
m.invoke(null, new Object[] { parsedArgs.remainingArgs });
}
- ZygoteServer是一個Socket,Zygote進程通過這個Socket和SystemService及其他應用程式進程做通信
- 通過fork創建的SystemServer進程是一個獨立運行的進程,避免SystemServer進程受到其他進程的影響。
- 關於SystemServer,後面還會更詳細的介紹
三、系統服務 System Server
在Zygote
中通過Zygote.forkSystemServer
方法創建了System Server進程,然後通過Java的反射機制
調用com.android.server.SystemServer
的main
方法來啟動System Server。
3.1 SystemServer.java
在SystemServer.java
的main
方法調用了自身的run
方法,在run方法中啟動了具體的系統服務,代碼如下:
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
// 初始化系統屬性,時區、語言、環境等,代碼略
...
// 載入本地服務
System.loadLibrary("android_servers");
...
// 初始化系統上下文
createSystemContext();
// 初始化主線模塊
ActivityThread.initializeMainlineModules();
...
// 創建系統服務管理器
mSystemServiceManager = new SystemServiceManager(mSystemContext);
...
/* 啟動系統服務 */
// 啟動引導服務
startBootstrapServices(t);
// 啟動核心服務
startCoreServices(t);
// 啟動其他服務
startOtherServices(t);
// 啟動 APEX 服務
startApexServices(t);
...
}
3.2 System Server啟動的主要服務
以下為System Server啟動的主要服務列表,具體實現可在源碼中查看。
服務名稱 | 功能說明 |
---|---|
Activity Manager Service (AMS) | 管理應用程式的生命周期,包括啟動和停止應用、管理任務和活動棧、處理廣播等 |
Package Manager Service (PMS) | 管理應用包的安裝、卸載、更新、許可權分配等 |
System Config Service | 管理系統配置和資源 |
Power Manager Service | 管理設備的電源狀態和電源策略,如休眠、喚醒等 |
Display Manager Service | 管理顯示設備,如屏幕亮度、顯示模式等 |
User Manager Service | 管理用戶賬戶和用戶信息 |
Battery Service | 監控和管理電池狀態和電池使用情況 |
Vibrator Service | 控制設備的振動功能 |
Sensor Service | 管理設備的感測器,如加速度計、陀螺儀等 |
Window Manager Service (WMS) | 管理視窗和顯示內容,包括視窗的創建、刪除、佈局等 |
Input Manager Service | 管理輸入設備,如觸摸屏、鍵盤等 |
Alarm Manager Service | 提供定時任務調度功能 |
Connectivity Service | 管理網路連接,如 Wi-Fi、移動數據等 |
Network Management Service | 管理網路介面和網路連接 |
Telephony Registry | 管理電話和簡訊服務 |
Input Method Manager Service (IMMS) | 管理輸入法框架 |
Accessibility Manager Service | 管理無障礙服務,為有特殊需要的用戶提供輔助功能 |
Mount Service | 管理存儲設備的掛載和卸載 |
Location Manager Service | 管理位置服務,如 GPS 和網路定位 |
Search Manager Service | 管理系統搜索功能 |
Clipboard Service | 管理剪貼板功能 |
DevicePolicy Manager Service | 管理設備的安全策略和企業管理功能 |
Status Bar Service | 管理狀態欄顯示和操作 |
Wallpaper Manager Service | 管理壁紙設置和操作 |
Media Router Service | 管理媒體設備路由 |
在系統服務全部啟動完成後,就開始啟動系統桌面程式Launcher了。
四、桌面程式Launcher
sequenceDiagram participant SystemServer participant ActivityManagerService participant ActivityTaskManagerService participant RootWindowContainer participant ActivityStartController participant Home SystemServer->>ActivityManagerService: systemReady() ActivityManagerService->>ActivityTaskManagerService: startHomeOnAllDisplays ActivityTaskManagerService->>RootWindowContainer: startHomeOnAllDisplays RootWindowContainer->>ActivityStartController: startHomeActivity ActivityStartController->>Home: Home application (Launcher) is started- SystemServer 啟動所有服務: SystemServer類在run方法中調用startOtherServices方法,啟動其他系統服務,包括ActivityManagerService。
- ActivityManagerService準備系統: ActivityManagerService 在systemReady方法中調用mAtmInternal.startHomeOnAllDisplays方法,開始在所有顯示器上啟動桌面程式。
- ActivityTaskManagerService啟動: Home Activity:ActivityTaskManagerService 調用RootWindowContainer的startHomeOnAllDisplays方法。
- RootWindowContainer迴圈所有顯示器: RootWindowContainer 遍歷每個顯示器,並調用startHomeOnDisplay方法。
- 啟動Home Activity: 在每個顯示器上,通過TaskDisplayArea調用ActivityStartController的startHomeActivity方法,最終調用ActivityManagerService的startActivity方法啟動Home Activity。
- Home應用啟動: ActivityManagerService處理啟動請求,啟動Home應用的Activity展示桌面界面。
核心代碼流轉:
4.1 SystemServer.java
private void run() {
...
// 啟動其他服務
startOtherServices(t);
...
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
...
// 啟動ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
...
// 啟動Launcher
mActivityManagerService.systemReady(...)
...
}
4.2 桌面程式Launcher(Home)的啟動流程
4.2.1 ActivityManagerService.java
public void systemReady(final Runnable goingCallback, TimingsTraceAndSlog t) {
...
// 在所有顯示器上啟動Launcher
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
...
}
- 此行代碼最終會調用到
ActivityTaskManagerService.java
的startHomeOnAllDisplays
方法
4.2.2 ActivityTaskManagerService.java
void startHomeOnAllDisplays(int userId, String reason) {
synchronized (mGlobalLock) {
// 在所有顯示器上啟動Launcher
return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
}
}
- 此行代碼最終會調用到
RootWindowContainer.java
的startHomeOnAllDisplays
方法
4.2.3 RootWindowContainer.java
boolean startHomeOnAllDisplays(int userId, String reason) {
boolean homeStarted = false;
for (int i = getChildCount() - 1; i >= 0; i--) {
final int displayId = getChildAt(i).mDisplayId;
// 在每一個顯示器上啟動桌面程式
homeStarted |= startHomeOnDisplay(userId, reason, displayId);
}
return homeStarted;
}
boolean startHomeOnDisplay(int userId, String reason, int displayId) {
return startHomeOnDisplay(userId, reason, displayId, false, false);
}
boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey) {
...
// 調用startHomeOnTaskDisplayArea
return display.reduceOnAllTaskDisplayAreas((taskDisplayArea, result) ->
result | startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
allowInstrumenting, fromHomeKey),false);
}
boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
boolean allowInstrumenting, boolean fromHomeKey) {
...
Intent homeIntent = mService.getHomeIntent();
mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
taskDisplayArea);
...
return true;
}
- 最終通過Intent和startHomeActivity方法啟動了桌面程式
五、總結
通過上述介紹,從用戶按下電源鍵開始,經過Bootloader啟動、內核啟動、init進程啟動、Zygote進程啟動、SystemServer進程啟動,以及系統應用的啟動,最終進入桌面環境。
每個階段都的核心工作:
-
Bootloader啟動:初始化硬體並載入內核。
-
內核啟動:內核是操作系統的核心,負責管理系統資源和硬體設備。
-
init進程啟動:init進程通過解析init.rc文件來啟動和配置系統服務。
-
Zygote進程啟動:Zygote是Android系統的獨有設計,負責創建應用進程。通過預載入資源和共用記憶體,Zygote大大提高了應用啟動的速度和系統資源的利用率。
-
SystemServer進程啟動:SystemServer進程啟動了大量系統服務,如Activity Manager和Package Manager等,這些服務構成了Android系統的骨幹,管理和協調應用的運行。
-
啟動系統應用:Launcher應用的啟動標志著系統啟動的完成。用戶進入桌面,可以開始正常使用設備。
通過深入理解Android的啟動流程,可以更有效地進行系統開發和維護,從而提供更高性能和更穩定的用戶體驗。
如有任何疑問或建議,歡迎留言討論。