Zygote进程到System Server进程

​ 上一篇文章讲到了Zygote拉起了System server进程,本文具体讲述一下,System server启动的流程。Zygote进程拉起System Server进程调用的方法是ZygoteInit.java forkSystemServer,如下:

ZygoteInit.java forkSystemServer

 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",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",//这个是后面启动的类名
        };
        ZygoteArguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteArguments(args);
            Zygote.applyDebuggerSystemProperty(parsedArgs);//设置一些属性
            Zygote.applyInvokeWithSystemProperty(parsedArgs);//设置一些属性

            if (Zygote.nativeSupportsMemoryTagging()) {
                /* The system server is more privileged than regular app processes, so it has async
                 * tag checks enabled on hardware that supports memory tagging. 系统服务比常规应用程序进程具有更大的特权,因此它在支持内存标记的硬件上启用了异步标记检查。*/
                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_ASYNC;
            } else if (Zygote.nativeSupportsTaggedPointers()) {
                /* Enable pointer tagging in the system server. Hardware support for this is present
                 * in all ARMv8 CPUs. 在系统服务中启用指针标记。 所有ARMv8 CPU中都提供对此的硬件支持。*/
                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
            }

            if (shouldProfileSystemServer()) {
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }

            /* Request to fork the system server process 请求fork 系统服务 进程*/
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process 新孵化出来的进程 pid是0*/
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {//有第二个socket?
                waitForSecondaryZygote(socketName);//等待第二个socket
            }

            zygoteServer.closeServerSocket();//关闭socket
            return handleSystemServerProcess(parsedArgs);//获取新进程的任务
        }

        return null;//zygote进程,直接返回null
    }

总结

​ main方法调用forkSystemServer来孵化system server进程,那么这个forkSystemServer方法做了什么事情呢?

  1. 准备参数,是一些启动system server进程需要的参数了,这里重点关注"com.android.server.SystemServer"
  2. 调用Zygote.java,设置一些属性值
  3. 调用Zygote.forkSystemServer进行孵化system server进程
  4. 对孵化进程结果进行处理,这里注意,得到返回值的时候,新进程已经孵化了,所以两个进程都会跑后面的程序
  5. 对于新进程(System Server),返回值pid是0,所以先判断是不是有其他socket需要等待,没有的话,关闭socket连接,获取新进程的任务。这个任务(Runnable)由main方法后边调用run方法执行
  6. 对于zygote进程,直接返回了null,这也对对应了main方法,对于zygote进程,后续是重新开启循环等待socket 客户端连接。

Zygote.java forkSystemServer

public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        ZygoteHooks.preFork();//应该是准备工作
        //调用native层的方法创建进程
        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits,
                permittedCapabilities, effectiveCapabilities);

        // Set the Java Language thread priority to the default value for new apps. 将Java语言线程优先级设置为新应用程序的默认值。
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);

        ZygoteHooks.postForkCommon();
        return pid;
    }

    private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);

总结

这个方法是Java世界fork进程调用的最后一个方法了,它调用native层的方法创建System server进程,并返回pid,其他没有太多的了。

接下来的工作是寻找,System Server进程被拉起来之后需要执行的任务是什么,也就是handleSystemServerProcess返回的Runnable哪里来的?

ZygoteArguments.java

​ 这个方法是用来获取System server进程接下来需要执行的任务的。先看一下,handleSystemServerProcess方法的参数哪里来的?是在ZygoteInit.java forkSystemServer方法来的。

String args[] = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",//这个是后面启动的类名
        };

ZygoteArguments(String[] args) throws IllegalArgumentException {//这里的args就是上面那个args
        parseArgs(args);
}

private void parseArgs(String[] args) throws IllegalArgumentException {
        int curArg = 0;

        boolean seenRuntimeArgs = false;

        boolean expectRuntimeArgs = true;
        for ( /* curArg */ ; curArg < args.length; curArg++) {//开始解析参数
            String arg = args[curArg];

            if (arg.equals("--")) {                                        //没有这个
                curArg++;
                break;
            } else if (arg.startsWith("--setuid=")) {                    //有这个
                if (mUidSpecified) {
                    throw new IllegalArgumentException(
                        "Duplicate arg specified");
                }
                mUidSpecified = true;
                mUid = Integer.parseInt(
                    arg.substring(arg.indexOf('=') + 1));
            } else if (arg.startsWith("--setgid=")) {                    //有这个
                if (mGidSpecified) {
                    throw new IllegalArgumentException(
                        "Duplicate arg specified");
                }
                mGidSpecified = true;
                mGid = Integer.parseInt(
                    arg.substring(arg.indexOf('=') + 1));
            } else if (arg.startsWith("--target-sdk-version=")) {        //有这个
                if (mTargetSdkVersionSpecified) {
                    throw new IllegalArgumentException(
                        "Duplicate target-sdk-version specified");
                }
                mTargetSdkVersionSpecified = true;
                mTargetSdkVersion = Integer.parseInt(
                    arg.substring(arg.indexOf('=') + 1));
            } else if (arg.equals("--runtime-args")) {                    //有这个
                seenRuntimeArgs = true;
            } else if (arg.startsWith("--runtime-flags=")) {            //没有这个
                mRuntimeFlags = Integer.parseInt(
                    arg.substring(arg.indexOf('=') + 1));
            } else if (arg.startsWith("--seinfo=")) {                    //没有这个
                //...
            } else if (arg.startsWith("--capabilities=")) {                //有这个
                if (mCapabilitiesSpecified) {
                    throw new IllegalArgumentException(
                        "Duplicate arg specified");
                }
                mCapabilitiesSpecified = true;
                String capString = arg.substring(arg.indexOf('=') + 1);

                String[] capStrings = capString.split(",", 2);

                if (capStrings.length == 1) {
                    mEffectiveCapabilities = Long.decode(capStrings[0]);
                    mPermittedCapabilities = mEffectiveCapabilities;
                } else {
                    mPermittedCapabilities = Long.decode(capStrings[0]);
                    mEffectiveCapabilities = Long.decode(capStrings[1]);
                }
            } else if (arg.startsWith("--rlimit=")) {                    //没有这个
                //...
            } else if (arg.startsWith("--setgroups=")) {                //有这个
                if (mGids != null) {
                    throw new IllegalArgumentException(
                        "Duplicate arg specified");
                }

                String[] params = arg.substring(arg.indexOf('=') + 1).split(",");

                mGids = new int[params.length];

                for (int i = params.length - 1; i >= 0; i--) {
                    mGids[i] = Integer.parseInt(params[i]);
                }
            } else if (arg.equals("--invoke-with")) {                    //没有这个
                if (mInvokeWith != null) {
                    throw new IllegalArgumentException(
                        "Duplicate arg specified");
                }
                try {
                    mInvokeWith = args[++curArg];
                } catch (IndexOutOfBoundsException ex) {
                    throw new IllegalArgumentException(
                        "--invoke-with requires argument");
                }
            } else if (arg.startsWith("--nice-name=")) {                //有这个
                if (mNiceName != null) {
                    throw new IllegalArgumentException(
                        "Duplicate arg specified");
                }
                mNiceName = arg.substring(arg.indexOf('=') + 1);
            } 
            //...   后面的这一长串都没有
        }
//下面的代码是处理剩余的参数的,注意到 args的参数中最后只剩下  "com.android.server.SystemServer" 这一个没有处理
        if (mBootCompleted) { //这个是false
            if (args.length - curArg > 0) {
                throw new IllegalArgumentException("Unexpected arguments after --boot-completed");
            }
        } else if (mAbiListQuery || mPidQuery) {//这两个是false
            if (args.length - curArg > 0) {
                throw new IllegalArgumentException("Unexpected arguments after --query-abi-list.");
            }
        } else if (mPreloadPackage != null) {//这个也没有赋值
            if (args.length - curArg > 0) {
                throw new IllegalArgumentException(
                    "Unexpected arguments after --preload-package.");
            }
        } else if (mPreloadApp != null) {//这个也没有赋值
            if (args.length - curArg > 0) {
                throw new IllegalArgumentException(
                    "Unexpected arguments after --preload-app.");
            }
        } else if (expectRuntimeArgs) {//这个是true
            if (!seenRuntimeArgs) {
                throw new IllegalArgumentException("Unexpected argument : " + args[curArg]);
            }

            mRemainingArgs = new String[args.length - curArg];//这里就把 "com.android.server.SystemServer" 参数处理了
            System.arraycopy(args, curArg, mRemainingArgs, 0, mRemainingArgs.length);
        }

        if (mStartChildZygote) {//这个也是false
            //...
        }
    }

总结

上面的这个ZygoteArguments类主要做参数处理。

  1. 将参数放到类的成员变量
  2. 把 "com.android.server.SystemServer" 参数 放到了 mRemainingArgs
  3. 需要注意一下mInvokeWith这个变量没有赋值,后面会用到

下面正式去寻找Runnable的来源

ZygoteInit.java handleSystemServerProcess

    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
        // set umask to 0077 so new files and directories will default to owner-only permissions.
        //将umask设置为0077,以便新文件和目录将默认为仅所有者权限。
        Os.umask(S_IRWXG | S_IRWXO);

        if (parsedArgs.mNiceName != null) {
            Process.setArgV0(parsedArgs.mNiceName);
        }

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);
            // Capturing profiles is only supported for debug or eng builds since selinux normally
            // prevents it.捕获配置文件仅支持调试或eng构建,因为selinux通常会阻止它。
            if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
                try {
                    Log.d(TAG, "Preparing system server profile");
                    prepareSystemServerProfile(systemServerClasspath);
                } catch (Exception e) {
                    Log.wtf(TAG, "Failed to set up system server profile", e);
                }
            }
        }
