Android情景分析之深入解析zygote

本文详细解析了Android系统中Zygote进程的启动过程及其核心作用。介绍了Zygote如何创建Java虚拟机,注册JNI函数,并启动Java世界的第一个进程system_server。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

我们都知道,Android系统存在着两个完全不同的世界:

1.      Java世界,Google提供的SDK编写出来的程序大部分都是针对这个世界的。在这个世界中运行的程序都是基于Dalvik虚拟机的java程序。

2.      Native世界,也就是用Native语言C或者C++开发的程序,例如采用NDK开发的程序。


于是便有了这个疑问:

Android系统是基于linux内核构建的,那么最早肯定是native世界,可java世界是什么时候开始被创建出来的呢?

带着这个疑问,我们今天就来剖析下zygote进程的实现原理。


zygote分析

zygote本身是一个Native的应用程序,在前面对init进程的分析中,我们知道,zygote是系统在刚开始初始化时,init进程根据init.rc配置文件fork出来的子进程,映像路径为/system/bin/app_process。所以,zygote最初的名字叫“app_process”,在程序运行过程中,app_process通过Linux下的prctl系统调用将自己的名字改成了“zygote”,所以我们通过ps命令看到的进程名是“zygote”。

Zygote的原型app_process所对应的源文件为frameworks\base\cmds\app_process\App_main.cpp。相应main函数如下:

  1. int main(int argc, charconst argv[])  
  2. {  
  3.     …..  
  4. /* 
  5.     Init.rc中的zygote启动参数: 
  6. -Xzygote /system/bin --zygote --start-system-server 
  7. */  
  8.     mArgC = argc;  
  9.     mArgV = argv;  
  10.   
  11.     mArgLen = 0;  
  12.     for (int i=0; i<argc; i++) {  
  13.         mArgLen += strlen(argv[i]) + 1;  
  14.     }  
  15.     mArgLen--;  
  16.       
  17.     // 定义一个AppRuntime的对象runtime  
  18.     AppRuntime runtime;  
  19.     const char* argv0 = argv[0];  
  20.   
  21.     argc--;  
  22.     argv++;  
  23.       
  24. // 添加vm启动参数  
  25.     int i = runtime.addVmArguments(argc, argv);  
  26.   
  27.     // 开始解析运行时参数  
  28.     bool zygote = false;  
  29.     bool startSystemServer = false;  
  30.     bool application = false;  
  31.     const char* parentDir = NULL;  
  32.     const char* niceName = NULL;  
  33.     const char* className = NULL;  
  34.     while (i < argc) {  
  35.         const char* arg = argv[i++];  
  36.         if (!parentDir) {  
  37.             parentDir = arg;    // parentDir = /system/bin  
  38.         } else if (strcmp(arg, "--zygote") == 0) {  
  39.             zygote = true;      // zygote确实也为true  
  40.             niceName = "zygote";  
  41.         } else if (strcmp(arg, "--start-system-server") == 0) {  
  42.             startSystemServer = true;   // 为true  
  43.         } else if (strcmp(arg, "--application") == 0) {  
  44.             application = true;  
  45.         } else if (strncmp(arg, "--nice-name=", 12) == 0) {  
  46.             niceName = arg + 12;  
  47.         } else {  
  48.             className = arg;  
  49.             break;  
  50.         }  
  51.     }  
  52.   
  53.     if (niceName && *niceName) {  
  54.         setArgv0(argv0, niceName);  
  55.         // 通过prctl系统调用把自己的名字改成zygote  
  56.         set_process_name(niceName);  
  57.     }  
  58.   
  59. runtime.mParentDir = parentDir;   
  60.   
  61. if (zygote) {  
  62.     /* 
  63.         调用runtime的start函数,startSystemServer为true 
  64.         参数1:“com.android.internal.os.ZygoteInit” 
  65.         参数2:“start-system-server” 
  66.     */  
  67.         runtime.start("com.android.internal.os.ZygoteInit",  
  68.                 startSystemServer ? "start-system-server" : "");  
  69.     } else if (className) {  
  70.         ……  
  71. }   
  72. ……  
  73. }  

zygote的main函数主要做了两件事情:

1.      app_process通过prctl系统调用把自己的名字改成zygote

