之前整顿过Android 7的初始化程序,曾经过期了,基于Android 11重新整理下并公布,不便查看与rc里初始化程序无关的问题和bug.
<!-- more -->
[Android 11]
代码可看
http://aosp.opersys.com/xref/...
初始化语言可看
/system/core/init/README.md
或者
https://blog.csdn.net/u010753159/article/details/51981121
这里不讲这些, 也不剖析init代码.
init rc 总体初始化程序
FirstStageMain() | v SetupSelinux() | v SecondStageMain() | v+----------------------+| SetupCgroups || SetKptrRestrict || TestPerfEventSelinux || early-init +--> mount_all fstab.persist --early // hardware/google/pixel/common/init.pixel.rc|wait_for_coldboot_done|| MixHwrngIntoLinuxRng || SetMmapRndBits || KeychordInit || init || MixHwrngIntoLinuxRng || | || bootmode == "charger"|| / \ || + + || charger late-init +--> +--------trigger---------+| \ / | | early-fs || + | | fs +--> mount_all fstab.firmware --early| | | | late-fs +--> +--------------------------------+|queue_property_triggers| | post-fs | |mount_all fstab.firmware --late +--> queue_fs_event --> trigger nonencrypted+-----------------------+ | post-fs-data | | class_start early_hal | | |load_persist_props_action| +--------------------------------+ +-class_start-+ | load_bpf_programs | | main | | zygote-start | | late_start | |firmware_mounts_complete| +-------------+ | early-boot | ^ | boot +--> +-class_start-+ | +------------------------+ | hal | | | | core | | | + ------------+ | +------------------------------------------执行完 on boot后才执行-------------------- -+
on late-init 和 late-fs 启动具体代码
/system/core/rootdir/init.rcon late-init trigger early-fs # Mount fstab in init.{$device}.rc by mount_all command. Optional parameter # '--early' can be specified to skip entries with 'latemount'. # /system and /vendor must be mounted by the end of the fs stage, # while /data is optional. trigger fs trigger post-fs # Mount fstab in init.{$device}.rc by mount_all with '--late' parameter # to only mount entries with 'latemount'. This is needed if '--early' is # specified in the previous mount_all command on the fs stage. # With /system mounted and properties form /system + /factory available, # some services can be started. trigger late-fs # Now we can mount /data. File encryption requires keymaster to decrypt # /data, which in turn can only be loaded when system properties are present. trigger post-fs-data # Load persist properties and override properties (if enabled) from /data. trigger load_persist_props_action # Should be before netd, but after apex, properties and logging is available. trigger load_bpf_programs # Now we can start zygote for devices with file based encryption trigger zygote-start # Remove a file to wake up anything waiting for firmware. trigger firmware_mounts_complete trigger early-boot trigger boot// late-fson late-fs # Ensure that tracefs has the correct permissions. # This does not work correctly if it is called in post-fs. chmod 0755 /sys/kernel/tracing chmod 0755 /sys/kernel/debug/tracing # HALs required before storage encryption can get unlocked (FBE/FDE) class_start early_hal
early_hal类服务有:
early_hal/system/hardware/interfaces/suspend/1.0/default/android.system.suspend@1.0-service.rc/system/core/trusty/keymaster/3.0/android.hardware.keymaster@3.0-service.trusty.rc/system/core/trusty/keymaster/4.0/android.hardware.keymaster@4.0-service.trusty.rc
留神:
QueueEventTrigger和QueueBuiltinAction都是将其放放到event_queue_里,等轮到他时再执行
/system/core/init/action_manager.cppvoid ActionManager::QueueEventTrigger(const std::string& trigger) { auto lock = std::lock_guard{event_queue_lock_}; // 退出到 event_queue_队列里 event_queue_.emplace(trigger);}......void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) { auto lock = std::lock_guard{event_queue_lock_}; auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name, std::map<std::string, std::string>{}); action->AddCommand(std::move(func), {name}, 0); // 退出到 event_queue_队列里 event_queue_.emplace(action.get()); actions_.emplace_back(std::move(action));}
也就是说在
on late-fs --> mount_all --> trigger nonencrypted
的时候,并没有执行 on nonencrypted
而是等到之前队列里的trigger执行完后才执行它, 咱们看到 on late-init
时加了一堆的trigger,
最初个是boot, 所以(如果两头没新退出的) on nonencrypted
是在 on boot
之后才执行的, 并不是在 on late-fs
之后执行的.
也即 class main
和class late_start
在 on boot后执行
on late-init trigger early-fs trigger fs trigger post-fs trigger late-fs .... trigger boot// on boot后执行on nonencrypted class_start main class_start late_start
imports 与 目录里的雷同Action执行程序
咱们晓得,不同rc文件文件里是能够有雷同的action的,init程序在解析时会将这些不同文件的action合并,
那这些合并后的action执行程序是咋样的?
BTW, 解析rc文件有趣味的能够看看, 相当于是个小型的语法解析. 代码在 /system/core/init/parser.cpp ParseData()
具体的说,就是
- init.rc 与 其 import导入的文件里雷同action执行程序
- /{system,vendor,odm}/etc/init/ 里雷同action执行程序
这个其实在/system/core/init/README.md
Imports 章节都有形容的, 倡议认真的看看.
简略来说,其先后顺序为
init.rc -> init.rc里的import -> import 自身 -> import的import -> /system/etc/init/ -> /vendor/etc/init/ -> /odm/etc/init/ ^ ^ +--------递归-----+
README.md用伪代码里形容如下:
fn Import(file) Parse(file) for (import : file.imports) Import(import)Import(/init.rc)Directories = [/system/etc/init, /vendor/etc/init, /odm/etc/init]for (directory : Directories) files = <Alphabetical order of directory's contents> for (file : files) Import(file)
具体的代码可看下
/system/core/init/init.cppSecondStageMain() --> LoadBootScripts()static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) { Parser parser = CreateParser(action_manager, service_list); std::string bootscript = GetProperty("ro.boot.init_rc", ""); if (bootscript.empty()) { parser.ParseConfig("/system/etc/init/hw/init.rc"); if (!parser.ParseConfig("/system/etc/init")) { late_import_paths.emplace_back("/system/etc/init"); } // late_import is available only in Q and earlier release. As we don't // have system_ext in those versions, skip late_import for system_ext. parser.ParseConfig("/system_ext/etc/init"); if (!parser.ParseConfig("/product/etc/init")) { late_import_paths.emplace_back("/product/etc/init"); } if (!parser.ParseConfig("/odm/etc/init")) { late_import_paths.emplace_back("/odm/etc/init"); } if (!parser.ParseConfig("/vendor/etc/init")) { late_import_paths.emplace_back("/vendor/etc/init"); } } else { parser.ParseConfig(bootscript); }}
从代码里咱们可看到,如果指定了ro.boot.init_rc
就用指定的,
否则就用默认那几个目录的, 其中还有对 /system/etc/init/hw/init.rc
和 system_ext
目录反对.
图就不画了,看看代码就好.
- 对同一个目录下文件解析, 其实是按升序解析的
所以如果同一目录下有雷同的action, 要依照文件名升序先后执行的.
代码如下
/system/core/init/parser.cppbool Parser::ParseConfigDir(const std::string& path) { LOG(INFO) << "Parsing directory " << path << "...";...... std::vector<std::string> files; // 获取目录下文件 while ((current_file = readdir(config_dir.get()))) { // Ignore directories and only process regular files. if (current_file->d_type == DT_REG) { std::string current_path = android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name); files.emplace_back(current_path); } } // 按升序排序 // Sort first so we load files in a consistent order (bug 31996208) std::sort(files.begin(), files.end()); // 挨个解析排序后的文件 for (const auto& file : files) { if (!ParseConfigFile(file)) { LOG(ERROR) << "could not import file '" << file << "'"; } } return true;}
执行程序调节
通过以上剖析,咱们大抵的晓得了这些rc文件和action执行先后顺序,
如果有须要调节程序的,能够从以下几个方面思考
- (自定义) 调节trigger程序
- 调节服务的 class 级别 (class main, class core ....)
- 调节rc文件地位
- 调节文件名按升序形式排在后面