目录
1.Zygote是什么:
2.Zygote是怎么启动的:
3.Zygote的运行流程
4.Fork进程流程:
5.APP的Fork进程过程:
英文直译是受精卵,Zygote进程在Android系统中是一个极其重要的守护进程服务(Daem Service),他的主要作用有以下几点:
启动Android框架层的进程:Zygote首先会启动SystemService进程,而在SystemService会启动Android系统中重要服务。例如ActvityManagerService、PackageManagerService等。
为启动的应用程序创建一个新的进程Zygote启动时会创建一个Socket,ActivityManagerService通过这个Socket发消息给Zygote为应用创建一个新的进程。
加快应用的启动速度Zygote启动时会创建一个Dalvik VM,并在Dalvik VM上装载系统资源,这样Zygote进程Fork子进程时就会继承此虚拟机的相关资源(也就是预加载系统的资源和类),这样启动一个应用只要加载应用的相关资源即可,这样大大的提高了应用的启动速度。
Zygote进程是有init进程格局init.rc配置的Action进行启动的,而init.rc是根据编译32位/64位系统来配置选择的,配置项为
/system/core/rootdir/init.rc import /init.${ro.zygote}.rc以init.zygote32_64.rc为例
/system/core/rootdir/init.zygote64_32.rc 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 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 /dev/stune/foreground/tasks /dev/blkio/foreground/tasks critical 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 socket zygote_secondary stream 660 root system onrestart restart zygote writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks /dev/blkio/foreground/tasks critical服务名称分别是zygote和zygote_secondary,分别是执行system/bin下的app_process64和app_process32这2个执行文件来启动的
/system/bin lrwxr-xr-x 1 root shell 13 2019-05-06 04:51 app_process -> app_process64 -rwxr-xr-x 1 root shell 24988 2019-05-06 04:51 app_process32 -rwxr-xr-x 1 root shell 23960 2019-05-06 04:51 app_process64
从第一个软连接可以看到,系统是64位的,同时兼容32位的,接下来看看app_process的源码
/frameworks/base/cmds/app_process/app_main.cpp int main(int argc, char* const argv[]) { ...... //创建Dalvik VM AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] argc--; argv++; // Everything up to '--' or first non '-' arg goes to the vm. // // The first argument after the VM args is the "parent dir", which // is currently unused. // // After the parent dir, we expect one or more the following internal // arguments : // // --zygote : Start in zygote mode // --start-system-server : Start the system server. // --application : Start in application (stand alone, non zygote) mode. // --nice-name : The nice name for this process. // // For non zygote starts, these arguments will be followed by // the main class name. All remaining arguments are passed to // the main method of this class. // // For zygote starts, all remaining arguments are passed to the zygote. // main function. // // Note that we must copy argument string values since we will rewrite the // entire argument block when we apply the nice name to argv0. // // As an exception to the above rule, anything in "spaced commands" // goes to the vm even though it has a space in it. const char* spaced_commands[] = { "-cp", "-classpath" }; // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s). bool known_command = false; int i; //从zygote.rc文件的Action中可以看出argv[0]="/system/bin"因此直接跳出循环 for (i = 0; i < argc; i++) { if (known_command == true) { runtime.addOption(strdup(argv[i])); ALOGV("app_process main add known option '%s'", argv[i]); known_command = false; continue; } for (int j = 0; j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0])); ++j) { if (strcmp(argv[i], spaced_commands[j]) == 0) { known_command = true; ALOGV("app_process main found known command '%s'", argv[i]); } } if (argv[i][0] != '-') { break; } if (argv[i][1] == '-' && argv[i][2] == 0) { ++i; // Skip --. break; } runtime.addOption(strdup(argv[i])); ALOGV("app_process main add option '%s'", argv[i]); } // 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; } } //到此初始化的值为: //zygote = true; startSystemServer = true;className = "--socket-name=zygote" Vector<String8> args; if (!className.isEmpty()) { // We're not in zygote mode, the only argument we need to pass // to RuntimeInit is the application argument. // // The Remainder of args get passed to startup class main(). Make // copies of them before we overwrite them with the process name. 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 { // We're in zygote mode. /*创建Dalvik VM缓存 *路径:/data/dalvik-cache/arm(支持32位) * /data/dalvik-cache/arm64(支持64位) */ maybeCreateDalvikCache(); if (startSystemServer) { args.add(String8("start-system-server")); } char prop[PROP_VALUE_MAX]; 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="); abiFlag.append(prop); args.add(abiFlag); // In zygote mode, pass all remaining arguments to the zygote // main() method. for (; i < argc; ++i) { args.add(String8(argv[i])); } } if (!niceName.isEmpty()) { runtime.setArgv0(niceName.string(), true /* setProcName */); } if (zygote) { //开始启动ZygoteInit 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."); } }在app_process服务中只要创建了一个Dalvik VM,之后根据app_process的参数列表,初始化Dalvik VM启动的类和参数,在上面AppRuntime创建了Delvik VM,AppRuntime是AndroidRuntime的子类,runtime.start方法就是调用了AndroidRuntime的start方法
/frameworks/base/core/jni/AndroidRuntime.cpp void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ...... /* start the virtual machine */ /*初始化Jni/ JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; /*初始化相关参数,并且启动Java VM*/ if (startVm(&mJavaVM, &env, zygote) != 0) { return; } /*回调VM启动成功*/ onVmCreated(env); /* * Register android functions. */ 在VM中注册Jni相关 if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } /* * We want to call main() with a String array with arguments in it. * At present we have two arguments, the class name and an option string. * Create an array to hold them. */ //初始化jni启动Java类的相关参数 jclass stringClass; jobjectArray strArray; jstring classNameStr; //创建一个java字符串,一个java字符串数组 stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL); assert(strArray != NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); //初始化java数组中的值 env->SetObjectArrayElement(strArray, 0, classNameStr); for (size_t i = 0; i < options.size(); ++i) { jstring optionsStr = env->NewStringUTF(options.itemAt(i).string()); assert(optionsStr != NULL); env->SetObjectArrayElement(strArray, i + 1, optionsStr); } /* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */ char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); 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"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); /* keep going */ } else { //调用com/android/internal/os/ZygoteInit的Main方法启动 正常运行会阻塞在这 //出异常之后才会继续执行 env->CallStaticVoidMethod(startClass, startMeth, strArray); #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"); }在start方法中主要就做了3件事:
启动VM初始化Jni调用ZygoteInit的main方法启动Java相关服务继续看看ZygoteInit中做了什么
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java public static void main(String argv[]) { /*请参数:com.android.internal.os.ZygoteInit start-system-server --abi-list=arm64-v8a --socket-name=zygote com.android.internal.os.ZygoteInit --abi-list=armeabi-v7a,armeabi --socket-name=zygote_secondary --enable-lazy-preload */ //注册Sockot,为接受命令Fock子进程做准备 ZygoteServer zygoteServer = new ZygoteServer(); // Mark zygote start. This ensures that thread creation will throw // an error. // Zygote goes into its own process group. //设置当前进程的pid try { Os.setpgid(0, 0); } catch (ErrnoException ex) { throw new RuntimeException("Failed to setpgid(0,0)", ex); } try { // Report Zygote start time to tron unless it is a runtime restart if (!"1".equals(SystemProperties.get("sys.boot_completed"))) { MetricsLogger.histogram(null, "boot_zygote_init", (int) SystemClock.elapsedRealtime()); } String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing"; BootTimingsTraceLog bootTimingsTraceLog = new BootTimingsTraceLog(bootTimeTag, Trace.TRACE_TAG_DALVIK); bootTimingsTraceLog.traceBegin("ZygoteInit"); //promote process priority to boost bootup int myPriority = Process.getThreadPriority(Process.myPid()); Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO); //启动DDMS RuntimeInit.enableDdms(); // Start profiling the zygote initialization. SamplingProfilerIntegration.start(); boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; boolean enableLazyPreload = false; for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; isPrimaryCpuAbi = 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)) { socketName = argv[i].substring(SOCKET_NAME_ARG.length()); } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } if (abiList == null) { throw new RuntimeException("No ABI list supplied."); } //将app_process的Socket注册到zygoteServer中 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) { bootTimingsTraceLog.traceBegin("ZygotePreload"); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); Jlog.d(JlogConstants.JLID_BOOT_PROGRESS_PRELOAD_START,"JL_BOOT_PROGRESS_PRELOAD_START:" + argv[0]); //加载常用类 preload(bootTimingsTraceLog); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); bootTimingsTraceLog.traceEnd(); // ZygotePreload Jlog.d(JlogConstants.JLID_BOOT_PROGRESS_PRELOAD_END,"JL_BOOT_PROGRESS_PRELOAD_END"); } else { Zygote.resetNicePriority(); } // Finish profiling the zygote initialization. SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup bootTimingsTraceLog.traceBegin("PostZygoteInitGC"); gcAndFinalize(); bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC bootTimingsTraceLog.traceEnd(); // ZygoteInit // Disable tracing so that forked processes do not inherit stale tracing tags from // Zygote. Trace.setTracingEnabled(false); //Restore process priority Process.setThreadPriority(myPriority); // Zygote process unmounts root storage spaces. Zygote.nativeUnmountStorageOnInit(); // Set seccomp policy Seccomp.setPolicy(); //启动framework层系统服务 if (startSystemServer) { startSystemServer(abiList, socketName, zygoteServer); } Log.i(TAG, "Accepting command socket connections, abiList= "+abiList); //阻塞循环等待命令 zygoteServer.runSelectLoop(abiList); zygoteServer.closeServerSocket(); } catch (Zygote.MethodAndArgsCaller caller) { caller.run(); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); zygoteServer.closeServerSocket(); throw ex; } }到此Zygote的启动流程就结束了,最重要的就是启动VM、加载framework层的系统服务和初始化Sokect通道(启动APP需要使用)。
Zygote启动后Fork的第一个进程就是SystemService,可以看上面代码中启动framework层系统服务。
./frameworks/base/core/java/com/android/internal/os/ZygoteInit.java /** * Prepare the arguments and fork for the system server process. */ private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_IPC_LOCK, OsConstants.CAP_KILL, OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_BIND_SERVICE, OsConstants.CAP_NET_BROADCAST, OsConstants.CAP_NET_RAW, OsConstants.CAP_SYS_MODULE, OsConstants.CAP_SYS_NICE, OsConstants.CAP_SYS_PTRACE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG, OsConstants.CAP_WAKE_ALARM ); /* Containers run without this capability, so avoid setting it in that case */ if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) { capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND); } /* Hardcoded command line to start the system server */ String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { //创建Arguments对象,初始化启动参数 parsedArgs = new ZygoteConnection.Arguments(args); //根据系统属性ro.debuggable来初始化Debuggger ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); //初始化invoke-with参数 ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /* Request to fork the system server process */ //调用jni方法fork进程 pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } zygoteServer.closeServerSocket(); handleSystemServerProcess(parsedArgs); } return true; }调用nativeForkSystemServer方法com_android_internal_os_Zygote_nativeForkSystemServer方法
/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp static jint com_android_internal_os_Zygote_nativeForkSystemServer( JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids, jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities, jlong effectiveCapabilities) { pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, permittedCapabilities, effectiveCapabilities, MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL, NULL, NULL, NULL); ...... return pid; } // Utility routine to fork zygote and specialize the child process. static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, jint debug_flags, jobjectArray javaRlimits, jlong permittedCapabilities, jlong effectiveCapabilities, jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, jintArray fdsToClose, jintArray fdsToIgnore, jstring instructionSet, jstring dataDir) { // Temporarily block SIGCHLD during forks. The SIGCHLD handler might // log, which would result in the logging FDs we close being reopened. // This would cause failures because the FDs are not whitelisted. // // Note that the zygote process is single threaded at this point. if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) { ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)); RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_BLOCK, { SIGCHLD }) failed."); } //调用linux的fork方法进行进程创建 pid_t pid = fork(); //此时会返回2个pid pid为0时此时运行的是子进程中, //pid大于0时返回的是子进程的pid,此时运行在父进程中 if (pid == 0) { ...... //挂载私有目录,准备私用资源等以及一些其他操作 } else if (pid > 0) { // the parent process // We blocked SIGCHLD prior to a fork, we unblock it here. if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) { ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)); RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed."); } } return pid; } } // anonymous namespace在调用fork()方法之前,暂时阻止SIGCHLD信号量,fork完成之后在恢复
在语句pid=fork()之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了,这两个进程的几乎完全相同,将要执行的下一条语句都是if(pid<0)…… 为什么两个进程的fpid不同呢,这与fork函数的特性有关。fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值: 1)在父进程中,fork返回新创建子进程的进程ID; 2)在子进程中,fork返回0; 3)如果出现错误,fork返回一个负值;
AMS中调用startProcessLocked之后在ZygoteProcess中初始化参数,之后通过Socket发消息给ZygoteService中,在ZygoteConnection中解析参数,并初始化,之后调用Jni方法,最后调用Linux的Fork方法新建一个子进程。