深入解析Android 虚拟机
上QQ阅读APP看书,第一时间看更新

6.7 ART进程管理

ART虚拟机的实现离不开进程管理,其进程管理特别依赖于Linux的进程体系。例如要为应用程序创建一个进程,会使用Linux的FORK机制复制一个进程,因为复制进程的过程比创建进程的效率要高。并且在Linux中进程之间的通信方式有很多,例如管道、信号、报文和共享内存等,这样对进程管理将更加方便。

在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的。当ActivityManagerService启动一个应用程序的时候,就会通过Socket与Zygote进程进行通信,请求它fork一个子进程出来作为这个即将要启动的应用程序的进程。在系统中有两个重要服务:PackageManagerService和ActivityManagerService,都是由SystemServer进程来负责启动的,而SystemServer进程本身是Zygote进程在启动的过程中fork出来的。

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

Zygote本身是一个应用层的程序,和驱动、内核模块没有任何关系。Zygote的启动由Linux的祖先init启动。启动后看到的进程名叫zygote,其最初的名字是app_process,通过直接调用pctrl把名字给改成了“zygote”。

(1)app_process.main函数。

此函数定义在文件“frameworks/base/cmds/app_process/App_main.cpp”中,具体实现代码如下所示:

        int main(int argc, char* const argv[])
        {
        #ifdef __arm__
            /*
            * b/7188322- Temporarily revert to the compat memory layout
            * to avoid breaking third party apps.
            *
            * THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE.
            *
            * http://git.kernel.org/? p=linux/kernel/git/torvalds/linux-2.6.git; a=commitdiff; h=7dbaa466
            * changes the kernel mapping from bottom up to top-down.
            * This breaks some programs which improperly embed
            * an out of date copy of Android's linker.
            */
            char value[PROPERTY_VALUE_MAX];
            property_get("ro.kernel.qemu", value, "");
            bool is_qemu = (strcmp(value, "1") == 0);
            if ((getenv("NO_ADDR_COMPAT_LAYOUT_FIXUP") == NULL) && ! is_qemu) {
                int current = personality(0xFFFFFFFF);
                if ((current & ADDR_COMPAT_LAYOUT) == 0) {
                  personality(current | ADDR_COMPAT_LAYOUT);
                  setenv("NO_ADDR_COMPAT_LAYOUT_FIXUP", "1", 1);
                  execv("/system/bin/app_process", argv);
                  return -1;
                }
            }
            unsetenv("NO_ADDR_COMPAT_LAYOUT_FIXUP");
        #endif
           //These are global variables in ProcessState.cpp
            mArgC = argc;
            mArgV = argv;
            mArgLen = 0;
            for (int i=0; i<argc; i++) {
                mArgLen += strlen(argv[i]) + 1;
            }
            mArgLen--;
            AppRuntime runtime;
            const char* argv0 = argv[0];
           //Process command line arguments
           //ignore argv[0]
            argc--;
            argv++;
           //Everything up to '--' or first non '-' arg goes to the vm
            int i = runtime.addVmArguments(argc, argv);
           //Parse runtime arguments.  Stop at first unrecognized option.
            bool zygote = false;
            bool startSystemServer = false;
            bool application = false;
            const char* parentDir = NULL;
            const char* niceName = NULL;
            const char* className = NULL;
            while (i < argc) {
                const char* arg = argv[i++];
                if (! parentDir) {
                  parentDir = arg;
                } else if (strcmp(arg, "--zygote") == 0) {
                  zygote = true;
                  niceName = "zygote";
                } else if (strcmp(arg, "--start-system-server") == 0) {
                  startSystemServer = true;
                } else if (strcmp(arg, "--application") == 0) {
                  application = true;
                } else if (strncmp(arg, "--nice-name=", 12) == 0) {
                  niceName = arg + 12;
                } else {
                  className = arg;
                  break;
                }
            }
            if (niceName && *niceName) {
                setArgv0(argv0, niceName);
                set_process_name(niceName);
            }
            runtime.mParentDir = parentDir;
            if (zygote) {
                runtime.start("com.android.internal.os.ZygoteInit",
                      startSystemServer ? "start-system-server" : "");
            } else if (className) {
               //Remainder of args get passed to startup class main()
                runtime.mClassName = className;
                runtime.mArgC = argc - i;
                runtime.mArgV = argv + i;
                runtime.start("com.android.internal.os.RuntimeInit",
                      application ? "application" : "tool");
            } 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;
            }
        }

