我们先看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
on early-init
...
on init
...
# This allows the ledtrig-transient properties to be created here so
# that they can be chown'd to system:system later on boot
write /sys/class/leds/vibrator/trigger "transient"
# This is used by Bionic to select optimized routines.
write /dev/cpu_variant:${ro.bionic.arch} ${ro.bionic.cpu_variant}
chmod 0444 /dev/cpu_variant:${ro.bionic.arch}
write /dev/cpu_variant:${ro.bionic.2nd_arch} ${ro.bionic.2nd_cpu_variant}
chmod 0444 /dev/cpu_variant:${ro.bionic.2nd_arch}
# Allow system processes to read / write power state.
chown system system /sys/power/state
chown system system /sys/power/wakeup_count
chmod 0660 /sys/power/state
# Start logd before any other services run to ensure we capture all of their logs.
start logd
# Start lmkd before any other services run so that it can register them
chown root system /sys/module/lowmemorykiller/parameters/adj
chmod 0664 /sys/module/lowmemorykiller/parameters/adj
chown root system /sys/module/lowmemorykiller/parameters/minfree
chmod 0664 /sys/module/lowmemorykiller/parameters/minfree
start lmkd
# Start essential services.
start servicemanager
start hwservicemanager
start vndservicemanager
# Mount filesystems and start core system services.
on late-init
trigger early-fs
trigger fs
trigger post-fs
# 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
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start && property:ro.crypto.state=unencrypted
wait_for_prop odsign.verification.done 1
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start statsd
start netd
start zygote
start zygote_secondary
on zygote-start && property:ro.crypto.state=unsupported
wait_for_prop odsign.verification.done 1
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start statsd
start netd
start zygote
start zygote_secondary
on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
wait_for_prop odsign.verification.done 1
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start statsd
start netd
start zygote
start zygote_secondary
解析init.rc
接着我们看是怎么解析init.rc文件的。给parse变量进行赋值,创建了三个parser,分别是对service,on,import单词进行parse。
首先*.rc 脚本中所有 service关键字定义的服务将会添加到service_list列表中。
*.rc 脚本中所有on关键开头的项将会被会添加到 action_list 列表中。
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
Parser parser;
parser.AddSectionParser("service", std::make_unique(&service_list, GetSubcontext(), std::nullopt));
parser.AddSectionParser("on", std::make_unique(&action_manager, GetSubcontext()));
parser.AddSectionParser("import", std::make_unique(&parser));
return parser;
}
void Parser::AddSectionParser(const std::string& name, std::unique_ptr parser) {
section_parsers_[name] = std::move(parser);
}
用于解析的关键函数是parseData函数,
next_token函数用就是寻找单词结束或者行结束标志,如果是单词结束标志就将单词push到args中,如果是行结束标志,则根据第一个单词来判断是否是一个section,section的标志只有三个"on",“service”,“import”,如果是"section",会根据关键字的不同会调用不同的 parser去解析(多态) 通过相应的ParseSection()函数来处理一个section,,action使用ActionParser,而 service 使用 ServiceParser 解析,该部分定义在LoadBootScrip()函数的第一行,parser.AddSectionParser()方法为parser的map成员section_parsers_创建了三个SectionParser,分别用来解析service,on,import的section;否则把这一行继续作为前“section”所属的行来处理
ParseSection()被用来解析一个新的section,ParseLineSection()被用来解析该section下的命令行
void Parser::ParseData(const std::string& filename, std::string* data) {
data->push_back('\n');
data->push_back('\0');
for (;;) {
switch (next_token(&state)) {
case T_EOF:
end_section();
for (const auto& [section_name, section_parser] : section_parsers_) {
section_parser->EndFile();
}
return;
case T_NEWLINE: {
state.line++;
if (args.empty()) break;
// If we have a line matching a prefix we recognize, call its callback and unset any
// current section parsers. This is meant for /sys/ and /dev/ line entries for
// uevent.
auto line_callback = std::find_if(
line_callbacks_.begin(), line_callbacks_.end(),
[&args](const auto& c) { return android::base::StartsWith(args[0], c.first); });
if (line_callback != line_callbacks_.end()) {
end_section();
if (auto result = line_callback->second(std::move(args)); !result.ok()) {
parse_error_count_++;
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
}
} else if (section_parsers_.count(args[0])) {
end_section();
section_parser = section_parsers_[args[0]].get();
section_start_line = state.line;
if (auto result =
section_parser->ParseSection(std::move(args), filename, state.line);
!result.ok()) {
parse_error_count_++;
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
section_parser = nullptr;
bad_section_found = true;
}
} else if (section_parser) {
if (auto result = section_parser->ParseLineSection(std::move(args), state.line);
!result.ok()) {
parse_error_count_++;
LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
}
} else if (!bad_section_found) {
parse_error_count_++;
LOG(ERROR) << filename << ": " << state.line
<< ": Invalid section keyword found";
}
args.clear();
break;
}
case T_TEXT:
args.emplace_back(state.text);
break;
}
}
}
解析完了init.rc文件以后,调用am.QueueEventTrigger(‘init-early’)意为early-init时间已经到来,可以执行triggle只为early-init的action了。
init最终会进入了无限循环的监听状态,可以看到这里面一个核心函数就是 am.ExecuteOneCommand();之前说的QueueEventTrigger(“early-init”)把early-init加入到event_queue_的队列中,ExecuteOneCommand()一开始就遍历之前解析的action向量表。当一个 action对象所有的 command 均执行完毕后,再执行下一个action。
从init.rc文件中可以看到最关键的是启动zygote。
本站内容来源于作者发布和网络转载,如有版权相关问题请及时与我们取得联系,我们将立即删除。