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请求到来时,会先从进程池中取出一个进程返回,节约启动时间。

相关推荐
一起搞IT吧10 分钟前
相机Camera日志实例分析之五:相机Camx【萌拍闪光灯后置拍照】单帧流程日志详解
android·图像处理·数码相机
浩浩乎@29 分钟前
【openGLES】安卓端EGL的使用
android
Kotlin上海用户组2 小时前
Koin vs. Hilt——最流行的 Android DI 框架全方位对比
android·架构·kotlin
zzq19962 小时前
Android framework 开发者模式下,如何修改动画过度模式
android
木叶丸2 小时前
Flutter 生命周期完全指南
android·flutter·ios
阿幸软件杂货间3 小时前
阿幸课堂随机点名
android·开发语言·javascript
没有了遇见3 小时前
Android 渐变色整理之功能实现<二>文字,背景,边框,进度条等
android
没有了遇见4 小时前
Android RecycleView 条目进入和滑出屏幕的渐变阴影效果
android
站在巨人肩膀上的码农4 小时前
去掉长按遥控器power键后提示关机、飞行模式的弹窗
android·安卓·rk·关机弹窗·power键·长按·飞行模式弹窗
呼啦啦--隔壁老王5 小时前
屏幕旋转流程
android