Android启动流程分析(十一) zygote的启动

#############################################

本文为极度寒冰原创,转载请注明出处

#############################################

前面的文章花了很大的篇幅去介绍了init进程如何去解析init.rc,如何去执行系统的一些服务。

那么,我们所说的zygote是怎么启动的呢?zygote又是具体负责了哪些工作呢?

本文我们来一探究竟。

zygote在inir.rc中有如下的描述:

service zygote /system/bin/app_process -Xzygote /system/bin –zygote –start-system-serverclass mainsocket zygote stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart mediaonrestart restart netd我们可以简单的分析下这两句话,

service zygote /system/bin/app_process -Xzygote /system/bin –zygote –start-system-server

class main

这个是说,zygote是属于main的class。

zygote是一个服务,服务的名字叫zygote. 启动的时候执行的命令是app_process, 传递的参数是-Xzygote /system/bin –zygote –start-system-server

那么,按照我们前面分析的理论,我们去看一下app_process是个什么东西首先我们到framework的目录下,在base/cmds/app_process里面,我们看到了生成app_process的makefile

include $(CLEAR_VARS)LOCAL_SRC_FILES:= \app_main.cppLOCAL_SHARED_LIBRARIES := \libcutils \libutils \liblog \libbinder \libandroid_runtimeLOCAL_MODULE:= app_processLOCAL_MULTILIB := bothLOCAL_MODULE_STEM_32 := app_process32LOCAL_MODULE_STEM_64 := app_process64include $(BUILD_EXECUTABLE)我们可以看到app_process被执行生成了一个应用程序。

试想一下,zygote的这个服务应该是一直在运行的,但是我们如果adb shell去看ps的话,并找不到app_process的这个命令在一直运行。

这个是为什么呢?

首先我们从app_process的main函数里面截取出来一段

