Android zygote 进程的启动过程分析

版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com

zygote进程在 Android 开发中属于比较底层的内容,然而要透彻的理解 AMS、WMS 和 IPC 等,不可避免的要先理解zogyte进程,因此本文即作为对自己的学习记录,也想分享出来和遇到同样问题的读者交流。

在正式内容开始之前,我建议读者朋友下载部分源代码备用,分别是:

  • platform/framework/base
  • platform/system/core
  • platform/packages/apps/Launcher3

我们可以到 Android 源码托管站下载:https://android.googlesource.com/,可以下载具体某个模块源代码,可以指定分支或者 tag,需要翻阅 GFW。

另外如果你没有翻阅 GFW 的条件的话,可以使用清华大学镜像源:
https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

例如,现在我们从 Terminal 进入~/Workspance/Android目录下,然后分别下载上述三个模块oreo-release分支的源代码:

$ git clone -b oreo-release https://aosp.tuna.tsinghua.edu.cn/platform/frameworks/base platform_framework_base
...
$ git clone -b oreo-release https://aosp.tuna.tsinghua.edu.cn/platform/system/core platform_system_core
...
$ git clone -b oreo-release https://aosp.tuna.tsinghua.edu.cn/platform/packages/apps/Launcher3 platform_packages_apps_Launcher3

特别声明:本文出现的源代码,为了更加简洁清晰,部分代码经过大量的精简,读者阅读本文时,如果有条件,最好配合源代码,以免产生误解。

另外,纠正一个无伤大雅的小问题,我们经常说的init进程、zygote进程和system_server进程,它们的名字如上所写,不是大写,也不是驼峰式写法,比如这些写法是不正确的:

Init进程,正确的应该是:init进程
Zygote进程,正确的应该是:zygote进程
SystemServer进程,正确的应该是:system_server进程

本文内容

  • init.rc 配置文件的作用和运行流程
  • init.zygote.rc 配置文件的含义和作用
  • ZygoteInit.java 初始化zygote进程的过程
  • ZygoteInit.java 启动system_server进程的过程
  • SystemServer.java 初始化system_server进程的过程
  • zygote 进程等待 Socket 客户端的请求

init.rc 配置文件的作用和运行流程

Android 系统是基于 Linux 内核的,Linux 系统中的进程都是 init 进程的子进程,Android 的zygote进程也是在系统启动的过程,由init进程创建的。本小节要分析从系统启动后代码是如何执行到 zygote相关逻辑块的,然后由此引出zygote的启动过程分析。

系统启动时kernel/init/main.c文件中的kernel_init()函数会做一些硬件相关的基础工作,比如 CPU 初始化和内存初始化等,然后会执行platform/system/core目录下的init程序,该程序即 Android 的init进程对应的程序。该程序的对应代码是platform/system/core/init.cpp,打开该文件并找到它的入口函数:

// 注意这两行引入
#include "property_service.h"
#include "service.h"

int main(int argc, char** argv) {
  ... // 一些必要的环境变量配置和启动其他Linux进程

  // 执行在头部引入的property_service.h的start_property_service()函数
  start_property_service();

  // 解析配置文件
  Parser& parser = Parser::GetInstance();
  // 解析service
  parser.AddSectionParser("service",std::make_unique<ServiceParser>());
  parser.AddSectionParser("on", std::make_unique<ActionParser>());
  parser.AddSectionParser("import", std::make_unique<ImportParser>());

  parser.ParseConfig("/init.rc");
  ...

  ActionManager& am = ActionManager::GetInstance();

  ... // 配置am命令参数

  while (true) {
    // 使用epoll机制 + 死循环,使init进程一直运行,类似Looper#loop()

    // 默认一直阻塞,直到有事情需要做被唤醒
    int epoll_timeout_ms = -1;

    if (...) {
      am.ExecuteOneCommand();
      // 一些赋值逻辑,可能是0
      epoll_timeout_ms = ...;
    }

    // 调用epoll_wait使init进程沉睡或者...
    epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms)}

  return 0;
}

我们会发现该函数中解析了位于platform/system/core/rootdir/init.rc的初始化配置文件,我摘抄出了与zygote进程相关的部分代码:

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

...

# 当电源键被按住的时候执行 property
on property:sys.boot_from_charger_mode=1
    class_stop charger
    trigger late-init

# 挂载文件系统并启动核心系统服务
on late-init
    ...
    # 调用zygote-start
    trigger zygote-start

    ...

    trigger early-boot
    trigger boot

