Android 系統啟動流程

panhaos發表於2018-08-23

Android系統是基於Linux定製的一款開源的而移動端作業系統,由於其開源的特性,各大手機廠商可以針對其原始碼進行深度定製,對於開發者來說,有如此龐大且優秀的開源os提供參考,尤其是對移動端的開發者來說,閱讀Android系統原始碼可以幫助我們更好地理解其中的各種機制,平時束手無策的問題也可以在原始碼中尋找答案。當然光8.0的原始碼就20多個g,像全部讀完幾乎是不可能的事,我們主要以framework為主線,以系統執行機制為分支,層層閱讀,剝開Android系統的神祕面紗。

Android 系統架構

首先來一張google經典的Android系統架構圖:可以看到,從上到下主要分為4層:應用層,framework層,系統庫和執行時,Linux核心層。

這裡寫圖片描述

#Android 啟動流程 這裡再上一張Android系統啟動的流程圖,可以看到系統從啟動開始是按照一個流程:Loader->kernel->framework->Application來進行的。

這裡寫圖片描述

Loader層:

  • Boot Rom:當手機處於關機狀態時,長按開機鍵開機,會引導晶片開始從固化在Rom裡預設的程式碼開始執行,然後載入載入程式到Ram
  • Boot Loader:啟動Android系統之前的載入程式,主要是檢查Ram,初始化引數等

Kernel層

Kernel層指的就是Android核心層,這裡一般開機剛剛結束進入Android系統,Kernel層的啟動流程如下:

  1. 啟動swapper程式(pid=0),這是系統初始化過程kernel建立的第一個程式,用於初始化程式管理、記憶體管理、載入DisplayCameraBinder等驅動相關工作
  2. 啟動kthreadd程式,這是Linux系統的核心程式,會建立核心工作執行緒kworkder、軟中斷執行緒ksoftirqdthermal等核心守護程式。kthreadd是所有核心程式的鼻祖。

Native層

這裡的native層主要包括由init程式孵化的使用者空間的守護程式,bootanim開機動畫和hal層等。InitLinux系統的守護程式,是所有使用者空間程式的鼻祖。

  • init程式會孵化出ueventdlogdhealthdinstalldadbd、lm這裡寫程式碼片kd等使用者守護程式;
  • init程式還會啟動ServiceManager(Binder服務管家)、bootanim(開機動畫)等重要服務。
  • init程式孵化出Zygote程式,Zygote程式是Android系統第一個Java程式(虛擬機器程式),Zygote程式是所有Java程式的父程式。

Framework層

framework層有native層和java層共同組成,協調系統平穩有序的工作。framework 層主要包括以下內容:

  • Media Server程式,是由init程式fork而來,負責啟動和管理整個C++ framework,包含AudioFlingerCamera Service等服務。
  • Zygote程式,由Init程式通過解析init.rc檔案生成,Zygote是Android系統的第一個Java程式,是所有Java程式的父程式。
  • System Server程式,由Zygote程式fork而來,是Zygote程式孵化的第一個子程式,負責啟動和管理整個Java Framework,包括AmsPms等。

App層

Zygote程式孵化的第一個App程式是Launcher程式,也就是我們的桌面程式,也就是我們開啟手機看到的使用者介面。因為在前面的framework 生成了各種守護程式和管理程式,對於Launcher也就有對應的點選、長按、滑動、解除安裝等監聽。Zygote程式也會建立BrowserPhoneEmail等App程式。也就是說所有的App程式都是由Zygote程式fork生成的。而且上層的程式全部由下層的程式進行管理,包括但不限於介面的註冊、跳轉,訊息的傳遞。

Zygote程式的啟動

瞭解了Android系統從按下開機鍵到桌面完整執行在使用者眼前的整個流程,我們就可以針對系統的各個過程進行分析。由於是移動開發,平時最多打交道的是應用層,也是就上面的App層,跟我們打交道最多的就是framework層,我們主要關注framework層是如何啟動並排程各應用程式協調工作的。從ZygoteInitmain方法開始,我們先看framework啟動流程的時序圖(省略了一些步驟)大體如下:

這裡寫圖片描述

