在Android系统中,如果用ps来查看进程列表的话,会发现有一个进程是zygote,它的父进程是init,而且,它是所有应用的父进程;还有一个进程是system_server,它的父进程是zygote。

事实上, zygote正是我们所说的JVM。而system_server进程又该如何理解呢?其实,它是整个Android Framework所在的进程。这样,我们所说的android系统最核心的组成部分就呈现给大家了(当然,这里先将kernel和应用除外),即jvm+framework。本文描述了整个jvm 和 system_server的初始化过程,这篇文章是在本博另外一篇文章"android初始化流程”的基础上继续探讨的。

 一.   zygote进程是通过app_process的方式启动的,而且是在init.rc中指定的,具体如下:
 service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server 

app_process是一个用可执行程序,代码位于: frameworks\base\cmds\app_process\目录下。

二.   system_server既然是zygote的子进程,理所当然,是由zygote来初始化的。





1. 通过app_process启动zygote

 

(1)app_main.cpp中的main函数: 
    int main(int argc, const char* const argv[])
 {
     // 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 *arg;
     const char *argv0;


     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);


     // Next arg is parent directory
     if (i < argc) {
         runtime.mParentDir = argv[i++];
     }


     // Next arg is startup classname or "--zygote"
     if (i < argc) {
         arg = argv[i++];
         if (0 == strcmp("--zygote", arg)) {
             bool startSystemServer = (i < argc) ? 
                     strcmp(argv[i], "--start-system-server") == 0 : false;
             setArgv0(argv0, "zygote");
             set_process_name("zygote");
             runtime.start("com.android.internal.os.ZygoteInit",
                 startSystemServer);
         } else {
             set_process_name(argv0);


             runtime.mClassName = arg;


             // Remainder of args get passed to startup class main()
             runtime.mArgC = argc-i;
             runtime.mArgV = argv+i;


             LOGV("App process is starting with pid=%d, class=%s.\n",
                  getpid(), runtime.getClassName());
             runtime.start();
         }
     } else {
         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
         fprintf(stderr, "Error: no class name or --zygote supplied.\n");
         app_usage();
         return 10;
     }
 }
  
 (2)AndroidRuntime.cpp中的start(位于frameworks\base\core\jni\AndroidRuntime.cpp):
 void AndroidRuntime::start(const char* className, const bool startSystemServer)
 {
     LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");
     ......
 
    preloadClasses();
     //cacheRegisterMaps();
     preloadResources();

 
    ......
     /*
      * Initialize the VM.
      *
      * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
      * If this call succeeds, the VM is ready, and we can start issuing
      * JNI calls.
      */
     if (JNI_CreateJavaVM(&mJavaVM, &env, &initArgs) < 0) {
         LOGE("JNI_CreateJavaVM failed\n");
         goto bail;
     }
     /*
      * We want to call main() with a String array with arguments in it.
      * At present we only have one argument, the class name.  Create an
      * array to hold it.
      */
     jclass stringClass;
     jobjectArray strArray;
     jstring classNameStr;
     jstring startSystemServerStr;


     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);
     startSystemServerStr = env->NewStringUTF(startSystemServer ? 
                                                  "true" : "false");
     env->SetObjectArrayElement(strArray, 1, startSystemServerStr);


     /*
      * Start VM.  This thread becomes the main thread of the VM, and will
      * not return until the VM exits.
      */
     jclass startClass;
     jmethodID startMeth;


     slashClassName = strdup(className);
     for (cp = slashClassName; *cp != '\0'; cp++)
         if (*cp == '.')
             *cp = '/';


     startClass = env->FindClass(slashClassName);
     if (startClass == NULL) {
         LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
         /* keep going */
     } else {
         startMeth = env->GetStaticMethodID(startClass, "main",
             "([Ljava/lang/String;)V");
         if (startMeth == NULL) {
             LOGE("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
         }
     }


     LOGD("Shutting down VM\n");
     if (mJavaVM->DetachCurrentThread() != JNI_OK)
         LOGW("Warning: unable to detach main thread\n");
     if (mJavaVM->DestroyJavaVM() != 0)
         LOGW("Warning: VM did not shut down cleanly\n");


 bail:
     free(slashClassName);
     free(stackTraceFile);
 } 
     
 说明:
 (1) LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");
       这个log信息应该不陌生了吧。 
 
