Android 8.0系统启动流程_init(一)

发布时间:2026/7/28 14:38:59
Android 8.0系统启动流程_init(一) 本系列主要介绍Android8.0系统启动过程中涉及到的init、Zygote、SystemServer和Launcher。init启动前准备init函数分析init函数解析init启动Zygote一、init启动前准备init进程是Android系统的第一个进程其进程号为1该进程启动后主要处理一些重要的初始化工作比如创建Zygote和各种属性服务。在电源按键按下后经历如下几个步骤后便开始引入init进程1. 启动电源及系统电源按下后引导芯片开始将固化在ROM中的BootLoader加载至RAM中并执行该程序2. 引导程序BootLoader引导程序BootLoader是在Android操作系统开始运行前执行的一个小程序其主要作用是把系统OS拉起来并运行3. Linux内核启动内核启动时设置缓存、被保护存储器、计划列表和加载驱动等完成设置后开始加载init.rc文件4. init进程启动开始初始化和启动属性服务创建Zygote进程。二、 init函数分析在Linux内核加载完成后开始查找init.rc文件并启动init进程其主要代码如下system/core/init/init.cppint main(int argc, char** argv) { ... if (is_first_stage) { boot_clock::time_point start_time boot_clock::now(); // 清理 umask. umask(0); // 创建和挂载所需的文件 mount(tmpfs, /dev, tmpfs, MS_NOSUID, mode0755); 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, hidepid2,gid MAKE_STR(AID_READPROC)); // Dont expose the raw commandline to unprivileged processes. chmod(/proc/cmdline, 0440); gid_t groups[] { AID_READPROC }; setgroups(arraysize(groups), groups); mount(sysfs, /sys, sysfs, 0, NULL); mount(selinuxfs, /sys/fs/selinux, selinuxfs, 0, NULL); mknod(/dev/kmsg, S_IFCHR | 0600, makedev(1, 11)); mknod(/dev/random, S_IFCHR | 0666, makedev(1, 8)); mknod(/dev/urandom, S_IFCHR | 0666, makedev(1, 9)); // 初始化Kernel日志 InitKernelLogging(argv); ... } ... //属性服务初始化 property_init(); ... //创建epoll句柄 epoll_fd epoll_create1(EPOLL_CLOEXEC); ... //设置子进程的处理函数 signal_handler_init(); //导入默认的环境变量 property_load_boot_defaults(); export_oem_lock_status(); //启动属性服务 start_property_service(); set_usb_controller(); ... if (bootscript.empty()) { //解析init.rc文件 parser.ParseConfig(/init.rc); parser.set_is_system_etc_init_loaded( parser.ParseConfig(/system/etc/init)); 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); } ... return 0; }该流程分析如下1. 挂载文件通过设置umask值屏蔽一些权限后开始挂载和创建所需的文件2. 属性服务通过property_init()属性服务初始化调用start_property_service()启动属性服务3. 子进程的处理函数 signal_handler_init()主要作用是防止出现僵尸进程子进程在暂停和终止后会发出SIGCHLD的信号signal_handler_init()接收到该信号后会对该进程进行回收处理防止占用系统进程资源4. 解析init.rc配置在8.0中对init.rc文件进行了拆分可查看system\core\rootdir目录包括init.zygote32.rcZygote对应的执行程序是app_process(纯32位模式)init.zygote64.rcZygote对应的执行程序是app_process64(纯64位模式)init.zygote32_64.rc启动两个Zygote进程( zygote 和 zygote_secondary)对应的执行程序是app_process32(主模式)和app_process64init.zygote64_32.rc启动两个Zygote进程( zygote 和 zygote_secondary)对应的执行程序是app_process64(主模式)和app_process32。三、 init函数解析\system\core\rootdir\init.rcinit.rc配置文件是由Android初始化语言Android Init Language编写的脚本主要包括5种语言类型Action、Command、Service、Option和Import。同时需要注意init.rc仅仅是配置文件类似于xml没有解析的顺序而言(不是自上而下运行)是通过程序调用获取相应的配置信息真正加载运行的程序是在上部分提到的init.cpp文件。import指令是用于类似于java语言主要用于扩展配置格式如下import filename一个init配置文件扩展当前配置filename一般是init.XXX.rc的形式源码中例如import /init.environ.rcAction一系列命令的开始其格式如下on trgger [ trigger]* command1 command2 command3 ...每个Action都至少有一个触发器(trgger)该触发器决定何时执行该Action即后面的command…指令其要通过ActionParser解析其实现代码在\system\core\init\action.cpp其格式如下# Indicate to fw loaders that the relevant mounts are up. on firmware_mounts_complete rm /dev/.bootingService:以service开头由init进程启动的一般运行于init的子进程中在启动该service前需要判断对应的可执行文件是否存在并通过fork方式生成子进程。其主要通过ServiceParser解析其实现代码在\system\core\init\service.cpp其格式如下service name pathname [ argument ]* option option ...其中name服务的名称pathname:当前服务对应程序的位置option当前服务设置的选项argument可选参数。例如service ueventd /sbin/ueventd class core critical seclabel u:r:ueventd:s0 shutdown critical四 、init启动Zygote\system\core\rootdir\init.rc\system\core\init\init.cpp\system\core\init\builtins.cpp\ frameworks\base\cmds\app_process\app_main.cpp在init.rc中关于Zygote的启动在如下部分\system\core\rootdir\init.rcon nonencrypted class_start main class_start late_start其中 main指的就是Zygote的服务名称其中class_start函数是指builtins.cpp中的函数\system\core\init\builtins.cppstatic int do_class_start(const std::vectorstd::string args) { ServiceManager::GetInstance(). ForEachServiceInClass(args[1], [] (Service* s) { s-StartIfNotDisabled(); }); return 0; }其中ForEachServiceInClass函数会遍历Service链表查找classname为main的Zygote并执行service.cpp中的StartIfNotDisabled函数如下所示\system\core\init\service.cppbool Service::StartIfNotDisabled() { if (!(flags_ SVC_DISABLED)) { return Start(); } else { flags_ | SVC_DISABLED_START; } return true; }如果该service没有在其对应的rc文件中设置disable选项则会执行Start()方法启动该Service在init.zygote64.rc中没有设置disable选项因此可以正常启动该Service。\system\core\init\builtins.cppbool Service::Start() { .. //是否正在运行 if (flags_ SVC_RUNNING) { return false; } ... //启动的路径是否存在 struct stat sb; if (stat(args_[0].c_str(), sb) -1) { PLOG(ERROR) cannot find args_[0] , disabling name_ ; flags_ | SVC_DISABLED; return false; } std::string scon; if (!seclabel_.empty()) { scon seclabel_; } else { scon ComputeContextFromExecutable(name_, args_[0]); if (scon ) { return false; } } //如果该进程未启动调用fork启动该进程 pid_t pid -1; if (namespace_flags_) { pid clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr); } else { pid fork(); } if (pid 0) { umask(077); ... } if (pid 0) { PLOG(ERROR) failed to fork for name_ ; pid_ 0; return false; } .... //启动该进程 SetProcessAttributes(); if (!ExpandArgsAndExecve(args_)) { PLOG(ERROR) cannot execve( args_[0] ); } _exit(127); NotifyStateChange(running); return true; }其主要流程如下是否正在运行如正在运行直接返回子进程是否启动如未启动调用fork并返回pid值如果以上正常则调用ExpandArgsAndExecve启动该进程完成Zygote的启动。启动Zygote进程真正执行的路径为frameworks\base\cmds\app_process\app_main.cpp下的main函数如下所示\ frameworks\base\cmds\app_process\app_main.cpp int main(int argc, char* const argv[]) { ... if (zygote) { runtime.start(com.android.internal.os.ZygoteInit, args, zygote);//启动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.); } ... }