Android之 系统启动流程

时间:2022-02-18 16:47:11

 

在前一篇文章"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()的源码如下:

Android之 系统启动流程Android之 系统启动流程
  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()源码如下:

Android之 系统启动流程Android之 系统启动流程
 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中,源码如下:

Android之 系统启动流程Android之 系统启动流程
 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了!