美文网首页
Android Framework学习(一)之Zygote启动

Android Framework学习(一)之Zygote启动

作者: NengLee | 来源:发表于2026-01-05 17:12 被阅读0次

系统中运行的第一个Dalvik虚拟机程序叫做Zygote,该名称意义是"卵",俗称“孵化器”;因为接下来的所有Dalvik虚拟机进程都是通过这个“卵”孵化出来的

Zygote进程中包含俩个主要的模块,分别如下:

  • Sockte服务器:该Sockte服务器用于接收启动新的Dalvik进程的命令
  • Framework共享类及共享资源:当Zygote进程启动后,会装载一些共享的类及资源,其中共享类是在preload-classes文件中被定义,共享资源是在preload-resources中被定义。因为Zygote进程用于孵化出其他的Dalvik进程,因此这些类和资源装状后,新的Dalvik进程就不要再装载这些类和资源了,这也就是所谓的共享。

Zygote进程对应的具体程序是:app_rocess,该程序存在于 System/bin 目录下,启动该程序的指令是在 init.rc 中进行配置

Zygote有俩个优秀的特点:

  • 每个Fork出来的进程都是一个Dalvik虚拟机,独立的进程可以防止一个程序的崩溃导致所有程序崩溃,这种虚拟机类似java虚拟机,对于编程者来说,可以直接使用java开发应用

  • Zygote进程预先会装载共享类和共享资源,这些类以及资源实际上就是SDK中定义的大部分类和资源,因此,当通过Zygote孵化出新的进程后,新的APK进程只需要去装载APK自身的类和资源即可,这样有效的解决多个APK共享Framework资源的问题。

Framework 源头

操作系统一般启动流程,分为三个步骤:

  1. 开机通电后,加载Bootloader程序

  2. 操作系统内核初始化

  3. 执行第一个应用程序

Android系统基于Linux内核,初学者可以直接连接操作系统内核初始化,在这个时候,它会加载init.rc文件

init.rc文件

在Android根目录下面,可以直接找到init.rc

# ..... 省略其他
 # Now we can start zygote for devices with file based encryption
trigger zygote-start

# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start 
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start netd
    start zygote
    start zygote_secondary

on property:vold.decrypt=trigger_restart_framework
    stop surfaceflinger
# 启动SF
    start surfaceflinger  

# ..... 省略其他 media(媒体)  network(网络)等启动

也就是在 init.rc时,启动Android 内核。

app_process

Android 内核也是main方法开始,函数main方法在位置(frameworks/base/cmds/app_process/app_main.cpp)

int main(int argc, char* const argv[])
{
    ...
    //初始化AndroidRuntime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

    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 = 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.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
    if (!className.isEmpty()) {
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    }else{
        ....
        //启动SystemServer
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }
    }
    ....
     if (zygote) {
       //启动Zygote
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

在这个Main方法中,先初始化了AppRuntime,他的父类是AndroidRuntime。然后看到启动java类Zygoteinit

那么C++代码是如何启动java类的,继续看 start 方法

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
   ...
   //启动Java虚拟机
     if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    ...
    //找到Java 里面的Main方法
     jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
        //执行Main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
    }
    ....    
}

可以看到最后先创建java虚拟机,同JIN调用java的main方法

ZygoteInit

ZygoteInit被创建,里面会执行什么内容呢?

//ZygoteInit.java
  public static void main(String argv[]) {
    ZygoteServer zygoteServer = new ZygoteServer();
    ZygoteHooks.startZygoteNoThreadCreation();

    //创建socket
    zygoteServer.createZygoteSocket(socketName);
    Zygote.createBlastulaSocket(blastulaSocketName);

    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();
    }

    //fork SystemServer进程
    if (startSystemServer) {
        Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
        // child (system_server) process.
        if (r != null) {
            r.run();
            return;
        }
    }

    //等待Socket的接入
    if (caller == null) {
        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.
        caller = zygoteServer.runSelectLoop(abiList);
    }

通过源码发现ZygoteInit - Main大概初始化内容如下:

  • 创建Sockte
  • 加载系统资源
  • 启动SystemServer
  • runSelectLoop 等待Socket接入,从Main方法开始

相关文章

网友评论

      本文标题:Android Framework学习(一)之Zygote启动

      本文链接:https://www.haomeiwen.com/subject/srvtkstx.html