进入用户空间
在kernel中通过run_init_process来执行init进程,之后就会进入system/core/init/init.cpp的main函数,这才真正的进入用户空间。
进入main函数后,会进行判断是否是系统启动的第一阶段,只有启动参数中有--second-stage才为第二阶段
bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
如果现在为系统启动的第一阶段, 就开始获取基本的文件系统,我们需要将他们放在一起处理。挂载文件系统到相应的目录。
// Get the basic filesystem setup we need put together in the initramdisk
// on / and then we'll let the rc file figure out the rest.
if (is_first_stage) {
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
#define MAKE_STR(x) __STRING(x)
mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
mount("sysfs", "/sys", "sysfs", 0, NULL);
}
对klog进行初始化,设置klog level为NOTICE,所以可以将NOTICE级别的log输出,而INFO级别的log就打印不出来
具体原因,请阅读Android7.0 klog机制
klog_init();
klog_set_level(KLOG_NOTICE_LEVEL);
系统启动流程的关键log来了,可以通过该行log知道init进程启动起来了,也表示kernel启动结束。大家注意klog level为NOTICE所以可以打印出来。
NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage");
//示例log , 我们可以通过时间戳2.042999s, 获得从开始启动kernel到进入init花费多长时间,也就是开机过程中kernel耗时情况。
[01-01 08:26:55.194] <13>[ 2.042999] c3 init: init first stage started!
如果为第一阶段的话会对selinux进行初始化
// Set up SELinux, including loading the SELinux policy if we're in the kernel domain.
selinux_initialize(is_first_stage);
selinux初始化函数,我们可以修改该函数,本地手动开关selinux来调试问题。
static void selinux_initialize(bool in_kernel_domain) {
Timer t; //使用Timer计时,计算selinux初始化耗时
selinux_callback cb;
cb.func_log = selinux_klog_callback;
selinux_set_callback(SELINUX_CB_LOG, cb);
cb.func_audit = audit_callback;
selinux_set_callback(SELINUX_CB_AUDIT, cb);
if (in_kernel_domain) { //第一阶段in_kernel_domain为true
INFO("Loading SELinux policy...\n"); //该行log打印不出,INFO级别
if (selinux_android_load_policy() < 0) {
ERROR("failed to load policy: %s\n", strerror(errno));
security_failure();
}
bool kernel_enforcing = (security_getenforce() == 1);
bool is_enforcing = selinux_is_enforcing();
if (kernel_enforcing != is_enforcing) {
if (security_setenforce(is_enforcing)) { //设置selinux的模式,是开还是关
ERROR("security_setenforce(%s) failed: %s\n",
is_enforcing ? "true" : "false", strerror(errno));
security_failure();
}
}
if (write_file("/sys/fs/selinux/checkreqprot", "0") == -1) {
security_failure();
}
NOTICE("(Initializing SELinux %s took %.2fs.)\n",
is_enforcing ? "enforcing" : "non-enforcing", t.duration()); //输出selinux的模式,与初始化耗时
} else {
selinux_init_all_handles(); //如果启动第二阶段,调用该函数
}
}
重新执行init,从kernel domain转变为init domain
// If we're in the kernel domain, re-exec init to transition to the init domain now
// that the SELinux policy has been loaded.
if (is_first_stage) {
if (restorecon("/init") == -1) {
ERROR("restorecon failed: %s\n", strerror(errno));
security_failure();
}
char* path = argv[0];
char* args[] = { path, const_cast("--second-stage"), nullptr }; //设置参数--second-stage
if (execv(path, args) == -1) { //执行init进程,重新进入main函数
ERROR("execv(\"%s\") failed: %s\n", path, strerror(errno));
security_failure();
}
}
输出第二阶段开始log信息
[01-01 08:26:55.197] <13>[ 2.238403] c0 init: init second stage started!
if (!is_first_stage) {
// Indicate that booting is in progress to background fw loaders, etc.
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
property_init(); //属性服务初始化
// If arguments are passed both on the command line and in DT,
// properties set in DT always have priority over the command-line ones.
process_kernel_dt();
process_kernel_cmdline();
// Propagate the kernel variables to internal variables
// used by init as well as the current required properties.
export_kernel_boot_props();
}
需要区分第一阶段第二阶段的代码已经执行完毕,下面就执行init进程中比较核心的代码。
对相关/dev进行重置上下文
NOTICE("Running restorecon...\n");
restorecon("/dev");
restorecon("/dev/socket");
restorecon("/dev/__properties__");
restorecon("/property_contexts");
restorecon_recursive("/sys");
通过BuiltinFunctionMap匹配命令与函数之间的对应关系
const BuiltinFunctionMap function_map;
Action::set_function_map(&function_map); //在Action中保存function_map对象,记录了命令与函数之间的对应关系
相关代码位置system/core/init/builtins.cpp
BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits::max();
static const Map builtin_functions = {
{"bootchart_init", {0, 0, do_bootchart_init}},
{"chmod", {2, 2, do_chmod}},
{"chown", {2, 3, do_chown}},
{"class_reset", {1, 1, do_class_reset}},
{"class_start", {1, 1, do_class_start}},
{"class_stop", {1, 1, do_class_stop}},
{"copy", {2, 2, do_copy}},
{"domainname", {1, 1, do_domainname}},
{"enable", {1, 1, do_enable}},
{"exec", {1, kMax, do_exec}},
{"export", {2, 2, do_export}},
{"hostname", {1, 1, do_hostname}},
{"ifup", {1, 1, do_ifup}},
{"init_user0", {0, 0, do_init_user0}},
{"insmod", {1, kMax, do_insmod}},
{"installkey", {1, 1, do_installkey}},
{"load_persist_props", {0, 0, do_load_persist_props}},
{"load_system_props", {0, 0, do_load_system_props}},
{"loglevel", {1, 1, do_loglevel}},
{"mkdir", {1, 4, do_mkdir}},
{"mount_all", {1, kMax, do_mount_all}},
{"mount", {3, kMax, do_mount}},
{"powerctl", {1, 1, do_powerctl}},
{"restart", {1, 1, do_restart}},
{"restorecon", {1, kMax, do_restorecon}},
{"restorecon_recursive", {1, kMax, do_restorecon_recursive}},
{"rm", {1, 1, do_rm}},
{"rmdir", {1, 1, do_rmdir}},
{"setprop", {2, 2, do_setprop}},
{"setrlimit", {3, 3, do_setrlimit}},
{"start", {1, 1, do_start}},
{"stop", {1, 1, do_stop}},
{"swapon_all", {1, 1, do_swapon_all}},
{"symlink", {2, 2, do_symlink}},
{"sysclktz", {1, 1, do_sysclktz}},
{"trigger", {1, 1, do_trigger}},
{"verity_load_state", {0, 0, do_verity_load_state}},
{"verity_update_state", {0, 0, do_verity_update_state}},
{"wait", {1, 2, do_wait}},
{"write", {2, 2, do_write}},
{"pipe", {2, 2, do_pipe}},
};
return builtin_functions;
重新回到init.cpp中继续分析,7.0使用了面向对象中的多态来管理各个section。与之前版本有所不同。
Parser& parser = Parser::GetInstance(); //获取Paser实例
parser.AddSectionParser("service",std::make_unique()); //增加ServiceParser为一个section,对应name为service
parser.AddSectionParser("on", std::make_unique()); //增加ActionParser为一个section,对应name为action
parser.AddSectionParser("import", std::make_unique()); //增加ImportParser为一个section,对应name为import
开始init进程的重头戏,解析init.rc文件
parser.ParseConfig("/init.rc");
详细流程请阅读解析init.rc文件
ActionManager& am = ActionManager::GetInstance(); //获取ActionManager对象,需要通过am对命令执行顺序进行控制
am.QueueEventTrigger("early-init"); //添加触发器early-init
// Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done"); //添加命令与触发器
// ... so that we can start queuing up actions that require stuff from /dev.
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
#if defined(__aarch64__)
am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
#endif
am.QueueBuiltinAction(keychord_init_action, "keychord_init");
am.QueueBuiltinAction(console_init_action, "console_init");
// Trigger all the boot actions to get us started.
am.QueueEventTrigger("init"); //添加触发器init
// Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
// wasn't ready immediately after wait_for_coldboot_done
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
// Don't mount filesystems or start core system services in charger mode.
std::string bootmode = property_get("ro.bootmode"); //获取启动模式
if (bootmode == "charger") {
am.QueueEventTrigger("early-fs");
am.QueueEventTrigger("fs");
am.QueueEventTrigger("post-fs");
am.QueueEventTrigger("charger");
} else {
am.QueueEventTrigger("late-init"); //非充电模式直接添加触发器late-init
}
// Run all property triggers based on current state of the properties.
am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
void ActionManager::QueueEventTrigger(const std::string& trigger) {
trigger_queue_.push(std::make_unique(trigger)); //将trigger push到trigger_queue队尾
}
void ActionManager::QueueBuiltinAction(BuiltinFunction func,
const std::string& name) {
auto action = std::make_unique(true);
std::vector name_vector{name};
if (!action->InitSingleTrigger(name)) {
return;
}
action->AddCommand(func, name_vector); //将对应命令加入commands_列表
trigger_queue_.push(std::make_unique(action.get())); //将trigger push到trigger_queue_队尾
actions_.emplace_back(std::move(action)); //将action加入action_列表
}
void Action::AddCommand(BuiltinFunction f,
const std::vector& args,
const std::string& filename, int line) {
commands_.emplace_back(f, args, filename, line); //将函数加入commands_中
}
之后init就根据这些trigger的顺利进行执行。
系统进入一个无限循环执行命令启动服务。
while (true) {
if (!waiting_for_exec) {
am.ExecuteOneCommand(); //执行一个命令
restart_processes(); //重启死去的服务
}
int timeout = -1;
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
if (am.HasMoreCommands()) {
timeout = 0;
}
bootchart_sample(&timeout);
epoll_event ev;
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
if (nr == -1) {
ERROR("epoll_wait failed: %s\n", strerror(errno));
} else if (nr == 1) {
((void (*)()) ev.data.ptr)();
}
}
system/core/init/action.cpp
void ActionManager::ExecuteOneCommand() {
// Loop through the trigger queue until we have an action to execute
while (current_executing_actions_.empty() && !trigger_queue_.empty()) { //当前没有可执行action,并且trigger_queue_不为空
for (const auto& action : actions_) {
if (trigger_queue_.front()->CheckTriggers(*action)) {
current_executing_actions_.emplace(action.get());
}
}
trigger_queue_.pop(); //从trigger_queue_中出栈
}
if (current_executing_actions_.empty()) {
return;
}
auto action = current_executing_actions_.front(); //获取当前需要执行的action
if (current_command_ == 0) {
std::string trigger_name = action->BuildTriggersString();
INFO("processing action (%s)\n", trigger_name.c_str());
}
action->ExecuteOneCommand(current_command_); //调用action的ExecuteOneCommand函数
// If this was the last command in the current action, then remove
// the action from the executing list.
// If this action was oneshot, then also remove it from actions_.
++current_command_;
if (current_command_ == action->NumCommands()) {
current_executing_actions_.pop();
current_command_ = 0;
if (action->oneshot()) {
auto eraser = [&action] (std::unique_ptr& a) {
return a.get() == action;
};
actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
}
}
}
void Action::ExecuteOneCommand(std::size_t command) const {
ExecuteCommand(commands_[command]);
}
void Action::ExecuteCommand(const Command& command) const {
Timer t;
int result = command.InvokeFunc(); //执行命令
if (klog_get_level() >= KLOG_INFO_LEVEL) {
std::string trigger_name = BuildTriggersString();
std::string cmd_str = command.BuildCommandString();
std::string source = command.BuildSourceString();
INFO("Command '%s' action=%s%s returned %d took %.2fs\n",
cmd_str.c_str(), trigger_name.c_str(), source.c_str(), //由于INFO的log输不出来,我们可以改为NOTICE,这样就可以将具体执行哪个命令耗时多少打印出。
result, t.duration());
}
}
int Command::InvokeFunc() const {
std::vector expanded_args;
expanded_args.resize(args_.size());
expanded_args[0] = args_[0];
for (std::size_t i = 1; i < args_.size(); ++i) {
if (!expand_props(args_[i], &expanded_args[i])) {
ERROR("%s: cannot expand '%s'\n", args_[0].c_str(), args_[i].c_str());
return -EINVAL;
}
}
return func_(expanded_args); //获取命令对应的函数,执行函数。
}