前言
O之后的启动流程,大体上差异应该不大,已经很多优秀的文章发布,本文也是参考其他文章,以及自己一遍看文档,一遍走读整理出来的。看文档还是要结合自己的阅读和理解才有意义,参考文档可以参考后面贴出来链接。
菜鸟一个,使用IDE, 需要配置一些东西,比较麻烦,所以代码阅读工具使用的是在线的https://cs.android.com/
一、init进程启动
init进程是Linux内核启动完成后在用户空间启动的第一个进程,主要负责初始化工作、启动属性服务、解析init.rc文件并启动Zygote进程。
1.1 main.cpp
//system/core/init/main.cpp
int main(int argc, char** argv) {
...
if (argc > 1) {
//4、第三阶段
if (!strcmp(argv[1], "subcontext")) {
android::base::InitLogging(argv, &android::base::KernelLogger);
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
return SubcontextMain(argc, argv, &function_map);
}
//2、启动Selinux安全策略
if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}
//3、第二阶段
if (!strcmp(argv[1], "second_stage")) {
return SecondStageMain(argc, argv);
}
}
//1、第一阶段
return FirstStageMain(argc, argv);
}
以上4个阶段均在system/core/init/README.md末尾有介绍,设计到的只是点还是挺多的,能力不足就不展开讲了。
int FirstStageMain(int argc, char** argv) {
...
//将基本文件系统设置放在 / 上的 initramdisk 中使用rc文件配置其他的
CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
CHECKCALL(mkdir("/dev/pts", 0755));
CHECKCALL(mkdir("/dev/socket", 0755));
CHECKCALL(mkdir("/dev/dm-user", 0755));
CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
...
const char* path = "/system/bin/init";
const char* args[] = {
path, "selinux_setup", nullptr};
...
//执行第二阶段指令
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;
}
执行下一阶段均是使用下一阶段参数执行 /system/bin/init,另一个比较重要的就是解析rc文件的SecondStageMain。
1.2 init.cpp
// system/core/init/init.cpp
int SecondStageMain(int argc, char** argv) {
...
ActionManager& am = ActionManager::GetInstance();
ServiceList& sm = ServiceList::GetInstance();
LoadBootScripts(am, sm);
...
return 0;
}
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
Parser parser = CreateParser(action_manager, service_list);
std::string bootscript = GetProperty("ro.boot.init_rc", "");
if (bootscript.empty()) {
parser.ParseConfig("/system/etc/init/hw/init.rc");
if (!parser.ParseConfig("/system/etc/init")) {
late_import_paths.emplace_back("/system/etc/init");
}
//late_import 仅在 Q 和更早版本中可用,之后的版本只关注未省略的内容即可
...
} else {
parser.ParseConfig(bootscript);
}
}
init.rc负责其他系统目录的创建,并并启动Zygote进程。
1.3 init.rc
//system/core/rootdir/init.rc
import /system/etc/init/hw/init.${
ro.zygote}.rc
...
# 挂载文件系统和启动核心系统服务
on late