2.      AppRuntime通过start函数接着启动system_server


AppRuntime分析

接着来看看AppRuntime的实现。

  1. class AppRuntime : public AndroidRuntime  
  2. {  
  3.     ……  
  4. }  

AppRuntime是继承自AndroidRuntime的,主要重载了onVmCreated、onStarted、onZygoteInit和onExit函数。前面的代码runtime.start(…),这个start函数使用的是基类AndroidRuntime的start,我们来分析一下它。

  1. // 参数1:“com.android.internal.os.ZygoteInit”  
  2. // 参数2:“start-system-server”  
  3. void AndroidRuntime::start(const char* className, const char* options)  
  4. {  
  5. ……  
  6.   
  7.     // 设置环境变量ANDROID_ROOT为"/system"  
  8.     const char* rootDir = getenv("ANDROID_ROOT");  
  9.     if (rootDir == NULL) {  
  10.         rootDir = "/system";  
  11.         if (!hasDir("/system")) {  
  12.             LOG_FATAL("No root directory specified, and /android does not exist.");  
  13.             return;  
  14.         }  
  15.         setenv("ANDROID_ROOT", rootDir, 1);  
  16. }  
  17.   
  18.     /* start the virtual machine */  
  19.     JNIEnv* env;  
  20.     if (startVm(&mJavaVM, &env) != 0) {  
  21.         return;  
  22.     }  
  23. ……  
  24.   
  25.     /* Register android functions. */  
  26.     if (startReg(env) < 0) {  
  27.         ALOGE("Unable to register all android natives\n");  
  28.         return;  
  29.     }  
  30.   
  31.     /* 
  32.      * We want to call main() with a String array with arguments in it. 
  33.      * At present we have two arguments, the class name and an option string. 
  34.      * Create an array to hold them. 
  35.      */  
  36.     jclass stringClass;  
  37.     jobjectArray strArray;  
  38.     jstring classNameStr;  
  39.     jstring optionsStr;  
  40.   
  41.     stringClass = env->FindClass("java/lang/String");  
  42.     assert(stringClass != NULL);  
  43.     strArray = env->NewObjectArray(2, stringClass, NULL);  
  44.     assert(strArray != NULL);  
  45.     classNameStr = env->NewStringUTF(className);  
  46.     assert(classNameStr != NULL);  
  47.     env->SetObjectArrayElement(strArray, 0, classNameStr);  
  48.     optionsStr = env->NewStringUTF(options);  
  49.     env->SetObjectArrayElement(strArray, 1, optionsStr);  
  50.   
  51.     /* 
  52.      * Start VM.  This thread becomes the main thread of the VM, and will 
  53.      * not return until the VM exits. 
  54.      */  
  55.     /* 
  56.         className本身为com.android.internal.os.ZygoteInit 
  57.         toSlashClassName函数将className的.转换成为/,于是 
  58.         转换之后为:com/android/internal/os/ZygoteInit 
  59. */  
  60.     char* slashClassName = toSlashClassName(className);  
  61.     jclass startClass = env->FindClass(slashClassName);  
  62.     if (startClass == NULL) {  
  63.         ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);  
  64.         /* keep going */  
  65. else {  
  66.     // 找到ZygoteInit类的main函数  
  67.         jmethodID startMeth = env->GetStaticMethodID(startClass, "main",  
  68.             "([Ljava/lang/String;)V");  
  69.         if (startMeth == NULL) {  
  70.             ALOGE("JavaVM unable to find main() in '%s'\n", className);  
  71.             /* keep going */  
  72.         } else {  
  73.         /* 
  74. 调用ZygoteInit类的main函数,此时将转到java世界开始执行 
  75. 所以zygote进程相当于开创java世界的盘古 
  76.         */  
  77.             env->CallStaticVoidMethod(startClass, startMeth, strArray);  
  78.   
  79. #if 0  
  80.             if (env->ExceptionCheck())  
  81.                 threadExitUncaughtException(env);  
  82. #endif  
  83.         }  
  84.     }  
  85.     free(slashClassName);  
  86.   
  87.     ALOGD("Shutting down VM\n");  
  88.     if (mJavaVM->DetachCurrentThread() != JNI_OK)  
  89.         ALOGW("Warning: unable to detach main thread\n");  
  90.     if (mJavaVM->DestroyJavaVM() != 0)  
  91.         ALOGW("Warning: VM did not shut down cleanly\n");  
  92. }  

上面的代码逻辑不难,但是要从native层进入到java层开始执行需要煞费一番苦心,我们一一来分析。


创建虚拟机 - startVm
  1. int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)  
  2. {  
  3. ……  
  4.     property_get("dalvik.vm.checkjni", propBuf, "");  
  5.     if (strcmp(propBuf, "true") == 0) {  
  6.         checkJni = true;  
  7.     } else if (strcmp(propBuf, "false") != 0) {  
  8.         /* property is neither true nor false; fall back on kernel parameter */  
  9.         property_get("ro.kernel.android.checkjni", propBuf, "");  
  10.         if (propBuf[0] == '1') {  
  11.             checkJni = true;  
  12.         }  
  13.     }  
  14.   
  15.    …..  
  16.   
  17.     /* 
  18.      * The default starting and maximum size of the heap.  Larger 
  19.      * values should be specified in a product property override. 
  20.      */  
  21.     strcpy(heapstartsizeOptsBuf, "-Xms");  
  22.     property_get("dalvik.vm.heapstartsize", heapstartsizeOptsBuf+4, "4m");  
  23.     opt.optionString = heapstartsizeOptsBuf;  
  24.     mOptions.add(opt);  
  25.     strcpy(heapsizeOptsBuf, "-Xmx");  
  26.     property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");  
  27.     opt.optionString = heapsizeOptsBuf;  
  28.     mOptions.add(opt);  
  29.   
  30.     // Increase the main thread's interpreter stack size for bug 6315322.  
  31.     opt.optionString = "-XX:mainThreadStackSize=24K";  
  32.     mOptions.add(opt);  
  33.   
  34.     ……  
  35.   
  36.     /* 
  37.      * Initialize the VM. 
  38.      * 
  39.      * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread. 
  40.      * If this call succeeds, the VM is ready, and we can start issuing 
  41.      * JNI calls. 
  42.      */  
  43.     if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {  
  44.         ALOGE("JNI_CreateJavaVM failed\n");  
  45.         goto bail;  
  46.     }  
  47.   
  48.     result = 0;  
  49.   
  50. bail:  
  51.     free(stackTraceFile);  
  52.     return result;  
  53. }  

这个函数主要是根据init进程初始化的时候解析的属性配置文件得到的数据来进行初始化VM虚拟机,包括设置jni check、heap size等等属性。最后,通过JNI_CreateJavaVM函数创建虚拟机。代码注释中写的也很清楚了,返回值pJavaVM一般是针对整个进程的,而pEnv是针对每个线程的。


注册JNI函数– startReg

前面已经调用startVm函数来创建虚拟机,下一步则需要给整个虚拟机注册一些常用的JNI函数。正是因为后续java世界用到的一些函数是采用native方式实现的,所以才需要提前注册这些函数。

  1. /* 
  2.  * Register android native functions with the VM. 
  3.  */  
  4. /*static*/ int AndroidRuntime::startReg(JNIEnv* env)  
  5. {  
  6.     /* 
  7.      * This hook causes all future threads created in this process to be 
  8.      * attached to the JavaVM.  (This needs to go away in favor of JNI 
  9.      * Attach calls.) 
  10.      */  
  11.     androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);  
  12.   
  13.     ALOGV("--- registering native functions ---\n");  
  14.   
  15.     /* 
  16.      * Every "register" function calls one or more things that return 
  17.      * a local reference (e.g. FindClass).  Because we haven't really 
  18.      * started the VM yet, they're all getting stored in the base frame 
  19.      * and never released.  Use Push/Pop to manage the storage. 
  20.      */  
  21.     env->PushLocalFrame(200);  
  22.   
  23.     if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {  
  24.         env->PopLocalFrame(NULL);  
  25.         return -1;  
  26.     }  
  27. env->PopLocalFrame(NULL);  
  28.   
  29.     return 0;  
  30. }  
  31.   
  32. static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)  
  33. {  
  34.     for (size_t i = 0; i < count; i++) {  
  35.         if (array[i].mProc(env) < 0) {  
  36.             return -1;  
  37.         }  
  38.     }  
  39.     return 0;  
  40. }  

