在
計算機啟動過程
和Linux核心Kernel啟動過程
介紹了計算機啟動和核心載入,本篇文章主要介紹Android系統是如何啟動的。
一、Android啟動流程
Android系統的啟動流程與Linux接近:
- 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程序和應用程序。
Android14的app_process原始碼地址
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)。
Android14的AndroidRuntime原始碼地址
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)的主執行緒。
Android14的ZygoteInit原始碼地址
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。
Android14的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
- 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
Android14的System Server原始碼地址
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
Android14的ActivityManagerService原始碼地址
public void systemReady(final Runnable goingCallback, TimingsTraceAndSlog t) {
...
// 在所有顯示器上啟動Launcher
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
...
}
- 此行程式碼最終會呼叫到
ActivityTaskManagerService.java
的startHomeOnAllDisplays
方法
4.2.2 ActivityTaskManagerService.java
Android14的ActivityTaskManagerService原始碼地址
void startHomeOnAllDisplays(int userId, String reason) {
synchronized (mGlobalLock) {
// 在所有顯示器上啟動Launcher
return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
}
}
- 此行程式碼最終會呼叫到
RootWindowContainer.java
的startHomeOnAllDisplays
方法
4.2.3 RootWindowContainer.java
Android14的RootWindowContainer原始碼地址
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的啟動流程,可以更有效地進行系統開發和維護,從而提供更高效能和更穩定的使用者體驗。
如有任何疑問或建議,歡迎留言討論。