结合源码探讨Android系统的启动流程

由于本人能力有限,所考虑或者疏忽错漏的地方或多或少应该存在。同时,Android从启动过程开始,实际上就涉及多个技术难点和多种通信机制的知识点。

基于上面两个原因,笔者会一直修改,补充,拓展此文。希望能够坚持下去,从而真正达到触类旁通。

从我们长按手机电源键,到安卓系统完全启动之间,总共经历了以下五个阶段。

第一步:启动电源以及系统启动

当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后执行。

第二步:引导程序

引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方。

引导程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。

第三步:内核的启动

Android内核与桌面Linux内核启动的方式差不多。内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动init进程。

第四步:init进程的启动

init是第一个进程,我们可以说它是root进程或者说有进程的父进程。init进程将进行两个主要操作,一是挂载目录,比如/sys、/dev、/proc,二是运行init.rc脚本。

其实第一步到第三步,可以理解为是一个Linux内核的启动的过程。从第四步开始,Android系统才可以算作是“真正”的开始启动。这也是本文所关注的重点起始的地方。先从init.rc脚本开始讲起。

.rc文件是安卓初始化语言,有特定的格式以及规则。例如:

[java] view plaincopy
  1. service <name><pathname> [<argument>]*
  2. <option>
  3. <option>
  4. ...

如上所示,这个语法代表的是启动一个指定路径的服务。

在init.rc这个配置文件中,涉及到两个最关键的步骤:

(init.rc文件既可在源码目录/system/core/rootdir,也可在设备根目录下找到)

1.启动ServiceManager进程

[java] view plaincopy
  1. service servicemanager /system/bin/servicemanager

ServiceManager是Binder的服务管理守护进程,是Binder的核心,由其使用Binder驱动进行IPC管理,关于IPC通讯 的机制,此处暂不详述。在APP和Framework中,应用程序使用的ServiceManager.Java就是通过Proxy与这个守护进程进行的 通讯。

2. 启动Zygote进程,Zygote的中文翻译是受精卵或孵化器,顾名思义,从它开始将会衍生出Android系统中的各种子进程。

[python] view plaincopy
  1. service zygote /system/bin/app_process -Xzygote/system/bin --zygote --start-system-server

第五阶段:Zygote进程加载SystemServer进程,并启动系统服务

如果在init.rc文件中找不到这一语句,我们可以关注下init.rc文件开头的几行import代码。

[python] view plaincopy
  1. import/init.environ.rc
  2. import /init.usb.rc
  3. import /init.${ro.hardware}.rc
  4. import /init.${ro.zygote}.rc  //在同一目录下,可以找到类似于init.zygote32.rc的文件
  5. //不同名字的zygote进程启动文件对应于不同位数的设备
  6. import /init.trace.rc

随便打开一个init.zygote32.rc文件,即可找到此语句

在这个步骤中,将启动zygote服务进程。Zygote进程将成为所有应用进程的孵化器。

我们来看一下app_process的代码,位置是在:

frameworks/base/cmds/app_process/app_main.cpp

C++文件的执行入口总在main()函数当中——其入口函数main在文件app_main.cpp中,接下来我们就从这个main函数入手来分析zygote的内部逻辑。

/*启动zygote的方式为service zygote /system/bin/app_process-Xzygote /system/bin --zygote --start-system-server

* 所以 argc == 5, argv中存的就是这5个参数argv[0]=="/system/bin/app_process" ,argv[1]== "-Xzygote"....

*/