1.ZygoteInit.main

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

        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();
		...
        try {
            // Report Zygote start time to tron unless it is a runtime restart
            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
                MetricsLogger.histogram(null, "boot_zygote_init",
                        (int) SystemClock.elapsedRealtime());
            }
			...
			// 1.載入首個Zygote程式的時候,載入引數有start-system-server,即startSystemServer=true
			
            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.");
            }

			// 2. 註冊zygote服務端localserversocket
            zygoteServer.registerServerSocket(socketName);
	        ...
			// 3.在這裡開啟了SystemServer,也就是Ams,Pms,Wms...等一系列系統服務
            if (startSystemServer) {
                startSystemServer(abiList, socketName, zygoteServer);
            }
            Log.i(TAG, "Accepting command socket connections");
            
			// 4.while(true) 死迴圈,除非丟擲異常系統中斷
            zygoteServer.runSelectLoop(abiList);
            zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        }
    }
複製程式碼

ZygoteInit.main()native層傳入初始化引數呼叫,這裡不再贅述,這邊主要沿Java的framework層來分析系統的呼叫,結合上圖和程式碼註釋可以看到,載入引數有start-system-server,即startSystemServer=true賦值,緊接著下面會呼叫ZygoteServer.registerServerSocket(),也就是這裡和ZygoteServer的通訊用到的是LocalSocket,我們知道跨程式呼叫最常見的呼叫方式就是LocalSocketaidl,在framework裡也有很多這樣通訊的。接下來就開啟了SystemServer,後面是一個runSelectLoop(),這裡其實是一個死迴圈,當丟擲異常終止則會呼叫zygoteServer.closeServerSocket()來關閉socket連線。我們繼續跟進startSystemServer看具體是如何開啟系統服務的。