上面的代码通过register_jni_procs函数注册JNI函数,其中gRegJNI是一个数组,如下:

  1. static const RegJNIRec gRegJNI[] = {  
  2.     REG_JNI(register_android_debug_JNITest),  
  3.     REG_JNI(register_com_android_internal_os_RuntimeInit),  
  4.     REG_JNI(register_android_os_SystemClock),  
  5.     REG_JNI(register_android_util_EventLog),  
  6.     REG_JNI(register_android_util_Log),  
  7.     REG_JNI(register_android_util_FloatMath),  
  8.     REG_JNI(register_android_text_format_Time),  
  9.     REG_JNI(register_android_content_AssetManager),  
  10. REG_JNI(register_android_content_StringBlock),  
  11. ……  
  12. }  

看第一个例子吧:

  1. int register_android_debug_JNITest(JNIEnv* env)  
  2. {  
  3.     return jniRegisterNativeMethods(env, "android/debug/JNITest",  
  4.         gMethods, NELEM(gMethods));  
  5. }  

其实就是调用jniRegisterNativeMethods函数来注册android.debug.JNITest类的JNI函数。


进入Java世界

虚拟机创建完毕,JNI函数也注册好了,可以说是万事俱备只欠东风了。那么我们来看看,JAVA世界的入口到底在哪里呢?根据前面的分析可知,CallStaticVoidMethod函数最终会调用com.android.internal.os.ZygoteInit类的main函数,下面就来看看这个入口函数吧。

  1. public static void main(String argv[]) {  
  2.         try {  
  3.             // Start profiling the zygote initialization.  
  4.             SamplingProfilerIntegration.start();  
  5.             // 注册zygote用的socket  
  6.             registerZygoteSocket();  
  7.             // 预加载资源和类  
  8.             preload();  
  9.   
  10.             // Finish profiling the zygote initialization.  
  11.             SamplingProfilerIntegration.writeZygoteSnapshot();  
  12.   
  13.             // Do an initial gc to clean up after startup  
  14.             gc();  
  15.   
  16.             // Disable tracing so that forked processes do not inherit stale tracing tags from  
  17.             // Zygote.  
  18.             Trace.setTracingEnabled(false);  
  19.             ……  
  20.   
  21.             if (argv[1].equals("start-system-server")) {  
  22.                 startSystemServer();  
  23.             } else if (!argv[1].equals("")) {  
  24.                 throw new RuntimeException(argv[0] + USAGE_STRING);  
  25.             }  
  26.   
  27.             runSelectLoop();    // 等待事件发生  
  28.   
  29.             closeServerSocket();  
  30.         } catch (MethodAndArgsCaller caller) {  
  31.             caller.run(); // 这个很重要,后面会分析到  
  32.         } catch (RuntimeException ex) {  
  33.             Log.e(TAG, "Zygote died with exception", ex);  
  34.             closeServerSocket();  
  35.             throw ex;  
  36.         }  
  37.     }  

