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) {
   
<think> 我们讨论的是Android系统中的Zygote进程启动流程ZygoteAndroid系统中的一个非常重要的进程,它的主要作用是孵化其他应用程序进程。在Android系统启动过程中,Zygote是由init进程根据init.rc配置文件启动的。 Zygote启动流程可以概括为以下几个步骤: 1. init进程启动后,解析init.rc配置文件,启动Zygote进程。 2. Zygote进程启动后,会创建一个Socket,用于接收启动新进程的请求。 3. Zygote进程会预加载一些类和资源,以提高应用程序启动的速度。 4. Zygote进程会进入循环,等待和处理创建新进程的请求。 下面我们详细描述一下Zygote启动流程: 1. **启动脚本**:在系统启动时,init进程会解析init.rc文件,该文件位于/system/core/rootdir/init.rc。在init.rc中,会启动一个名为zygote的服务,该服务执行/system/bin/app_process(或app_process64)可执行文件,并传入一些参数。 2. **执行app_process**:app_process的main函数(在app_main.cpp中)会被调用。它会解析传入的参数,然后启动Android运行时。在这个阶段,它会创建一个AppRuntime对象(它是AndroidRuntime的子类),然后调用它的start函数。 3. **启动虚拟机**:在AndroidRuntime::start函数中,会启动Java虚拟机(JVM),并注册JNI函数,然后调用ZygoteInit的main方法(通过JNI调用)。 4. **进入Java世界**:ZygoteInit的main方法(在ZygoteInit.java中)是Zygote进程的Java入口点。在这里,它会创建一个Server端的Socket(名为zygote),用于监听来自ActivityManagerService的请求。 5. **预加载**:在ZygoteInit中,会调用preload()方法,预加载一些常用的Java类、资源文件以及一些共享库。这样,每个由Zygote fork出来的进程都可以共享这些预加载的资源,从而加快应用程序的启动速度。 6. **循环等待请求**:预加载完成后,Zygote进程会进入一个循环,通过Socket等待来自ActivityManagerService的连接请求。当有新的应用程序启动请求时,Zygote会fork出一个新的进程,并在该进程中调用ActivityThread的main方法,从而启动应用程序。 由于Zygote启动流程涉及到底层C++代码和上层Java代码,我们不会在这里提供完整的代码实现,但可以给出一些关键代码片段。 下面是一个简化的流程,用伪代码表示: 在init.rc中: ``` service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server ... ``` 在app_main.cpp中: ```cpp int main(int argc, char* const argv[]) { ... // 解析参数 bool zygote = false; bool startSystemServer = false; // 解析参数,判断是否是zygote模式,是否启动SystemServer ... if (zygote) { // 启动运行时并调用ZygoteInit runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } ... } ``` 在AndroidRuntime.cpp中: ```cpp void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ... // 启动虚拟机 JNIEnv* env; if (startVm(&mJavaVM, &env, zygote) != 0) { return; } ... // 注册JNI函数 if (startReg(env) < 0) { return; } ... // 找到ZygoteInit类 jclass startClass = env->FindClass(className); jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); // 调用ZygoteInit的main方法 env->CallStaticVoidMethod(startClass, startMeth, strArray); ... } ``` 在ZygoteInit.java中: ```java public class ZygoteInit { public static void main(String argv[]) { // 创建Server Socket zygoteServer = new ZygoteServer(isPrimaryZygote); // 预加载 preload(bootTimingsTraceLog); // 如果是首次启动,则启动SystemServer if (startSystemServer) { forkSystemServer(...); } // 进入循环,等待请求 zygoteServer.runSelectLoop(...); } } ``` 以上代码片段展示了Zygote启动的关键步骤。 现在,根据要求,在最后提出相关问题: §§相关问题§§: 1. Zygote进程预加载了哪些资源和类? 2. 为什么Android系统要使用Zygote来孵化应用进程,而不是直接启动新进程? 3. Zygote进程如何接收并处理启动新应用的请求? 4. 在Zygote进程中fork新进程时,如何保证新进程不会继承父进程的所有状态(比如已注册的JNI函数等)? </think> ### Android Zygote启动流程详解 ZygoteAndroid 系统的核心进程,负责孵化所有 Android 应用进程和系统服务进程(如 SystemServer)。以下是完整的启动流程: #### 1. **init 进程启动 Zygote** - Linux 内核启动 init 进程(PID=1) - init 进程解析 `/init.rc` 配置文件: ```rc service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root system ``` - 启动命令:`/system/bin/app_process` 是 Zygote 的可执行文件 #### 2. **app_process 入口(C++ 层)** 文件路径:`frameworks/base/cmds/app_process/app_main.cpp` ```cpp int main(int argc, char* const argv[]) { // 解析参数(--zygote --start-system-server) while (i < argc) { if (strcmp(arg, "--zygote") == 0) { zygote = true; } else if (strcmp(arg, "--start-system-server") == 0) { startSystemServer = true; } } if (zygote) { // 创建 AndroidRuntime 实例 runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } } ``` #### 3. **启动 Java 虚拟机(JVM)** 文件路径:`frameworks/base/core/jni/AndroidRuntime.cpp` ```cpp void AndroidRuntime::start(const char* className, const Vector<String8>& options) { // 1. 初始化 JVM JNIEnv* env; if (startVm(&mJavaVM, &env) != 0) return; // 2. 注册 JNI 方法 if (startReg(env) < 0) return; // 3. 调用 ZygoteInit.main() jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); env->CallStaticVoidMethod(startClass, startMeth, strArray); } ``` #### 4. **ZygoteInit 入口(Java 层)** 文件路径:`frameworks/base/core/java/com/android/internal/os/ZygoteInit.java` ```java public static void main(String[] argv) { // 1. 创建 ZygoteServer(Unix Domain Socket) ZygoteServer zygoteServer = new ZygoteServer(); // 2. 预加载资源(类/资源/JAR等) preload(); // 3. 启动 SystemServer 进程 if (argv[1].equals("start-system-server")) { forkSystemServer(zygoteServer); } // 4. 进入 Socket 循环监听 zygoteServer.runSelectLoop(); } ``` #### 5. **预加载关键资源** ```java static void preload() { // 加载 2000+ 系统类 preloadClasses(); // 加载资源(drawables/xml) preloadResources(); // 加载 OpenGL/ICU 等共享库 preloadSharedLibraries(); // 初始化 Android 核心类 preloadAndroidNio(); } ``` #### 6. **启动 SystemServer** ```java private static Runnable forkSystemServer(ZygoteServer zygoteServer) { // 1. 通过 fork 创建子进程 pid = Zygote.forkSystemServer(/* uid=0 */); if (pid == 0) { // 子进程 // 2. 关闭继承的Socket zygoteServer.closeServerSocket(); // 3. 启动 SystemServer 主线程 return handleSystemServerProcess(args); } } ``` #### 7. **Socket 事件循环** ```java void runSelectLoop() { while (true) { // 1. 监听 Socket 请求 int pollReturnValue = Os.poll(pollFds, -1); // 2. 处理新连接(AMS请求创建App进程) if (pollFds[0].revents == POLLIN) { ZygoteConnection connection = acceptCommandPeer(); // 3. 处理命令(fork新进程) Runnable command = connection.processCommand(); } } } ``` --- ### 关键机制解析 1. **COW(Copy-On-Write)优化** Zygote 预加载的类/资源在 fork 时通过写时复制共享内存,大幅提升应用启动速度。 2. **Socket 通信** ActivityManagerService 通过 `local_socket` 向 Zygote 发送进程创建请求。 3. **进程隔离** 每个 fork 出的进程通过 `setuid()` 切换非 root 用户,确保沙箱隔离。 4. **资源预加载** 预加载的类包括 `android.*` 包下 2000+ 核心类,避免每个 APP 重复加载。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值