安卓系统启动之Zygote进程启动过程

背景

安卓系统启动时首先启动init进程,而后init进程会创建zygote进程,zygote进程则会fork出来SystemServer进程。在安卓开发学习之SystemServer启动过程一文中记录了阅读SystemServer启动的过程,现在就记录一下Zygote进程的启动过程

 

源码阅读

Zygote进程的启动源自于ZygoteInit类的入口main()方法

ZygoteInit#main()

main()方法代码如下

    public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();

        ZygoteHooks.startZygoteNoThreadCreation(); // 启动hook跟踪

        try {
            Os.setpgid(0, 0);
            // 指定当前进程的id(第一个参数是目标进程id,第二个参数是进程组id,把第二个参数设置成第一个的值)
        } catch (ErrnoException ex) {
            .. // 异常
        }

        try {
            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
                // 如果是重启sys.boot_completed值是1
                MetricsLogger.histogram(null, "boot_zygote_init",
                        (int) SystemClock.elapsedRealtime());
            } // 上报Zygote进程启动的时间,除非是进程重启

            .. // 日志跟踪
            RuntimeInit.enableDdms(); // 启动ddms
            SamplingProfilerIntegration.start(); // 用于系统优化

            boolean startSystemServer = false;
            String socketName = "zygote"; // 进程套接字名字时zygote
            String abiList = null; // abi列表(armeabi、armeabi-v7a、x86等)
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) { // 遍历参数列表
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true; // 是否启动SystemServer进程,一般都要启动
                } 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()); // 获取abi列表
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length()); // 获取套接字名字
                } else {
                    .. // 异常
                }
            }

            if (abiList == null) {
                .. // 异常
            }

            zygoteServer.registerServerSocket(socketName); // 注册套接字
            
            if (!enableLazyPreload) { // 如果不启动懒人式预加载
                ..
                preload(bootTimingsTraceLog); // 就调用preload()方法进行预加载
                ..
            } else {
                Zygote.resetNicePriority(); // 启动懒人式预加载的话,就只重置fifo策略
            }

            SamplingProfilerIntegration.writeZygoteSnapshot(); // 保存快照

            ..
            gcAndFinalize(); // 进行gc
            
            ..

            Zygote.nativeUnmountStorageOnInit(); // 卸载root的存储空间

            Seccomp.setPolicy(); // seccomp安全模式

            ZygoteHooks.stopZygoteNoThreadCreation();

            if (startSystemServer) {
                startSystemServer(abiList, socketName, zygoteServer); // 启动SystemServer
            }

            ..
            zygoteServer.runSelectLoop(abiList); // zygote进程进入死循环,不断准备接收新的socket连接

            zygoteServer.closeServerSocket(); // 关闭zygote套接字
        } catch (Zygote.MethodAndArgsCaller caller) {
            caller.run(); // 启动SystemServer时,最终会到这里调用SystemServer.main()
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        }
    }

第一次启动的话,肯定不会是懒人预加载,肯定会调用preload()方法进行初始化,这个方法代码如下

    static void preload(BootTimingsTraceLog bootTimingsTraceLog) {
        ..
        beginIcuCachePinning(); // 指令缓存
        ..
        preloadClasses(); // 利用反射进行某些类的预加载
        ..
        preloadResources(); // 预加载资源
        ..
        preloadOpenGL(); // 预加载openGL
        ..
        preloadSharedLibraries(); // 预加载native库
        preloadTextResources(); // 预加载文字资源
        
        WebViewFactory.prepareWebViewInZygote(); // 在zygote进程就预加载了webview
        endIcuCachePinning(); // 结束指令缓存
        warmUpJcaProviders(); // 预加载jca加密缓存
        ..

        sPreloadComplete = true;
    }

原来系统资源以及一些库的初始化都在zygote进程里就进行了,特别是webView的预加载也是这么早。

回到main()方法,然后一个比较重要的方法是startSystemServer()方法,因为这个方法会启动SystemServer进程

 

ZygoteInit#startSystemServer()