建立IPC通信服务端– registerZygoteSocket
  1. private static void registerZygoteSocket() {  
  2.         if (sServerSocket == null) {  
  3.             int fileDesc;  
  4.             try {  
  5.                 /* 
  6.                         private static final String ANDROID_SOCKET_ENV =  
  7. "ANDROID_SOCKET_zygote"; 
  8.                 */  
  9.                 String env = System.getenv(ANDROID_SOCKET_ENV);  
  10.                 fileDesc = Integer.parseInt(env);  
  11.             } catch (RuntimeException ex) {  
  12.                 throw new RuntimeException(  
  13.                         ANDROID_SOCKET_ENV + " unset or invalid", ex);  
  14.             }  
  15.   
  16.             try {  
  17.                 sServerSocket = new LocalServerSocket(  
  18.                         createFileDescriptor(fileDesc));  
  19.             } catch (IOException ex) {  
  20.                 throw new RuntimeException(  
  21.                         "Error binding to local socket '" + fileDesc + "'", ex);  
  22.             }  
  23.         }  

从环境变量中获得名为“ANDROID_SOCKET_zygote”的值作为socket的fd,那么这个ANDROID_SOCKET_zygote环境变量又是什么时候设置的呢?

还记得在init进程初始化的时候会去解析init.rc的service服务,并且最后会调用service_start去启动服务。那么service_start函数其中有如下一段代码,用来创建通信用的socket fd:

  1. for (si = svc->sockets; si; si = si->next) {  
  2.     int socket_type = (  
  3.             !strcmp(si->type, "stream") ? SOCK_STREAM :  
  4.                 (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));  
  5.     /* 
  6. create_socket其实就是往ANDROID_SOCKET_DIR中创建了一个文件,zygote进程为 
  7. /dev/socket/zygote,并返回文件fd 
  8.     */  
  9.     int s = create_socket(si->name, socket_type,  
  10.                           si->perm, si->uid, si->gid);  
  11. if (s >= 0) {  
  12.     // zygote服务的si->name即socket名也为zygote  
  13.         publish_socket(si->name, s);  
  14.     }  
  15. }  

其中publish_socket函数就是设置ANDROID_SOCKET_zygote环境变量的地方:

  1. static void publish_socket(const char *name, int fd)  
  2. {  
  3.     /* 
  4.         #define ANDROID_SOCKET_ENV_PREFIX   "ANDROID_SOCKET_" 
  5. #define ANDROID_SOCKET_DIR      "/dev/socket" 
  6.     */  
  7.     char key[64] = ANDROID_SOCKET_ENV_PREFIX;  
  8.     char val[64];  
  9.       
  10.     // 拼接socket的名字,即ANDROID_SOCKET_zygote  
  11.     strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,  
  12.             name,  
  13.             sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));  
  14. snprintf(val, sizeof(val), "%d", fd);  
  15. // 添加socket的fd值到环境变量  
  16.     add_environment(key, val);  
  17.   
  18.     /* make sure we don't close-on-exec */  
  19.     fcntl(fd, F_SETFD, 0);  
  20. }  

知道了ANDROID_SOCKET_ENV的来龙去脉,那么我们接着回过头来看registerZygoteSocket函数,这个函数其实很简单,就是创建了一个服务端的socket,并赋值给全局变量sServerSocket。那么这个服务端的socket具体要接受什么消息,之后又需要处理什么事件呢?我们后面再来看。

预加载类、资源等
  1. static void preload() {  
  2.     preloadClasses();  
  3.     preloadResources();  
  4.     preloadOpenGL();  
  5. }  

先来看看类加载:

  1. private static void preloadClasses() {  
  2.         final VMRuntime runtime = VMRuntime.getRuntime();  
  3.           
  4.         // private static final String PRELOADED_CLASSES = "preloaded-classes";  
  5.         // 预加载类的信息存储在PRELOADED_CLASSES文件中  
  6.         InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(  
  7.                 PRELOADED_CLASSES);  
  8.         if (is == null) {  
  9.             Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");  
  10.         } else {  
  11.             ……  
  12.   
  13.             try {  
  14.                 BufferedReader br  
  15.                     = new BufferedReader(new InputStreamReader(is), 256);  
  16.   
  17.                 int count = 0;  
  18.                 String line;  
  19.                 while ((line = br.readLine()) != null) {  
  20.                     // Skip comments and blank lines.  
  21.                     line = line.trim();  
  22.                     if (line.startsWith("#") || line.equals("")) {  
  23.                         continue;  
  24.                     }  
  25.   
  26.                     try {  
  27.                         ……  
  28.                         // 通过Java反射来加载类,line为类名  
  29.                         Class.forName(line);  
  30.                         ……  
  31.                         count++;  
  32.                     } catch (ClassNotFoundException e) {  
  33.                         Log.w(TAG, "Class not found for preloading: " + line);  
  34.                     } catch (Throwable t) {  
  35.                         ……  
  36.                     }  
  37.                 }  
  38.             } catch (IOException e) {  
  39.                 Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);  
  40.             } finally {  
  41.                 ……  
  42.             }  
  43.         }  
  44. }  