while (i < argc) {const char* arg = argv[i++];if (strcmp(arg, "–zygote") == 0) { // 如果从init.rc里面传进来的参数是带–zygote的话,一定是会进这个判断zygote = true; // 将zygote设置为trueniceName = ZYGOTE_NICE_NAME; // 将niceName设置为zygote_nice_name设置为zygote} else if (strcmp(arg, "–start-system-server") == 0) { // 如果是要启动start-system-server的话startSystemServer = true; // 会将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 (!niceName.isEmpty()) { //如果niceName不为空的话runtime.setArgv0(niceName.string());set_process_name(niceName.string()); // 调用这个函数将这个process的name设置为zygote}if (zygote) { // zygote一定为trueruntime.start("com.android.internal.os.ZygoteInit", args); //我们进入到了这个判断} else if (className) {runtime.start("com.android.internal.os.RuntimeInit", args);} else {fprintf(stderr, "Error: no class name or –zygote supplied.\n");app_usage();LOG_ALWAYS_FATAL("app_process: no class name or –zygote supplied.");return 10;}我们可以看到,runtime是调用了start的方法区进行了这个zygote的启动的工作,那么我们这个runtime是调用的哪边的start呢?

我们在当前的appruntime里面,是没有相关start函数的实现。

那我们去他的父类里面去看一下。

class AppRuntime : public AndroidRuntimeandroidruntime是怎么样的呢?里面有没有start的方法呢?

我们从里面找到了start的方法。

951void AndroidRuntime::start(const char* className, const Vector<String8>& options)952{953 ALOGD(">>>>>> START %s uid %d <<<<<<\n",954className != NULL ? className : "(unknown)", getuid());955956 static const String8 startSystemServer("start-system-server");957958 /*959* 'startSystemServer == true' means runtime is obsolete and not run from960* init.rc anymore, so we print out the boot start event here.961*/962 for (size_t i = 0; i < options.size(); ++i) {963if (options[i] == startSystemServer) {964/* track our progress through the boot sequence */965const int LOG_BOOT_PROGRESS_START = 3000;966LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));967}968 }969970 const char* rootDir = getenv("ANDROID_ROOT");971 if (rootDir == NULL) {972rootDir = "/system";973if (!hasDir("/system")) {974LOG_FATAL("No root directory specified, and /android does not exist.");975return;976}977setenv("ANDROID_ROOT", rootDir, 1);978 }979980 //const char* kernelHack = getenv("LD_ASSUME_KERNEL");981 //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);982983 /* start the virtual machine */984 JniInvocation jni_invocation;985 jni_invocation.Init(NULL);986 JNIEnv* env;987 if (startVm(&mJavaVM, &env) != 0) { // 创建虚拟机988return;989 }990 onVmCreated(env);991992 /*993* Register android functions.994*/995 if (startReg(env) < 0) { // 注册jni的方法996ALOGE("Unable to register all android natives\n");997return;998 }9991000 /*1001* We want to call main() with a String array with arguments in it.1002* At present we have two arguments, the class name and an option string.1003* Create an array to hold them.1004*/1005 jclass stringClass; // class对象1006 jobjectArray strArray; // 对应objectArray对象1007 jstring classNameStr; // 一个string10081009 stringClass = env->FindClass("java/lang/String"); //首先找到了string的class1010 assert(stringClass != NULL);1011 strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL); // New 了一个ObjectArray1012 assert(strArray != NULL);1013 classNameStr = env->NewStringUTF(className); // 将className转换为UTF8的类型1014 assert(classNameStr != NULL);1015 env->SetObjectArrayElement(strArray, 0, classNameStr); // 设置objectarray的第一个元素为classname10161017 for (size_t i = 0; i < options.size(); ++i) { // 将后续的参数依次经过转换push到strArray的数组中1018jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());1019assert(optionsStr != NULL);1020env->SetObjectArrayElement(strArray, i + 1, optionsStr);1021 }10221023 /*1024* Start VM. This thread becomes the main thread of the VM, and will1025* not return until the VM exits.1026*/1027 char* slashClassName = toSlashClassName(className); // 将className转换为/的形式1028 jclass startClass = env->FindClass(slashClassName); // 寻找这个类1029 if (startClass == NULL) { // 如果找不到的话,我们会返回NULL1030ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);1031/* keep going */1032 } else {1033jmethodID startMeth = env->GetStaticMethodID(startClass, "main",1034"([Ljava/lang/String;)V"); // 获取我们寻找到的这个类的main函数1035if (startMeth == NULL) {1036ALOGE("JavaVM unable to find main() in '%s'\n", className);1037/* keep going */1038} else {1039env->CallStaticVoidMethod(startClass, startMeth, strArray); // 去执行这个类的main函数的方法。10401041#if 01042if (env->ExceptionCheck())1043threadExitUncaughtException(env);1044#endif1045}1046 }1047 free(slashClassName); // free10481049 ALOGD("Shutting down VM\n");1050 if (mJavaVM->DetachCurrentThread() != JNI_OK)1051ALOGW("Warning: unable to detach main thread\n");1052 if (mJavaVM->DestroyJavaVM() != 0)1053ALOGW("Warning: VM did not shut down cleanly\n");1054}来根据刚才传递的参数来看一下zygoteInit的main函数648 public static void main(String argv[]) {649try {650// Start profiling the zygote initialization.651SamplingProfilerIntegration.start();652653boolean startSystemServer = false;654String socketName = "zygote";655String abiList = null;656for (int i = 1; i < argv.length; i++) {657if ("start-system-server".equals(argv[i])) {658startSystemServer = true; // startSystemServer为true659} else if (argv[i].startsWith(ABI_LIST_ARG)) {660abiList = argv[i].substring(ABI_LIST_ARG.length());661} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {662socketName = argv[i].substring(SOCKET_NAME_ARG.length());663} else {664throw new RuntimeException("Unknown command line argument: " + argv[i]);665}666}667668if (abiList == null) {669throw new RuntimeException("No ABI list supplied.");670}671672registerZygoteSocket(socketName); // 注册了一个socket,用来与系统中的其他应用程序进行通信673EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,674SystemClock.uptimeMillis());675preload(); // 预加载一些资源676EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,677SystemClock.uptimeMillis());678679// Finish profiling the zygote initialization.680SamplingProfilerIntegration.writeZygoteSnapshot();681682// Do an initial gc to clean up after startup683gc();684685// Disable tracing so that forked processes do not inherit stale tracing tags from686// Zygote.687Trace.setTracingEnabled(false);688689if (startSystemServer) { // 如果startSystemServer为true的话,我们会启动systemServer690startSystemServer(abiList, socketName);691}692693Log.i(TAG, "Accepting command socket connections");694runSelectLoop(abiList); // 进入select的循环,用来响应其他应用程序的请求695696closeServerSocket();697} catch (MethodAndArgsCaller caller) {698caller.run();699} catch (RuntimeException ex) {700Log.e(TAG, "Zygote died with exception", ex);701closeServerSocket();702throw ex;703}704 }那么,最后我们对zygote进行一下总结

首先zygote创建了appruntime的对象,并调用他的start。此后的活动由AppRuntime来控制

然后调用startVM来创建了虚拟机,调用startReg来注册JNI的函数

通过JNI调用zygoteInit进入了java的世界

调用registerZygoteSocket来响应子孙后代的请求,同时调用preload函数进行资源的预加载

调用startSystemServer来进行系统启动的后续工作

完成了java世界的初创工作后,,变进入了select循环,来处理后续的请求。

你并不一定会从此拥有更美好的人生,

Android启动流程分析(十一) zygote的启动

相关文章:

你感兴趣的文章:

标签云: