相关文章

Android系统启动流程(1)  ——  解析init进程启动过程

Android系统启动流程(3)  ——  解析SystemServer进程启动过程

Android系统启动流程(4)  ——  解析Launcher启动过程

Zygote 进程启动过程

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

    1. Zygote简介

       在Android系统中,DVM(Dalvik虚拟机)、应用程序进程以及运行系统的关键服务的SystemServer进程都是由zygote进程来创建的,我们也将它称为孵化器。它通过fock(复制进程)的形式来创建应用程序进程和SystemServer进程,由于zygote进程在启动时会创建DVM,因此通过fock而创建的应用程序进程和SystemServer进程可以在内部获取一个DVM的实例拷贝。
       关于init启动zygote我们在上一篇文章已经提到了,这里就不赘述了,这篇文章主要分析Android8.1系统的zygote进程的启动流程。

     2. Zygote启动脚本

        在init.rc文件中采用了Import类型语句来引入Zygote启动脚本,这些启动脚本都是由Android初始化语言(Android Init Language)来编写的,引入Zygote脚本代码如下:

system/core/init/init.cpp

import /init.${ro.zygote}.rc

       在init.rc中通过属性ro.zygote的值来引入不同的zygote启动脚本的。从Android5.0开始,Android开始支持64位程序,Zygote也就有了32位和64位的区别了,所以在这里用 ro.zygote 属性来控制使用不同的 Zygote 启动脚本,从而也就启动了不同版本zygote进程, ro.zygote 属性的取值有以下4种:

  • init.zygote32.rc
  • init.zygote32_64.rc
  • init.zygote64.rc
  • init.zygote64_32.rc
      这些 Zygote 启 动脚本都放 system/core/ rootdir 目录 中。        

     1. init.zygote32.rc

      表示支持纯 32 位程序, init.zygote32.rc 文件内容如下所示:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server    class main    priority -20    user root    group root readproc    socket zygote stream 660 root system    onrestart write /sys/android_power/request_state wake    onrestart write /sys/power/state on    onrestart restart audioserver    onrestart restart cameraserver    onrestart restart media    onrestart restart netd    onrestart restart wificond    writepid /dev/cpuset/foreground/tasks

       根据 Service类型语句的格式,可以得知 Zygote 进程名称为zygote ,执行程序为 app _process, class name为main ,如果 audioserver cameraservermedia、netd、wificond 进程终止了,就需要进行 restart (重启 )。

      2. init.zygote32_64.rc

       表示既支持 32 位程序也支持64位程序, init.zygote32_64.rc 文件内容如下所示:

service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote    class main    priority -20    user root    group root readproc    socket zygote stream 660 root system    onrestart write /sys/android_power/request_state wake    onrestart write /sys/power/state on    onrestart restart audioserver    onrestart restart cameraserver    onrestart restart media    onrestart restart netd    onrestart restart wificond    writepid /dev/cpuset/foreground/tasksservice zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary    class main    priority -20    user root    group root readproc    socket zygote_secondary stream 660 root system    onrestart restart zygote    writepid /dev/cpuset/foreground/tasks
       脚本中有两个 Service 类型语 句,说明会启动两个z ygote 进程, 第一 个名称为 zygote,执行程序为 app _process32 ,作为 主模式 ;第二 个名称为 zygote_ secondary ,执行程序为 app _process64 ,作为辅模式。

     3. init.zygote64.rc

      表示支持纯 64 位程序, init.zygote64.rc 文件内容如下所示:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server    class main    priority -20    user root    group root readproc    socket zygote stream 660 root system    onrestart write /sys/android_power/request_state wake    onrestart write /sys/power/state on    onrestart restart audioserver    onrestart restart cameraserver    onrestart restart media    onrestart restart netd    onrestart restart wificond    writepid /dev/cpuset/foreground/tasks

       根据 Service类型语句的格式,可以得知 Zygote 进程名称为zygote ,执行程序为 app _process64, class name为main ,如果 audioserver cameraservermedia、netd、wificond 进程终止了,就需要进行 restart (重启 )。

      4. init.zygote64_32.rc

       表示既支持 32 位程序也支持64位程序, init.zygote64_32.rc 文件内容如下所示:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote    class main    priority -20    user root    group root readproc    socket zygote stream 660 root system    onrestart write /sys/android_power/request_state wake    onrestart write /sys/power/state on    onrestart restart audioserver    onrestart restart cameraserver    onrestart restart media    onrestart restart netd    onrestart restart wificond    writepid /dev/cpuset/foreground/tasksservice zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload    class main    priority -20    user root    group root readproc    socket zygote_secondary stream 660 root system    onrestart restart zygote    writepid /dev/cpuset/foreground/tasks

       脚本中有两个Service类型语句,说明会启动两个zygote 进程, 第一个名称为 zygote,执行程序为 app_process64 ,作为主模式 ;第二个名称为 zygote_secondary,执行程序为 app _process ,作为辅模式。

    3. Zygote 进程启动过程介绍

       在init启动zygote进程是主要是调用App_mian.cpp的main函数中的AppRuntime的start方法来启动zygote进程的,那我们就从App_main.cpp的main函数开始分析,代码如下:

frameworks/base/cmds/app_process/App_main.cpp

