前言
前面分析了init流程的启动,在解析init.rc配置文件中,会执行start zygote,然后会去解析相关的init.zygote.rc文件,在init.rc文件的顶部的import可以看出,由于操作系统的兼容性,有纯32位,纯64位,也有兼容模式的64_32,这样会产生两个zygote进程,分别用于去fork不同位数的用户应用。
接下来就开始分析zygote进程的流程,以64_32位的zygote为例子分析
//#init.zygote64_32.rc
/***
* 进程名称是 zygote
* 运行的二进制文件在 /system/bin/app_process64
* 启动参数是 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
**/
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system //创建一个 socket,名字叫zygote
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
onrestart write /sys/power/state on //onrestart 指当前进程重启时执行后面的命令
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
task_profiles ProcessCapacityHigh MaxPerformance
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
class main
priority -20
user root
group root readproc reserved_disk
socket zygote_secondary stream 660 root system
socket usap_pool_secondary stream 660 root system
onrestart restart zygote
task_profiles ProcessCapacityHigh MaxPerformance
通过对应Android.bp文件可知道,zygote进程的启动,会进入到app_main.cpp代码,执行对应的main函数
//#app_main.cpp
int main(int argc, char* const argv[])
{
// 将参数 argv 放到 argv_String 字符串中,然后打印出来
// 之前start zygote 传入的参数是 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
if (!LOG_NDEBUG) {
String8 argv_String;
for (int i = 0; i < argc; ++i) {
argv_String.append("\"");
argv_String.append(argv[I]);
argv_String.append("\" ");
}
ALOGV("app_process main with argv: %s", argv_String.string());
}
//AppRuntime 定义于 app_main.cpp 中,继承自 AndroidRuntime
//就是对 Android 运行环境的一种抽象,类似于 Java 虚拟机对 Java 程序的作用
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
//这两个参数是Java 程序需要依赖的jar包,相当于import
const char* spaced_commands[] = { "-cp", "-classpath" };
bool known_command = false;
int I;
for (i = 0; i < argc; i++) { //解析参数的起点
if (known_command == true) { //将 space_commands 中的参数额外加入 VM
runtime.addOption(strdup(argv[i]));
known_command = false;
continue;
}
for (int j = 0;
j < static_cast(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
++j) {
//比较参数是否是 spaced_commands 中的参数
if (strcmp(argv[i], spaced_commands[j]) == 0) {
known_command = true;
}
}
//如果参数第一个字符是'-',直接跳出循环,zygote启动的参数第一个参数就是 -Zygote,执行到这里就会跳出循环
if (argv[i][0] != '-') {
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
}
// Parse runtime arguments. Stop at first unrecognized option.
//这里可以看出,通过app_main 可以启动 zygote,system-server,普通的application进程
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName; // app_process 的名称改为 zygote
String8 className; // 启动 apk 进程时,对应的类名
++i; // Skip unused "parent dir" argument.
//跳过一个参数,就是 -Xzygote 后面的参数,也就是 、system/bin,就是所谓的parent dir
while (i < argc) { //开始解析参数
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) { //表示是 zygote 启动模式
zygote = true;
niceName = ZYGOTE_NICE_NAME; //这个值就是根据平台参数,可能是zygote64 或者 zygote
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true; //init.zygote.rc 中定义,启动zygote 后会启动 system-server
} else if (strcmp(arg, "--application") == 0) {
application = true; //表示是 application 启动模式,也就是普通的应用程序
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12); // 进程别名,可以自己知道进程名
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg); // 与 --application 配置,启动指定的类,application 启动的class
break;
} else {
--I;
break;
}
}
//准备参数
Vector args;
if (!className.isEmpty()) { //className 不为空,说明是 application 启动模式
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
if (!LOG_NDEBUG) {
String8 restOfArgs;
char* const* argv_new = argv + I;
int argc_new = argc - I;
for (int k = 0; k < argc_new; ++k) {
restOfArgs.append("\"");
restOfArgs.append(argv_new[k]);
restOfArgs.append("\" ");
}
ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
}
} else { // zygote 启动模式
// We're in zygote mode.
maybeCreateDalvikCache(); //创建dalvik 的缓存目录并定义权限
if (startSystemServer) { //增加 start-system-server 参数
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX]; //获取对应平台的 abi 信息
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list="); //参数需要指定 abi
abiFlag.append(prop);
args.add(abiFlag); // 加入 --abi-list = 参数
for (; i < argc; ++i) {
args.add(String8(argv[i])); //将剩下的参数加入 args
}
}
if (!niceName.isEmpty()) { //将 app_process 的进程名,替换为niceName
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
if (zygote) { //调用 Runtime 的start 函数,启动 zygoteInit
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
//非zygote启动方式进入这个分支
//如果是 application 启动模式,则加入 RuntimeInit
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.");
}
}
小结
app_main.cpp的代码流程小结一下
- 初始化AndroidRuntime
- strcmp(arg, "--zygote") 设置为zygote启动模式
- args.add(String8("start-system-server"))给start函数的参数args赋值
- runtime.start("com.android.internal.os.ZygoteInit", args, zygote) 启动zygoteInit
从Android的系统架构来看,硬件抽象层上面和JNI同级别的有一个Android runtime,ART的的初始化也是在zygote的启动流程中,接着就进入了runtime的start()方法
//#AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
static const String8 startSystemServer("start-system-server");
// Whether this is the primary zygote, meaning the zygote which will fork system server.
bool primary_zygote = false;
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL); //初始化 JNI,加载 libart.so
JNIEnv* env;
//创建虚拟机,其中大多数参数有系统属性决定,最终startVm 利用 JNI_CreateJavaVM 创建虚拟机
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
//回调 AppRuntime 的 onVmCreated 函数
//对于 zygote 进程的启动流程而言,无实际操作,表示虚拟机创建完成,里面是空实现
onVmCreated(env);
//注册 JNI 函数
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
//替换string为实际路径,将"com.android.internal.os.ZygoteInit" 替换为 “com/android/internal/os/ZygoteInit”
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName); //找到class文件
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V"); //通过反射找到ZygoteInit 的 main 函数
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray); //调用ZygoteInit的main()函数
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK) //退出当前线程
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0) //创建一个线程,该线程会等待所有子线程结束后关闭虚拟机
ALOGW("Warning: VM did not shut down cleanly\n");
}
int AndroidRuntime::startReg(JNIEnv* env)
{
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
return 0;
}
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) {
return -1;
}
}
return 0;
}
static const RegJNIRec gRegJNI[] = {
REG_JNI(register_com_android_internal_os_RuntimeInit),
REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
REG_JNI(register_android_os_SystemClock),
......
}
struct RegJNIRec {
int (*mProc)(JNIEnv*);
};
从源代码中找到主要的流程
- startVm 创建虚拟机
- startReg 注册JNI方法
- env->CallStaticVoidMethod 使用JNI调用ZygoteInit 的main函数,进入java层
这部分就是zygote的c++代码的主要业务,会创建虚拟机,也会注册JNI方法,注册JNI方法就是类似的一个方法名对应的关联代理,在AndroidRuntim.cpp文件中,就会查到相关的jni调用的函数指向,处理完这些,就会进入java层的zygote流程
小结
从上面的流程可以看出,在Zygote进程中通过startVm方法启动了虚拟机,后续应用进程通过zygote孵化拷贝fork出新的进程,就会复制zygote中的虚拟机,所以每个应用进程会有自己独立的虚拟机,虚拟机的主要功能就是实现进程的内存管理(堆区,方法区,栈之类的),每个进程独立管理自己的内存,遇到各种内存问题导致进程崩溃而相互之间不会影响,做到了进程间的隔离
Java层Zygote流程
上面的流程还是在c++代码中,通过反射执行到了ZygoteInit.main(),进入了Java层的逻辑
//#ZygoteInit.java
public static void main(String argv[]) {
ZygoteServer zygoteServer = null; //
ZygoteHooks.startZygoteNoThreadCreation(); //调用native函数,确保当前没有其他线程在运行,主要出于安全的考虑
Runnable caller;
try {
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
//解析参数,得到上述变量的值
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[I]);
}
}
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(bootTimingsTraceLog); //默认情况,预加载信息
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
}
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); //fork systemserver
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList); //zygote 进程进入无限循环,处理请求
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
}
通过上述源码,zygote的Java层启动流程梳理一下
- preload(bootTimingsTraceLog) 预加载资源,加快后续进程的启动,应用进程也是从zygote进程孵化来的,一些系统的默认资源在zygote进行预加载,加快后续进程孵化启动的速度
- zygoteServer = new ZygoteServer(isPrimaryZygote) 实例化socket
- Runnable r = forkSystemServer() 启动systemserver 进程,AMS
- caller = zygoteServer.runSelectLoop(abiList) 死循环,接收AMS传过来的信息
到此Zygote进程的启动流程结束,zygote进程会去启动systemserver进程,这个进程跟各种系统服务有关系,zygote会通过socket的通信方式,接收其他进程的请求,去孵化应用进程
总结
zygote进程的启动分为native层和Java层
native层:
- 会去初始化运行环境,创建jvm Android 虚拟机-AndroidRuntime ART
- 注册JNI
- 调用zygoteInit.main进入java层
java层:
- 预加载系统资源,加快后续应用进程的启动速度
- socket 跨进程通信方案,接收其他进程的消息
- 循环等待消息
zygote的流程走完了,下一篇开始分析systemserver的流程了