栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

<Android开发> Android内核系统开发-启动过程详解(第2部分 系统关键服务的启动简析)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

<Android开发> Android内核系统开发-启动过程详解(第2部分 系统关键服务的启动简析)

<Android开发> Android内核系统开发-启动过程详解(第2部分 系统关键服务的启动简析)

继上一篇介绍语法后,接下来详细看看init进程解析init.rc后启动的一些关键的系统服务进程,其中最重要的有ServiceManager、Zygote和SystemServer。

一、Android的“DNS服务器”--------ServiceManager
ServiceManager是Binder机制中的“DNS服务器”,负责域名(某Binder服务在ServiceManager注册时提供的名称) 到IP地址(有底层Binder驱动分配的值)的解析。
在高通8155 LA.1.1 中 ServiceManager是在init.rc里由init进程启动。如下:

on init                                                                         #init事件
	.......略
    # Start logd before any other services run to ensure we capture all of their logs.
    # 在任何其他服务运行之前启动 logd 以确保我们捕获它们的所有日志。
    start logd              # 这个命令将启动一个服务 logd ,如果它没有处于运行状态的话

    # Start essential services.
    # 启动基本服务。
    start servicemanager        # 这个命令将启动一个服务 servicemanager ,如果它没有处于运行状态的话
    start hwservicemanager      # 这个命令将启动一个服务 hwservicemanager ,如果它没有处于运行状态的话
    start vndservicemanager     # 这个命令将启动一个服务 vndservicemanager ,如果它没有处于运行状态的话
    ......略

有servicemanager文件可看出,servicemanager是一个 Linux程序的执行文件。它在设备中的存储路径是“/system/bin/servicemanager”(需要进入root才能查询到,如下图),源码路径则是“frameworks/native/cmds/servicemanager”。

servicemanager的启动描述则在servicemanager.rc文件里,.rc文件位于“frameworks/native/cmds/servicemanager/servicemanager.rc”。高通8155的LA.1.1基线代码对于servicemanager的描述和启动的位置分在两个不同的.rc文件。servicemanager.rc具体启动描述内容如下:

service servicemanager /system/bin/servicemanager
    class core animation                    #所属类是  core 和 animation
    user system                             #在启动服务前将用户切换至 system ,默认是root
    group system readproc                   #在启动服务前将用户组切换至 system 和 readproc
    critical                                #表明这是对设备至关重要的一个服务,如果4分钟内退出超过4次,则设备将重启进入恢复模式
    onrestart restart healthd               #当servicemanager重启时,重启  healthd 进程
    onrestart restart zygote                #当servicemanager重启时,重启  zygote 进程
    onrestart restart audioserver           #当servicemanager重启时,重启  audioserver 进程
    onrestart restart media                 #当servicemanager重启时,重启  media 进程
    onrestart restart surfaceflinger        #当servicemanager重启时,重启  surfaceflinger 进程
    onrestart restart inputflinger          #当servicemanager重启时,重启  inputflinger 进程
    onrestart restart drm                   #当servicemanager重启时,重启  drm 进程
    onrestart restart cameraserver          #当servicemanager重启时,重启  cameraserver 进程
    onrestart restart keystore              #当servicemanager重启时,重启  keystore 进程
    onrestart restart gatekeeperd           #当servicemanager重启时,重启  gatekeeperd 进程
    onrestart restart thermalservice        #当servicemanager重启时,重启  thermalservice 进程
    writepid /dev/cpuset/system-background/tasks # 当fork一个子进程时,写子进程的pid到一个给定的文件。是给cgroup/cpuset使用
    
    #设置服务进程的关闭行为。如果未指定此选项,则在关闭过程中通过使用SIGTERM和SIGKILL终止服务。
    #shutdown_behavior为"critical"时,服务在关闭期间不会被杀死,直到关闭超时为止。
    #当服务进程关闭超时时,即使标记为"shutdown critical"的服务也将被杀死。
    #当shutdown行为启动时,标有"shutdown critical"的服务未运行时,它将启动。
    shutdown critical                       #服务在关闭期间不会被杀死,直到关闭超时为止

由servicemanager.rc可看出,servicemanager所属class是core,其它同类的系统进程包括ueventd、console(/system/bin/sh)、adbd等。根据core组的特性,这些进程会同时被启动或停止。另外,critical选项说明它是系统的关键进程,意味着如果进程不幸在4分钟异常退出4次,则设备将重启进入还原模式。每当servicemanager重启时,其它关键进程也会被重启,如:healthd、zygote、audioserver、media、surfaceflinger、inputflinger、drm、cameraserver、keystore、gatekeeperd、thermalservice等。

二、Zygote—“孕育”新的线程和进程
Zygote这个词的字面意思时“受精卵”,因而可以“孕育”出一个“新生命”。在Android中大多数应用进程和系统进程都是通过Zygote来生成的。下面具体分析Zygote时如何启动的。
同servicemanager类似,Zygote也是由init解析rc脚本时启动的。在早期的Android版本中Zygote的启动命令是直接被写在init.rc中。但随着硬件等的不断升级换代,Android系统不得不面对32位和64位机器同时存在的状况,因而,对Zygote的启动也需要根据不同的情况区分对待,在高通平台中,在init.rc中加载Zygote的脚本描述如下:

import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc

根据系统属性ro.zygote的具体值,init.rc中加载不同的描述zygote的rc脚本,zygote的描述脚本包含“init.zygote32_64.rc”、“init.zygote32.rc”、“init.zygote64_32.rc”、“init.zygote64.rc”,具体文件如下:(目录:system/core/rootdir)

其中zygote32和zygote64分别对应32位和64位机器的情况,而zygote32_64和zygote64_32,则是Primary Arch和Secondary Arch的组合。
组合介绍如下:

路径:device/qcom/msmnile_au/BoardConfig.mk
BoardConfig.mk用于指定目标平台相关的不少属性,咱们能够在这个脚本中同时指定Primary和Secondary的CPU Arch和ABI:

与Primary Arch相关的变量有TARGET_ARCH、TARGET_ARCH_VARIANT、TARGET_CPU_VARIANT等,具体范例以下:

TARGET_ARCH := arm64
TARGET_ARCH_VARIANT := armv8-a
TARGET_CPU_ABI := arm64-v8a
TARGET_CPU_ABI2 :=
TARGET_CPU_VARIANT := generic

与Secondary Arch相关的变量有TARGET_2ND_ARCH、TARGET_2ND_ARCH_VARIANT、TARGET_2ND_CPU_VARIANT等,具体范例以下:

TARGET_2ND_ARCH := arm
TARGET_2ND_ARCH_VARIANT := armv7-a-neon
TARGET_2ND_CPU_ABI := armeabi-v7a
TARGET_2ND_CPU_ABI2 := armeabi
TARGET_2ND_CPU_VARIANT := cortex-a9

