(注:以下代码分析基于android-10.0.0_r30)
一 概述
因为Android系统是基于Linux内核,所以Android系统的启动首先是从Linux开始的,当我们启动Android手机的时候,会经过一系列的调用,直到启动zygote进程,也是我们系统的第一个进程
system/core/init/main.cpp
system/core/init/init.cpp
system/core/init/parser.cpp
system/core/init/epoll.h
system/core/init/epoll.cpp
system/core/rootdir/init.rc
system/core/rootdir/init.zygote64.rc
二 init
最初的启动,是在Android系统目录system/core/init/main.cpp中的main函数中执行的
main函数中主要有几个函数
- FirstStageMain:系统启动的第一阶段
- SetupSelinux:加载SELinux规则
- SecondStageMain:系统启动的第二个阶段
它们是通过传递不同的参数来进行调用的
[main.cpp]
int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
__asan_set_error_report_callback(AsanReportCallback);
#endif
// 设置优先级,这个优先级会在SecondStageMain中被还原
setpriority(PRIO_PROCESS, 0, -20);
if (!strcmp(basename(argv[0]), "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;
//
return SubcontextMain(argc, argv, &function_map);
}
if (!strcmp(argv[1], "selinux_setup")) {
//加载SELinux规则,并进入第二阶段
return SetupSelinux(argv);
}
if (!strcmp(argv[1], "second_stage")) {
//系统启动关键的第二步
return SecondStageMain(argc, argv);
}
}
//系统启动关键的第一步
return FirstStageMain(argc, argv);
}
FirstStageMain
init进程启动的第一步,这一步主要做了几件事
- 挂载一些分区并创建关键目录
- 初始化Kernel日志系统
- 进入SetupSelinux阶段
[init.cpp]
int FirstStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
//用于init进程崩溃时,启动bootloader,让开发者定位问题
InstallRebootSignalHandlers();
}
boot_clock::time_point start_time = boot_clock::now();
std::vector<std::pair<std::string, int>> errors;
#define CHECKCALL(x) \
if ((x) != 0) errors.emplace_back(#x " failed", errno);
// Clear the umask.
umask(0);
//创建并挂载一些启动需要的系统文件
CHECKCALL(clearenv());
...
#undef CHECKCALL
//重定向标准输入输出错误输出到 dev/null,第一阶段和第二阶段都需要做
SetStdioToDevNull(argv);
//初始化linux log,因为现在android的log还没有启动
InitKernelLogging(argv);
//加载一些ramdisk
...
//传入参数selinux_setup,进入selinux_setup阶段
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));
return 1;
}
SetupSelinux
SELinux全称是Security-Enhanced Linux,它是一个Linux相关的安全子系统,这里在作为这些相关操作后,会进入
SecondStageMain阶段
int SetupSelinux(char** argv) {
//一些Selinux相关的初始化
...
//进入init进程的第二阶段
const char* path = "/system/bin/init";
const char* args[] = {path, "second_stage", nullptr};
execv(path, const_cast<char**>(args));
return 1;
}
SecondStageMain
init进程启动的第二步,这一步做的操作非常多
- 系统会进行一些linux的相关设置
- 然后系统会初始化一些属性PropertyInit
- 进行一些SELinux的设置
- 创建一个epoll,它会接受一下信号并处理
- 设置系统属性StartPropertyService
- 解析rc文件,开始添加action,这些ation可以分为四个阶段:early-init,init,early-boot,boot
- 进入死循环,执行这些action
[init.cpp]
int SecondStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
//用于init进程崩溃时,启动bootloader,让开发者定位问题
InstallRebootSignalHandlers();
}
boot_clock::time_point start_time = boot_clock::now();
trigger_shutdown = [](const std::string& command) { shutdown_state.TriggerShutdown(command); };
//和第一步中一样,重定向标准输入输出错误输出到 dev/null
SetStdioToDevNull(argv);
InitSecondStageLogging(argv);
//前面会有一些linux相关的设置,这里略去
...
//初始化一些属性
PropertyInit();
//debug相关
if (load_debug_prop) {
UmountDebugRamdisk();
}
//挂载filesystems文件
MountExtraFilesystems();
//设置SELinux
SelinuxSetupKernelLogging();
//初始化Selabel
SelabelInitialize();
//设置Selinux并恢复一些上下文
SelinuxRestoreContext();
//新建epoll
Epoll epoll;
if (auto result = epoll.Open(); !result.ok()) {
PLOG(FATAL) << result.error();
}
//设置子进程退出的信号处理函数
InstallSignalFdHandler(&epoll);
//设置属性更改的通知函数
InstallInitNotifier(&epoll);
//设置系统属性
StartPropertyService(&property_fd);
// Make the time that init stages started available for bootstat to log.
RecordStageBoottimes(start_time);
// 设置 libavb 版本
if (const char* avb_version = getenv("INIT_AVB_VERSION"); avb_version != nullptr) {
SetProperty("ro.boot.avb_version", avb_version);
}
unsetenv("INIT_AVB_VERSION");
fs_mgr_vendor_overlay_mount_all();
export_oem_lock_status();
MountHandler mount_handler(&epoll);
SetUsbController();
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
Action::set_function_map(&function_map);
if (!SetupMountNamespaces()) {
PLOG(FATAL) << "SetupMountNamespaces failed";
}
//初始化第二阶段上下文
InitializeSubcontext();
//构建ActionManager和ServiceList相关对象,用来解析rc相关文件的action、service
ActionManager& am = ActionManager::GetInstance();
ServiceList& sm = ServiceList::GetInstance();
//加载启动的配置文件,即一些rc文件
LoadBootScripts(am, sm);
// Turning this on and letting the INFO logging be discarded adds 0.2s to
// Nexus 9 boot time, so it's disabled by default.
if (false) DumpState();
// 确保 gsi 可用
auto is_running = android::gsi::IsGsiRunning() ? "1" : "0";
SetProperty(gsi::kGsiBootedProp, is_running);
auto is_installed = android::gsi::IsGsiInstalled() ? "1" : "0";
SetProperty(gsi::kGsiInstalledProp, is_installed);
//添加一下action
am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
am.QueueBuiltinAction(TestPerfEventSelinuxAction, "TestPerfEventSelinux");
//init有四个阶段:early-init,init,early-boot,boot
//第一阶段 early-init
am.QueueEventTrigger("early-init");
// 等待冷启动队列的完成,用来确认ueventd已经设置所有的/dev
am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
// 开始处理需要/dev的action
am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
//初始化/dev/keychord设备,调试相关
Keychords keychords;
am.QueueBuiltinAction(
[&epoll, &keychords](const BuiltinArguments& args) -> Result<void> {
for (const auto& svc : ServiceList::GetInstance()) {
keychords.Register(svc->keycodes());
}
keychords.Start(&epoll, HandleKeychord);
return {};
},
"KeychordInit");
// 第二阶段,init阶段
am.QueueEventTrigger("init");
//如果wait_for_coldboot_done没有准备好,就重复mix_hwrng_into_linux_rng
am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
// 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 {
//在非charger模式下挂着filesystems,启动core system
am.QueueEventTrigger("late-init");
}
// 在当前状态下运行所有的属性触发器
am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
// 还原优先级
setpriority(PRIO_PROCESS, 0, 0);
while (true) {
// 这里是一个死循环,主要就是处理之前添加的各种事件,如果对应的子进程挂掉,也会重启对应的子进程
auto epoll_timeout = std::optional<std::chrono::milliseconds>{};
auto shutdown_command = shutdown_state.CheckShutdown();
if (shutdown_command) {
LOG(INFO) << "Got shutdown_command '" << *shutdown_command
<< "' Calling HandlePowerctlMessage()";
HandlePowerctlMessage(*shutdown_command);
shutdown_state.set_do_shutdown(false);
}
if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {
//执行之前添加到action中的Command
am.ExecuteOneCommand();
}
if (!IsShuttingDown()) {
auto next_process_action_time = HandleProcessActions();
// 如果进程需要重启,就唤醒
if (next_process_action_time) {
epoll_timeout = std::chrono::ceil<std::chrono::milliseconds>(
*next_process_action_time - boot_clock::now());
if (*epoll_timeout < 0ms) epoll_timeout = 0ms;
}
}
if (!(prop_waiter_state.MightBeWaiting() || Service::is_exec_service_running())) {
// 如果工作没做完,就继续唤醒
if (am.HasMoreCommands()) epoll_timeout = 0ms;
}
//循环等待事件
auto pending_functions = epoll.Wait(epoll_timeout);
if (!pending_functions.ok()) {
LOG(ERROR) << pending_functions.error();
} else if (!pending_functions->empty()) {
//在处理其他功能前,先处理children,避免守护进程看到程序退出而产生init竞争
ReapAnyOutstandingChildren();
//处理等待的事件
for (const auto& function : *pending_functions) {
(*function)();
}
}
if (!IsShuttingDown()) {
HandleControlMessages();
SetUsbController();
}
}
return 0;
}
三 Epoll
关于Epoll,它的百度百科如下
epoll是Linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。
具体的定义在system/core/init/epoll.h
class Epoll {
public:
Epoll();
Result<void> Open();
Result<void> RegisterHandler(int fd, std::function<void()> handler, uint32_t events = EPOLLIN);
Result<void> UnregisterHandler(int fd);
Result<std::vector<std::function<void()>*>> Wait(
std::optional<std::chrono::milliseconds> timeout);
private:
android::base::unique_fd epoll_fd_;
std::map<int, std::function<void()>> epoll_handlers_;
};
在初始化中,调用了两个函数
//设置子进程退出的信号处理函数
InstallSignalFdHandler(&epoll);
//设置属性更改的通知函数
InstallInitNotifier(&epoll);
InstallSignalFdHandler
注册子进程的SIGCHLD信号来监听子进程的运行状况,如果子进程挂断,那么就就移除或者重启挂掉的子进程而避免它成为僵尸进程
[init.cpp]
static void InstallSignalFdHandler(Epoll* epoll) {
...
// Register a handler to unblock signals in the child processes.
const int result = pthread_atfork(nullptr, nullptr, &UnblockSignals);
if (result != 0) {
LOG(FATAL) << "Failed to register a fork handler: " << strerror(result);
}
signal_fd = signalfd(-1, &mask, SFD_CLOEXEC);
if (signal_fd == -1) {
PLOG(FATAL) << "failed to create signalfd";
}
//注册signal_fd事件
if (auto result = epoll->RegisterHandler(signal_fd, HandleSignalFd); !result.ok()) {
LOG(FATAL) << result.error();
}
}
InstallInitNotifier
注册一个wake_main_thread_fd事件的监听
[init.cpp]
static void InstallInitNotifier(Epoll* epoll) {
wake_main_thread_fd = eventfd(0, EFD_CLOEXEC);
if (wake_main_thread_fd == -1) {
PLOG(FATAL) << "Failed to create eventfd for waking init";
}
auto clear_eventfd = [] {
uint64_t counter;
TEMP_FAILURE_RETRY(read(wake_main_thread_fd, &counter, sizeof(counter)));
};
if (auto result = epoll->RegisterHandler(wake_main_thread_fd, clear_eventfd); !result.ok()) {
LOG(FATAL) << result.error();
}
}
四 Android Init Language
当前面的几步做完之后,就需要来加载init.rc的相关文件了,在android 10中,rc文件有多个,这些rc文件是通过AIL(Android Init Language)语言编写的,关于AIL的官方文档在这里
五 zygote
LoadBootScripts
LoadBootScripts是通过解析器Parser对rc文件进行解析,比较常见的有Action、Command、import等
[init.cpp]
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
Parser parser = CreateParser(action_manager, service_list);
//获取rc文件的值,默认是空
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 is available only in Q and earlier release. As we don't
// have system_ext in those versions, skip late_import for system_ext.
parser.ParseConfig("/system_ext/etc/init");
if (!parser.ParseConfig("/product/etc/init")) {
late_import_paths.emplace_back("/product/etc/init");
}
if (!parser.ParseConfig("/odm/etc/init")) {
late_import_paths.emplace_back("/odm/etc/init");
}
if (!parser.ParseConfig("/vendor/etc/init")) {
late_import_paths.emplace_back("/vendor/etc/init");
}
} else {
parser.ParseConfig(bootscript);
}
}
//创建解析器
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
Parser parser;
parser.AddSectionParser("service", std::make_unique<ServiceParser>(
&service_list, GetSubcontext(), std::nullopt));
parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, GetSubcontext()));
parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
return parser;
}
rc相关文件都在system/core/rootdir/init.rc目录下,因为这里有多个zygote文件,所以它就会通过import导入对应的zygote文件,然后再启动Zygote
[init.rc]
import /init.${ro.zygote}.rc
[init.zygote64.rc]
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks