美文网首页Android系统源码学习
android init进程--init.rc解析过程与执行

android init进程--init.rc解析过程与执行

作者: 覆水无言 | 来源:发表于2019-12-15 20:03 被阅读0次

    android源码学习目录

    \color{#ea4335}{请先阅读:}

    1.init.rc的解析

    从文章android init进程可以看出,init.rc的解析是从init进程main函数中进行的。

        //android 8.0
        //init进程main函数解析init.rc代码。 
        //Parser init.rc文件的解析入口  /system/core/init/init_parse.cpp
        Parser& parser = Parser::GetInstance();
        // 1 为解析类添加解析能力
        parser.AddSectionParser("service",std::make_unique<ServiceParser>());
        parser.AddSectionParser("on", std::make_unique<ActionParser>());
        parser.AddSectionParser("import", std::make_unique<ImportParser>());
        std::string bootscript = GetProperty("ro.boot.init_rc", "");  //2 环境变量里是否有ro.boot.init_rc
        if (bootscript.empty()) {
            parser.ParseConfig("/init.rc");  //3 解析
            parser.set_is_system_etc_init_loaded(
                    parser.ParseConfig("/system/etc/init"));  //解析system/etc/init文件夹下左右的rc文件。
            parser.set_is_vendor_etc_init_loaded(
                    parser.ParseConfig("/vendor/etc/init"));
            parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
        } else {
            parser.ParseConfig(bootscript);
            parser.set_is_system_etc_init_loaded(true);
            parser.set_is_vendor_etc_init_loaded(true);
            parser.set_is_odm_etc_init_loaded(true);
        }
    
    

    这是Android init进程解析init.rc文件的代码,

    1. Parser是init.rc类文件解析的入口,parser.AddSectionParser()函数是为了添加init.rc类文件解析的能力,会根据init.rc文件每一行的内容选择不同的处理器eg:ActionParser,
    2. 代码2处是判断是否有启动配置脚本,按照是否有来进行解析,一般都是系统默认的,没有启动配置脚本使用Android系统的init.rc进行解析,解析在代码3处,ParseConfig函数就是解析函数
     //代码位置 /system/core/init/init_parse.cpp
    bool Parser::ParseConfig(const std::string& path) {
        if (is_dir(path.c_str())) {
            return ParseConfigDir(path);
        }
        return ParseConfigFile(path);   //进行文件解析,解析的是init.rc
    }
    
    
    bool Parser::ParseConfigFile(const std::string& path) {
        LOG(INFO) << "Parsing file " << path << "...";
        Timer t;
        std::string data;
        if (!read_file(path, &data)) {  //将文件内容读取到data里,
            return false;
        }
    
        data.push_back('\n'); // TODO: fix parse_config.
        ParseData(path, data);  //内容解析函数,分派给各个解析类eg:ActionParse
        for (const auto& sp : section_parsers_) {
            sp.second->EndFile(path);
        }
        LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";
        return true;
    }
    
    
    void Parser::ParseData(const std::string& filename, const std::string& data) {
        //TODO: Use a parser with const input and remove this copy
        std::vector<char> data_copy(data.begin(), data.end());
        data_copy.push_back('\0');
    
        parse_state state;   //解析过程使用的结构体,/system/core/init/parse.h parse.cpp
        state.filename = filename.c_str();
        state.line = 0;
        state.ptr = &data_copy[0];
        state.nexttoken = 0;
    
        SectionParser* section_parser = nullptr;
        std::vector<std::string> args;
    
        for (;;) {
            switch (next_token(&state)) {// 更具next_token读取state里的内容
            case T_EOF:
                if (section_parser) {
                    section_parser->EndSection(); //结束一个文件的分析,
                }
                return;
            case T_NEWLINE:   //分析每一行的命令
                state.line++;
                if (args.empty()) {
                    break;
                }
                if (section_parsers_.count(args[0])) {
                    if (section_parser) {
                        section_parser->EndSection();
                    }
                     //根据args[0]也就是每个init.rc执行逻辑的第一个参数,选取解析的类,选我们之前添加的ActionParse等
                    section_parser = section_parsers_[args[0]].get();
                    std::string ret_err;
                    if (!section_parser->ParseSection(args, &ret_err)) {  
                        parse_error(&state, "%s\n", ret_err.c_str());
                        section_parser = nullptr;
                    }
                } else if (section_parser) {
                    std::string ret_err;
                    if (!section_parser->ParseLineSection(args, state.filename,
                                                          state.line, &ret_err)) {  //解析一行
                        parse_error(&state, "%s\n", ret_err.c_str());
                    }
                }
                args.clear();
                break;
            case T_TEXT:
                args.emplace_back(state.text);
                break;
            }
        }
    }
    

    从上面代码可以看出parseData函数对init.rc进行了读取与处理,它根据读取的内容的每个模块(eg:Action是on)选择解析需要的Parse,后对init.rc中每个模块的每一行进行了解析。

    1.1:实际解析类的分析

    位置/system/core/init/action.cpp ActionParse

    //负责根据读取的args,生成代码类中的action
    bool ActionParser::ParseSection(const std::vector<std::string>& args,
                                    std::string* err) {
        std::vector<std::string> triggers(args.begin() + 1, args.end());
        if (triggers.size() < 1) {
            *err = "actions must have a trigger";
            return false;
        }
    
        auto action = std::make_unique<Action>(false);
        if (!action->InitTriggers(triggers, err)) {
            return false;
        }
    
        action_ = std::move(action);
        return true;
    }
    
    //解析一行指令,将command加入到它所属于的action
    bool ActionParser::ParseLineSection(const std::vector<std::string>& args,
                                        const std::string& filename, int line,
                                        std::string* err) const {
        return action_ ? action_->AddCommand(args, filename, line, err) : false;
    }
    
    //一个action解析结束,将解析的action添加到ActionManager中。
    void ActionParser::EndSection() {
        if (action_ && action_->NumCommands() > 0) {
            ActionManager::GetInstance().AddAction(std::move(action_));
        }
    }
    

    上述代码是构建action和保存action的处理,到这里init.rc的一个action就解析完了。ActionManager是所有action的管理类,所有解析的action都使用一个 std::vector<std::unique_ptr<Action>> actions_ 集合保存下来。

    2.Action的执行。

        //1 执行action与函数绑定 /system/core/init/builtins.cpp
        const BuiltinFunctionMap function_map;
        Action::set_function_map(&function_map);
      ....
    
        //2 这里就是上文对action解析之后形成的ActionManager类, 
        ActionManager& am = ActionManager::GetInstance();
        //执行early-init的action
        am.QueueEventTrigger("early-init");
    
        //查询手写action是否已执行
        // 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");
        am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
        am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict");
        am.QueueBuiltinAction(keychord_init_action, "keychord_init");
        am.QueueBuiltinAction(console_init_action, "console_init");
    
        // Trigger all the boot actions to get us started.
        //执行action init
        am.QueueEventTrigger("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 = GetProperty("ro.bootmode", "");  //查询现在启动的模式
        if (bootmode == "charger") {
            am.QueueEventTrigger("charger");    //在充电执行action charger
        } else {
            am.QueueEventTrigger("late-init");  //没有充电执行action late-init
        }
    
        // Run all property triggers based on current state of the properties.
        am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
    
        while (true) {   //开始循环,执行actionManager中的每个action
            // By default, sleep until something happens.
            int epoll_timeout_ms = -1;
    
            if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
                am.ExecuteOneCommand(); // 执行action的command
            }
            if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
                restart_processes();  //.rc文件中的service, 与actionManager类似由ServiceManager管理。
    
                // If there's a process that needs restarting, wake up in time for that.
                if (process_needs_restart_at != 0) {
                    epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;
                    if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
                }
    
                // If there's more work to do, wake up again immediately.
                if (am.HasMoreCommands()) epoll_timeout_ms = 0;
            }
    
            epoll_event ev;
            int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
            if (nr == -1) {
                PLOG(ERROR) << "epoll_wait failed";
            } else if (nr == 1) {
                ((void (*)()) ev.data.ptr)(); //3
            }
        }
    
    • 注释1处action与执行函数进行绑定,就是执行那个action就执行那个函数,函数内容是在/system/core/init/builtins.cpp文件中。
    • 在就是执行action,和循环遍历执行全部的action,
    • 代码3处用是用了epoll句柄(即epoll_fd)主要监听子进程结束,及其它进程设置系统属性的请求.这里会处理action启动的进程如果死了会收到进程终止信号量,在进行重启进程。了解android init进程

    相关文章

      网友评论

        本文标题:android init进程--init.rc解析过程与执行

        本文链接:https://www.haomeiwen.com/subject/rfslnctx.html