Android世界的起源 — Zygote

作者: Geekholt | 来源:发表于2020-04-02 15:21 被阅读0次

    目录

    前言

    默认情况下,每一个Android应用程序,都是一个独立的进程,并且每个进程都运行在一个独立的虚拟机中,这点我想很多人应该都知道。那么大家有没有想过,每一个应用进程和虚拟机,都是由谁创建的呢?创建的时机又是怎么样的呢?如何尽量减少创建一个新的进程的性能损耗呢?(即如何缩短应用的启动时间)

    Zygote简介

    我们今天要说的主角,就是Zygote,这个单词的中文翻译叫做“受精卵”,顾名思义,这就是Android应用程序的起点,它是 Android 系统中的第一个 Java 进程

    Zygote的作用

    • 加载常用类、JNI函数、主题资源、共享库
    • 启动虚拟机
    • 初始化binder机制
    • 启动SystemServer(稍后具体分析)
    • 孵化应用进程

    Zygote从何而来

    那么这个Zygote又是由谁创建的呢?

    Android系统启动后,首先引导加载程序会加载内核并启动init进程。然后,init进程会去读取一个配置文件init.rc,这个配置文件记录了需要启动的系统服务,例如android调试守护进程,USB守护进程等。当然这其中也包含创建Zygote进程的配置

    有兴趣的可以通过adb shell查看设备中的文件,这里推荐使用模拟器(可以通过su命令获取root权限)

    模拟器文件目录

    下面粘贴了部分文件的内容

    /vendor/default.prop

    ro.zygote=zygote64_32
    

    /init.rc

    import /init.${ro.zygote}.rc
    on zygote-start && property:ro.crypto.state=...
        # A/B update verifier that marks a successful boot.
        exec_start update_verifier_nonencrypted
        start netd
        start zygote
        start zygote_secondary
    

    /init.zygote64_32.rc

    这里可以看出启动Zygote真正执行的其实是/system/bin/目录下的app_process64程序

    #zygote代表进程名称
    #/system/bin/app_process64代表程序的可执行路径
    service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
        class main
        priority -20
        user root
        group root readproc reserved_disk
        socket zygote stream 660 root system
        onrestart write /sys/android_power/request_state wake
        onrestart write /sys/power/state on
        onrestart restart audioserver
        onrestart restart cameraserver
        onrestart restart media
        onrestart restart netd
        onrestart restart wificond
        writepid /dev/cpuset/foreground/tasks
    
    service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
        class main
        priority -20
        user root
        group root readproc reserved_disk
        socket zygote_secondary stream 660 root system
        onrestart restart zygote
        writepid /dev/cpuset/foreground/tasks
    

    所以总结一句话,Zygote就是Android应用程序的起点,它是由Linux内核的init进程创建的

    Zygote的工作流程

    提示:对看源码感到头疼的同学可以先看每段源码后面的结论,再根据自己的兴趣翻看对应源码

    上面说到了真正执行的其实是/system/bin/目录下的app_process64程序(我的模拟器是64位的),它所对应的源代码是frameworks/base/cmds/app_process/app_main.cpp

    app_main.cpp

    #if defined(__LP64__)
    static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
    static const char ZYGOTE_NICE_NAME[] = "zygote64";
    #else
    static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
    static const char ZYGOTE_NICE_NAME[] = "zygote";
    #endif
    
    int main(int argc, char* const argv[])
    {
    
        //...
      
        bool zygote = false;
        bool startSystemServer = false;
        bool application = false;
        String8 niceName;
        String8 className;
      
        //解析app_process的参数
        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 (!niceName.isEmpty()) {
            runtime.setArgv0(niceName.string());
                //设置进程名称为“zygote”
            set_process_name(niceName.string());
        }
    
        //args中存储的是关于虚拟机的参数,主要有start-system-server,abi-list,socket-name=zygote
        if (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.");
            return 10;
        }
    }
    

    这个方法主要做了下面几件事情:

    1. 解析app_process的参数
    2. 设置当前进程名由app_process改为zygote
    3. 调用是AndroidRuntime#start()

    接下来程序就走到了frameworks\base\core\jni\AndroidRuntime.cpp

    AndroidRuntime.cpp

    void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
    {
        static const String8 startSystemServer("start-system-server");
    
        //...
        JniInvocation jni_invocation;
        jni_invocation.Init(NULL);
        JNIEnv* env;
        //启动虚拟机
        if (startVm(&mJavaVM, &env, zygote) != 0) {
            return;
        }
        onVmCreated(env);
    
        //注册JNI函数
        if (startReg(env) < 0) {
            ALOGE("Unable to register all android natives\n");
            return;
        }
      
        //...
        char* slashClassName = toSlashClassName(className);
        //这里的startClass就是com.android.internal.os.ZygoteInit
        jclass startClass = env->FindClass(slashClassName);
        if (startClass == NULL) {
            ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        } else {
            //反射调用ZygoteInit.main()方法
            jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
                "([Ljava/lang/String;)V");
            if (startMeth == NULL) {
                ALOGE("JavaVM unable to find main() in '%s'\n", className);
            } else {
                env->CallStaticVoidMethod(startClass, startMeth, strArray);
            }
        }
        free(slashClassName);
    }
    

    这个方法主要做了下面几件事情:

    1. 启动虚拟机
    2. 注册JNI函数
    3. 调用ZygoteInit.main()方法

    ZygoteInit是java方法,从这里开始就从native世界进入到了java世界

    ZygoteInit.java

    public static void main(String argv[]) {
                //创建ZygoteServer
            ZygoteServer zygoteServer = new ZygoteServer();
    
                //...
    
            final Runnable caller;
            try {
          
                            //...
                boolean startSystemServer = false;
                String socketName = "zygote";
                String abiList = null;
                boolean enableLazyPreload = false;
                //解析app_main.cpp传来的参数
                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)) {
                        socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                    } else {
                        throw new RuntimeException("Unknown command line argument: " + argv[i]);
                    }
                }
    
                if (abiList == null) {
                    throw new RuntimeException("No ABI list supplied.");
                }
    
                //注册Zygote进程的socket通讯
                zygoteServer.registerServerSocketFromEnv(socketName);
              
                //...
              
                //加载进程的资源和类
                    preload(bootTimingsTraceLog);
                    
                //...
              
                if (startSystemServer) {
                    //创建SystemServer进程,这是zygote进程的第一次分裂
                    Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
    
                    if (r != null) {
                        r.run();
                        return;
                    }
                }
    
                Log.i(TAG, "Accepting command socket connections");
    
                        //启动一个死循环监听来自Client端的消息
                caller = zygoteServer.runSelectLoop(abiList);
            } catch (Throwable ex) {
                Log.e(TAG, "System zygote died with exception", ex);
                throw ex;
            } finally {
                //关闭SystemServer的Socket
                zygoteServer.closeServerSocket();
            }
    
            if (caller != null) {
                caller.run();
            }
        }
    

    这个方法主要做了下面几件事情:

    1. 预加载类和资源,包括颜色,R文件、drawable类等
    2. 创建SystemServer进程
    3. 创建ZygoteServer,开启一个死循环,等待着接收ActivityManagerService的socket请求,即创建应用程序进程请求

    SystemServer进程是一个非常重要的进程,我们来看看forkSystemServer()是如何创建SystemServer进程的

    ZygoteInit.java

     private static Runnable forkSystemServer(String abiList, String socketName,
                ZygoteServer zygoteServer) {
           
                //...
            //真正创建SystemServer进程
            int pid = Zygote.forkSystemServer(...);
                 
            if (pid == 0) {
                if (hasSecondZygote(abiList)) {
                    waitForSecondaryZygote(socketName);
                }
    
                zygoteServer.closeServerSocket();
                //继续方法调用
                return handleSystemServerProcess(parsedArgs);
            }
    
            return null;
        }
    

    fork() 函数是一次执行,两次返回。说的更严谨一点是 两个进程对用一个程序的两次执行。当 pid == 0 时,说明现在处于子进程,当 pid > 0 时,说明处于父进程

    ZygoteInit.java

    private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
            //....
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
    }
    

    ZygoteInit.java

    public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        //常规的一些初始化,比如日志输出、未捕获异常处理等
        RuntimeInit.commonInit();
        //主要用于初始化binder机制,并启动一个binder线程(用于SystemServer与其他进程通信)
        ZygoteInit.nativeZygoteInit();
        //调用SystemServer.java的入口函数
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }
    

    所以forkSystemServer()主要做了下面几件事:

    1. 创建SystemServer进程
    2. 一些常规初始化
    3. 初始化Binder机制,用于SystemServer与其他进程的通信(如应用进程、ServiceManager进程等)
    4. 调用SystemServer.java的入口函数

    SystemServer.mian()直接调用了SystemServer#run()方法

    SystemServer.java

    private void run() {
        //...
        //为主线程创建Looper
        Looper.prepareMainLooper();
        //加载共享库,即系统服务的native层代码
        System.loadLibrary("android_servers");
        //创建上下文   
        createSystemContext();
        //...
      
        //启动ActivityManagerService、SystemServiceManager、DisplayManagerService、
        //PackageManagerService、WindowManager等
        startBootstrapServices();
        startCoreServices();
        //开始准备HomeActivity的前奏工作,并通过Intent唤起桌面应用
        startOtherServices();
      
            //...
        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
    

    下面放一张图概括一下上面的整个过程

    android系统启动过程

    总结

    回到我们最初的问题

    每一个应用进程和虚拟机,都是由谁创建的呢?

    由Zygote进程创建

    应用进程创建的时机又是怎么样的呢?

    当Activity需要被启动的时候,SystemServer中负责管理进程的AMS利用Socket客户端向Zygote的Socket服务端发送创建新进程命令,Zygote收到命令后为应用创建进程,这是典型的C/S架构

    如何尽量减少创建一个新的进程的性能损耗呢?

    每个应用进程不仅有自己的数据资源和需要执行的代码,还需要用到Android框架中通用的资源和代码,由于这些资源和代码是大部分应用都需要调用到的,并且比较重量级,所以安卓把它们都放在Zygote进程的空间中,而应用进程又是继承于Zygote进程,所以当应用需要的时候就直接到里面去找就行了

    本文主要讲了系统启动的流程,但是我们实际上并没有对Activity是如何被启动的做深入的分析,所以对Activity启动流程感兴趣的可以看Activity启动流程

    相关文章

      网友评论

        本文标题:Android世界的起源 — Zygote

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