函数比较简单,就是读取preloaded-classes文件的内容,以行为单位。preloaded-classes文件的内容如下:

  1. # Classes which are preloaded by com.android.internal.os.ZygoteInit.  
  2. # Automatically generated by frameworks/base/tools/preload/WritePreloadedClassFile.java.  
  3. # MIN_LOAD_TIME_MICROS=1250  
  4. # MIN_PROCESSES=10  
  5. android.R$styleable  
  6. android.accounts.Account  
  7. android.accounts.Account$1  
  8. android.accounts.AccountManager  
  9. android.accounts.AccountManager$12  
  10. android.accounts.AccountManager$13  
  11. android.accounts.AccountManager$6  
  12. android.accounts.AccountManager$AmsTask  
  13. android.accounts.AccountManager$AmsTask$1  
  14. android.accounts.AccountManager$AmsTask$Response  
  15. android.accounts.AccountManagerFuture  
  16. android.accounts.IaccountManager  
  17. ……  
  18. // 省略N行  

preloaded-classes这个文件主要由frameworks\base\tools\preload工具自动生成的,工具会判断每个类加载的时间是否大于1250微妙,超过这个时间就会被写到preloaded-classes文件中,最后由zygote来预加载。它总共有1000多行的类,可见Zygote进程初始化的时候任务还是很繁重的,这也是导致Android系统启动慢的原因之一。

preloadResources和preloadOpenGL我也就不多做解释了,大体处理都差不多。


启动system_server
  1. /** 
  2.      * Prepare the arguments and fork for the system server process. 
  3.      */  
  4.     private static boolean startSystemServer()  
  5.             throws MethodAndArgsCaller, RuntimeException {  
  6.         long capabilities = posixCapabilitiesAsBits(  
  7.             OsConstants.CAP_KILL,  
  8.             OsConstants.CAP_NET_ADMIN,  
  9.             OsConstants.CAP_NET_BIND_SERVICE,  
  10.             OsConstants.CAP_NET_BROADCAST,  
  11.             OsConstants.CAP_NET_RAW,  
  12.             OsConstants.CAP_SYS_MODULE,  
  13.             OsConstants.CAP_SYS_NICE,  
  14.             OsConstants.CAP_SYS_RESOURCE,  
  15.             OsConstants.CAP_SYS_TIME,  
  16.             OsConstants.CAP_SYS_TTY_CONFIG  
  17.         );  
  18.         /* Hardcoded command line to start the system server */  
  19.         String args[] = {  
  20.             "--setuid=1000",    // #define AID_SYSTEM  1000  
  21.             "--setgid=1000",    // 1000 是系统属性  
  22.             "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",  
  23.             "--capabilities=" + capabilities + "," + capabilities,  
  24.             "--runtime-init",  
  25.             "--nice-name=system_server",    // 进程名为system_server  
  26.             "com.android.server.SystemServer",  // 类名  
  27.         };  
  28.         ZygoteConnection.Arguments parsedArgs = null;  
  29.   
  30.         int pid;  
  31.   
  32.         try {  
  33.             parsedArgs = new ZygoteConnection.Arguments(args);  
  34.             ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);  
  35.             ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);  
  36.   
  37.             /*  
  38.                 进程启动参数都已经在上面硬编码了 
  39.                 最后调用fork启动system_server进程 
  40.  */  
  41.             pid = Zygote.forkSystemServer(  
  42.                     parsedArgs.uid, parsedArgs.gid,  
  43.                     parsedArgs.gids,  
  44.                     parsedArgs.debugFlags,  
  45.                     null,  
  46.                     parsedArgs.permittedCapabilities,  
  47.                     parsedArgs.effectiveCapabilities);  
  48.         } catch (IllegalArgumentException ex) {  
  49.             throw new RuntimeException(ex);  
  50.         }  
  51.   
  52.         /* For child process */  
  53.         if (pid == 0) {  
  54.             // 子进程处理消息  
  55.             handleSystemServerProcess(parsedArgs);  
  56.         }  
  57.   
  58.         return true;  
  59. }  

系统初始化到这里之后,系统中已经有3个进程了,最开始的init,zygote和zygote分裂出来的system_server。system_server部门我们以后再看,接着看zygote的执行。


