目录
init 进程启动过程
init 进程是 Android 系统中用户空间的第一个进程,进程号为 1,是 Android 系统启动
流程中一个关键的步骤,作为第一个进程,它被赋予了很多极其重要的工作职责,比如创
Zygote (孵化器)和属性服务等。 init 程是由多个源文件共同组成的,这些文件位于
源码目录 system/core init 中。
引入 init 进程
为了讲解 init 进程,首先要了解
Android 系统启动流程的前几步,以引入 init 进程
启动电源以及系统启动
当电源按下时引导芯片代码从预定义的地方(固化在ROM )开始执行。加载引导程序BootLoader 到RAM中,然后执行
引导程序 Bootloader
引导程序 BootLoader 是在 Android 操作系统开始运行前的 个小程序,它的主要作用是把系统 OS 拉起来并运行
Linux 内核启动
当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。在内核完成系统设置后,它首先在系统文件中寻找 init.rc 文件,井启动 init 进程
init 进程启动
init 进程做的工作比较多 ,主要用来初始化和启动属性服务,也用来启动 Zygote 进程
init入口函数
init的入口函数为main,代码如下所示。
system/core/init/init.cpp
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv);
}
umask(0);
add_environment("PATH", _PATH_DEFPATH);
bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
//创建文件并挂载
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);
}
open_devnull_stdio();
klog_init();
klog_set_level(KLOG_NOTICE_LEVEL);
NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage");
if (!is_first_stage) {
// Indicate that booting is in progress to background fw loaders, etc.
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
//初始化属性相关资源
property_init();//1
process_kernel_dt();
process_kernel_cmdline();
export_kernel_boot_props();
}
...
//启动属性服务
start_property_service();//2
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>());
//解析init.rc配置文件
parser.ParseConfig("/init.rc");//3
...
while (true) {
if (!waiting_for_exec) {
am.ExecuteOneCommand();
restart_processes();
}
int timeout = -1;
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
if (am.HasMoreCommands()) {
timeout = 0;
}
bootchart_sample(&timeout);
epoll_event ev;
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
if (nr == -1) {
ERROR("epoll_wait failed: %s\n", strerror(errno));
} else if (nr == 1) {
((void (*)()) ev.data.ptr)();
}
}
return 0;
}
注释1处调用 property_init来对属性进行初始化
注释2处的 调用start_property_service启动属性服务,关于属性服务
注释3处parser.ParseConfig(“/init.rc”)用来解析init.rc,解析init.rc的文件为system/core/init/init_parse.cpp文件
init.rc
init.rc是一个配置文件,内部由Android初始化语言编写(Android Init Language)编写的脚本,它主要包含五种类型语句:
Action、Commands、Services、Options和Import
system/core/rootdir/init.rc
on init
sysclktz 0
# Mix device-specific information into the entropy pool
copy /proc/cmdline /dev/urandom
copy /default.prop /dev/urandom
...
on boot
# basic network init
ifup lo
hostname localhost
domainname localdomain
# set RLIMIT_NICE to allow priorities from 19 to -20
setrlimit 13 40 40
...
</