前言
本系列主要介绍Android8.0系统启动过程中涉及到的init、Zygote、SystemServer和Launcher。
一、init启动前准备
init进程是Android系统的第一个进程,其进程号为1,该进程启动后,主要处理一些重要的初始化工作,比如创建Zygote和各种属性服务。在电源按键按下后,经历如下几个步骤后,便开始引入init进程:
- 启动电源及系统:电源按下后,引导芯片开始将固化在ROM中的BootLoader加载至RAM中,并执行该程序;
- 引导程序BootLoader:引导程序BootLoader是在Android操作系统开始运行前,执行的一个小程序,其主要作用是把系统OS拉起来并运行;
- Linux内核启动:内核启动时,设置缓存、被保护存储器、计划列表和加载驱动等,完成设置后,它首先在系统文件中寻找init.rc文件,并启动init进程
- init进程启动:init进程做的工作比较多,主要是用来初始化和启动属性服务,也用来启动Zygote进程。
二、init进程的入口函数
在Linux内核加载完成后,开始查找init.rc文件,并启动init进程,其主要代码如下:
int main(int argc, char** argv) {
...
bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
if (is_first_stage) {
boot_clock::time_point start_time = boot_clock::now();
umask(0);
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));
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));
InitKernelLogging(argv);
...
}
...
property_init();
...
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()) {
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);
}
...
while (true) {
int epoll_timeout_ms = -1;
if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
am.ExecuteOneCommand();
}
if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
restart_processes();
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 (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)();
}
}
return 0;
}
该流程分析如下:
- 挂载文件:通过设置umask值,屏蔽一些权限后,开始挂载和创建所需的文件;
- 属性服务:通过property_init()属性服务初始化,调用start_property_service()启动属性服务;
- 子进程的处理函数: signal_handler_init()主要作用是防止出现僵尸进程,子进程在暂停和终止后,会发出SIGCHLD的信号,signal_handler_init()接收到该信号后,会对该进程进行回收处理,防止占用系统进程资源;
- 解析init.rc配置:在8.0中对init.rc文件进行了拆分,可查看system\core\rootdir目录,包括:
init.zygote32.rc:Zygote对应的执行程序是app_process(纯32位模式); init.zygote64.rc:Zygote对应的执行程序是app_process64(纯64位模式); init.zygote32_64.rc:启动两个Zygote进程( zygote 和 zygote_secondary),对应的执行程序是app_process32(主模式)和app_process64; init.zygote64_32.rc:启动两个Zygote进程( zygote 和 zygote_secondary),对应的执行程序是app_process64(主模式)和app_process32。
三、init函数解析
/system/core/rootdir/init.rc
init.rc是一个非常重要的配置文件,它是由Android初始化语言(Android Init Language)编写的脚本,这种语言主要包含5种类型语句:Action、Command、Service、Option和Import。init.rc的配置代码如下所示:
|