Android系統的開機畫面顯示過程分析(5)

2021-09-05 03:38:16 字數 3326 閱讀 8828

2. 第二個開機畫面的顯示過程

由於第二個開機畫面是在init程序啟動的過程中顯示的,因此,我們就從init程序的入口函式main開始分析第二個開機畫面的顯示過程。

init程序的入口函式main實現在檔案system/core/init/init.c中,如下所示:

int main(int argc, char **argv)   

if (!signal_fd_init && get_signal_fd() > 0)    

if (!keychord_fd_init && get_keychord_fd() > 0)    

if (process_needs_restart)    

if (!action_queue_empty() || cur_action)   

timeout = 0;   

......   

nr = poll(ufds, fd_count, timeout);   

if (nr <= 0)   

continue;   

for (i = 0; i < fd_count; i++)    

}   

}   

return 0;   

}   

函式一開始就首先判斷引數argv[0]的值是否等於「ueventd」,即當前正在啟動的程序名稱是否等於「ueventd」。如果是的話,那麼就以ueventd_main函式來作入口函式。這是怎麼回事呢?當前正在啟動的程序不是init嗎?它的名稱怎麼可能會等於「ueventd」?原來,在目標裝置上,可執行檔案/sbin/ueventd是可執行檔案/init的乙個符號鏈結檔案,即應用程式ueventd和init執行的是同乙個可執行檔案。核心啟動完成之後,可執行檔案/init首先會被執行,即init程序會首先被啟動。init程序在啟動的過程中,會對啟動指令碼/init.rc進行解析。在啟動指令碼/init.rc中,配置了乙個ueventd程序,它對應的可執行檔案為/sbin/ueventd,即ueventd程序載入的可執行檔案也為/init。因此,通過判斷引數argv[0]的值,就可以知道當前正在啟動的是init程序還是ueventd程序。

ueventd程序是作什麼用的呢?它是用來處理uevent事件的,即用來管理系統裝置的。從前面的描述可以知道,它真正的入口函式為ueventd_main,實現在system/core/init/ueventd.c中。ueventd程序會通過乙個socket介面來和核心通訊,以便可以監控系統裝置事件。例如,在前面

在ubuntu上為android系統編寫linux核心驅動程式

一文中, 我們呼叫device_create函式來建立了乙個名稱為「hello」的字元裝置,這時候核心就會向前面提到的socket傳送乙個裝置增加事件。ueventd程序通過這個socket獲得了這個裝置增加事件之後,就會/dev目錄下建立乙個名稱為「hello」的裝置檔案。這樣使用者空間的應用程式就可以通過裝置檔案/dev/hello來和驅動程式hello進行通訊了。

接下來呼叫另外乙個函式queue_builtin_action來向init程序中的乙個待執行action佇列增加了乙個名稱等於「console_init」的action。這個action對應的執行函式為console_init_action,它就是用來顯示第二個開機畫面的。

函式queue_builtin_action實現在檔案system/core/init/init_parser.c檔案中,如下所示:

static list_declare(action_list);   

static list_declare(action_queue);   

void queue_builtin_action(int (*func)(int nargs, char **args), char *name)   

void action_add_queue_tail(struct action *act)   

action_list列表用來儲存從啟動指令碼/init.rc解析得到的一系列action,以及一系列內建的action。當這些action需要執行的時候,它們就會被新增到action_queue列表中去,以便init程序可以執行它們。

回到init程序的入口函式main中,最後init程序會進入到乙個無限迴圈中去。在這個無限迴圈中,init程序會做以下五個事情:

a. 呼叫函式execute_one_command來檢查action_queue列表是否為空。如果不為空的話,那麼init程序就會將儲存在列表頭中的action移除,並且執行這個被移除的action。由於前面我們將乙個名稱為「console_init」的action新增到了action_queue列表中,因此,在這個無限迴圈中,這個action就會被執行,即函式console_init_action會被呼叫。

b. 呼叫函式restart_processes來檢查系統中是否有程序需要重啟。在啟動指令碼/init.rc中,我們可以指定乙個程序在退出之後會自動重新啟動。在這種情況下,函式restart_processes就會檢查是否存在需要重新啟動的程序,如果存在的話,那麼就會將它重新啟動起來。

c. 處理系統屬性變化事件。當我們呼叫函式property_set來改變乙個系統屬性值時,系統就會通過乙個socket(通過呼叫函式get_property_set_fd可以獲得它的檔案描述符)來向init程序傳送乙個屬性值改變事件通知。init程序接收到這個屬性值改變事件之後,就會呼叫函式handle_property_set_fd來進行相應的處理。後面在分析第三個開機畫面的顯示過程時,我們就會看到,su***ceflinger服務就是通過修改「ctl.start」和「ctl.stop」屬性值來啟動和停止第三個開機畫面的。

d. 處理一種稱為「chorded keyboard」的鍵盤輸入事件。這種型別為chorded keyboard」的鍵盤裝置通過不同的銨鍵組合來描述不同的命令或者操作,它對應的裝置檔案為/dev/keychord。我們可以通過呼叫函式get_keychord_fd來獲得這個裝置的檔案描述符,以便可以監控它的輸入事件,並且呼叫函式handle_keychord來對這些輸入事件進行處理。

e. **殭屍程序。我們知道,在linux核心中,如果父程序不等待子程序結束就退出,那麼當子程序結束的時候,就會變成乙個殭屍程序,從而占用系統的資源。為了**這些殭屍程序,init程序會安裝乙個sigchld訊號接收器。當那些父程序已經退出了的子程序退出的時候,核心就會發出乙個sigchld訊號給init程序。init程序可以通過乙個socket(通過呼叫函式get_signal_fd可以獲得它的檔案描述符)來將接收到的sigchld訊號讀取回來,並且呼叫函式handle_signal來對接收到的sigchld訊號進行處理,即**那些已經變成了殭屍的子程序。

注意,由於後面三個事件都是可以通過檔案描述符來描述的,因此,init程序的入口函式main使用poll機制來同時輪詢它們,以便可以提高效率。

修改Android開機畫面

android系統開機動畫包括兩部分 開機顯示的 android 文字 android發光動畫。這篇文章說的開機動畫是第一種,下面開始正文!1.製作當前螢幕畫素的 模擬器預設為320 480 使用ps製作一張320 480的,儲存時選 儲存為 web 所用格式 然後在彈開的視窗上,預設 項選擇 pn...

Android開機畫面修改

第一屏 1.將大小為480 800的png轉換為mbn格式 ffmpeg i image.png f rawvideo pix fmt rgb565 oemlogo.mbn 2把生成的oemlogo.mbn檔案放到手機的指定資料夾,覆蓋原來的 資料夾的位置我們可以通過檢視 init.rc得到 cat...

Android系統的開機畫面顯示過程分析(2)

接下來我們主要關注函式fbcon init和fbcon switch的實現,系統就是通過它來初始化和切換控制台的。在初始化的過程中,會決定是否需要準備第乙個開機畫面的內容,而在切換控制台的過程中,會決定是否需要顯示第乙個開機畫面的內容。函式fbcon init的實現如下所示 static void ...