Android之 系統啟動流程


 

在前一篇文章"Android之 看“馬達”如何貫通Android系統 (從硬件設計 --> 驅動 --> HAL --> JNI --> Framework --> Application)"中,我們談到“馬達等系統服務都是通過SystemServer啟動/管理的”。本章,我們就Android的系統啟動流程進行分析;也說說SystemServer到底是如何工作的。

轉載請注明出處:http://www.cnblogs.com/skywang12345/p/3405100.html

在詳細說明之后,我們先建立個整體思路:
Kernel中啟動的第一個用戶進程是init程序;而init會通過解析init.rc來啟動zygote服務;而zygote又會進一步的啟動SystemServer。在SystemServer中,Android會啟動一系列的系統服務共用戶調用。整個流程大致如此。下面,我們通過源碼來查看一下各個環節到底是如何運作的。


1. kernel啟動init服務

在Linux的內核init/main.c中,啟動的/init程序。源碼如下:

 1 static int __init kernel_init(void * unused)
 2 {
 3 
 4     ...
 5         
 6     // “設置第一個運行程序是/init”
 7     if (!ramdisk_execute_command)
 8         ramdisk_execute_command = "/init";
 9 
10         ...
11 
12     init_post();
13     return 0;
14 }
15 
16 
17 static noinline int init_post(void)
18     __releases(kernel_lock)
19 {
20 
21     ...
22     // 運行"/init"程序
23     if (ramdisk_execute_command) {
24         run_init_process(ramdisk_execute_command);
25         printk(KERN_WARNING "Failed to execute %s\n",
26                 ramdisk_execute_command);
27     }
28 
29     ...
30 
31     run_init_process("/sbin/init");
32     run_init_process("/etc/init");
33     run_init_process("/bin/init");
34     run_init_process("/bin/sh");
35 
36     ...
37 }

從中,我們發現:kernel_init()中會將ramdisk_execute_command的值初始化為"/init",進而在init_post()中調用run_init_process(),從而執行"/init"程序。
我們所說的kernel內核空間到用戶空間啟動的第一個init程序,實際上就是"/init"程序。

 

2. init服務的定義

2.1 init的配置文件

Android系統中init程序對應的Android.mk所在路徑:system/core/init/Android.mk。內容如下: 

 1 LOCAL_PATH:= $(call my-dir)
 2 include $(CLEAR_VARS)
 3 
 4 LOCAL_SRC_FILES:= \
 5     builtins.c \
 6     init.c \
 7     devices.c \
 8     property_service.c \
 9     util.c \
10     parser.c \
11     logo.c \
12     keychords.c \
13     signal_handler.c \
14     init_parser.c \
15     ueventd.c \
16     ueventd_parser.c \
17     watchdogd.c
18 
19 LOCAL_MODULE:= init
20 
21 include $(BUILD_EXECUTABLE)
22 
23 ...

說明: 在“完整的編譯Android系統” 或 “對init執行模塊編譯(即$ mmm system/core/init)”的時候,會在system下生產文件out/.../root/init。"/root/init"意味着init在rootfs文件系統下,而不是system文件系統下。這也意味着,init會被解壓到系統的根目錄,即對應/init文件!

 

2.2 init的程序入口

init程序的入口函數main()定義在system/core/init/init.c中,源碼如下:

 1 int main(int argc, char **argv)
 2 {
 3 
 4     ...
 5 
 6     // 創建目錄
 7     mkdir("/dev", 0755);
 8     mkdir("/proc", 0755);
 9     mkdir("/sys", 0755);
10 
11     mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
12     mkdir("/dev/pts", 0755);
13     mkdir("/dev/socket", 0755);
14     mount("devpts", "/dev/pts", "devpts", 0, NULL);
15     mount("proc", "/proc", "proc", 0, NULL);
16     mount("sysfs", "/sys", "sysfs", 0, NULL);
17 
18     ...
19 
20     init_parse_config_file("/init.rc");
21 
22     ...
23 }

說明在init程序中,我們會進行一些列的初始化,包括創建目錄,解析"init.rc"文件,啟動相應的系統服務和守護進程等。zygote服務定義在init.rc中,它是在init中啟動的。

 

3. init啟動解析init.rc,並啟動zygote