所以,由BoardConfig.mk可知,高通8155的LA.1.1基线中的“init.rc“-》“import /init.${ro.zygote}.rc“-》ro.zygote的值为“zygote64_32”,即Primary Arch为64,Secondary Arch为32。接下来详细看zygote64_32的内容,如下:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main                                              #所属类是  main
    priority -20                                            #设置服务进程的优先级.优先级取值范围为-20~19,默认是0.可以通过setpriority()设置
    user root                                               #在启动服务前将用户切换至 root ,默认是 root
    group root readproc reserved_disk                       #在启动服务前将用户组切换至 root 和 readproc 和 reserved_disk
    socket zygote stream 660 root system                    #创建一个名为 /dev/socket/zygote 的unix domian socket ,然后将它的fd值传给启动它的进程,有效的值为 stream (dgram,stream,seqpacket),权限 660 用户 root ,用户组 system
    socket usap_pool_primary stream 660 root system         #创建一个名为 /dev/socket/usap_pool_primary 的unix domian socket ,然后将它的fd值传给启动它的进程,有效的值为 stream (dgram,stream,seqpacket),权限 660 用户 root ,用户组 system
    onrestart write /sys/android_power/request_state wake   #当 zygote 重启时,写  wake 到 /sys/android_power/request_state
    onrestart write /sys/power/state on                     #当 zygote 重启时,写  on   到 /sys/power/state
    onrestart restart audioserver                           #当 zygote 重启时,重启  audioserver 进程
    onrestart restart cameraserver                          #当 zygote 重启时,重启  cameraserver 进程
    onrestart restart media                                 #当 zygote 重启时,重启  media 进程
    onrestart restart netd                                  #当 zygote 重启时,重启  netd 进程
    onrestart restart wificond                              #当 zygote 重启时,重启  wificond 进程
    writepid /dev/cpuset/foreground/tasks                   # 当fork一个子进程时,写子进程的pid到一个给定的文件。是给cgroup/cpuset使用

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
    class main                                          #所属类是  main
    priority -20                                        #设置服务进程的优先级.优先级取值范围为-20~19,默认是0.可以通过setpriority()设置
    user root                                           #在启动服务前将用户切换至 root ,默认是 root
    group root readproc reserved_disk                   #在启动服务前将用户组切换至 root 和 readproc 和 reserved_disk
    socket zygote_secondary stream 660 root system      #创建一个名为 /dev/socket/zygote_secondary    的unix domian socket ,然后将它的fd值传给启动它的进程,有效的值为 stream (dgram,stream,seqpacket),权限 660 用户 root ,用户组 system
    socket usap_pool_secondary stream 660 root system   #创建一个名为 /dev/socket/usap_pool_secondary 的unix domian socket ,然后将它的fd值传给启动它的进程,有效的值为 stream (dgram,stream,seqpacket),权限 660 用户 root ,用户组 system
    onrestart restart zygote                            #当 zygote_secondary 重启时,重启  zygote 进程
    writepid /dev/cpuset/foreground/tasks               # 当fork一个子进程时,写子进程的pid到一个给定的文件。是给cgroup/cpuset使用

从上面这段脚本描述可以看出:
存在两个服务 zygote 和 zygote_secondary;
zygote的path:/system/bin/app_process64
zygote_secondary的path:/system/bin/app_process32
zygote的Arguments:-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
zygote_secondary的Arguments:-Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload

zygote和zygote_secondary所属class都为main,而不是core。同class的系统进程有netd、debuggerd、rild等。从两者的路径可以看出,它们所在的程序名分别叫“ app_process64” 和 “ app_process32”,而不像ServiceManager一样在一个独立的程序中。通过指定–zygote 参数,app_process可以识别出用户是否需要启动zygote。那么app_process又是什么东东呢?app_process的源码路径在:frameworks/base/cmds/app_process中,先看看其Android.mk的内容,如下:

LOCAL_PATH:= $(call my-dir)

app_process_common_shared_libs := 
    libandroid_runtime 
    libbinder 
    libcutils 
    libdl 
    libhidlbase 
    liblog 
    libnativeloader 
    libutils 

# This is a list of libraries that need to be included in order to avoid
# bad apps. This prevents a library from having a mismatch when resolving
# new/delete from an app shared library.
# See b/21032018 for more details.
# 这是为了避免不良应用程序需要包含的库列表。 这可以防止库在从应用程序共享库中解析新/删除时出现不匹配。
# 详情请参阅 b/21032018。
app_process_common_shared_libs += 
    libwilhelm 

app_process_common_static_libs := 
    libsigchain 

app_process_src_files := 
    app_main.cpp 

app_process_cflags := 
    -Wall -Werror -Wunused -Wunreachable-code

app_process_ldflags_32 := 
    -Wl,--version-script,art/sigchainlib/version-script32.txt -Wl,--export-dynamic
app_process_ldflags_64 := 
    -Wl,--version-script,art/sigchainlib/version-script64.txt -Wl,--export-dynamic

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= $(app_process_src_files)

LOCAL_LDFLAGS_32 := $(app_process_ldflags_32)    #32位程序的ld标志
LOCAL_LDFLAGS_64 := $(app_process_ldflags_64)    #64位程序的ld标志

LOCAL_SHARED_LIBRARIES := $(app_process_common_shared_libs)         #共享库

LOCAL_WHOLE_STATIC_LIBRARIES := $(app_process_common_static_libs)   #静态库

LOCAL_MODULE:= app_process              #模块名称
LOCAL_MULTILIB := both                  #用于针对的硬件平台架构,可选项:"both":同时   "32":针对32  "64":针对64   " ":由系统根据其它变量决定
LOCAL_MODULE_STEM_32 := app_process32   #指定32位系统下的应用程序
LOCAL_MODULE_STEM_64 := app_process64   #指定64位系统下的应用程序

LOCAL_CFLAGS += $(app_process_cflags)

# In SANITIZE_LITE mode, we create the sanitized binary in a separate location (but reuse
# the same module). Using the same module also works around an issue with make: binaries
# that depend on sanitized libraries will be relinked, even if they set LOCAL_SANITIZE := never.
#
# Also pull in the asanwrapper helper.

# 在 SANITIZE_LITE 模式下,我们在单独的位置创建经过清理的二进制文件(但重用相同的模块)。 
# 使用相同的模块也可以解决 make 的问题:依赖于已清理库的二进制文件将被重新链接,即使它们设置 LOCAL_SANITIZE := never。
# 同时引入 asanwrapper 助手。
ifeq ($(SANITIZE_LITE),true)
LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)/asan
LOCAL_REQUIRED_MODULES := asanwrapper
endif

include $(BUILD_EXECUTABLE)

# Create a symlink from app_process to app_process32 or 64
# depending on the target configuration.
# 根据目标配置创建从 app_process 到 app_process32 或 64 的符号链接。
ifneq ($(SANITIZE_LITE),true)
include  $(BUILD_SYSTEM)/executable_prefer_symlink.mk
endif

从上面的描述可看到,app_process其实扮演的类似一个外壳,实际是去调用 app_process64 或app_process32程序。那么app_process具体内容有哪些呢?下面分析app_process.cpp中的main主函数的实现,内容如下:

