前言
做android開發已經好些年頭,一直對android系統的開機啓動流程一知半解。前前後後看了不少文章和源碼,在這裏把自己的一些總結記錄下來,也算是加深自己的理解。
Android N 開機啓動流程概述
相信只要接觸過Android的人,都會看過下面這張圖:
Android層次架構圖
圖片展示了Android的五層架構,從上到下依次是:應用層,應用框架層,庫層,運行時層以及Linux內核層。而Android的啓動流程是自下而上的,大體上分爲三個階段:1. BootLoader引導;2. 啓動Kernel;3. 啓動Android。如果再細化一點,則如下圖所示:
Android的啓動流程圖
Android的啓動過程可以分爲兩個階段,第一階段是Linux的啓動,第二階段纔是Android的啓動。上圖中1、2、3是linux啓動的過程,從4開始就是android啓動的過程。
下面我詳細描述一下過程:
Step 1. Boot Rom
當按開機鍵的時候,引導芯片開始從固化在ROM的預設代碼開始執行,然後加載引導程序到RAM。
Step 2. Bootloader
BootLoader,又稱爲引導程序。它是在操作系統運行之前運行的一段程序,是運行的第一個程序。主要有檢查RAM,初始化硬件參數等功能,當然它的最終目的是把操作系統給拉起來。
文件路徑
:
/bootable/bootloader/legacy/
BootLoader的主要功能分析,我摘抄過來,一起看看:
其實Bootloader主要的必須的作用只有一個:就是把操作系統映像文件拷貝到RAM中去,然後跳轉到它的入口處去執行,我們稱之爲啓動加載模式,該過程沒有用戶的介入,是它正常工作的模式。它的步驟如下:
Stage1:
硬件設備初始化。爲stage2的執行及隨後內核的執行準備好基本的硬件環境 爲加載stage2 準備ram空間。爲了獲得更好的執行速度,通常吧stage2加載到ram中執行 複製stage2的代碼到ram中 設置好堆棧 跳轉到stage2的c程序入口
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Stage2:
初始化本階段要使用的硬件設備 檢測系統內存映射 將內核映像和根文件系統映像從flash讀到ram中 爲內核設置啓動參數 調用內核
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
(摘自:http://www.cnblogs.com/little221/archive/2012/12/06/2804387.html)
簡單的說,Bootloader負責初始化軟件運行所需要的最小硬件環境,最後加載內核到內存。
Step 3. 初始化Kernel
接着就進入C語言編寫的結構無關的代碼了。這個入口的函數是start_kernel函數。start_kernel 函數完成了內核的大部分初始化工作。實際上,可以將start_kernel 函數看做內核的main函數。start_kernel函數執行到最後調用了reset_init函數進行後續的初始化。 reset_init函數最主要的任務就是啓動內核線程kernel_init。kernel_init函數將完成設備驅動程序的初始化,並調用init_post函數啓動用戶空間的init進程。到init_post函數爲止,內核的初始化已經基本完成。
文件路徑:/kernel_imx/init/main.c
簡單的說,內核加載進內存後,將首先進入內核引導階段,在內核引導階段的最後,調用start_kernel進入內核啓動階段,主要是完成內核的大部分初始化工作。start_kernel會最終啓動用戶空間的init進程。
Step 4. init進程
當初始化內核之後,就會啓動一個相當重要的祖先進程,也就是init進程,在Linux中所有的進程都是由init進程直接或間接fork出來的。init進程負責創建系統中最關鍵的幾個核心daemon(守護)進程,尤其是zygote和servicemanager。前者是android啓動的第一個dalvik 虛擬機,它將負責啓動Java世界的進程;後者是BInder通信的基礎。另外,它還提供了property service(屬性服務),類似於windows系統的註冊表服務。
在Android系統中,會有個init.rc腳本。init進程一啓動就會讀取並解析這個腳本文件,把其中的元素整理成自己的數據結構(鏈表)。
換句話說, init進程負責解析init.rc配置文件,開啓系統守護進程。兩個最重要的守護進程是zygote進程和servicemanager,zygote是Android啓動的第一個Dalvik虛擬機,servicemanager是Binder通訊的基礎。
文件路徑: /system/core/init/init.c
/system/core/rootdir/init.rc
/system/core/init/readme.txt
Step 5. Zygote進程
當init進程創建之後,會fork出一個Zygote進程,這個進程是所有Java進程的父進程。我們知道,Linux是基於C的,而Android是基於Java的(當然底層也是C)。所以這裏就會fork出一個Zygote Java進程用來fork出其他的進程。在zygote開啓的時候,會調用ZygoteInit.main()進行初始化。下面我們看一段ZygoteInit.main()源碼:
public static void main(String argv[]) {
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();
try {
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
RuntimeInit.enableDdms();
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
// 加載zygote的時候,會傳入參數,startSystemServer變爲true
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
registerZygoteSocket(socketName);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
gcAndFinalize();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false);
// Zygote process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();
ZygoteHooks.stopZygoteNoThreadCreation();
// 啓動SystemServer進程
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (Throwable ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
文件路徑:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
從代碼中可以看出,zygote虛擬機啓動子進程system_server,同時也可以看出zygote中定義了一個Socket,用於接收ActivityManagerService啓動應用程序的請求。
Step 6. SystemServer進程
前面ZygoteInit.java裏面通過startSystemServer() fork出了SystemServer進程,這個進程在整個的Android中非常重要,它和Zygote進程一樣,是Android Framework層的兩大重要進程。系統裏面重要的服務都是在這個進程裏面開啓的,例如AMS, WindowsManager, PackageManagerService等等都是由這個SystemServer fork出來的。在下面SystemServer 的代碼中可以看到,這些服務如何開啓和具體開啓了哪些服務。
文件路徑:/frameworks/base/services/java/com/android/server/SystemServer.java
從SystemServer.java文件代碼中可以看出,在SystemServer進程開啓的時候,就會初始化ActivityManagerService 。同時,會加載本地系統的服務庫,調用createSystemContext()創建系統上下文,創建ActivityThread及開啓各種服務等等。
也就是說在system_server中開啓了核心系統服務,並將系統服務添加到ServiceManager中,然後系統進入SystemReady狀態。
Step 7. Home Activity
上面ActivityManagerService 開啓之後,會調用finishBooting() ,完成引導過程,同時發送開機廣播。
文件路徑:/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
之後就會啓動Home程序,完成系統界面的加載與顯示。
其實這一步遠比上面所說的複雜,具體步驟是:
1、在systemReady狀態,ActivityManagerService會與zygote的Socket通信,請求啓動Home。
2、zygote收到AMS的連接請求後,執行runSelectLoopMode處理請求。
3、zygote處理請求會通過forkAndSpecialize啓動新的應用進程,並最終啓動Home。
Android的開機啓動流程就完成了。
總結一下整個開機啓動流程:
Step1 系統加電,執行bootloader。Bootloader負責初始化軟件運行所需要的最小硬件環境,最後加載內核到內存。
Step2 內核加載進內存後,將首先進入內核引導階段,在內核引導階段的最後,調用start_kernel進入內核啓動階段。start_kernel最終啓動用戶空間的init程序。
Step3 init程序負責解析init.rc配置文件,開啓系統守護進程。兩個最重要的守護進程是zygote進程和ServiceManager,zygote是Android啓動的第一個Dalvik虛擬機,ServiceManager是Binder通訊的基礎。
Step4 zygote虛擬機啓動子進程system_server,在system_server中開啓了核心系統服務,並將系統服務添加到ServiceManager中,然後系統進入SystemReady狀態。
Step5 在SystemReady狀態,ActivityManagerService與zygote中的socket通信,通過zygote啓動home應用,進入系統桌面。
從Step3開始,init啓動後,上層的實現。
Step1 init啓動的核心Daemon服務包括Android的第一個Dalvik虛擬機zygote。
Step2 zygote定義一個socket,用於接受ActivityManagerService啓動應用的請求。
Step3 zygote通過fork系統調用創建system_server進程
Step4 在system_server進程中,將會啓動系統核心服務以及其他服務。
Step5 系統服務啓動後會註冊到ServiceManager中,用於Binder通信。
Step6 ActivityManagerService進入systemReady狀態。
Step7 在systemReady狀態,ActivityManagerService會與zygote的Socket通信,請求啓動Home。
Step8 zygote收到AMS的連接請求後,執行runSelectLoopMode處理請求。
Step9 zygote處理請求會通過forkAndSpecialize啓動新的應用進程,並最終啓動Home。
參考文檔:http://blog.csdn.net/frakie_kwok/article/details/70196986
http://www.jianshu.com/p/45cf56172d22
http://blog.csdn.net/dd864140130/article/details/57624948