init.rc的路徑:system/core/rootdir/init.rc。zygote在init.rc中的定義如下:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

從中,我們知道:zygote是service名稱,而/system/bin/app_process是zygote對應的進程。后面的內容是service的參數。

 

4. zygote服務

4.1 zygote服務的配置文件

通過init.rc中zygote的定義,我們知道zygote對應是通過/system/bin/app_process是啟動的。app_process對應的Android.mk的路徑:frameworks/base/cmds/app_process/Android.mk。它的內容如下:

 1 LOCAL_PATH:= $(call my-dir)
 2 include $(CLEAR_VARS)
 3 
 4 LOCAL_SRC_FILES:= \
 5     app_main.cpp
 6 
 7 LOCAL_SHARED_LIBRARIES := \
 8     libcutils \
 9     libutils \
10     libbinder \
11     libandroid_runtime
12 
13 LOCAL_MODULE:= app_process
14 
15 include $(BUILD_EXECUTABLE)

從中,我們知道/system/bin/app_process會執行app_main.cpp。

 

4.2 zygote對應的程序app_main.app

app_main.cpp的入口main()源碼如下:

 1 int main(int argc, const char* const argv[])
 2 {
 3     // These are global variables in ProcessState.cpp
 4     mArgC = argc;
 5     mArgV = argv;
 6 
 7     mArgLen = 0;
 8     for (int i=0; i<argc; i++) {
 9         mArgLen += strlen(argv[i]) + 1;
10     }
11     mArgLen--;
12 
13     AppRuntime runtime;
14     const char* argv0 = argv[0];
15 
16     // Process command line arguments
17     // ignore argv[0]
18     argc--;
19     argv++;
20 
21     // Everything up to '--' or first non '-' arg goes to the vm
22 
23     int i = runtime.addVmArguments(argc, argv);
24 
25     // Parse runtime arguments.  Stop at first unrecognized option.
26     bool zygote = false;
27     bool startSystemServer = false;
28     bool application = false;
29     const char* parentDir = NULL;
30     const char* niceName = NULL;
31     const char* className = NULL;
32     // 解析參數
33     while (i < argc) {
34         const char* arg = argv[i++];
35         if (!parentDir) {
36             parentDir = arg;
37         } else if (strcmp(arg, "--zygote") == 0) {
38             // 設置zygote為true
39             zygote = true;
40             niceName = "zygote";
41         } else if (strcmp(arg, "--start-system-server") == 0) {
42             // 設置startSystemServer為true
43             startSystemServer = true;
44         } else if (strcmp(arg, "--application") == 0) {
45             application = true;
46         } else if (strncmp(arg, "--nice-name=", 12) == 0) {
47             niceName = arg + 12;
48         } else {
49             className = arg;
50             break;
51         }
52     }
53 
54     if (niceName && *niceName) {
55         setArgv0(argv0, niceName);
56         set_process_name(niceName);
57     }
58 
59     runtime.mParentDir = parentDir;
60 
61     if (zygote) {
62         // 啟動"com.android.internal.os.ZygoteInit"
63         runtime.start("com.android.internal.os.ZygoteInit",
64                 startSystemServer ? "start-system-server" : "");
65     } else if (className) {
66         // Remainder of args get passed to startup class main()
67         runtime.mClassName = className;
68         runtime.mArgC = argc - i;
69         runtime.mArgV = argv + i;
70         runtime.start("com.android.internal.os.RuntimeInit",
71                 application ? "application" : "tool");
72     } else {
73         fprintf(stderr, "Error: no class name or --zygote supplied.\n");
74         app_usage();
75         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
76         return 10;
77     }
78 }

從中,我們可以知道main()最終會調用以下代碼:

runtime.start("com.android.internal.os.ZygoteInit",
        startSystemServer ? "start-system-server" : "");

我們接着看start()的代碼。start()的源碼定義在frameworks/base/core/jni/AndroidRuntime.cpp中。

runtime是AppRuntime成員。AppRuntime定義在app_main.cpp中,聲明如下:

class AppRuntime : public AndroidRuntime {
  ...
}

顯然AppRuntime繼承於AndroidRuntime。

 

4. AndroidRuntime.cpp