int main(int argc, char* const argv[])
{
    
    if (!LOG_NDEBUG) {
      String8 argv_String;
      for (int i = 0; i < argc; ++i) {
        argv_String.append(""");
        argv_String.append(argv[i]);
        argv_String.append("" ");
      }
      ALOGV("app_process main with argv: %s", argv_String.string());
    }

    //Android运行时环境
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // Process command line arguments  处理命令行参数
    // ignore argv[0]   忽略 argv[0]
    argc--;
    argv++;

    // Everything up to '--' or first non '-' arg goes to the vm.
    //
    // The first argument after the VM args is the "parent dir", which
    // is currently unused.
    //
    // After the parent dir, we expect one or more the following internal
    // arguments :
    //
    // --zygote : Start in zygote mode
    // --start-system-server : Start the system server.
    // --application : Start in application (stand alone, non zygote) mode.
    // --nice-name : The nice name for this process.
    //
    // For non zygote starts, these arguments will be followed by
    // the main class name. All remaining arguments are passed to
    // the main method of this class.
    //
    // For zygote starts, all remaining arguments are passed to the zygote.
    // main function.
    //
    // Note that we must copy argument string values since we will rewrite the
    // entire argument block when we apply the nice name to argv0.
    //
    // As an exception to the above rule, anything in "spaced commands"
    // goes to the vm even though it has a space in it.

    // 直到 '--' 或第一个非 '-' arg 的所有内容都进入 vm。
    // VM args 后面的第一个参数是“父目录”,目前未使用。
    // 在父目录之后,我们期望一个或多个以下内部参数:
    // --zygote : 以 zygote 模式启动
    // --start-system-server : 启动系统服务器。
    // --application : 以应用程序(独立,非 zygote)模式启动。
    // --nice-name : 这个进程的好名字。
    // 对于非 zygote 启动,这些参数后跟主类名。所有剩余的参数都传递给这个类的 main 方法。
    // 对于 zygote 启动,所有剩余的参数都传递给 zygote。
    // 主功能。
    // 请注意,我们必须复制参数字符串值,因为当我们将 nice 名称应用于 argv0 时,我们将重写整个参数块。
    // 作为上述规则的一个例外,“间隔命令”中的任何内容都会进入 vm,即使其中有空格。
    const char* spaced_commands[] = { "-cp", "-classpath" };
    // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).
    // 允许“间隔命令”通过恰好 1 个参数(不管 -s)。
    bool known_command = false;

    int i;
    for (i = 0; i < argc; i++) {
        if (known_command == true) {            //判断参数是否存在
          runtime.addOption(strdup(argv[i]));   //将参数传给runtime
          // The static analyzer gets upset that we don't ever free the above
          // string. Since the allocation is from main, leaking it doesn't seem
          // problematic. NOLINTNEXTLINE
          // 静态分析器对我们没有释放上面的字符串感到不安。 由于分配来自 main,因此泄漏它似乎没有问题。 NOLINTNEXTLINE
          ALOGV("app_process main add known option '%s'", argv[i]);
          known_command = false;
          continue;
        }

        for (int j = 0;
             j < static_cast(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
             ++j) {
          if (strcmp(argv[i], spaced_commands[j]) == 0) {       //比较判断argv中的参数是否存在 和 spaced_commands中一样的部分
            known_command = true;                               //标记阐述存在
            ALOGV("app_process main found known command '%s'", argv[i]);
          }
        }

        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.        跳过 --开头的
            break;
        }

        runtime.addOption(strdup(argv[i]));  //将参数传给runtime
        // The static analyzer gets upset that we don't ever free the above
        // string. Since the allocation is from main, leaking it doesn't seem
        // problematic. NOLINTNEXTLINE
        // 静态分析器对我们没有释放上面的字符串感到不安。 由于分配来自 main,因此泄漏它似乎没有问题。 NOLINTNEXTLINE
        ALOGV("app_process main add option '%s'", argv[i]);
    }

    // Parse runtime arguments.  Stop at first unrecognized option.
    // 解析运行时参数。 在第一个无法识别的选项处停止。
    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   表示当前进程承载 zygote
            zygote = true;                                      //标记
            niceName = ZYGOTE_NICE_NAME;                        //别名
        } else if (strcmp(arg, "--start-system-server") == 0) { //判断参数存在  --start-system-server   表示需要启动 system server
            startSystemServer = true;                           //标记
        } else if (strcmp(arg, "--application") == 0) {         //判断参数存在  --application   表示启动进入独立的程序模式
            application = true;                                 //标记
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {     //判断参数存在  --nice-name=   表示设置进程别名为 = 后面的字串
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {                //判断参数存在  --   表示设置className 增加 --后面字串 作为数据
            className.setTo(arg);
            break;
        } else {
            --i;        //倒叙检索参数
            break;
        }
    }

    Vector args;
    if (!className.isEmpty()) {     //判断 非zygote
        // We're not in zygote mode, the only argument we need to pass
        // to RuntimeInit is the application argument.
        //
        // The Remainder of args get passed to startup class main(). Make
        // copies of them before we overwrite them with the process name.
        // 我们不是在 zygote 模式下,我们需要传递给 RuntimeInit 的唯一参数是应用程序参数。
         // args 的剩余部分被传递给启动类 main()。 在我们用进程名称覆盖它们之前制作它们的副本。
        args.add(application ? String8("application") : String8("tool"));  //如果参数 包含 application 则添加application作为数据 否则为tool
        runtime.setClassNameAndArgs(className, argc - i, argv + i); //设置Android运行时环境 runtime 的类名和参数

        //调试信息,输出类名和参数
        if (!LOG_NDEBUG) {
          String8 restOfArgs;
          char* const* argv_new = argv + i;
          int argc_new = argc - i;
          for (int k = 0; k < argc_new; ++k) {
            restOfArgs.append(""");
            restOfArgs.append(argv_new[k]);
            restOfArgs.append("" ");
          }
          ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
        }
    } else {
        // We're in zygote mode.
        // 我们处于 zygote 模式。
        maybeCreateDalvikCache();

        if (startSystemServer) {    //判断 startSystemServer 参数存在
            args.add(String8("start-system-server"));   //添加参数 start-system-server
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {     //ABI属性列表获取 列表参数
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",     
                ABI_LIST_PROPERTY); //无法从属性中确定 ABI 列表
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);   //abi标志列表  最加prop
        args.add(abiFlag);      //将列表 加入到 参数列表中

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        // 在 zygote 模式下,将所有剩余的参数传递给 zygote main() 方法。
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }

    if (!niceName.isEmpty()) {      //判断别名
        runtime.setArgv0(niceName.string(), true ); //设置runtime的setArgv0参数,即别名
    }

    if (zygote) {   //判断是  zygote ,启动zygote进程  传入args参数列表
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) { //非zygote 情况下,运行RuntimeInit进程 , 传入args参数列表
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {        //否则都不是,错误:没有提供类名或 --zygote。
        fprintf(stderr, "Error: no class name or --zygote supplied.n");
        app_usage();    //输出 启动命令的用法
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

这个函数用于解析启动app_process时传入的参数,具体参数如下:
–zygote:表示当前进行用于承载zygote
–start-system-server:是否需要启动system server
–application:启动进入独立的程序模式
–nice-name:此进程的“别名”

对于非zygote的情况下,在上述参数的末尾会跟上main class的名称,而后的其它参数则属于这个class的主函数传入的参数;
对于zygote的情况,所有参数则会作为它的主函数传入参数使用;

在前面的 init.zegote64_32.rc中指定了 “–zygote“选项,因而app_process接下来将启动“com.android.internal.os.ZygoteInit ”,并传入“start-system-server”。之后ZygoteInit会运行于Java虚拟机上,那为什么呢?
原因就是runtime这个变量,它实际上是一个AndroidRuntime对象,其start函数源码如下:


void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<FindClass("java/lang/String");   //找 string 类
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);  //新建string类的对象的队列
    assert(strArray != NULL);
    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);
    }

    
    
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'n", slashClassName);
        
    } else {
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'n", className);
            
        } else {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);

    ALOGD("Shutting down VMn");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main threadn");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanlyn");
}

对于虚拟机的具体启动和运行过程,等作者学习了后续在出相关文章讲解。
按照正常的启动流程,VM成功启动,并进入ZygoteInit执行;ZygoteInit执行源码如下:

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

        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        // 标记zygote开始。 这确保线程创建将引发错误。
        ZygoteHooks.startZygoteNoThreadCreation();

        // Zygote goes into its own process group.
        // Zygote 进入它自己的进程组。
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }

        Runnable caller;
        try {
            // Report Zygote start time to tron unless it is a runtime restart
            // 向 tron 报告 Zygote 启动时间,除非是运行时重启
            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
                MetricsLogger.histogram(null, "boot_zygote_init",
                        (int) SystemClock.elapsedRealtime());
            }

            String bootTimetag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
            TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimetag,
                    Trace.TRACE_TAG_DALVIK);
            bootTimingsTraceLog.traceBegin("ZygoteInit");
            RuntimeInit.enableDdms();

            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;                           //标记,需要启动 SystemServer
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;                           //标记, 使能 LazyPreload
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {          //abi列表参数
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {       //socket名参数
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }

            // 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);			  //预加载资源
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }

            // Do an initial gc to clean up after startup
            // 启动后执行初始 gc 清理
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

            bootTimingsTraceLog.traceEnd(); // ZygoteInit
            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            // 禁用跟踪,以便分叉的进程不会从 Zygote 继承陈旧的跟踪标记。
            Trace.setTracingEnabled(false, 0);


            Zygote.initNativeState(isPrimaryZygote);

            ZygoteHooks.stopZygoteNoThreadCreation();

            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {        //启动一个 SystemServer 进程
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                // {@code r == null} 在父 (zygote) 进程中,{@code r != null} 在子 (system_server) 进程中。
                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.
            // select 循环在 fork 之后的子进程中尽早返回,并在 zygote 中永远循环。
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

ZygoteInit的主函数主要完成以下几点:
—Socket—
zygote是一个孵化器,一旦有新程序需要运行时,系统会通过这个socket(完整名称为:zygote 、Zygote.PRIMARY_SOCKET_NAME))第一时间通知“总管事”Zygote,并由它负责实际的进程孵化过程。

