美文网首页流程Android开发经验谈程序员
Android启动(三)----开启SystemServer进程

Android启动(三)----开启SystemServer进程

作者: 拉丁吴 | 来源:发表于2016-05-19 15:31 被阅读228次

    前面已经讲到,从C/C++层进入了Java层,即调用了ZygoteInit.main()函数,那么接下来会发生什么事情呢?

    源码参考Android4.1.1,涉及的文件有ZygoteInit.java,RuntimeInit.java(framework文件夹下)

    ZygoteInit.main():

    public static void main(String argv[]) {
            try {
                // Start profiling the zygote initialization.
                SamplingProfilerIntegration.start();
               //创建服务端的socket
                registerZygoteSocket();
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                    SystemClock.uptimeMillis());
           // 最终调用preloadClasses();preloadResources();两个函数,
           //加载class文件和res资源
                preload();
              
      EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
    
                // Finish profiling the zygote initialization.
                SamplingProfilerIntegration.writeZygoteSnapshot();
    
                // Do an initial gc to clean up after startup
                gc();
                //这里的argv就是在C层产生的字符串数组,有两个元素
                // If requested, start system server directly from Zygote
                if (argv.length != 2) {
                    throw new RuntimeException(argv[0] + USAGE_STRING);
                }
                //显然,条件成立
                if (argv[1].equals("start-system-server")) {
                   //这是要真刀真枪的开启SS进程了
                    startSystemServer();
                } else if (!argv[1].equals("")) {
                    throw new RuntimeException(argv[0] + USAGE_STRING);
                }
    
                Log.i(TAG, "Accepting command socket connections");
    
                if (ZYGOTE_FORK_MODE) {
                    runForkMode();
                } else {
                   //这个函数其实也很重要,简而言之,让zygote休眠,但是随时能接受消息
                    //从loop字眼也可以看出循环的意思,后面的文章会在提到这个
                    runSelectLoopMode();
                }
    
                closeServerSocket();
            } catch (MethodAndArgsCaller caller) {
                caller.run();
            } catch (RuntimeException ex) {
                Log.e(TAG, "Zygote died with exception", ex);
                closeServerSocket();
                throw ex;
            }
        }
    
    

    再看看startSystemServer()函数

     private static boolean startSystemServer()
                throws MethodAndArgsCaller, RuntimeException {
            /* 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,3001,3002,3003,3006,3007",
                "--capabilities=130104352,130104352",
                "--runtime-init",
                "--nice-name=system_server",
                "com.android.server.SystemServer",
            };
            ZygoteConnection.Arguments parsedArgs = null;
    
            int pid;
    
            try {
                parsedArgs = new ZygoteConnection.Arguments(args);
                ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
                ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
    
                /* Request to fork the system server process */
                pid = Zygote.forkSystemServer(//fork一个子进程
                        parsedArgs.uid, parsedArgs.gid,
                        parsedArgs.gids,
                        parsedArgs.debugFlags,
                        null,
                        parsedArgs.permittedCapabilities,
                        parsedArgs.effectiveCapabilities);
            } catch (IllegalArgumentException ex) {
                throw new RuntimeException(ex);
            }
    
            /* For child process */
            if (pid == 0) {//子进程,即system_server进程
                handleSystemServerProcess(parsedArgs);
            }
            return true;
        }
    

    果然看到了forkSystemServer这样的函数了,接下来在子进程中调用了handleSystemServerProcess()函数:

      /**
         * Finish remaining work for the newly forked system server process.
         */
        private static void handleSystemServerProcess(
                ZygoteConnection.Arguments parsedArgs)
                throws ZygoteInit.MethodAndArgsCaller {
    
            closeServerSocket();
    
            // set umask to 0077 so new files and directories will default to owner-only permissions.
            FileUtils.setUMask(FileUtils.S_IRWXG | FileUtils.S_IRWXO);
           //niceName?
            if (parsedArgs.niceName != null) {
                Process.setArgV0(parsedArgs.niceName);
            }
    
            if (parsedArgs.invokeWith != null) {
                WrapperInit.execApplication(parsedArgs.invokeWith,
                        parsedArgs.niceName, parsedArgs.targetSdkVersion,
                        null, parsedArgs.remainingArgs);
            } else {
                /*
                 * Pass the remaining arguments to SystemServer.
                 */
              //显然就是这个函数最重要了,
                RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
            }
        }
    

    需要注意的是zygoteInit()函数是RuntimeInit类直接调用的,说明它是静态函数,在RuntimeInit.java文件中,zygoteInit()函数如下:

    /**
         * The main function called when started through the zygote process. This
         * could be unified with main(), if the native code in nativeFinishInit()
         * were rationalized with Zygote startup.<p>
         *
         * Current recognized args:
         * <ul>
         *   <li> <code> [--] <start class name>  <args>
         * </ul>
         *
         * @param targetSdkVersion target SDK version
         * @param argv arg strings
         */
        public static final void zygoteInit(int targetSdkVersion, String[] argv)
                throws ZygoteInit.MethodAndArgsCaller {
            if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
    
            redirectLogStreams();
            commonInit(); 
           //本地zygoteInit函数,主要职责是C++层的初始化
            nativeZygoteInit();
          //另外的一些初始化工作
            applicationInit(targetSdkVersion, argv);
        }
    
    

    本地的zygoteInit函数我们先放在一边,先看applicationInit函数:

    private static void applicationInit(int targetSdkVersion, String[] argv)
                throws ZygoteInit.MethodAndArgsCaller {
            // 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.
            nativeSetExitWithoutCleanup(true);
    
            // We want to be fairly aggressive about heap utilization, to avoid
            // holding on to a lot of memory that isn't needed.
    
            VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
            VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
    
            final Arguments args;
            try {
               //一些参数设定
                args = new Arguments(argv);
            } catch (IllegalArgumentException ex) {
                Slog.e(TAG, ex.getMessage());
                // let the process exit
                return;
            }
    
            // Remaining arguments are passed to the start class's static main
    //英文解释的其实已经比较明白了,
            invokeStaticMain(args.startClass, args.startArgs);
        }
    
    

    再来看看invokeStaticMain函数,很明显,调用了JNI.

        private static void invokeStaticMain(String className, String[] argv)
                throws ZygoteInit.MethodAndArgsCaller {
            Class<?> cl;
    
            try { 
                //获取类对象
                cl = Class.forName(className);
            } 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.
             */
            throw new ZygoteInit.MethodAndArgsCaller(m, argv);
            ##居然主动抛出异常?!!,what‘s the shit?
        }
    

    好吧,我在手心连写十个“忍”,继续还是心平气和的看代码,其实只要往上追溯,由于上层的方法都选择抛出该异常,最终追溯到了ZygoteInit.main()方法中,
    在回顾main函数(部分):

    try {
          .........
          .........
          .........
                if (argv[1].equals("start-system-server")) {
                    startSystemServer();
                } else if (!argv[1].equals("")) {
                    throw new RuntimeException(argv[0] + USAGE_STRING);
                }
    
                Log.i(TAG, "Accepting command socket connections");
    
                if (ZYGOTE_FORK_MODE) {
                    runForkMode();
                } else {
                    runSelectLoopMode();
                }
    
                closeServerSocket();
            } catch (MethodAndArgsCaller caller) {
              ##shit!!,在这里catch到了这个异常,看来是有意为之了
                caller.run();
            } catch (RuntimeException ex) {
                Log.e(TAG, "Zygote died with exception", ex);
                closeServerSocket();
                throw ex;
            }
    

    好,caller对象是(MethodAndArgsCaller类型的,继续看caller.run()做了什么:

         ......
         ......
            public void run() {
                try {
             ##kidding me ??!!,在这里调用了SystemServer.main()方法?
                    mMethod.invoke(null, new Object[] { mArgs });
                    //有兴趣的同学可以研究一下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);
                }
            }
    
    • 问题到这里可以说结束了,最终(fork的子进程)调用了SystemServer.main()函数,相当于创造了SystemS进程。

    那么问题来了,为什么不在主动抛出异常的的地方直接调用main方法?

    • 说实话,我不是很理解,但是看了邓平凡大大的《深入理解Android I》(是本好书,值得推荐),里面给出了一种解释那就是释放堆栈中被浪费的资源。

    稍微解释一下,就是函数的调用是需要利用调用堆栈来实现的,每调用一个函数,原来的函数的资源会被压入栈,如果嵌套调用的函数多了的话,会占用系统资源。而关键在于SystemServer进程是不会死的(如果死了的话,系统也挂掉了),所以,也就意味着在这之前占用的那些资源不会被释放,so.......

    多说一句,这种方式似乎达成了exec的函数调用的效果,上一篇文章提到,fork往往和exec一起用,可以造就两个不同的进程,但是实际上exec系统调用的工作原理是替换原来的进程的执行内容,只保留进程ID,可以说exec系统调用会擦除之前的进程积压的资源,这种抛异常的方式从某种程度上来讲实现了exec的效果。

    相关文章

      网友评论

        本文标题:Android启动(三)----开启SystemServer进程

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