问题
在进入到 Android 启动过程之前先让我们思考以下几个问题 1. Android 系统的启动过程是怎样的? 2. init 、zygote 进程是什么?在系统启动的过程中各自发挥了什么作用? 3. AMS、PMS 等这些服务是如何被启动的? 4. Launcher 是如何被启动的?
此篇文章将针对 init 部分给出分析
启动流程简述
在了解 init 部分之前,首先简单介绍下系统的启动流程以便抓住主线,当我们通过电源键开启系统的时候,系统首先会加载 bootloader 程序到 RAM 中,然后通过 bootloader 将内核程序加载到 RAM 中,之后内核程序会创建init 进程,在 init 进程中会创建 zygote 进程,而 zygote 进程则会创建 DVM 并且启动 SystemServer 进程,通过SystemServer 系统会启动一系列的服务,包括常见的 AMS、PMS 等,最后再通过 AMS 进入到我们熟知的 Launcher 程序。 所以整个流程的关键点在于 init 进程如何创建 zygote、zygote 进程如何创建 SystemServer、SystemServer 进程如何启动 AMS、AMS 如何启动 Launcher。
init 启动流程分析
由于 bootloader 和内核不是关心的重点,所以这里只是简单介绍它们的作用。
加载运行 BootLoader
在电源上电之后,CPU 中的操作控制器将发出控制信号,将程序计数器(PC)的内容送至地址寄存器(AR),之后启动对主存的读操作,最终将 BootLoader 加载到 RAM 当中。然后 BootLoader 开始执行,主要负责硬件的初始化,将内核程序加载到内存。
init 进程的启动
内核启动之后将会初始化软硬件环境,加载驱动程序,挂载根文件系统,然后创建 init 进程,init 作为系统中的第一个用户进程,其进程号为 1,在创建 init 进程之时,系统会执行位于 system/core/init 下的 init.cpp 程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 int main (int argc, char ** argv) { ... if (is_first_stage) { mount ("tmpfs" , "/dev" , "tmpfs" , MS_NOSUID, "mode=0755" ); mkdir ("/dev/pts" , 0755 ); mkdir ("/dev/socket" , 0755 ); mount ("devpts" , "/dev/pts" , "devpts" , 0 , NULL ); #define MAKE_STR(x) __STRING(x) mount ("proc" , "/proc" , "proc" , 0 , "hidepid=2,gid=" MAKE_STR (AID_READPROC)); mount ("sysfs" , "/sys" , "sysfs" , 0 , NULL ); } ... signal_handler_init (); property_load_boot_defaults (); export_oem_lock_status (); start_property_service (); ... const BuiltinFunctionMap function_map; Action::set_function_map (&function_map); Parser& parser = Parser::GetInstance (); parser.AddSectionParser ("service" ,std::make_unique <ServiceParser>()); parser.AddSectionParser ("on" , std::make_unique <ActionParser>()); parser.AddSectionParser ("import" , std::make_unique <ImportParser>()); parser.ParseConfig ("/init.rc" ); ... return 0 ; }
可以看到 init 进程主要做了三件事情:创建用户空间文件夹并挂载、启动属性服务、解析位于 system文件夹下的 init.rc 文件 。 这里我们主要关注解析 init.rc 文件的过程,因为 zygote 进程就是在这个过程中创建的。
Android Init Language
由于 init.rc 是一个用 Android 初始化语言(AIL)编写的文件,为了更好的理解 rc 文件的解析过程需要了解一部分 AIL 语法。 AIL 主要有五种类型语句 Actions、Commands、Services、Options、Imports,在 AIL 中每个部分(语句块)表示为一个 Section,比如:
1 2 3 4 on boot ifup lo hostname localhost domainname localdomain
五种语句中只有 Actions、Services、Import 可以用于确定一个 Section。其中 Actions 由一系列 command 组成,Actions 拥有一个 trigger 用于确定何时执行这些命令。
1 2 3 4 5 6 7 8 on <trigger> <command> <command> <command> on early-init //触发器 early-init write /proc/1/oom_score_adj -1000 //command write /proc/sys/kernel/sysrq 0
Services 由一些 option 组成,其在初始化的时候启动,并可以在退出后重启(可选)。
1 2 3 4 5 6 7 8 service <name> <pathname> [ <argument> ]* //服务名、执行路径、参数 <option> <option> service ueventd /sbin/ueventd class core critical seclabel u:r:ueventd:s0
Services 定义了自身的服务名、执行路径以及执行时传入的参数,option 用于指定何时和怎样启动 service,关于何时启动这里进行一下说明,Actions 中有一条命令是 class_start <服务类别名> 用于启动所有未运行的相同类别的 service,而 option 可以通过 class <类别名> 对 service 的类别名进行指定。所以 service 的启动一般是通过 action 触发之后执行 class_start 命令进行启动的。 AIL 的介绍就到这了,如果想要详细了解请阅读 system/core/init 下的 readme.txt 文件 类别名>服务类别名>
init.rc 解析
system/core/rootdir/init.rc 现在接着分析 init.rc 文件,在文件的首部可以看到
1 2 3 4 5 import /init.environ.rcimport /init.usb.rcimport /init.${ro.hardware}.rcimport /init.usb.configfs.rcimport /init.${ro.zygote}.rc
在这里可以看到需要启动的 zygote,但是与其它引入的 rc 文件相比 zygote 部分并没有使用确定的值,而是使用 ${ro.zygote} 变量去替代,这是因为从 Android 在 5.0 以后开始支持 64 位程序,所以需要根据系统中 ro.zygote 属性的值动态引入。ro.zygote 的值可以通过 adb shell getprop 进行查询,我的手机查询结果是:
这说明手机会启动两个 zygote 进程,对应的执行程序分别是 app_process64 (主模式)、app_process32,通过 adb shell ps | grep zygote 可以看到确实存在两个 zygote 进程
接着查看与 init.rc 同一目录下的 init.zygote64_32.rc 文件 system/core/rootdir/init.zygote64_32.rc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote class main socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver onrestart restart media onrestart restart netd writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary class main socket zygote_secondary stream 660 root system onrestart restart zygote writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
前文说过 service 的启动和类别名相关,这里两个 zygote service 的类别名都是 main,所以要想知道 zygote 怎么被启动的我们可以在 init.rc 中搜索 class_start main,可以发现
1 2 3 4 5 on nonencrypted # A/B update verifier that marks a successful boot. exec - root -- /system/bin/update_verifier nonencrypted class_start main class_start late_start
从这里我们可以了解到当 nonencrypted 这个触发器被触发的时候 zygote 就会被启动,所以启动 zygote 的问题就转变为这个触发器什么时候执行?class_start 对应的处理函数是什么? 要想知道答案,必须回到 init.cpp 的解析过程当中
1 2 3 4 5 Parser& parser = Parser::GetInstance (); parser.AddSectionParser ("service" ,std::make_unique <ServiceParser>()); parser.AddSectionParser ("on" , std::make_unique <ActionParser>()); parser.AddSectionParser ("import" , std::make_unique <ImportParser>()); parser.ParseConfig ("/init.rc" );
init.rc 交由一个 Parser 对象进行解析,而 Parser 的实现在 system/core/init/init_parser.cpp 文件中,让我们进入到 init_parser.cpp 中查看 AddSectionParser 的实现
1 2 3 4 5 6 7 void Parser::AddSectionParser (const std::string& name, std::unique_ptr<SectionParser> parser) { section_parsers_[name] = std::move (parser); } std::map<std::string, std::unique_ptr<SectionParser>> section_parsers_;
可以看到每一个 parser 最终被保存在 section_parsers_ 中,section_parsers_ 是什么?查看 init_parser.h 中的定义可以知道,section_parsers_ 是一个 map 集合,所以 section_parsers_ 的作用是将 parser 与对应的 Section 进行绑定。 在添加完所有的 parser 之后就会调用 Parser 的 ParseConfig 方法
1 2 3 4 5 6 bool Parser::ParseConfig (const std::string& path) { if (is_dir (path.c_str ())) { return ParseConfigDir (path); } return ParseConfigFile (path); }
ParseConfig 中会对 path 进行判断,如果是目录则调用 ParseConfigDir 进行递归然后再通过 ParseConfigFile 进行解析。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 bool Parser::ParseConfigDir (const std::string& path) { INFO ("Parsing directory %s...\n" , path.c_str ()); std::unique_ptr<DIR, int (*) (DIR*) > config_dir (opendir(path.c_str()), closedir) ; if (!config_dir) { ERROR ("Could not import directory '%s'\n" , path.c_str ()); return false ; } dirent* current_file; while ((current_file = readdir (config_dir.get ()))) { std::string current_path = android::base::StringPrintf ("%s/%s" , path.c_str (), current_file->d_name); if (current_file->d_type == DT_REG) { if (!ParseConfigFile (current_path)) { ERROR ("could not import file '%s'\n" , current_path.c_str ()); } } } return true ; }
最终在 ParseConfigFile 中通过 ParseData 进行解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 bool Parser::ParseConfigFile (const std::string& path) { INFO ("Parsing file %s...\n" , path.c_str ()); Timer t; std::string data; if (!read_file (path.c_str (), &data)) { return false ; } data.push_back ('\n' ); ParseData (path, data); ... return true ; }
ParseData 解析过程如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 void Parser::ParseData (const std::string& filename, const std::string& data) { std::vector<char > data_copy (data.begin(), data.end()) ; data_copy.push_back ('\0' ); parse_state state; 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)) { case T_EOF: if (section_parser) { section_parser->EndSection (); } return ; case T_NEWLINE: state.line++; if (args.empty ()) { break ; } if (section_parsers_.count (args[0 ])) { if (section_parser) { section_parser->EndSection (); } 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 中通过调用 system/core/init/parser.cpp 中的 next_token 函数对 rc 内容进行分析,如果是 T_TEXT 则会保存在 args 中,如果是 T_NEWLINE 则会交由对应的解析器进行解析。init.rc 的大致解析过程如此,但是到这里我们依旧没能找到所需要的答案,所以需要继续查看 ActionParser 和 ServiceParser 的解析过程。
ActionParser 解析过程
ActionParser 位于 system/core/init/action.cpp 中,从前面的解析过程来看,最后的解析总是调用了对应 parser 的 ParseSection、ParseLineSection 以及 EndSection,所以我们主要看下这两个部分 ParseSection 的主要工作是创建 Action 对象,为对象添加触发器,并将 action_ 移动至当前 Action 对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 bool ActionParser::ParseSection (const std::vector<std::string>& args, std::string* err) { std::vector<std::string> triggers (args.begin() + 1 , args.end()) ; ... auto action = std::make_unique <Action>(false ); if (!action->InitTriggers (triggers, err)) { return false ; } action_ = std::move (action); return true ; } private : std::unique_ptr<Action> action_;
ParseLineSection 的主要工作为查找对应 command 的处理函数,将创建的 Command 对象添加到到commands_,由于 commands_ 是 Action 的一个域,所以实际上 ParseLineSection 在填充当前 Action 对象的域。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 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 ; } bool Action::AddCommand (const std::vector<std::string>& args, const std::string& filename, int line, std::string* err) { ... auto function = function_map_->FindFunction (args[0 ], args.size () - 1 , err); if (!function) { return false ; } AddCommand (function, args, filename, line); return true ; } void Action::AddCommand (BuiltinFunction f, const std::vector<std::string>& args, const std::string& filename, int line) { commands_.emplace_back (f, args, filename, line); } std::vector<Command> commands_; class Command {public : Command (BuiltinFunction f, const std::vector<std::string>& args, const std::string& filename, int line); int InvokeFunc () const ; std::string BuildCommandString () const ; std::string BuildSourceString () const ; private : BuiltinFunction func_; std::vector<std::string> args_; std::string filename_; int line_; };
EndSection 的主要工作是将解析完成的 action (域填充完毕的 Action 对象)添加到 ActionManager 的 acitons_ 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 void ActionParser::EndSection () { if (action_ && action_->NumCommands () > 0 ) { ActionManager::GetInstance ().AddAction (std::move (action_)); } } void ActionManager::AddAction (std::unique_ptr<Action> action) { ... if (old_action_it != actions_.end ()) { (*old_action_it)->CombineAction (*action); } else { actions_.emplace_back (std::move (action)); } } class ActionManager {public : static ActionManager& GetInstance () ; void AddAction (std::unique_ptr<Action> action) ; void QueueEventTrigger (const std::string& trigger) ; void QueuePropertyTrigger (const std::string& name, const std::string& value) ; void QueueAllPropertyTriggers () ; void QueueBuiltinAction (BuiltinFunction func, const std::string& name) ; void ExecuteOneCommand () ; bool HasMoreCommands () const ; void DumpState () const ; private : ActionManager (); ActionManager (ActionManager const &) = delete ; void operator =(ActionManager const &) = delete ; std::vector<std::unique_ptr<Action>> actions_; std::queue<std::unique_ptr<Trigger>> trigger_queue_; std::queue<const Action*> current_executing_actions_; std::size_t current_command_; };
通过以上分析我们能够知道 class_start 的处理函数和 function_map_ 相关,查看 function_map_ 在 action.h 中的定义可以看到
1 2 3 4 5 static const KeywordMap<BuiltinFunction>* function_map_;static void set_function_map (const KeywordMap<BuiltinFunction>* function_map) { function_map_ = function_map; }
所以要想知道处理函数是什么只需要知道 set_function_map 在哪里调用?让我们再次回到 init.cpp 中,可以看到
1 2 const BuiltinFunctionMap function_map;Action::set_function_map (&function_map);
接下来需要找到 BuiltinFunctionMap,BuiltinFunctionMap 的实现我们可以在 builtins.cpp 中找到,其具体的实现 system/core/init/builtins.cpp
1 2 3 4 5 6 7 8 9 10 BuiltinFunctionMap::Map& BuiltinFunctionMap::map () const { constexpr std::size_t kMax = std::numeric_limits<std::size_t >::max (); static const Map builtin_functions = { ... {"class_start" , {1 , 1 , do_class_start}}, {"class_stop" , {1 , 1 , do_class_stop}}, ... }; return builtin_functions; }
到这里就可以确定 class_start 对应的处理函数是 do_class_start,do_class_start 也可在 builtins.cpp 中找到。 简单总结下解析 Action 的过程,实际上是创建一个 Action 对象,然后为 Action 对象添加 Trigger 以及对应的 Command,其中在添加 Command 的过程中还为 Command 指定了处理函数,最后在将 Action 对象增加到 ActionManager vector 类型的 actions_ 链表当中去。
ServiceParser 解析过程
与前文一致,接着看那三个函数 ParseSection 的主要工作是创建 Service 对象,将 service_ 移动至当前 Service 对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 bool ServiceParser::ParseSection (const std::vector<std::string>& args, std::string* err) { ... const std::string& name = args[1 ]; ... std::vector<std::string> str_args (args.begin() + 2 , args.end()) ; service_ = std::make_unique <Service>(name, "default" , str_args); return true ; } std::unique_ptr<Service> service_;
ParseLineSection 的主要工作是为 Service 中每个 option 指定处理函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 bool ServiceParser::ParseLineSection (const std::vector<std::string>& args, const std::string& filename, int line, std::string* err) const { return service_ ? service_->HandleLine (args, err) : false ; } bool Service::HandleLine (const std::vector<std::string>& args, std::string* err) { ... static const OptionHandlerMap handler_map; auto handler = handler_map.FindFunction (args[0 ], args.size () - 1 , err); ... return (this ->*handler)(args, err); }
EndSection 的主要工作是将解析完成的 service (域填充完毕的 Service 对象)添加到 ServiceManager 的 services_ 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 void ServiceParser::EndSection() { if (service_) { ServiceManager::GetInstance().AddService(std::move(service_)); } } void ServiceManager::AddService(std::unique_ptr<Service> service) { Service* old_service = FindServiceByName(service->name()); if (old_service) { ERROR("ignored duplicate definition of service '%s'" , service->name().c_str()); return ; } services_.emplace_back(std::move(service)); } class ServiceManager {public : static ServiceManager& GetInstance(); void AddService (std::unique_ptr<Service> service) ; Service* MakeExecOneshotService(const std::vector<std::string>& args); Service* FindServiceByName(const std::string& name) const; Service* FindServiceByPid(pid_t pid) const; Service* FindServiceByKeychord(int keychord_id) const; void ForEachService (std::function<void (Service*) > callback) const; void ForEachServiceInClass (const std::string& classname, void (*func) (Service* svc) ) const; void ForEachServiceWithFlags (unsigned matchflags, void (*func) (Service* svc) ) const; void ReapAnyOutstandingChildren () ; void RemoveService (const Service& svc) ; void DumpState () const; private : ServiceManager(); bool ReapOneProcess () ; static int exec_count_; std::vector<std::unique_ptr<Service>> services_; };
对应的可以看下 option 的处理函数,虽然 OptionHandlerMap 与启动 zygote 无关,但是还是看下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map () const { constexpr std::size_t kMax = std::numeric_limits<std::size_t >::max (); static const Map option_handlers = { {"class" , {1 , 1 , &Service::HandleClass}}, {"console" , {0 , 0 , &Service::HandleConsole}}, {"critical" , {0 , 0 , &Service::HandleCritical}}, {"disabled" , {0 , 0 , &Service::HandleDisabled}}, {"group" , {1 , NR_SVC_SUPP_GIDS + 1 , &Service::HandleGroup}}, {"ioprio" , {2 , 2 , &Service::HandleIoprio}}, {"keycodes" , {1 , kMax, &Service::HandleKeycodes}}, {"oneshot" , {0 , 0 , &Service::HandleOneshot}}, {"onrestart" , {1 , kMax, &Service::HandleOnrestart}}, {"seclabel" , {1 , 1 , &Service::HandleSeclabel}}, {"setenv" , {2 , 2 , &Service::HandleSetenv}}, {"socket" , {3 , 6 , &Service::HandleSocket}}, {"user" , {1 , 1 , &Service::HandleUser}}, {"writepid" , {1 , kMax, &Service::HandleWritepid}}, }; return option_handlers; }
与解析 Action 类似,在整个过程中先创建 Service 对象,解析出 Service 的名字和对应的参数添加到对象当中,并且给每个 Option 指定了相应的处理函数 到这里 rc 文件的解析就结束了,通过 rc 文件的解析使得每个 action 都有了对应的执行函数,所以接下来的问题是这些 action 是如何被触发的(也即是 command 命令是如何被执行的)?
Actions 的触发
让我们继续回到 init.cpp 中
1 2 3 4 5 6 7 8 9 10 ActionManager& am = ActionManager::GetInstance (); .... while (true ) { if (!waiting_for_exec) { am.ExecuteOneCommand (); restart_processes (); } ... }
可以看到 action 的 command 的执行是通过 ActionManager 的 ExecuteOneCommand 函数,而ActionManager 的 ExecuteOneCommand 最终调用了 Action 的 ExecuteOneCommand system/core/init/action.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 void ActionManager::ExecuteOneCommand () { while (current_executing_actions_.empty () && !trigger_queue_.empty ()) { for (const auto & action : actions_) { if (trigger_queue_.front ()->CheckTriggers (*action)) { current_executing_actions_.emplace (action.get ()); } } trigger_queue_.pop (); } ... auto action = current_executing_actions_.front (); if (current_command_ == 0 ) { std::string trigger_name = action->BuildTriggersString (); INFO ("processing action (%s)\n" , trigger_name.c_str ()); } action->ExecuteOneCommand (current_command_); ++current_command_; ... } void Action::ExecuteOneCommand (std::size_t command) const { ExecuteCommand (commands_[command]); } void Action::ExecuteCommand (const Command& command) const { Timer t; int result = command.InvokeFunc (); ... }
通过上述分析可以知道,init 进程最终进入到无限循环中,然后按照 ActionManager 中 actions_ 保存的 action 顺序依次对每个 Action 进行处理,而在这个过程中 system/core/init/builtins.cpp 下用于启动 zygote 的 do_class_start 函数将会被执行
1 2 3 4 5 static int do_class_start (const std::vector<std::string>& args) { ServiceManager::GetInstance (). ForEachServiceInClass (args[1 ], [] (Service* s) { s->StartIfNotDisabled (); }); return 0 ; }
do_class_start 函数中调用 Service 的 StartIfNotDisabled,StartIfNotDisabled 在 service.cpp 的实现如下
1 2 3 4 5 6 7 8 bool Service::StartIfNotDisabled () { if (!(flags_ & SVC_DISABLED)) { return Start (); } else { flags_ |= SVC_DISABLED_START; } return true ; }
StartIfNotDisabled 最终调用了 Service 的 Start 函数,Start 函数创建了 zygote 的进程,并且执行了 init.zygote64_32.rc 中定义的执行路径下的文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 bool Service::Start () { .... pid_t pid = fork(); if (pid == 0 ) { ... if (execve (args_[0 ].c_str (), (char **) &strs[0 ], (char **) ENV) < 0 ) { ERROR ("cannot execve('%s'): %s\n" , args_[0 ].c_str (), strerror (errno)); } _exit(127 ); } .... return true ; }
在完成这一切之后将会进入 frameworks/base/cmds/app_process/app_main.cpp 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int main (int argc, char * const argv[]) { .... if (zygote) { runtime.start ("com.android.internal.os.ZygoteInit" , args, zygote); } else if (className) { runtime.start ("com.android.internal.os.RuntimeInit" , args, zygote); } else { fprintf (stderr, "Error: no class name or --zygote supplied.\n" ); app_usage (); LOG_ALWAYS_FATAL ("app_process: no class name or --zygote supplied." ); return 10 ; } }
可以看到 zygote 最终在 app_main 的 main 函数中被启动。
总结
到这里我们就能够回答对 init 部分相关的问题了 1. init 的作用 init 是系统中的第一个用户进程,它的主要作用是创建用户空间文件夹并挂载、启动属性服务、解析 init.rc 文件并启动 zygote 进程 。 2. init 启动 zygote 的过程 init 进程通过解析 init.rc 文件将 action 保存在 ActionManager 的 actions_ 链表中,然后通过遍历 actions_ 链表,执行 action 命令对应的处理函数,从而转至 builtins.cpp 的 do_class_start 函数,之后通过 Service 的 StartIfNotDisabled 调用 Service 的 Start 函数,最终通过 Start 函数创建 zygote 进程,执行对应的 app_main.cpp 文件启动 zygote。
Thanks
Android7.0 init进程源码分析
Android Init Language(android初始化语言)
Android系统启动流程(一)解析init进程启动过程