編輯:Android資訊
面向新的一年,我們可能啟動了許多有意義的計劃,在這個有著特殊意義的日子裡,讓我們來一起學習一下Android系統是如何啟動的。
init進程是一切的開始,在Android系統中,所有進程的進程號都是不確定的,唯獨init進程的進程號一定是1。因為這個進程是系統起來的第一個進程。並且,init進程掌控了整個系統的啟動流程。
我們知道,Android可能運行在各種不同的平台,不同的設備上。因此,啟動的邏輯是不盡相同的。 為了適應各種平台和設備的需求,init進程的初始化工作通過init.rc
配置文件來管理。init.rc以Android Init Language作為語法,下文我們簡稱Android Init Language為init語言。配置文件的主入口文件是/init.rc,這個文件會通過import
關鍵字引入其他的配置文件。在這裡,我們統稱這些文件為init.rc
。
/init.rc可能import
以下路徑中的.rc文件:
init語言,以換行為語句分隔,以空格來為符號分隔,以“#“為注釋開始。配置文件中支持五種類型的表達式:
這其中,Action和Service需要保證名稱唯一。
Action表達式的語法如下:
on <trigger> [&& <trigger>]* <command> <command> <command>
這裡的Trigger是Action執行的觸發器,當觸發器條件滿足時,command會被執行。觸發器有兩類:
QueueEventTrigger()
函數發出一個Action可以有多個屬性觸發器,但是只能包含一個事件觸發器。下面是一些例子:
on boot && property:a=b
在”boot”事件發生時,並且屬性a的值是b時觸發on property:a=b && property:c=d
在屬性a的值是b並且屬性c的值是d時觸發Action中的Command是init語言定義的命令,所有支持的命令如下表所示:
Service是init進程啟動的可執行程序。服務可以選擇在自己退出之後,由init將其重啟。
Service表達式的語法如下:
service <name> <pathname> [ <argument> ]* <option> <option>
Option是對服務的修飾,它們影響著init進程如何以及何時啟動服務。所有支持的option如下表所示:
import是一個關鍵字,並不是一個命令。可以在.rc文件中通過這個關鍵字來加載其他的.rc文件。它的語法很簡單:
import path
path可以是另外一個.rc文件,也可以是一個文件夾。如果是文件夾,那麼這個文件夾下面的所有文件都會被導入,但是它不會循環加載子目錄中的文件。
AOSP中包含了Android系統需要的最基本的.rc文件,它們位於這個路徑:/system/core/rootdir/ 。
我們選取其中了一兩個代碼片段來了解一下:
# /system/core/rootdir/init.rc import /init.environ.rc import /init.usb.rc import /init.${ro.hardware}.rc import /init.usb.configfs.rc import /init.${ro.zygote}.rc on early-init # Set init and its forked children's oom_adj. write /proc/1/oom_score_adj -1000 # Disable sysrq from keyboard write /proc/sys/kernel/sysrq 0 # Set the security context of /adb_keys if present. restorecon /adb_keys # Shouldn't be necessary, but sdcard won't start without it. http://b/22568628. mkdir /mnt 0775 root system # Set the security context of /postinstall if present. restorecon /postinstall start ueventd on init sysclktz 0 # Mix device-specific information into the entropy pool copy /proc/cmdline /dev/urandom copy /default.prop /dev/urandom # Backward compatibility. symlink /system/etc /etc symlink /sys/kernel/debug /d # Link /vendor to /system/vendor for devices without a vendor partition. symlink /system/vendor /vendor ...
這是根目錄/init.rc文件中一開始的代碼片段。有了前面的講解之後,這段代碼應當還是比較好理解的。在這段代碼中:
“eraly-init”和”init”這兩個事件都是由init進程發出的。
下面,我們再來看另外一個代碼片段:
這段代碼定義了一個名稱為zygote
的Service,這個服務是通過可執行命令/system/bin/app_process啟動的,啟動的時候傳遞了參數:-Xzygote /system/bin --zygote --start-system-server
。
Zygote是Android系統中一個非常重要的服務,zygote的中文意思是“受精卵“。這是一個很有寓意的名稱:所有的應用進程都是由zygote
fork出來的子進程,因此zygote進程是所有應用進程的父進程。
關於Zygote,我們已經在另外一篇文章中講解過了,參見這裡Zygote進程,有興趣的讀者可以再次回顧一下。
Android系統是一個跨越了多種設備的操作系統,從最初的系統的研發到最終終端用戶的使用,這其中經歷了許多道的開發流程。而每一道流程的開發者都有可能對系統做不同程度的定制。
Android系統的設計者從一開始就考慮到了這種復雜性,這一點從很多系統模塊的設計中很能看得出來。系統啟動的機制便是一個很好的范例:這裡在保證系統核心服務啟動順序的前提下,還為不同階段的開發者預留好了便於調整和擴展的機制,並且不用修改任何的源代碼。
這種對於“開閉原則”的遵守,是非常值得我們學習的。
本文由碼農網 – 豆照建原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃! 最近 Google 已經發布 Android 新版本 7.0 N
在Android應用開發中會經常碰到一個叫divider的東西,就是兩個View之間的分割線。最近工作中注意到這個divider並分析了一下,竟然發現內有乾坤,驚
前言 這篇文章主要是介紹了一些小細節的優化技巧,當這些小技巧綜合使用起來的時候,對於整個Android App的性能提升還是有作用的,只是不能較大幅度的提升性能而
要為Android應用找到一個好的架構不是一件容易的事情。谷歌似乎不太在乎這個事情,因此在設計模式上,除了Activity 生命周期管理之外,再也沒有官方的推薦。