android啟動過程
⑴ Android啟動過程深入解析
當按下Android設備電源鍵時究竟發生了什麼?
Android的啟動過程是怎麼樣的?
什麼是linux內核?
桌面系統linux內核與Android系統linux內核有什麼區別?
什麼是引導裝載程序?
什麼是Zygote?
什麼是X86以及ARM linux?
什麼是init.rc?
什麼是系統服務?
當我們想到Android啟動過程時,腦海中總是冒出很多疑問。本文將介紹Android的啟動過程,希望能幫助你找到上面這些問題的答案。
Android是一個基於Linux的開源操作系統。x86(x86是一系列的基於intel 8086 CPU的計算機微處理器指令集架構)是linux內核部署最常見的系統。然而,所有的Android設備都是運行在ARM處理器(ARM 源自進階精簡指令集機器,源自ARM架構)上,除了英特爾的Xolo設備(http://xolo.in/xolo-x900-features)。Xolo來源自凌動1.6GHz x86處理器。Android設備或者嵌入設備或者基於linux的ARM設備的啟動過程與桌面版本相比稍微有些差別。這篇文章中,我將解釋Android設備的啟動過程。深入linux啟動過程是一篇講桌面linux啟動過程的好文。
當你按下電源開關後Android設備執行了以下步驟。
此處圖片中step2中的一個單詞拼寫錯了,Boot Loaeder應該為Boot Loader(多謝@jameslast 提醒)
第一步:啟動電源以及系統啟動
當電源按下,引導晶元代碼開始從預定義的地方(固化在ROM)開始執行。載入引導程序到RAM,然後執行。
第二步:引導程序
引導程序是在Android操作系統開始運行前的一個小程序。引導程序是運行的第一個程序,因此它是針對特定的主板與晶元的。設備製造商要麼使用很受歡迎的引導程序比如redboot、uboot、qi bootloader或者開發自己的引導程序,它不是Android操作系統的一部分。引導程序是OEM廠商或者運營商加鎖和限制的地方。
引導程序分兩個階段執行。第一個階段,檢測外部的RAM以及載入對第二階段有用的程序;第二階段,引導程序設置網路、內存等等。這些對於運行內核是必要的,為了達到特殊的目標,引導程序可以根據配置參數或者輸入數據設置內核。
Android引導程序可以在找到。
傳統的載入器包含的個文件,需要在這里說明:
init.s初始化堆棧,清零BBS段,調用main.c的_main()函數;
main.c初始化硬體(鬧鍾、主板、鍵盤、控制台),創建linux標簽。
更多關於Android引導程序的可以在這里了解。
第三步:內核
Android內核與桌面linux內核啟動的方式差不多。內核啟動時,設置緩存、被保護存儲器、計劃列表,載入驅動。當內核完成系統設置,它首先在系統文件中尋找」init」文件,然後啟動root進程或者系統的第一個進程。
第四步:init進程
init是第一個進程,我們可以說它是root進程或者說有進程的父進程。init進程有兩個責任,一是掛載目錄,比如/sys、/dev、/proc,二是運行init.rc腳本。
init進程可以在/system/core/init找到。
init.rc文件可以在/system/core/rootdir/init.rc找到。
readme.txt可以在/system/core/init/readme.txt找到。
對於init.rc文件,Android中有特定的格式以及規則。在Android中,我們叫做Android初始化語言。
Action(動作):動作是以命令流程命名的,有一個觸發器決定動作是否發生。
語法
1
2
3
4
5
; html-script: false ]
on <trigger>
<command>
<command>
<command>
Service(服務):服務是init進程啟動的程序、當服務退出時init進程會視情況重啟服務。
語法
1
2
3
4
5
; html-script: false ]
service <name> <pathname> [<argument>]*
<option>
<option>
...
Options(選項)
選項是對服務的描述。它們影響init進程如何以及何時啟動服務。
咱們來看看默認的init.rc文件。這里我只列出了主要的事件以及服務。
Table
Action/Service
描述
on early-init
設置init進程以及它創建的子進程的優先順序,設置init進程的安全環境
on init
設置全局環境,為cpu accounting創建cgroup(資源控制)掛載點
on fs
掛載mtd分區
on post-fs
改變系統目錄的訪問許可權
on post-fs-data
改變/data目錄以及它的子目錄的訪問許可權
on boot
基本網路的初始化,內存管理等等
service servicemanager
啟動系統管理器管理所有的本地服務,比如位置、音頻、Shared preference等等…
service zygote
啟動zygote作為應用進程
在這個階段你可以在設備的屏幕上看到「Android」logo了。
第五步
在java中,我們知道不同的虛擬機實例會為不同的應用分配不同的內存。假如Android應用應該盡可能快地啟動,但如果Android系統為每一個應用啟動不同的Dalvik虛擬機實例,就會消耗大量的內存以及時間。因此,為了克服這個問題,Android系統創造了」Zygote」。Zygote讓Dalvik虛擬機共享代碼、低內存佔用以及最小的啟動時間成為可能。Zygote是一個虛擬器進程,正如我們在前一個步驟所說的在系統引導的時候啟動。Zygote預載入以及初始化核心庫類。通常,這些核心類一般是只讀的,也是Android SDK或者核心框架的一部分。在Java虛擬機中,每一個實例都有它自己的核心庫類文件和堆對象的拷貝。
Zygote載入進程
載入ZygoteInit類,源代碼:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
registerZygoteSocket()為zygote命令連接注冊一個伺服器套接字。
preloadClassed 「preloaded-classes」是一個簡單的包含一系列需要預載入類的文本文件,你可以在/frameworks/base找到「preloaded-classes」文件。
preloadResources() preloadResources也意味著本地主題、布局以及android.R文件中包含的所有東西都會用這個方法載入。
在這個階段,你可以看到啟動動畫。
第六步:系統服務或服務
完成了上面幾步之後,運行環境請求Zygote運行系統服務。系統服務同時使用native以及java編寫,系統服務可以認為是一個進程。同一個系統服務在Android SDK可以以System Services形式獲得。系統服務包含了所有的System Services。
Zygote創建新的進程去啟動系統服務。你可以在ZygoteInit類的」startSystemServer」方法中找到源代碼。
核心服務:
啟動電源管理器;
創建Activity管理器;
啟動電話注冊;
啟動包管理器;
設置Activity管理服務為系統進程;
啟動上下文管理器;
啟動系統Context Providers;
啟動電池服務;
啟動定時管理器;
啟動感測服務;
啟動窗口管理器;
啟動藍牙服務;
啟動掛載服務。
其他服務:
啟動狀態欄服務;
啟動硬體服務;
啟動網路狀態服務;
啟動網路連接服務;
啟動通知管理器;
啟動設備存儲監視服務;
啟動定位管理器;
啟動搜索服務;
啟動剪切板服務;
啟動登記服務;
啟動壁紙服務;
啟動音頻服務;
啟動耳機監聽;
啟動AdbSettingsObserver(處理adb命令)。
第七步:引導完成
一旦系統服務在內存中跑起來了,Android就完成了引導過程。在這個時候「ACTION_BOOT_COMPLETED」開機啟動廣播就會發出去。
⑵ Android輸入法IMMS服務啟動流程(3)(啟動IMS應用)
接上一篇,IMMS設置當前默認輸入法為LatinIME輸入法後,調用onCreate方法,然後會調用startInputInnerLocked啟動輸入法LatinIME的服務
本章節主要分析,onCreate生命周期中,各個流程調用
bindServiceAsUser啟動的服務是LatinIME
如上圖流程圖,服務啟動後,會調用到InputMethodManagerService的方法
該流程的主要邏輯:
完成對mMethodList和mMethodMap的數據初始化;檢查當前默認的輸入法(LatinIME)服務是否存在,很明顯,經過systemrunning過程以後,
mMethodMap已經包含了LatinIME,因此不會重復執行選擇和設定另外輸入法為默認輸入法的操作
該方法主要是檢查默認的LatinIME是否是可用的可用的輸入法,如果不可用,則設置為可用;
對應的settingprovider欄位為:
經過以上流程後,默認輸入法依然為LatinIME輸入法,該流程的主要作用為,將啟動的輸入法應用更新到可用列表enabled_input_methods中;
不過,目前默認的輸入法依然為LatinIME輸入法,跟重啟手機前,我們設置的輸入法(搜狗輸入法)依然不一致
下一篇文章,我們研究下,輸入法啟動過程中的onBind和onServiceConnected流程
⑶ Android啟動優化概述
Android啟動應用, 按 官方說法 分為冷啟動, 溫啟動和熱啟動.
具體的定義可以看官方文檔, 簡單地說
一般我們只需要關注冷啟動即可.
要想啟動快, 硬體性能必然有影響, 在硬體一定的前提下, 我們要盡量 降低啟動應用時CPU的負載 , 讓CPU有更多的算力投入到啟動流程中:
在做好一些基本原則後, 接著看具體的流程優化點
在應用進程創建後, 首先必然是載入類, 此時一些靜態變數就會初始化了, 因此我們應該
類載入完畢後就是創建 Application 實例了, 因此我們應該
之後會先創建 ContentProvider 和執行 ContentProvider.onCreate() , 因此我們應該
跟接著就會執行 Application.onCreate() 等方法, 因此我們應該
接著就進入 Activity 環節.
同樣第一步會是創建實例, 因此我們應該
在 Activity 進程生命周期後, 第一步就是渲染(inflate)布局, 我們應該
在應用啟動的瞬間, 系統服務會先展示一個空白窗口, 等待應用第一幀繪制完畢後, 再從該窗口切換到應用, 如果啟動耗時較長, 就會明顯看到白屏, 對於這一點, 常見的操作有
可以使用IdleHandler, 在主線程空閑時再執行某些不重要的操作
實際上非同步初始化只是不阻塞主線程, 但是子線程一樣會佔用CPU資源, 讓主線程的執行時間變少, 所以不應該盲目地將所有工作放到子線程.
優化做到最後, 就是在系統流程上做文章了
原理是將啟動時載入的類放到主dex,提升了這些類的內聚,讓更多的類滿足pre-verify的條件,在安裝時就做了校驗和優化,以減少首次載入的耗時,從而優化冷啟動耗時。
Redex 初探與 Interdex:Andorid 冷啟動優化
應用啟動過程中會從apk壓縮包中讀取文件, 該優化的原理是利用Linux中的Pagecache機制, 讓啟動過程會用到的文件盡可能進入緩存中, 減少磁碟IO次數
支付寶 App 構建優化解析:通過安裝包重排布優化 Android 端啟動性能
在Dalvik VM(Android5.0以前)載入類的時候會有一個類校驗過程, 它需要校驗方法的每一個指令, 是一個比較耗時的過程, 可以通過Hook去掉類載入過程中的類驗證過程. 不過對於ART(Android5.0之後)來說, 這個過程在安裝時已經做了, 所以用處不大.
不進入冷啟動, 就不用優化了~
這個Android Studio自帶的工具, 可以看到啟動過程中詳細的方法執行流程, 但是採集數據本身會影響方法執行, 所以不能准確判斷每個方法的耗時, 但是仍可以判斷哪個方法相對來說耗時.
這個工具的好處是可以自定義事件, 可以指定需要採集的數據集, 可以看到線程間的狀態等.
啟動優化的一個關鍵點在於定義啟動結束的點, 以及如何測量啟動時間.
在Android4.4以上, 系統進程會提供一個類似 ActivityManager: Displayed ***: +3s534ms 的日誌, 表示從啟動進程到首次繪制完畢所用的時間.
應用可以在任何時候調用該方法, 觸發系統列印類似 system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms 的日誌
應用可以通過 ViewTreeObserver 來監聽繪制前回調來判斷第一幀的繪制時機, 或者直接在控制項樹的末尾加一個簡單的View, 它 onDraw 調用時即表示頁面(差不多)繪制完畢.
應用啟動過程可以參考 Android Vitals Series' Articles 系列文章
⑷ Android 10.0 ActivityManagerService的啟動流程
我們講完了SystemServer的啟動過程,本節主要來講解ActivityManagerService的啟動過程。ActivityManagerService簡稱AMS,管理Activity行為,控制Activity的生命周期,派發消息事件,內存管理等功能。
ActivityManagerService啟動由SystemServer中startBootstrapService啟動
ATM啟動最終調用的是ActivityTaskManagerService.Lifecycle.onStart()來啟動ATM服務的
源碼:ActivityTaskManagerService.java#Lifecycle.class
將ActivityTaskManagerInternal添加到本地服務的全局注冊表中。
ActivityTaskManagerInternal為抽象類,其實現類為ActivityTaskManagerService#LocalService.class
構造函數初始化主要工作就是初始化一些變數,供之後的service,broadcast,provider的管理和調度
start中做了兩件事
AMS的systemReady處理分為三個階段
同時獲取一些配置參數。 需要注意的是,由於只有Java進程才會向AMS注冊,而一般的Native進程不會向AMS注冊,因此此處殺死的進程是Java進程。
主要是調用一些關鍵服務的初始化函數,然後殺死那些沒有FLAG_PERSISTENT 卻在AMS啟動完成前已經存在的進程,同時獲取一些配置參數。需要注意的是,由於只有Java進程才會向AMS注冊,而一般的Native進程不會向AMS注冊,因此此處殺手的進程是Java進程。
執行goingCallback的處理,主要的工作就是通知一些服務可以進行systemReady相關的工作,並進行啟動服務或應用進程的工作
監控Native的crash,啟動WebView,執行一些服務的systemReady和systemRunning方法
啟動Home Activity,當啟動結束,發送ACTION_BOOT_COMPLETED廣播時,AMS的啟動過程告一段落
啟動Home Activity
AMS的啟動主要經歷了如下幾個階段:
⑸ Android系統啟動之init.rc文件解析過程
第一篇: Android系統啟動之bootloader
第二篇: Android系統啟動之Init流程(上)
第三篇: Android系統啟動之Init流程(下)
第四篇: Android系統啟動之init.rc文件解析過程
第五篇: Android系統啟動之zyogte進程
第六篇: Android系判嘩統啟動之zyogte進程java(上)
第七篇: Android系統啟動之zyogte進程java(下)
第八篇: Android系統啟動之SystemServer
Android init.rc文件由系統第一個啟動的init程序解析。是啟動系統服務使用的文件。
主要包含了四種類型的語句:
Action和services顯式聲明了一個語句塊,而commands和options屬於最近聲明的語句塊。
在第一個語句塊之前 的commands和options會被忽略.
基本規則如下:
動掘螞行作表示了一組命令(commands)組成.動作包括一個觸發器,決定了何時運行這個動作。
注意: 當觸發器的條件滿足時,這個動作會被增加到已被運行的隊列尾。假設此動作在隊列中已經存在,那麼它將不會運行.
一個動作所包括的命令將被依次運行。
在"動作"(action)裡面的,on後面物隱跟著的字元串是觸發器(trigger),trigger是一個用於匹配某種事件類型的字元串,它將對應的Action的執行。
觸發器(trigger)有幾種格式:
常見的格式:
command是action的命令列表中的命令,或者是service中的選項 onrestart 的參數命令.
命令將在所屬事件發生時被一個個地執行.
常見命令:
服務是指那些須要在系統初始化時就啟動或退出時自己主動重新啟動的程序.
解釋一下各個參數:
options是Service的修訂項。它們決定一個服務何時以及如何運行.
使用例子:
源碼路徑 system/core/init/init.cpp 中:
開始解析rc文件.
ParseConfig函數在文件 core/init/init_parser.cpp 140行:
ParseConfigFile函數:
Android init.rc文件淺析
安卓系統啟動--3init.rc解析
init.rc深入學習
⑹ Android 從點擊應用圖標到界面顯示的過程
[轉] 一篇文章看明白 Android 從點擊應用圖標到界面顯示的過程 (遵循CC 4.0 BY-SA版權協議)
從點擊桌面應用圖標到應用顯示的過程我們再熟悉不過了,下面我們來分析下這個過程都做了什麼。
本文主要對以下問題分析:
如不了解 Android 是如何從開機到 Launcher 啟動的過程,請先閱讀 Android - 系統啟動過程
我們知道 Android 系統啟動後已經啟動了 Zygote,ServiceManager,SystemServer 等系統進程;ServiceManager 進程中完成了 Binder 初始化;SystemServer 進程中 ActivityManagerService,WindowManagerService,PackageManagerService 等系統服務在 ServiceManager 中已經注冊;最後啟動了 Launcher 桌面應用。
其實 Launcher 本身就是一個應用程序,運行在自己的進程中,我們看到的桌面就是 Launcher 中的一個 Activity。
應用安裝的時候,通過 PackageManagerService 解析 apk 的 AndroidManifest.xml 文件,提取出這個 apk 的信息寫入到 packages.xml 文件中,這些信息包括:許可權、應用包名、icon、apk 的安裝位置、版本、userID 等等。packages.xml 文件位於系統目錄下/data/system/packages.xml。
同時桌面 Launcher 會為安裝過的應用生成不同的應用入口,對應桌面上的應用圖標,下面分析點擊應用圖標的到應用啟動的過程。
點擊 Launcher 中應用圖標將會執行以下方法
在 system_server 進程中的服務端 ActivityManagerService 收到 START_ACTIVITY_TRANSACTION 命令後進行處理,調用 startActivity() 方法。
從 Launcher 點擊圖標,如果應用沒有啟動過,則會 fork 一個新進程。創建新進程的時候,ActivityManagerService 會保存一個 ProcessRecord 信息,Activity 應用程序中的AndroidManifest.xml 配置文件中,我們沒有指定 Application 標簽的 process 屬性,系統就會默認使用 package 的名稱。每一個應用程序都有自己的 uid,因此,這里 uid + process 的組合就可以為每一個應用程序創建一個 ProcessRecord。每次在新建新進程前的時候會先判斷這個 ProcessRecord 是否已存在,如果已經存在就不會新建進程了,這就屬於應用內打開 Activity 的過程了。
進程創建成功切換至 App 進程,進入 app 進程後將 ActivityThread 類載入到新進程,並調用 ActivityThread.main() 方法
此時只創建了應用程序的 ActivityThread 和 ApplicationThread,和開啟了 Handler 消息循環機制,其他的都還未創建, ActivityThread.attach(false) 又會最終到 ActivityMangerService 的 attachApplication,這個工程其實是將本地的 ApplicationThread 傳遞到 ActivityMangerService。然後 ActivityMangerService 就可以通過 ApplicationThread 的代理 ApplicationThreadProxy 來調用應用程序 ApplicationThread.bindApplication,通知應用程序的 ApplicationThread 已和 ActivityMangerService 綁定,可以不藉助其他進程幫助直接通信了。此時 Launcher 的任務也算是完成了。
在 system_server 進程中的服務端 ActivityManagerService 收到 ATTACH_APPLICATION_TRANSACTION 命令後進行處理,調用 attachApplication()。
發送送完 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令,還會發送 BIND_APPLICATION_TRANSACTION 命令來創建 Application。
在 app 進程中,收到 BIND_APPLICATION_TRANSACTION 命令後調用 ActivityThread.bindApplication()。
ApplicationThreadProxy.bindApplication(…) 會傳來這個應用的一些信息,如ApplicationInfo,Configuration 等,在 ApplicationThread.bindApplication 里會待信息封裝成AppBindData,通過
將信息放到應用里的消息隊列里,通過 Handler 消息機制,在 ActivityThread.handleMeaasge 里處理 H.BIND_APPLICATION 的信息,調用 AplicationThread.handleBindApplication。
Instrumentation:
這時 Application 就創建好了,這點很重要,很多資料里說 Application 是在performLaunchActivity() 里創建的,因為 performLaunchActivity() 也有mInstrumentation.newApplication 這個調用,newApplication() 函數中可看出會先判斷是否以及創建了 Application,如果之前已經創建,就返回已創建的 Application 對象。
上面 fork 進程時會發送 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令,在 app 進程中,收到 SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION 命令後調用 ApplicationThread.scheleLaunchActivity()。
與 Window 進行關聯,具體過程詳見: Activity,Window,View 之間的關系
Activity 的整體啟動流程如圖所示:
⑺ Android的文件系統和分區表誰能給我詳細地講一講
Android系統啟動流程如下:
1、啟動電源以及系統啟動
當電源按下時引導晶元代碼從預定義的地方(固化在ROM)開始執行。載入引導程序BootLoader到RAM,然後執行。
2、引導程序BootLoader
引導程序BootLoader是在Android操作系統開始運行前的一個小程序,它的主要作用使把系統OS拉起來並運行。
3、Linux內核啟動
當內核啟動時,設置緩存、被保護存儲器、計劃列表、載入驅動。當內核完成系統設置時,它首先在系統文件中尋找init.rc文件,並啟動init進程。
4、init進程啟動
初始化和啟動屬性服務,並且啟動Zygote進程。
5、Zygote進程啟動
創建Java虛擬機並為Java虛擬機注冊JNI方法,創建伺服器端Socket,啟動SystemServer進程。
6、SystemServer進程啟動
啟動Binder線程池和SystemServiceManager,並且啟動各種系統服務。
7、Launcher啟動
被SystemServer進程啟動的AMS會啟動Launcher,Launcher啟動會將已安裝的快捷圖標顯示在界面上。