接觸Android也有幾年了,最近想對Android系統的啟動流程做一個完整的分析總結,以便後續學習 。
(1)Android架構介紹
我們先來看一下Android文檔給的一份系統架構圖。

從以上可以看到,Android大體上被分為4個子產品(Kernel,Hal/Native,Java Framework,Apps)。
接下來我們從系統啟動的角度來看兩種更加詳細的圖。
從上圖可以看出,系統啟動我們底層将其主要分為三個部分。
- Android裝置上電後,首先會從處理器片上ROM的啟動引導代碼開始執行,片上ROM會尋找Bootloader代碼,并加載到記憶體。
- Bootloader開始執行,首先負責完成硬體的初始化,然後找到Linux核心代碼,并加載到記憶體。
- Linux核心開始啟動,初始化各種軟硬體環境,加載驅動程式,挂載根檔案系統,并執行init程式,由此開啟Android的世界。
每一層的作用不做介紹,這裡主要講涉及的鏡像有boot.img、system.img、vendor.img、recovery.img、userdata.img、cache.img,與平台相關的鏡像有lk.bin(MTK)、preloader.img(MTK)、logo.bin(MTK)等,通常來說,修改kernel層通常編譯boot.img即可,修改Framework層或Native層主要是編譯system.img。
(2)Android啟動概述
概述:Loader > Kernel > Native > Framework > Application
細分:BootRom > Bootloader > Kernel > Init > Zygote > SystemServer > Launcher
- Loader層主要包括Boot Rom和Boot Loader
- Kernel層主要是Android核心層
- Native層主要是包括init程序以及其fork出來的使用者空間的守護程序、HAL層、開機動畫等
- Framework層主要是AMS和PMS等Service的初始化
- Application層主要指SystemUI、Launcher的啟動
kernel的C啟動階段可以了解為真正的啟動階段,Linux下有3個特殊的程序,idle(swapper)程序(PID = 0)、init程序(PID = 1)和kthreadd(PID = 2)。
-
idle(swapper)程序由系統自動建立,運作在核心态
idle程序其pid=0,其前身是系統建立的第一個程序,也是唯一一個沒有通過fork或者kernel_thread産生的程序。
完成加載系統後,演變為程序排程、交換,常常被稱為交換程序。
-
init程序由idle通過kernel_thread建立,在核心空間完成初始化後,加載init程式,并最終轉變為使用者空間的init程序
由0程序建立,完成系統的初始化,是系統中所有其它使用者程序的祖先程序。
Linux中的所有程序都是有init程序建立并運作的。首先Linux核心啟動,然後在使用者空間中啟動init程序,再啟動其他系統程序。
在系統啟動完成後,init将變為守護程序監視系統其他程序。
-
kthreadd程序由idle通過kernel_thread建立,并始終運作在核心空間,負責所有核心線程的排程和管理
它的任務就是管理和排程其他核心線程kernel_thread,會循環執行一個kthreadd的函數,該函數的作用就是運作kthread_create_list全局連結清單中維護的kthread,當我們調用kernel_thread建立的核心線程會被加入到此連結清單中,是以所有的核心線程都是直接或者間接的以kthreadd為父程序。
以上程序可以通過如下圖檔展示:
可通過ps -A(查詢程序)和ps -T -p xxx(查詢xxx程序中的線程數)指令來檢視Android系統相關程序。
//ps -A
USER PID PPID VSZ RSS WCHAN ADDR S NAME
root 1 0 68444 3052 0 0 S init
root 2 0 0 0 0 0 S [kthreadd]
root 3 2 0 0 0 0 I [rcu_gp]
root 4 2 0 0 0 0 I [kworker/0:0]
root 5 2 0 0 0 0 I [kworker/0:0H]
root 13 2 0 0 0 0 S [watchdog/0]
root 14 2 0 0 0 0 S [cpuhp/0]
root 15 2 0 0 0 0 S [cpuhp/1]
...
root 459 1 34620 872 0 0 S init
root 461 1 36156 3544 0 0 S ueventd
system 478 1 29772 1532 0 0 S servicemanager
system 479 1 2132152 3036 0 0 S hwservicemanager
root 609 1 2487788 5064 0 0 S netd
root 610 1 5495940 86496 0 0 S zygote64
root 611 1 1813256 69932 0 0 S zygote
root 626 1 30980 2292 0 0 S healthd
audioserver 685 1 2396272 8056 0 0 S audioserver
system 686 1 86580 2332 0 0 S displayservice
system 691 1 3022164 23440 0 0 S surfaceflinger
cameraserver 782 1 43032 4820 0 0 S cameraserver
media 805 1 183008 5824 0 0 S mediaserver
system 1268 775 10563968 372340 0 0 S system_server
shell 7278 1 108560 3672 0 0 S adbd
shell 7279 1 77376 776 0 0 S hdbd
root 610 1 5495940 86496 0 0 S zygote64
system 1695 610 6086164 108188 0 0 S com.android.settings
u0_a26 1719 610 7740036 246752 0 0 S com.android.systemui
radio 2138 610 6634868 104272 0 0 S com.android.phone
u0_a22 3363 610 6435100 121448 0 0 S com.android.gallery3d
nfc 3447 610 5734092 61980 0 0 S com.android.nfc
u0_a11 4170 610 5711704 68868 0 0 S android.process.media
u0_a18 4303 610 6470168 140176 0 0 S com.google.android.gms
...
//ps -T -p xxx
USER PID TID PPID VSZ RSS WCHAN ADDR S CMD
system 1268 1268 610 10943004 318288 0 0 S system_server
system 1268 1342 610 10943004 318288 0 0 S android.display
system 1268 1343 610 10943004 318288 0 0 S android.anim
system 1268 1347 610 10943004 318288 0 0 S watchdog
system 1268 1364 610 10943004 318288 0 0 S ActivityManagerService
system 1268 1412 610 10943004 318288 0 0 S PowerManagerService
system 1268 1427 610 10943004 318288 0 0 S PackageManagerService
system 1268 1517 610 10943004 318288 0 0 S SensorService
system 1268 1535 610 10943004 318288 0 0 S AlarmManager
system 1268 1571 610 10943004 318288 0 0 S WifiService
system 1268 2212 610 10943004 318288 0 0 S SoundPool
...
當 Linux 核心啟動後會初始化各種軟硬體環境,加載驅動程式,挂載根檔案系統,Linux 核心加載的最後階段會啟動執行第一個使用者空間程序 init 程序。