这个方法代码如下

    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_IPC_LOCK, // IPC通信时获取锁
            OsConstants.CAP_KILL, // 绕过权限检查直接向别的进程发信号
            OsConstants.CAP_NET_ADMIN, // 网络管理
            OsConstants.CAP_NET_BIND_SERVICE, // 绑定到1024以下的端口
            OsConstants.CAP_NET_BROADCAST, // 广播
            OsConstants.CAP_NET_RAW, // 使用原始套接字
            OsConstants.CAP_SYS_MODULE, // 对系统内核模块进行插入删除
            OsConstants.CAP_SYS_NICE, // 禁止普通用户进行线程的FIFO调度策略
            OsConstants.CAP_SYS_PTRACE, // 进程跟踪
            OsConstants.CAP_SYS_TIME, // 系统时间
            OsConstants.CAP_SYS_TTY_CONFIG, // 配置tty(终端)信息
            OsConstants.CAP_WAKE_ALARM // 系统闹钟
        ); // 初始化要赋予SystemServer进程的能力
        
        if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
            // 如果系统属性PROPERTY_RUNNING_IN_CONTAINER的值是false
            // 就在要赋予SystemServer的能力里加上CAP_BLOCK_SUSPEND(阻止系统进程挂起)
            capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
        }
        
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        }; // 启动参数,进行权限的设置
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            // 解析启动参数,获取ZygoteConnection.Arguments对象
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            // 设置参数对象的debugFLags,判断是否JDWP调试(默认是不调试的)
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
            // 根据参数里的nice-name值获取SystemProperties对应的值,并保存到参数对象的invokeWith属性里,但这个属性默认是null

            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities); // fork子进程,返回子进程的pid
        } catch (IllegalArgumentException ex) {
            ..
        }

        /* For child process */
        if (pid == 0) { // fork完后,如果当前进程是子进程
            if (hasSecondZygote(abiList)) { // 根据abiList考虑是否要进行第二次孵化
            /*
                    这个是根据ro.product.cpu.abilist系统属性判断的,如果abiList不是这个系统属性的值,就要进行二次孵化
                    ro.product.cpu.abilist属性也包括了ro.product.cpu.abilist32属性,在Android-X86系统里,它们的值是
                        ro.product.cpu.abilist=x86,armeabi-v7a,armeabi
                        ro.product.cpu.abilist32=x86,armeabi-v7a,armeabi
                */
                waitForSecondaryZygote(socketName); // 是的话,等待进行下一次孵化
            }

            zygoteServer.closeServerSocket(); // 不用的话,关闭套接字
            handleSystemServerProcess(parsedArgs); // 而后继续SystemServer启动
        }

        return true;
    }

解释都在注释里,如果fork完子进程,而且当前在子进程里,就进入下一步:handleSystemServerProcess()。这个子进程,就是SystemServer进程

 

ZygoteInit.handleSystemServerProcess()

由上文可知,这个方法是在SystemServer进程里被执行的,所以下面就是关于SystemServer如何被启动的内容了

    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws Zygote.MethodAndArgsCaller {

        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);

        if (parsedArgs.niceName != null) {
            Process.setArgV0(parsedArgs.niceName);
            // 设置进程的参数一为启动参数里的niceName(也就是SystemServer)
        }

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        // 获取环境变量SYSTEMSERVERCLASSPATH的值
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);
             // 执行SystemServer的dex优化
            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);
            if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {
                // 是否进行SystemServer性能优化
                try {
                    File profileDir = Environment.getDataProfilesDePackageDirectory(
                            Process.SYSTEM_UID, "system_server");
                    File profile = new File(profileDir, "primary.prof");
                    profile.getParentFile().mkdirs();
                    profile.createNewFile();
                    String[] codePaths = systemServerClasspath.split(":");
                    VMRuntime.registerAppInfo(profile.getPath(), codePaths);
                } catch (Exception e) {
                    ..
                }
            }
        }

        if (parsedArgs.invokeWith != null) {
           // 正常情况invokeWith为null
           ....
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                // 获取path的classLoader,这个classLoader用来加载SystemServer类
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
                // 设置此线程的上下文classLoader
            }
            
            ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }

获取完SystemServer的classLoader后,调用zygoteInit()方法进行下一步初始化

 

ZygoteInit.zygoteInit()方法

    public static final void zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
        .. // 日志

        RuntimeInit.redirectLogStreams(); // 把标准输出和标准错误重定向给log.i和log.e

        RuntimeInit.commonInit(); // 针对日志和异常处理进行初始化
        ZygoteInit.nativeZygoteInit(); // zygote初始化
        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

又是一系列的初始化操作,之后进入RuntimeInit.applicationInit()方法,此方法代码如下

      protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller {
        
        nativeSetExitWithoutCleanup(true);

        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);  // 设置内存最大利用率
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); // 设置sdk版本

        final Arguments args;
        try {
            args = new Arguments(argv); // main()方法需要的参数
        } catch (IllegalArgumentException ex) {
            .. // 异常
        }

        ..

        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

设置内存利用率和sdk版本,并且解析完参数后,调用invoteStaticMain()方法,调用main(),此方法代码如下

    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller {
        Class cl;

        try {
            cl = Class.forName(className, true, classLoader); // 反射获取SystemServer类
        } catch (ClassNotFoundException ex) {
            .. // 异常
        }

        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class }); // 获取main()方法
        } catch (Exception ex) {
            ..
        } 

        int modifiers = m.getModifiers(); // 获取main()方法的访问修饰符
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            .. // 如果不是静态公有的,就抛出异常
        }

        // 正常情况会抛出这个异常,这个异常在ZygoteInit.main()方法中被捕捉
        throw new Zygote.MethodAndArgsCaller(m, argv);
    }

正常情况下,这段代码抛出Zygote.MethodAndArgsCaller异常,并携带main()方法和方法参数,它在ZygoteInit.main()方法中捕获后(可以回去看看ZygoteInit.main()),会调用这个异常的run()方法,run()方法代码如下

        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (Exception ex) {
                ..
            } 
        }

执行SystemServer的main()方法,从而开始SystemServer的启动流程

 

结语

关于Zygote进程的启动过程就是如此。总结一下:

进行一系列初始化(包括系统资源,openGL,webView等)后,fork一个SystemServer进程,通过抛出异常的方式开始SystemServer的主函数的执行,fork之后的zygote自己则进入等待套接字连接的死循环。

源码选自Android8.0

你可能感兴趣的:(安卓开发,系统启动)