IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android系统启动流程及其路径浅析 -> 正文阅读

[移动开发]Android系统启动流程及其路径浅析

Android 系统启动流程相关的文章很多,但初次学习查阅的过程中,总是找不到相关文件的路径以及调用的过程。因此本文旨在梳理出 Android 系统启动过程中的主干节点,理清整个过程中的方法调用和相关文件路径。正文基本按照系统的启动过程来排布,在此分享一个Android 源码在线查看工具,本文的代码都来源于此。http://aospxref.com/

1 BootLoader

1.1 加载 BootLoader

在关机状态下,Android 系统是存放在 ROM 中,而系统的运行是在 RAM中,因此有将 系统从 ROM 加载到 RAM 中的这一过程。当按下电源键或者通过重启命令启动Android系统时,引导芯片会从 ROM 中加载引导程序 BootLoader 到 RAM中。

1.2 运行 BootLoader

BootLoader 是系统运行的第一个程序,它的主要作用是把 Linux Kernel 加载到 RAM 中并拉起。

2 初始化 Kernel

引导程序在完成工作后,会将系统控制权转交到 head.S,其为汇编代码。
路径:msm/arch/arm64/kernel/head.S
流程:在其中会调用 start_kernel,进入到内核启动。

start_kernel 所在的代码路径为 /kernel/msm/init/main.c,其中的主要调用流程如下(前一个函数调用后一个函数):
start_kernel: 这个函数可以看作内核的 main,完成了内核的大部分初始化工作;
rest_init:完成后续初始化,主要启动内核线程;
kernel_init:设备驱动程序初始化;
run_init_processs:其中, do_execve 会依次去找根目录下的 init,execute_command,/sbin/init,/etc/init,/bin/init, /bin/sh 这六个可执行文件,找到其中一个就会进入 init 进程(这几个目录在手机系统下,非源代码的路径)。

3 init 进程

3.1 入口 main.cpp

init 进程的入口代码路径为: /system/core/init/main.cpp,其 main 方法如下:

51  int main(int argc, char** argv) {
52  #if __has_feature(address_sanitizer)
53      __asan_set_error_report_callback(AsanReportCallback);
54  #endif
55      // Boost prio which will be restored later
56      setpriority(PRIO_PROCESS, 0, -20);
57      if (!strcmp(basename(argv[0]), "ueventd")) {
58          return ueventd_main(argc, argv);
59      }
60  
61      if (argc > 1) {
62          if (!strcmp(argv[1], "subcontext")) {
63              android::base::InitLogging(argv, &android::base::KernelLogger);
64              const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
65  
66              return SubcontextMain(argc, argv, &function_map);
67          }
68  
69          if (!strcmp(argv[1], "selinux_setup")) {
70              return SetupSelinux(argv);
71          }
72  
73          if (!strcmp(argv[1], "second_stage")) {
74              return SecondStageMain(argc, argv);
75          }
76      }
77  
78      return FirstStageMain(argc, argv);
79  }

在这个 mian 方法中,根据传入参数的不同,会选择执行不同阶段的代码。
FirstStageMain: 路径 /system/core/init/first_stage_init.cpp
作用:创建和挂载启动所需的文件目录
SecondStageMain: 路径 /system/core/init/init.cpp
作用:解析和执行 init.rc 中定义的各种启动任务,启动 Zygote进程

3.2 解析 rc 文件

在SecondStageMain中,调用 LoadBootScripts 解析各种 rc 配置文件

303  static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
304      Parser parser = CreateParser(action_manager, service_list);
305  
306      std::string bootscript = GetProperty("ro.boot.init_rc", "");
307      if (bootscript.empty()) {
308          parser.ParseConfig("/system/etc/init/hw/init.rc");
309          if (!parser.ParseConfig("/system/etc/init")) {
310              late_import_paths.emplace_back("/system/etc/init");
311          }
312          // late_import is available only in Q and earlier release. As we don't
313          // have system_ext in those versions, skip late_import for system_ext.
314          parser.ParseConfig("/system_ext/etc/init");
315          if (!parser.ParseConfig("/vendor/etc/init")) {
316              late_import_paths.emplace_back("/vendor/etc/init");
317          }
318          if (!parser.ParseConfig("/odm/etc/init")) {
319              late_import_paths.emplace_back("/odm/etc/init");
320          }
321          if (!parser.ParseConfig("/product/etc/init")) {
322              late_import_paths.emplace_back("/product/etc/init");
323          }
324      } else {
325          parser.ParseConfig(bootscript);
326      }
327  }

/system/core/rootdir/init.rc 中,能看到如下导入 zygote 相关 rc 文件的代码:

12 import /system/etc/init/hw/init.${ro.zygote}.rc

