Android7.0探索之旅--init进程

进入用户空间

在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对命令执行顺序进行控制

init执行命令触发器主要分为early-init,init,late-init,boot等。

    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");

system/core/init/action.cpp

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);              //获取命令对应的函数,执行函数。
}


你可能感兴趣的:(Android启动流程)