Android系統核心機制之系統啓動篇

夢幻曲:Android系統啓動

之前花過一段時間整理了下Android系統啓動、Activity啓動以及ActivityThread等系統內容。時間久遠,很多細節都忘了,本着互聯共享的精神,在這裏把之前的文檔重新整理。計劃寫三篇文章:《夢幻曲:Android系統啓動》,《沉思曲:Activity啓動》、《小夜曲:ActivityThread分析》,一家之言難免有各種問題,僅供參考。
參考 | http://blog.csdn.net/jeffbao/article/details/18242515

概念


Dalvik虛擬機

當java程序運行時,都是有一個虛擬機來解釋java的字節碼,它將這些字節碼翻譯成本地CPU的指令碼,然後執行。

AndroidRuntime

歸納起來的意思就是,Runtime 是支撐程序運行的基礎庫,它是與語言綁定在一起的。比如:

  • C Runtime:就是C standard lib,也就是我們常說的libc。(有意思的是, Wiki會自動將“C runtime” 重定向到 “C Standard Library”)。
  • Java Runtime: 同樣,Wiki將其重定向到” Java Virtual Machine”,這裏當然包括Java 的支撐類庫(.jar)。
  • AndroidRuntime: 顯而易見,就是爲Android應用運行所需的運行時環境。包括:
    • Dalvik VM: Android的Java VM,解釋運行Dex格式Java程序。每個進程運行一個虛擬機(什麼叫運行虛擬機?說白了,就是一些C代碼,不停的去解釋Dex格式的二進制碼(Bytecode),把它們轉成機器碼(Machine code),然後執行。
      • 當然,現在大多數的Java 虛擬機都支持JIT,也就是說,byte code可能在運行前就已經被轉換成機器碼,從而大大提高了性能。過去一個普遍的認識是Java 程序比C,C++等靜態編譯的語言慢,但隨着JIT的介入和發展,這個已經完全是過去時了,JIT的動態性運行允許虛擬機根據運行時環境,優化機器碼的生成,在某些情況下,Java甚至可以比C/C++跑得更快,同時又兼具平臺無關的特性,這也是爲什麼Java如今如此流行的原因之一吧)。
    • Android的Java 類庫, 大部分來自於 Apache Hamony, 開源的Java API 實現,如 java.lang, java.util, java.net. 但去除了AWT, Swing 等部件。
    • JNI: C和Java互調的接口。
    • Libc: Android也有很多C代碼,自然少不了libc,注意的是,Android的libc叫 bionic C.


框架圖

在往下講之前,先看下框架圖:

框架圖.png

代碼流程圖

Android系統啓動流程圖.png

init進程


init進程的啓動配置在init.rc文件中,
note:init.rc文件的語法可參考:init.rc分析

1.1、init進程啓動ServiceManager

/*service後第一個參數爲進程名,第二個參數爲進程路徑,後面參數爲啓動改進程傳遞的參數*/

//service關鍵字啓動servicemanager
service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart drm
  • Servicemanager負責管理所有的服務(native service、java service),如服務的註冊、查找等。
  • native service主要有: surfaceflinger、drm、media等。
  • java service主要有:ActivityManagerService、WindowManagerService、PowerManagerService等。
  • 其中,native service大多在init.rc文件中由service關鍵字創建啓動;java service大多由zygote創建啓動。

1.2、init進程啓動Zygote

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd
  • 由service第二個參數可知,此處啓動的進程爲zygote進程,並由app_process實現。
  • zygote由java編寫,不能有init進程直接啓動;必須先生成Dalvik虛擬機,再在Dalvik虛擬機中裝載zygote的實現類(ZygoteInit.java)。

Zygote進程


在往下講Zygote進程前,先看附圖,瞭解下Zygote都做啥了:

Zygote.png

Zygote進程的入口在app_main.cpp文件的main方法中,看下其main方法

2.1 main | app_main.cpp

