Android系统启动流程

2019/09/09 Android

Android系统从开机到Launcher启动的整体流程,其中包括Init进程,Zygote进程,SystemServer进程及Launcher的启动流程。

Android 系统启动流程

Android 启动流程大致分为以下几步

  • 1.Init进程的启动。
  • 2.Zygote进程的启动
  • 3.SystemServer进程的启动
  • 4.Launcher的启动

目录

Init进程的启动

Init进程为Android系统中第一个进程,进程号为1.内核启动之后,通过init.rc配置文件,启动init进程。init进程会进行初始化和启动属性服务,并且启动Zygote进程。

Zygote进程

Zygote进程,意为“孵化器”,我们的应用程序进程通过Zygote fork自身的方式来创建进程。同时SystemServer进程也是通过Zygote进程来fork创建的。Zygote进程中创建了Java虚拟机,并且为虚拟机注册了JNI方法。通过JNI方法进入ZygoteInit.java文件中的main(),由此进入了Java层。

core\java\com\android\internal\os\ZygoteInit.java

public static void main(String argv[]) {
        try {
            ......
            String socketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } 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());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }

            // 1 Zygote进程创建了一个Socket,用于之后的AMS请求连接。
            zygoteServer.registerServerSocket(socketName);  
            // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                    SystemClock.uptimeMillis());
                preload(bootTimingsTraceLog);   // 2 Zygote预加载类和资源
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }
            ......

            if (startSystemServer) {
                startSystemServer(abiList, socketName, zygoteServer); // 3 开启SystemServer进程
            }

            Log.i(TAG, "Accepting command socket connections");
            zygoteServer.runSelectLoop(abiList);    // 4 启动Socket连接,等待AMS请求。

            zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        }
    }

main()函数的注释1中,我们可以看到Zygote进程创建了一个Socket,这个Socket是用于之后AMS请求连接的,因为AMS在请求创建根Activity之前会先判断当前应用程序进程是否已经创建,如果未创建则会通过这个Socket请求Zygote进程来fork应用程序进程。也即Zygote进程和AMS所在进程(SystemServer进程)是通过Socket进行通信的。
在注释2中,Zygote进行预加载类和资源。 从注释3中可见,在预加载完类和资源之后,Zygote进程开始创建启动SystemServer进程。
而在注释4中可见,Zygote进程开始启动运行Socket连接,等待AMS请求。我们可以看下代码及注释是如何开启Socket等待AMS连接的。

core\java\com\android\internal\os\ZygoteServer.java

    /**
     * Runs the zygote process's select loop. Accepts new connections as
     * they happen, and reads commands from connections one spawn-request's
     * worth at a time.
     *
     * @throws Zygote.MethodAndArgsCaller in a child process when a main()
     * should be executed.
     */
    void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

        fds.add(mServerSocket.getFileDescriptor());
        peers.add(null);

        while (true) {  // 无线循环来监听AMS的连接请求。
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = 0; i < pollFds.length; ++i) {
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i);
                pollFds[i].events = (short) POLLIN;
            }
            try {
                Os.poll(pollFds, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            for (int i = pollFds.length - 1; i >= 0; --i) {
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }
                if (i == 0) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    boolean done = peers.get(i).runOnce(this);  // Zygote进程接收到AMS请求之后进行fork本身来创建应用程序进程。
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }

所以从ZygoteInitmain()方法中我们可以知道Zygote进程中完成了以下几件事情:

  1. 创建了一个用于AMS请求连接的Socket。
  2. 预加载类和资源
  3. 创建启动SystemServer进程
  4. 开启Socket连接,等待AMS请求。

SystemServer进程的启动

从上文我们可以得知,SystemServer进程由Zygote进程创建并启动,函数入口为startSystemServer方法,我们可以来分析下这个方法。

core\java\com\android\internal\os\ZygoteInit.java

    /**
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.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,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 {
            // 将SystemServer进程启动参数,封装为Arguments类的一个对象依次传递下去。
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);  // Zygote进程通过fork自身来创建SystemServer进程。
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) { // 进程号为0,说明运行在子进程中。此处即为在SystemeServer进程中运行。
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            //  关闭Socket连接
            zygoteServer.closeServerSocket();
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

首先进行fork之前的准备工作,初始化参数args[],将其封装为ZygoteConnection.Arguments类的一个对象,之后依次传递下去。随后通过Zygote.forkSystemServer来fork本身来创建SystemServer进程。我们先看下在Zygote.java中是如何forkSystemServer的。

core\java\com\android\internal\os\Zygote.java

    /**
     * Special method to start the system server process. In addition to the
     * common actions performed in forkAndSpecialize, the pid of the child
     * process is recorded such that the death of the child process will cause
     * zygote to exit.
     *
     * @param uid the UNIX uid that the new process should setuid() to after
     * fork()ing and and before spawning any threads.
     * @param gid the UNIX gid that the new process should setgid() to after
     * fork()ing and and before spawning any threads.
     * @param gids null-ok; a list of UNIX gids that the new process should
     * setgroups() to after fork and before spawning any threads.
     * @param debugFlags bit flags that enable debugging features.
     * @param rlimits null-ok an array of rlimit tuples, with the second
     * dimension having a length of 3 and representing
     * (resource, rlim_cur, rlim_max). These are set via the posix
     * setrlimit(2) call.
     * @param permittedCapabilities argument for setcap()
     * @param effectiveCapabilities argument for setcap()
     *
     * @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.   // 如果是子进程,pid返回0。如果是父进程,则返回-1。
     */
    public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        VM_HOOKS.preFork();
        // Resets nice priority for zygote process.
        resetNicePriority();
        // 通过native方法来创建SystemServer进程。
        int pid = nativeForkSystemServer(
                uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
        // Enable tracing as soon as we enter the system_server.
        if (pid == 0) {
            Trace.setTracingEnabled(true);
        }
        VM_HOOKS.postForkCommon();
        return pid;
    }

可以看到,forkSystemServer通过调用native方法nativeForkSystemServer来进行创建SystemServer进程的,同时可从函数的javadoc文档注释中看到,当fork SystemServer进程之后在SystemServer进程中将返回0。然后再回过头去看startSystemServer函数。

        /* For child process */
        if (pid == 0) { // 进程号为0,说明运行在子进程中。此处即为在SystemeServer进程中运行。
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            //  关闭Socket连接
            zygoteServer.closeServerSocket();
            handleSystemServerProcess(parsedArgs);
        }

在Zygote进程fork SystemServer进程之后,在SystemServer进程中会首先关闭Socket连接,然后再处理一些SystemServer进程需要初始化的一些事情。这时有个问题来了,为什么在SystemServer进程中需要关闭Socket连接呢?因为SystemServer进程是通过Zygote进程fork本身创建的,而之前我们分析Zygote进程时知道,Zygote进行创建了Java虚拟机及用于等待AMS进程连接的Socket所以SystemServer进程也会拥有这些。而在SystemServer进程中不需要这个Socket,所以需要将其关闭。然后我们再来看下handleSystemServerProcess方法来了解SystemServer进程具体做了哪些事情。

core\java\com\android\internal\os\ZygoteInit.java

    /**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws Zygote.MethodAndArgsCaller {
        // ......
        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        // ......
        if (parsedArgs.invokeWith != null) {
            String[] args = parsedArgs.remainingArgs;
            // 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.
            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.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                // 创建PathClassLoader。
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

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

            /*
             * Pass the remaining arguments to SystemServer.
             */
            // 传入剩下的参数给SystemServer进程。
            ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }

从方法调用依次看来,我们知道参数parsedArgs是从startSystemServer函数中SystemServer启动参数args[]封装而来,而parsedArgs.invokeWith是为null的。所以进入下面的判断。在中文注释中可以看到,SystemServer进程创建了Android类加载器中的其中一类 : PathClassLoader。(Android中类加载器有,BootClassLoader, DexClassLoader, PathClassLoader)然后再看剩下的SystemServer启动参数传入SystemServer。进入到ZygoteInit.java的ZygoteInit.zygoteInit方法。

core\java\com\android\internal\os\ZygoteInit.java

    /**
     * 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> [--] &lt;start class name&gt;  &lt;args&gt;
     * </ul>
     *
     * @param targetSdkVersion target SDK version
     * @param argv arg strings
     */
    public static final void zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

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

        RuntimeInit.commonInit();
        // 创建Binder线程池
        ZygoteInit.nativeZygoteInit();
        // 进行初始化操作
        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

这里有两个重要的方法。ZygoteInit.nativeZygoteInit()RuntimeInit.applicationInit()。第一个方法调用native方法创建了Binder线程池,为了SystemServer进程可以和其他进程进行通信。而第二个方法进行了初始化的操作。我们来看下RuntimeInit.java的applicationInit().