—Preload预加载资源—
通过enableLazyPreload判断是否预加载资源。加载虚拟机运行时所需的资源,包括:
preloadClasses();
cacheNonBootClasspathClassLoaders();
preloadResources();
nativePreloadAppProcessHALs();
maybePreloadGraphicsDriver();
preloadSharedLibraries();
preloadTextResources();
从对应的名称可看出每个preload函数的作用。以preloadClasses为例,它负责加载和初始化常用的一些classes。这些需要预加载的classes被记录在"out/target/product/msmnile_au/system/etc/preloaded-classes"中,在高通8155的LA.1.1中如下所示:

# Preloaded-classes filter file for phones.
# Classes in this file will be allocated into the boot image, and forcibly initialized in
# the zygote during initialization. This is a trade-off, using virtual address space to share
# common heap between apps.
# This file has been derived for mainline phone (and tablet) usage.
#
android.R$styleable
android.accessibilityservice.AccessibilityServiceInfo$1
android.accessibilityservice.AccessibilityServiceInfo
android.accounts.Account$1
android.accounts.Account
android.accounts.AccountManager$10
android.accounts.AccountManager$11
android.accounts.AccountManager$18
android.accounts.AccountManager$1
android.accounts.AccountManager$20
android.accounts.AccountManager$2
android.accounts.AccountManager$AmsTask$1
android.accounts.AccountManager$AmsTask$Response
android.accounts.AccountManager$AmsTask
android.accounts.AccountManager$baseFutureTask$1
android.accounts.AccountManager$baseFutureTask$Response
....略

从输出文件中可以看出preloaded-classes中包含多达上千个classes,而且包括了libcore里面的重要基础资源,如:android.system、android.util等。另外,这个记录表通过“frameworks/base/tools/preload/WritePreloadedClassFile.java”生成。

—启动System Server—
如果app_process的调用参数中带有“start-system-server”,那么此时就会通过“forkSystemServer”来启动“SystemServer”。

Zygote在前期主要担当启动系统服务的工作,后期则又负责“程序孵化”的任务。但是Zygote只在init.rc中被启动一次,它又是如何协调这两者的工作关系呢?从前面的过程中,大致推断,上述中的“forkSystemServer”应该会新建一个专门的进程来承载系统服务的运行,而后app_process所在的进程转化为Zygote的“孵化器”守护进程。那么具体如何呢?接下来分析“forkSystemServer”的内容,如下:

  
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        long capabilities = posixCapabilitiesAsBits(
                OsConstants.CAP_IPC_LOCK,
                OsConstants.CAP_KILL,
                OsConstants.CAP_NET_ADMIN,
                OsConstants.CAP_NET_BIND_SERVICE,
                OsConstants.CAP_NET_BROADCAST,
                OsConstants.CAP_NET_RAW,
                OsConstants.CAP_SYS_MODULE,
                OsConstants.CAP_SYS_NICE,
                OsConstants.CAP_SYS_PTRACE,
                OsConstants.CAP_SYS_TIME,
                OsConstants.CAP_SYS_TTY_CONFIG,
                OsConstants.CAP_WAKE_ALARM,
                OsConstants.CAP_BLOCK_SUSPEND
        );
        
        
        StructCapUserHeader header = new StructCapUserHeader(
                OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
        StructCapUserData[] data;
        try {
            data = Os.capget(header);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to capget()", ex);
        }
        capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);

        
        
        String args[] = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        ZygoteArguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteArguments(args);
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);

            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);
            if (profileSystemServer) {
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }

            
            
            pid = Zygote.forkSystemServer(              //此处fork一个新的进程(子进程)
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        
        
        if (pid == 0) {                         //子进程,即System Server所承载进程
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);   //启动各个 System Server 
        }

        return null;
    }

上述代码段中又出现了我们熟悉的fork流程,forkSystemServer在内部利用UNIX的fork机制创建了一个新的进程;而这个“新生儿”(即pid=0分支)会在随后的执行过程中通过“handleSystemServerProcess”来启动各种支撑系统运行的 System Server。

在跟踪 System Server的具体启动过程之前,先来为Zygote接下来的工作做个分析,与我们之前所见的fork处理流程不同的是,ZygoteInit.java-》main()-》forkSystemServer()函数中并没有为父进程专门开辟一个代码分支,因而这个函数最后会通过return handleSystemServerProcess(parsedArgs) 返回到ZygoteInit.java-》main()中。在main()接着就是语句:
caller = zygoteServer.runSelectLoop(abiList);
从runSelectLoop的函数名可猜到,这很可能会是一个“死循环”,除非Zygote退出或者出现异常才会跳出循环,runSelectLoop函数内容如下:


