本篇博客主要结合Android 8.0的代码,回顾一下zygote进程的流程。
一、解析init.rc
在分析init进程时,我们知道init进程启动后,
会解析init.rc文件,然后创建和加载service字段指定的进程。
zygote进程就是以这种方式,被init进程加载的。
在system/core/rootdir/init.rc的开始部分,可以看到:
.............
//${ro.zygote}由厂商定义,与平台相关
import /init.${ro.zygote}.rc
.............
我们可以看出在不同的平台(32、64及64_32)上,init.rc将包含不同的zygote.rc文件。
在system/core/rootdir目录下,有init.zygote32_64.rc、init.zyote64.rc、
init.zyote32.rc、init.zygote64_32.rc。
不同的zygote.rc内容大致相同,主要区别体现在启动的是32位,还是64位的进程。
init.zygote32_64.rc和init.zygote64_32.rc会启动两个进程,且存在主次之分。
我们看看比较主流的init.zygote64.rc:
//启动的进程地址为/system/bin/app_process64
//参数为-Xzygote /system/bin --zygote --start-system-server
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc
//会创建一个zygote socket,便于指定权限
socket zygote stream 660 root system
//解析service时, 构造了onrestart action对应的一系列command
//当service被reap时,会执行onrestart对应的command
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进程的启动。
init进程启动的最后,会产生”late-init”事件。
对应于init.rc文件的内容类似于:
..........
on late-init
........
# Now we can start zygote for devices with file based encryption
trigger zygote-start
........
..........
进一步触发了zygote-start事件后,就会启动zygote进程了。
对应的init.rc文件类似于:
on zygote-start && property:ro.crypto.state=unencrypted
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
//start对应的映射关系定义于system/core/init/builtins.cpp中
//调用start对应的处理函数,启动名为zygote的服务
//即传入前文init.zygote.rc中定义的参数
start zygote
start zygote_secondary
关键字start对应的处理函数为do_start,
定义于builtins.cpp中:
static int do_start(const std::vector<std::string>& args) {
//找到zygote service对应信息
Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]);
if (!svc) {
LOG(ERROR) << "do_start: Service " << args[1] << " not found";
return -1;
}
//启动对应的进程
if (!svc->Start())
return -1;
return 0;
}
最后,我们来看看service.cpp中定义Start函数:
bool Service::Start() {
............
pid_t pid = -1;
if (namespace_flags_) {
pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
} else {
//从init进程中,fork出zygote进程
pid = fork();
}
if (pid == 0) {
..........
//当前fork的子进程替换为app_process
if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
}
.........
}
........
}
二、app_process的main函数
从init.zygote64.rc可以看出,zygote64启动文件的地址为app_process64。
app_process对应的代码定义在frameworks/base/cmds/app_process中,
我们来看看对应的Android.mk:
............
app_process_src_files := \
app_main.cpp \
............
LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
............
可以看出,无论平台的版本是什么,都是该目录对应的代码来处理。
接下来我们就看看app_process对应的main函数,
该函数定义于app_main.cpp中。
int main(int argc, char* const argv[])
{
//log相关代码
........
//AppRuntime定义于app_main.cpp中,继承自AndroidRuntime
//就是对Android运行环境的一种抽象,类似于java虚拟机对Java程序的作用
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
..........
int i;
//找到解析参数的起点
for (i = 0; i < argc; i++) {
......
}
// Parse runtime arguments. Stop at first unrecognized option.
// 从这里其实可以看出,通过app_main可以启动zygote、system-server及普通apk进程
// 这个可以通过init.rc来配置
bool zygote = false;
bool startSystemServer = false;
bool application =