android源碼學(xué)習(xí)目錄
1.init.rc的解析
從文章android init進(jìn)程可以看出纵朋,init.rc的解析是從init進(jìn)程main函數(shù)中進(jìn)行的潘懊。
//android 8.0
//init進(jìn)程main函數(shù)解析init.rc代碼飘哨。
//Parser init.rc文件的解析入口 /system/core/init/init_parse.cpp
Parser& parser = Parser::GetInstance();
// 1 為解析類添加解析能力
parser.AddSectionParser("service",std::make_unique<ServiceParser>());
parser.AddSectionParser("on", std::make_unique<ActionParser>());
parser.AddSectionParser("import", std::make_unique<ImportParser>());
std::string bootscript = GetProperty("ro.boot.init_rc", ""); //2 環(huán)境變量里是否有ro.boot.init_rc
if (bootscript.empty()) {
parser.ParseConfig("/init.rc"); //3 解析
parser.set_is_system_etc_init_loaded(
parser.ParseConfig("/system/etc/init")); //解析system/etc/init文件夾下左右的rc文件侧戴。
parser.set_is_vendor_etc_init_loaded(
parser.ParseConfig("/vendor/etc/init"));
parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
} else {
parser.ParseConfig(bootscript);
parser.set_is_system_etc_init_loaded(true);
parser.set_is_vendor_etc_init_loaded(true);
parser.set_is_odm_etc_init_loaded(true);
}
這是Android init進(jìn)程解析init.rc文件的代碼,
- Parser是init.rc類文件解析的入口,parser.AddSectionParser()函數(shù)是為了添加init.rc類文件解析的能力,會(huì)根據(jù)init.rc文件每一行的內(nèi)容選擇不同的處理器eg:ActionParser,
- 代碼2處是判斷是否有啟動(dòng)配置腳本,按照是否有來進(jìn)行解析呢堰,一般都是系統(tǒng)默認(rèn)的,沒有啟動(dòng)配置腳本使用Android系統(tǒng)的init.rc進(jìn)行解析脑又,解析在代碼3處暮胧,ParseConfig函數(shù)就是解析函數(shù)
//代碼位置 /system/core/init/init_parse.cpp
bool Parser::ParseConfig(const std::string& path) {
if (is_dir(path.c_str())) {
return ParseConfigDir(path);
}
return ParseConfigFile(path); //進(jìn)行文件解析锐借,解析的是init.rc
}
bool Parser::ParseConfigFile(const std::string& path) {
LOG(INFO) << "Parsing file " << path << "...";
Timer t;
std::string data;
if (!read_file(path, &data)) { //將文件內(nèi)容讀取到data里,
return false;
}
data.push_back('\n'); // TODO: fix parse_config.
ParseData(path, data); //內(nèi)容解析函數(shù)往衷,分派給各個(gè)解析類eg:ActionParse
for (const auto& sp : section_parsers_) {
sp.second->EndFile(path);
}
LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";
return true;
}
void Parser::ParseData(const std::string& filename, const std::string& data) {
//TODO: Use a parser with const input and remove this copy
std::vector<char> data_copy(data.begin(), data.end());
data_copy.push_back('\0');
parse_state state; //解析過程使用的結(jié)構(gòu)體,/system/core/init/parse.h parse.cpp
state.filename = filename.c_str();
state.line = 0;
state.ptr = &data_copy[0];
state.nexttoken = 0;
SectionParser* section_parser = nullptr;
std::vector<std::string> args;
for (;;) {
switch (next_token(&state)) {// 更具next_token讀取state里的內(nèi)容
case T_EOF:
if (section_parser) {
section_parser->EndSection(); //結(jié)束一個(gè)文件的分析钞翔,
}
return;
case T_NEWLINE: //分析每一行的命令
state.line++;
if (args.empty()) {
break;
}
if (section_parsers_.count(args[0])) {
if (section_parser) {
section_parser->EndSection();
}
//根據(jù)args[0]也就是每個(gè)init.rc執(zhí)行邏輯的第一個(gè)參數(shù),選取解析的類席舍,選我們之前添加的ActionParse等
section_parser = section_parsers_[args[0]].get();
std::string ret_err;
if (!section_parser->ParseSection(args, &ret_err)) {
parse_error(&state, "%s\n", ret_err.c_str());
section_parser = nullptr;
}
} else if (section_parser) {
std::string ret_err;
if (!section_parser->ParseLineSection(args, state.filename,
state.line, &ret_err)) { //解析一行
parse_error(&state, "%s\n", ret_err.c_str());
}
}
args.clear();
break;
case T_TEXT:
args.emplace_back(state.text);
break;
}
}
}
從上面代碼可以看出parseData函數(shù)對(duì)init.rc進(jìn)行了讀取與處理布轿,它根據(jù)讀取的內(nèi)容的每個(gè)模塊(eg:Action是on)選擇解析需要的Parse,后對(duì)init.rc中每個(gè)模塊的每一行進(jìn)行了解析。
1.1:實(shí)際解析類的分析
位置/system/core/init/action.cpp ActionParse
//負(fù)責(zé)根據(jù)讀取的args来颤,生成代碼類中的action
bool ActionParser::ParseSection(const std::vector<std::string>& args,
std::string* err) {
std::vector<std::string> triggers(args.begin() + 1, args.end());
if (triggers.size() < 1) {
*err = "actions must have a trigger";
return false;
}
auto action = std::make_unique<Action>(false);
if (!action->InitTriggers(triggers, err)) {
return false;
}
action_ = std::move(action);
return true;
}
//解析一行指令汰扭,將command加入到它所屬于的action
bool ActionParser::ParseLineSection(const std::vector<std::string>& args,
const std::string& filename, int line,
std::string* err) const {
return action_ ? action_->AddCommand(args, filename, line, err) : false;
}
//一個(gè)action解析結(jié)束,將解析的action添加到ActionManager中福铅。
void ActionParser::EndSection() {
if (action_ && action_->NumCommands() > 0) {
ActionManager::GetInstance().AddAction(std::move(action_));
}
}
上述代碼是構(gòu)建action和保存action的處理萝毛,到這里init.rc的一個(gè)action就解析完了。ActionManager是所有action的管理類滑黔,所有解析的action都使用一個(gè) std::vector<std::unique_ptr<Action>> actions_ 集合保存下來笆包。
2.Action的執(zhí)行。
//1 執(zhí)行action與函數(shù)綁定 /system/core/init/builtins.cpp
const BuiltinFunctionMap function_map;
Action::set_function_map(&function_map);
....
//2 這里就是上文對(duì)action解析之后形成的ActionManager類略荡,
ActionManager& am = ActionManager::GetInstance();
//執(zhí)行early-init的action
am.QueueEventTrigger("early-init");
//查詢手寫action是否已執(zhí)行
// 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(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict");
am.QueueBuiltinAction(keychord_init_action, "keychord_init");
am.QueueBuiltinAction(console_init_action, "console_init");
// Trigger all the boot actions to get us started.
//執(zhí)行action init
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(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
// Don't mount filesystems or start core system services in charger mode.
std::string bootmode = GetProperty("ro.bootmode", ""); //查詢現(xiàn)在啟動(dòng)的模式
if (bootmode == "charger") {
am.QueueEventTrigger("charger"); //在充電執(zhí)行action charger
} else {
am.QueueEventTrigger("late-init"); //沒有充電執(zhí)行action late-init
}
// Run all property triggers based on current state of the properties.
am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
while (true) { //開始循環(huán)庵佣,執(zhí)行actionManager中的每個(gè)action
// By default, sleep until something happens.
int epoll_timeout_ms = -1;
if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
am.ExecuteOneCommand(); // 執(zhí)行action的command
}
if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
restart_processes(); //.rc文件中的service, 與actionManager類似由ServiceManager管理。
// If there's a process that needs restarting, wake up in time for that.
if (process_needs_restart_at != 0) {
epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;
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)(); //3
}
}
- 注釋1處action與執(zhí)行函數(shù)進(jìn)行綁定汛兜,就是執(zhí)行那個(gè)action就執(zhí)行那個(gè)函數(shù)巴粪,函數(shù)內(nèi)容是在/system/core/init/builtins.cpp文件中。
- 在就是執(zhí)行action粥谬,和循環(huán)遍歷執(zhí)行全部的action肛根,
- 代碼3處用是用了epoll句柄(即epoll_fd)主要監(jiān)聽子進(jìn)程結(jié)束,及其它進(jìn)程設(shè)置系統(tǒng)屬性的請(qǐng)求.這里會(huì)處理action啟動(dòng)的進(jìn)程如果死了會(huì)收到進(jìn)程終止信號(hào)量帝嗡,在進(jìn)行重啟進(jìn)程晶通。了解android init進(jìn)程