start()的源碼如下:

  1 void AndroidRuntime::start(const char* className, const char* options)
  2 {
  3     ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
  4             className != NULL ? className : "(unknown)");
  5 
  6     blockSigpipe();
  7 
  8     /*
  9      * 'startSystemServer == true' means runtime is obsolete and not run from
 10      * init.rc anymore, so we print out the boot start event here.
 11      */
 12     if (strcmp(options, "start-system-server") == 0) {
 13         /* track our progress through the boot sequence */
 14         const int LOG_BOOT_PROGRESS_START = 3000;
 15         LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
 16                        ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
 17     }
 18 
 19     const char* rootDir = getenv("ANDROID_ROOT");
 20     if (rootDir == NULL) {
 21         rootDir = "/system";
 22         if (!hasDir("/system")) {
 23             LOG_FATAL("No root directory specified, and /android does not exist.");
 24             return;
 25         }
 26         setenv("ANDROID_ROOT", rootDir, 1);
 27     }
 28 
 29     //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
 30     //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
 31 
 32     /* start the virtual machine */
 33     JNIEnv* env;
 34     if (startVm(&mJavaVM, &env) != 0) {
 35         return;
 36     }
 37     onVmCreated(env);
 38 
 39     /*
 40      * Register android functions.
 41      */
 42     if (startReg(env) < 0) {
 43         ALOGE("Unable to register all android natives\n");
 44         return;
 45     }
 46 
 47     /*
 48      * We want to call main() with a String array with arguments in it.
 49      * At present we have two arguments, the class name and an option string.
 50      * Create an array to hold them.
 51      */
 52     jclass stringClass;
 53     jobjectArray strArray;
 54     jstring classNameStr;
 55     jstring optionsStr;
 56 
 57     stringClass = env->FindClass("java/lang/String");
 58     assert(stringClass != NULL);
 59     strArray = env->NewObjectArray(2, stringClass, NULL);
 60     assert(strArray != NULL);
 61     classNameStr = env->NewStringUTF(className);
 62     assert(classNameStr != NULL);
 63     env->SetObjectArrayElement(strArray, 0, classNameStr);
 64     optionsStr = env->NewStringUTF(options);
 65     env->SetObjectArrayElement(strArray, 1, optionsStr);
 66 
 67     /*
 68      * Start VM.  This thread becomes the main thread of the VM, and will
 69      * not return until the VM exits.
 70      */
 71     // 將"com.android.internal.os.ZygoteInit"轉換為"com/android/internal/os/ZygoteInit"
 72     char* slashClassName = toSlashClassName(className);
 73     // 獲取"com/android/internal/os/ZygoteInit"對應的class對象
 74     jclass startClass = env->FindClass(slashClassName);
 75     if (startClass == NULL) {
 76         ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
 77         /* keep going */
 78     } else {
 79         // 找到"com/android/internal/os/ZygoteInit"中main()方法的methodID
 80         jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
 81             "([Ljava/lang/String;)V");
 82         if (startMeth == NULL) {
 83             ALOGE("JavaVM unable to find main() in '%s'\n", className);
 84             /* keep going */
 85         } else {
 86             // 執行"com/android/internal/os/ZygoteInit"中main()方法
 87             env->CallStaticVoidMethod(startClass, startMeth, strArray);
 88 
 89 #if 0
 90             if (env->ExceptionCheck())
 91                 threadExitUncaughtException(env);
 92 #endif
 93         }
 94     }
 95     free(slashClassName);
 96 
 97     ALOGD("Shutting down VM\n");
 98     if (mJavaVM->DetachCurrentThread() != JNI_OK)
 99         ALOGW("Warning: unable to detach main thread\n");
100     if (mJavaVM->DestroyJavaVM() != 0)
101         ALOGW("Warning: VM did not shut down cleanly\n");
102 }
View Code

說明start()是通過JNI回調java層的方法,它主要的目的是執行"com/android/internal/os/ZygoteInit"中main()方法,即frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中的main()函數。

 