int main(int argc, char* const argv[])
{
 ...
  //解析入參,此處入參爲“--zygote --start-system-server”
  while (i < argc) {
      const char* arg = argv[i++];
      if (!parentDir) {
          parentDir = arg;
      } else if (strcmp(arg, "--zygote") == 0) {
          zygote = true;
          niceName = "zygote";
      } else if (strcmp(arg, "--start-system-server") == 0) {
          startSystemServer = true;
      } else if (strcmp(arg, "--application") == 0) {
          application = true;
      } else if (strncmp(arg, "--nice-name=", 12) == 0) {
          niceName = arg + 12;
      } else {
          className = arg;
          break;
      }
  }

  //設置進程名
  if (niceName && *niceName) {
      setArgv0(argv0, niceName);
      set_process_name(niceName);
  }

  runtime.mParentDir = parentDir;

  if (zygote) {
      //start生成並初始化Dalvik虛擬機,並加載ZygoteInit類到虛擬機中
      runtime.start("com.android.internal.os.ZygoteInit",
              startSystemServer ? "start-system-server" : "");
  } else if (className) {
      runtime.mClassName = className;
      runtime.mArgC = argc - i;
      runtime.mArgV = argv + i;
      //加載RuntimeInit類到虛擬機中
      runtime.start("com.android.internal.os.RuntimeInit",
              application ? "application" : "tool");
  } else {
      app_usage();
      return 10;
  }
}
  • 入參爲“–zygote –start-system-server”,通過調用runtime.start創建和生成Dalvik虛擬機,並加載ZygoteInit類到虛擬機中。
  • 加載ZygoteInit類,調用其main方法,啓動SystemServer。

2.2、main | ZygoteInit.java

public static void main(String argv[]) {
   try {
      //註冊server socket
      //其它進程的創建,通過連接到該Socket後,由zygote孵化
      registerZygoteSocket();

      ...
      //預加載android framework類和資源
      preload();

      ...
      if (argv[1].equals("start-system-server")) {
          //啓動SystemServer
          startSystemServer();
      } else if (!argv[1].equals("")) {
          throw new RuntimeException(argv[0] + USAGE_STRING);
      }

      //死循環接收client socket連接,由此創建新進程
      runSelectLoop();

      closeServerSocket();
  } catch (MethodAndArgsCaller caller) {
      caller.run();
  } catch (RuntimeException ex) {
      closeServerSocket();
      throw ex;
  }
}
  • 入參爲”start-system-server”,Zygote進程調用 startSystemServer()方法啓動SystemServer。

2.3、startSystemServer

startSystemServer方法在ZygoteInit.java中,看方法名是要啓動SystemServer進程了。

private static boolean startSystemServer()
        throws MethodAndArgsCaller, RuntimeException {
   ...
    //啓動systemServer的參數
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "-- setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
        "--capabilities=" + capabilities + "," + capabilities,
        "--runtime-init",
        "--nice-name=system_server",
        //啓動的SystemServer全限定名,後續根據該參數反射創建實例
        "com.android.server.SystemServer",
    };
    ZygoteConnection.Arguments parsedArgs = null;

    int pid;
    try {
        /**
         * 將傳入參數進行轉換
         * 注意:參數com.android.server.SystemServer 放在parsedArgs中的remainingArgs裏
         */
        parsedArgs = new ZygoteConnection.Arguments(args);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        //Zygote爲SystemServer創建子進程
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }

    //子進程執行
    if (pid == 0) {
        handleSystemServerProcess(parsedArgs);
    }
    return true;
}
  • Zygote爲SystemServer創建新進程,並在新進程中調用handleSystemServerProcess。

SystemServer進程


上一步中調用了handleSystemServerProcess方法。

3.1、handleSystemServerProcess

該方法在ZygoteInit.java文件中

private static void handleSystemServerProcess(
        ZygoteConnection.Arguments parsedArgs)
        throws ZygoteInit.MethodAndArgsCaller {

    //關閉SystemServer進程的serversocket
    //SystemServer進程基礎了父進程zygote所有資源
    closeServerSocket();

    //設置文件權限
    Libcore.os.umask(S_IRWXG | S_IRWXO);

    //設置新進程名
    if (parsedArgs.niceName != null) {
        Process.setArgV0(parsedArgs.niceName);
    }

    if (parsedArgs.invokeWith != null) {
        WrapperInit.execApplication(parsedArgs.invokeWith,
                parsedArgs.niceName, parsedArgs.targetSdkVersion,
                null, parsedArgs.remainingArgs);
    } else {
        //remainArgs中包含SystemServer的全限定名:com.android.server.SystemServer     
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
    }
}
  • 新進程中接着調用RuntimeInit.zygoteInit方法

3.2、RuntimeInit.zygoteInit

RuntimeInit.zygoteInit爲靜態方法,在RuntimeInit.java文件中。

public static final void zygoteInit(int targetSdkVersion, String[] argv)
        throws ZygoteInit.MethodAndArgsCaller {
    if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

    redirectLogStreams();

    commonInit();
    nativeZygoteInit();

    //調用該方法,往下執行
    applicationInit(targetSdkVersion, argv);
}

3.3、applicationInit

上方法接着調用了applicationInit方法,該方法在RuntimeInit.java文件中。