(2) preloadClasses();  和preloadResources();, 顾名思义,它加载了许多class和resources,libmedia_jni.so 和libwebcore就是在这里加载的(在本文最后面,会给出相关的log信息,里面显示了加载了哪些库,一定要看喔:))。
(3)
 
(4)  GetStaticMethodID和 CallStaticVoidMethod就会调用 传入的class的对应的方法。
        这里,class是ZygoteInit,方法是main, 而ZygoteInit位于ZygoteInit.java中,注意,从这里开始,
        首次以java定义的类来调用,因为在这之前,jvm也初始化好了,需要jniEnv的参数也设置好了。
        于是,就会执行到下面的ZygoteInit.java的main函数中。 
2.  ZygoteInit.java   
  代码:
      位于frameworks\base\core\java\com\android\internal\os目录下。
   在它的main函数中,最主要的就是:
  startSystemServer(); 这个函数也位于ZygoteInit.java中,代码如下:
    /**
      * Prepare the arguments and fork for the system server process.
      */
     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,3001,3002,3003",
             "--capabilities=121715744,121715744",
             "--runtime-init",
             "--nice-name=system_server",
             "com.android.server.SystemServer",
         };
         ZygoteConnection.Arguments parsedArgs = null;


         int pid;


         try {
             parsedArgs = new ZygoteConnection.Arguments(args);


             /*
              * Enable debugging of the system process if *either* the command line flags
              * indicate it should be debuggable or the ro.debuggable system property
              * is set to "1"
              */
             int debugFlags = parsedArgs.debugFlags;
             if ("1".equals(SystemProperties.get("ro.debuggable")))
                 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;


             /* Request to fork the system server process */
             pid = Zygote.forkSystemServer(
                     parsedArgs.uid, parsedArgs.gid,
                     parsedArgs.gids, debugFlags, null);
         } catch (IllegalArgumentException ex) {
             throw new RuntimeException(ex);
         } 
  
         /* For child process */
         if (pid == 0) {
             handleSystemServerProcess(parsedArgs);
         }


         return true;
     } 
        
 说明: 
    (1)  设置进程的参数是system_server, ; 
           对应的类是com.android.server.SystemServer。 
    (2)  Zygote.forkSystemServer真正地fork一个进程,参数前面已经设置好了,所以,这个fork出来的进程就是system_server,而这个进程恰恰是zygote的子进程(用ps可以看到)。
    (3) Zygote.forkSystemServer相关:
          它调用了forkAndSpecialize(dalvik\libcore\dalvik\src\main\java\dalvik\system\zytote.java), 而后者又通过jni的方式调用到 
          Dalvik_dalvik_system_Zygote_forkSystemServer(dalvik\vm\native\dalvik_system_Zygote.c),继而调用到forkAndSpecializeCommon,在这个函数中,通过 fork()函数来真正创建一个进程。这里,如果看log的话,有打印语句:LOGE("System server process %d has died. Restarting Zygote!", pid);, 而这个log在本文最后给出的log中也是有体现的。
          所以,最终,还是回到了下层的c或者cpp代码中; 而jvm只不过是对fork()进行了封装,当然,这只是它的一个必不可少的功能之一而已。 
3. system_server:
 
system_server上面也提到了,是一个进程,事实上,它是整个Framework的主进程,在这个进程中,会创建并启动一个thread,而这个线程是整个framework的主线程,在这个线程中,这里声明并初始化了所有的framework组件。代码位于:
  systemserver.java(位于frameworks\base\services\java\com\android\server)
   至此, 整个Android os 可以认为是启动完毕。