**
     * 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 socketFDs = new ArrayList();
        ArrayList peers = new ArrayList();

        socketFDs.add(mZygoteSocket.getFileDescriptor());
        peers.add(null);    //添加null是为了保存fds和peers的一致性

        while (true) {      //死循环
            fetchUsapPoolPolicyPropsWithMinInterval();

            int[] usapPipeFDs = null;
            StructPollfd[] pollFDs = null;

            // Allocate enough space for the poll structs, taking into account
            // the state of the USAP pool for this Zygote (could be a
            // regular Zygote, a WebView Zygote, or an AppZygote).

            // 为轮询结构分配足够的空间,同时考虑此 Zygote 的 USAP 池的状态
            //(可以是常规 Zygote、WebView Zygote 或 AppZygote)。
            if (mUsapPoolEnabled) {
                usapPipeFDs = Zygote.getUsapPipeFDs();
                pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
            } else {
                pollFDs = new StructPollfd[socketFDs.size()];
            }

            
            
            int pollIndex = 0;
            for (FileDescriptor socketFD : socketFDs) {
                pollFDs[pollIndex] = new StructPollfd();
                pollFDs[pollIndex].fd = socketFD;
                pollFDs[pollIndex].events = (short) POLLIN;
                ++pollIndex;
            }

            final int usapPoolEventFDIndex = pollIndex;

            if (mUsapPoolEnabled) {
                pollFDs[pollIndex] = new StructPollfd();
                pollFDs[pollIndex].fd = mUsapPoolEventFD;
                pollFDs[pollIndex].events = (short) POLLIN;
                ++pollIndex;

                for (int usapPipeFD : usapPipeFDs) {
                    FileDescriptor managedFd = new FileDescriptor();
                    managedFd.setInt$(usapPipeFD);

                    pollFDs[pollIndex] = new StructPollfd();
                    pollFDs[pollIndex].fd = managedFd;
                    pollFDs[pollIndex].events = (short) POLLIN;
                    ++pollIndex;
                }
            }

            try {
                Os.poll(pollFDs, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }

            boolean usapPoolFDRead = false;

            while (--pollIndex >= 0) {      //
                if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                    continue;
                }

                if (pollIndex == 0) {       //有新的连接请求
                    // Zygote server socket
                    // Zygote 服务器套接字
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    socketFDs.add(newPeer.getFileDescriptor());

                } else if (pollIndex < usapPoolEventFDIndex) {      //已建立的连接中有客户端发过来的数据需要处理
                    // Session socket accepted from the Zygote server socket
                    // 从 Zygote 服务器套接字接受的会话套接字
                    try {
                        ZygoteConnection connection = peers.get(pollIndex);
                        final Runnable command = connection.processOneCommand(this);

                        // TODO (chriswailes): Is this extra check necessary?
                        // TODO (chriswailes): 这个额外的检查是必要的吗?
                        if (mIsForkChild) {
                            // We're in the child. We should always have a command to run at this
                            // stage if processoneCommand hasn't called "exec".
                            // 我们在孩子里面。 如果 processoneCommand 没有调用“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.
                            // 在我们尝试从 processoneCommand 中读取之前,我们不知道套接字的远程端是否已关闭。 
                            // 这在我们的常规处理循环中显示为常规 POLLIN 事件。
                            if (connection.isClosedByPeer()) {
                                connection.closeSocket();
                                peers.remove(pollIndex);
                                socketFDs.remove(pollIndex);
                            }
                        }
                    } 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.
                            // 我们在服务器中,所以这里的任何异常都是在处理命令或从控制套接字读取/写入时发生的 pre-fork。 
                            // 对任何此类异常大声喧哗,以便我们确切知道失败的原因和原因。            
                            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(pollIndex);
                            conn.closeSocket();

                            socketFDs.remove(pollIndex);
                        } 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.
                            // 我们在子进程中,所以这里捕获的任何异常都发生在分叉后和
                            // 执行 ActivityThread.main(或任何其他 main() 方法)之前。 记录异常的详细信息并关闭该过程。
                            Log.e(TAG, "Caught post-fork exception in child process.", e);
                            throw e;
                        }
                    } finally {
                        // Reset the child flag, in the event that the child process is a child-
                        // zygote. The flag will not be consulted this loop pass after the Runnable
                        // is returned.
                        // 如果子进程是子zygote,则重置子标志。 在 Runnable 返回后,将不会在此循环过程中查询标志。
                        mIsForkChild = false;
                    }
                } else {                            //出错情况
                    // Either the USAP pool event FD or a USAP reporting pipe.

                    // If this is the event FD the payload will be the number of USAPs removed.
                    // If this is a reporting pipe FD the payload will be the PID of the USAP
                    // that was just specialized.
                    // USAP 池事件 FD 或 USAP 报告管道。
                    // 如果这是事件 FD,则有效载荷将是移除的 USAP 的数量。 
                    // 如果这是一个报告管道 FD,则有效载荷将是刚刚专门化的 USAP 的 PID。
                    long messagePayload = -1;

                    try {
                        byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
                        int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);

                        if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
                            DataInputStream inputStream =
                                    new DataInputStream(new ByteArrayInputStream(buffer));

                            messagePayload = inputStream.readLong();
                        } else {
                            Log.e(TAG, "Incomplete read from USAP management FD of size "
                                    + readBytes);
                            continue;
                        }
                    } catch (Exception ex) {
                        if (pollIndex == usapPoolEventFDIndex) {
                            Log.e(TAG, "Failed to read from USAP pool event FD: "
                                    + ex.getMessage());
                        } else {
                            Log.e(TAG, "Failed to read from USAP reporting pipe: "
                                    + ex.getMessage());
                        }

                        continue;
                    }

                    if (pollIndex > usapPoolEventFDIndex) {
                        Zygote.removeUsapTableEntry((int) messagePayload);
                    }

                    usapPoolFDRead = true;
                }
            }

            // Check to see if the USAP pool needs to be refilled.
            // 检查是否需要重新填充 USAP 池。
            if (usapPoolFDRead) {
                int[] sessionSocketRawFDs =
                        socketFDs.subList(1, socketFDs.size())
                                .stream()
                                .mapToInt(fd -> fd.getInt$())
                                .toArray();

                final Runnable command = fillUsapPool(sessionSocketRawFDs);

                if (command != null) {
                    return command;
                }
            }
        }
    }
}

从上述程序可看到,runSelectLoop函数的主体部分确实是一和while循环,它将作为zygoted 守护体存在。因为zygote此时运行在虚拟机环境中,所以需要处理USAP 池的分配与管理的问题。
在mZygoteSocket.getFileDescriptor()获取的是Server socket的文件描述符,并添加到 ArrayList socketFDs ,这意味着zygote中不光只有一个socket产生。具体而言,while会先通过下面句子判断当前哪个fd处于可读状态。

try {
                Os.poll(pollFDs, -1);       //判断 当前轮训到的 pollFDs中的socketFD 是否处于可读状态
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }

当pollFDs中的socketFD指示的某个文件有可读数据时,pollFDs的revents成员的值会被修改。
pollIndex表示当前轮训的第几个socket,从最大值开始轮训。pollIndex大于或等于0时进入循环。

首先判断当前socket的事件 是否 时进入轮训状态,是的话进入重新循环,否则继续运行下面的判断。

if ((pollFDs[pollIndex].revents & POLLIN) == 0) {   //轮训
       continue;
   }

pollIndex = 0
此时表示有新的客户端连接,需要通过“ZygoteConnection newPeer = acceptCommandPeer(abiList);”接受来自客户端的连接,产生一个新的ZygoteConnection,然后分别更新peers和socketFDs,为了保证这两个列表中的对象序列号保存一致,可以看到peer在初始化时专门添加了一个null,对应的是Zygote Server Socket 这个“监听者”。

