Zygote简单地说主要作用是两方面:
Android中大多数应用进程和系统进程都是通过Zygote进程来生成。Zygote为孵化的应用程序提供了几个基础资源:
Zygote由init进程解析init.rc脚本启动的。现在机器分为32位和64位,Zygote的启动也要区分对待:
/system/core/rootdir/init.rc
import /init.${ro.zygote}.rc
根据系统属性ro.zygote的具体值,加载不同的描述Zygote的rc脚本。譬如firely rk3399包含的文件: init.zygote32.rc init.zygote32_64.rc init.zygote64.rc init.zygote64_32.rc 其中zygote32和zygote64分别对应32位和64位机器。zygote32_64和zygote64_32则Primary Arch 和 Secondary Arch的组合,以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
从路径来看,Zygote所在的应用程序名称叫"app_process64",
可以简单地用下面这副图描述Zygote的启动
zygote创建.png
Zygote启动主要经历了两部分:
从Zygote的rc脚本我们知道, Zygote是通过app_process启动,入口就是app_process的main函数 frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
}
这里有3点,
简单来说,Zygote在native世界做的主要是以下几步:
Zygote的java世界入口是ZygoteInit 的main函数 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
zygoteServer.registerServerSocket(socketName);
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
preload(bootTimingsTraceLog); //预加载各类资源
} else {
Zygote.resetNicePriority();
}
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
caller = zygoteServer.runSelectLoop(abiList);
}
ZygoteInit的主函数主要完成几件事情:
Zygote是通过fork来创建新进程的,而binder是多线程的,有可能造成死锁。
在 POSIX 标准中,fork 的行为是这样的:复制整个用户空间的数据(通常使用 copy-on-write 的策略,所以可以实现的速度很快)以及所有系统对象, 然后仅复制当前线程到子进程。这里:所有父进程中别的线程,到了子进程中都是突然蒸发掉的。
假如父进程在获取到锁的情况下,fork了一个子进程。子进程的内存中,这个锁的状态是上锁状态。子进程仅运行了fork所在的这个线程,其它线程没有运行,当它尝试获取锁时,就发生了死锁
主要有两个好处:
所有应用进程都是从同一个进程fork出来的,这会有效地破坏地址空间布局随机化,这一技术是对抗代码注入攻击的重要安全手段
参考 网络课程 --剖析Framework面试 冲击Android高级职位 最强Android书架构大剖析 深入理解Android内核设计思想 https://blog.csdn.net/boygrass/article/details/27103383