core\java\com\android\internal\os\RuntimeInit.java

    protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller {
        //  ......
        final Arguments args = new Arguments(argv);
        //......

        // Remaining arguments are passed to the start class's static main
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

applicationInit()中最主要调用了方法invokeStaticMain

   /**
     * Invokes a static "main(argv[]) method on class "className".
     * Converts various failing exceptions into RuntimeExceptions, with
     * the assumption that they will then cause the VM instance to exit.
     *
     * @param className Fully-qualified class name
     * @param argv Argument vector for main()
     * @param classLoader the classLoader to load {@className} with
     */
    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws Zygote.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);
        }

        // 下文的英文注释也说了,异常最终抛给ZygoteInit.main()来处理。并且这样的处理会清除设置过程中的堆栈帧。
        /*
         * 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 Zygote.MethodAndArgsCaller(m, argv);
    }

可以看到在invokeStaticMain()中通过className反射拿到要执行的类,而这里的className也就是com.android.server.SystemServer,拿到的类也就是SystemServer类。而这里的className为什么就是SystemServer类,具体可通过调用栈依次向前看,可以在ZygoteInit.java中的startSystemServer()方法中找到args这个字符串数组,最后一个字符串"com.android.server.SystemServer"就是我们这里的className。方法mmain方法。然后方法最终会抛出MethodAndArgsCaller异常。异常依次向上抛,最终在ZygoteInit.javamain()中处理,我们可以返回看下。

core\java\com\android\internal\os\ZygoteInit.java

    public static void main(String argv[]) {
        //......
        try {
            zygoteServer.closeServerSocket();
            } catch (Zygote.MethodAndArgsCaller caller) {
                // 通过捕获抛出的异常来执行main方法
                caller.run();
            } catch (Throwable ex) {
                Log.e(TAG, "System zygote died with exception", ex);
                zygoteServer.closeServerSocket();
                throw ex;
            }
    }

最终捕获异常来运行SystemServer中的main方法。为什么需要以这种方式来执行main方法呢,因为在启动SystemServer的过程中调用了一系列的准备方法,而通过抛异常的方式可以清除设置过程中的堆栈帧,让SystemServer看起来像从main入口处开始执行。这样SystemServer进程就开始执行main()函数了。

services\java\com\android\server\SystemServer.java

    public static void main(String[] args) {
        new SystemServer().run();
    }

执行SystemServer中的run()方法。

    private void run() {
        try {
            // 创建Looper
            Looper.prepareMainLooper();
            // 加载so文件
            // Initialize native services.
            System.loadLibrary("android_servers");

            // Check whether we failed to shut down last time we tried.
            // This call may not return.
            performPendingShutdown();

            // 创建系统上下文
            // Initialize the system context.
            createSystemContext();

            // 创建了SystemServiceManager
            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // Prepare the thread pool for init tasks that can be parallelized
            SystemServerInitThreadPool.get();
        } finally {
            traceEnd();  // InitBeforeStartServices
        }

        // Start services.
        try {
            traceBeginAndSlog("StartServices");
            // 启动引导服务
            startBootstrapServices();
            // 启动核心服务
            startCoreServices();
            // 启动其他服务
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
        ......

        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

run()的注释中我们可以知道,SystemServer创建了SystemServiceManager并且启动了三种服务。(Android把系统服务分为三种,分别为引导服务,核心服务,其他服务)。其中ActivityManagerServicePackageManagerService属于引导服务。在服务创建之后,SystemServiceManger会通过单例将服务添加进去,用来管理系统中的各种Service,用于系统的C/S架构中的Binder通信机制,某个Client需要使用服务时,需要先到SystemServiceManager中查询服务,然后通过Binder和Service所在的Server进程建立通信来调用服务。

所以SystemServer进程做了以下事情:

  1. 创建了Binder线程池,为了与其他进程进行通信。
  2. 创建SystemServiceManager启动并管理系统服务。
  3. 创建并启动三种系统服务。

Launcher的启动

Launcher的启动由AMS(ActivityManagerService)启动之后开始的,通过一系列的调用

`AMS(systemReady())-ActivityStackSupervisor(resumeFocusedStackTopActivityLocked())-ActivityStack(resumeTopActivityUncheckedLocked())-ActivityStack(resumeTopActivityInnerLocked())-ActivityStackSupervisor(resumeHomeStackTask)-AMS(startHomeActivityLocked())`

一系列的调用,最后调用AMS的startHomeActivityLocked()方法。

services\core\java\com\android\server\am\ActivityManagerService.java

    boolean startHomeActivityLocked(int userId, String reason) {
        ......
        // 创建Launcher需要的Intent
        Intent intent = getHomeIntent();
        ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
            // Don't do this if the home app is currently being
            // instrumented.
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
            if (app == null || app.instr == null) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
                // For ANR debugging to verify if the user activity is the one that actually
                // launched.
                final String myReason = reason + ":" + userId + ":" + resolvedUserId;
                // 启动Launcher
                mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
            }
        } else {
            Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
        }

        return true;
    }

通过getHomeIntent()创建Launcher需要的Intent,然后startHomeActivityLocked()启动Launcher。

services\core\java\com\android\server\am\ActivityStarter.java

    void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
        mSupervisor.moveHomeStackTaskToTop(reason);
        mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
                null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
                null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
                null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
                null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
                0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
                false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
                null /*container*/, null /*inTask*/, "startHomeActivity: " + reason);
        if (mSupervisor.inResumeTopActivity) {
            // If we are in resume section already, home activity will be initialized, but not
            // resumed (to avoid recursive resume) and will stay that way until something pokes it
            // again. We need to schedule another resume.
            mSupervisor.scheduleResumeTopActivities();
        }
    }

startHomeActivityLocked()通过startActivityLocked()启动,进入了Activity的启动流程,启动Launcher。

  • 遗留问题:https://www.zhihu.com/question/345196352 (该问题已解答)

Search

    Table of Contents