pollIndex < usapPoolEventFDIndex
usapPoolEventFDIndex是记录了socketFDs的数量的。此时说明已经建立Socket连接中有来自客户端的数据需要处理,完成具体工作的是connection.processoneCommand(this),该函数具体内容如下:


  
    
    Runnable processOneCommand(ZygoteServer zygoteServer) {
        String args[];
        ZygoteArguments parsedArgs = null;
        FileDescriptor[] descriptors;

        try {
            args = Zygote.readArgumentList(mSocketReader);

            // TODO (chriswailes): Remove this and add an assert.
            // TODO (chriswailes): 删除它并添加一个断言。
            descriptors = mSocket.getAncillaryFileDescriptors();
        } catch (IOException ex) {
            throw new IllegalStateException("IOException on command socket", ex);
        }

        // readArgumentList returns null only when it has reached EOF with no available
        // data to read. This will only happen when the remote socket has disconnected.
        // readArgumentList 仅在到达 EOF 且没有可读取的数据时才返回 null。 这只会在远程套接字断开连接时发生。
        if (args == null) {
            isEof = true;
            return null;
        }

        int pid = -1;
        FileDescriptor childPipeFd = null;
        FileDescriptor serverPipeFd = null;

        parsedArgs = new ZygoteArguments(args);

        if (parsedArgs.mAbiListQuery) {
            handleAbiListQuery();
            return null;
        }

        if (parsedArgs.mPidQuery) {
            handlePidQuery();
            return null;
        }

        if (parsedArgs.mUsapPoolStatusSpecified) {
            return handleUsapPoolStatusChange(zygoteServer, parsedArgs.mUsapPoolEnabled);
        }

        if (parsedArgs.mPreloadDefault) {
            handlePreload();
            return null;
        }

        if (parsedArgs.mPreloadPackage != null) {
            handlePreloadPackage(parsedArgs.mPreloadPackage, parsedArgs.mPreloadPackageLibs,
                    parsedArgs.mPreloadPackageLibFileName, parsedArgs.mPreloadPackageCacheKey);
            return null;
        }

        if (canPreloadApp() && parsedArgs.mPreloadApp != null) {
            byte[] rawParcelData = base64.getDecoder().decode(parsedArgs.mPreloadApp);
            Parcel appInfoParcel = Parcel.obtain();
            appInfoParcel.unmarshall(rawParcelData, 0, rawParcelData.length);
            appInfoParcel.setDataPosition(0);
            ApplicationInfo appInfo = ApplicationInfo.CREATOR.createFromParcel(appInfoParcel);
            appInfoParcel.recycle();
            if (appInfo != null) {
                handlePreloadApp(appInfo);
            } else {
                throw new IllegalArgumentException("Failed to deserialize --preload-app");
            }
            return null;
        }

        if (parsedArgs.mApiBlacklistExemptions != null) {
            return handleApiBlacklistExemptions(zygoteServer, parsedArgs.mApiBlacklistExemptions);
        }

        if (parsedArgs.mHiddenApiAccessLogSampleRate != -1
                || parsedArgs.mHiddenApiAccessStatslogSampleRate != -1) {
            return handleHiddenApiAccessLogSampleRate(zygoteServer,
                    parsedArgs.mHiddenApiAccessLogSampleRate,
                    parsedArgs.mHiddenApiAccessStatslogSampleRate);
        }

        if (parsedArgs.mPermittedCapabilities != 0 || parsedArgs.mEffectiveCapabilities != 0) {
            throw new ZygoteSecurityException("Client may not specify capabilities: "
                    + "permitted=0x" + Long.toHexString(parsedArgs.mPermittedCapabilities)
                    + ", effective=0x" + Long.toHexString(parsedArgs.mEffectiveCapabilities));
        }

        Zygote.applyUidSecurityPolicy(parsedArgs, peer);
        Zygote.applyInvokeWithSecurityPolicy(parsedArgs, peer);

        Zygote.applyDebuggerSystemProperty(parsedArgs);
        Zygote.applyInvokeWithSystemProperty(parsedArgs);

        int[][] rlimits = null;

        if (parsedArgs.mRLimits != null) {
            rlimits = parsedArgs.mRLimits.toArray(Zygote.INT_ARRAY_2D);
        }

        int[] fdsToIgnore = null;

        if (parsedArgs.mInvokeWith != null) {
            try {
                FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
                childPipeFd = pipeFds[1];
                serverPipeFd = pipeFds[0];
                Os.fcntlInt(childPipeFd, F_SETFD, 0);
                fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()};
            } catch (ErrnoException errnoEx) {
                throw new IllegalStateException("Unable to set up pipe for invoke-with", errnoEx);
            }
        }

        

        int [] fdsToClose = { -1, -1 };

        FileDescriptor fd = mSocket.getFileDescriptor();

        if (fd != null) {
            fdsToClose[0] = fd.getInt$();
        }

        fd = zygoteServer.getZygoteSocketFileDescriptor();

        if (fd != null) {
            fdsToClose[1] = fd.getInt$();
        }

        fd = null;

        pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
                parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
                parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);

        try {
            if (pid == 0) {
                // in child
                //在子进程
                zygoteServer.setForkChild(); //mIsForkChild 值为true

                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;

                return handleChildProc(parsedArgs, descriptors, childPipeFd,
                        parsedArgs.mStartChildZygote);
            } else {
                // In the parent. A pid < 0 indicates a failure and will be handled in
                // handleParentProc.
                // 在父级中。 pid < 0 表示失败,将在 handleParentProc 中处理。
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                handleParentProc(pid, descriptors, serverPipeFd);
                return null;
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
    }

函数processOneCommand比较长,其中重点内容是函数的后面部分,我们重点关注两点:

创建承载应用程序的新进程
这个是在意料之中的,zygote需要为每个新启动的应用程序生成自己独立的进程。不过processOneCommand中并没有直接使用fork来父进程的“收尾”工作
执行完上述的任务后,父进程还需要做一些清尾工作才算“大功告成”。包括:将子进程加入进程组;正确关闭文件;调用方返回结果值等。

Specialize的字面意思是“专门化”,表达了“forkAndSpecialize”在“孵化”的同时也把它转变为Android应用程序的目标。函数forkAndSpecialize的处理分为3个阶段,即 preFork、nativeForkAndSpecialize以及postForkCommon。函数内容如下:

    
    public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
            int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
            int targetSdkVersion) {
        ZygoteHooks.preFork();
        // Resets nice priority for zygote process.
        // 重置 zygote 进程的优先级。
        resetNicePriority();
        int pid = nativeForkAndSpecialize(
                uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                fdsToIgnore, startChildZygote, instructionSet, appDataDir);
        // Enable tracing as soon as possible for the child process.
        // 尽快为子进程启用跟踪。
        if (pid == 0) {
            Zygote.disableExecuteOnly(targetSdkVersion);
            Trace.setTracingEnabled(true, runtimeFlags);

            // Note that this event ends at the end of handleChildProc,
            // 注意这个事件在handleChildProc结束时结束,
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
        }
        ZygoteHooks.postForkCommon();
        return pid;
    }

preFork分析
preFork在Zygote中对应的实现如下:


static jlong ZygoteHooks_nativePreFork(JNIEnv* env, jclass) {
  Runtime* runtime = Runtime::Current();
  CHECK(runtime->IsZygote()) << "runtime instance not started with -Xzygote";

  runtime->PreZygoteFork();

  // Grab thread before fork potentially makes Thread::pthread_key_self_ unusable.
  // 在 fork 之前抓取线程可能会使 Thread::pthread_key_self_ 不可用。
  return reinterpret_cast(ThreadForEnv(env));
}

这里的Runtime实例具体而言指的是 Zygote进程中的运行环境(后续如果讲解虚拟机时在详细讲解)。而runtime->PreZygoteFork()又会间接调用Heap::PreZygoteFrok,从而完成堆栈空间的初始化。
函数nativeForkAndSpecialize是一个native方法。具体对应的实现是com_android_internal_os_Zygote_nativeForkAndSpecialize,后者有进一步调用了 ForkCommon 和 SpecializeCommon。
com_android_internal_os_Zygote_nativeForkAndSpecialize 函数内容如下:


static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
        JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits,
        jint mount_external, jstring se_info, jstring nice_name,
        jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
        jstring instruction_set, jstring app_data_dir) {
    jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);

    if (UNLIKELY(managed_fds_to_close == nullptr)) {
      ZygoteFailure(env, "zygote", nice_name, "Zygote received a null fds_to_close vector.");
    }

    std::vector fds_to_close =
        ExtractJIntArray(env, "zygote", nice_name, managed_fds_to_close).value();
    std::vector fds_to_ignore =
        ExtractJIntArray(env, "zygote", nice_name, managed_fds_to_ignore)
            .value_or(std::vector());

    std::vector usap_pipes = MakeUsapPipeReadFDVector();

    fds_to_close.insert(fds_to_close.end(), usap_pipes.begin(), usap_pipes.end());
    fds_to_ignore.insert(fds_to_ignore.end(), usap_pipes.begin(), usap_pipes.end());

    fds_to_close.push_back(gUsapPoolSocketFD);

    if (gUsapPoolEventFD != -1) {
      fds_to_close.push_back(gUsapPoolEventFD);
      fds_to_ignore.push_back(gUsapPoolEventFD);
    }

    pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore);

    if (pid == 0) {
      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                       capabilities, capabilities,
                       mount_external, se_info, nice_name, false,
                       is_child_zygote == JNI_TRUE, instruction_set, app_data_dir);
    }
    return pid;
}

ForkCommon函数的内容如下:


// Utility routine to fork a process from the zygote.
// 从 zygote 派生一个进程的实用程序。
static pid_t ForkCommon(JNIEnv* env, bool is_system_server,
                        const std::vector& fds_to_close,
                        const std::vector& fds_to_ignore) {
  SetSignalHandlers();

  // Curry a failure function.
  // Curry 一个失败函数。
  auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote",
                           nullptr, _1);

  // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
  // log, which would result in the logging FDs we close being reopened.
  // This would cause failures because the FDs are not whitelisted.
  //
  // Note that the zygote process is single threaded at this point.
  // 在分叉期间临时阻塞 SIGCHLD。 SIGCHLD 处理程序可能会记录日志,
  // 这将导致我们关闭的日志记录 FD 被重新打开。 这将导致失败,因为 FD 未列入白名单。
  // 注意此时zygote进程是单线程的。
  BlockSignal(SIGCHLD, fail_fn);

  // Close any logging related FDs before we start evaluating the list of
  // file descriptors.
  // 在我们开始评估文件描述符列表之前,关闭所有与日志记录相关的 FD。
  __android_log_close();
  stats_log_close();

  // If this is the first fork for this zygote, create the open FD table.  If
  // it isn't, we just need to check whether the list of open files has changed
  // (and it shouldn't in the normal case).
  // 如果这是此 zygote 的第一个分叉,则创建打开的 FD 表。 
  // 如果不是,我们只需要检查打开文件列表是否发生了变化(正常情况下不应该)。
  if (gOpenFdTable == nullptr) {
    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, fail_fn);
  } else {
    gOpenFdTable->Restat(fds_to_ignore, fail_fn);
  }

  android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level();

  pid_t pid = fork(); //这里真正孵化出一个新的进程

  if (pid == 0) {
    // The child process.
    // 子进程。
    PreApplicationInit();

    // Clean up any descriptors which must be closed immediately
    // 清理所有必须立即关闭的描述符
    DetachDescriptors(env, fds_to_close, fail_fn);

    // Invalidate the entries in the USAP table.
    // 使 USAP 表中的条目无效。
    ClearUsapTable();

    // Re-open all remaining open file descriptors so that they aren't shared
    // with the zygote across a fork.
    // 重新打开所有剩余的打开文件描述符,这样它们就不会通过 fork 与 zygote 共享。
    gOpenFdTable->ReopenOrDetach(fail_fn);

    // Turn fdsan back on.
    // 重新打开 fdsan。
    android_fdsan_set_error_level(fdsan_error_level);
  } else {  
    //父进程不做任何事,应为在 “frameworks/base/core/java/com/android/internal/os/ZygoteServer.java”中 connection.processoneCommand(this)里有处理
    ALOGD("Forked child process %d", pid);
  }

  // We blocked SIGCHLD prior to a fork, we unblock it here.
  // 我们在分叉之前阻塞了 SIGCHLD,我们在这里解除阻塞。
  UnblockSignal(SIGCHLD, fail_fn);

  return pid;
}

SpecializeCommon的内容如下:


// Utility routine to specialize a zygote child process.
// 用于专门化 zygote 子进程的实用程序。
static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
                             jint runtime_flags, jobjectArray rlimits,
                             jlong permitted_capabilities, jlong effective_capabilities,
                             jint mount_external, jstring managed_se_info,
                             jstring managed_nice_name, bool is_system_server,
                             bool is_child_zygote, jstring managed_instruction_set,
                             jstring managed_app_data_dir) {
  const char* process_name = is_system_server ? "system_server" : "zygote";
  auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
  auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);

  auto se_info = extract_fn(managed_se_info);
  auto nice_name = extract_fn(managed_nice_name);
  auto instruction_set = extract_fn(managed_instruction_set);
  auto app_data_dir = extract_fn(managed_app_data_dir);

  // Keep capabilities across UID change, unless we're staying root.
  // 保持跨 UID 更改的功能,除非我们保持 root。
  if (uid != 0) {
    EnableKeepCapabilities(fail_fn);
  }

  SetInheritable(permitted_capabilities, fail_fn);

  DropCapabilitiesBoundingSet(fail_fn);

  bool use_native_bridge = !is_system_server &&
                           instruction_set.has_value() &&
                           android::NativeBridgeAvailable() &&
                           android::NeedsNativeBridge(instruction_set.value().c_str());

  if (use_native_bridge && !app_data_dir.has_value()) {
    // The app_data_dir variable should never be empty if we need to use a
    // native bridge.  In general, app_data_dir will never be empty for normal
    // applications.  It can only happen in special cases (for isolated
    // processes which are not associated with any app).  These are launched by
    // the framework and should not be emulated anyway.
    // 如果我们需要使用本地网桥,app_data_dir 变量永远不应该为空。 
    // 通常,对于普通应用程序,app_data_dir 永远不会为空。 
    // 它只能在特殊情况下发生(对于与任何应用程序无关的隔离进程)。 
    // 这些是由框架启动的,无论如何都不应该被模拟。
    use_native_bridge = false;
    ALOGW("Native bridge will not be used because managed_app_data_dir == nullptr.");
  }

  MountEmulatedStorage(uid, mount_external, use_native_bridge, fail_fn);

  // If this zygote isn't root, it won't be able to create a process group,
  // since the directory is owned by root.
  // 如果这个 zygote 不是 root,它将无法创建进程组,因为该目录是由 root 拥有的。
  if (!is_system_server && getuid() == 0) {
    const int rc = createProcessGroup(uid, getpid());
    if (rc == -EROFS) {
      ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
    } else if (rc != 0) {
      ALOGE("createProcessGroup(%d, %d) failed: %s", uid,  0, strerror(-rc));
    }
  }

  SetGids(env, gids, is_child_zygote, fail_fn);
  SetRLimits(env, rlimits, fail_fn);

  if (use_native_bridge) {
    // Due to the logic behind use_native_bridge we know that both app_data_dir
    // and instruction_set contain values.
    // 由于 use_native_bridge 背后的逻辑,我们知道 app_data_dir 和 instruction_set 都包含值。
    android::PreInitializeNativeBridge(app_data_dir.value().c_str(),
                                       instruction_set.value().c_str());
  }

  if (setresgid(gid, gid, gid) == -1) {
    fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
  }

  // Must be called when the new process still has CAP_SYS_ADMIN, in this case,
  // before changing uid from 0, which clears capabilities.  The other
  // alternative is to call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that
  // breaks SELinux domain transition (see b/71859146).  As the result,
  // privileged syscalls used below still need to be accessible in app process.
  // 必须在新进程仍有 CAP_SYS_ADMIN 时调用,在这种情况下,在将 uid 从 0 更改为清除功能之前。 
  // 另一种选择是在之后调用 prctl(PR_SET_NO_NEW_PRIVS, 1),但这会中断 SELinux 域转换(参见 b/71859146)。 
  // 因此,下面使用的特权系统调用仍然需要在应用程序进程中访问。
  SetUpSeccompFilter(uid, is_child_zygote);

  if (setresuid(uid, uid, uid) == -1) {
    fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno)));
  }

  // The "dumpable" flag of a process, which controls core dump generation, is
  // overwritten by the value in /proc/sys/fs/suid_dumpable when the effective
  // user or group ID changes. See proc(5) for possible values. In most cases,
  // the value is 0, so core dumps are disabled for zygote children. However,
  // when running in a Chrome OS container, the value is already set to 2,
  // which allows the external crash reporter to collect all core dumps. Since
  // only system crashes are interested, core dump is disabled for app
  // processes. This also ensures compliance with CTS.
  // 当有效用户或组 ID 更改时,控制核心转储生成的进程的“dumpable”标志被 /proc/sys/fs/suid_dumpable 中的值覆盖。 
  // 有关可能的值,请参见 proc(5)。 在大多数情况下,该值为 0,因此对 zygote 子项禁用核心转储。 
  // 但是,在 Chrome OS 容器中运行时,该值已设置为 2,这允许外部崩溃报告器收集所有核心转储。 
  // 由于只对系统崩溃感兴趣,因此对应用程序进程禁用核心转储。 这也确保符合 CTS。
  int dumpable = prctl(PR_GET_DUMPABLE);
  if (dumpable == -1) {
    ALOGE("prctl(PR_GET_DUMPABLE) failed: %s", strerror(errno));
    RuntimeAbort(env, __LINE__, "prctl(PR_GET_DUMPABLE) failed");
  }

  if (dumpable == 2 && uid >= AID_APP) {
    if (prctl(PR_SET_DUMPABLE, 0, 0, 0, 0) == -1) {
      ALOGE("prctl(PR_SET_DUMPABLE, 0) failed: %s", strerror(errno));
      RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 0) failed");
    }
  }

  // Set process properties to enable debugging if required.
  // 如果需要,设置进程属性以启用调试。
  if ((runtime_flags & RuntimeFlags::DEBUG_ENABLE_JDWP) != 0) {
    EnableDebugger();
  }
  if ((runtime_flags & RuntimeFlags::PROFILE_FROM_SHELL) != 0) {
    // simpleperf needs the process to be dumpable to profile it.
    // simpleperf 需要进程可转储以对其进行分析。
    if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) {
      ALOGE("prctl(PR_SET_DUMPABLE) failed: %s", strerror(errno));
      RuntimeAbort(env, __LINE__, "prctl(PR_SET_DUMPABLE, 1) failed");
    }
  }

  if (NeedsNoRandomizeWorkaround()) {
    // Work around ARM kernel ASLR lossage (http://b/5817320).
    // 解决 ARM 内核 ASLR 丢失问题 (http://b/5817320)。
    int old_personality = personality(0xffffffff);
    int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
    if (new_personality == -1) {
      ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
    }
  }

  SetCapabilities(permitted_capabilities, effective_capabilities, permitted_capabilities, fail_fn);

  SetSchedulerPolicy(fail_fn);

  __android_log_close();
  stats_log_close();

  const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr;
  const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr;

  if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) {
    fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, "%s", "%s") failed",
                         uid, is_system_server, se_info_ptr, nice_name_ptr));
  }

  // Make it easier to debug audit logs by setting the main thread's name to the
  // nice name rather than "app_process".
  // 通过将主线程的名称设置为好听的名称而不是“app_process”,可以更轻松地调试审计日志。
  if (nice_name.has_value()) {
    SetThreadName(nice_name.value());
  } else if (is_system_server) {
    SetThreadName("system_server");
  }

  // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
  // 取消设置 SIGCHLD 处理程序,但继续忽略 SIGHUP(SetSignalHandlers 中的基本原理)。
  UnsetChldSignalHandler();

  if (is_system_server) {
    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks);
    if (env->ExceptionCheck()) {
      fail_fn("Error calling post fork system server hooks.");
    }

    // Prefetch the classloader for the system server. This is done early to
    // allow a tie-down of the proper system server selinux domain.
    // 预取系统服务器的类加载器。 这是尽早完成以允许绑定适当的系统服务器 selinux 域。
    env->CallStaticVoidMethod(gZygoteInitClass, gCreateSystemServerClassLoader);
    if (env->ExceptionCheck()) {
      // Be robust here. The Java code will attempt to create the classloader
      // at a later point (but may not have rights to use AoT artifacts).
      // 这里要健壮。 Java 代码稍后将尝试创建类加载器(但可能无权使用 AoT 工件)。
      env->ExceptionClear();
    }

    // TODO(oth): Remove hardcoded label here (b/117874058).
    // TODO(oth):在此处删除硬编码标签 (b/117874058)。
    static const char* kSystemServerLabel = "u:r:system_server:s0";
    if (selinux_android_setcon(kSystemServerLabel) != 0) {
      fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel));
    }
  }

  env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
                            is_system_server, is_child_zygote, managed_instruction_set);

  if (env->ExceptionCheck()) {
    fail_fn("Error calling post fork hooks.");
  }
}