此函数的主要作用就是创建一个AppRuntime变量,然后调用它的start成员函数。runtime是AppRuntime的实例,AppRuntime继承自AndroidRuntime,进入AndroidRuntime类的start函数。函数start在文件“frameworks/base/core/jni/AndroidRuntime.cpp”中定义,具体代码如下所示:

        void AndroidRuntime::start(const char* className, const char* options)
        {
            ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
                  className ! = NULL ? className : "(unknown)");
            /*
            * 'startSystemServer == true' means runtime is obsolete and not run from
            * init.rc anymore, so we print out the boot start event here.
            */
            if (strcmp(options, "start-system-server") == 0) {
              /* track our progress through the boot sequence */
              const int LOG_BOOT_PROGRESS_START = 3000;
              LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
                          ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
            }
            const char* rootDir = getenv("ANDROID_ROOT");
            if (rootDir == NULL) {
              rootDir = "/system";
              if (! hasDir("/system")) {
                  LOG_FATAL("No root directory specified, and /android does not exist.");
                  return;
              }
              setenv("ANDROID_ROOT", rootDir, 1);
            }
            //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
            //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
            /* start the virtual machine */
            JniInvocation jni_invocation;
            jni_invocation.Init(NULL);
            JNIEnv* env;
            if (startVm(&mJavaVM, &env) ! = 0) {
              return;
            }
            onVmCreated(env);
            /*
            * Register android functions.
            */
            if (startReg(env) < 0) {
              ALOGE("Unable to register all android natives\n");
              return;
            }
            /*
             * We want to call main() with a String array with arguments in it.
             * At present we have two arguments, the class name and an option string.
             * Create an array to hold them.
             */
            jclass stringClass;
            jobjectArray strArray;
            jstring classNameStr;
            jstring optionsStr;
            stringClass = env->FindClass("java/lang/String");
            assert(stringClass ! = NULL);
            strArray = env->NewObjectArray(2, stringClass, NULL);
            assert(strArray ! = NULL);
            classNameStr = env->NewStringUTF(className);
            assert(classNameStr ! = NULL);
            env->SetObjectArrayElement(strArray, 0, classNameStr);
            optionsStr = env->NewStringUTF(options);
            env->SetObjectArrayElement(strArray, 1, optionsStr);
            /*
             * Start VM.  This thread becomes the main thread of the VM, and will
             * not return until the VM exits.
             */
            char* slashClassName = toSlashClassName(className);
            jclass startClass = env->FindClass(slashClassName);
            if (startClass == NULL) {
                ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
                /* keep going */
            } else {
                jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
                  "([Ljava/lang/String; )V");
                if (startMeth == NULL) {
                  ALOGE("JavaVM unable to find main() in '%s'\n", className);
                  /* keep going */
                } else {
                  env->CallStaticVoidMethod(startClass, startMeth, strArray);
        #if 0
                  if (env->ExceptionCheck())
                      threadExitUncaughtException(env);
        #endif
                }
            }
            free(slashClassName);
            ALOGD("Shutting down VM\n");
            if (mJavaVM->DetachCurrentThread() ! = JNI_OK)
                ALOGW("Warning: unable to detach main thread\n");
            if (mJavaVM->DestroyJavaVM() ! = 0)
                ALOGW("Warning: VM did not shut down cleanly\n");
        }

此函数的作用是启动Android系统运行时库,它主要做了3件事情:一是调用函数startVM启动虚拟机,二是调用函数startReg注册JNI方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。在上述代码中,还调用了类JniInvocation的Init函数,该函数在文件“libnativehelper/JniInvocation.cpp”中定义,具体实现代码如下所示:

        bool JniInvocation::Init(const char* library) {
        #ifdef HAVE_ANDROID_OS
          char default_library[PROPERTY_VALUE_MAX];
          property_get("persist.sys.dalvik.vm.lib", default_library, "libdvm.so");
        #else
          const char* default_library = "libdvm.so";
        #endif
          if (library == NULL) {
            library = default_library;
          }
        handle_ = dlopen(library, RTLD_NOW);
        if (handle_ == NULL) {
          ALOGE("Failed to dlopen %s: %s", library, dlerror());
          return false;
        }
        if (! FindSymbol(reinterpret_cast<void**>(&JNI_GetDefaultJavaVMInitArgs_),
                    "JNI_GetDefaultJavaVMInitArgs")) {
          return false;
        }
        if (! FindSymbol(reinterpret_cast<void**>(&JNI_CreateJavaVM_),
                    "JNI_CreateJavaVM")) {
          return false;
        }
        if (! FindSymbol(reinterpret_cast<void**>(&JNI_GetCreatedJavaVMs_),
                    "JNI_GetCreatedJavaVMs")) {
          return false;
        }
        return true;
      }