这些 rc 在 init.rc 在同级目录下
在这里插入图片描述
在 init.rc 的 late-init 阶段启动 zygote,如下所示:

468 on late-init
		trigger early-fs
    	.
    	.
  		.
496 	trigger zygote-start

5 Zygote 进程

5.1 启动阶段

上一节最后准备启动的 zygote 定义在 /system/core/rootdir/init.zygote64.rc (这里以64位系统为例)里,其第一行代码如下:

1 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
...

service 表示 Zygote 进程以服务的形式来启动;
zygote 则是进程的名字;
/system/bin/app_process64 是执行程序的路径,后面几项则是传给执行程序的参数;
–start-system-server 表示在 Zygote 进程启动后需要启动 SystemServer 进程。

zygote-start 触发后会执行手机系统中 /system/bin/app_process64 的程序
在这里插入图片描述
对应的系统源码在 /frameworks/base/cmds/app_process/app_main.cpp,在其 main 方法中靠后处,有如下判断:

335      if (zygote) {
336          runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
337      } 

意思是如果当前的 main 函数,运行在 Zygote 进程中,则调用 AppRuntime 的 start 函数(runtime 是一个AppRuntime对象)。
继续跟踪代码发现 AppRunTime 继承自 /frameworks/base/core/jni/AndroidRuntime.cpp,其 start 方法中的主要过程有:调用 startVm 函数来创建 Java 虚拟机;调用 startReg 函数为 Java 虚拟机注册 JNI 方法。

然后通过 GetStaticMethodID 找到 ZygoteInt 的 main 方法,再通过CallStaticVoidMethod 进入到该 main 方法中

1288      if (startClass == NULL) {
1289          ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
1290          /* keep going */
1291      } else {
1292          jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
1293              "([Ljava/lang/String;)V");
1294          if (startMeth == NULL) {
1295              ALOGE("JavaVM unable to find main() in '%s'\n", className);
1296              /* keep going */
1297          } else {
1298              env->CallStaticVoidMethod(startClass, startMeth, strArray);

5.2 执行阶段

现在进入到 /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java的 main 方法中,通过如下代码开始启动 SystemServer:

975              if (startSystemServer) {
976                  Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
977  
978                  // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
979                  // child (system_server) process.
980                  if (r != null) {
981                      r.run();
982                      return;
983                  }
984              }

在 forkSystemServer 方法内部又调用了 Zygote.forkSystemServer 来 fork 出 SystemServer 进程,随后通过 handleSystemServerProcess 来处理子进程:

836              /* Request to fork the system server process */
837              pid = Zygote.forkSystemServer(
838                      parsedArgs.mUid, parsedArgs.mGid,
839                      parsedArgs.mGids,
840                      parsedArgs.mRuntimeFlags,
841                      null,
842                      parsedArgs.mPermittedCapabilities,
843                      parsedArgs.mEffectiveCapabilities);
844          } catch (IllegalArgumentException ex) {
845              throw new RuntimeException(ex);
846          }
847  
848          /* For child process */
849          if (pid == 0) {
850              if (hasSecondZygote(abiList)) {
851                  waitForSecondaryZygote(socketName);
852              }
853  
854              zygoteServer.closeServerSocket();
855              return handleSystemServerProcess(parsedArgs);
856          }

紧接着再跟踪一下 handleSystemServerProcess 方法,其结尾处调用了 ZygoteInit.zygoteInit:

557              return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
558                      parsedArgs.mDisabledCompatChanges,
559                      parsedArgs.mRemainingArgs, cl);

在这个被调用的方法里,使用了 RuntimeInit.applicationInit 进入到 SystemServer 的 main 方法。

1047      public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
1048              String[] argv, ClassLoader classLoader) {
1049          if (RuntimeInit.DEBUG) {
1050              Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
1051          }
1052  
1053          Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
1054          RuntimeInit.redirectLogStreams();
1055  
1056          RuntimeInit.commonInit();
1057          ZygoteInit.nativeZygoteInit();
1058          return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
1059                  classLoader);
1060      }

6 SystemServer 进程启动

/frameworks/base/services/java/com/android/server/SystemServer.java 的 main 方法中,通过 SystemServer().run() 创建 SystemServer 对象,并执行 run 方法.

在其中,会启动引导服务、核心服务、其他服务。

874          // Start services.
875          try {
876              t.traceBegin("StartServices");
877              startBootstrapServices(t);
878              startCoreServices(t);
879              startOtherServices(t);
880          }

7 桌面 Launcher 启动

Laucher 作为一个独立的 app,代码路径为 /packages/apps/Launcher3/src/com/android/launcher3/Launcher.java,其启动是从 SystemServer 中使用 AMS 启动 Launcher开始的,具体过程这里不再详述。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-28 23:02:56  更:2021-12-28 23:03:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:16:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码