[cpp] view plaincopy
  1. int main(int argc, char* const argv[])
  2. {
  3. if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
  4. // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
  5. // EINVAL. Don't die on such kernels.
  6. if (errno != EINVAL) {
  7. LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
  8. return 12;
  9. }
  10. }
  11. AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
  12. // Process command line arguments
  13. // ignore argv[0]
  14. argc--;
  15. argv++;
  16. // Everything up to '--' or first non '-' arg goes to the vm.
  17. //
  18. // The first argument after the VM args is the "parent dir", which
  19. // is currently unused.
  20. //
  21. // After the parent dir, we expect one or more the following internal
  22. // arguments :
  23. //
  24. // --zygote : Start in zygote mode
  25. // --start-system-server : Start the system server.
  26. // --application : Start in application (stand alone, non zygote) mode.
  27. // --nice-name : The nice name for this process.
  28. //
  29. // For non zygote starts, these arguments will be followed by
  30. // the main class name. All remaining arguments are passed to
  31. // the main method of this class.
  32. //
  33. // For zygote starts, all remaining arguments are passed to the zygote.
  34. // main function.
  35. //
  36. // Note that we must copy argument string values since we will rewrite the
  37. // entire argument block when we apply the nice name to argv0.
  38. int i;
  39. for (i = 0; i < argc; i++) {
  40. if (argv[i][0] != '-') {
  41. break;
  42. }
  43. if (argv[i][1] == '-' && argv[i][2] == 0) {
  44. ++i; // Skip --.
  45. break;
  46. }
  47. runtime.addOption(strdup(argv[i]));
  48. }
  49. // Parse runtime arguments.  Stop at first unrecognized option.
  50. bool zygote = false;
  51. bool startSystemServer = false;
  52. bool application = false;
  53. String8 niceName;
  54. String8 className;
  55. ++i;  // Skip unused "parent dir" argument.
  56. while (i < argc) {
  57. const char* arg = argv[i++];
  58. if (strcmp(arg, "--zygote") == 0) { //将会走这个分支
  59. zygote = true;
  60. niceName = ZYGOTE_NICE_NAME;
  61. } else if (strcmp(arg, "--start-system-server") == 0) { //将会走这个分支
  62. startSystemServer = true;
  63. } else if (strcmp(arg, "--application") == 0) {
  64. application = true;
  65. } else if (strncmp(arg, "--nice-name=", 12) == 0) {
  66. niceName.setTo(arg + 12);
  67. } else if (strncmp(arg, "--", 2) != 0) { //启动zygote中的参数都不会走到这个分支,仔细思考下就知道是因为所有带"--"的参数都会先被前面的if判断分支截获
  68. className.setTo(arg);
  69. break;
  70. } else {
  71. --i;
  72. break;
  73. }
  74. }
  75. //经历了上面的while循环后,总结下变量的赋值和变化情况:
  76. //boolean zygote 变为true
  77. //boolean startSystemServer变为true
  78. //boolean application依然为false
  79. //字符串变量niceName和className为Null
  80. //在这个基础上分析下面的流程就很容易了
  81. Vector<String8> args;  //重点关注下这个变量,它将作为接下来调用runtime.start()方法的传入参数
  82. if (!className.isEmpty()) {
  83. // We're not in zygote mode, the only argument we need to pass
  84. // to RuntimeInit is the application argument.
  85. //
  86. // The Remainder of args get passed to startup class main(). Make
  87. // copies of them before we overwrite them with the process name.
  88. args.add(application ? String8("application") : String8("tool"));
  89. runtime.setClassNameAndArgs(className, argc - i, argv + i);
  90. } else {
  91. // We're in zygote mode.
  92. maybeCreateDalvikCache();
  93. if (startSystemServer) {
  94. args.add(String8("start-system-server")); //args中添加的第一个变量
  95. }
  96. char prop[PROP_VALUE_MAX];
  97. if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
  98. LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
  99. ABI_LIST_PROPERTY);
  100. return 11;
  101. }
  102. String8 abiFlag("--abi-list=");
  103. abiFlag.append(prop);
  104. args.add(abiFlag); //args中添加的第二个变量
  105. // In zygote mode, pass all remaining arguments to the zygote
  106. // main() method.
  107. for (; i < argc; ++i) {
  108. args.add(String8(argv[i]));
  109. }
  110. }
  111. if (!niceName.isEmpty()) {
  112. runtime.setArgv0(niceName.string());
  113. set_process_name(niceName.string());
  114. }
  115. if (zygote) {
  116. runtime.start("com.android.internal.os.ZygoteInit", args); //zygote为true
  117. } else if (className) {
  118. runtime.start("com.android.internal.os.RuntimeInit", args);
  119. } else {
  120. fprintf(stderr, "Error: no class name or --zygote supplied.\n");
  121. app_usage();
  122. LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
  123. return 10;
  124. }
  125. }

在执行到app_process/app_main.cpp这个文件的最后,将会调用runtime.start("com.android.internal.os.ZygoteInit",args); 这个语句runtime是一个AppRuntime变量,其定义同样在/frameworks/base/cmds/app_process/app_main.cpp这个文件当中。