2.startSystemServer

    /**
     * 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 {
	        //傳入準備引數,注意上面引數最後的"com.android.server.SystemServer"
            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);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
		
		// pid = 0 說明建立子程式成功,SystemServer此時擁有獨立程式,可以獨立在自己的程式內操作了
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            // 處理SystemServer程式
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }
複製程式碼

這個方法不是很長,看註釋可以知道,主要是用來準備SystemServer程式的引數和forkSystemServer程式。前面一堆引數不用看,注意我新增中文註釋的地方,傳入的引數有一個內容為"com.android.server.SystemServer",這是SystemServer類的全限定名,接下來呼叫Zygote.forkSystemSeerver(),最後當pid=0時,也就是說明子程式建立成功,如果這時候有兩個Zygote程式則等待第二個Zygote程式連線,關閉掉第一個Zygote程式和ZygoteServersocket連線。最後呼叫handleSystemServerProcess()來處理SystemServer程式。這裡的Zygote.forkSystemServer()實際上是呼叫了native層的forkSystemServer()來fork子程式。這裡主要跟進handleSystemServerProcess()看看是如何完成新fork的SystemServer程式的剩餘工作的。

3.handleSystemServerProcess

	/**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws Zygote.MethodAndArgsCaller {
		...
		// 預設為null,走Zygote.init()流程
		
        if (parsedArgs.invokeWith != null) {
            ...
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
	            // 建立類載入器,並賦予當前執行緒
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
            ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }
複製程式碼

parsedArgs.invokeWith預設是為null的,也就是走else流程,可以看到先建立了一個類載入器並賦予了當前執行緒,然後進入了ZygoteInit.zygoteInit()

4.ZygoteInit.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> [--] &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();
		// Zygote初始化
        ZygoteInit.nativeZygoteInit();
		// 應用初始化
        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }
複製程式碼

這個方法不是很長,主要工作是Zygote的初始化和Runtime的初始化。Zygote 的初始化呼叫了native方法,裡面的大致工作是開啟/dev/binder驅動裝置,建立一個新的binder執行緒,呼叫talkWithDriver()不斷地跟驅動互動。 進入RuntimeInit.applicationInit()檢視具體應用初始化流程。

5.RuntimeInit.applicationInit

    protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws Zygote.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;
        }

        // 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
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }
複製程式碼

這個方法也不是很長,前面的一些配置略過,主要看解析引數和invokeStaticMain(),顧名思義,這裡的目的是通過反射呼叫靜態的main方法,那麼呼叫的是哪個類的main方法,我們看傳入的引數是args.startClass,我們追溯引數的傳遞過程,發現之前提到的一系列args被封裝進ZygoteConnection.Arguments類中,這一系列引數原本是

        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",
        };
複製程式碼

可以看到,唯一的類的全限定名是com.android.server.SystemServer,追述args = new Arguments(argv)的原始碼也可以找到答案:

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

        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;
                }
            }

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

			// startClass 為args的最後一個引數
            startClass = args[curArg++];
            startArgs = new String[args.length - curArg];
            System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
        }
    }
複製程式碼

6.RuntimeInit.invokeStaticMain

    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);
        }

        /*
         * 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);
    }
複製程式碼

可以看到,這邊走的就是正常的一個反射流程,會對main方法的引數、修飾符等校驗,有問題丟擲RuntimeException執行時異常,沒問題就丟擲一個Zygote.MethodAndArgsCaller,這一步的處理可以說是非常奇怪了,既然執行完畢為什麼不直接invoke而是丟擲異常呢,我們可以看到英文註釋的大概解釋,這個異常丟擲在ZygoteInit.main()方法,執行了異常的run方法,其目的是清除設定中的所有堆疊幀,既然如此我們回到ZygoteInit.main()方法,果然:

	try{
		...
	}catch (Zygote.MethodAndArgsCaller caller) {
        caller.run();
    }
複製程式碼

丟擲該異常呼叫了caller.run()方法,那我們看這裡做了什麼:

    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);
            }
        }
    }
複製程式碼

可以看到,這裡呼叫了mMethod.invoke(null, new Object[] { mArgs }),也就是執行了SystemServermain方法。

7.SystemServer.main

    public static void main(String[] args) {
        new SystemServer().run();
    }
複製程式碼
		try {
			...
			//主執行緒在當前程式
			Looper.prepareMainLooper();
			...
            // 初始化系統上下文
            createSystemContext();
            
            // 1.建立SystemServiceManager
            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();
		}
		...
        try {
            traceBeginAndSlog("StartServices");
			//2.開啟一些重要的系統服務
            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");
複製程式碼

可以看到,這邊主要的工作,建立主執行緒Looper迴圈器,初始化系統上下文,最關鍵的還是後面的開啟一系列的服務,這些服務就包括了系統服務,跟進sartBootstrapService()看看是如何初始化系統服務的。

8.SystemServer.startBootstrapServices

		...
		SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);
		// 阻塞等待與installd建立socket通道
		Installer installer = mSystemServiceManager.startService(Installer.class);
		// 1. 在這裡開啟了Ams
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        ...

		// 2.在這裡開啟了PowerManagerService
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
		
		// 3.Ams 初始化PowerManager
        mActivityManagerService.initPowerManagement();
        
        // Bring up recovery system in case a rescue party needs a reboot
        if (!SystemProperties.getBoolean("config.disable_noncore", false)) {
            traceBeginAndSlog("StartRecoverySystemService");
            // 
            mSystemServiceManager.startService(RecoverySystemService.class);
            traceEnd();
        }
		
		mSystemServiceManager.startService(LightsService.class);
		
		mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
		
		mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();
        
		mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
		
		mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));
		
複製程式碼

可以看見啟動了很多的系統服務,其中很多的服務目前也不是很瞭解,主要的是ActivityMangerServicePackageManagerService等主要管理系統的一些服務。自此,Android系統的SystemServer已經啟動,並且其相關的各種系統服務已經啟動,Ams等重要系統服務也均已開啟。Ams是貫穿Android系統的核心服務,負責系統四大元件的啟動、切換及其生命週期管理和排程等工作,各個應用程式App作為獨立程式需要通過BinderAms進行通訊,而AmsSystemServer中通過LocalSocketZygote進行通訊。不管是對於系統執行的原理,還是各元件的排程過程,理解Ams的工作原理十分重要,接下來將以此為主線,分別分析Ams、四大元件等的啟動流程和生命週期的管理等。

參考資料

Android 8.0.1原始碼

Android系統開篇

Android系統啟動過程深入分析

相關文章