5. ZygoteInit.java

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中的main()源碼如下:

 1 public static void main(String argv[]) {
 2     try {
 3         // Start profiling the zygote initialization.
 4         SamplingProfilerIntegration.start();
 5 
 6         registerZygoteSocket();
 7         EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
 8             SystemClock.uptimeMillis());
 9         preload();
10         EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
11             SystemClock.uptimeMillis());
12 
13         // Finish profiling the zygote initialization.
14         SamplingProfilerIntegration.writeZygoteSnapshot();
15 
16         // Do an initial gc to clean up after startup
17         gc();
18 
19         // If requested, start system server directly from Zygote
20         if (argv.length != 2) {
21             throw new RuntimeException(argv[0] + USAGE_STRING);
22         }
23 
24         if (argv[1].equals("start-system-server")) {
25             // 調用startSystemServer()
26             startSystemServer();
27         } else if (!argv[1].equals("")) {
28             throw new RuntimeException(argv[0] + USAGE_STRING);
29         }
30 
31         Log.i(TAG, "Accepting command socket connections");
32 
33         if (ZYGOTE_FORK_MODE) {
34             runForkMode();
35         } else {
36             runSelectLoopMode();
37         }
38 
39         closeServerSocket();
40     } catch (MethodAndArgsCaller caller) {
41         caller.run();
42     } catch (RuntimeException ex) {
43         Log.e(TAG, "Zygote died with exception", ex);
44         closeServerSocket();
45         throw ex;
46     }
47 }
View Code

說明:main()會執行startSystemServer()來啟動系統服務。

startSystemServer()也是定義在ZygoteInit.java中,源碼如下:

 1 private static boolean startSystemServer()
 2         throws MethodAndArgsCaller, RuntimeException {
 3     /* Hardcoded command line to start the system server */
 4     String args[] = {
 5         "--setuid=1000",
 6         "--setgid=1000",
 7         "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
 8         "--capabilities=130104352,130104352",
 9         "--runtime-init",
10         "--nice-name=system_server",
11         "com.android.server.SystemServer",
12     };
13     ZygoteConnection.Arguments parsedArgs = null;
14 
15     int pid;
16 
17     try {
18         parsedArgs = new ZygoteConnection.Arguments(args);
19         ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
20         ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
21 
22         /* Request to fork the system server process */
23         pid = Zygote.forkSystemServer(
24                 parsedArgs.uid, parsedArgs.gid,
25                 parsedArgs.gids,
26                 parsedArgs.debugFlags,
27                 null,
28                 parsedArgs.permittedCapabilities,
29                 parsedArgs.effectiveCapabilities);
30     } catch (IllegalArgumentException ex) {
31         throw new RuntimeException(ex);
32     }
33 
34     /* For child process */
35     if (pid == 0) {
36         handleSystemServerProcess(parsedArgs);
37     }
38 
39     return true;
40 }

說明
     startSystemServer()會通過Zygote.forkSystemServer()函數來創建一個新的進程來啟動SystemServer組件,返回值pid等0的地方就是新的進程要執行的路徑,即新創建的進程會執行handleSystemServerProcess()函數。 

handleSystemServerProcess()也是定義在ZygoteInit.java中,源碼如下:

 1 private static void handleSystemServerProcess(
 2         ZygoteConnection.Arguments parsedArgs)
 3         throws ZygoteInit.MethodAndArgsCaller {
 4 
 5     closeServerSocket();
 6 
 7     // set umask to 0077 so new files and directories will default to owner-only permissions.
 8     Libcore.os.umask(S_IRWXG | S_IRWXO);
 9 
10     if (parsedArgs.niceName != null) {
11         Process.setArgV0(parsedArgs.niceName);
12     }
13 
14     if (parsedArgs.invokeWith != null) {
15         WrapperInit.execApplication(parsedArgs.invokeWith,
16                 parsedArgs.niceName, parsedArgs.targetSdkVersion,
17                 null, parsedArgs.remainingArgs);
18     } else {
19         /*
20          * Pass the remaining arguments to SystemServer.
21          */
22         RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
23     }
24 
25     /* should never reach here */
26 }
View Code

說明handleSystemServerProcess()會調用 RuntimeInit.zygoteInit()器初始化zygote。

 

6. RuntimeInit.java

