事先宣告本文為作者本人記錄學習使用
其中部分文字或者技術觀點摘自https://blog.csdn.net/marshal_zsx/article/details/80600622 這里推薦此作者文章
main(int argc, char** argv) AOSP/system/core/rootdir/init.cpp
這三句代碼都是new一個Parser(決議器),然后將它們放到一個map里存起來 ServiceParser、ActionParser、ImportParser分別對應service action import的決議
parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sm));
parser.AddSectionParser("on", std::make_unique<ActionParser>(&am));
parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
...
parser.ParseConfig("/init.rc");
ParseConfig() AOSP/system/core/init/init_parser.cpp
判斷是檔案還是Dir或者是File 檔案呼叫ParseConfigFile
ParseConfigFile() AOSP/system/core/init/init_parser.cpp
取出資料呼叫 ParseData(path, data);
ParseData(path, data) AOSP/platform/system/core/init/init_parser.cpp
取出對應的parser 決議對應的Section
section_parser = section_parsers_[args[0]].get();
std::string ret_err;
if (!section_parser->ParseSection(std::move(args), filename, state.line, &ret_err)) {
LOG(ERROR) << filename << ": " << state.line << ": " << ret_err;
section_parser = nullptr;
}
三個parser 這里主要介紹serviceparser
Action AOSP/system/core/init/action.cpp
Service AOSP/system/core/init/service.cpp
ImportParser AOSP/system/core/init/import_parser.cpp
經過以上的決議,系統從各種.rc檔案中讀取了需要執行的Action和Service,但是還是需要一些額外的配置,也需要加入觸發條件準備去觸發
main(int argc, char** argv) AOSP/system/core/rootdir/init.cpp
QueueEventTrigger用于觸發Action,這里觸發 early-init事件
QueueBuiltinAction用于添加Action,第一個引數是Action要執行的Command,第二個是Trigger
...
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(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");
...
QueueEventTrigger() AOSP/system/core/init/action.cpp
它并沒有去觸發trigger,而是構造了一個EventTrigger物件,放到佇列中存起來
QueueBuiltinAction() AOSP/system/core/init/action.cpp
QueueBuiltinAction(BuiltinFunction func, const std::string& name)
這個函式有兩個引數,第一個引數是一個函式指標,第二引數是字串. 首先是創建一個Action物件,將第二引數作為Action觸發條件,將第一個引數作為Action觸發后的執行命令,并且又把第二個引數作為命令的引數,最后是將Action加入觸發佇列并加入Action串列
main(int argc, char** argv) AOSP/system/core/rootdir/init.cpp
觸發
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 || sm.IsWaitingForExec())) {
am.ExecuteOneCommand();
}
if (!(waiting_for_prop || sm.IsWaitingForExec())) {
if (!shutting_down) restart_processes();
ExecuteOneCommand() AOSP/system/core/init/action.cpp
執行一個command,在函式一開始就從trigger_queue_佇列中取出一個trigger,然后遍歷所有action,找出滿足trigger條件的action加入待執行串列current_executing_actions_中,接著從這個串列中取出一個action,執行它的第一個命令,并將命令所在下標自加1. 由于ExecuteOneCommand外部是一個無限回圈,因此按照上面的邏輯一遍遍執行,將按照trigger表的順序,依次執行滿足trigger條件的action,然后依次執行action中的命令.
restart_processes() AOSP/system/core/rootdir/init.cpp
主要是呼叫了 ForEachServiceWithFlags RestartIfNeeded
static void restart_processes()
{
process_needs_restart_at = 0;
ServiceManager::GetInstance().ForEachServiceWithFlags(SVC_RESTARTING, [](Service* s) {
s->RestartIfNeeded(&process_needs_restart_at);
});
}
ForEachServiceWithFlags() AOSP/system/core/rootdir/service.cpp
遍歷所有service,找出flags是SVC_RESTARTING的,執行func,也就是傳入的RestartIfNeeded
void ServiceManager::ForEachServiceWithFlags(unsigned matchflags,
void (*func)(Service* svc)) const {
for (const auto& s : services_) {
if (s->flags() & matchflags) {
func(s.get());
}
}
}
RestartIfNeeded() AOSP/system/core/rootdir/service.cpp
這個函式將主要作業交給了Start,也就是具體的啟動service,但是交給它之前做了一些判斷,也就是5秒內只能啟動一個服務,如果有多個服務,那么后續的服務將進入等待
void Service::RestartIfNeeded(time_t* process_needs_restart_at) {
boot_clock::time_point now = boot_clock::now();
boot_clock::time_point next_start = time_started_ + 5s;
if (now > next_start) {
flags_ &= (~SVC_RESTARTING);
Start();
return;
}
time_t next_start_time_t = time(nullptr) +
time_t(std::chrono::duration_cast<std::chrono::seconds>(next_start - now).count());
if (next_start_time_t < *process_needs_restart_at || *process_needs_restart_at == 0) {
*process_needs_restart_at = next_start_time_t;
}
}
Start() AOSP/system/core/rootdir/service.cpp
Start是具體去啟動服務了,它主要是呼叫clone或fork創建子行程,然后呼叫execve執行配置的二進制檔案,另外根據之前在.rc檔案中的配置,去執行這些配置
bool Service::Start() {
... //清空標記,根據service的配置初始化console、SELinux策略等
LOG(INFO) << "starting service '" << name_ << "'...";
pid_t pid = -1;
if (namespace_flags_) {//這個標記當service定義了namespace時會賦值為CLONE_NEWPID|CLONE_NEWNS
pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr); //以clone方式在新的namespace創建子行程
} else {
pid = fork();//以fork方式創建子行程
}
if (pid == 0) {//表示創建子行程成功
... //執行service配置的其他引數,比如setenv、writepid等
std::vector<char*> strs;
ExpandArgs(args_, &strs);//將args_決議一下,比如有${x.y},然后賦值表strs
if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) { //執行系統呼叫execve,也就是執行配置的二進制檔案,把引數傳進去
PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
}
_exit(127);
}
if (pid < 0) { //子行程創建失敗
PLOG(ERROR) << "failed to fork for '" << name_ << "'";
pid_ = 0;
return false;
}
... //執行service其他引數如oom_score_adjust_,改變service運行狀態等
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/280217.html
標籤:其他