# 在init.rc中调用zygote-start解除zygote的启动阻塞
on zygote-start && property:ro.crypto.state=unencrypted
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start netd
    start zygote

上述配置的代码类似 C 语言风格,每一个on和后边的定义我们暂且把它叫做函数,当手机处于关机状态时,我们摁住电源键开机,init进程执行到这里时,会调用property函数,该函数做一些准备工作后,会调用late-init函数,late-init函数会做一些启动初始化相关的工作,完事以后会调用zygote-start去执行init.zygote*.rc,我们发现该配置文件在init.rc文件头部被引入:

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

该文件被引入时有个ro.zygote变量,它可以被理解为一个环境变量,该变量的值和设备的 CPU 平台相关,同样在./rootdir目录下的可选项有:

init.zygote32.rc
init.zygote32_64.rc
init.zygote64.rc
init.zygote64_32.rc

为了一目了然简单清晰,我们选择init.zygote32.rc来分析,init进程执行到这里,根据init.zygote32.rc的描述,会 fork zygote进程,具体细节请看下一节。

init.zygote.rc 配置文件的含义和作用

打开init.zygote32.rc文件后我们发现它的代码很简洁清晰:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    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,在platform/core/init/README.md中有对init语法的描述,service的语法是这样的:

service <name> <pathname> [ <argument> ]*
    <option>
    <option>

其中对service的解释是:serviceinit退出时启动和重新启动的程序。我认为在这里,init会先 fork 一个进程,会把该进程命名为zygote,然后在该进程中执行/system/bin/app_process程序,并且带上参数--zygote -- start-system-server

后面的socket是为zygote进程创建一个名称为"zygote"的socket资源,在系统启动后,我们可以在/dev/socket目录下发现一个名为“zygote”的文件。在本文中,该配置被执行完后我们会做这个 Socket 资源的验证。

接下来,我们把目光集中在zygote进程接下来要执行的/system/bin/app_process程序上,system/bin一般用来存放系统命令类的程序,通过分析和查找,它对应的代码在platform/frameworks/base/cmds/app_process/app_main.cpp文件中,接下来我们详细分析该文件。

ZygoteInit.java 初始化 zygote 进程的过程

上面讲到init进程解析init.zygote.rc后,会 forkzygote进程,然后在zygote进程中执行/system/bin/app_process程序,执行该程序的目的是初始化zygote进程。

接下来我们打开platform/frameworks/base/cmds/app_process/app_main.cpp文件,来分析初始化zygote进程时做了哪些事情,目光定位在main()函数上:

int main(int argc, char* const argv[])
{
    // 创建 AppRuntime的成员变量
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

    ...

    // 解析运行时参数,赋值zygote和startSystemServer
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } 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.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    if (!className.isEmpty()) {
        ...
    } else {
        ...
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }
    }

    if (zygote) {
        // 调用 ZygoteInit#main()
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } 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.");
    }
}

上述代码,首先创建了一个AppRuntime的局部成员变量,然后对入参进行了解析,根据对init.zygote32.rc传入参数的分析,这里的zygote变量和startSystemServer的值均为true,因此在最后调用AppRuntime#start()函数时走了:

if (zygote) {
    runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}

AppRuntime类也定义在platform/frameworks/base/cmds/app_process/app_main.cpp中:

class AppRuntime : public AndroidRuntime
{
  ...
};

