Zygote启动流程(AndroidV)

一:背景

众所周知,Android应用及system_server基本都是由zygote fork出来的,那么zygote是如何启动的、又是如何接收fork进程的请求,接下来一步步揭秘。

二:启动流程

init进程是Android系统启动时,启动的第一个进程,其他所有进程基本都是由init进程来启动,其中也包括zygote,下面看下zygote的启动。

2.1 init进程启动zygote

init.rc里,在late-init阶段会触发zygote-start,zygote-start会启动zygote服务。在zygote服务中会启动app_process64(即zygote)并传入必要参数。

//system/core/rootdir/init.rc
on late-init
    ...
    # Now we can start zygote.
    trigger zygote-start
    ...

//system/core/rootdir/init.rc
on zygote-start
    ...
    # 启动zygote服务
    start zygote
    start zygote_secondary

//system/core/rootdir/init.zygote64.rc
#启动app_process64时传参:-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    priority -20
    ...

2.2 zygote初始化

2.2.1 AndroidRuntime.start

  • 启动java虚拟机,根据"dalvik.vm.xxx"属性值进行初始化

  • 注册jni函数

  • 调用ZygoteInit的main函数

    //frameworks/base/cmds/app_main.cpp
    int main(int argc, char* const argv[])
    {
    ...
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

      ++i;  // Skip unused "parent dir" argument.
      //获取启动参数并根据参数初始化zygote、startSystemServer等值
      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 = (arg + 12);
          } else if (strncmp(arg, "--", 2) != 0) {
              className = arg;
              break;
          } else {
              --i;
              break;
          }
      }
      ...
      if (zygote) {
          runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
      ...
    

    }

    //frameworks/base/core/jni/AndroidRuntime.cpp
    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
    ...
    bool primary_zygote = false;
    for (size_t i = 0; i < options.size(); ++i) {
    if (options[i] == startSystemServer) {
    primary_zygote = true;
    /* track our progress through the boot sequence /
    const int LOG_BOOT_PROGRESS_START = 3000;
    LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
    addBootEvent("boot_progress_start");
    }
    }
    ...
    //启动java虚拟机,根据"dalvik.vm.xxx"属性值进行初始化
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
    return;
    }
    ...
    //注册jni函数
    if (startReg(env) < 0) {
    ALOGE("Unable to register all android natives\n");
    return;
    }
    ...
    //将className中的.替换为/ ,转换之后slashClassName的值为"com/android/internal/os/ZygoteInit"
    char
    slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
    ...
    } else {
    //获取main函数
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
    "([Ljava/lang/String;)V");
    if (startMeth == NULL) {
    ...
    } else {
    //调用ZygoteInit的main函数
    env->CallStaticVoidMethod(startClass, startMeth, strArray);
    }
    }
    ...
    }

2.2.2 ZygoteInit.main

  • 在fork前做一些初始化工作,主要是enable DDMS

  • 提前加载框架通用类和系统资源

  • fork进程之前进行一次gc

  • 初始化seLinux

  • 初始化storage

  • 创建zygote的服务端对象

    //frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    public static void main(String[] argv) {
    ZygoteServer zygoteServer = null;
    ...

          //zygote运行在单独的进程组中
          try {
              Os.setpgid(0, 0);
          }
          ...
    
          Runnable caller;
          try {
              ...
              bootTimingsTraceLog.traceBegin("ZygoteInit");
              //做fork前的一些初始化工作,主要是enable DDMS
              RuntimeInit.preForkInit();
    
              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;
                  } else if ("--enable-lazy-preload".equals(argv[i])) {
                      enableLazyPreload = true;
                  } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                      abiList = argv[i].substring(ABI_LIST_ARG.length());
                  } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                      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 (!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
              }
    
              bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
              //fork进程之前进行一次gc
              gcAndFinalize();
              bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
    
              bootTimingsTraceLog.traceEnd(); // ZygoteInit
    
              ...
              //native初始化
              Zygote.initNativeState(isPrimaryZygote);
              ...
              //创建zygote的服务端对象
              zygoteServer = new ZygoteServer(isPrimaryZygote);
    
    
              if (startSystemServer) {
                  //fork system_server进程
                  Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                  if (r != null) {
                      r.run();
                      return;
                  }
              }
    
              ...
              caller = zygoteServer.runSelectLoop(abiList);
          }
          ...
    
          //在单独的线程中接收来自应用的zygote请求
          if (caller != null) {
              caller.run();
          }
      }
    

    //frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    static void preload(TimingsTraceLog bootTimingsTraceLog) {
    ...
    //加载/system/etc/preloaded-classes定义的所有的类
    preloadClasses();
    ...
    //加载frameworks/base/core/res/res/values/arrays.xml中preloaded_drawables和preloaded_color_state_lists定义的所有资源
    Resources.preloadResources();
    ...
    //加载graphic的hal
    nativePreloadAppProcessHALs();
    ...
    //加载graphic
    maybePreloadGraphicsDriver();
    ...
    //加载android、jnigraphics、compiler_rt这三个共享库
    preloadSharedLibraries();
    //加载字体资源
    preloadTextResources();
    ...
    }

    //frameworks/base/core/java/com/android/internal/os/Zygote.java
    static void initNativeState(boolean isPrimary) {
    nativeInitNativeState(isPrimary);
    }

    //frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
    static void com_android_internal_os_Zygote_nativeInitNativeState(JNIEnv* env, jclass,
    jboolean is_primary) {
    //从环境中获取init创建的文件描述符。
    gZygoteSocketFD =
    android_get_control_socket(is_primary ? "zygote" : "zygote_secondary");
    ...
    //创建用于向system_server发送未经请求的消息的socket,在app申请zygote fork进程时被调用,fork完成后关闭
    initUnsolSocketToSystemServer();
    ...
    //初始化seLinux
    gIsSecurityEnforced = security_getenforce();
    selinux_android_seapp_context_init();

    //初始化storage
    UnmountStorageOnInit(env);
    
    //设置高优先级
    if (!SetTaskProfiles(0, {})) {
      zygote::ZygoteFailure(env, "zygote", nullptr, "Zygote SetTaskProfiles failed");
    }
    

    }

2.2.3 ZygoteInit.forkSystemServer

  • 设置启动system_server的参数,例如uid、gid、进程名称等

  • 调用Linux的fork函数来实现fork system_server进程

    //frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    private static Runnable forkSystemServer(String abiList, String socketName,
    ZygoteServer zygoteServer) {
    ...
    //设置启动system_server的参数
    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,3005,3006,3007,3009,3010,3011,3012",
    "--capabilities=" + capabilities + "," + capabilities,
    "--nice-name=system_server",
    "--runtime-args",
    "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
    "com.android.server.SystemServer",
    };
    ...
    try {
    ...
    //fork system_server
    pid = Zygote.forkSystemServer(...);
    }
    ...

          //子进程
          if (pid == 0) {
              ...
              zygoteServer.closeServerSocket();
              return handleSystemServerProcess(parsedArgs);
          }
          ...
      }
    

    //frameworks/base/core/java/com/android/internal/os/Zygote.java
    static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
    int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
    ZygoteHooks.preFork();

          int pid = nativeForkSystemServer(
                  uid, gid, gids, runtimeFlags, rlimits,
                  permittedCapabilities, effectiveCapabilities);
    
          //设置线程优先级为NORM_PRIORITY
          Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
          //ZygoteHooks.postForkCommon是Zygote进程中的一个钩子函数,它在Zygote进程fork出子进程后被调用。这个钩子函数的作用是在子进程中执行一些初始化操作,例如创建Binder线程池和消息循环等。
          ZygoteHooks.postForkCommon();
          return pid;
      }
    

    //frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
    static jint com_android_internal_os_Zygote_nativeForkSystemServer(...) {
    ...
    pid_t pid = zygote::ForkCommon(env, true,
    fds_to_close,
    fds_to_ignore,
    true);
    ...
    return pid;
    }

    //frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
    pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,
    const std::vector<int>& fds_to_close,
    const std::vector<int>& fds_to_ignore,
    bool is_priority_fork,
    bool purge) {
    ATRACE_CALL();
    if (is_priority_fork) {//设置最大优先级
    setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
    }

    //设置信号处理程序
    SetSignalHandlers();
    ...
    //阻断信号
    BlockSignal(SIGCHLD, fail_fn);
    
    ...
    //真正fork进程的地方,在父进程中,fork()返回新创建子进程的PID,而在子进程中,fork()返回0。
    pid_t pid = fork();
    
    ...
    //解除阻断信号
    UnblockSignal(SIGCHLD, fail_fn);
    
    if (is_priority_fork && pid != 0) {//设置优先级为PROCESS_PRIORITY_DEFAULT
      setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT);
    }
    
    return pid;
    

    }

2.2.4 RuntimeInit.applicationInit

  • 获取SystemServer.java类对应的ClassLoader
  • 初始化时区、User-Agent等
  • 开启线程池
  • 调用SystemServer的main函数,开始启动系统服务等

这个时候system_server进程就启动了,开始启动系统服务等

//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
        ...
        if (parsedArgs.mInvokeWith != null) {
            ...
        } else {
            //获取SystemServer.java类对应的ClassLoader
            ClassLoader cl = getOrCreateSystemServerClassLoader();
            ...
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }
    }

//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        ...
        //初始化时区、User-Agent等
        RuntimeInit.commonInit();
        //开启线程池
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

//frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        ...
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

//frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
    protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

        try {
            //获取SystemServer类
            cl = Class.forName(className, true, classLoader);
        }
        ...

        Method m;
        try {
            //获取main函数
            m = cl.getMethod("main", new Class[] { String[].class });
        }
        ...
        //调用SystemServer的main函数,开始启动系统服务等
        return new MethodAndArgsCaller(m, argv);
    }

2.2.5 ZygoteServer.runSelectLoop

在线程里启动一个死循环,接收请求fork的socket请求

//frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
    Runnable runSelectLoop(String abiList) {
        ...
        while (true) {
            ...
            if (pollReturnValue == 0) {
                ...
            } else {
                ...
                while (--pollIndex >= 0) {
                    if (pollIndex == 0) {
                        ...
                    } else if (pollIndex < usapPoolEventFDIndex) {
                        try {
                            //获取socket连接
                            ZygoteConnection connection = peers.get(pollIndex);
                            boolean multipleForksOK = !isUsapPoolEnabled()
                                    && ZygoteHooks.isIndefiniteThreadSuspensionSafe();
                            //处理来自应用请求fork的socket请求
                            final Runnable command =
                                    connection.processCommand(this, multipleForksOK);
                        }
                        ...
                    }
                }
                ...
            }
            ...
        }
    }

三:小结

3.1 zygote进程是否只有一个?

答:不是。

zygote进程一般都会有zygote和zygote64两个,分别用来fork32位和64位的应用,这两个进程都是在init.rc中启动的。

如果系统中有webview类应用,那么还会存在webview_zygote这个进程,用来fork webview类应用。webview_zygote进程的启动是在ProcessList的startProcess函数中判断是否是webview类型应用,如果是则会调用Process的startWebView函数,接着会判断webview_zygote进程是否存在,如果不存在则调用zygote fork出来。

3.2 是否每次应用冷启动时都要调用zygote的fork函数?

答:不是。

Android系统有usap机制,会在Android系统启动时,开启一个进程池。如果usap功能打开,当有fork请求到来时,会先从进程池中取出一个进程返回,节约启动时间。

相关推荐
Henry_He1 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗1 小时前
Android笔试面试题AI答之Android基础(1)
android
qq_397562312 小时前
android studio更改应用图片,和应用名字。
android·ide·android studio
峥嵘life2 小时前
Android Studio版本升级那些事
android·ide·android studio
新手上路狂踩坑2 小时前
Android Studio的笔记--BusyBox相关
android·linux·笔记·android studio·busybox
TroubleMaker5 小时前
OkHttp源码学习之retryOnConnectionFailure属性
android·java·okhttp
叶羽西7 小时前
Android Studio IDE环境配置
android·ide·android studio
发飙的蜗牛'7 小时前
23种设计模式
android·java·设计模式
花追雨16 小时前
Android -- 双屏异显之方法一
android·双屏异显
小趴菜822716 小时前
安卓 自定义矢量图片控件 - 支持属性修改矢量图路径颜色
android