關于Android Init的詳解,關于Action,Service,Trigger的請參考Android init.rc詳解1,關于Options的請參考Android init.rc詳解2,本章將介紹常見的Commands。
1 Commands
-
bootchart [start|stop]
- 啟動或停止bootcharting(系統啟動性能分析),bootcharting只有在文件
/data/bootchart/enabled
存在時才會激活,斗則將不執行任何操作。- bootchart是一個收集和分析Android系統啟動過程性能數據的工具,通過采樣CPU、I/O、進程活動等信息,生成可視化的啟動時序圖(
.png
或.svg
),幫助開發者優化開機時間。bootchart start
:在啟動早期(如?on init
?階段)調用,啟動數據采集。bootchart stop
:在啟動后期(如?on property:sys.boot_completed=1
)調用,停止采集并生成日志。- init.rc中使用該command的舉例:
on post-fs-data# Start bootcharting as soon as possible after the data partition is# mounted to collect more data.mkdir /data/bootchart 0755 shell shell encryption=Requirebootchart starton property:sys.boot_completed=1bootchart stop# Setup per_boot directory so other .rc could start to use it on boot_completedexec - system system -- /bin/rm -rf /data/per_bootmkdir /data/per_boot 0700 system system encryption=Require key=per_boot_refsetprop ro.vendor.qti.per_boot_created 1
Android 系統的關鍵啟動時間指標(如
bootanimation
顯示、sys.boot_completed=1
)主要取決于:
class_start main
class_start late_start
- 關鍵服務(如?
zygote
、system_server
)的啟動速度。
-
chmod <octal-mode> <path>
- 更改指定文件或者目錄的訪問權限(讀/寫/執行),使用8進制表示法。
- 使用舉例:
# set system-background to 0775 so SurfaceFlinger can touch it chmod 0775 /dev/cpuset/system-backgroundchmod 0664 /dev/cpuset/foreground/tasks chmod 0664 /dev/cpuset/background/tasks chmod 0664 /dev/cpuset/system-background/tasks chmod 0664 /dev/cpuset/top-app/tasks
-
chown <owner> <group> <path>
- 改變文件的所有者和用戶組。
- 使用舉例
# change permissions for all cpusets we'll touch at runtime chown system system /dev/cpuset chown system system /dev/cpuset/foreground chown system system /dev/cpuset/background chown system system /dev/cpuset/system-background
? 總結
指令 | 作用 | 典型用途 | 注意事項 |
---|---|---|---|
bootchart [start|stop] | 控制啟動性能分析 | 優化開機時間 | 需手動創建?/data/bootchart/enabled ?啟用 |
chmod <mode> <path> | 修改文件權限 | 設置可執行、保護敏感文件 | 使用八進制權限,最小權限原則 |
chown <owner> <group> <path> | 修改文件所有者和組 | 確保服務能訪問資源 | 與?chmod ?配合使用 |
-
class _start <serviceclass>
- 啟動指定類別(service class)的所有服務,前提是這些服務尚未運行。將同一類別的service集中管理,便于延遲啟動或者統一控制。
- 他是一個批量啟動服務的指令,常見的service class由
service class 值 含義 main 系統運行所必需的核心服務:zygote, bluetoothbd, storaged,?
core
核心服務,servicemanager, console,ueventd, bootanim late_start 非關鍵、耗時或可延遲的服務(優化啟動時間的關鍵,可以縮短sys.boot_completed時間) early_hal
需要在main之前啟動的服務 hal 指Android HAL層的服務,用于與底層通信。 charger
和充電有關的service,例如charger,hw-health-service,在on charger觸發的services
-
class_stop <serviceclass>
- 關閉指定類型的services。
- 使用舉例
# Healthd can trigger a full boot from charger mode by signaling this # property when the power button is held. on property:sys.boot_from_charger_mode=1class_stop chargertrigger late-init
-
class_restart [ --only--enabled ] <serviceclass>
- 重啟指定類別的所有services。
- 如果指定了--only--enabled,則跳過被禁用的服務(即disabled修飾的service)。
- 如果沒有指定該選項,則會嘗試重啟該類別下的所有服務(包括disabled和oneshort修飾的service),如果服務正在運行,則先stop,然后再start;如果服務沒運行,直接start。
? 總結
指令 | 作用 | 是否阻塞 | 典型觸發時機 |
---|---|---|---|
class_start <class> | 啟動指定類別中尚未運行的服務 | 否(異步) | on boot 、on property: |
class_stop <class> | 停止指定類別中正在運行的所有服務 | 否(異步) | 用戶切換、省電模式、調試 |
class_restart [--only-enabled] <class> | 先停止,再重新啟動該類所有服務 | 否(異步) | 錯誤恢復、配置重載、調試 |
-
start <service>
如果指定的服務尚未運行,則啟動該服務。如果該服務已運行,start不會重復啟動。
-
stop <service>
停止運行指定的service。
-
restart [ --only-if-running ] <service>
- 停止并重啟一個正在運行的service。
- 如果該service處于重啟過程中,則不執行任何操作;
- 如果該服務未運行,則直接啟動該服務(相當于start <service>);
- 如果指定了--only-if-running選項,則僅當服務正在運行時才執行重啟。如果服務未運行,則不做任何操作。
exec_start <service>
- 啟動指定的服務,并暫停后續init指令,知道該service執行完成并返回。
- 他是惟一能阻塞init進程的同步指令,允許在關鍵啟動中精確控制執行順序,確保某些service必須啟動完成。
- 使用舉例:
on zygote-start && property:ro.crypto.state=unencrypted# wait OTA signature verifcation wait_for_prop odsign.verification.done 1# A/B update verifier that marks a successful boot.exec_start update_verifier_nonencryptedstart statsdstart netdstart zygotestart zygote_secondary
- A/B update:又稱無縫更新,設備上由兩套系統分區:A和B,當前系統允許在分區A,分區B可以后臺靜默更新,更新完成后,下次重啟就切換到B分區。?
- 首次啟動B系統,則必須標記本次啟動成功,如果啟動成功,則B被永久標注為“新系統”,如果啟動失敗,下次自動切換A分區。
- A/B update verifier:檢查當前系統是否時首次從新系統啟動,如果是則將successful標志置為1
-
enable <servicename>
- 將一個disabled的service轉化成enable,即激活service。
- enable本身不啟動服務,他只是激活service,當service的啟動條件滿足時才會被啟動,即使他是disabled。
? 總結
指令 | 作用 | 是否阻塞?init | 典型使用場景 | 注意事項 |
---|---|---|---|---|
start <servic> | 啟動一個已定義的服務 | ?否 (異步) | 正常啟動服務,如?start zygote | 若服務已在運行,不會重復啟動 |
stop <servic> | 停止一個正在運行的服務 | 否 (異步) | 關機、切換模式時停止服務 | 服務進程退出后不再自動重啟(除非有 respawning) |
restart <servic> | 先?stop ,再?start ?服務 | 否 (異步) | 配置變更后重載服務,如?restart adbd | 等價于?stop + start ,服務會短暫中斷 |
exec_start <servic> | 同步執行一個?oneshot ?服務,并等待其完成 | 是 (同步) | 關鍵初始化任務,如標記 OTA 成功、運行配置腳本 | 僅適用于?oneshot ?服務;init ?會等待其退出后再執行后續命令 |
enable <service> | 激活一個被?disabled ?的服務,使其可被?start ?或自動啟動 | 否 (異步) | 根據屬性動態啟用服務,如?enable watchdogd ?when?ro.boot.quiescent=1 | 服務必須先定義為?disabled ;enable ?后若滿足條件(如屬于?main ?class 且已?class_start ),會立即啟動 |
-
exec [ <seclabel> [ <user> [ <group> *] ] ] -- <command> [ <argument> *]
fork一個子進程并在指定的上下文(SELinux權限以及user/group)下執行。
該指令是一個同步的,會阻塞init進程。在該指令執行完成前,init將暫停后續所有指令。
參數解釋 | 說明 |
---|---|
<seclabel> | SELinux 安全上下文,如? 用? |
<user> | 執行用戶,如?root 、system 、shell |
<group>* | 零個或多個補充組,如?inet 、log 、system |
-- | 分隔符,表示前面是執行上下文,后面是命令 |
<command> | 要執行的可執行文件路徑 |
[argument]* | 命令參數,支持屬性展開?${prop} |
-
exec_backgroud?[ <seclabel> [ <user> [ <group> *] ] ] -- <command> [ <argument> *]
- 與exec類似,fork一個子進程并在指定的上下文(SELinux權限以及user/group)下執行。
- 該指令是異步的,不會阻塞init,會繼續執行后續指令。
? 總結
指令 | 是否阻塞?init | 用途 |
---|---|---|
exec | ? 是(同步) | 執行關鍵初始化任務,必須完成才能繼續 |
exec_background | ? 否(異步) | 執行非關鍵、后臺任務,不阻塞啟動流程 |
-
setprop <name> <value>
給指定的系統屬性賦值。
- 它是觸發屬性值為條件(on property:)的event,eg:
on property:sys.boot_completed=1bootchart stop# Setup per_boot directory so other .rc could start to use it on boot_completedexec - system system -- /bin/rm -rf /data/per_bootmkdir /data/per_boot 0700 system system encryption=Require key=per_boot_refsetprop ro.vendor.qti.per_boot_created 1
- 常見的系統屬性分類:
前綴 說明 是否可寫 ro.*
只讀屬性(Read-Only) ? 僅在? init
?階段可設,之后不可改sys.*
系統屬性,可被? init
?和系統服務修改? 可修改 persist.*
持久化屬性,寫入? /data/property/
? 可修改,重啟后保留 ctl.*
控制屬性(如? ctl.start
,?ctl.stop
)? 觸發服務控制 debug.*
調試屬性 ? 開發者可設symlink <target> <path>
-
trigger <event>
觸發一個事件,用于從一個Action執行完成后,主動觸發另一個Action。
-
symlink <target> <path>
在指定path創建一個指向target的符號鏈接(相當于軟連接,即ln -s <target> <path>)。
-
wait_for_prop <name> <value>
等待指定系統屬性的值變成指定value,如果該屬性值等于value,則立即執行后續命令。
他是init中用于同步控制的關鍵指令,setprop會觸發該指令往后執行。
2 Imports?
-
import <path>
- 導入一個init配置文件(或者目錄下所有文件)。如果path是文件,則解析該文件;如果path是目錄,則解析該目錄下所有文件(不遞歸子目錄)。
import是Android init系統實現模塊化、分層話配置管理的核心機制。它允許:
將龐大的初始化配置拆分為多個?.rc
?文件;
按硬件、供應商、產品維度組織配置;
實現系統組件的解耦與可維護性;
支持動態加載?/vendor
、/odm
?等分區的配置。- 使用舉例,init.rc中
import /init.environ.rc import /system/etc/init/hw/init.usb.rc import /init.${ro.hardware}.rc import /vendor/etc/init/hw/init.${ro.hardware}.rc import /system/etc/init/hw/init.usb.configfs.rc import /system/etc/init/hw/init.${ro.zygote}.rc
3 Properties
-
init.svc.<name>
- 查詢指定Service name的狀態。name是.rc文件中定義的Service名稱。
- 當每個Service的狀態發生便后時,init都會更新對應的init.svc.<name>的屬性值。
eg: 查詢某個Service的狀態:adb shell getprop init.svc.zygote
- 服務的狀態值類型有:
狀態值 說明 running
服務正在運行(主進程已啟動且未崩潰) stopped
服務已停止(未運行,且不是因為崩潰) restarting
服務正在重啟(通常因崩潰后由? init
?重啟)stopping
服務正在停止過程中(收到? SIGTERM
,但進程尚未退出)disabled
服務被禁用(通過? setprop init.svc.<name> disabled
)invalid
服務未定義或路徑無效(如可執行文件不存在)
-
ctl. [ <target>_ ] <command> <value>
- 該類屬性是Android init用于遠程控制Service生命周期和行為的“控制通道”。它允許系統其他組件通過設置屬性來間接執行start/stop等。
- <target>是可選的,指定匹配的Service(當前只支持target取值Interface),注意“_”不要缺失;
- <command>是要執行的指令,前邊1 Command部分介紹的指令集,常見的有start/stop?
- <value>可以是Servicename,如果是Interface,對于AIDL,則value是aidl/instance;對于HIDL,則value是package::Interface/instance。
- 使用舉例:
setprop ctl.restart vendor.power-hal-aidl setprop ctl.interface_restart android.hardware.power@1.0::IPower/default
4 Boot Timing
init進程在啟動過程中會精確記錄關鍵結算的時間戳和耗時,并將其寫入只讀屬性ro.boottime.*中。
屬性 含義 單位 說明 ro.boottime.init
第一階段? init
?啟動的時間點ns 從? CLOCK_BOOTTIME
?開始到?init
?進程開始執行的時間ro.boottime.init.first_stage
第一階段? init
?執行耗時ns 通常指? ramdisk
?中的?init
?執行時間(如設備樹解析、掛載?/dev
?等)ro.boottime.init.selinux
SELinux 策略加載與轉換耗時 ns 包括? load_policy
、restorecon
?等操作ro.boottime.init.modules
內核模塊加載耗時 ms init
?執行?insmod
?或?modprobe
?加載?.ko
?文件的總時間ro.boottime.init.cold_boot_wait
等待? ueventd
?完成冷啟動設備發現的耗時ns init
?等待?ueventd
?發出?coldboot_done
?事件的時間