安卓系统启动流程

目录

光看分析文章还是不够的,还是要和实践结合。

1 init阶段

init 命令的入口是init/main.cppmain()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
__asan_set_error_report_callback(AsanReportCallback);
#elif __has_feature(hwaddress_sanitizer)
__hwasan_set_error_report_callback(AsanReportCallback);
#endif

// //以上部分是和编译相关的语法,满足条件时则保留后面的语句。它具体针对的是两种不同的内存检查工具:AddressSanitizer (ASan) 和 Hardware Address Sanitizer (HWAsan)。

// Boost prio which will be restored later
// 提升权限,后续会恢复
setpriority(PRIO_PROCESS, 0, -20);
if (!strcmp(basename(argv[0]), "ueventd")) {
//init进程创建子进程ueventd,并将创建设备节点文件的工作托付给ueventd
return ueventd_main(argc, argv);
}

if (argc > 1) {
// 根据不同参数执行不同阶段
if (!strcmp(argv[1], "subcontext")) {
android::base::InitLogging(argv, &android::base::KernelLogger);
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();

return SubcontextMain(argc, argv, &function_map);
}

if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}

if (!strcmp(argv[1], "second_stage")) {
return SecondStageMain(argc, argv);
}
}
// 最开始执行第一阶段
return FirstStageMain(argc, argv);
}

init的启动阶段图

来源 https://www.sunmoonblog.com/2024/07/15/android-startup/

1.1 FirstStage

firstStage的源码在/system/core/init/first_stage_init.cpp

大部分是创建启动所需的各种目录,还初始化kernel log,最下面有这么一段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
     const char* path = "/system/bin/init"; 
const char* args[] = {path, "selinux_setup", nullptr};
auto fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
close(fd);
execv(path, const_cast<char**>(args));

// execv() only returns if an error happened, in which case we
// panic and never fall through this conditional.
PLOG(FATAL) << "execv(\"" << path << "\") failed";

return 1;
}

这就是进入下一阶段的代码

1.2 SELinux Setup

SetupSelinux主要功能就是管理selinux和相关策略。

SELinux(Security Enhanced Linux)是一种为Linux内核提供的强制访问控制(MAC, Mandatory Access Control)框架。它的设计目的是为了提高Linux系统的安全性,通过严格的权限管理机制来限制进程和用户的访问权限,从而减少系统被攻击的风险。

在SELinux Setup的结尾也有进入下一阶段的代码。

1.3 SecondStage

在SecondStage中有一个LoadBootScripts的函数

init.rc是和init相关的配置文件

这里会在 LoadBootScripts() 方法中解析 init.rc 文件。关于该文件指令的含义可以参考 AOSP 中的文档:《Android Init Language》. 完成解析相关的类是 ActionManagerParserXXParser,均位于 system/core/init 目录下面。除此之外,还有 ActionService 等类。它们的作用是,各种 Parser 用来解析 rc 文件中的指令。解析出的指令会被封装成 ActionService 等对象。
作者:开发者如是说
链接:https://juejin.cn/post/6844904137268674568
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

简单摘要一下SecondStage的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int SecondStageMain(int argc, char** argv) {
...
ActionManager& am = ActionManager::GetInstance();
...
am.QueueEventTrigger("early-init");

// Trigger all the boot actions to get us started.
am.QueueEventTrigger("init");
// Don't mount filesystems or start core system services in charger mode.
std::string bootmode = GetProperty("ro.bootmode", "");
if (bootmode == "charger") {
am.QueueEventTrigger("charger");
} else {
am.QueueEventTrigger("late-init");
}
...
}

这里是构造了一个EventTrigger对象, 放到事件队列中,但是并没有触发

直到ExecuteOneCommand才会依次触发

具体做什么,就在读取的配置文件中。源代码中位于/system/core/rootdir/init.rc

init中会start service manager

在lateinit中会trigger zygote-start

zygote-start会根据不同的配置,执行不同的操作,但最终都会执行start zygote

2 init.rc的配置

上面提到在init.rc中有start zygote等启动服务的配置,那么这个start又做了什么。

根据https://chromium.googlesource.com/aosp/platform/system/core/+/refs/heads/master/init

这里的解释还是只有启动服务。