[cpp] view plaincopy
  1. class AppRuntime : public AndroidRuntime
  2. ......
  3. ;

可以发现其继承于AndroidRuntime类。AndroidRuntime类定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中。

runtime.start方法调用的正是其父类AndroidRuntime.cpp中的start方法。

AndroidRuntime.start()方法代码如下:

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

这个方法,除去一些系统启动过程中的出错处理和相关信息排查操作,总体逻辑还是比较清晰的。关注几个关键的步骤可以知道,这个方法完成了三个最重要的责任:

关键步骤1——调用函数startVM,启动虚拟机

关键步骤2——调用函数startReg注册JNI方法,以完成安卓上层和native层的交互

关键步骤3——找到className为” com.android.internal.os.ZygoteInit”的类,并调用其main方法

接着前行,步骤3中涉及到这个类定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中。找到其函数入口main方法:

[java] view plaincopy
  1. public static void main(String argv[]) {
  2. try {
  3. // Start profiling the zygote initialization.
  4. SamplingProfilerIntegration.start();
  5. boolean startSystemServer = false;
  6. String socketName = "zygote";
  7. String abiList = null;
  8. for (int i = 1; i < argv.length; i++) {
  9. if ("start-system-server".equals(argv[i])) {
  10. startSystemServer = true;
  11. } else if (argv[i].startsWith(ABI_LIST_ARG)) {
  12. abiList = argv[i].substring(ABI_LIST_ARG.length());
  13. } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
  14. socketName = argv[i].substring(SOCKET_NAME_ARG.length());
  15. } else {
  16. throw new RuntimeException("Unknown command line argument: " + argv[i]);
  17. }
  18. }
  19. if (abiList == null) {
  20. throw new RuntimeException("No ABI list supplied.");
  21. }
  22. registerZygoteSocket(socketName); //关键步骤1,注册Zygote进程的套接字
  23. EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
  24. SystemClock.uptimeMillis());
  25. preload();
  26. EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
  27. SystemClock.uptimeMillis());
  28. // Finish profiling the zygote initialization.
  29. SamplingProfilerIntegration.writeZygoteSnapshot();
  30. // Do an initial gc to clean up after startup
  31. gc();
  32. // Disable tracing so that forked processes do not inherit stale tracing tags from
  33. // Zygote.
  34. Trace.setTracingEnabled(false);
  35. if (startSystemServer) {
  36. startSystemServer(abiList, socketName);//关键步骤2,启动SystemServer
  37. }
  38. Log.i(TAG, "Accepting command socket connections");
  39. runSelectLoop(abiList);//关键步骤3
  40. closeServerSocket();
  41. } catch (MethodAndArgsCaller caller) {
  42. caller.run();
  43. } catch (RuntimeException ex) {
  44. Log.e(TAG, "Zygote died with exception", ex);
  45. closeServerSocket();
  46. throw ex;
  47. }
  48. }

详细分析这四个关键步骤。

关键步骤1:——调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService通讯

[java] view plaincopy
  1. ZygoteInit.registerZygoteSocket():
  2. /**
  3. * Registers a server socket for zygote command connections
  4. *
  5. * @throws RuntimeException when open fails
  6. */
  7. private static void registerZygoteSocket(String socketName) {
  8. if (sServerSocket == null) {
  9. int fileDesc;
  10. final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; //安卓规范套接字前缀+socket名字
  11. try {
  12. String env = System.getenv(fullSocketName);
  13. fileDesc = Integer.parseInt(env);
  14. } catch (RuntimeException ex) {
  15. throw new RuntimeException(fullSocketName + " unset or invalid", ex);
  16. }
  17. try {
  18. sServerSocket = new LocalServerSocket(
  19. createFileDescriptor(fileDesc));//创建一个文件描述符
  20. } catch (IOException ex) {
  21. throw new RuntimeException(
  22. "Error binding to local socket '" + fileDesc + "'", ex);
  23. }
  24. }
  25. }

关键步骤2:——调用startSystemServer,启动SystemServer这个系统核心进程

startSystemServer方法位于同一文件ZygoteInit.java当中。