在上述代码中,首先定义了default_library字符数组,然后从属性系统中获得名为persist.sys. dalvik.vm.lib的属性值,默认值为libdvm.so。对于ART环境来说,该值为libart.so。由于参数library为NULL,因此将default_library赋值给library。接下来调用dlopen打开libart.so文件,分别调用FindSymbol函数从打开的libart.so文件中搜索到对应的导出符号,例如JNI_CreateJavaVM对应的是文件“/art/runtime/jni_internal.cc”中的JNI_CreateJavaVM函数,而不是“/dalvik/vm/Jni.cpp”的JNI_CreateJavaVM函数,因为现在打开的是libart.so,这是需要注意的地方。

而在前面的函数AndroidRuntime::start中,调用startVm函数启动虚拟机,该函数最终会调用JNI_CreateJavaVM函数,此处的JNI_ CreateJavaVM函数在文件“/art/runtime/jni_internal.cc”中定义,具体实现代码如下所示:

        extern "C" jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args) {
          const JavaVMInitArgs* args = static_cast<JavaVMInitArgs*>(vm_args);
          if (IsBadJniVersion(args->version)) {
            LOG(ERROR) << "Bad JNI version passed to CreateJavaVM: " << args->version;
            return JNI_EVERSION;
          }
          Runtime::Options options;
          for (int i = 0; i < args->nOptions; ++i) {
            JavaVMOption* option = &args->options[i];
            options.push_back(std::make_pair(std::string(option->optionString), option->extraInfo));
          }
          bool ignore_unrecognized = args->ignoreUnrecognized;
          if (! Runtime::Create(options, ignore_unrecognized)) {
            return JNI_ERR;
          }
          Runtime* runtime = Runtime::Current();
          bool started = runtime->Start();
          if (! started) {
            delete Thread::Current()->GetJniEnv();
            delete runtime->GetJavaVM();
            LOG(WARNING) << "CreateJavaVM failed";
            return JNI_ERR;
          }
          *p_env = Thread::Current()->GetJniEnv();
          *p_vm = runtime->GetJavaVM();
          return JNI_OK;
        }

在上述代码中,首先解析虚拟机启动参数并存入到Runtime::Options实例中。然后根据解析的参数信息调用函数Create创建Runtime的实例,该函数的具体实现代码如下所示:

        1. bool Runtime::Create(const Options& options, bool ignore_unrecognized) {
        2. ......
        3. InitLogging(NULL);
        4. instance_ = new Runtime;
        5. if (! instance_->Init(options, ignore_unrecognized)) {
        6. .....
        7. return false;
        8. }
        9. return true;
        10. }

在上述代码中,第3行初始化Log系统,第4行创建Runtime实例,第7行初始化Runtime。

再次回到JNI_ Create JavaVM函数中,获得Runtime当前实例后,Runtime使用单例模式实现,并调用Start函数,该函数的实现代码如下:

        1. bool Runtime::Start() {
        2. ......
        3. Thread* self = Thread::Current();
        4. self->TransitionFromRunnableToSuspended(kNative);
        5. started_ = true;
        6. InitNativeMethods();
        7. ......
        8. if (is_zygote_) {
        9. if (! InitZygote()) {
        10. return false;
        11. }
        12. } else {
        13. DidForkFromZygote();
        14. }
        15. StartDaemonThreads();
        16. ......
        17. return true;
        18. }

在上述代码中,第3行获得当前运行线程;第4行将该线程状态从Runnable切换到Suspend;第6行完成Native函数的初始化工作,函数InitNativeMethods的实现代码如下所示:

        1. void Runtime::InitNativeMethods() {
        2. .....
        3. JNIEnv* env = self->GetJniEnv();
        4. ......
        5. RegisterRuntimeNativeMethods(env);
        6. ......
        7. }

在上述代码中,第3行获取JNI环境;第5行调用RegisterRuntimeNativeMethods函数完成Native函数的注册,至于注册了哪些Native函数,有兴趣的可以继续跟踪源码。

继续分析Runtime:: Start函数,调用InitZygote完成一些文件文件系统的mount后,会最终通过调用java.lang.Daemons.start()函数启动守护进程。

再看函数ZygoteInit.main,此函数在文件“frameworks/base/core/java/com/android/internal/os/ZygoteInit.java”中定义,具体实现代码如下所示:

        public class ZygoteInit {
          ......
          public static void main(String argv[]) {
          try {
          ......
          registerZygoteSocket();
          ......
          ......
          if (argv[1].equals("true")) {
          startSystemServer();
          } else if (! argv[1].equals("false")) {
          ......
          }
          ......
          if (ZYGOTE_FORK_MODE) {
          ......
          } else {
          runSelectLoopMode();
          }
          ......
          } catch (MethodAndArgsCaller caller) {
          ......
          } catch (RuntimeException ex) {
          ......
          }
          }
          ......
          }

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

再看ZygoteInit.registerZygoteSocket,此函数在文件“frameworks/base/core/java/com/android/internal/os/ZygoteInit.java”中定义,具体实现代码如下所示:

        public class ZygoteInit {
          ......
          /**
          * Registers a server socket for zygote command connections
          *
          * @throws RuntimeException when open fails
          */
          private static void registerZygoteSocket() {
          if (sServerSocket == null) {
          int fileDesc;
          try {
          String env = System.getenv(ANDROID_SOCKET_ENV);
          fileDesc = Integer.parseInt(env);
          } catch (RuntimeException ex) {
          ......
          }
          try {
          sServerSocket = new LocalServerSocket(
          createFileDescriptor(fileDesc));
          } catch (IOException ex) {
          .......
          }
          }
          }
          ......
          }

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

        public class ZygoteInit {
        ......
        private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
        ......
        }

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

        void service_start(struct service *svc, const char *dynamic_args)
         {
         ......
         pid_t pid;
         ......
         pid = fork();
         if (pid == 0) {
         struct socketinfo *si;
         ......
         for (si = svc->sockets; si; si = si->next) {
         int socket_type = (
         !strcmp(si->type, "stream") ? SOCK_STREAM :
         (! strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
         int s = create_socket(si->name, socket_type,
         si->perm, si->uid, si->gid);
         if (s >= 0) {
         publish_socket(si->name, s);
         }
         }
         ......
         }
         ......
         }

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

        static void publish_socket(const char *name, int fd)
          {
          char key[64] = ANDROID_SOCKET_ENV_PREFIX;
          char val[64];
          strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) -1,
          name,
          sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
          snprintf(val, sizeof(val), "%d", fd);
          add_environment(key, val);
          /* make sure we don't close-on-exec */
          fcntl(fd, F_SETFD, 0);
          }

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

        view plain#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了。ActivityManagerService是通过Process.start函数来创建一个新的进程的,而Process.start函数会首先通过Socket连接到Zygote进程中,最终由Zygote进程来完成创建新的应用程序进程,而类Process是通过函数openZygoteSocketIfNeeded来连接到Zygote进程中的Socket的,具体实现代码如下所示:

        public class Process {
          ......
          private static void openZygoteSocketIfNeeded()
          throws ZygoteStartFailedEx {
          ......
          for (int retry = 0
          ; (sZygoteSocket == null) && (retry < (retryCount + 1))
          ; retry++ ) {
          ......
          try {
          sZygoteSocket = new LocalSocket();
          sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
          LocalSocketAddress.Namespace.RESERVED));
          sZygoteInputStream
          = new DataInputStream(sZygoteSocket.getInputStream());
          sZygoteWriter =
          new BufferedWriter(
          new OutputStreamWriter(
          sZygoteSocket.getOutputStream()),
          256);
          ......
          } catch (IOException ex) {
          ......
          }
          }
          ......
          }
          ......
          }

这里的ZYGOTE_SOCKET定义如下。

        public class Process {
          ......
          private static final String ZYGOTE_SOCKET = "zygote";
          ......
          }

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

Android系统中的socket机制和binder机制一样,都是可以用来进行进程间通信。当Socket对象创建完成之后,回到第三步中的ZygoteInit.main函数中,startSystemServer函数来启动SystemServer组件。

(2)ZygoteInit.startSystemServer函数。

此函数在文件“frameworks/base/core/java/com/android/internal/os/ZygoteInit.java”中定义,具体实现代码如下所示:

        public class ZygoteInit {
          ......
          private static boolean startSystemServer()
          throws MethodAndArgsCaller, RuntimeException {
          /* Hardcoded command line to start the system server */
          String args[] = {
          "--setuid=1000",
          "--setgid=1000",
          "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",
          "--capabilities=130104352,130104352",
          "--runtime-init",
          "--nice-name=system_server",
          "com.android.server.SystemServer",
          };
          ZygoteConnection.Arguments parsedArgs = null;
          int pid;
          try {
          parsedArgs = new ZygoteConnection.Arguments(args);
          ......
          /* Request to fork the system server process */
          pid = Zygote.forkSystemServer(
          parsedArgs.uid, parsedArgs.gid,
          parsedArgs.gids, debugFlags, null,
          parsedArgs.permittedCapabilities,
          parsedArgs.effectiveCapabilities);
          } catch (IllegalArgumentException ex) {
          ......
          }
          /* For child process */
          if (pid == 0) {
          handleSystemServerProcess(parsedArgs);
          }
          return true;
          }
          ......
          }

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

(3)ZygoteInit.handleSystemServerProcess函数。

此函数在文件“frameworks/base/core/java/com/android/internal/os/ZygoteInit.java”中定义,具体实现代码如下所示:

        public class ZygoteInit {
          ......
          private static void handleSystemServerProcess(
          ZygoteConnection.Arguments parsedArgs)
          throws ZygoteInit.MethodAndArgsCaller {
          closeServerSocket();
          /*
          * Pass the remaining arguments to SystemServer.
          * "--nice-name=system_server com.android.server.SystemServer"
          */
          RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
          /* should never reach here */
          }
          ......
          }

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

(4)RuntimeInit.zygoteInit函数。

此函数在文件“frameworks/base/core/java/com/android/internal/os/RuntimeInit.java”中定义,具体实现代码如下所示:

        public class RuntimeInit {
          ......
          public static final void zygoteInit(String[] argv)
          throws ZygoteInit.MethodAndArgsCaller {
          ......
          zygoteInitNative();
          ......
         //Remaining arguments are passed to the start class's static main
          String startClass = argv[curArg++];
          String[] startArgs = new String[argv.length - curArg];
          System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
          invokeStaticMain(startClass, startArgs);
          }
          ......
          }

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

(5)RuntimeInit.zygoteInitNative函数。

此函数定义在文件“frameworks/base/core/java/com/android/internal/os/RuntimeInit.java”中,具体实现代码如下所示:

        public class RuntimeInit {
          ......
          public static final native void zygoteInitNative();
          ......
          }

从这里可以看出,函数zygoteInitNative是一个Native函数,实现在文件“frameworks/base/core/jni/AndroidRuntime.cpp”中。完成这一步后,这个进程的Binder进程间通信机制基础设施就准备好了。

回到步骤(7)中的RuntimeInit.zygoteInitNative函数,下一步它就要执行com.android.server.System Server类的main函数了。

(6)SystemServer.main函数。

此函数在文件“frameworks/base/services/java/com/android/server/SystemServer.java”中定义,具体实现代码如下所示:

        public class SystemServer
          {
          ......
          native public static void init1(String[] args);
          ......
          public static void main(String[] args) {
          ......
          init1(args);
          ......
          }
          public static final void init2() {
          Slog.i(TAG, "Entered the Android system server! ");
          Thread thr = new ServerThread();
          thr.setName("android.server.ServerThread");
          thr.start();
          }
          ......
          }

这里的main函数首先会执行JNI方法init1,然后init1会调用这里的init2函数,在init2函数里面,会创建一个ServerThread线程对象来执行一些系统关键服务的启动操作。

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

(7)ZygoteInit.runSelectLoopMode函数。

此函数在文件“frameworks/base/core/java/com/android/internal/os/ZygoteInit.java”中定义,具体实现代码如下所示:

        public class ZygoteInit {
          ......
          private static void runSelectLoopMode() throws MethodAndArgsCaller {
          ArrayList fds = new ArrayList();
          ArrayList peers = new ArrayList();
          FileDescriptor[] fdArray = new FileDescriptor[4];
          fds.add(sServerSocket.getFileDescriptor());
          peers.add(null);
          int loopCount = GC_LOOP_COUNT;
          while (true) {
          int index;
          ......
          try {
          fdArray = fds.toArray(fdArray);
          index = selectReadable(fdArray);
          } catch (IOException ex) {
          throw new RuntimeException("Error in select()", ex);
          }
          if (index < 0) {
          throw new RuntimeException("Error in select()");
          } else if (index == 0) {
          ZygoteConnection newPeer = acceptCommandPeer();
          peers.add(newPeer);
          fds.add(newPeer.getFileDesciptor());
          } else {
          boolean done;
          done = peers.get(index).runOnce();
          if (done) {
          peers.remove(index);
          fds.remove(index);
          }
          }
          }
          }
          ......
          }

此函数用于等待ActivityManagerService来连接这个Socket,然后调用ZygoteConnection.runOnce函数创建新的应用程序。

这样,Zygote进程就启动完成了,到此为止,终于都对Android系统中的进程有了一个深刻的认识,在此总结如下3点。

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

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

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