前面的文章花了很大的篇幅去介绍了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 AndroidRuntime
androidruntime是怎么样的呢?里面有没有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循环,来处理后续的请求。