Android啟動過程分析 1

2021-07-09 05:23:28 字數 3630 閱讀 6098

從系統的角度看,android的啟動過程可以分為bootloader引導、裝載和啟動linux核心,啟動andorid系統的3個大的階段。其中android系統的啟動還可以細分為啟動init程序,啟動zygote,啟動sytemserver,啟動各項服務等多個階段。

(1) bootloader的引導

bootloader的主要的作用是初始化基本的硬體裝置(如cpu、記憶體、flash等)並且通過建立記憶體空間對映,為裝載linux核心準備好合適的執行環境。

(2) 裝載和啟動linux核心

android的boot.img存放的就是linux核心和乙個根檔案系統(ramdisk.img)。bootloader會把boot.img裝載進記憶體。然後linux核心會執行整個系統的初始化。完成後裝載的跟檔案系統,這裡的跟檔案系統就是ramdisk.img,它是out目錄下的root目錄打包生成的,在裡面可以看到init程序的執行檔案和一些需要解析的檔案。而init程序,就是核心載入完畢後第乙個執行的使用者程序。

(3) 啟動init程序

在init程序的啟動過程中,會解析linux的配置指令碼init.rc。根據init.rc檔案的內容,init程序會裝載android的檔案系統,建立系統目錄,啟動android系統重要的守護程序(服務)。同時還會初始化屬性系統,解析屬性檔案,配置系統屬性。設定selinux安全上下文。

最後init程序也會作為守護程序來執行修改屬性請求,重啟崩潰的程序的操作。

1.init程序的初始化過程

init程序的原始碼位於system/core/init目錄下。在m的**中,init的原始檔從c變為了c++。雖然在實現方式上有所改變,但大體流程上還是和前面的版本一致的。

(1) 進入main函式後,首先檢查啟動程式的檔名。如果檔名是「uevented」或者「watchdogd」,就會執行對應的main函式。然後清楚系統掩碼,新增環境變數,判斷當前是否是first_stage,也就是從核心來的第一次啟動。在下面的**中,init會再次啟動自己一次。從注釋上看,在第一次啟動的時候,當前處於kernel domain,將會去載入selinux policy。

接下來會建立目錄,並掛載檔案系統。將標準輸入,標準輸出和標準錯誤重定向到空檔案中。初始化在init中的log系統,在init程序中可以用kernel的log系統來輸出log. 建立.booting檔案,通過該檔案是否存在判斷當前init程序啟動是否完成,該檔案將在init.rc的boot行為中被刪除。初始化屬性系統,從dt或者kernel cmdline讀取屬性進行設定。重新設定安全上下文,註冊訊號處理機制,用於接受子程序的死亡訊號。讀取default.prop,設定屬性。在屬性中設定當前oem的狀態,啟動屬性服務,監聽屬性的修改。接下來就是對init.rc的解析了。

init.rc是以塊(section)為單位組織的,乙個「塊」可以包含多行。「塊」分為兩大類:一類稱為行為「行為(action)」;另一類稱為「服務(service)」。「行為」塊以關鍵字「on」開始,表示一堆命令的集合,「服務」塊以關鍵字「service」開始。

無論是「行為」塊還是「服務」塊,並不是按照檔案中的編排的順序逐一執行的。它們只是乙份放在這裡的定義,至於執行與否以及何時執行都是由init程序在執行時決定的。

「行為(action)」的關鍵字後面跟的字串稱為「觸發器(trigger)」。「觸發器」後面是命令列表。命令列表中的每一行都是一條命令,命令的種類非常多,比如使用start可以啟動乙個服務。「觸發器」有幾種格式,一般常見的有兩種,一種是乙個單純的字串。這種簡單的格式可以使用命令「trigger」來觸發。另一種常見的格式是「on prpperty:《屬性》=「《值》」,如果屬性值在執行時設定成了這裡的指定的值,則「塊」中的命令列表就會執行。接下來,我們看幾個具體的"行為"塊:

「服務(service)」塊的關鍵字「service」後面是服務名稱。我們可以使用"start"命令加「服務名稱」來啟動乙個服務。服務名稱後面的是程序的可執行檔案的路徑和啟動引數。關鍵字「service」以下的行稱為「選項」,每個選項佔一行,選項也有很多種,接下來,我們也看幾個具體的「服務」塊。

由於時間有限,init_prase_config_file()就不具體講解,在init模組中定義了三個全域性的列表service_list、action_list和action_queue.service_list列表包括了啟動指令碼中所有的「service」,action_list列表包括了指令碼中所有的「action」,init指令碼解析的結果就是生成這兩張列表。action_queue列表則儲存了正在執行中的「action」,init的main()函式會把需要執行的action插入到action_queue中。

接下來的action_for_each_trigger()函式就是用來將制定的action插入到action_queue中 。如果系統不在充電模式下,則把「late_init」 action 新增到執行列表中; 如果在充電模式, 將「charger」加入到執行列表中。

queuebuiltin_action()函式用來動態的生成乙個action並插入到action_queue中。插入的action由乙個函式指標和乙個表示名字的字串組成。android以前的版本中直接呼叫這兒函式來完成某些初始化的工作,但是,這些函式可能會依賴init.rc裡定義的一些命令和服務的執**況。現在把這些這些初始化函式也通過action插入到執行列表中,這樣就能控制它們的執行順序了。

main()指令碼中所有的「action」,init指令碼解析的結果就是生成這兩張列表。action_queue列表則儲存了正在執行中的「action」,init的main()函式會把需要執行的action插入到action_queue中。

接下來的action_for_each_trigger()函式就是用來將制定的action插入到action_queue中 。如果系統不在充電模式下,則把「late_init」 action 新增到執行列表中; 如果在充電模式, 將「charger」加入到執行列表中。

queue_builtin_action()函式用來動態的生成乙個action並插入到action_queue中。插入的action由乙個函式指標和乙個表示名字的字串組成。android以前的版本中直接呼叫這兒函式來完成某些初始化的工作,但是,這些函式可能會依賴init.rc裡定義的一些命令和服務的執**況。現在把這些這些初始化函式也通過action插入到執行列表中,這樣就能控制它們的執行順序了。

main()函式最後會進入乙個無限for迴圈,每次迴圈開始都會呼叫execute_one_command()函式來執行命令列表中的一條命令,同時呼叫restart_processes來重啟需要重啟的服務程序。

init程序初始化系統後,會化身為守護程序來處理來處理子進的死亡訊號,修改屬性的請求和組合鍵盤事件。

2.啟動service程序

在前面介紹action中,講到會使用start的可以啟動服務,最終會調到service_start()函式。

1.重置service結構中的標誌

2.如果服務需要控制台,但是還沒有啟動控制台就退出

3.檢查service的二進位制檔案是否存在

4.檢查svc_oneshot引數

5.設定安全上下文

6.fork子程序

7.準備環境變數

8.建立socket

9.處理標準輸入、標準輸入、標準錯誤3個檔案描述符。

10.執行exec

執行完exec後,init程序的記憶體映像就被被替換成新檔案的映像。上面的**中呼叫的是execve()h函式,它可以同時設定環境變數。s

Android啟動過程的分析

本文講的是android啟動過程的分析,大多數智慧型手機使用者使用的android作業系統的功能和操作過程都比較複雜。對於android作業系統的初學者來說,引導過程,只不過是終端使用者的一些花哨的影象和動畫。但當你閱讀完這篇文章後,你可能會打破原來對引導過程的狹隘思維。基本核心過程 引導rom 引...

tomcat啟動過程分析(1)

以tomcat為例,看tomcat是怎樣啟動的。tomcat中有乙個startup.bat 批處理檔案,這個檔案會啟動另乙個批處理檔案 catalina.bat 而這個批處理會設定set classpath classpath catalina home bin bootstrap.jar 也就是把...

Android啟動過程

android啟動過程之image分析過程 android在啟動的時候,會由uboot傳入乙個init引數,這個init引數指定了開機的時候第乙個執行的程式,預設就是init程式,這個程式在ramdisk.img中。可以分析一下它的 看看在其中到底做了一些什麼樣的初始化任務,它的原始檔在system...