[java] view plaincopy
  1. ZygoteInit.startSystemServer():
  2. /**
  3. * Prepare the arguments and fork for the system server process.
  4. */
  5. private static boolean startSystemServer(String abiList, String socketName)
  6. throws MethodAndArgsCaller, RuntimeException {
  7. long capabilities = posixCapabilitiesAsBits(
  8. OsConstants.CAP_BLOCK_SUSPEND,
  9. OsConstants.CAP_KILL,
  10. OsConstants.CAP_NET_ADMIN,
  11. OsConstants.CAP_NET_BIND_SERVICE,
  12. OsConstants.CAP_NET_BROADCAST,
  13. OsConstants.CAP_NET_RAW,
  14. OsConstants.CAP_SYS_MODULE,
  15. OsConstants.CAP_SYS_NICE,
  16. OsConstants.CAP_SYS_RESOURCE,
  17. OsConstants.CAP_SYS_TIME,
  18. OsConstants.CAP_SYS_TTY_CONFIG
  19. );
  20. /* Hardcoded command line to start the system server */
  21. String args[] = {
  22. "--setuid=1000",
  23. "--setgid=1000",
  24. "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
  25. "--capabilities=" + capabilities + "," + capabilities,
  26. "--runtime-init",
  27. "--nice-name=system_server",
  28. "com.android.server.SystemServer",
  29. };
  30. ZygoteConnection.Arguments parsedArgs = null;
  31. int pid;
  32. try {
  33. parsedArgs = new ZygoteConnection.Arguments(args);
  34. ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
  35. ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
  36. /* Request to fork the system server process */
  37. pid = Zygote.forkSystemServer( //与Android 4.4之前的版本不一样的地方
  38. parsedArgs.uid, parsedArgs.gid,
  39. parsedArgs.gids,
  40. parsedArgs.debugFlags,
  41. null,
  42. parsedArgs.permittedCapabilities,
  43. parsedArgs.effectiveCapabilities);
  44. } catch (IllegalArgumentException ex) {
  45. throw new RuntimeException(ex);
  46. }
  47. /* For child process */
  48. if (pid == 0) {
  49. if (hasSecondZygote(abiList)) {
  50. waitForSecondaryZygote(socketName);
  51. }
  52. handleSystemServerProcess(parsedArgs);
  53. }
  54. return true;
  55. }

这里我们可以看到,Zygote进程通过Zygote.forkSystemServer函数来创建一个新的进程来启动SystemServer组件,返回值pid等0的地方就是新的进程要执行的路径,即新创建的进程会执行handleSystemServerProcess函数。

[java] view plaincopy
  1. ZygoteInit.handleSystemServerProcess():
  2. /**
  3. * Finish remaining work for the newly forked system server process.
  4. */
  5. private static void handleSystemServerProcess(
  6. ZygoteConnection.Arguments parsedArgs)
  7. throws ZygoteInit.MethodAndArgsCaller {
  8. closeServerSocket();
  9. // set umask to 0077 so new files and directories will default to owner-only permissions.
  10. Os.umask(S_IRWXG | S_IRWXO);
  11. if (parsedArgs.niceName != null) {
  12. Process.setArgV0(parsedArgs.niceName);
  13. }
  14. final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
  15. if (systemServerClasspath != null) {
  16. performSystemServerDexOpt(systemServerClasspath);
  17. }
  18. if (parsedArgs.invokeWith != null) {
  19. String[] args = parsedArgs.remainingArgs;
  20. // If we have a non-null system server class path, we'll have to duplicate the
  21. // existing arguments and append the classpath to it. ART will handle the classpath
  22. // correctly when we exec a new process.
  23. if (systemServerClasspath != null) {
  24. String[] amendedArgs = new String[args.length + 2];
  25. amendedArgs[0] = "-cp";
  26. amendedArgs[1] = systemServerClasspath;
  27. System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
  28. }
  29. WrapperInit.execApplication(parsedArgs.invokeWith,
  30. parsedArgs.niceName, parsedArgs.targetSdkVersion,
  31. null, args);
  32. } else {
  33. ClassLoader cl = null;
  34. if (systemServerClasspath != null) {
  35. cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
  36. Thread.currentThread().setContextClassLoader(cl);
  37. }
  38. /*
  39. * Pass the remaining arguments to SystemServer.
  40. */
  41. RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
  42. }
  43. /* should never reach here */
  44. }