首先在ForkCommon函数内,会先fork一个新进程,并在pid=0这一分支中为孵化出的进程完成一系列初始化操作,而后在SpecializeCommon函数内执行CallStaticVoidMethod函数。CallStaticVoidMethod函数的参数 gZygoteClass对应的是“com/android/internal/os/Zygote”,而gCallPostForkChildHooks则是Zygote这个类中的成员函数callPostForkChildHooks,从名称可看出其是用于执行孵化后的一些处理工作。
ForkCommon和SpecializeCommon都没有涉及与应用程序相关的具体业务,这部分由 “frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java”->processOneCommand中的handleChildProc()来完成。
函数handleChildProc的内容如下:



    private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
            FileDescriptor pipeFd, boolean isZygote) {
        
        
        closeSocket();
        if (descriptors != null) {
            try {
                Os.dup2(descriptors[0], STDIN_FILENO);
                Os.dup2(descriptors[1], STDOUT_FILENO);
                Os.dup2(descriptors[2], STDERR_FILENO);

                for (FileDescriptor fd: descriptors) {
                    IoUtils.closeQuietly(fd);
                }
            } catch (ErrnoException ex) {
                Log.e(TAG, "Error reopening stdio", ex);
            }
        }

        if (parsedArgs.mNiceName != null) {         //存在子进程的别名
            Process.setArgV0(parsedArgs.mNiceName); //设置子进程的别名
        }

        // End of the postFork event.
        // postFork 事件结束。
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        if (parsedArgs.mInvokeWith != null) {
            WrapperInit.execApplication(parsedArgs.mInvokeWith,             // 执行应用程序,正常情况下不返回
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(),
                    pipeFd, parsedArgs.mRemainingArgs);

            // Should not get here.
            // 不应该到这里。
            throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned"); //WrapperInit.execApplication 意外返回
        } else {    //否则重新初始化zygote
            if (!isZygote) {
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null );
            } else {
                return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null );
            }
        }
    }

这个函数的任务是,处理参数后调用WrapperInit.execApplication(),执行应用程序。Android系统中所有应用程序理论上都是由zygote启动的, 从前面的分析来看,不难发现zygote会为新启动的应用程序fork一个进程。不过和传统的内核中的fork+exec的作法不同的地方是,Zygote中并不会执行exec()。在这种情况下就会造成一些障碍,比如无法使用valgrind来监控程序的内存泄漏情况。android系统提供了一种Wrapper实现,并通过parsedArgs.mInvokeWith 来加以控制。有兴趣的读者可查阅相关资料。

在高通的这个基线代码中execApplication函数主要是分析参数后,调用shell执行运行程序的命令。execApplication的内容如下:



    public static void execApplication(String invokeWith, String niceName,
            int targetSdkVersion, String instructionSet, FileDescriptor pipeFd,
            String[] args) {
        StringBuilder command = new StringBuilder(invokeWith);

        final String appProcess;
        if (VMRuntime.is64BitInstructionSet(instructionSet)) {
            appProcess = "/system/bin/app_process64";
        } else {
            appProcess = "/system/bin/app_process32";
        }
        command.append(' ');
        command.append(appProcess);

        // Generate bare minimum of debug information to be able to backtrace through JITed code.
        // We assume that if the invoke wrapper is used, backtraces are desirable:
        //  * The wrap.sh script can only be used by debuggable apps, which would enable this flag
        //    without the script anyway (the fork-zygote path).  So this makes the two consistent.
        //  * The wrap.* property can only be used on userdebug builds and is likely to be used by
        //    developers (e.g. enable debug-malloc), in which case backtraces are also useful.
        // 生成最少的调试信息,以便能够通过 JITed 代码进行回溯。
        // 我们假设如果使用调用包装器,则需要回溯: wrap.sh 脚本只能由可调试的应用程序使用,
        // 这将在没有脚本的情况下启用此标志(fork-zygote 路径)。 所以这使得两者一致。 
        // wrap.* 属性只能在 userdebug 构建中使用,并且很可能被开发人员使用(例如启用 debug-malloc),在这种情况下回溯也很有用。
        command.append(" -Xcompiler-option --generate-mini-debug-info");

        command.append(" /system/bin --application");
        if (niceName != null) {
            command.append(" '--nice-name=").append(niceName).append("'");
        }
        command.append(" com.android.internal.os.WrapperInit ");
        command.append(pipeFd != null ? pipeFd.getInt$() : 0);
        command.append(' ');
        command.append(targetSdkVersion);
        Zygote.appendQuotedShellArgs(command, args);
        preserveCapabilities();
        Zygote.execShell(command.toString());
    }

在前面的handleChildProc这个函数中,会有一些会参数的处理,详细的了解需要对应用程序的启动由一个全局的认识。所以可以穿插阅读其它有关文档文章(后续作者也会持续更新)。这里假设运行的流程已经到了ActivityManagerService。

由于文章篇幅太长,本部分先讲解到这。后面文章将紧接这部分讲解分析流程。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/731691.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号