Android 源码解析(03) Zygote孵化SystemServer

Zygote字面意思是“受精卵、接合子”,生物学中意味着一个新生命的诞生。Android系统中也有一个进程叫Zygote,它的主要功能就是在Android系统中产生并运行新的进程。

Android是基于Linux内核的,Android系统上电启动之后,首先Linux内核启动,然后在用户空间启动init进程,init进程启动完一些系统守护进程之后,就会启动Zygote进程,启动Dalvik虚拟机,之后转到java层运行ZygoteInit的main方法。ZygoteInit源码位于:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
下面我们就通过这个类的部分源代码,分析其一些主要流程,先看main方法:

    public static void main(String argv[]) {
        ...
        try {
            ...
            // 1、注册Socket,用于接收新的app启动请求
            registerZygoteSocket(socketName);
            ...
            // 2、预加载Android Framework的class和Resource
            preload();
            ...
            // 3、启动SystemServer
            if (startSystemServer) {
                startSystemServer(abiList, socketName);
            }
            ...
            // 4、处理新的app启动请求
            runSelectLoop(abiList);

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            // 5、新进程启动,要运行main方法时,会抛出MethodAndArgsCaller
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

步骤1、注册Socket,用于接收新的app运行请求。AMS启动新的Activity的时候,根据需要会启动对应app,启动app最终调用到frameworks/base/core/java/android/os/Process.java的startViaZygote,里面会通过发送Socket请求启动新的app。步骤1这边的注册就是为了监听这个请求。
步骤2、初始化了BootClassLoader,并将Framework中的class和drawable等预加载出来。使得新的进程可以直接使用这些类和资源,加快了程序运行。
步骤3、native层运行ZygoteInit的main方法时,会传入参数“start-system-server”,这边就会调用startSystemServer启动系统服务
步骤4、监听Socket请求,有请求就执行,并循环继续监听
步骤5、子进程启动之后,要运行主入口的main方法时,会抛出MethodAndAnrgsCaller,这边接收执行。后面会详细讲到这个设计

步骤1和2比较简单,有兴趣同学自己去看源码,今天我们主要看步骤3和5,4的话和3类似
接下来看看步骤3的startSystemServer方法重要步骤源码:

    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        ...
        // 1、准备参数
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,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.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            // 2、孵化systemServer进程
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        // 3、子进程运行
        if (pid == 0) {
            ...
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

步骤1、准备参数,前几个就是设置进程的userId,groupId,权限等,最后一个没有带“--”的表示要新进程启动之后要运行的入口类,也就是最终新进程会运行这个类的main方法
步骤2、调用jni方法孵化新进程。新进程创建成功之后,会共享和复制父进程的内存信息,包括PC计数都会一样,所以新进程一诞生就会从这边开始执行。因此如果在这个方法之后打印log的话,会发现会打印两次。一次是新进程,返回的pid是0;一次是原进程(父进程),返回值是新进程的pid。
TIP:新进程创建之后,这里内存共享和复制采用一种叫COW(Copy On Write)技术。一般来说,复制内存开销非常大,所以子进程会先和父进程共享内存,只有当需要修改共享内存信息的时候,子进程才会将父进程中的内存信息复制到自身内存空间。
步骤3、返回值pid是0,也就是现在是子进程运行到这里,那就继续执行systemServer进程。而父进程则直接返回,进入main方法步骤4监听新app启动的Socket请求

步骤3的handleSystemServerProcess方法重要步骤源码:

    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
        // 1、子进程关闭Socket
        closeServerSocket();
        ...
        if (parsedArgs.invokeWith != null) {
            // 指定运行命令,则运行。
        } else {
            ...
            // 2、正常走这里,运行目标类SystemServer的main方法
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }

步骤1、由于子进程是父进程孵化而来,所以也带有监听socket功能,所以这里将其关闭掉。
步骤2、初始化Zygote并运行目标类SystemServer的main方法

看看RuntimeInit的zygoteInit方法,位于
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        ...
        applicationInit(targetSdkVersion, argv, classLoader);
    }
    private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        ...
        // 1、设置虚拟机一些参数
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        final Arguments args;
        try {
            // 2、解析之前孵化前设置的参数
            args = new Arguments(argv);
        } catch (IllegalArgumentException ex) {
            Slog.e(TAG, ex.getMessage());
            // let the process exit
            return;
        }
        ...
        // 3、调用目标类(SystemServer)的main方法
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

步骤2、解析之前startSystemServer中的参数,其中最后一个参数“com.android.server.SystemServer”将会解析到 arg的startClass
步骤3、调用目标类的静态main方法

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

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }

解析:通过反射机制获取目标类的静态方法main,最后创建并抛出一个MethodAndArgsCaller异常

我们再看看MethodAndArgsCaller的源码:

    public static class MethodAndArgsCaller extends Exception
            implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
    }

解析:这是一个异常,并实现Runnable方法,其中run方法就是反射调用目标函数(main方法)

回到RuntimeInit的invokeStaticMain方法的最后一行抛出MethodAndArgsCaller之后,到ZygoteInit的main方法的步骤5进程catch并运行里面的run方法。
这样设计的原因是,这个进程目标类的main方法抛出异常的的时候,可以清空上面的这些方法的调用栈,让分析者感觉是ZygoteInit的main方法直接调用执行的

SystemServer源码:位于frameworks/base/services/java/com/android/server/SystemServer.java,我们看看main方法主要流程:

    public static void main(String[] args) {
        new SystemServer().run();
    }
    ...
    private void run() {
        ...
        // Start services.
        try {
            // 启动引导服务
            startBootstrapServices();
            // 启动核心服务
            startCoreServices();
            // 启动其他服务
            startOtherServices();
        } catch (Throwable ex) {
            throw ex;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
        ...
    }

最后附上一张大致启动流程图

到这里,我们大致了解了从ZygoteInit到运行各种SystemServer的基本流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值