发现AppRuntime类继承于AndroidRuntime,而AppRuntime类中是没有start()函数的,因此回到上方的main()函数中,实际上当执行AppRuntime#start()时实际上是执行了AndroidRuntime#start(),下面我们来看看AndroidRuntime类,它位于platform/frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, ..., bool zygote)
{
    static const String8 startSystemServer("start-system-server");

    ...

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;

    startVm(&mJavaVM, &env, zygote);
    onVmCreated(env);

    /*
     * Register android functions.
     */
    startReg(env);

    /*
     * We want to call main() with a String array with arguments in it.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    /*
     * 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);
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
        "([Ljava/lang/String;)V");
    env->CallStaticVoidMethod(startClass, startMeth, strArray);

    ...
}

根据AndroidRuntime名称和上述代码可以分析得出,该函数启动了 Android 系统运行时库,其中它主要做了三件事:

  • 调用startVmVM()函数启动虚拟机
  • 调用startReg()函数注册 Android 的 Java 方法,其实在这里就是 JNI 方法
  • 反射调用 Java 类com.android.internal.os.ZygoteInit#main()方法,并把 fork zygote进程时的参数传入用来辅助初始化zygote进程

此时,我们回到启动zygote进程的地方回顾一下:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

根据上述分析,此时调用句柄已经执行到com.android.internal.os.ZygoteInit#main(),该类的 Java 文件位于platform/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
    ZygoteServer zygoteServer = new ZygoteServer();

    // 标记Zygote开始初始化,并Hook确保不创建其他线程
    ZygoteHooks.startZygoteNoThreadCreation();

    // Zygote进入自己的进程组
    try {
        Os.setpgid(0, 0);
    } catch (ErrnoException ex) {
        throw new RuntimeException("Failed to setpgid(0,0)", ex);
    }

    ...

    boolean startSystemServer = false;
    String socketName = "zygote";

    // 解析参数,初始化局部变量
    for (int i = 1; i < argv.length; i++) {
        if ("start-system-server".equals(argv[i])) {
            startSystemServer = true;
        }
        ...
    }

    // 注册一个名为zygote的ServerSocket,
    zygoteServer.registerServerSocket(socketName);

    // 第一次启动时会预加载资源
    if (!enableLazyPreload) {
        ...
        preload(bootTimingsTraceLog);
    }
    ...

    // 停止Hook不创建其他线程,也就是说允许创建其他线程
    ZygoteHooks.stopZygoteNoThreadCreation();

    // 这里一定是true,启动SystemServer
    if (startSystemServer) {
        startSystemServer(abiList, socketName, zygoteServer);
    }

    // 运行zygote进程的select循环
    zygoteServer.runSelectLoop(abiList);

    zygoteServer.closeServerSocket();
}

在这个初始化过程中,做了不少准备工作,更加详细的过程请阅读上述代码注释和源码,我们这里总结以下我们需要着重关注的几件事:

  1. 调用ZygoteServer#registerServerSocket()方法创建一个名为zygote的 Socket 资源
  2. 调用ZygoteInit#starSystemServer()方法启动system_server进程
  3. 调用ZygoteInit#runSelectLoop()方法循环接受 Socket 连接,在这里开始和 AMS 搭上边,其实这里就是循环等待 AMS 的连接和命令,更加详细的过程在下文中分析。

ZygoteServer#registerServerSocket()创建 Java 层的 ServerSocket 对象

上面说到ZygoteServer#registerServerSocket()创建了一个名为zygote的 Socket 资源,我们知道,Socket 是 IPC 通信的一种方式,该 Socket 资源在后期被用在和 AMS 等服务进行进程间通信。下面我们来看ZygoteServer#registerServerSocket()的具体实现,ZygoteServer.java位于com.android.internal.os.ZygoteServer.java

class ZygoteServer {

  private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";

  private LocalServerSocket mServerSocket;

  ZygoteServer() {
  }

  void registerServerSocket(String socketName) {
      if (mServerSocket == null) {
          int fileDesc;

          // fullSocketname的值是ANDROID_SOCKET_zygote
          final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;

          // 获取Socket名称对应的环境变量
          String env = System.getenv(fullSocketName);
          fileDesc = Integer.parseInt(env);

          // 根据环境变量创建文件描述符
          FileDescriptor fd = new FileDescriptor();
          fd.setInt$(fileDesc);

          // 根据文件描述符创建Socket
          mServerSocket = new LocalServerSocket(fd);
    }
  }
}

请读者先看完上述代码的注释,上述代码中其他的因素都是确定的,只有 Socket 名称对应的环境变量是不确定的,这个环境变量指向的文件描述符的值是在文章开头的platform/system/init.cpp创建的,在文章开头其实我已经标识出来了,但是大多数人应该不知道是干嘛用的,我们回到init.cpp

// 注意这两行引入
#include "property_service.h"
#include "service.h"

int main(int argc, char** argv) {
  ... // 一些必要的环境变量配置和启动其他Linux进程

  // 执行在头部引入的property_service.h的start_property_service()函数
  start_property_service();

  // 解析配置文件
  Parser& parser = Parser::GetInstance();
  // 解析service
  parser.AddSectionParser("service",std::make_unique<ServiceParser>());
  ...
}

该函数中start_property_service()会去创建 Socket 资源,下面我们一步步看这些相关的文件。

platform/system/core/init/property_service.cpp中调用util#create_socket()函数:

#include "util.h"

void start_property_service() {
    property_set("ro.property_service.version", "2");

    // 创建Socket连接
    property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | ...);
    ...

    register_epoll_handler(property_set_fd, handle_property_set_fd);
}

platform/system/core/init/util.cppcreate_socket()函数会在ANDROID_SOCKET_DIR常量指定的目录创建一个 Unix 的 Socket 资源,并通过ANDROID_SOCKET_ENV_PREFIX常量加[name]指定名称的环境变量向其他位置共享该文件描述符的值:

#include 

/*
 * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR
 * ("/dev/socket") as dictated in init.rc. This socket is inherited by the
 * daemon. We communicate the file descriptor's value via the environment
 * variable ANDROID_SOCKET_ENV_PREFIX ("ANDROID_SOCKET_foo").
 */
int create_socket(const char *name, ...)
{
    ...

    android::base::unique_fd fd(socket(PF_UNIX, type, 0));
    ...

    return fd.release();
}

上述两个常量定义在platform/system/core/include/cutils/sockets.h中:

#define ANDROID*SOCKET_ENV_PREFIX "ANDROID_SOCKET*"
#define ANDROID_SOCKET_DIR "/dev/socket"

如果你手里有个 Android 系统的设备,我们可以查看一下该文件:

Harrys-MacBook-Pro:Visit Harry$ adb shell

shell@cancro:/ $ cd /dev/socket
shell@cancro:/dev/socket $ ls
adbd
...
zygote
shell@cancro:/dev/socket $

在上述com.android.internal.os.ZygoteServer.java中也能看到 Socket 资源的前缀常量,因此它在这里就获取到了名为ANDROID_SOCKET_zygote的文件描述符,并在 Java 层创建了LocalServerSocket的服务端 Socket 对象。

ZygoteInit.java 启动 system_server 进程的过程

zygote进程启动了 Java 层的LocalServerSocket后,接着调用了ZygoteInit#starSystemServer()启动system_server进程。

/**
  * Prepare the arguments and fork for the system server process.
  */
private static boolean startSystemServer(String socketName,
    ZygoteServer zygoteServer) {

  /* Hardcoded command line to start the system server */
  String args[] = {
    ...
    "--nice-name=system_server", // 指定进程名字 system_server
    "--runtime-args",
    "com.android.server.SystemServer", // 指定进程fork后要执行的程序
  };

  ZygoteConnection.Arguments parsedArgs = new ZygoteConnection.Arguments(args);
  ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
  ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

  // 从zygote进程fork system_server进程
  int pid = Zygote.forkSystemServer(
      parsedArgs.uid, parsedArgs.gid,
      parsedArgs.gids,
      parsedArgs.debugFlags,
      null,
      parsedArgs.permittedCapabilities,
      parsedArgs.effectiveCapabilities);

  return true;
}

这段代码中指定了 fork 新进程的名称为system_server,当进程被 fork 后会调用com.android.server.SystemServer#main()方法。

先简单的看一下 fork 新进程的方法:

    /**
     * Fork system_server进程,并返回该进程的pid
     */
    public static int forkSystemServer(int uid, int gid, ...) {
        VM_HOOKS.preFork();

        //
        int pid = nativeForkSystemServer(uid, gid, ...);

        VM_HOOKS.postForkCommon();
        return pid;
    }

    native private static int nativeForkSystemServer(int uid, int gid, ...);

上述代码也比较清晰明了,实际上是调用了native方法 fork 了一个新的进程。

SystemServer.java 初始化 system_server 进程的过程

接着会执行com.android.server.SystemServer#main()方法,我们看一下该方法:

public final class SystemServer {
  /**
    * The main entry point from zygote.
    */
  public static void main(String[] args) {
    new SystemServer().run();
  }

  public SystemServer() {
    mFactoryTestMode = FactoryTest.getMode();
    mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
  }

  private void run() {
    ...

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

    // Within the system server, any incoming Bundles should be defused
    // to avoid throwing BadParcelableException.
    BaseBundle.setShouldDefuse(true);

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

    // Increase the number of binder threads in system_server
    BinderInternal.setMaxThreads(sMaxBinderThreads);

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

    // 初始化家在系统的native服务组件
    System.loadLibrary("android_servers");

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

    // 初始化系统Context
    createSystemContext();

    // 创建系统服务管理器,这个很关键
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

    // Prepare the thread pool for init tasks that can be parallelized
    SystemServerInitThreadPool.get();

    // 启动一些系统核心服务,很关键
    startBootstrapServices();
    startCoreServices();
    startOtherServices();

    SystemServerInitThreadPool.shutdown();

    ...

    // 让MainLooper无限循环的运行下去
    Looper.loop();
    hrow new RuntimeException("Main thread loop unexpectedly exited");
  }
}

看到这一段代码时我们可能会有一种在黑暗中走了很久,终于看到阳光的感觉,我们看到main()方法中实例化了SystemServer,并调用该对象的run()方法,然后开始初始化system_server进程,该方法主要做了以下几件事:

  1. 一些有关系统的初始化工作,例如 VM 虚拟机、运行时环境和线程池优先级等
  2. 调用Looper#prepareMainLooper()准备 Android 主线程Looper
  3. 调用System#loadLibrary()初始化native环境
  4. 调用createSystemContext()创建应用上下文
  5. 实例化SystemServiceManager以备后续启动系统中的其他核心服务
  6. 调用startServices()启动相关核心服务
  7. 调用Looper#loop()让主线程的Looper跑起来

这里的Looper#loop()和上文中platform/system/core/init.cpp保活init进程的原理相同,都是使用 Linux 的epoll原理,关于Looper的更多知识点请参阅这篇文章:
https://yanzhenjie.blog.csdn.net/article/details/89218745

创建系统上下文:

接下来看一个超级简单又复杂的方法,创建系统上下文:

  private Context mSystemContext;

  private void createSystemContext() {
    ActivityThread activityThread = ActivityThread.systemMain();
    mSystemContext = activityThread.getSystemContext();
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

    final Context systemUiContext = activityThread.getSystemUiContext();
    systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
  }

有些同学觉得 Android 的Context有点飘,但是想象 Java 这个面向对象语言,我们猜测它应该也是个普通对象吧,那么从这里更加证明了其实它也就是个普通的类,是个普通的对象而,只是它的能力可能比较多,不同的应用进程有不同的 Context 对象,通过 Context 可以获取该进程中应用的相关信息,然后我们再针对性的学习它在不同的情景下的能力就可以了。

启动系统核心服务

SystemServer#run()方法中有以下几个非常重要的方法调用:

startBootstrapServices();
startCoreServices();
startOtherServices();

我们依次观察这三个方法的源代码,首先是startBootstrapServices(),名字取得非常一目了然,望文生义,该访问是启动引导服务的,我们来看看启动了哪些服务:

/**
 * Starts the small tangle of critical services that are needed to get
 * the system off the ground.  These services have complex mutual dependencies
 * which is why we initialize them all in one place here.  Unless your service
 * is also entwined in these dependencies, it should be initialized in one of
 * the other functions.
 */
private void startBootstrapServices() {
  ...
  Installer installer = mSystemServiceManager.startService(Installer.class);

  mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);

  // 启动AMS,Acitivity管理服务
  mActivityManagerService = mSystemServiceManager.startService(
      ActivityManagerService.Lifecycle.class).getService();
  mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
  mActivityManagerService.setInstaller(installer);

  // 启动电源管理服务
  mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
  mActivityManagerService.initPowerManagement();

  mSystemServiceManager.startService(LightsService.class);

  // 启动显示管理服务
  mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
  mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

  ...

  // 启动包管理服务
  mPackageManagerService = PackageManagerService.main(mSystemContext,
    installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
  mFirstBoot = mPackageManagerService.isFirstBoot();
  mPackageManager = mSystemContext.getPackageManager();

  // 启动用户管理服务
  mSystemServiceManager.startService(UserManagerService.LifeCycle.class);

  // 初始化缓存包中资源属性
  AttributeCache.init(mSystemContext);

  // 为系统进程设置Application实例
  mActivityManagerService.setSystemProcess();

  ...
}

这段代码启动很多系统中的关键服务,如果深扒还有很多有趣的东西。这里比较有趣的是最后一句,我们可以简单的拿出一两句来瞅瞅,打开com.android.server.am.ActivityManagerServer#setSystemProcess()

public void setSystemProcess() {
  ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
  ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
  ServiceManager.addService("meminfo", new MemBinder(this));
  ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
  ServiceManager.addService("dbinfo", new DbBinder(this));
  if (MONITOR_CPU_USAGE) {
    ServiceManager.addService("cpuinfo", new CpuBinder(this));
  }
  ServiceManager.addService("permission", new PermissionController(this));
  ServiceManager.addService("processinfo", new ProcessInfoService(this));

  ApplicationInfo info = mContext.getPackageManager()
      .getApplicationInfo("android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
  mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

  ...
}

看到第一句我们可能想起,我们获取ActivityManager的方式:

ActivityManager am = Context.getSystemService(Context.ACTIVITY_SERVICE);

没错,它们是息息相关的东西,后面我会发布专门的文章来分析这个。

startCoreServices()方法和startOtherServices()方法也是启动一些核心服务,例如:

IStorageManager storageManager = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
NetworkScoreService networkScore = null;
NsdService serviceDiscovery= null;
WindowManagerService wm = null;
SerialService serial = null;
NetworkTimeUpdateService networkTimeUpdater = null;
CommonTimeManagementService commonTimeMgmtService = null;
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
ConsumerIrService consumerIr = null;
MmsServiceBroker mmsService = null;
HardwarePropertiesManagerService hardwarePropertiesService = null;

我们在这里不深究了,我自己是把这块代码都看了一遍,建议读者也认真的阅读一遍,对我们的启发很大。

zygote 进程等待 Socket 客户端的请求

目光回到ZygoteInit#main()中,我回顾下该方法最后的几句代码:

    // 这里一定是true,启动SystemServer
    if (startSystemServer) {
        startSystemServer(abiList, socketName, zygoteServer);
    }

    // 运行zygote进程的select循环
    zygoteServer.runSelectLoop(abiList);

    ...

可以看到,在成功的创建LocalServerSocket对象后,就执行了zygote进程的select循环,该方法还是在ZygoteServer.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.
  *
  * @throws Zygote.MethodAndArgsCaller in a child process when a main()
  * should be executed.
  */
void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

    fds.add(mServerSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            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) {
            if ((pollFds[i].revents & POLLIN) == 0) {
                 continue;
            }
            if (i == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                boolean done = peers.get(i).runOnce(this);
                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

这里就是不停的从LocalServerSocket接受新连接,并且从一个spawn-request的连接中一次性读取读取命令行调用ZygoteConnection#runOne(Ser)。其实就是等待 AMS 来连接这个 Socket,以便启动新的进程来处理后续的事情。

直到这里,zygote进程的启动和初始化就全部执行完毕,然后等待其他进程的请求再做其他的事,这里面错综复杂的地方很多,在本文中我们没有去深究,其实每一个分支我们都可以单独写一篇甚至几篇文章来分析。

最后我们对整个流程做个梳理:

  1. 系统启动时执行init进程,init的程序准备工作做完后会fork一个名为zygote的进程

    • 该程序的代码位于platform/system/core/init/init.cpp
    • 使用死循环 + Linuxepoll机制,使init进程持续运行
  2. init.zygote.rc配置文件指令告诉init进程执行/system/bin/app_process程序

    • 该程序的代码位于platform/framework/base/cmds/app_process/app_main.cpp
  3. 根据init.zygote.rc的指令参数,app_process最终反射调用了com.android.internal.os.ZygoteInit#main()Java 方法,该方法用来初始化zygote进程

    • /dev/socket目录下创建一个名为zygote的 Socket 资源
    • 调用ZygoteInit#starSystemServer()方法启动system_server进程
    • 调用ZygoteInit#runSelectLoop()方法循环接受客户端 Socket 连接请求,使zygote进程持续运行
  4. ZygoteInit#main()调用ZygoteInit#startSystemServer()调用Zygote#forkSystemServer()创建system_server进程,并指定该进程执行com.android.sever.SystemServer#main()方法

  5. SystemServer#main()方法初始化system_server进程,其中主要做了以下几件事

    • 创建system_server进程的 Context(System Context)
    • 启动 AMS 和 WMS 等系统核心服务
    • 调用Looper#prepareMainLooper()准备 MainLooper
    • 调用Looper#loop()让 MainLooper 无限循环运行,使system_server进程持续运行

    Looper#loop()方法中调用的是MessageQueue#next(),该方法中使用死循环 + Linuxepoll机制持续运行程序

  6. 最终zygote执行句柄在ZygoteServer#runSelectLoop()中无限循环运行,使zygote进程持续运行

此时,系统启动完成,当我们需要启动一个 Android AMS 会通过 Socket 进程进行 IPC 通信,通知zygote进程为这个应用程序创建一个新的进程。

本文到此结束,告辞!


版权声明:转载必须注明本文转自严振杰的博客:http://blog.yanzhenjie.com

你可能感兴趣的:(Android,源码分析)