zoukankan      html  css  js  c++  java
  • Android系统进程Zygote启动过程的源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6768304

    在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育 (fork)出来的,这也许就是为什么要把它称为Zygote(受精卵)的原因吧。由于Zygote进程在Android系统中有着如此重要的地位,本文 将详细分析它的启动过程。

            在前面一篇文章Android应用程序进程启动过程的源代码分析中,我们看到了,当ActivityManagerService启动一个应用程序的时候,就会通过Socket与Zygote进程进行通信,请求它fork一个子进程出来作为这个即将要启动的应用程序的进程;在前面两篇文章Android应用程序安装过程源代码分析Android系统默认Home应用程序(Launcher)的启动过程源代码分析中, 我们又看到了,系统中的两个重要服务PackageManagerService和ActivityManagerService,都是由 SystemServer进程来负责启动的,而SystemServer进程本身是Zygote进程在启动的过程中fork出来的。

            我们知道,Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或 者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。在系统启动脚本system/core /rootdir/init.rc文件中,我们可以看到启动Zygote进程的脚本命令:

    1. service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server  
    2.     socket zygote stream 666  
    3.     onrestart write /sys/android_power/request_state wake  
    4.     onrestart write /sys/power/state on  
    5.     onrestart restart media  
    6.     onrestart restart netd  

            前面的关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。

            接下来的socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以在/dev /socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来作本地进程间通信用的,具体可以参考前面一篇文章Android学习启动篇提到的一书《Linux内核源代码情景分析》的第七章--基于socket的进程间通信。前面我们说到的ActivityManagerService就是通这个socket来和zygote进程通信请求fork一个应用程序进程的了。

            最后的一系列onrestart关键字表示这个zygote进程重启时需要执行的命令。

            关于init.rc文件的更多信息,请参考system/core/init/readme.txt文件。

            了解了这个信息之后,我们就知道Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于 frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。在继续分析Zygote进程 启动的过程之前,我们先来看看它的启动序列图:

            下面我们就详细分析每一个步骤。

            Step 1. app_process.main

            这个函数定义在frameworks/base/cmds/app_process/app_main.cpp文件中:

    1. int main(int argc, const char* const argv[])  
    2. {  
    3.     // These are global variables in ProcessState.cpp  
    4.     mArgC = argc;  
    5.     mArgV = argv;  
    6.   
    7.     mArgLen = 0;  
    8.     for (int i=0; i<argc; i++) {  
    9.         mArgLen += strlen(argv[i]) + 1;  
    10.     }  
    11.     mArgLen--;  
    12.   
    13.     AppRuntime runtime;  
    14.     const char *arg;  
    15.     argv0 = argv[0];  
    16.   
    17.     // Process command line arguments  
    18.     // ignore argv[0]  
    19.     argc--;  
    20.     argv++;  
    21.   
    22.     // Everything up to '--' or first non '-' arg goes to the vm  
    23.   
    24.     int i = runtime.addVmArguments(argc, argv);  
    25.   
    26.     // Next arg is parent directory  
    27.     if (i < argc) {  
    28.         runtime.mParentDir = argv[i++];  
    29.     }  
    30.   
    31.     // Next arg is startup classname or "--zygote"  
    32.     if (i < argc) {  
    33.         arg = argv[i++];  
    34.         if (0 == strcmp("--zygote", arg)) {  
    35.             bool startSystemServer = (i < argc) ?  
    36.                 strcmp(argv[i], "--start-system-server") == 0 : false;  
    37.             setArgv0(argv0, "zygote");  
    38.             set_process_name("zygote");  
    39.             runtime.start("com.android.internal.os.ZygoteInit",  
    40.                 startSystemServer);  
    41.         } else {  
    42.             set_process_name(argv0);  
    43.   
    44.             runtime.mClassName = arg;  
    45.   
    46.             // Remainder of args get passed to startup class main()  
    47.             runtime.mArgC = argc-i;  
    48.             runtime.mArgV = argv+i;  
    49.   
    50.             LOGV("App process is starting with pid=%d, class=%s. ",  
    51.                 getpid(), runtime.getClassName());  
    52.             runtime.start();  
    53.         }  
    54.     } else {  
    55.         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");  
    56.         fprintf(stderr, "Error: no class name or --zygote supplied. ");  
    57.         app_usage();  
    58.         return 10;  
    59.     }  
    60.   
    61. }  

            这个函数的主要作用就是创建一个AppRuntime变量,然后调用它的start成员函数。AppRuntime这个类我们在Android应用程序进程启动过程的源代码分析一文中已经有过介绍了,它同样是在frameworks/base/cmds/app_process/app_main.cpp文件中定义:

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

            它约继承于AndroidRuntime类, AndroidRuntime类定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:

    1. ......  
    2.   
    3. static AndroidRuntime* gCurRuntime = NULL;  
    4.   
    5. ......  
    6.   
    7. AndroidRuntime::AndroidRuntime()  
    8. {  
    9.     ......  
    10.   
    11.     assert(gCurRuntime == NULL);        // one per process  
    12.     gCurRuntime = this;  
    13. }  

            当AppRuntime对象创建时,会调用其父类AndroidRuntime的构造函数,而在AndroidRuntime类的构造函数里面,会将 this指针保存在静态全局变量gCurRuntime中,这样,当其它地方需要使用这个AppRuntime对象时,就可以通过同一个文件中的这个函数 来获取这个对象的指针:

    1. AndroidRuntime* AndroidRuntime::getRuntime()  
    2. {  
    3.     return gCurRuntime;  
    4. }  

            回到上面的main函数中,由于我们在init.rc文件中,设置了app_process启动参数--zygote和--start-system-server,因此,在main函数里面,最终会执行下面语句:

    1. runtime.start("com.android.internal.os.ZygoteInit",  
    2. rtSystemServer);  

            这里的参数startSystemServer为true,表示要启动SystemServer组件。由于AppRuntime没有实现自己的 start函数,它继承了父类AndroidRuntime的start函数,因此,下面会执行AndroidRuntime类的start函数。

            Step 2. AndroidRuntime.start

            这个函数定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:

    1. /* 
    2. * Start the Android runtime.  This involves starting the virtual machine 
    3. * and calling the "static void main(String[] args)" method in the class 
    4. * named by "className". 
    5. */  
    6. void AndroidRuntime::start(const char* className, const bool startSystemServer)  
    7. {  
    8.     ......  
    9.   
    10.     char* slashClassName = NULL;  
    11.     char* cp;  
    12.     JNIEnv* env;  
    13.   
    14.     ......  
    15.   
    16.     /* start the virtual machine */  
    17.     if (startVm(&mJavaVM, &env) != 0)  
    18.         goto bail;  
    19.   
    20.     /* 
    21.     * Register android functions. 
    22.     */  
    23.     if (startReg(env) < 0) {  
    24.         LOGE("Unable to register all android natives ");  
    25.         goto bail;  
    26.     }  
    27.   
    28.     /* 
    29.     * We want to call main() with a String array with arguments in it. 
    30.     * At present we only have one argument, the class name.  Create an 
    31.     * array to hold it. 
    32.     */  
    33.     jclass stringClass;  
    34.     jobjectArray strArray;  
    35.     jstring classNameStr;  
    36.     jstring startSystemServerStr;  
    37.     stringClass = env->FindClass("java/lang/String");  
    38.     assert(stringClass != NULL);  
    39.     strArray = env->NewObjectArray(2, stringClass, NULL);  
    40.     assert(strArray != NULL);  
    41.     classNameStr = env->NewStringUTF(className);  
    42.     assert(classNameStr != NULL);  
    43.     env->SetObjectArrayElement(strArray, 0, classNameStr);  
    44.     startSystemServerStr = env->NewStringUTF(startSystemServer ?  
    45.         "true" : "false");  
    46.     env->SetObjectArrayElement(strArray, 1, startSystemServerStr);  
    47.   
    48.     /* 
    49.     * Start VM.  This thread becomes the main thread of the VM, and will 
    50.     * not return until the VM exits. 
    51.     */  
    52.     jclass startClass;  
    53.     jmethodID startMeth;  
    54.   
    55.     slashClassName = strdup(className);  
    56.     for (cp = slashClassName; *cp != ''; cp++)  
    57.         if (*cp == '.')  
    58.             *cp = '/';  
    59.   
    60.     startClass = env->FindClass(slashClassName);  
    61.     if (startClass == NULL) {  
    62.         ......  
    63.     } else {  
    64.         startMeth = env->GetStaticMethodID(startClass, "main",  
    65.             "([Ljava/lang/String;)V");  
    66.         if (startMeth == NULL) {  
    67.             ......  
    68.         } else {  
    69.             env->CallStaticVoidMethod(startClass, startMeth, strArray);  
    70.             ......  
    71.         }  
    72.     }  
    73.   
    74.     ......  
    75. }  

            这个函数的作用是启动Android系统运行时库,它主要做了三件事情,一是调用函数startVM启动虚拟机,二是调用函数startReg注册 JNI方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。

            Step 3. ZygoteInit.main

            这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

    1. public class ZygoteInit {  
    2.     ......  
    3.   
    4.     public static void main(String argv[]) {  
    5.         try {  
    6.             ......  
    7.   
    8.             registerZygoteSocket();  
    9.               
    10.             ......  
    11.   
    12.             ......  
    13.   
    14.             if (argv[1].equals("true")) {  
    15.                 startSystemServer();  
    16.             } else if (!argv[1].equals("false")) {  
    17.                 ......  
    18.             }  
    19.   
    20.             ......  
    21.   
    22.             if (ZYGOTE_FORK_MODE) {  
    23.                 ......  
    24.             } else {  
    25.                 runSelectLoopMode();  
    26.             }  
    27.   
    28.             ......  
    29.         } catch (MethodAndArgsCaller caller) {  
    30.             ......  
    31.         } catch (RuntimeException ex) {  
    32.             ......  
    33.         }  
    34.     }  
    35.   
    36.     ......  
    37. }  

             它主要作了三件事情,一个调用registerZygoteSocket函数创建了一个socket接口,用来和 ActivityManagerService通讯,二是调用startSystemServer函数来启动SystemServer组件,三是调用 runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的 应用程序进程。

             Step 4. ZygoteInit.registerZygoteSocket

             这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

    1. public class ZygoteInit {  
    2.     ......  
    3.   
    4.     /** 
    5.     * Registers a server socket for zygote command connections 
    6.     * 
    7.     * @throws RuntimeException when open fails 
    8.     */  
    9.     private static void registerZygoteSocket() {  
    10.         if (sServerSocket == null) {  
    11.             int fileDesc;  
    12.             try {  
    13.                 String env = System.getenv(ANDROID_SOCKET_ENV);  
    14.                 fileDesc = Integer.parseInt(env);  
    15.             } catch (RuntimeException ex) {  
    16.                 ......  
    17.             }  
    18.   
    19.             try {  
    20.                 sServerSocket = new LocalServerSocket(  
    21.                     createFileDescriptor(fileDesc));  
    22.             } catch (IOException ex) {  
    23.                 .......  
    24.             }  
    25.         }  
    26.     }  
    27.           
    28.     ......  
    29. }  

             这个socket接口是通过文件描述符来创建的,这个文件描符代表的就是我们前面说的/dev/socket/zygote文件了。这个文件描述符是通过环境变量ANDROID_SOCKET_ENV得到的,它定义为:

    1. public class ZygoteInit {  
    2.     ......  
    3.   
    4.     private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";  
    5.           
    6.     ......  
    7. }  

            那么,这个环境变量的值又是由谁来设置的呢?我们知道,系统启动脚本文件system/core/rootdir/init.rc是由init进程来解 释执行的,而init进程的源代码位于system/core/init目录中,在init.c文件中,是由service_start函数来解释 init.rc文件中的service命令的:

    1. void service_start(struct service *svc, const char *dynamic_args)  
    2. {  
    3.     ......  
    4.   
    5.     pid_t pid;  
    6.   
    7.     ......  
    8.   
    9.     pid = fork();  
    10.   
    11.     if (pid == 0) {  
    12.         struct socketinfo *si;  
    13.   
    14.         ......  
    15.   
    16.         for (si = svc->sockets; si; si = si->next) {  
    17.             int socket_type = (  
    18.                 !strcmp(si->type, "stream") ? SOCK_STREAM :  
    19.                 (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));  
    20.             int s = create_socket(si->name, socket_type,  
    21.                 si->perm, si->uid, si->gid);  
    22.             if (s >= 0) {  
    23.                 publish_socket(si->name, s);  
    24.             }  
    25.         }  
    26.   
    27.         ......  
    28.     }  
    29.   
    30.     ......  
    31. }  

            每一个service命令都会促使init进程调用fork函数来创建一个新的进程,在新的进程里面,会分析里面的socket选项,对于每一个 socket选项,都会通过create_socket函数来在/dev/socket目录下创建一个文件,在这个场景中,这个文件便是zygote了, 然后得到的文件描述符通过publish_socket函数写入到环境变量中去:

    1. static void publish_socket(const char *name, int fd)  
    2. {  
    3.     char key[64] = ANDROID_SOCKET_ENV_PREFIX;  
    4.     char val[64];  
    5.   
    6.     strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,  
    7.             name,  
    8.             sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));  
    9.     snprintf(val, sizeof(val), "%d", fd);  
    10.     add_environment(key, val);  
    11.   
    12.     /* make sure we don't close-on-exec */  
    13.     fcntl(fd, F_SETFD, 0);  
    14. }  

           这里传进来的参数name值为"zygote",而ANDROID_SOCKET_ENV_PREFIX在system/core/include/cutils/sockets.h定义为:

    1. #define ANDROID_SOCKET_ENV_PREFIX   "ANDROID_SOCKET_"  

            因此,这里就把上面得到的文件描述符写入到以"ANDROID_SOCKET_zygote"为key值的环境变量中。又因为上面的 ZygoteInit.registerZygoteSocket函数与这里创建socket文件的create_socket函数是运行在同一个进程 中,因此,上面的ZygoteInit.registerZygoteSocket函数可以直接使用这个文件描述符来创建一个Java层的 LocalServerSocket对象。如果其它进程也需要打开这个/dev/socket/zygote文件来和Zygote进程进行通信,那就必须 要通过文件名来连接这个LocalServerSocket了,参考Android应用程序进程启动过程的源代码分析一 文中的Step 4,ActivityManagerService是通过Process.start函数来创建一个新的进程的,而Process.start函数会首先 通过Socket连接到Zygote进程中,最终由Zygote进程来完成创建新的应用程序进程,而Process类是通过 openZygoteSocketIfNeeded函数来连接到Zygote进程中的Socket的:

    1. public class Process {    
    2.     ......    
    3.    
    4.     private static void openZygoteSocketIfNeeded()    
    5.             throws ZygoteStartFailedEx {    
    6.   
    7.         ......  
    8.   
    9.         for (int retry = 0    
    10.             ; (sZygoteSocket == null) && (retry < (retryCount + 1))    
    11.             ; retry++ ) {    
    12.   
    13.                 ......  
    14.   
    15.                 try {    
    16.                     sZygoteSocket = new LocalSocket();    
    17.                     sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,    
    18.                         LocalSocketAddress.Namespace.RESERVED));    
    19.   
    20.                     sZygoteInputStream    
    21.                         = new DataInputStream(sZygoteSocket.getInputStream());    
    22.   
    23.                     sZygoteWriter =    
    24.                         new BufferedWriter(    
    25.                         new OutputStreamWriter(    
    26.                         sZygoteSocket.getOutputStream()),    
    27.                         256);    
    28.   
    29.                     ......    
    30.                 } catch (IOException ex) {    
    31.                     ......    
    32.                 }    
    33.         }    
    34.   
    35.         ......    
    36.     }    
    37.   
    38.     ......    
    39. }  

            这里的ZYGOTE_SOCKET定义为:

    1. public class Process {    
    2.     ......    
    3.    
    4.     private static final String ZYGOTE_SOCKET = "zygote";    
    5.   
    6.     ......    
    7. }   

            它刚好就是对应/dev/socket目录下的zygote文件了。

            Android系统中的socket机制和binder机制一样,都是可以用来进行进程间通信,读者可以自己对比一下这两者的不同之处,Binder进程间通信机制可以参考Android进程间通信(IPC)机制Binder简要介绍和学习计划一文。

           Socket对象创建完成之后,回到Step 3中的ZygoteInit.main函数中,startSystemServer函数来启动SystemServer组件。

           Step 5. ZygoteInit.startSystemServer
           这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

    1. public class ZygoteInit {  
    2.     ......  
    3.   
    4.     private static boolean startSystemServer()  
    5.             throws MethodAndArgsCaller, RuntimeException {  
    6.         /* Hardcoded command line to start the system server */  
    7.         String args[] = {  
    8.             "--setuid=1000",  
    9.             "--setgid=1000",  
    10.             "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",  
    11.             "--capabilities=130104352,130104352",  
    12.             "--runtime-init",  
    13.             "--nice-name=system_server",  
    14.             "com.android.server.SystemServer",  
    15.         };  
    16.         ZygoteConnection.Arguments parsedArgs = null;  
    17.   
    18.         int pid;  
    19.   
    20.         try {  
    21.             parsedArgs = new ZygoteConnection.Arguments(args);  
    22.   
    23.             ......  
    24.   
    25.             /* Request to fork the system server process */  
    26.             pid = Zygote.forkSystemServer(  
    27.                 parsedArgs.uid, parsedArgs.gid,  
    28.                 parsedArgs.gids, debugFlags, null,  
    29.                 parsedArgs.permittedCapabilities,  
    30.                 parsedArgs.effectiveCapabilities);  
    31.         } catch (IllegalArgumentException ex) {  
    32.             ......  
    33.         }  
    34.   
    35.         /* For child process */  
    36.         if (pid == 0) {  
    37.             handleSystemServerProcess(parsedArgs);  
    38.         }  
    39.   
    40.         return true;  
    41.     }  
    42.       
    43.     ......  
    44. }  

            这里我们可以看到,Zygote进程通过Zygote.forkSystemServer函数来创建一个新的进程来启动SystemServer组件, 返回值pid等0的地方就是新的进程要执行的路径,即新创建的进程会执行handleSystemServerProcess函数。

            Step 6. ZygoteInit.handleSystemServerProcess
            这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

    1. public class ZygoteInit {  
    2.     ......  
    3.   
    4.     private static void handleSystemServerProcess(  
    5.             ZygoteConnection.Arguments parsedArgs)  
    6.             throws ZygoteInit.MethodAndArgsCaller {  
    7.         closeServerSocket();  
    8.   
    9.         /* 
    10.         * Pass the remaining arguments to SystemServer. 
    11.         * "--nice-name=system_server com.android.server.SystemServer" 
    12.         */  
    13.         RuntimeInit.zygoteInit(parsedArgs.remainingArgs);  
    14.         /* should never reach here */  
    15.     }  
    16.   
    17.     ......  
    18. }   

            由于由Zygote进程创建的子进程会继承Zygote进程在前面Step 4中创建的Socket文件描述符,而这里的子进程又不会用到它,因此,这里就调用closeServerSocket函数来关闭它。这个函数接着调用 RuntimeInit.zygoteInit函数来进一步执行启动SystemServer组件的操作。

            Step 7. RuntimeInit.zygoteInit

            这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

    1. public class RuntimeInit {    
    2.     ......    
    3.   
    4.     public static final void zygoteInit(String[] argv)    
    5.             throws ZygoteInit.MethodAndArgsCaller {    
    6.         ......    
    7.     
    8.         zygoteInitNative();    
    9.   
    10.         ......    
    11.   
    12.   
    13.         // Remaining arguments are passed to the start class's static main    
    14.   
    15.         String startClass = argv[curArg++];    
    16.         String[] startArgs = new String[argv.length - curArg];    
    17.   
    18.         System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);    
    19.         invokeStaticMain(startClass, startArgs);    
    20.     }    
    21.   
    22.     ......    
    23. }  

             这个函数会执行两个操作,一个是调用zygoteInitNative函数来执行一个Binder进程间通信机制的初始化工作,这个工作完成之后,这个进 程中的Binder对象就可以方便地进行进程间通信了,另一个是调用上面Step 5传进来的com.android.server.SystemServer类的main函数。

             Step 8. RuntimeInit.zygoteInitNative

             这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

    1. public class RuntimeInit {    
    2.     ......    
    3.   
    4.     public static final native void zygoteInitNative();    
    5.   
    6.     ......    
    7. }  

            这里可以看出,函数zygoteInitNative是一个Native函数,实现在frameworks/base/core/jni/AndroidRuntime.cpp文件中,这里我们就不再细看了,具体可以参考Android应用程序进程启动过程的源代码分析一文的Step 9,完成这一步后,这个进程的Binder进程间通信机制基础设施就准备好了。

            回到Step 7中的RuntimeInit.zygoteInitNative函数,下一步它就要执行com.android.server.SystemServer类的main函数了。

            Step 9. SystemServer.main

            这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中:

    1. public class SystemServer    
    2. {    
    3.     ......    
    4.   
    5.     native public static void init1(String[] args);    
    6.   
    7.     ......    
    8.   
    9.     public static void main(String[] args) {    
    10.         ......    
    11.   
    12.         init1(args);    
    13.   
    14.         ......    
    15.     }   
    16.   
    17.     public static final void init2() {    
    18.         Slog.i(TAG, "Entered the Android system server!");    
    19.         Thread thr = new ServerThread();    
    20.         thr.setName("android.server.ServerThread");    
    21.         thr.start();    
    22.     }    
    23.   
    24.     ......    
    25. }  

            这里的main函数首先会执行JNI方法init1,然后init1会调用这里的init2函数,在init2函数里面,会创建一个ServerThread线程对象来执行一些系统关键服务的启动操作,例如我们在前面两篇文章Android应用程序安装过程源代码分析Android系统默认Home应用程序(Launcher)的启动过程源代码分析中提到的PackageManagerService和ActivityManagerService。
            这一步的具体执行过程可以参考Android应用程序安装过程源代码分析一文,这里就不再详述了。

            这里执行完成后,层层返回,最后回到上面的Step 3中的ZygoteInit.main函数中,接下来它就要调用runSelectLoopMode函数进入一个无限循环在前面Step 4中创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程了。

            Step 10. ZygoteInit.runSelectLoopMode

            这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

    1. public class ZygoteInit {  
    2.     ......  
    3.   
    4.     private static void runSelectLoopMode() throws MethodAndArgsCaller {  
    5.         ArrayList<FileDescriptor> fds = new ArrayList();  
    6.         ArrayList<ZygoteConnection> peers = new ArrayList();  
    7.         FileDescriptor[] fdArray = new FileDescriptor[4];  
    8.   
    9.         fds.add(sServerSocket.getFileDescriptor());  
    10.         peers.add(null);  
    11.   
    12.         int loopCount = GC_LOOP_COUNT;  
    13.         while (true) {  
    14.             int index;  
    15.   
    16.             ......  
    17.   
    18.   
    19.             try {  
    20.                 fdArray = fds.toArray(fdArray);  
    21.                 index = selectReadable(fdArray);  
    22.             } catch (IOException ex) {  
    23.                 throw new RuntimeException("Error in select()", ex);  
    24.             }  
    25.   
    26.             if (index < 0) {  
    27.                 throw new RuntimeException("Error in select()");  
    28.             } else if (index == 0) {  
    29.                 ZygoteConnection newPeer = acceptCommandPeer();  
    30.                 peers.add(newPeer);  
    31.                 fds.add(newPeer.getFileDesciptor());  
    32.             } else {  
    33.                 boolean done;  
    34.                 done = peers.get(index).runOnce();  
    35.   
    36.                 if (done) {  
    37.                     peers.remove(index);  
    38.                     fds.remove(index);  
    39.                 }  
    40.             }  
    41.         }  
    42.     }  
    43.   
    44.     ......  
    45. }        

            这个函数我们已经在Android应用程序进程启动过程的源代码分析一文的Step 5中分析过了,这就是在等待ActivityManagerService来连接这个Socket,然后调用ZygoteConnection.runOnce函数来创建新的应用程序,有兴趣的读者可以参考Android应用程序进程启动过程的源代码分析这篇文章,这里就不再详述了。

            这样,Zygote进程就启动完成了,学习到这里,我们终于都对Android系统中的进程有了一个深刻的认识了,这里总结一下:

            1. 系统启动时init进程会创建Zygote进程,Zygote进程负责后续Android应用程序框架层的其它进程的创建和启动工作。

            2. Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。

            3. 当我们需要启动一个Android应用程序时,ActivityManagerService会通过Socket进程间通信机制,通知Zygote进程为这个应用程序创建一个新的进程。

    老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!

  • 相关阅读:
    Win7+IIS伪静态 UrlRewriter配置
    让VS2010打包工具找回丢失的.net 2.0 .
    高效注册DLL控件 让你的IE浏览器复活
    查询及删除重复记录的方法
    .NET代码模板生成工具CodeSmith 5.0.1 专业版完美版下载
    如何使用CslaGen生成CSLA DAL层代码
    用C# + WebBrowser控件抓取AJAX页面的内容[转]
    了解IIS6应用程序池假死问题解决办法
    美化界面2
    C# WebBrowser高级应用
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4142473.html
Copyright © 2011-2022 走看看