zygote等待请求– runSelectLoop
  1. private static void runSelectLoop() throws MethodAndArgsCaller {  
  2.         ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();  
  3.         ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();  
  4.         FileDescriptor[] fdArray = new FileDescriptor[4];  
  5.       
  6.         // sServerSocket是之前在registerZygoteSocket创建的服务端socket  
  7.         fds.add(sServerSocket.getFileDescriptor());  
  8.         peers.add(null);  
  9.   
  10.         int loopCount = GC_LOOP_COUNT;  
  11.         while (true) {  
  12.             int index;  
  13.   
  14.             /* 
  15.              * Call gc() before we block in select(). 
  16.              * It's work that has to be done anyway, and it's better 
  17.              * to avoid making every child do it.  It will also 
  18.              * madvise() any free memory as a side-effect. 
  19.              * 
  20.              * Don't call it every time, because walking the entire 
  21.              * heap is a lot of overhead to free a few hundred bytes. 
  22.              */  
  23.             if (loopCount <= 0) {  
  24.                 gc();  
  25.                 loopCount = GC_LOOP_COUNT;  
  26.             } else {  
  27.                 loopCount--;  
  28.             }  
  29.   
  30.             try {  
  31.                 fdArray = fds.toArray(fdArray);  
  32.                 /* 
  33. selectReadable是一个native函数,内部调用select等待客户端 
  34.                     的连接,客户端连接上之后就会返回。 
  35.                     返回值: 
  36.                     <0:  内部发生错误 
  37.                     =0: 该客户端第一次连接到服务端 
  38.                     >0:  客户端与服务端已经建立连接,并开始发送数据 
  39.                 */  
  40.                 index = selectReadable(fdArray);  
  41.             } catch (IOException ex) {  
  42.                 throw new RuntimeException("Error in select()", ex);  
  43.             }  
  44.   
  45.             if (index < 0) {  
  46.                 throw new RuntimeException("Error in select()");  
  47.             } else if (index == 0) {  
  48.                 /* 
  49. 返回0,表明该客户端第一次请求服务端,服务端调用accept与客户 
  50. 端建立连接。客户端在zygote中以ZygoteConnection对象表示。 
  51.                 */  
  52.                 ZygoteConnection newPeer = acceptCommandPeer();  
  53.                 peers.add(newPeer);  
  54.                 fds.add(newPeer.getFileDesciptor());  
  55.             } else {  
  56.                 boolean done;  
  57.                 /* 
  58.                     返回>0,表明发送数据的客户端的index,peers.get(index)取得 
  59.                     发送数据客户端的ZygoteConnection对象,之后调用runOnce 
  60.                     函数处理具体的请求。 
  61.                 */  
  62.                 done = peers.get(index).runOnce();  
  63.                 // 请求处理完成之后,移除与该客户端的连接  
  64.                 if (done) {  
  65.                     peers.remove(index);  
  66.                     fds.remove(index);  
  67.                 }  
  68.             }  
  69.         }  
  70. }  

runSelectLoop函数的逻辑比较简单,主要有两点

1、  处理客户端的连接和请求。其中客户端在zygote进程中使用ZygoteConnection对象表示。

2、  客户的请求有ZygoteConnection的runOnce来处理。


Zygote总结

Zygote是在android系统中创建java世界的盘古,它创建了第一个java虚拟机。同时,它又是女娲,它成功的繁殖了framework的核心system_server进程。主要步骤如下:

1、  创建AppRuntime对象,并调用其start函数。之后zygote的核心初始化都由AppRuntime中。

2、  调用startVm创建java虚拟机,然后调用startReg来注册JNI函数。

3、  通过JNI调用com.android.internal.os.ZygoteInit类的main函数,从此进入了java世界。

4、  调用registerZygoteSocket创建可以响应子孙后代请求的socket。同时,zygote调用preload函数预加载了常用的类、资源等,为java世界添砖加瓦。

5、  调用startSystemServer函数分裂了一个子进程system_server来为java世界服务。

6、  Zygote完成了java世界的初创工作,便调用runSelectLoop来让自己沉沉的睡去。之后,如果收到子孙后代的请求,它便会醒来为他们工作。


转自:http://blog.youkuaiyun.com/hu3167343/article/details/38370993



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值