这个函数接着调用RuntimeInit.zygoteInit函数来进一步执行启动SystemServer组件的操作。

[java] view plaincopy
  1. RuntimeInit.zygoteInit函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中。
  2. public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
  3. throws ZygoteInit.MethodAndArgsCaller {
  4. if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
  5. redirectLogStreams();
  6. commonInit();
  7. nativeZygoteInit(); //调用了JNI层的方法,为Binder通信机制的建立奠定了基础,此处暂不深入讨论
  8. applicationInit(targetSdkVersion, argv, classLoader);
  9. }

继续查看RuntimeInit.applicationInit()方法

[java] view plaincopy
  1. private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
  2. throws ZygoteInit.MethodAndArgsCaller {
  3. // If the application calls System.exit(), terminate the process
  4. // immediately without running any shutdown hooks.  It is not possible to
  5. // shutdown an Android application gracefully.  Among other things, the
  6. // Android runtime shutdown hooks close the Binder driver, which can cause
  7. // leftover running threads to crash before the process actually exits.
  8. nativeSetExitWithoutCleanup(true);
  9. // We want to be fairly aggressive about heap utilization, to avoid
  10. // holding on to a lot of memory that isn't needed.
  11. VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
  12. VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
  13. final Arguments args;
  14. try {
  15. args = new Arguments(argv);
  16. } catch (IllegalArgumentException ex) {
  17. Slog.e(TAG, ex.getMessage());
  18. // let the process exit
  19. return;
  20. }
  21. // Remaining arguments are passed to the start class's static main
  22. /*
  23. *从ZygoteInit.startSystemServer()方法中传过来的parsedArgs参数包括
  24. *"--nice-name=system_server", "com.android.server.SystemServer"
  25. *实际上它们就是互相对应的硬编码,调用SystemServer的main方法
  26. */
  27. invokeStaticMain(args.startClass, args.startArgs, classLoader);
  28. }
  29. }

不要放弃,继续往下看,到这里我们将调用RuntimeInit.java中的invokeStaticMain方法:

[java] view plaincopy
  1. /**
  2. * Invokes a static "main(argv[]) method on class "className".
  3. * Converts various failing exceptions into RuntimeExceptions, with
  4. * the assumption that they will then cause the VM instance to exit.
  5. *
  6. * @param className Fully-qualified class name
  7. * @param argv Argument vector for main()
  8. * @param classLoader the classLoader to load {@className} with
  9. */
  10. private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
  11. throws ZygoteInit.MethodAndArgsCaller {
  12. Class<?> cl;
  13. try {
  14. cl = Class.forName(className, true, classLoader);//加载com.android.server.SystemServer这个类
  15. } catch (ClassNotFoundException ex) {
  16. throw new RuntimeException(
  17. "Missing class when invoking static main " + className,
  18. ex);
  19. }
  20. Method m;
  21. try {
  22. m = cl.getMethod("main", new Class[] { String[].class });//获取main方法
  23. } catch (NoSuchMethodException ex) {
  24. throw new RuntimeException(
  25. "Missing static main on " + className, ex);
  26. } catch (SecurityException ex) {
  27. throw new RuntimeException(
  28. "Problem getting static main on " + className, ex);
  29. }
  30. int modifiers = m.getModifiers();
  31. if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
  32. throw new RuntimeException(
  33. "Main method is not public and static on " + className);
  34. }
  35. /*
  36. * This throw gets caught in ZygoteInit.main(), which responds
  37. * by invoking the exception's run() method. This arrangement
  38. * clears up all the stack frames that were required in setting
  39. * up the process.
  40. */
  41. throw new ZygoteInit.MethodAndArgsCaller(m, argv);
  42. }

我们出奇的发现RuntimeInit.invokeStaticMain方法并没有直接调用SystemServer的main的方法,那么它是怎么被调用的?答案在这个函数的末尾——抛出了一个MethodAndArgsCaller异常。源码中注释非常清楚地说明了,这个异常将在main方法中被截获。

[java] view plaincopy
  1. public static void main(String argv[]) {
  2. try {
  3. ........ //省略掉中间的内容
  4. } catch (MethodAndArgsCaller caller) {//就是在这里截获的!
  5. caller.run();
  6. } catch(RuntimeException ex) {
  7. Log.e(TAG, "Zygote died withexception", ex);
  8. closeServerSocket();
  9. throw ex;
  10. }
  11. }

