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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值