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
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
313
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
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
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
979
980 if (r != null) {
981 r.run();
982 return;
983 }
984 }
在 forkSystemServer 方法内部又调用了 Zygote.forkSystemServer 来 fork 出 SystemServer 进程,随后通过 handleSystemServerProcess 来处理子进程:
836
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
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
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开始的,具体过程这里不再详述。
|