1. 程式人生 > >Android原始碼學習之八—系統啟動過程

Android原始碼學習之八—系統啟動過程

Android原始碼數量龐大,雖然對它的學習從未停止,但是整理成這樣的文字,實在是費時費力的一件事情,不過好在前文已經對其基本機制加以分析,相信以此為基礎,其他的內容學習起來就沒那麼困難了。

今天是2010年的最後一天了,回顧這一年,從手機作業系統的角度來看,我把重點放在了Android上,對Windows PhoneIPhone沒有太深入研究,正好以此做一終結,把對Android原始碼的學習告一段落。從軟體工程或專案管理角度來看,今年感觸也很多,可能會成為明年的重點吧,希望到時能在軟體工程方法、過程、架構設計、專案管理方面也能成些文字以供交流。

做為Android原始碼學習系列的最後一文,還是應該從大的角度寫點東西,想寫

ParcelableBinder,也想寫WindowsManagerDialog,或者是系統架構、JNI,最後還是落筆為Android的系統啟動過程了,原因是友人問我這方面的問題,於是偷了懶,順手成文。

Android的啟動過程可以分為兩個階段,第一階段是Linux的啟動,第二階段才是Android的啟動,下面我們分別來了解一下具體的過程。

首先是Linux啟動,這一部分我想就可以略過了,無非是LinuxBootloaderKernelDriver之類的,在這裡唯一要提到的就是ServiceManager,即服務管理器,這個是做為一個程序在Android載入之前就被啟動了,我們可以從

init.rc中看到這個配置項:

service servicemanager /system/bin/servicemanager

ServiceManagerBinder的服務管理守護程序,是Binder的核心,由其使用Binder驅動進行IPC管理,關於IPC通訊的機制,此處不再詳述。在APPFramework中,應用程式使用的ServiceManager.java就是通過Proxy與這個守護程序進行的通訊。

然後是Android的啟動,接下來要詳細描述的部分。我們還是先看一下init.rc中的配置

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

linux啟動以後,啟動zygote服務程序,這個程序恰如其名:孵化器,是所有Android應用程式的孵化器。

我們來看一下app_process的程式碼,位置是在:

frameworks/base/cmds/app_process/app_main.cpp

main()函式中有如下程式碼:

if (0 == strcmp("--zygote", arg)) {

bool startSystemServer = (i < argc) ?

strcmp(argv[i], "--start-system-server") == 0 : false;

setArgv0(argv0, "zygote");

set_process_name("zygote");

runtime.start("com.android.internal.os.ZygoteInit",

startSystemServer);

}

從中可以追蹤到AndroidRuntime,程式碼位於:

frameworks/base/core/jni/AndroidRuntime.cpp

start()函式中有如下程式碼:

/* start the virtual machine */

if (startVm(&mJavaVM, &env) != 0)

goto bail;

……

env->CallStaticVoidMethod(startClass, startMeth, strArray);

即先啟動了虛擬機器,然後利用JNI呼叫了zygoteInit函式。

繼續追蹤到frameworks/base/core/java/com/android/internal/os/ZygoteInit.javamain()函式,程式碼如下:

if (argv[1].equals("true")) {

startSystemServer();

} else if (!argv[1].equals("false")) {

throw new RuntimeException(argv[0] + USAGE_STRING);

}

Log.i(TAG, "Accepting command socket connections");

if (ZYGOTE_FORK_MODE) {

runForkMode();

} else {

runSelectLoopMode();

}

前一部分是在啟動系統服務,後一部分是雖然是一個條件判斷,但ZYGOTE_FORK_MODE被賦了false,所以進行else分支的runSelectLoopMode()函式,在該函式中,實際上是在一死迴圈中利用zygoteConnection類通過socket的方式進行訊息處理,用於fork出新的zygote,從而以最輕量級的方式實現每個程序一個虛擬機器的機制。

繼續來看startSystemServer(),程式碼位於:

frameworks/base/services/java/com/android/server/systemserver.java

在其main()函式中呼叫了init1(args)這個native函式,利用JNI機制,跟蹤至

frameworks/base/services/jni/com_android_server_systemService.cpp,然後到

frameworks/base/cmds/system_server/library/system_init.cpp

system_init()函式中有如下程式碼:

if (strcmp(propBuf, "1") == 0) {

// Start the SurfaceFlinger

SurfaceFlinger::instantiate();

}

AndroidRuntime* runtime = AndroidRuntime::getRuntime();

LOGI("System server: starting Android services./n");

runtime->callStatic("com/android/server/SystemServer", "init2");

即完成了SurfaceFlinger的例項化,然後利用執行時的callStatic()函式呼叫了SystemServerinit2()函式,這個函式位於:

frameworks/base/services/java/com/android/server/SystemServer.java

程式碼是:

public static final void init2() {

Slog.i(TAG, "Entered the Android system server!");

Thread thr = new ServerThread();

thr.setName("android.server.ServerThread");

thr.start();

}

在這個ServerThread執行緒中,可以看到我們熟悉的Android服務了,比如WallpaperService服務的啟動:

try {

Slog.i(TAG, "Wallpaper Service");

wallpaper = new WallpaperManagerService(context);

ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);

} catch (Throwable e) {

Slog.e(TAG, "Failure starting Wallpaper Service", e);

}

最後,呼叫各服務的systemReady()函式通知系統就緒。

至此,系統的啟動過程結束,借用兩張圖來說明問題:

從這裡可以看出,linuxinit在啟動若干守護程序之後,就啟動了Androidruntimezygotezygote再啟動虛擬機器,系統服務,系統服務再啟動完本地服務後,又啟動了若干Android服務,並完成向ServiceManager的註冊工作,最後系統啟動完成。系統的程序空間如下圖所示:

可見,由zygote孵化器為各程序以寫時複製的方式用最小的代價實現了虛擬機器。

 

好了,相信經過這一系列的原始碼跟蹤,我們都能對Android的啟動過程有更清晰的認識,新年即將到來,在結束本系列文章的同時,祝大家新年快樂。