int main(int argc, char* const argv[]){        AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));        ...    while (i < argc) {        const char* arg = argv[i++];        if (strcmp(arg, "--zygote") == 0) { // ... 1            // 如果当前运行在zygote进程中,则将zygote设置为true            zygote = true; // ... 2            niceName = ZYGOTE_NICE_NAME;        } else if (strcmp(arg, "--start-system-server") == 0) { // ... 3            // 如果当前运行在SystemServer进程中,则将startSystemServer设置为true            startSystemServer = true; // ... 4        } else if (strcmp(arg, "--application") == 0) {            application = true;        } else if (strncmp(arg, "--nice-name=", 12) == 0) {            niceName.setTo(arg + 12);        } else if (strncmp(arg, "--", 2) != 0) {            className.setTo(arg);            break;        } else {            --i;            break;        }    }    ...     if (!niceName.isEmpty()) {        runtime.setArgv0(niceName.string(), true /* setProcName */);    }    // 如果运行在zygote进程中    if (zygote) { // ... 5        runtime.start("com.android.internal.os.ZygoteInit", args, zygote); // ... 6    } else if (className) {        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);    } else {        fprintf(stderr, "Error: no class name or --zygote supplied.\n");        app_usage();        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");    }}

       由于zygote进程都是通过fock自身来创建子进程的,所以zygote进程以及它的子进程都可以进入App_main.cpp的main函数,因此main函数中为了区分当前运行在哪个进程中,会在注释1处判断参数 arg是否包含了“--zygote”,如果包含了则说明main函数是运行在 zygote 进程中的并在注释2处将 zygote设置为ture,同理在注释3处判断参数arg中是否包含了“--start-system-server”,如果包含了则说明 main 函数是运行在SystemServer进程中的并在注释4处将 startSystemServer设置为true。

      在注释5处,如果zygote为true,就说明当前运行在zygote进程中,就会调用注释6处的runtime的start函数,runtime指的就是AppRuntime,AppRuntime声明也在App_main.cpp中,它继承AndroidRuntime,但是AppRuntime并没有重写start函数,也就是说我们调用start函数其实调用的就是AndroidRuntime的start函数,如下所示:

frameworks/base/cmds/app_process/App_main.cpp

class AppRuntime : public AndroidRuntime
         接下来我们分析AndroidRuntime中的start函数,代码如下:   frameworks/base/core/jni/AndroidRuntime. cpp
/* * Start the Android runtime.  This involves starting the virtual machine * and calling the "static void main(String[] args)" method in the class * named by "className". * * Passes the main function two arguments, the class name and the specified * options string. */void AndroidRuntime::start(const char* className, const Vector& options, bool zygote){    ...    /* start the virtual machine */    JniInvocation jni_invocation;    jni_invocation.Init(NULL);    JNIEnv* env;    // 启动java虚拟机    if (startVm(&mJavaVM, &env, zygote) != 0) { // ... 1        return;    }    onVmCreated(env);    /*     * Register android functions.     * 为java虚拟机注册JNI方法     */    if (startReg(env) < 0) { // ... 2        ALOGE("Unable to register all android natives\n");        return;    }         ...       stringClass = env->FindClass("java/lang/String");    assert(stringClass != NULL);    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);    assert(strArray != NULL);    // 从App_main的main函数得知,className为com.android.internal.os.ZygoteInit    classNameStr = env->NewStringUTF(className);    assert(classNameStr != NULL);    env->SetObjectArrayElement(strArray, 0, classNameStr);    for (size_t i = 0; i < options.size(); ++i) {        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());        assert(optionsStr != NULL);        env->SetObjectArrayElement(strArray, i + 1, optionsStr);    }    /*     * Start VM.  This thread becomes the main thread of the VM, and will     * not return until the VM exits.     */    // 将className的"."替换为"/"    char* slashClassName = toSlashClassName(className != NULL ? className : ""); // .. 4    // 找到ZygoteInit    jclass startClass = env->FindClass(slashClassName); // ... 5    if (startClass == NULL) {        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);        /* keep going */    } else {        // 找到ZygoteInit的main方法        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",            "([Ljava/lang/String;)V"); // ... 6        if (startMeth == NULL) {            ALOGE("JavaVM unable to find main() in '%s'\n", className);            /* keep going */        } else {            // 通过JNI调用ZygoteInit的main方法            env->CallStaticVoidMethod(startClass, startMeth, strArray); // ... 7#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");}
       在注释1 处调s artVm函 数来创建 Java 虚拟 机,在注释2处调 startReg 函数为 Java 虚拟机注册 JNI 方法。注释3 处的 c la ssName 的值是传进来的参数, 它的值为“com.android.internal.os.ZygoteInit”。 在注释4处通过toSlashClassName函数 ,将 className 的“.”为“/ ”,替换后 的值为 " com/ android/ intemal/os/ Zygot el nit" 并赋值给 s lashClassN ame ,接着在注释5处根据 s lashCl assN ame 找到 Zygotelnit ,找到了 Zygotelnit 之后在注释6处再去查找它的main方法 。最 终会在 注释7 处通过 JNI 调用 Zygotelnit的 ma in 方法 ,这里为何要使用JNI?因为 Zygotelnit的 main 方法是由 Java 语言编写 的,当前的运行逻辑在 Native 中,这就需要通过 JNI 调用 Java 。这样 Zygote 就从 Native 层 进入了 Java 框 架层。        在我 们通过 JNI 调用 Zygot el nit的 main 方法 后, Zygote 便进入了 Java框 架层, 此前 没有任何代码进入 Java 框架层 的,换句话说是 Zygote 开创了 Java 框架层。接下来我们看ZygoteInit.java的mian方法,代码如下:   frameworks/base/core/java/com/android/internal/os/Zygotelnit.java
public static void main(String argv[]) {        ZygoteServer zygoteServer = new ZygoteServer()        ...        String socketName = "zygote";         ...               try {                         ...            // 创建一个Server端的Socket,socketName的值为"zygote"            zygoteServer.registerServerSocket(socketName); // ... 1            // In some configurations, we avoid preloading resources and classes eagerly.            // In such cases, we will preload things prior to our first fork.            if (!enableLazyPreload) {                bootTimingsTraceLog.traceBegin("ZygotePreload");                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,                    SystemClock.uptimeMillis());                // 预加载类和资源                preload(bootTimingsTraceLog); // ... 2                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,                    SystemClock.uptimeMillis());                bootTimingsTraceLog.traceEnd(); // ZygotePreload            } else {                Zygote.resetNicePriority();            }            ...            if (startSystemServer) {                // 启动SystemServer进程                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the                // child (system_server) process.                if (r != null) {                    r.run();                    return;                }            }            Log.i(TAG, "Accepting command socket connections");            // The select loop returns early in the child process after a fork and            // loops forever in the zygote.            // 等待AMS请求            caller = zygoteServer.runSelectLoop(abiList); // 4        } catch (Throwable ex) {            Log.e(TAG, "System zygote died with exception", ex);            throw ex;        } finally {            zygoteServer.closeServerSocket();        }        // We're in the child process and have exited the select loop. Proceed to execute the        // command.        if (caller != null) {            caller.run();        }    }

       在注释1处通过registerServerSocket 方法来创建 Server 端的 Socket ,这个name 为“zygote”的 Socket 用于等待 ActivityManagerService 请求 Zygote 来创建新的应用程序进程,后续会出AMS相关的文章解析AMS,这里就先不做介绍了。在注释2处预加载类和资源。在注释3处启动 SystemServer进程,这样系统的服务也会由 SystemServer进程启动起来。在注释4处调用 zygoteServer.runSelectLoop 方法来等待 AMS 请求创建新的应用程序进程。由此得知, Zygotelnit的main方法主要做了4件事:

       (1 )创建一个 Server 端的 Socket        (2 )预加载类和资源。        (3 )启动 SystemServer 进程。        (4 )等待 AMS 请求 创建新的 应用程序进程。          其中第二件事预加载类和资源这里不做介绍,有兴趣的读者可以查看源码,这里会对其他的主要事件进行分析。

      1 . registerZygoteSocket

       首先我们来查看 ZygoteServer的registerZygoteSocket 方法做了什么,代码如下所示:

frameworks/base/core/java/com/android/internal/os/ZygoteServe.java

    /**     * Registers a server socket for zygote command connections     *     * @throws RuntimeException when open fails     */    void registerServerSocket(String socketName) {        if (mServerSocket == null) {            int fileDesc;            // 拼接Socket的名称            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;             try {                // 获取Socket的环境变量的值                String env = System.getenv(fullSocketName);                 // 将Socket环境变量的值转化为文件描述符的参数                fileDesc = Integer.parseInt(env);             } catch (RuntimeException ex) {                throw new RuntimeException(fullSocketName + " unset or invalid", ex);            }            try {                // 创建文件描述符                FileDescriptor fd = new FileDescriptor();                 // 设置文件描述符的参数                fd.setInt$(fileDesc);                // 创建服务器端Socket                mServerSocket = new LocalServerSocket(fd); // ... 1            } catch (IOException ex) {                throw new RuntimeException(                        "Error binding to local socket '" + fileDesc + "'", ex);            }        }    }
       注释1处用来创建LocalServerSocket,也就是服务器端的Socket。当zygote进程将 SystemServer 进程启动之后,就会在这个服务器端的Socket上来等待ActivityManagerService请求zygote进程来创建新的应用程序进程。

      2. 启动SystemServer进程

       接下来查看 forkSystemServer方法, 代码如下所示:

frameworks/base/core/java/com/android/internal/os/Zygotelnit.java

    /**     * Prepare the arguments and forks for the system server process.     *     * Returns an {@code Runnable} that provides an entrypoint into system_server code in the     * child process, and {@code null} in the parent.     */    private static Runnable forkSystemServer(String abiList, String socketName,            ZygoteServer zygoteServer) {                ...          /* Hardcoded command line to start the system server */        // 创建 args 数组,这个数组用来保存启动SystemServer进程的启动参数        String args[] = {            "--setuid=1000",            "--setgid=1000",            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",            "--capabilities=" + capabilities + "," + capabilities,            "--nice-name=system_server",            "--runtime-args",            "com.android.server.SystemServer",        };  // ... 1         ZygoteConnection.Arguments parsedArgs = null;        int pid;        try {            parsedArgs = new ZygoteConnection.Arguments(args); // ... 2            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);            /* Request to fork the system server process */            // 创建system_server进程            pid = Zygote.forkSystemServer(                    parsedArgs.uid, parsedArgs.gid,                    parsedArgs.gids,                    parsedArgs.debugFlags,                    null,                    parsedArgs.permittedCapabilities,                    parsedArgs.effectiveCapabilities); // ... 3        } catch (IllegalArgumentException ex) {            throw new RuntimeException(ex);        }        /* For child process */        // 当前代码逻辑运行在子进程中        if (pid == 0) {            if (hasSecondZygote(abiList)) {                waitForSecondaryZygote(socketName);            }            zygoteServer.closeServerSocket();            // 处理system_server进程            return handleSystemServerProcess(parsedArgs); // ... 4        }        return null;    }

       注释1处的代码用来创建 args 数组,这个数组用来保存启动SystemServer 进程的启动参数,其中可以看出SystemServer 进程的用户id 和用户组 id 被设置为1000 ,并且拥有用户组 1001~1010、1018、1021、1032 、3001~3010 的权限;进程名为 system_server ;启动的类名 com.android server.SystemServer 。在注释2处将 args 数组封装成 Arguments 对象并供注释3处的 forkSystemServer 函数调用 。在注释3处调用 Zygote.forkSystemServer 方法, 其内部会调用 nativeForkSystemServer 这个 Native 方怯, nativeForkSystemServer方法最终会通过fork函数在当前进程创建一个子进程,也就是SystemServer 进程,如果forkSystemServer 方法返回的 pid 的值为0 ,就表示当前的代码运行在新创建的子进程中, 则执行注释4处的 handleSystemServerProcess 来处理 SystemServer 进程。

      3. runSelectloop

       启动Systemserver 进程后,会执行ZygoteServer的runSelectLoop 方法来等待AMS的请求,代码如下所示:

frameworks/base/core/java/com/android/internal/os/ZygoteServe.java

/**     * Runs the zygote process's select loop. Accepts new connections as     * they happen, and reads commands from connections one spawn-request's     * worth at a time.     */    Runnable runSelectLoop(String abiList) {        ArrayList fds = new ArrayList();        ArrayList peers = new ArrayList();        fds.add(mServerSocket.getFileDescriptor()); // ... 1        peers.add(null);        // 无线循环等待AMS的请求        while (true) {            StructPollfd[] pollFds = new StructPollfd[fds.size()];            for (int i = 0; i < pollFds.length; ++i) { // ... 2                pollFds[i] = new StructPollfd();                pollFds[i].fd = fds.get(i);                pollFds[i].events = (short) POLLIN;            }            try {                Os.poll(pollFds, -1);            } catch (ErrnoException ex) {                throw new RuntimeException("poll failed", ex);            }            for (int i = pollFds.length - 1; i >= 0; --i) { // ... 3                if ((pollFds[i].revents & POLLIN) == 0) {                    continue;                }                if (i == 0) {                    ZygoteConnection newPeer = acceptCommandPeer(abiList); // ... 4                    peers.add(newPeer);                    fds.add(newPeer.getFileDesciptor());                } else {                    try {                        ZygoteConnection connection = peers.get(i);                        final Runnable command = connection.processOneCommand(this); // ... 5                        if (mIsForkChild) {                            // We're in the child. We should always have a command to run at this                            // stage if processOneCommand hasn't called "exec".                            if (command == null) {                                throw new IllegalStateException("command == null");                            }                            return command;                        } else {                            // We're in the server - we should never have any commands to run.                            if (command != null) {                                throw new IllegalStateException("command != null");                            }                            // We don't know whether the remote side of the socket was closed or                            // not until we attempt to read from it from processOneCommand. This shows up as                            // a regular POLLIN event in our regular processing loop.                            if (connection.isClosedByPeer()) {                                connection.closeSocket();                                peers.remove(i);                                fds.remove(i);                            }                        }                    } catch (Exception e) {                        if (!mIsForkChild) {                            // We're in the server so any exception here is one that has taken place                            // pre-fork while processing commands or reading / writing from the                            // control socket. Make a loud noise about any such exceptions so that                            // we know exactly what failed and why.                            Slog.e(TAG, "Exception executing zygote command: ", e);                            // Make sure the socket is closed so that the other end knows immediately                            // that something has gone wrong and doesn't time out waiting for a                            // response.                            ZygoteConnection conn = peers.remove(i);                            conn.closeSocket();                            fds.remove(i);                        } else {                            // We're in the child so any exception caught here has happened post                            // fork and before we execute ActivityThread.main (or any other main()                            // method). Log the details of the exception and bring down the process.                            Log.e(TAG, "Caught post-fork exception in child process.", e);                            throw e;                        }                    }                }            }        }   }
       注释1处的 mServerSocket 就是我们在 registerZygoteSocket 函数中创建的服务器端 Socket ,调用 mServerSocket.getFileDescriptor方法 用来获得该 Socket 的fd字段的值并添加 到fd的列表fds 中。接下来无限循环用来等待 AMS 请求 Zygote 进程创建新的应用程序进程。 在注释2处通过遍历将 fds 存储的信息转移到 pollFds 数组中。在注释3 处对 pollFds数组 进行遍历,如果 i==0  ,说明服务器端 Socket 与客户端连接上了,换句话说就是,当前 Zygote 进程与 AMS 立了连接。在注释4 处通过 acceptCommandPeer 方法 得到 ZygoteConnection 类并添 加到 Socket 连接列表 peers 中,接着 将该Z ygoteConnection 的fd添加到fd列表 fds 中,以便可以接收到 AMS 发送过来的 请求。 如果i 的值不 等于0  ,则 说明 AMS向 Zygote 进程发送了一个创建应用进程的请求,则 在注释5 处调用Z ygoteConnection的processOneCommand 数来创建一个新的应用程序进程,并在成功创建后将这个连接从Socket 连接列表 peers fd列表 fds 中清除。

     4. Zygote 进程启动总结

       在init进程中通过   AppRuntime 类 并调用其 start 方法 ,启动 Zygote 进程。        Zygote 进程 启动共 做了如下几件事情:        (1 )创建 Java 虚拟机并为 Java 虚拟机注册 JNI 方法        (2 )通过JNI调 Zygotelnit的 main 函数进入 Zygote的 Java 框架 层。        (3 )通过 registerZygoteSocket方法 创建服务器端 Socket ,并通过 runSelectLoop 方法 AMS 的请求来创建新的应用程序进程。        (4 )启动 SystemServer 进程。

更多相关文章

  1. Android夸进程通信机制七:使用 Socket进行进程间通信
  2. android 进程与线程 - 开发文档翻译 - 进程
  3. android init 进程分析 (1 简介)
  4. android 进程与线程 - 开发文档翻译 - 线程
  5. Android 中三种使用线程的方法
  6. android修改进程名
  7. Android Activity onConfigurationChanged()方法 监听状态改变

随机推荐

  1. Android获取sd卡上的文件目录-日记
  2. Android Animation动画(超详细)
  3. Android Glide加载图片成圆形
  4. Android全面屏显示不全下方有黑色解决方
  5. 一个老程序员的Android学习路线指南
  6. Android双击退出
  7. android studio使用github
  8. [Android学习笔记五] Android View和Widg
  9. Android(OPhone) 学习笔记 - SharedPrefere
  10. What Is Bootloader And How To Unlock B