目光转移到MethodAndArgsCaller的run()方法。该方法定义在/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java方法中。

[java] view plaincopy
  1. public static class MethodAndArgsCaller extends Exception
  2. implements Runnable {
  3. /** method to call */
  4. private final Method mMethod;
  5. /** argument array */
  6. private final String[] mArgs;
  7. public MethodAndArgsCaller(Method method, String[] args) {
  8. //将方法参数,和调用方法的类传递下来
  9. mMethod = method;
  10. mArgs = args;
  11. }
  12. public void run() {
  13. try {
  14. //在线程的run()方法中开始正式调用main方法
  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. }

至此,终于正式调用SystemServer的main方法了。

Android5.0.0以上版本的SystemServer.java文件位于

/frameworks/base/services/java/com/android/server/中

[java] view plaincopy
  1. public static void main(String[] args) {
  2. new SystemServer().run();
  3. }

main方法中只有仅仅一句代码。调用了SystemServer的构造函数,并让他以“线程的方式”跑起来。

[java] view plaincopy
  1. public SystemServer() {
  2. // Checkfor factory test mode.
  3. mFactoryTestMode = FactoryTest.getMode();
  4. }
[java] view plaincopy
  1. private void run() {
  2. // If a device's clock is before 1970 (before 0), a lot of
  3. // APIs crash dealing with negative numbers, notably
  4. // java.io.File#setLastModified, so instead we fake it and
  5. // hope that time from cell towers or NTP fixes it shortly.
  6. if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
  7. Slog.w(TAG, "System clock is before 1970; setting to 1970.");
  8. SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
  9. }
  10. // Here we go!
  11. Slog.i(TAG, "Entered the Android system server!");
  12. EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
  13. // In case the runtime switched since last boot (such as when
  14. // the old runtime was removed in an OTA), set the system
  15. // property so that it is in sync. We can't do this in
  16. // libnativehelper's JniInvocation::Init code where we already
  17. // had to fallback to a different runtime because it is
  18. // running as root and we need to be the system user to set
  19. // the property. http://b/11463182
  20. SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
  21. // Enable the sampling profiler.
  22. if (SamplingProfilerIntegration.isEnabled()) {
  23. SamplingProfilerIntegration.start();
  24. mProfilerSnapshotTimer = new Timer();
  25. mProfilerSnapshotTimer.schedule(new TimerTask() {
  26. @Override
  27. public void run() {
  28. SamplingProfilerIntegration.writeSnapshot("system_server", null);
  29. }
  30. }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
  31. }
  32. // Mmmmmm... more memory!
  33. VMRuntime.getRuntime().clearGrowthLimit();
  34. // The system server has to run all of the time, so it needs to be
  35. // as efficient as possible with its memory usage.
  36. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
  37. // Some devices rely on runtime fingerprint generation, so make sure
  38. // we've defined it before booting further.
  39. Build.ensureFingerprintProperty();
  40. // Within the system server, it is an error to access Environment paths without
  41. // explicitly specifying a user.
  42. Environment.setUserRequired(true);
  43. // Ensure binder calls into the system always run at foreground priority.
  44. BinderInternal.disableBackgroundScheduling(true);
  45. // Prepare the main looper thread (this thread).
  46. android.os.Process.setThreadPriority(
  47. android.os.Process.THREAD_PRIORITY_FOREGROUND);
  48. android.os.Process.setCanSelfBackground(false);
  49. Looper.prepareMainLooper();
  50. // Initialize native services.
  51. //关键步骤1
  52. System.loadLibrary("android_servers");
  53. nativeInit();
  54. // Check whether we failed to shut down last time we tried.
  55. // This call may not return.
  56. performPendingShutdown();
  57. // Initialize the system context.
  58. createSystemContext();
  59. //关键步骤2
  60. // Create the system service manager.
  61. mSystemServiceManager = new SystemServiceManager(mSystemContext);
  62. LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
  63. //关键步骤3
  64. // Start services.
  65. try {
  66. startBootstrapServices();
  67. startCoreServices();
  68. startOtherServices();
  69. } catch (Throwable ex) {
  70. Slog.e("System", "******************************************");
  71. Slog.e("System", "************ Failure starting system services", ex);
  72. throw ex;
  73. }
  74. // For debug builds, log event loop stalls to dropbox for analysis.
  75. if (StrictMode.conditionallyEnableDebugLogging()) {
  76. Slog.i(TAG, "Enabled StrictMode for system server main thread.");
  77. }
  78. // Loop forever.
  79. Looper.loop();
  80. throw new RuntimeException("Main thread loop unexpectedly exited");
  81. }

SystemServer.run()方法中最值得关注的就是我注释中标注的三个关键步骤,下面稍作解释:

关键步骤1——初始化native层的系统服务。从nativeInit名字就可以看出来这是一个native层的代码,调用了jni层的代码。这个方法的实际实现在:frameworks/base/services/core/jni/com_android_server_SystemServer.cpp。相关代码如下:

[cpp] view plaincopy
  1. </pre><pre name="code" class="cpp">static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) {
  2. char propBuf[PROPERTY_VALUE_MAX];
  3. property_get("system_init.startsensorservice", propBuf, "1");
  4. if (strcmp(propBuf, "1") == 0) {
  5. // Start the sensor service
  6. SensorService::instantiate();
  7. }
  8. }

大概就是根据属性配置文件来确定是否需要初始化SensorService,这里就不多介绍了。

关键步骤2——将SystemManagerService注册到SystemServer(自身)中。

关键步骤3——启动系统运行所需的服务。其中:

startBootstrapServices()方法启动ActivityManagerService(AMS),PowerManagerService,PackageManagerServices(),DisplayManagerService等系统关键服务。

startCoreServices()方法调用了一些核心服务,例如LightService,BatteryService等。

startOtherServices()方法则调用剩余的一些服务。出人意料的是,WindowMangaerService竟然是在这里启动。除此之外,还有InputManagerService和AlarmManagerService都在这里启动。

完成了这三个关键步骤后,最后会通过Looper.loop()来进行消息循环,然后处理消息。

此前安卓版本与5.0之后版本SystemServer的启动方式有很大区别:

此前的SystemServer会通过  ServerThread thr = new ServerThread();直接建立一个ServerThread进程。

到这里,系统的关键服务都启动完毕,安卓系统的启动过程也接近尾声。

这里执行完成后,层层返回,最后回到上面的ZygoteInit.main函数中,接下来它就要调用runSelectLoop函数进入一个无限循环在前面ZygoteInit.main函数关键步骤1中创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程了。runSelectLoop()函数实际上是在一死循环中利用zygoteConnection类通过socket的方式进行消息 处理,用于fork出新的zygote,从而以最轻量级的方式实现每个进程一个虚拟机的机制。

最后我们再简单梳理下Android启动的过程。毕竟这么复杂的过程需要不断回顾。后续可能会补充上更多流程图,以帮助自己和大家进行梳理。

1. Linux内核启动完毕后,系统开始init.rc配置文件启动Zygote进程。

2. Zygote进程的启动经历了ZygoteInit,RuntimeInit,fork出SystemServer这个进程。

3. SystemServer进程负责启动,初始化系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。除了注册到ServiceManager中,还将调用各服务的systemReady()告诉它们系统已经正常启动

4. (老罗总结)当我们需要启动一个Android应用程序时,ActivityManagerService会通过Socket进程间通信机制,通知Zygote进程为这个应用程序创建一个新的进程。

文末感谢下为我提供过帮助的博客大牛和文章,传送门:

1.《Android启动过程深入解析》我所归纳的安卓启动分为几个阶段由此文借鉴。

2.《Android系统进程Zygote启动过程的源代码分析》 安卓名人老罗的传世名作。

3. 《Android情景分析之深入解析system_server》为我解决了不少疑惑。

结合源码探讨Android系统的启动流程相关推荐

  1. 结合源码探讨Android距离传感器亮灭屏机制

    结合源码探讨Android距离传感器亮灭屏机制 本文的分析是基于Android 5.0.0 Google原生代码的. Android中的距离传感器,也就是P-sensors(Proximity Sen ...

  2. java jni编译_从源码编译Android系统的Java类库和JNI动态库的方法

    利用源码编译Android系统Java类库 1.编写Java项目和Android.mk文件 ├── Android.mk └── src └── com └── lhw └── framework └ ...

  3. Android系统的启动流程简要分析

    这是我结合网上的资料以及自己分析android4.4的源码整理的笔记,对整个安卓系统的流程启动进行了梳理,很多细节并未展开,只是简要的进行了介绍. 一.Android系统的架构介绍 Android的整 ...

  4. Netty 源码解析系列-服务端启动流程解析

    netty源码解析系列 Netty 源码解析系列-服务端启动流程解析 Netty 源码解析系列-客户端连接接入及读I/O解析 五分钟就能看懂pipeline模型 -Netty 源码解析 1.服务端启动 ...

  5. Alian解读SpringBoot 2.6.0 源码(七):启动流程分析之准备应用上下文

    目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.准备应用上下文 2.1.整体流程 2.2.设置环境 2.3.应用上下文进行后置处理 2.4.应用所有初始化器 2.5.发布应用上下 ...

  6. Alian解读SpringBoot 2.6.0 源码(六):启动流程分析之创建应用上下文

    目录 一.背景 1.1.run方法整体流程 1.2.本文解读范围 二.创建应用上下文 2.1.初始化入口 2.2.初始化AbstractApplicationContext 2.3.初始化Generi ...

  7. Android系统 lk启动流程简析

    本篇文章是对初步学习Android系统lk启动流程的一个大致简介.方便掌握lk启动流程的大致框架,具体细节后续再进行更新 1. 前言 需要了解的文件类型: 1)编译LK的链接文件(.ld) 2)汇编文 ...

  8. Alian解读SpringBoot 2.6.0 源码(八):启动流程分析之刷新应用上下文(中)

    目录 一.背景 1.1.刷新的整体调用流程 1.2.本文解读范围 二.调用后处理器 2.1.调用在上下文中注册为beanFactory的后置处理器 2.2.invokeBeanFactoryPostP ...

  9. Alian解读SpringBoot 2.6.0 源码(十):启动流程之自动装配原理

    目录 一.背景 1.1.主类的加载 1.2.后置处理器的获取 二.配置类后处理器 2.1.获取配置类 2.2. 2.3.解析主类 2.3.1.整体解析过程 2.3.2.核心解析过程 2.3.3.延迟导 ...

