上一篇结尾的时候,说过AppRuntime的start()最后会加载Java层次的ZygoteInit类(com.android.internal.os.ZygoteInit),并调用其main函数。

ZygoteInit要做一些和Android平台紧密相关的重要动作,比如创建LocalServerSocket对象、预加载一些类以及资源、启动“Android系统服务”.

ZygoteInit类源码位置:Android源码/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public static void main(String argv[]) {    try {        // Start profiling the zygote initialization.
        SamplingProfilerIntegration.start();

        boolean startSystemServer = false;
        String socketName = "zygote";//-----------------------------------
        .................................................
        registerZygoteSocket(socketName);//-----------------------注册zygote套接字
        EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
            SystemClock.uptimeMillis());
        preload();//------------------------------------------------预加载资源
        EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
            SystemClock.uptimeMillis());
        .................................................
        if (startSystemServer) {//-------------------------------- 启动 system server 服务
            startSystemServer(abiList, socketName);
        }

        Log.i(TAG, "Accepting command socket connections");
        runSelectLoop(abiList);//------------------------------------

        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {        caller.run();
    } catch (RuntimeException ex) {        Log.e(TAG, "Zygote died with exception", ex);
        closeServerSocket();
        throw ex;
    }
}

registerZygoteSocket

其中registerZygoteSocket函数代码如下图所示

代码中 ANDROID_SOCKET_PREFIX 定义如下:

1
private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";

那么fullSocketName就是ANDROID_SOCKET_zygote了。要想知道这个环境变量,是怎么来的,那就要先分析init进程了,这不是我们的重点,等后面分析init进程的时候,在详细讨论这个变量的由来。

这里先简单说一下吧。在前面提到的关于zygote的rc配置文件,例如init.zygote32.rc中,有这么个option内容:

1
socket zygote stream 660 root system

说明zygote进程需要一个名为“zygote”的“流型(stream)”socket,当init进程真的启动zygote服务时,会走到service_start(),该函数会检查到zygote服务,需要一个“流型(stream)”的socket,那么便会在/dev/socket中为其创建一个名为zygote的流类型socket,并把新建的socket的文件描述符记录在以“ANDROID_SOCKET_zygote”的环境变量中。

那么ZygoteInit类中main函数下面的代码就清楚了其含义了:

1
2
String env = System.getenv(ANDROID_SOCKET_ENV);
fileDesc = Integer.parseInt(env);

从环境变量的字符串中解析出文件描述符,然后创建LocalServerSocket对象,并将其记录在静态变量sServerSocket中,以后zygote进程会循环监听这个socket,一旦accept到连接请求,就创建命令连接(Command Connection)。监听动作的细节是在runSelectLoop()中。

预先加载类和资源

预先加载类

注册完socket接口,ZygoteInit会预加载一些类,这些类记录在Android源码/frameworks/base/preloaded-classes文本文件里:

1
2
3
4
5
6
7
8
9
10
11
12
13
# Classes which are preloaded by com.android.internal.os.ZygoteInit.
# Automatically generated by frameworks/base/tools/preload/WritePreloadedClassFile.java.
# MIN_LOAD_TIME_MICROS=1250
# MIN_PROCESSES=10
........................................
[Landroid.accounts.Account;
[Landroid.animation.Animator;
[Landroid.animation.Keyframe$FloatKeyframe;
[Landroid.animation.Keyframe$IntKeyframe;
[Landroid.animation.PropertyValuesHolder;
[Landroid.app.FragmentState;
[Landroid.app.LoaderManagerImpl;
........................................

这个文件开头已经说的很清楚了,预先加载的这些类,每个加载时间都至少是1250微秒。Android 5.1中预先加载的类大约有3000个,可想而已Android启动的时候,花在这上面的时间可不少呢。preload函数中会调研preloadClasses()的函数预先加载这些类。

预先加载资源

preload函数中还会利用preloadResources()函数预先加载一些资源,这些资源记录在Android源码/frameworks/base/core/res/res/values/arrays.xml中。

基本上有两大类资源:
1)一类和图片有关(preloaed_drawables)
2)另一类和颜色有关(preloaded_color_state_lists)

预先加载的其他资源

preload函数还要调用下面两个函数还要预先加载opengl和一些so库。

1
2
3
4
5
6
7
8
9
10
11
12
private static void preloadSharedLibraries() {    Log.i(TAG, "Preloading shared libraries...");
    System.loadLibrary("android");
    System.loadLibrary("compiler_rt");
    System.loadLibrary("jnigraphics");
}

private static void preloadOpenGL() {    if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {        EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
    }
}

启动system server服务

ZygoteInit的main()函数会调用startSystemServer()来启动system server,这是Android上层系统最重要的服务了。其大体做法是先fork一个子进程,然后在子进程中做一些初始化动作,继而执行SystemServer类的main()静态函数。需要注意的是,startSystemServer()并不是在函数体内直接调用Java类的main()函数的,而是通过抛异常的方式,在startSystemServer()之外加以处理的。

startSystemServer函数部分代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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,1021,1032,
                        3001,3002,3003,3006,3007",
        "--capabilities=" + capabilities + "," + capabilities,
        "--runtime-init",
        "--nice-name=system_server",
        "com.android.server.SystemServer",
    };
    ZygoteConnection.Arguments parsedArgs = null;
    int pid;
    try {        parsedArgs = new ZygoteConnection.Arguments(args);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        // fork出系统服务对应的进程
        pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,
                                            parsedArgs.gids, parsedArgs.debugFlags, null,
                                            parsedArgs.permittedCapabilities,
                                            parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {        throw new RuntimeException(ex);
    }

    // 对新fork出的系统进程,执行handleSystemServerProcess()
    if (pid == 0) {            if (hasSecondZygote(abiList)) {                waitForSecondaryZygote(socketName);
            }

            handleSystemServerProcess(parsedArgs);
        }
    return true;

}

Zygote.forkSystemServer

android源码/frameworks/base/core/java/com/android/internal/os/Zygote.java

1
2
3
4
5
6
7
8
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
        int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {    VM_HOOKS.preFork();
    int pid = nativeForkSystemServer(
            uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
    VM_HOOKS.postForkCommon();
    return pid;
}

其中参数可以从下面获取:

1
2
3
4
5
6
7
8
9
10
String args[] = {    "--setuid=1000",
    "--setgid=1000",
    "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,
                    3001,3002,3003,3006,3007",
    "--capabilities=" + capabilities + "," + capabilities,
    "--runtime-init",
    "--nice-name=system_server",
    "com.android.server.SystemServer",
};

nativeForkSystemServer()是个native成员函数,其对应的C++层代码位置:Android源码/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) {  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      debug_flags, rlimits,
                                      permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL,
                                      NULL, NULL);
  if (pid > 0) {      // The zygote process checks whether the child process has died or not.
      ALOGI("System server process %d has been created", pid);
      gSystemServerPid = pid;
      // There is a slight window that the system server process has crashed
      // but it went unnoticed because we haven't published its pid yet. So
      // we recheck here just to make sure that all is well.
      int status;
      if (waitpid(pid, &status, WNOHANG) == pid) {          ALOGE("System server process %d has died. Restarting Zygote!", pid);
          RuntimeAbort(env);
      }
  }
  return pid;
}

forkAndSpecializeCommon()内部其实会调用fork(),而后设置gid、uid等信息

handleSystemServerProcess

startSystemServer()会在新fork出的子进程中调用handleSystemServerProgress(),让这个新进程成为真正的系统进程(SystemServer进程)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
    * Finish remaining work for the newly forked system server process.
    */
   private static void handleSystemServerProcess(
           ZygoteConnection.Arguments parsedArgs)
           throws ZygoteInit.MethodAndArgsCaller {
       closeServerSocket();//------------------因为子进程是system server 不是zygote,所以要关闭zygote socket

       // set umask to 0077 so new files and directories will default to owner-only permissions.
       Os.umask(S_IRWXG | S_IRWXO);

       if (parsedArgs.niceName != null) {           Process.setArgV0(parsedArgs.niceName);//----------------niceName 是 system_server
       }

       final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
       if (systemServerClasspath != null) {           performSystemServerDexOpt(systemServerClasspath);
       }

       if (parsedArgs.invokeWith != null) {           String[] args = parsedArgs.remainingArgs;
           // If we have a non-null system server class path, we'll have to duplicate the
           // existing arguments and append the classpath to it. ART will handle the classpath
           // correctly when we exec a new process.
           if (systemServerClasspath != null) {               String[] amendedArgs = new String[args.length + 2];
               amendedArgs[0] = "-cp";
               amendedArgs[1] = systemServerClasspath;
               System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
           }

           WrapperInit.execApplication(parsedArgs.invokeWith,
                   parsedArgs.niceName, parsedArgs.targetSdkVersion,
                   null, args);
       } else {           ClassLoader cl = null;
           if (systemServerClasspath != null) {               cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
               Thread.currentThread().setContextClassLoader(cl);
           }

           /*
            * Pass the remaining arguments to SystemServer.
            */
           // 此时的remainingArgs就是”com.android.server.SystemServer”
           RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
       }

       /* should never reach here */
   }

因为当前已经不是运行在zygote进程里了,所以zygote里的那个监听socket就应该关闭了.在handleSystemServerProcess()函数里,parsedArgs.niceName就是“system_server”,而且因为parsedArgs.invokeWith没有指定,所以其值为null,于是程序会走到RuntimeInit.zygoteInit().

Android源码/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

1
2
3
4
5
6
7
8
9
10
11
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
           throws ZygoteInit.MethodAndArgsCaller {       if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

       redirectLogStreams();//-------------在新fork出的系统进程里,需要重新定向系统输出流

       commonInit();
       nativeZygoteInit();

       applicationInit(targetSdkVersion, argv, classLoader);
   }

上面调用的nativeZygoteInit()是个JNI函数,在AndroidRuntime.cpp文件中可以看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
 * JNI registration.
 */
static JNINativeMethod gMethods[] = {    { "nativeFinishInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
    { "nativeZygoteInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
    { "nativeSetExitWithoutCleanup", "(Z)V",
        (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};

static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{    gCurRuntime->onZygoteInit();
}

gCurRuntime是C++层的AndroidRuntime类的静态变量。在AndroidRuntime构造之时,gCurRuntime = this

其中onZygoteInit是一个虚函数,是有AndroidRuntime的子类AppRuntime负责实现的。

Android源码/framework/base/cmds/app_process/App_main.cpp

1
2
3
4
5
6
7
8
9
virtual void onZygoteInit()
  {      // Re-enable tracing now that we're no longer in Zygote.
      atrace_set_tracing_enabled(true);

      sp<ProcessState> proc = ProcessState::self();
      ALOGV("App process: starting thread pool.\n");
      proc->startThreadPool();
  }

里面构造了进程的ProcessState全局对象,而且启动了线程池。 这就涉及到了Binder机制的知识了,关于Binder后面再讲。

也就是说system server进程内部会开启一个线程池。

在来看applicationInit()函数的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {    nativeSetExitWithoutCleanup(true);

    VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
    VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

    final Arguments args;
    try {        args = new Arguments(argv);
    } catch (IllegalArgumentException ex) {        Slog.e(TAG, ex.getMessage());
        // let the process exit
        return;
    }

    // Remaining arguments are passed to the start class's static main
  invokeStaticMain(args.startClass, args.startArgs, classLoader);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
         throws ZygoteInit.MethodAndArgsCaller {     Class<?> cl;

     try {         cl = Class.forName(className, true, classLoader);
     } catch (ClassNotFoundException ex) {         throw new RuntimeException(
                 "Missing class when invoking static main " + className,
                 ex);
     }
     Method m;
     try {         m = cl.getMethod("main", new Class[] { String[].class });//-----------------注意看这里的 main
     } catch (NoSuchMethodException ex) {         throw new RuntimeException(
                 "Missing static main on " + className, ex);
     } catch (SecurityException ex) {         throw new RuntimeException(
                 "Problem getting static main on " + className, ex);
     }

     int modifiers = m.getModifiers();
     if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {         throw new RuntimeException(
                 "Main method is not public and static on " + className);
     }
     /*
      * This throw gets caught in ZygoteInit.main(), which responds
      * by invoking the exception's run() method. This arrangement
      * clears up all the stack frames that were required in setting
      * up the process.
      */
     throw new ZygoteInit.MethodAndArgsCaller(m, argv);
 }

可见在invokeStaticMain函数中最后抛出了异常。这相当于一个“特殊的goto语句”!上面的cl = Class.forName函数,其实加载的就是SystemServer类。这个类名是从前文的parsedArgs.remainingArgs得来的,其值就是“com.android.server.SystemServer”。此处抛出的异常,会被本进程的catch语句接住,在那里才会执行SystemServer类的main()函数

如下图所示,新fork出的SystemServer子进程直接跳过了中间那句runSelectLoop(),去执行caller.run()去了,也就是说这个run函数是在子进程中执行的。

父进程Zygote在fork动作后,会退出startSystemServer()函数,并走到runSelectLoop(),从而进入一种循环监听状态,每当Activity Manager Service向它发出“启动新应用进程”的命令时,它又会fork一个子进程,并在子进程里抛出一个异常,这样子进程还是会跳转到catch一句。

现在看以下 SystemServer类的main函数:

frameworks/base/services/java/com/android/server/SystemServer.java

1
2
3
4
5
6
/**
 * The main entry point from zygote.
 */
public static void main(String[] args) {    new SystemServer().run();
}

可见创建了SystemServer对象,并且执行其run函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
private void run() {        // If a device's clock is before 1970 (before 0), a lot of
        // APIs crash dealing with negative numbers, notably
        // java.io.File#setLastModified, so instead we fake it and
        // hope that time from cell towers or NTP fixes it shortly.
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }

        // Here we go!
        Slog.i(TAG, "Entered the Android system server!");
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());

        // In case the runtime switched since last boot (such as when
        // the old runtime was removed in an OTA), set the system
        // property so that it is in sync. We can't do this in
        // libnativehelper's JniInvocation::Init code where we already
        // had to fallback to a different runtime because it is
        // running as root and we need to be the system user to set
        // the property. http://b/11463182
        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

        // Enable the sampling profiler.
        if (SamplingProfilerIntegration.isEnabled()) {            SamplingProfilerIntegration.start();
            mProfilerSnapshotTimer = new Timer();
            mProfilerSnapshotTimer.schedule(new TimerTask() {                @Override
                public void run() {                    SamplingProfilerIntegration.writeSnapshot("system_server", null);
                }
            }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
        }

        // Mmmmmm... more memory!
        VMRuntime.getRuntime().clearGrowthLimit();

        // The system server has to run all of the time, so it needs to be
        // as efficient as possible with its memory usage.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

        // Some devices rely on runtime fingerprint generation, so make sure
        // we've defined it before booting further.
        Build.ensureFingerprintProperty();

        // Within the system server, it is an error to access Environment paths without
        // explicitly specifying a user.
        Environment.setUserRequired(true);

        // Ensure binder calls into the system always run at foreground priority.
        BinderInternal.disableBackgroundScheduling(true);

        // Prepare the main looper thread (this thread).
        android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        Looper.prepareMainLooper();

        // Initialize native services.
        System.loadLibrary("android_servers");
        nativeInit();

        // Check whether we failed to shut down last time we tried.
        // This call may not return.
        performPendingShutdown();

        // Initialize the system context.
        createSystemContext();

        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

        // Start services.
        try {            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }

        // For debug builds, log event loop stalls to dropbox for analysis.
        if (StrictMode.conditionallyEnableDebugLogging()) {            Slog.i(TAG, "Enabled StrictMode for system server main thread.");
        }

        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

可见会初始化 native services.

1
2
System.loadLibrary("android_servers");
nativeInit();

监听zygote socket

ZygoteInit的main()函数在调用完startSystemServer()之后,zygote进程会进一步走到runSelectLoop()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    FileDescriptor[] fdArray = new FileDescriptor[4];

    fds.add(sServerSocket.getFileDescriptor());//------------------------sServerSocket就是zygote socket文件描述符
    peers.add(null);

    int loopCount = GC_LOOP_COUNT;
    while (true) {        int index;

        /*
         * Call gc() before we block in select().
         * It's work that has to be done anyway, and it's better
         * to avoid making every child do it.  It will also
         * madvise() any free memory as a side-effect.
         *
         * Don't call it every time, because walking the entire
         * heap is a lot of overhead to free a few hundred bytes.
         */
        if (loopCount <= 0) {            gc();
            loopCount = GC_LOOP_COUNT;
        } else {            loopCount--;
        }

        try {            fdArray = fds.toArray(fdArray);//-----------------------------fdArry中就包含了zygote socket文件描述符了
            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) {//-----------------------------------------对应的zygote socket有数据可读
            ZygoteConnection newPeer = acceptCommandPeer(abiList);
            peers.add(newPeer);
            fds.add(newPeer.getFileDescriptor());
        } else {//-------------------------------------------------对应其他文件描述符有数据可读
            boolean done;
            done = peers.get(index).runOnce();

            if (done) {                peers.remove(index);
                fds.remove(index);
            }
        }
    }
}

在一个while循环中,不断调用selectReadable()。该函数是个native函数,对应C++层的com_android_internal_os_ZygoteInit_selectReadable()。

Android源码/frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp

1
2
3
4
5
6
7
static JNINativeMethod gMethods[] = {.................................................................
    { "selectReadable", "([Ljava/io/FileDescriptor;)I",
        (void *) com_android_internal_os_ZygoteInit_selectReadable },
    { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
        (void *) com_android_internal_os_ZygoteInit_createFileDescriptor }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static jint com_android_internal_os_ZygoteInit_selectReadable (JNIEnv *env, jobject clazz,
                                                                         jobjectArray fds)
{    . . . . . .
    int err;
    do {        err = select (nfds, &fdset, NULL, NULL, NULL);
    } while (err < 0 && errno == EINTR);
    . . . . . .
    for (jsize i = 0; i < length; i++) {        jobject fdObj = env->GetObjectArrayElement(fds, i);
        . . . . . .
        int fd = jniGetFDFromFileDescriptor(env, fdObj);
        . . . . . .
        if (FD_ISSET(fd, &fdset)) {            return (jint)i;
        }
    }
    return -1;
}

主要就是调用select()而已。在Linux的socket编程中,select()负责监视若干文件描述符的变化情况,我们常见的变化情况有:读、写、异常等等。

在zygote中,err = select (nfds, &fdset, NULL, NULL, NULL);一句的最后三个参数都为NULL,表示该select()操作只打算监视文件描述符的“读变化”,而且如果没有可读的文件,select()就维持阻塞状态。

在被监视的文件描述符数组(fds)中,第一个文件描述符对应着“zygote接收其他进程连接申请的那个socket(及sServerSocket)”,一旦它发生了变化,我们就尝试建立一个ZygoteConnection。

新创建的ZygoteConnection会被再次写入文件描述符数组(fds):

1
fds.add(newPeer.getFileDescriptor());

如果select动作发现文件描述符数组(fds)的其他文件描述符有东西可读了,说明有其他进程通过某个已建立好的ZygoteConnection发来了命令,此时我们需要调用runOnce()。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    . . . . . .
        args = readArgumentList();//----------------------------------------------------------------
        descriptors = mSocket.getAncillaryFileDescriptors();
    . . . . . .
    int pid = -1;
    FileDescriptor childPipeFd = null;
    FileDescriptor serverPipeFd = null;

    try {        parsedArgs = new Arguments(args);
        . . . . . .
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal,
                parsedArgs.seInfo, parsedArgs.niceName);
    }
    . . . . . .
        if (pid == 0) {            // in child
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
            return true;
        } else {            // in parent...pid of < 0 means failure
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
        }
    . . . . . .
}

runOnce()中从socket中读取参数数据的动作是由readArgumentList()完成的,该函数的代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private String[] readArgumentList()
        throws IOException
{    int argc;
    . . . . . .
        String s = mSocketReader.readLine();
    . . . . . .
        argc = Integer.parseInt(s);
    . . . . . .
    String[] result = new String[argc];
    for (int i = 0; i < argc; i++) {        result[i] = mSocketReader.readLine();
        if (result[i] == null) {            // We got an unexpected EOF.
            throw new IOException("truncated request");
        }
    }
    return result;
}

AMS会想这个socke写入参数。AMS需要启动一个新进程时,会调用类似下面的句子:

1
2
3
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, null);

包括ActivityThread类名等重要信息的参数,最终就会通过socket传递给zygote。

runOnce()在读完参数之后,会进一步调用到handleChildProc()。该函数会间接抛出特殊的MethodAndArgsCaller异常,只不过此时抛出的异常携带的类名为ActivityThread,前面我们提到的类名是SystemServer。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
                             FileDescriptor pipeFd, PrintStream newStderr)
                             throws ZygoteInit.MethodAndArgsCaller
{    closeSocket();//--------------------------------------------因为不是zygote进程了,所以肯定要先关闭socket了
    ZygoteInit.closeServerSocket();
    . . . . . .
    if (parsedArgs.niceName != null) {        Process.setArgV0(parsedArgs.niceName);
    }

    if (parsedArgs.runtimeInit) {        if (parsedArgs.invokeWith != null) {            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    pipeFd, parsedArgs.remainingArgs);
        } else {            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                    parsedArgs.remainingArgs);
        }
    } else {        String className;
        . . . . . .
            className = parsedArgs.remainingArgs[0];
        . . . . . .
        String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1];
        System.arraycopy(parsedArgs.remainingArgs, 1,
                mainArgs, 0, mainArgs.length);

        if (parsedArgs.invokeWith != null) {            WrapperInit.execStandalone(parsedArgs.invokeWith,
                    parsedArgs.classpath, className, mainArgs);
        } else {            ClassLoader cloader;
            if (parsedArgs.classpath != null) {                cloader = new PathClassLoader(parsedArgs.classpath,
                        ClassLoader.getSystemClassLoader());
            } else {                cloader = ClassLoader.getSystemClassLoader();
            }

            try {                ZygoteInit.invokeStaticMain(cloader, className, mainArgs);//-----------------------很熟悉吧,忘了的话,往上看
            } catch (RuntimeException ex) {                logAndPrintError(newStderr, "Error starting.", ex);
            }
        }
    }
}

Zygote进程实际上是利用fork()创建新进程。如果fork()出的新进程是system server,那么其最终执行的就是SystemServer类的main()函数,而如果fork()出的新进程是普通的用户进程的话,那么其最终执行的就是ActivityThread类的main()函数。

原文地址: http://www.iloveandroid.net/2015/09/21/Zygote_2/

Android 5.1 Lollipop的Zygote分析——下篇相关推荐

  1. Android 5.1 Lollipop的Zygote分析——上篇

    整体介绍 因为公司最近的项目,频繁的使用了xposed框架.作为一种Hook技术,xposed框架主要是对Android系统中的app_process程序做了手脚.为了弄清楚xposed框架背后的原理 ...

  2. Android中init与受精卵Zygote分析,以及添加自己开机启动的系统服务

    最近在做云游戏的项目,由于需要购买硬件,系统提供Android源码需要自己编译.所以特地学习一下记录一下Android的启动(我的是AOSP7.1然后+厂商系统补丁) 先上图: 目录 一. 启动流程硬 ...

  3. Android Zygote分析

    1. app_process到zygote zygote本身是一个Native应用程序,和驱动.内核均无关系,zygote是由init进行根据init.rc文件中的配置进行创建的,具体的配置代码如下: ...

  4. android 的Zygote 分析

    jollen 發表於 April 5, 2010 3:14 PM Android 作業系統開機時,會經由 init.rc 來啟動許多外部程式,其中有一個最重要 process 稱為 Zygote.Zy ...

  5. Android Studio - HPROF文件查看和分析工具

    Android Studio - HPROF文件查看和分析工具 Android Studio 翻译的官方文章 原文链接 当你在Android Studio中使用Android Monitor里的Mem ...

  6. Android系统(244)---Zygote进程的启动流程

    Android进程系列第二篇---Zygote进程的启动流程 内容预览.png 概述: 本文(基于Android O源码)主要讲解Zygote进程创建流程,线程容易创建,但进程的相关的东西都被系统很好 ...

  7. Android 系统(78)---《android framework常用api源码分析》之 app应用安装流程

    <android framework常用api源码分析>之 app应用安装流程 <android framework常用api源码分析>android生态在中国已经发展非常庞大 ...

  8. 转:Android应用开发性能优化完全分析

    转自:http://blog.csdn.net/yanbober/article/details/48394201 1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜 ...

  9. Android系统启动流程—— init进程zygote进程SystemServer进程启动流程

    原文地址:https://blog.csdn.net/qq_30993595/article/details/82714409 Android系统启动流程 Android系统启动过程往细了说可以分为5 ...

最新文章

  1. 非本地类型不能定义方法 cannot define new methods on non-local type time.Duration
  2. Oracle导出空表解决办法
  3. JavaScript如何声明对象、函数以及对象中的函数(即方法)
  4. GraphQL入门之graphql-java项目的介绍
  5. QPushButton hover配置
  6. react学习(69)--置空操作
  7. 【计算机组成原理】双端口RAM和多模块存储器
  8. J2EE实现发送邮件功能
  9. Web开发技术大会演讲
  10. 深入阅读Mina源码(3) —— Mina之IOAdapter(二)
  11. 最新版本elasticsearch本地搭建入门篇
  12. fork 与 vfork
  13. html怎么将背景图片旋转,css怎么旋转图片?
  14. angular7.0+ngx-weui公众号开发,开发及框架搭建(一)
  15. 半小时一篇文过完C语言基础知识点
  16. D-009 eMMC电路设计
  17. matlab 画拉普拉斯变换的零极点
  18. 笔记本电脑周边双屏显示方案
  19. Unity插件学习(五) ------ 本地存储Easy Save3
  20. golang生成UUID通用唯一识别码

热门文章

  1. static 成员小记
  2. DRM-内容数据版权加密保护技术学习(上):视频文件打包实现(转)
  3. leetcode刷题之堆
  4. Python学习笔记:常用内建模块4:hmac
  5. iptables防火墙详解
  6. Python中if __name__ == '__main__':作用
  7. [云炬创业管理笔记]第四章把握创业机会测试6
  8. [云炬创业基础笔记]第二章创业者测试1
  9. [云炬ThinkPython阅读笔记]3.4 增加新函数
  10. 获得 DataSet中的记录总数