4.  log,是在开机过程中抓取的,当然,用的是logcat:
09-07 06:21:52.288: DEBUG/AndroidRuntime(541): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<
 09-07 06:21:52.288: DEBUG/AndroidRuntime(541): CheckJNI is ON
 ......
 09-07 06:21:52.937: INFO/(542): ServiceManager: 0xac38
 09-07 06:21:52.957: INFO/AudioFlinger(542): AudioFlinger's thread ready to run for output 0
 09-07 06:21:52.957: INFO/CameraService(542): CameraService started: pid=542
 09-07 06:21:52.978: DEBUG/AndroidRuntime(541): --- registering native functions ---
 09-07 06:21:53.308: INFO/Zygote(541): Preloading classes...
 09-07 06:21:53.318: DEBUG/dalvikvm(541): GC freed 764 objects / 42216 bytes in 11ms
 09-07 06:21:53.517: DEBUG/dalvikvm(541): GC freed 278 objects / 17160 bytes in 4ms
 09-07 06:21:53.898: DEBUG/dalvikvm(541): GC freed 208 objects / 12696 bytes in 6ms
 09-07 06:21:53.988: DEBUG/dalvikvm(541): Trying to load lib /system/lib/libmedia_jni.so 0x0
 09-07 06:21:54.148: DEBUG/dalvikvm(541): Added shared lib /system/lib/libmedia_jni.so 0x0
 09-07 06:21:54.148: DEBUG/dalvikvm(541): Trying to load lib /system/lib/libmedia_jni.so 0x0
 09-07 06:21:54.158: DEBUG/dalvikvm(541): Shared lib '/system/lib/libmedia_jni.so' already loaded in same CL 0x0
 09-07 06:21:54.158: DEBUG/dalvikvm(541): Trying to load lib /system/lib/libmedia_jni.so 0x0
 09-07 06:21:54.158: DEBUG/dalvikvm(541): Shared lib '/system/lib/libmedia_jni.so' already loaded in same CL 0x0
 09-07 06:21:54.158: DEBUG/dalvikvm(541): Trying to load lib /system/lib/libmedia_jni.so 0x0
 09-07 06:21:54.158: DEBUG/dalvikvm(541): Shared lib '/system/lib/libmedia_jni.so' already loaded in same CL 0x0
 09-07 06:21:54.168: DEBUG/dalvikvm(541): GC freed 462 objects / 29144 bytes in 8ms
 ......
 09-07 06:21:58.748: DEBUG/dalvikvm(541): Trying to load lib /system/lib/libwebcore.so 0x0
 09-07 06:21:58.828: DEBUG/dalvikvm(541): Added shared lib /system/lib/libwebcore.so 0x0
 ......
 09-07 06:22:02.258: INFO/Zygote(541): ...preloaded 1166 classes in 8951ms.
 09-07 06:22:02.337: DEBUG/dalvikvm(541): GC freed 313 objects / 19952 bytes in 67ms
 09-07 06:22:02.337: INFO/Zygote(541): Preloading resources...
 ......
 09-07 06:22:03.509: INFO/dalvikvm(541): Splitting out new zygote heap
 09-07 06:22:03.569: INFO/dalvikvm(541): System server process 570 has been created
 09-07 06:22:03.569: INFO/Zygote(541): Accepting command socket connections
 09-07 06:22:03.638: INFO/jdwp(570): received file descriptor 10 from ADB
 09-07 06:22:03.797: DEBUG/dalvikvm(570): Trying to load lib /system/lib/libandroid_servers.so 0x0
 09-07 06:22:04.008: DEBUG/dalvikvm(570): Added shared lib /system/lib/libandroid_servers.so 0x0
 09-07 06:22:04.027: INFO/sysproc(570): Entered system_init()
 09-07 06:22:04.051: INFO/sysproc(570): ServiceManager: 0x16c900
 09-07 06:22:04.051: INFO/SurfaceFlinger(570): SurfaceFlinger is starting
 09-07 06:22:04.058: INFO/SurfaceFlinger(570): SurfaceFlinger's main thread ready to run. Initializing graphics H/W...
 09-07 06:22:04.079: ERROR/MemoryHeapBase(570): error opening /dev/pmem: No such file or directory
 09-07 06:22:04.087: ERROR/SurfaceFlinger(570): Couldn't open /sys/power/wait_for_fb_sleep or /sys/power/wait_for_fb_wake
 09-07 06:22:04.117: ERROR/GLLogger(570): couldn't load <libhgl.so> library (Cannot find library)
 09-07 06:22:04.127: INFO/SurfaceFlinger(570): EGL informations:
 09-07 06:22:04.127: INFO/SurfaceFlinger(570): # of configs : 6
 09-07 06:22:04.127: INFO/SurfaceFlinger(570): vendor    : Android
 09-07 06:22:04.127: INFO/SurfaceFlinger(570): version   : 1.31 Android META-EGL
 09-07 06:22:04.127: INFO/SurfaceFlinger(570): extensions: 
 09-07 06:22:04.127: INFO/SurfaceFlinger(570): Client API: OpenGL ES
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): using (fd=22)
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): id           = 
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): xres         = 320 px
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): yres         = 480 px
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): xres_virtual = 320 px
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): yres_virtual = 960 px
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): bpp          = 16
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): r            = 11:5
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): g            =  5:6
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): b            =  0:5
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): width        = 49 mm (165.877548 dpi)
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): height       = 74 mm (164.756760 dpi)
 09-07 06:22:04.127: INFO/EGLDisplaySurface(570): refresh rate = 60.00 Hz
 09-07 06:22:04.138: WARN/HAL(570): load: module=/system/lib/hw/copybit.goldfish.so error=Cannot find library
 09-07 06:22:04.138: WARN/HAL(570): load: module=/system/lib/hw/copybit.default.so error=Cannot find library
 09-07 06:22:04.138: WARN/SurfaceFlinger(570): ro.sf.lcd_density not defined, using 160 dpi by default.
 09-07 06:22:04.148: INFO/SurfaceFlinger(570): OpenGL informations:
 09-07 06:22:04.148: INFO/SurfaceFlinger(570): vendor    : Android
 09-07 06:22:04.148: INFO/SurfaceFlinger(570): renderer  : Android PixelFlinger 1.0
 09-07 06:22:04.148: INFO/SurfaceFlinger(570): version   : OpenGL ES-CM 1.0
 09-07 06:22:04.148: INFO/SurfaceFlinger(570): extensions: GL_OES_byte_coordinates GL_OES_fixed_point GL_OES_single_precision GL_OES_read_format GL_OES_compressed_paletted_texture GL_OES_draw_texture GL_OES_matrix_get GL_OES_query_matrix GL_ARB_texture_compression GL_ARB_texture_non_power_of_two GL_ANDROID_direct_texture GL_ANDROID_user_clip_plane GL_ANDROID_vertex_buffer_object GL_ANDROID_generate_mipmap 
 09-07 06:22:04.148: WARN/HAL(570): load: module=/system/lib/hw/copybit.goldfish.so error=Cannot find library
 09-07 06:22:04.148: WARN/HAL(570): load: module=/system/lib/hw/copybit.default.so error=Cannot find library
 09-07 06:22:04.148: WARN/HAL(570): load: module=/system/lib/hw/overlay.goldfish.so error=Cannot find library
 09-07 06:22:04.148: WARN/HAL(570): load: module=/system/lib/hw/overlay.default.so error=Cannot find library
 09-07 06:22:04.167: INFO/sysproc(570): System server: starting Android runtime.
 09-07 06:22:04.167: INFO/sysproc(570): System server: starting Android services.
 09-07 06:22:04.179: INFO/SystemServer(570): Entered the Android system server!
 09-07 06:22:04.209: INFO/sysproc(570): System server: entering thread pool.
 09-07 06:22:04.267: ERROR/GLLogger(570): couldn't load <libhgl.so> library (Cannot find library)
 09-07 06:22:04.338: INFO/SystemServer(570): Starting Power Manager.
 09-07 06:22:04.387: INFO/ARMAssembler(570): generated scanline__00000077:03545404_00000A01_00000000 [ 30 ipp] (51 ins) at [0x190ed0:0x190f9c] in 6840752 ns
 09-07 06:22:04.397: INFO/SystemServer(570): Starting Activity Manager.
 09-07 06:22:04.578: INFO/SystemServer(570): Starting telephony registry
 09-07 06:22:04.588: INFO/SystemServer(570): Starting Package Manager.
 09-07 06:22:04.619: INFO/Installer(570): connecting...
 09-07 06:22:04.619: INFO/installd(543): new connection
 ......

当然,这里的信息足够多的,有兴趣的朋友不妨用这种方法去理解和研究一下android启动过程。