zygoteInit()定義在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java中,源碼如下:

 1 public static final void zygoteInit(int targetSdkVersion, String[] argv)
 2         throws ZygoteInit.MethodAndArgsCaller {
 3     if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
 4 
 5     redirectLogStreams();
 6 
 7     commonInit();
 8     nativeZygoteInit();
 9 
10     // 通過applicationInit()啟動SystemServer
11     applicationInit(targetSdkVersion, argv);
12 }

說明:zygoteInit()會調用applicationInit()函數初始化應用程序SystemServer。

 

applicationInit()也定義在RuntimeInit.java中,源碼如下:

 1 private static void applicationInit(int targetSdkVersion, String[] argv)
 2         throws ZygoteInit.MethodAndArgsCaller {
 3     nativeSetExitWithoutCleanup(true);
 4 
 5     VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
 6     VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
 7 
 8     final Arguments args;
 9     try {
10         args = new Arguments(argv);
11     } catch (IllegalArgumentException ex) {
12         Slog.e(TAG, ex.getMessage());
13         // let the process exit
14         return;
15     }
16 
17     // invokeStaticMain()會執行SystemServer的main()方法。
18     invokeStaticMain(args.startClass, args.startArgs);
19 }

說明:applicationInit()會調用invokeStaticMain()來執行SystemServer的main()方法。

 

invokeStaticMain()也定義在RuntimeInit.java中,源碼如下:

 1 private static void invokeStaticMain(String className, String[] argv)
 2         throws ZygoteInit.MethodAndArgsCaller {
 3     Class<?> cl;
 4 
 5     try {
 6         // 根據“反射”查找SystemServer對應的Class
 7         cl = Class.forName(className);
 8     } catch (ClassNotFoundException ex) {
 9         throw new RuntimeException(
10                 "Missing class when invoking static main " + className,
11                 ex);
12     }
13 
14     Method m;
15     try {
16         // 獲取SystemServer對應的main()方法
17         m = cl.getMethod("main", new Class[] { String[].class });
18     } catch (NoSuchMethodException ex) {
19         throw new RuntimeException(
20                 "Missing static main on " + className, ex);
21     } catch (SecurityException ex) {
22         throw new RuntimeException(
23                 "Problem getting static main on " + className, ex);
24     }
25 
26     int modifiers = m.getModifiers();
27     if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
28         throw new RuntimeException(
29                 "Main method is not public and static on " + className);
30     }
31 
32     // 通過ZygoteInit.MethodAndArgsCaller()執行該main()方法
33     throw new ZygoteInit.MethodAndArgsCaller(m, argv);
34 }

說明
    首先,我們要搞清楚invokeStaticMain()的輸入參數className,實際上它的值是"com.android.server.SystemServer"。
              我們看從startSystemServer()方法中的args成員開始查看,在args通過ZygoteConnection.Arguments(args)解析之后得到parsedArgs對象;其中,parsedArgs.remainingArgs就是"com.android.server.SystemServer"。。
    接着,parseArgs傳遞給handleSystemServerProcess();
   再接着,將parsedArgs.remainingArgs,也就是"com.android.server.SystemServer"傳遞給了RuntimeInit.zygoteInit()。

 

7. ZygoteInit.MethodAndArgsCaller

MethodAndArgsCaller是一個實現了Runnable的類,它定義在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中。源碼如下:

 1 public static class MethodAndArgsCaller extends Exception
 2         implements Runnable {
 3     private final Method mMethod;
 4 
 5     private final String[] mArgs;
 6 
 7     public MethodAndArgsCaller(Method method, String[] args) {
 8         mMethod = method;
 9         mArgs = args;
10     }
11 
12     public void run() {
13         try {
14             // 通過反射,執行方法mMethod
15             mMethod.invoke(null, new Object[] { mArgs });
16         } catch (IllegalAccessException ex) {
17             throw new RuntimeException(ex);
18         } catch (InvocationTargetException ex) {
19             Throwable cause = ex.getCause();
20             if (cause instanceof RuntimeException) {
21                 throw (RuntimeException) cause;
22             } else if (cause instanceof Error) {
23                 throw (Error) cause;
24             }
25             throw new RuntimeException(ex);
26         }
27     }
28 }

說明:MethodAndArgsCaller()是個線程,它會執行方法mMethod。也就是執行"com.android.server.SystemServer"中的main()方法。
至此,我們就啟動了SystemServer了!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM