• Android 9.0 Zygote 启动流程



    极力推荐文章:欢迎收藏
    Android 干货分享

    本篇文章主要介绍 Android Zygote 启动分析 知识点,通过阅读本篇文章,您将收获以下内容:

    一、 Android 系统基本服务
    二、虚拟机创建和第一个Java 程序引导
    三、Dalvik 虚拟机基本配置
    四、Zygote 启动流程
    五、Zygote 启动分析
    六、Zygote 创建system_server主要方法
    七、Zygote 创建System_server 分析
    八、Zygote 创建应用
    九、Zygote 创建应用流程
    十、Zygote 预加载资源
    十一、Zygote 预加载的目的
    十二、优化Zygote 启动方法: 线程池
    十三、fork SystemServer

    Zygote 服务时通过 init.rc进程启动的,Zygoteclassnamemain .
    init.rc 文件配置代码如下:

    ... ... 
    on nonencrypted
        class_start main
        class_start late_start
    
    on property:sys.init_log_level=*
        loglevel ${sys.init_log_level}
    
    ... ...
    

    详细可以参考 init.rc启动分析。
    Android 9.0 系统启动流程

    一、 Android 系统基本服务

    Android 系统包含netdservicemanagersurfaceflingezygotemediainstalldbootanimation 等基本服务,具体作用请看下图。

    Android 系统基本服务

    二、虚拟机创建和第一个Java 程序引导

    为了让APK在不同的虚拟机都可以运行,Google 采取了适配器模式,在让虚拟机运行之前先执行 dexopt ,即将dex 文件优化成odex 文件,可以让虚拟机更加优化的执行。

    ART 虚拟机中,dexoptdex文件优化成二进制格式的问题,从而可以让ART虚拟机执行。
    dexopt 会调用dex2oat 进行优化,dex2oat 的任务是将原来的dex文件进行预翻译,从而可以加快app运行的时间,但是由于某些app比较复杂,所以优化的时间就比较长。
    优化是以dex 文件中的Method 方法为单位,dex2oat 在优化时候,会根据需求优化一定量的Method,即不是所有的Method 都回翻译成oat模式。

    虚拟机创建和第一个Java 程序引导

    三、Dalvik 虚拟机基本配置

    Android 系统中,Dalvik 虚拟机 和ART、应用程序进程,以及运行系统的关键服务SystemServer 进程都是由 Zygote 进程创建孵化的。

    Dalvik 虚拟机基本配置如下:

    Dalvik 虚拟机基本配置

    四、Zygote 启动流程

    Zygote 是由 init.rc 脚本启动,在init 脚本中,我们可以看到会导入import /init.${ro.zygote}.rc 脚本

    # Copyright (C) 2012 The Android Open Source Project
    #
    # IMPORTANT: Do not create world writable files or directories.
    # This is a common source of Android security bugs.
    #
    
    import /init.environ.rc
    import /init.usb.rc
    import /init.${ro.hardware}.rc
    import /vendor/etc/init/hw/init.${ro.hardware}.rc
    import /init.usb.configfs.rc
    ... ...
    import /init.${ro.zygote}.rc
    
    ... ...
    

    system/core/rootdir目录下,会根据ro.zygote属性值不同,启动不同的脚本,主要包含以下四个zygote 脚本。

    • 1.init.zygote32.rc 支持32为系统
    • 2.init.zygote32_64.rc
    • 3.init.zygote64.rc
    • 4.init.zygote64_32.rc

    init.zygte.rc脚本

    Zygote 启动流程

    五、Zygote 启动分析

    Zygote 启动分析

    六、Zygote 创建system_server主要方法

    Zygote 创建system_server主要方法

    七、Zygote 创建System_server 分析

    Zygote 创建System_server

    八、Zygote 创建应用

    Zygote 创建应用

    九、Zygote 创建应用流程

    Zygote 创建应用流程

    十、Zygote 预加载资源

    Zygote 预加载资源

    preloadClasses()

    preloadResources()

    十一、Zygote 预加载的目的

    Zygote 预加载的目的

    十二、优化Zygote 启动方法: 线程池

    Zygote 启动优化前提:

    • 1:加载类和资源是可重入操作,所以在并行模式下,不存在互斥的场景

    • 2:Android提供了Executors和ExecutorService多线程类,因此可以使用多线程来加载类和资源。

    • 3:硬件平台最好是多核,否则加速也不明显;

    线程池 优化Zygote 启动

    Zygote 启动优化实质:

    使我们的进程最大限度的抢占CPU

    十三、fork SystemServer

    经过一系列初始化后,在ZygoteInit类中 forkSystemServer,为启动SystemServer 做准备。ZygoteInit.java代码路径如下:alpsframeworksasecorejavacomandroidinternalosygoteInit.java

    
        /**
         * Prepare the arguments and forks for the system server process.
         *
         * Returns an {@code Runnable} that provides an entrypoint into system_server code in the
         * child process, and {@code null} in the parent.
         */
        private static Runnable forkSystemServer(String abiList, String socketName,
                ZygoteServer zygoteServer) {
            long capabilities = posixCapabilitiesAsBits(
                OsConstants.CAP_IPC_LOCK,
                OsConstants.CAP_KILL,
                OsConstants.CAP_NET_ADMIN,
                OsConstants.CAP_NET_BIND_SERVICE,
                OsConstants.CAP_NET_BROADCAST,
                OsConstants.CAP_NET_RAW,
                OsConstants.CAP_SYS_MODULE,
                OsConstants.CAP_SYS_NICE,
                OsConstants.CAP_SYS_PTRACE,
                OsConstants.CAP_SYS_TIME,
                OsConstants.CAP_SYS_TTY_CONFIG,
                OsConstants.CAP_WAKE_ALARM,
                OsConstants.CAP_BLOCK_SUSPEND
            );
            /* Containers run without some capabilities, so drop any caps that are not available. */
            StructCapUserHeader header = new StructCapUserHeader(
                    OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
            StructCapUserData[] data;
            try {
                data = Os.capget(header);
            } catch (ErrnoException ex) {
                throw new RuntimeException("Failed to capget()", ex);
            }
            capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);
    
            /* Hardcoded command line to start the system server */
            String args[] = {
                "--setuid=1000",
                "--setgid=1000",
                /// M: [Wi-Fi Hotspot Manager] system_server add dhcp (1014) group to access
                /// "/data/misc/dhcp/dnsmasq.leases"
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1014,1018,1021,1023," +
                            "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
            };
            ZygoteConnection.Arguments parsedArgs = null;
    
            int pid;
    
            try {
                parsedArgs = new ZygoteConnection.Arguments(args);
                ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
                ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
    
                boolean profileSystemServer = SystemProperties.getBoolean(
                        "dalvik.vm.profilesystemserver", false);
                if (profileSystemServer) {
                    parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
                }
    
                /* Request to fork the system server process */
                pid = Zygote.forkSystemServer(
                        parsedArgs.uid, parsedArgs.gid,
                        parsedArgs.gids,
                        parsedArgs.runtimeFlags,
                        null,
                        parsedArgs.permittedCapabilities,
                        parsedArgs.effectiveCapabilities);
            } catch (IllegalArgumentException ex) {
                throw new RuntimeException(ex);
            }
    
            /* For child process */
            if (pid == 0) {
                if (hasSecondZygote(abiList)) {
                    waitForSecondaryZygote(socketName);
                }
    
                zygoteServer.closeServerSocket();
                return handleSystemServerProcess(parsedArgs);
            }
    
            return null;
        }
    
    

    至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

    微信关注公众号:  程序员Android,领福利

  • 相关阅读:
    Xcode6模拟器下键盘出不来的原因
    iOS7View被导航栏遮挡问题的解决
    iOS中设置导航栏标题的字体颜色和大小
    iphone ios 屏幕,导航条,状态栏的高度
    iOS: TableView如何刷新指定的cell 或section
    rest api load test
    异步图片处理服务器
    bitbucket SSH 生成
    基于Token的授权(with srping mvc)
    Netty性能调优
  • 原文地址:https://www.cnblogs.com/wangjie1990/p/11310914.html
Copyright © 2020-2023  润新知