这里的 start 会被映射到 builtins 类的 do_start() 方法。该方法会调用 Servicestart() 方法。该方法主要是调用 clonefork 创建子进程,然后调用 execve 执行配置的二进制文件,另外根据之前在 rc 文件中的配置,去执行这些配置。
作者:开发者如是说
链接:https://juejin.cn/post/6844904137268674568
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

builtinssystem/core/init/builtins.cpp

system/core/init/service.cpp

servicemanager的配置位于/framework/native/cmds/servicemanager

zygote的配置是根据系统类型变化的,在init.rc的开头被import

zygote64为例,配置文件如下

主要是启动了/system/bin/app_process64

相关源码在/frameworks/base/cmds/app_process/

3 Zygote的启动

来源  https://www.sunmoonblog.com/2024/07/15/android-startup/

3.1 app_process

/frameworks/base/cmds/app_process/app_main.cpp

主要是进行参数解析

还有启动ZygoteInit

这里的runtimeAndroidRuntime

AndroidRuntime定义于/frameworks/base/core/jni/AndroidRuntime.cpp

所以这里的 start() 方法是一种 JNI (Java Native Interface)调用。这里将会调用 Java 中的静态 main() 方法继续执行。这里是在 C++ 中调用 Java 的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...

/* 获取环境变量 */
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /system does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}

...

/* start the virtual machine */
/* startVM启动虚拟机 */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
onVmCreated(env);

...

/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
/* 获取类及其Main,并Call */
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);

ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}


3.2 Zygoteinit.java

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;

// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();

// Zygote goes into its own process group.
// 设置进程权限
try {
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}

Runnable caller;
try {
// Store now for StatsLogging later.
final long startTime = SystemClock.elapsedRealtime();
final boolean isRuntimeRestarted = "1".equals(
SystemProperties.get("sys.boot_completed"));

String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
Trace.TRACE_TAG_DALVIK);
bootTimingsTraceLog.traceBegin("ZygoteInit");
RuntimeInit.preForkInit();

boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;

// 解析参数
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}

// ... 资源预加载与日志

// 启动zygoteServer
zygoteServer = new ZygoteServer(isPrimaryZygote);

if (startSystemServer) {
// 启动SystemServer
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}

Log.i(TAG, "Accepting command socket connections");

// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with fatal exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}

// ...
}

这里主要做了

  • 创建ZygoteServer 对象。提供了等待 UNIX 套接字的命令,并且提供了 fork 虚拟机的方法。
  • 资源预加载
  • 调用 forkSystemServer() 。其中会调用 Zygote 的静态方法来 Fork 一个子进程。该方法内部又会调用 JNI 层的 nativeForkSystemServer 方法最终完成 Fork 操作。
  • 启动 select 循环,等待连接。会等待接受命令,fork子进程,并返回子进程的 main 方法

4 SystemServer

启动了SystemServer后,SystemServer还会拉起其他的系统内服务。

/frameworks/base/services/java/com/android/server/SystemServer.java

摘要一些代码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}

// frameworks/base/services/java/com/android/server/SystemServer.java
private void run() {
TimingsTraceAndSlog t = new TimingsTraceAndSlog();
try {

// ...

// Create the system service manager.
// 启动system service manager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
mDumper.addDumpable(mSystemServiceManager);


// Start services.
try {
t.traceBegin("StartServices");
startBootstrapServices(t); // 启动引导服务
startCoreServices(t); // 启动核心服务
startOtherServices(t); // 启动其他服务
startApexServices(t); // 启动Apex服务
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}

// ...

// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}


各种启动服务的操作是通过调用 SystemServiceManagerstartService()

startBootstrapServices() 中会拉起Activity Manager ServicePackage Manager Service

Apex服务是指Android操作系统中的一种应用程序启动方式,它允许应用程序在设备启动时以系统服务的形式自动运行。这些服务通常包括系统应用、框架服务和系统UI等。它们在设备启动时会自动运行,并为用户提供各种基础功能和界面。
startApexServices方法会遍历所有已安装的Apex服务,并调用它们的启动方法,使它们在系统启动时自动运行。该方法在系统启动过程中被调用,是Android操作系统启动过程中的一部分。

5 总结

来源https://juejin.cn/post/6844904137268674568#heading-2