private static void applicationInit(int targetSdkVersion, String[] argv)
        throws ZygoteInit.MethodAndArgsCaller {
    //應用調用System.exit(),退出進程
    nativeSetExitWithoutCleanup(true);

    //設置堆
    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());
        return;
    }

    //創建args.startClass實例,並調用其main方法
    invokeStaticMain(args.startClass, args.startArgs);
}
  • 該方法接着調用invokeStaticMain方法,注意:此處args.startClass爲com.android.server.SystemServer

3.4、invokeStaticMain

上方法接着調用了invokeStaticMain方法,該方同樣在RuntimeInit.java中。看方法名,似乎是反射調用main方法。

private static void invokeStaticMain(String className, String[] argv)
        throws ZygoteInit.MethodAndArgsCaller {
    Class<?> cl;
    try {
        //全限定名,此處傳入爲"com.android.server.SystemServer"
        cl = Class.forName(className);
    }
    ...

    Method m;
    try {
        //main方法
        m = cl.getMethod("main", new Class[] { String[].class });
    }
    ...

    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()中被捕獲,
     * 捕獲後會觸發MethodAndArgsCaller的run()方法,
     * run方法中完成類main方法的調用
     */
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
  • 該方法最後通過拋異常的方式,拋出異常MethodAndArgsCaller;該異常被Zygote捕獲,捕獲後調用該異常的run方法,而在run放中完成類main方法的調用。
  • 因此,該步最後調用SystemServer的main方法。

3.5、main | SystemServer.java

終於調用SystemServer的main方法了,看下其java層代碼主要幹啥了。

public static void main(String[] args) {
    ...
    //SystemServer需要一直運行,因此它需要有效的利用內存
    VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

    Environment.setUserRequired(true);
    System.loadLibrary("android_servers");

    //初始化native服務
    nativeInit();

    //ServerThread並非Thread,它只是運行在SystemServer進程的主線程中
    ServerThread thr = new ServerThread();
    //調用該方法初始化和循環處理
    thr.initAndLoop();
}

3.6、initAndLoop

上面方法的主要內容在initAndLoop方法中,該方法是SystemServer的內部類ServerThread的方法。

public void initAndLoop() {
    ...
    //main looper
    Looper.prepareMainLooper();
    ...

    try {
        //啓動DisplayManagerService服務,並註冊到ServiceManager
        display = new DisplayManagerService(context, wmHandler);
        ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);

        //啓動TelephonyRegistry服務,並註冊到ServiceManager
        telephonyRegistry = new TelephonyRegistry(context);
        ServiceManager.addService("telephony.registry", telephonyRegistry);

        //啓動其它服務,並註冊到ServiceManager
        ...

        //啓動ActivityManagerService
        ActivityManagerService.setSystemProcess();

        //啓動其它服務,並註冊到ServiceManager
        ...

    //調用ActivityManagerService的systemReady方法,啓動Launcher
    ActivityManagerService.self().systemReady(new Runnable() {
        public void run() {
            ... 
            //開始系統啓動畫面
            if (!headless) {
                startSystemUi(contextF);
            }
           ...
    });

    //不停的從消息隊列中獲取消息
    Looper.loop();
}
  • initAndLoop方法中,SystemServer主要負責啓動各種服務,並將啓動的服務註冊到ServiceManager中。
  • 上方法中注意ActivityManagerService的啓動,可知:
    • AMS在SystemServier進程中運行;
    • SystemServer調用AMS的systemReady方法來啓動系統UI了;

插話

上面講完SystemServer進程創建後,下一部分就是應用進程創建了,這部分內容在後面文章展開,這裏貼副圖簡單描述下Zygote是如何創建應用進程的。改圖以Zygote創建Launcher進程爲例:


zygote創建應用進程.png

總結


回顧整篇內容,可以用下圖做個簡單描述:

總結.png

本文從init進程啓動出發,沿着zygote進程、SystemServer進程創建流程分析了Android系統啓動,其中內容無非是這麼幾點:

  • init進程創建了Zygote進程
  • Zygote進程孵化創建了SystemServer進程
  • SystemServer進程啓動了Android常見的系統服務,如AMS、PMS等。及SystemServer可理解爲應用與之交互的遠程服務端。
  • 已知Android的每個進程都與一個VM關聯,上面代碼未展開描述,但可概括爲:VM由Zygote創建,Zygote每創建一個進程,就爲爲該進程拷貝一份VM實例,從而實現關聯。

在後面的兩篇文章中,會從Activity啓動角度出發,分析Zygote是如何創建應用進程,以及ActivityThread有如何使主線程等問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章