在简单易懂(一)之Android系统启动流程中,我们知道了init进程启动后,会去解析init.rc配置文件,然后会去启动zygote进程。这篇文章我们就来简单分析下init.rc文件是如何被解析并启动zygote的。
以下分析的源码版本号:Android 8.0
1、init进程入口函数
在内核加载完成后,会去启动init进程,我们来看下init进程的入口函数main,代码如下:
//代码文件位置:system/core/init/init.cpp
int main(int argc, char** argv) {
*****省略部分代码*****
if (bootscript.empty()) {
parser.ParseConfig("/init.rc");
*****省略部分代码*****
}
*****省略部分代码*****
}
可以看到在init进程中,有一句parser.ParseConfig(“/init.rc”),它就是用来解析init.rc文件的。
2、解析init.rc文件
需要提前知道的是,在Android8.0中,对init.rc文件进行了拆分,每个服务都有一个对应的rc文件。我们要分析的zygote启动脚本在init.zygoteXX.rc中定义,以64位处理器为例,我们要找的就是init.zygote64.rc文件:
//代码文件位置:system/core/rootdir/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc
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
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
init.rc文件,它是由Android初始化语言(Android Init Language)编写的脚本,这种语言主要包含5种类型语句Action、Command、Service、Option和Import。我们这里只讲下Service类型语句:
//name:指service的名字 pathname:指执行程序的路径 argument:指传递的参数
service <name> <pathname> [ <argument> ]
//option 是 service的修饰词,用来表示什么时候、如何启动Service
<option>
理解完Service类型语句后,回来重新看init.zygote64.rc的内容。根据Service类型语句的格式,我们可以知道Service通知了init进程去创建一个名为zygote的进程,并且这个zygote进程它执行代码程序的路径是/system/bin/app_process64,后面剩下的-Xzygote /system/bin --zygote --start-system-server是传给app_process64的参数。
我们找到app_process64执行程序所对应的源文件是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);
} 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.");
}
}
从上面代码得知,主要是调用了runtime的start函数去启动Zygote。
OK,看到这后,对于init进程是如何启动zygote进程的,我们应该有了一个大概的理解。但是这个启动过程远没有这么简单,涉及到源码很多而且复杂,下一篇文章我们去详解zygote启动过程。