在前一篇文章"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

相关文章:

  • 2022-12-23
  • 2021-09-19
  • 2021-09-09
  • 2022-12-23
  • 2021-07-04
  • 2021-12-27
猜你喜欢
  • 2021-12-10
  • 2021-11-24
相关资源
相似解决方案