Android启动流程分析(十一) zygote的启动
#############################################
本文为极度寒冰原创,转载请注明出处
#############################################
前面的文章花了很大的篇幅去介绍了init进程如何去解析init.rc,如何去执行系统的一些服务。
那么,我们所说的zygote是怎么启动的呢?zygote又是具体负责了哪些工作呢?
本文我们来一探究竟。
zygote在inir.rc中有如下的描述:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart 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.cpp LOCAL_SHARED_LIBRARIES := libcutils libutils liblog libbinder libandroid_runtime LOCAL_MODULE:= app_process LOCAL_MULTILIB := both LOCAL_MODULE_STEM_32 := app_process32 LOCAL_MODULE_STEM_64 := app_process64 include $(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设置为true niceName = 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一定为true runtime.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的方法呢?
AndroidRunTime的实现位于:frameworks/base/core/jni/AndroidRuntime.cpp
我们从里面找到了start的方法。
951void AndroidRuntime::start(const char* className, const Vector<String8>& options) 952{ 953 ALOGD(">>>>>> START %s uid %d <<<<<<\n", 954 className != NULL ? className : "(unknown)", getuid()); 955 956 static const String8 startSystemServer("start-system-server"); 957 958 /* 959 * 'startSystemServer == true' means runtime is obsolete and not run from 960 * init.rc anymore, so we print out the boot start event here. 961 */ 962 for (size_t i = 0; i < options.size(); ++i) { 963 if (options[i] == startSystemServer) { 964 /* track our progress through the boot sequence */ 965 const int LOG_BOOT_PROGRESS_START = 3000; 966 LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); 967 } 968 } 969 970 const char* rootDir = getenv("ANDROID_ROOT"); 971 if (rootDir == NULL) { 972 rootDir = "/system"; 973 if (!hasDir("/system")) { 974 LOG_FATAL("No root directory specified, and /android does not exist."); 975 return; 976 } 977 setenv("ANDROID_ROOT", rootDir, 1); 978 } 979 980 //const char* kernelHack = getenv("LD_ASSUME_KERNEL"); 981 //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack); 982 983 /* start the virtual machine */ 984 JniInvocation jni_invocation; 985 jni_invocation.Init(NULL); 986 JNIEnv* env; 987 if (startVm(&mJavaVM, &env) != 0) { // 创建虚拟机 988 return; 989 } 990 onVmCreated(env); 991 992 /* 993 * Register android functions. 994 */ 995 if (startReg(env) < 0) { // 注册jni的方法 996 ALOGE("Unable to register all android natives\n"); 997 return; 998 } 999 1000 /* 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; // 一个string 1008 1009 stringClass = env->FindClass("java/lang/String"); //首先找到了string的class 1010 assert(stringClass != NULL); 1011 strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL); // New 了一个ObjectArray 1012 assert(strArray != NULL); 1013 classNameStr = env->NewStringUTF(className); // 将className转换为UTF8的类型 1014 assert(classNameStr != NULL); 1015 env->SetObjectArrayElement(strArray, 0, classNameStr); // 设置objectarray的第一个元素为classname 1016 1017 for (size_t i = 0; i < options.size(); ++i) { // 将后续的参数依次经过转换push到strArray的数组中 1018 jstring optionsStr = env->NewStringUTF(options.itemAt(i).string()); 1019 assert(optionsStr != NULL); 1020 env->SetObjectArrayElement(strArray, i + 1, optionsStr); 1021 } 1022 1023 /* 1024 * Start VM. This thread becomes the main thread of the VM, and will 1025 * not return until the VM exits. 1026 */ 1027 char* slashClassName = toSlashClassName(className); // 将className转换为/的形式 1028 jclass startClass = env->FindClass(slashClassName); // 寻找这个类 1029 if (startClass == NULL) { // 如果找不到的话,我们会返回NULL 1030 ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); 1031 /* keep going */ 1032 } else { 1033 jmethodID startMeth = env->GetStaticMethodID(startClass, "main", 1034 "([Ljava/lang/String;)V"); // 获取我们寻找到的这个类的main函数 1035 if (startMeth == NULL) { 1036 ALOGE("JavaVM unable to find main() in '%s'\n", className); 1037 /* keep going */ 1038 } else { 1039 env->CallStaticVoidMethod(startClass, startMeth, strArray); // 去执行这个类的main函数的方法。 1040 1041#if 0 1042 if (env->ExceptionCheck()) 1043 threadExitUncaughtException(env); 1044#endif 1045 } 1046 } 1047 free(slashClassName); // free 1048 1049 ALOGD("Shutting down VM\n"); 1050 if (mJavaVM->DetachCurrentThread() != JNI_OK) 1051 ALOGW("Warning: unable to detach main thread\n"); 1052 if (mJavaVM->DestroyJavaVM() != 0) 1053 ALOGW("Warning: VM did not shut down cleanly\n"); 1054}来根据刚才传递的参数来看一下zygoteInit的main函数
648 public static void main(String argv[]) { 649 try { 650 // Start profiling the zygote initialization. 651 SamplingProfilerIntegration.start(); 652 653 boolean startSystemServer = false; 654 String socketName = "zygote"; 655 String abiList = null; 656 for (int i = 1; i < argv.length; i++) { 657 if ("start-system-server".equals(argv[i])) { 658 startSystemServer = true; // startSystemServer为true 659 } else if (argv[i].startsWith(ABI_LIST_ARG)) { 660 abiList = argv[i].substring(ABI_LIST_ARG.length()); 661 } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { 662 socketName = argv[i].substring(SOCKET_NAME_ARG.length()); 663 } else { 664 throw new RuntimeException("Unknown command line argument: " + argv[i]); 665 } 666 } 667 668 if (abiList == null) { 669 throw new RuntimeException("No ABI list supplied."); 670 } 671 672 registerZygoteSocket(socketName); // 注册了一个socket,用来与系统中的其他应用程序进行通信 673 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, 674 SystemClock.uptimeMillis()); 675 preload(); // 预加载一些资源 676 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, 677 SystemClock.uptimeMillis()); 678 679 // Finish profiling the zygote initialization. 680 SamplingProfilerIntegration.writeZygoteSnapshot(); 681 682 // Do an initial gc to clean up after startup 683 gc(); 684 685 // Disable tracing so that forked processes do not inherit stale tracing tags from 686 // Zygote. 687 Trace.setTracingEnabled(false); 688 689 if (startSystemServer) { // 如果startSystemServer为true的话,我们会启动systemServer 690 startSystemServer(abiList, socketName); 691 } 692 693 Log.i(TAG, "Accepting command socket connections"); 694 runSelectLoop(abiList); // 进入select的循环,用来响应其他应用程序的请求 695 696 closeServerSocket(); 697 } catch (MethodAndArgsCaller caller) { 698 caller.run(); 699 } catch (RuntimeException ex) { 700 Log.e(TAG, "Zygote died with exception", ex); 701 closeServerSocket(); 702 throw ex; 703 } 704 }那么,最后我们对zygote进行一下总结
首先zygote创建了appruntime的对象,并调用他的start。此后的活动由AppRuntime来控制
然后调用startVM来创建了虚拟机,调用startReg来注册JNI的函数
通过JNI调用zygoteInit进入了java的世界
调用registerZygoteSocket来响应子孙后代的请求,同时调用preload函数进行资源的预加载
调用startSystemServer来进行系统启动的后续工作
完成了java世界的初创工作后,变进入了select循环,来处理后续的请求。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。