Android 9.0 init 啟動流程
閱讀五分鐘,每日十點,和您一起終身學習,這裡是程式設計師Android
本篇文章主要介紹 Android
開發中的部分知識點,通過閱讀本篇文章,您將收穫以下內容:
一、啟動流程概述
一、 啟動流程概述
Android
啟動流程跟 Linux
啟動類似,大致分為如下五個階段。
1.開機上電,載入固化的
ROM
。2.載入
BootLoader
,拉起Android OS
。3.載入
Uboot
,初始外設,引導Kernel
啟動等。4.啟動
Kernel
,載入驅動,硬體。5.啟動
Android
,掛載分割槽,載入驅動、服務,init
程式等。
1.Android系統啟動大致過程如下
Android 啟動過程
由於水平有限,無法深入了理解驅動層程式碼,本文主要對 Android
上層啟動流程進行分析。
二、Android啟動分析
Uboot
啟動Kernel
完成系統設定後,會首先在系統中尋找init.rc
檔案,並啟動init
程式。
Android 啟動分析
三、init 程式啟動分析
Init
程式是Android
啟動的第一個程式,程式號為1
,是Android
的系統啟動的核心程式,主要用來建立Zygote
、屬性服務等。 init.cpp
中的main
函式,是init
程式的入口函式,原始碼主要存在\system\core\init
目錄下。
1.常見init.xxx.rc 程式
常見init.xxx.rc 程式
2.init 程式主要作用
init 程式主要作用
3./system/core/init 部分內容如下:
/system/core/init 部分內容
4.main 函式主要做的事情
1.建立掛載啟動所需的檔案系統(tmpfs、 devpts、 proc、 sysfs、 selinuxfs等)
。init.rc
指令碼配置檔案,並啟動Zygote
程式。
5.init.cpp main 函式實現程式碼
int main(int argc, char** argv) {
... ...
if (!strcmp(basename(argv[0]), "watchdogd")) {
//啟動看門狗函式
return watchdogd_main(argc, argv);
}
... ...
//啟動第一階段
if (is_first_stage) {
boot_clock::time_point start_time = boot_clock::now();
// 清理 umask.
umask(0);
clearenv();
setenv("PATH", _PATH_DEFPATH, 1);
// 在RAM記憶體上獲取基本的檔案系統,剩餘的被 rc 檔案所用
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
#define MAKE_STR(x) __STRING(x)
mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
// 非特權應用不能使用 Android 命令列
chmod("/proc/cmdline", 0440);
gid_t groups[] = { AID_READPROC };
setgroups(arraysize(groups), groups);
mount("sysfs", "/sys", "sysfs", 0, NULL);
mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
if constexpr (WORLD_WRITABLE_KMSG) {
mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11));
}
mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
// Mount staging areas for devices managed by vold
// See storage config details at http://source.android.com/devices/storage/
mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=1000");
//建立可供讀寫的 vendor目錄
mkdir("/mnt/vendor", 0755);
// 在/dev目錄下掛載好 tmpfs 以及 kmsg
// 這樣就可以初始化 /kernel Log 系統,供使用者列印log
InitKernelLogging(argv);
LOG(INFO) << "init first stage started!";
if (!DoFirstStageMount()) {
LOG(FATAL) << "Failed to mount required partitions early ...";
}
SetInitAvbVersionInRecovery();
// Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
global_seccomp();
// 優先載入selinux log系統, 緊接著初始化selinux
SelinuxSetupKernelLogging();
SelinuxInitialize();
// 新增 selinux 是否啟動成功的log
if (selinux_android_restorecon("/init", 0) == -1) {
PLOG(FATAL) << "restorecon failed of /init failed";
}
setenv("INIT_SECOND_STAGE", "true", 1);
static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;
uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;
setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1);
char* path = argv[0];
char* args[] = { path, nullptr };
execv(path, args);
// execv() only returns if an error happened, in which case we
// panic and never fall through this conditional.
PLOG(FATAL) << "execv(\"" << path << "\") failed";
}
//啟動第二階段
InitKernelLogging(argv);
LOG(INFO) << "init second stage started!";
// Set up a session keyring that all processes will have access to. It
// will hold things like FBE encryption keys. No process should override
// its session keyring.
keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);
// Indicate that booting is in progress to background fw loaders, etc.
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
//初始化屬性
property_init();
// If arguments are passed both on the command line and in DT,
// properties set in DT always have priority over the command-line ones.
process_kernel_dt();
process_kernel_cmdline();
// Propagate the kernel variables to internal variables
// used by init as well as the current required properties.
export_kernel_boot_props();
// Make the time that init started available for bootstat to log.
property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));
property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));
// Set libavb version for Framework-only OTA match in Treble build.
const char* avb_version = getenv("INIT_AVB_VERSION");
if (avb_version) property_set("ro.boot.avb_version", avb_version);
// 清空設定的環境變數
unsetenv("INIT_SECOND_STAGE");
unsetenv("INIT_STARTED_AT");
unsetenv("INIT_SELINUX_TOOK");
unsetenv("INIT_AVB_VERSION");
// 設定第二階段的selinux
SelinuxSetupKernelLogging();
SelabelInitialize();
SelinuxRestoreContext();
//建立 epoll 控制程式碼
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (epoll_fd == -1) {
PLOG(FATAL) << "epoll_create1 failed";
}
//設定 子程式處理函式
sigchld_handler_init();
if (!IsRebootCapable()) {
// If init does not have the CAP_SYS_BOOT capability, it is running in a container.
// In that case, receiving SIGTERM will cause the system to shut down.
InstallSigtermHandler();
}
LoadRscRoProps();
property_load_boot_defaults();
export_oem_lock_status();
//啟動屬性服務
start_property_service();
//為USB儲存設定udc Contorller, sys/class/udc
set_usb_controller();
const BuiltinFunctionMap function_map;
Action::set_function_map(&function_map);
subcontexts = InitializeSubcontexts();
ActionManager& am = ActionManager::GetInstance();
ServiceList& sm = ServiceList::GetInstance();
LoadBootScripts(am, sm);
// Turning this on and letting the INFO logging be discarded adds 0.2s to
// Nexus 9 boot time, so it's disabled by default.
if (false) DumpState();
am.QueueEventTrigger("early-init");
// Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
// ... so that we can start queuing up actions that require stuff from /dev.
am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
am.QueueBuiltinAction(keychord_init_action, "keychord_init");
am.QueueBuiltinAction(console_init_action, "console_init");
// Trigger all the boot actions to get us started.
am.QueueEventTrigger("init");
// Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
// wasn't ready immediately after wait_for_coldboot_done
am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
// Don't mount filesystems or start core system services in charger mode.
std::string bootmode = GetProperty("ro.bootmode", "");
if (bootmode == "charger") {
am.QueueEventTrigger("charger");
} else {
am.QueueEventTrigger("late-init");
}
// Run all property triggers based on current state of the properties.
am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
while (true) {
// By default, sleep until something happens.
int epoll_timeout_ms = -1;
if (do_shutdown && !shutting_down) {
do_shutdown = false;
if (HandlePowerctlMessage(shutdown_command)) {
shutting_down = true;
}
}
if (!(waiting_for_prop || Service::is_exec_service_running())) {
am.ExecuteOneCommand();
}
if (!(waiting_for_prop || Service::is_exec_service_running())) {
if (!shutting_down) {
auto next_process_restart_time = RestartProcesses();
// If there's a process that needs restarting, wake up in time for that.
if (next_process_restart_time) {
epoll_timeout_ms = std::chrono::ceil<std::chrono::milliseconds>(
*next_process_restart_time - boot_clock::now())
.count();
if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
}
}
// If there's more work to do, wake up again immediately.
if (am.HasMoreCommands()) epoll_timeout_ms = 0;
}
epoll_event ev;
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
if (nr == -1) {
PLOG(ERROR) << "epoll_wait failed";
} else if (nr == 1) {
((void (*)()) ev.data.ptr)();
}
}
return 0;
}
6.基於MTK 平臺 init.cpp 原始碼分析
基於MTK 平臺 init.cpp 主要作用
四、 init 啟動指令碼分析
init.rc
路徑 一般在system/core/rootdir
下,init
指令碼是有Android
初始化語言編寫。
1.Android Init Language 語句型別
1.Action
2.Command
3.Service
4.Option
5.Import
init 程式分析
init.rc on
init.rc services
init.rc import
五、init 程式分析
init 程式分析
init 解析指令碼分析
init 事件列表
init 事件結構
六 、init 指令碼執行
init 程式解析和執行
啟動指令碼解析結果
整理事件列表
init 構建事件
Service 事件分類
init 程式執行命令和啟動服務
七、init 程式守護
init
程式處理訊息事件
根據
Shell
或者系統中訊息設定系統prop
守護系統服務,如果服務退出,重啟退出的服務。
init守護程式
init 處理 prop 訊息分析
init 守護服務分析
八、init rc 指令碼啟動Zygote
Zygote
的 classname
為main
.init.rc
檔案配置程式碼如下:
... ...
on nonencrypted
class_start main
class_start late_start
on property:sys.init_log_level=*
loglevel ${sys.init_log_level}
... ...
九、啟動分析小結
啟動分析小結
友情推薦
至此,本篇已結束,如有不對的地方,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!
分享到朋友圈吧,方便您使用時快速查詢!
相關文章
- Activity 的 "啟動流程"(基於 Android 9.0)Android
- Android系統啟動流程(一)解析init程式Android
- 原始碼閱讀之Activity啟動與App啟動流程 - Android 9.0原始碼APPAndroid
- 原始碼閱讀之Activity啟動與App啟動流程 – Android 9.0原始碼APPAndroid
- 【Android】【init】解析init程式啟動過程Android
- (連載)Android 8.0 : 系統啟動流程之init程式(二)Android
- (連載)Android 8.0 : 系統啟動流程之init程式(一)Android
- Android系統啟動:init程式與init語言Android
- FlutterEngin啟動流程&androidFlutterAndroid
- Android 應用啟動流程Android
- Android 系統啟動流程Android
- Android APP 冷啟動流程AndroidAPP
- android app啟動流程解析AndroidAPP
- Android系統啟動流程(四)Launcher啟動過程與系統啟動流程Android
- 系統啟動, init
- Android 啟動過程簡析(一)之 init 程式Android
- Android應用啟動流程分析Android
- OpenHarmony的init程式、init配置與啟動項配置
- Flutter Android 端啟動流程淺析FlutterAndroid
- Android Activity啟動流程原始碼分析Android原始碼
- Android App應用啟動流程(一)AndroidAPP
- Android原始碼分析:Activity啟動流程Android原始碼
- [譯]Android Application 啟動流程分析AndroidAPP
- Android 7.0 應用啟動流程分析Android
- 【Android原始碼】Activity的啟動流程Android原始碼
- Android系統啟動流程(三)解析SyetemServer程式啟動過程AndroidServer
- 深入理解Android 之 Activity啟動流程(Android 10)Android
- Android 系統開發_啟動階段篇 — 深入鑽研 initAndroid
- Debian init 開機啟動管理
- init.cssd程式啟動失敗CSS
- Android 9.0 預設輸入法的設定流程分析Android
- Android系統啟動流程(二)解析Zygote程式AndroidGo
- Android系統原始碼分析–Service啟動流程Android原始碼
- 梳理一下Android 系統啟動流程Android
- Android系統原始碼分析--Service啟動流程Android原始碼
- MSM8953 Android 9.0 開啟uart串列埠Android串列埠
- Flutter啟動流程Flutter
- AMS啟動流程