最新文章

  1. BigPipe:高性能的“流水线技术”网页
  2. 第一篇:数据仓库概述
  3. hdu3182 状态压缩dp
  4. 中文字符串函数php,php截取中文字符串函数实例,_PHP教程
  5. python打开文件_喜大普奔 | 如何在Win10下利用Python打开grib文件
  6. h.264 html播放,浏览器 – 我如何播放H264视频?
  7. spring java配置_Spring:使基于Java的配置更加优雅
  8. GestureDetector类及其用法
  9. BZOJ3295 [Cqoi2011]动态逆序对 分治 树状数组
  10. python批量获取百度贴吧_python网络爬虫案例:批量爬取百度贴吧页面数据
  11. GIT版本控制(详解)
  12. Windows API、SDK和CRT的关系
  13. 转:JavaScript 全栈工程师培训教程
  14. buu RSA what(共模攻击+base64隐写)
  15. 自然语言处理的词法分析、句法分析、语义分析
  16. 微软windows自带邮箱设置和使用(更改windows10账户绑定邮箱)qq邮箱绑定windows邮箱,163邮箱绑定windows邮箱,阿里云邮箱绑定windows邮箱
  17. win10家庭版计算机配置在哪里,Windows10家庭版没有组策略的解决方法
  18. html 用户列表,用户列表.html
  19. Faster R-CNN论文翻译笔记
  20. WPF--3Dmax+blend+WPF综合运用

热门文章

  1. ASP.NET中实现二级或多级域名(修改UrlRewrite)
  2. (转自孟岩的CSDN)理解矩阵
  3. 【海洋女神原创】关于installshield“完美卸载”的改进方法
  4. PyTorch 和 TensorFlow 引领未来
  5. 大数据分析-时间序列(pandas库 )
  6. Python 3.4中文编码
  7. Javascript第四章函数function也是数据类型第六课
  8. vue项目中vue-fullcalendar的使用(行程日历)
  9. 如何利用VUE动态添加class样式
  10. .net java xml_java.net.MalformedURLException – 在通过StAX解析XML文件时