一.概述
init进程启动后,会解析system、system_ext、vendor、odm、product分区下的*.rc文件,最后解析完成后,会得到一系列的Action和Service,并通过ActionManager存储所有的Action,通过ServiceList存储所有的Service,最后由SecondStageMain通过轮训调用ActionManager::ExecuteOneCommand触发执行。
二.rc文件解析流程
-
rc文件的解析是从init进程启动的第二阶段开始的,即
SecondStageMain方法。源码位于
system/core/init/init.cpp。c++int SecondStageMain(int argc, char** argv) { ... const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap(); Action::set_function_map(&function_map); ... ActionManager& am = ActionManager::GetInstance(); ServiceList& sm = ServiceList::GetInstance(); LoadBootScripts(am, sm); ... return 0; } -
GetBuiltinFunctionMap
源码位于
system/core/init/builtins.cppc++const BuiltinFunctionMap& GetBuiltinFunctionMap() { constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max(); // clang-format off static const BuiltinFunctionMap builtin_functions = { ... {"class_start", {1, 1, {false, do_class_start}}}, ... {"trigger", {1, 1, {false, do_trigger}}}, ... }; // clang-format on return builtin_functions; }从源码可以看出,GetBuiltinFunctionMap的返回结果,里面记录了rc语法中的涉及的命令及执行该命令时要调用的函数。
-
通过调用
Action::set_function_map,GetBuiltinFunctionMap的返回会被保存到Action的静态成员属性中,源码位于
system/core/init/action.hc++class Action { public: ... static void set_function_map(const BuiltinFunctionMap* function_map) { function_map_ = function_map; } private: ... static const BuiltinFunctionMap* function_map_; }; -
LoadBootScripts
源码位于
system/core/init/init.cppc++static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) { Parser parser = CreateParser(action_manager, service_list); std::string bootscript = GetProperty("ro.boot.init_rc", ""); // bootscript.empty(): 1 if (bootscript.empty()) { parser.ParseConfig("/system/etc/init/hw/init.rc"); // parser.ParseConfig("/system/etc/init"): 1 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"): 1 parser.ParseConfig("/system_ext/etc/init"); // parser.ParseConfig("/vendor/etc/init"): 1 if (!parser.ParseConfig("/vendor/etc/init")) { late_import_paths.emplace_back("/vendor/etc/init"); } // parser.ParseConfig("/odm/etc/init"): 0 if (!parser.ParseConfig("/odm/etc/init")) { late_import_paths.emplace_back("/odm/etc/init"); } // parser.ParseConfig("/product/etc/init"): 0 if (!parser.ParseConfig("/product/etc/init")) { late_import_paths.emplace_back("/product/etc/init"); } } else { parser.ParseConfig(bootscript); } } -
CreateParser
源码位于
system/core/init/init.cppc++Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) { Parser parser; // c++中std::make_unique相当于new对象,会返回一个std::unique_ptr,即智能指针,可以自动管理内存 // unique_ptr持有对对象的独有权,两个unique_ptr不能指向一个对象,不能进行复制操作只能进行移动操作 parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, GetSubcontext())); parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, GetSubcontext())); parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser)); return parser; }依次调用Parser对象的AddSectionParser方法,并传入"service"和ServiceParser对象,"on"和ActionParser对象,"import"和ImportParser对象。
AddSectionParser方法的源码位于
system/core/init/parser.cpp。c++void Parser::AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser) { // std::move是移动操作,例如: p1 = std::move(p),指针p指向的对象会移动到p1。 // section_parsers_是一个std:map,相当于java中的HashMap // section_parsers_中只有三个key,分别是on、service、import section_parsers_[name] = std::move(parser); }因此,CreateParser调用完成后,会创建一个map,并设置给Parser对象的私有成员属性section_parsers_持有,section_parsers_中只有三个key,service、on、import,分别对应ServiceParser、ActionParser、ImportParser对象。
ServiceParser源码位于
system/core/init/service_parser.cpp。ActionParser源码位于
system/core/init/action_parser.cpp。ImportParser源码位于
system/core/init/import_parser.cpp回到LoadBootScripts方法,继续调用ParseConfig,并依次传入
/system/etc/init/hw/init.rc、/system/etc/init、/system_ext/etc/init、/vendor/etc/init、/odm/etc/init、/product/etc/init。 -
ParseConfig和ParseConfigDir
源码位于
system/core/init/parser.cppc++bool Parser::ParseConfig(const std::string& path) { if (is_dir(path.c_str())) { return ParseConfigDir(path); } return ParseConfigFile(path); } bool Parser::ParseConfigDir(const std::string& path) { LOG(INFO) << "Parsing directory " << path << "..."; std::unique_ptr<DIR, decltype(&closedir)> config_dir(opendir(path.c_str()), closedir); if (!config_dir) { PLOG(INFO) << "Could not import directory '" << path << "'"; return false; } dirent* current_file; 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; }ParseConfig会判断传入路径是文件还是目录,如果是文件,调用ParseConfigFile,如果是目录,则遍历该目录下的
*.rc文件,对文件调用ParseConfigFile。 -
ParseConfigFile
源码位于
system/core/init/parser.cppc++bool Parser::ParseConfigFile(const std::string& path) { LOG(INFO) << "Parsing file " << path << "..."; android::base::Timer t; auto config_contents = ReadFile(path); if (!config_contents.ok()) { LOG(INFO) << "Unable to read config file '" << path << "': " << config_contents.error(); return false; } ParseData(path, &config_contents.value()); LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)"; return true; }ParseConfigFile会读取rc文件的内容,并调用ParseData。
三.ParseData
源码位于system/core/init/parser.cpp
c++
void Parser::ParseData(const std::string& filename, std::string* data) {
data->push_back('\n');
data->push_back('\0');
parse_state state;
state.line = 0;
state.ptr = data->data();
state.nexttoken = 0;
SectionParser* section_parser = nullptr;
int section_start_line = -1;
std::vector<std::string> args;
// If we encounter a bad section start, there is no valid parser object to parse the subsequent
// sections, so we must suppress errors until the next valid section is found.
bool bad_section_found = false;
auto end_section = [&] {
bad_section_found = false;
if (section_parser == nullptr) return;
if (auto result = section_parser->EndSection(); !result.ok()) {
parse_error_count_++;
LOG(ERROR) << filename << ": " << section_start_line << ": " << result.error();
}
section_parser = nullptr;
section_start_line = -1;
};
for (;;) {
// 一行一行的解析rc文件内容
switch (next_token(&state)) {
case T_EOF:
end_section();
for (const auto& [section_name, section_parser] : section_parsers_) {
section_parser->EndFile();
}
// 6.最后rc文件解析完后,所有的Action会被存入
// ActionManager持有的 std::vector<std::unique_ptr<Action>> actions_
// 所有的Service会被存入
// ServiceList持有的 std::vector<std::unique_ptr<Service>> services_
// 最后退出循环
return;
case T_NEWLINE: {
// 2. 开始解析读取到的一行数据
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])) {
// args[0]是当前行的第一个单词
// C++中std:map的count函数是查找key,相当于Java中Map的contains
// 3.解析以on、service或import开头的行
// 结束上一个section,
// 如果上一个section以on开头,执行ActionParser的EndSection(),
// 解析结果会被添加到ActionManager持有的 std::vector<std::unique_ptr<Action>> actions_ 中
// 如果上一个section以service开头,执行ServiceParser的EndSection(),
// 解析结果会被添加到ServiceList持有的 std::vector<std::unique_ptr<Service>> services_ 中
// 如果上一个section以import开头,执行ImportParser的EndSection(),递归解析被import的rc文件
end_section();
// 如果args[0]等于on,section_parser为ActionParser
// 执行section_parser->ParseSection会得到一个Action对象
// Action对象的大致结构为:
// Action {
// std::string event_trigger_; 事件触发条件
// std::vector<Command> commands_; 存储当前解析的Section中定义的所有命令
// std::string filename_; 当前Section所属的rc文件路径
// int line_; 当前Section的开头在rc文件中是第几行
// ...
// }
// 如果args[0]等于service,section_parser为ServiceParser
// 执行section_parser->ParseSection会得到一个Sevice对象
// Sevice对象的大致结构为:
// Sevice {
// const std::string name_; 解析到的service名称
// std::string filename_; 当前Section所属的rc文件路径
// const std::vector<std::string> args_; service的可执行二进制文件路径及参数
// ...
// }
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) { //如果当前行不是以on、service、import开头,说明是command或options
// 4.解析当前section下面的command或options
// command对应解析结果为Command对象,并存入当前Action对象持有的 std::vector<Command> commands_
// options的解析结果会复制给当前Service对象的属性
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";
}
// 5.当前行解析完成,清空args数组
args.clear();
break;
}
case T_TEXT:
// 1.将读取的一行数据按照空格拆分,并放到args中
args.emplace_back(state.text);
break;
}
}
}
ParseData会逐行解析rc文件的内容:
-
如果解析到以import开头的一行,则通过ImportParser递归去解析被导入的rc文件
-
以on开头的行到当前Section的最后一个command所在行的内容,认为是一个Action类型的Section,通过ActionParser解析为一个Action对象,并保存到ActionManager持有的 std::vector<std::unique_ptr<Action>> actions_。
-
以service开头的行到当前Section的最后一个options所在行的内容,认为是一个Service类型的Section,通过ServiceParser解析为一个Service对象,并保存到ServiceList持有的 std::vector<std::unique_ptr> services_。
-
Action的关键信息
c++Action { std::map<std::string, std::string> property_triggers_; // 属性触发条件 std::string event_trigger_; // 事件触发条件 std::vector<Command> commands_; // 存储当前解析的Section中定义的所有命令 std::string filename_; // 当前Section所属的rc文件路径 int line_; // 当前Section的开头在rc文件中是第几行 ... } -
Service的关键信息
c++Sevice { const std::string name_; // 解析到的service名称 std::string filename_; // 当前Section所属的rc文件路径 const std::vector<std::string> args_; // service的可执行二进制文件路径及参数 ... // 其他option }
四.如何触发Action执行
-
事件触发
ActionManager::QueueEventTrigger(const std::string& trigger);
c++void ActionManager::QueueEventTrigger(const std::string& trigger) { auto lock = std::lock_guard{event_queue_lock_}; event_queue_.emplace(trigger); } -
系统属性改变触发
ActionManager::QueuePropertyChange(const std::string& name, const std::string& value);
c++void ActionManager::QueuePropertyChange(const std::string& name, const std::string& value) { auto lock = std::lock_guard{event_queue_lock_}; event_queue_.emplace(std::make_pair(name, value)); } -
内建Action触发
ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name);
c++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_.emplace(action.get()); actions_.emplace_back(std::move(action)); } -
三种触发方式,都是把对应的触发条件添加到ActionManager持有的event_queue_队列中,真正触发执行是在SecondStageMain中完成的。
SecondStageMain的最后会开启一个死循环,轮训调用ActionManager::ExecuteOneCommand
system/core/init/init.cppc++int SecondStageMain(int argc, char** argv) { ... ActionManager& am = ActionManager::GetInstance(); ... while (true) { ... if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) { am.ExecuteOneCommand(); } ... } return 0; }ActionManager::ExecuteOneCommand
system/core/init/action_manager.cppc++void ActionManager::ExecuteOneCommand() { { auto lock = std::lock_guard{event_queue_lock_}; // Loop through the event queue until we have an action to execute while (current_executing_actions_.empty() && !event_queue_.empty()) { for (const auto& action : actions_) { if (std::visit([&action](const auto& event) { return action->CheckEvent(event); }, event_queue_.front())) { current_executing_actions_.emplace(action.get()); } } event_queue_.pop(); } } if (current_executing_actions_.empty()) { return; } auto action = current_executing_actions_.front(); if (current_command_ == 0) { std::string trigger_name = action->BuildTriggersString(); LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename() << ":" << action->line() << ")"; } action->ExecuteOneCommand(current_command_); // If this was the last command in the current action, then remove // the action from the executing list. // If this action was oneshot, then also remove it from actions_. ++current_command_; if (current_command_ == action->NumCommands()) { current_executing_actions_.pop(); current_command_ = 0; if (action->oneshot()) { auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; }; actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser), actions_.end()); } } }ExecuteOneCommand会遍历之前从rc文件中解析到的所有action,从event_queue_中取出一个触发条件(如果有),触发条件可以是字符串、map、也可以是一个Action对象,通过这个触发条件过滤出满足条件的Action,同时将触发条件从event_queue_队列中移除。
system/core/init/action.cppc++bool Action::CheckPropertyTriggers(const std::string& name, const std::string& value) const { if (property_triggers_.empty()) { return true; } if (!name.empty()) { auto it = property_triggers_.find(name); if (it == property_triggers_.end()) { return false; } const auto& trigger_value = it->second; if (trigger_value != "*" && trigger_value != value) { return false; } } for (const auto& [trigger_name, trigger_value] : property_triggers_) { if (trigger_name != name) { std::string prop_value = android::base::GetProperty(trigger_name, ""); if (trigger_value == "*" && !prop_value.empty()) { continue; } if (trigger_value != prop_value) return false; } } return true; } bool Action::CheckEvent(const EventTrigger& event_trigger) const { return event_trigger == event_trigger_ && CheckPropertyTriggers(); } bool Action::CheckEvent(const PropertyChange& property_change) const { const auto& [name, value] = property_change; return event_trigger_.empty() && CheckPropertyTriggers(name, value); } bool Action::CheckEvent(const BuiltinAction& builtin_action) const { return this == builtin_action; }然后把满足条件的Action加入到current_executing_actions_队列,然后按顺序执行该Action中的一个command,同时会记录这个Action,当前已经执行的命令数。
如果这个Action的所有command都被执行完了,则会从current_executing_actions_队列中移除,同时将当前已经执行的命令数清零,如果action的oneshot为true,action还会从ActionManager中移除。
如果是从rc文件解析的Action,Action的oneshot属性为false。
只有通过ActionManager::QueueBuiltinAction内建的Action,oneshot才会被设为true。