//***说实话,前面一大堆代码干嘛的没看懂

        //前面分析参数的时候,知道了这个mInvokeWith没有赋值,所以会是null
        if (parsedArgs.mInvokeWith != null) {
            String[] args = parsedArgs.mRemainingArgs;
            // If we have a non-null system server class path, we'll have to duplicate the
            // existing arguments and append the classpath to it. ART will handle the classpath
            // correctly when we exec a new process.
            //如果我们有一个非null的系统服务类路径,我们将必须复制现有参数并将类路径附加到该路径上。 当我们执行新进程时,ART将正确处理类路径。
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(args, 0, amendedArgs, 2, args.length);
                args = amendedArgs;
            }

            WrapperInit.execApplication(parsedArgs.mInvokeWith,
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);

            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.mTargetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             * 将其余参数传递给SystemServer。
             */
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }

        /* should never reach here */
    }

总结

上面这个方法没什么好看的,只看最后返回ZygoteInit.zygoteInit的返回值,注意:parsedArgs.mRemainingArgs的值是:"com.android.server.SystemServer"

ZygoteInit.java zygoteinit

   public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
       //前面好像都是一些初始化操作
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader); 
    }

总结

这个方法比较简单了,最后调用RuntimeInit.applicationInit,不多说了。注意:argv只有一个参数:"com.android.server.SystemServer"

RuntimeInit.java applicationInit

 protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
         // 如果应用程序调用System.exit(),则在不运行任何关闭挂钩的情况下立即终止进程。 无法正常关闭Android应用程序。 其中,Android运行时关闭挂钩会关闭Binder驱动程序,这可能导致剩余的运行线程在进程实际退出之前崩溃。
        nativeSetExitWithoutCleanup(true);

        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);//设置sdk版本
        VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);//兼容性?不太懂这句

        final Arguments args = new Arguments(argv);//重新封装参数 argv只有一个参数:"com.android.server.SystemServer"

        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        // Remaining arguments are passed to the start class's static main 其余参数传递给起始类的静态main
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

总结

这个方法也简单

  1. 设置sdk版本
  2. 重新封装参数
  3. 找到要运行的静态类
  4. 重点关注一下调用findStaticMain方法的args.startClass参数

下面看一下findStaticMain方法的args.startClass参数:

static class Arguments {
        /** first non-option argument */
        String startClass;

        /** all following arguments */
        String[] startArgs;

        Arguments(String args[]) throws IllegalArgumentException {
            parseArgs(args);
        }

        /**
         * Parses the commandline arguments intended for the Runtime.
         */
        private void parseArgs(String args[])
                throws IllegalArgumentException {
            int curArg = 0;
            for (; curArg < args.length; curArg++) {
                String arg = args[curArg];

                if (arg.equals("--")) {//没有 -- 开头的参数
                    curArg++;
                    break;
                } else if (!arg.startsWith("--")) {//没有 -- 开头的参数 直接break了
                    break;
                }
            }

            if (curArg == args.length) {
                throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
            }

            startClass = args[curArg++];// 这里有一个 "com.android.server.SystemServer" 参数了
            startArgs = new String[args.length - curArg];
            System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
        }
    }

总结

这个类也简单,需要注意的是:startClass的值是com.android.server.SystemServer

RuntimeInit.java findStaticMain

protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        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);
        }

        /*
         * This throw gets caught in ZygoteInit.main(), which responds
         * by invoking the exception's run() method. This arrangement
         * clears up all the stack frames that were required in setting
         * up the process.
         */
        return new MethodAndArgsCaller(m, argv);
    }

总结

这个方法也简单

  1. 通过反射找到需要运行的类的main方法,startClass的值是com.android.server.SystemServer,所以这里运行那个类不用多说了吧
  2. 创建MethodAndArgsCaller类的对象返回,MethodAndArgsCaller类实现Runnable接口,可算找到了,哈哈哈

RuntimeInit.java MethodAndArgsCaller类

static class MethodAndArgsCaller 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);
            }
        }
    }

这个类也简单

  1. 实现了Runnable接口
  2. 在run方法中运行传递过来的方法

最终总结

整个流程走下来,其实都非常简单,最主要的是要记住参数都是来自哪里,是个什么值,这对后续的代码走哪里非常重要。到这,System Server进程就启动,而且之后的任务是执行: com.android.server.SystemServer的main方法

results matching ""

    No results matching ""