• Android 12 init(2) rc脚本解析和事件执行流程


    文章托管在gitee上 Android Notes , 同步csdn
    本文基于Android12 分析

    在init启动的SecondStage,通过调用LoadBootScripts来解析启动脚本,也就是rc文件。下面来研究这个解析过程,之后再看看init如何处理事件并执行相关action的。

    SecondStageMain

    int SecondStageMain(int argc, char** argv) {
      ...
      const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
      Action::set_function_map(&function_map); // 设置 Action 需要的函数映射表
      ...
      InitializeSubcontext(); // 初始化Subcontext
    
      ActionManager& am = ActionManager::GetInstance(); // 创建action管理器
      ServiceList& sm = ServiceList::GetInstance(); // 创建服务管理列表
    
      LoadBootScripts(am, sm); // 加载并解析启动脚本
      ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    InitializeSubcontext

    创建subcontext进程,用于执行init交给其的一些任务(比如后面执行的某些Command),通过socket与init进行通信

    /// @system/core/init/subcontext.cpp
    void InitializeSubcontext() {
        if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_P__) {
            subcontext.reset( // 创建Subcontext, path_prefixes为"/vendor", "/odm"
                    new Subcontext(std::vector<std::string>{"/vendor", "/odm"}, kVendorContext));
        }
    }
    
    /// @system/core/init/subcontext.h
    Subcontext(std::vector<std::string> path_prefixes, std::string context, bool host = false)
        : path_prefixes_(std::move(path_prefixes)), context_(std::move(context)), pid_(0) {
        if (!host) { /// host默认为false
            Fork(); // 创建subcontext进程
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    LoadBootScripts

    加载并解析 init rc 脚本

    /// @system/core/init/init.cpp
    static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
        // 创建 Parser 对象
        Parser parser = CreateParser(action_manager, service_list);
    
        std::string bootscript = GetProperty("ro.boot.init_rc", "");//获取属性指定的rc
        if (bootscript.empty()) { // 没有指定rc,解析默认位置
            parser.ParseConfig("/system/etc/init/hw/init.rc"); // 首先解析 init.rc
            if (!parser.ParseConfig("/system/etc/init")) { // 解析 /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"); // 解析 /system_ext/etc/init 目录
            if (!parser.ParseConfig("/vendor/etc/init")) { // 解析 /vendor/etc/init 目录
                late_import_paths.emplace_back("/vendor/etc/init");
            }
            if (!parser.ParseConfig("/odm/etc/init")) { // 解析 /odm/etc/init 目录
                late_import_paths.emplace_back("/odm/etc/init");
            }
            if (!parser.ParseConfig("/product/etc/init")) { // 解析 /product/etc/init 目录
                late_import_paths.emplace_back("/product/etc/init");
            }
        } else {
            parser.ParseConfig(bootscript);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    CreateParser

    /// @system/core/init/init.cpp
    Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
        Parser parser;
        // 添加各部分解析器
        // 创建ServiceParser 解析 service 服务,用于管理和启动native进程
        parser.AddSectionParser("service", std::make_unique<ServiceParser>(
                                                   &service_list, GetSubcontext(), std::nullopt));
        // 创建ActionParser 解析 on action , 定义的一些动作                                           
        parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, GetSubcontext()));
        // ImportParser解析import, 导入其他rc
        parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
    
        return parser;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    AddSectionParser按名称添加parser到集合

    /// @system/core/init/parser.cpp
    void Parser::AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser) {
        section_parsers_[name] = std::move(parser); // 按名称存储对应的parser
    }
    // 集合按名字存储对应的 SectionParser
    std::map<std::string, std::unique_ptr<SectionParser>> section_parsers_;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    接下来看解析流程,通过调用Parser::ParseConfig函数来实现解析指定路径的rc文件或目录下的rc文件。

    Parser::ParseConfig

    /// @system/core/init/parser.cpp
    bool Parser::ParseConfig(const std::string& path) {
        if (is_dir(path.c_str())) { // 如果提供的目录
            return ParseConfigDir(path); // 解析配置目录
        }
        return ParseConfigFile(path);  // 解析配置文件
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Parser::ParseConfigDir

    执行解析配置目录操作,遍历目录调用ParseConfigFile解析每一个文件。忽略目录下的子目录,也就是不支持多层级目录。

    /// @system/core/init/parser.cpp
    bool Parser::ParseConfigDir(const std::string& path) {
        LOG(INFO) << "Parsing directory " << path << "...";
        std::unique_ptr<DIR, decltype(&closedir)> config_dir(opendir(path.c_str()), closedir);
        if (!config_dir) {
            PLOG(INFO) << "Could not import directory '" << path << "'";
            return false;
        }
        dirent* current_file;
        std::vector<std::string> files;
        while ((current_file = readdir(config_dir.get()))) { // 读取目录下的内容
            // Ignore directories and only process regular files.
            if (current_file->d_type == DT_REG) { // 如果是文件则添加到待解析集合
                std::string current_path =
                    android::base::StringPrintf("%s/%s", path.c_str(), current_file->d_name);
                files.emplace_back(current_path);
            }
        }
        // Sort first so we load files in a consistent order (bug 31996208)
        std::sort(files.begin(), files.end());
        for (const auto& file : files) { // 遍历集合,解析文件
            if (!ParseConfigFile(file)) {
                LOG(ERROR) << "could not import file '" << file << "'";
            }
        }
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    接下来看如何解析一个配置文件

    Parser::ParseConfigFile

    /// @system/core/init/parser.cpp
    bool Parser::ParseConfigFile(const std::string& path) {
        LOG(INFO) << "Parsing file " << path << "...";
        android::base::Timer t;
        // 读取文件内容到string,实现在system/core/init/util.cpp,调用 android::base::ReadFdToString
        auto config_contents = ReadFile(path);
        if (!config_contents.ok()) {
            LOG(INFO) << "Unable to read config file '" << path << "': " << config_contents.error();
            return false;
        }
    
        ParseData(path, &config_contents.value()); // 解析脚本内容
    
        LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    Parser::ParseData

    解析流程循环:

    • 获取的下一个token来决定接下来的动作,比如EOF结尾或者某个关键字
    • 遇到T_EOF则调用EndSection结束当前解析的ParseSection,退出循环
    • 遇到T_NEWLINE换新行,则进行解析一行
    • 如果获取的token是parser对应的关键字,比如on,则获取对应的parser进行解析,调用ParseSection
    • 如果token不是关键字,且上一步有获取parser,则进行解析一行,调用ParseLineSection
    • 遇到下一个关键字则调用EndSection结束当前解析的ParseSection,开启新的解析
    • 如果解析到文本,则添加到args集合
    void Parser::ParseData(const std::string& filename, std::string* data) {
        data->push_back('\n'); // 添加一个换行
        data->push_back('\0'); // 添加一个结束符
    
        parse_state state;
        state.line = 0;
        state.ptr = data->data();
        state.nexttoken = 0;
    
        SectionParser* section_parser = nullptr;
        int section_start_line = -1;
        std::vector<std::string> args;
    
        // If we encounter a bad section start, there is no valid parser object to parse the subsequent
        // sections, so we must suppress errors until the next valid section is found.
        bool bad_section_found = false;
    
        auto end_section = [&] { // 结束section的回调
            bad_section_found = false;
            if (section_parser == nullptr) return;
    
            if (auto result = section_parser->EndSection(); !result.ok()) {
                parse_error_count_++;
                LOG(ERROR) << filename << ": " << section_start_line << ": " << result.error();
            }
    
            section_parser = nullptr;
            section_start_line = -1;
        };
    
        for (;;) {
            switch (next_token(&state)) { // 根据获取的下一个token来决定接下来的动作
                case T_EOF: // 文件结束。
                    end_section();
    
                    for (const auto& [section_name, section_parser] : section_parsers_) {
                        section_parser->EndFile();
                    }
    
                    return;
                case T_NEWLINE: { // 检测到换行,解析当前行
                    state.line++;
                    if (args.empty()) break;
                    // If we have a line matching a prefix we recognize, call its callback and unset any
                    // current section parsers.  This is meant for /sys/ and /dev/ line entries for
                    // uevent.
                    auto line_callback = std::find_if(
                        line_callbacks_.begin(), line_callbacks_.end(),
                        [&args](const auto& c) { return android::base::StartsWith(args[0], c.first); });
                    if (line_callback != line_callbacks_.end()) { // 针对指定prefix的情况,比如 /dev/
                        end_section();
    
                        if (auto result = line_callback->second(std::move(args)); !result.ok()) {
                            parse_error_count_++;
                            LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
                        }
                    } else if (section_parsers_.count(args[0])) { // 如果第一个值能够匹配到parser, 比如是 service
                        end_section(); // 结束之前。
                        section_parser = section_parsers_[args[0]].get();
                        section_start_line = state.line;
                        if (auto result = // 解析 section
                                    section_parser->ParseSection(std::move(args), filename, state.line);
                            !result.ok()) {
                            parse_error_count_++;
                            LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
                            section_parser = nullptr;
                            bad_section_found = true;
                        }
                    } else if (section_parser) { // 使用当前parser解析一行
                        if (auto result = section_parser->ParseLineSection(std::move(args), state.line);
                            !result.ok()) {
                            parse_error_count_++;
                            LOG(ERROR) << filename << ": " << state.line << ": " << result.error();
                        }
                    } else if (!bad_section_found) { // 没有任何匹配,则表示关键字错误
                        parse_error_count_++;
                        LOG(ERROR) << filename << ": " << state.line
                                   << ": Invalid section keyword found";
                    }
                    args.clear();
                    break;
                }
                case T_TEXT: // 是文本则添加到vector
                    args.emplace_back(state.text);
                    break;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    next_token

    该函数是用来解析token的,并获取有效的文本信息

    /// @system/core/init/tokenizer.cpp
    int next_token(struct parse_state *state)
    {
        char *x = state->ptr;
        char *s;
    
        if (state->nexttoken) {
            int t = state->nexttoken;
            state->nexttoken = 0;
            return t;
        }
    
        for (;;) {
            switch (*x) {
            case 0: // 结尾
                state->ptr = x;
                return T_EOF;
            case '\n': // 换行符
                x++;
                state->ptr = x;
                return T_NEWLINE;
            case ' ':
            case '\t':
            case '\r': // 跳过空白字符
                x++;
                continue;
            case '#':
                while (*x && (*x != '\n')) x++; // 跳过 # 注释行
                if (*x == '\n') { // 换行
                    state->ptr = x+1;
                    return T_NEWLINE;
                } else { // 结尾
                    state->ptr = x;
                    return T_EOF;
                }
            default: // 默认跳转到文本处理
                goto text;
            }
        }
    
    textdone:
        state->ptr = x;
        *s = 0;
        return T_TEXT;
    text:
        state->text = s = x;
    textresume:
        for (;;) {
            switch (*x) {
            case 0: // 字符结束符
                goto textdone;
            case ' ':
            case '\t':
            case '\r': // 检测到空白符则返回
                x++;
                goto textdone;
            case '\n': // 换行
                state->nexttoken = T_NEWLINE;
                x++;
                goto textdone;
            case '"': // 引号包裹内存
                x++;
                for (;;) {
                    switch (*x) {
                    case 0:
                            /* unterminated quoted thing */
                        state->ptr = x;
                        return T_EOF;
                    case '"':
                        x++;
                        goto textresume;
                    default:
                        *s++ = *x++; // 复制引号内容
                    }
                }
                break;
            case '\\':  // 下面处理其他转义字符
                x++;
                switch (*x) {
                case 0:
                    goto textdone;
                case 'n':
                    *s++ = '\n';
                    x++;
                    break;
                case 'r':
                    *s++ = '\r';
                    x++;
                    break;
                case 't':
                    *s++ = '\t';
                    x++;
                    break;
                case '\\':
                    *s++ = '\\';
                    x++;
                    break;
                case '\r':
                        /* \   -> line continuation */
                    if (x[1] != '\n') {
                        x++;
                        continue;
                    }
                    x++;
                    FALLTHROUGH_INTENDED;
                case '\n':
                        /* \  -> line continuation */
                    state->line++;
                    x++;
                        /* eat any extra whitespace */
                    while((*x == ' ') || (*x == '\t')) x++;
                    continue;
                default:
                        /* unknown escape -- just copy */
                    *s++ = *x++;
                }
                continue;
            default:
                *s++ = *x++;
            }
        }
        return T_EOF;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123

    接下来以解析on为例来分析,看关键字对应的是ActionParser

    ActionParser::ParseSection

    /// @system/core/init/action_parser.cpp
    Result<void> ActionParser::ParseSection(std::vector<std::string>&& args,
                                            const std::string& filename, int line) {
        std::vector<std::string> triggers(args.begin() + 1, args.end()); // 除了on的其他参数
        if (triggers.size() < 1) { // on 后面需要指定trigger
            return Error() << "Actions must have a trigger";
        }
    
        Subcontext* action_subcontext = nullptr;
        // 检查路径是否匹配path_prefixes_中的路径前缀 /vendor, /odm
        if (subcontext_ && subcontext_->PathMatchesSubcontext(filename)) {
            action_subcontext = subcontext_; // 前缀匹配会获取到 subcontext_
        }
    
        std::string event_trigger;
        std::map<std::string, std::string> property_triggers;
    
        if (auto result = // 解析 trigger
                    ParseTriggers(triggers, action_subcontext, &event_trigger, &property_triggers);
            !result.ok()) {
            return Error() << "ParseTriggers() failed: " << result.error();
        }
        // 创建该action对象,第一个参数false表示非oneshot,
        auto action = std::make_unique<Action>(false, action_subcontext, filename, line, event_trigger,
                                               property_triggers);
    
        action_ = std::move(action); // 缓存此解析的action,后续解析line的时候会用到
        return {};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    ParseTriggers

    以解析 on post-fs-data && property:ro.debuggable=1 为例分析,args 就是on 之后的内容。

    Result<void> ParseTriggers(const std::vector<std::string>& args, Subcontext* subcontext,
                               std::string* event_trigger,
                               std::map<std::string, std::string>* property_triggers) {
        const static std::string prop_str("property:");//属性触发器前缀
        for (std::size_t i = 0; i < args.size(); ++i) {
            if (args[i].empty()) {
                return Error() << "empty trigger is not valid";
            }
    
            if (i % 2) { // 按 && 将各个触发器连接起来,奇数位的是 &&
                if (args[i] != "&&") {
                    return Error() << "&& is the only symbol allowed to concatenate actions";
                } else {
                    continue;
                }
            }
            // property: 开头的是属性触发器
            if (!args[i].compare(0, prop_str.length(), prop_str)) {
                if (auto result = ParsePropertyTrigger(args[i], subcontext, property_triggers); // 解析属性触发器
                    !result.ok()) {
                    return result;
                }
            } else { // 否则是事件触发器,比如 post-fs-data
                if (!event_trigger->empty()) { // 只能指定一个事件触发器
                    return Error() << "multiple event triggers are not allowed";
                }
                // 检查组成字符合法性,通常只能由 _ 、- 、数字或字母 组成
                if (auto result = ValidateEventTrigger(args[i]); !result.ok()) {
                    return result;
                }
    
                *event_trigger = args[i]; // 保存事件触发器
            }
        }
    
        return {};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    ParsePropertyTrigger

    Result<void> ParsePropertyTrigger(const std::string& trigger, Subcontext* subcontext,
                                      std::map<std::string, std::string>* property_triggers) {
        const static std::string prop_str("property:"); // property:ro.debuggable=1
        std::string prop_name(trigger.substr(prop_str.length()));// 去除前缀 ro.debuggable=1
        size_t equal_pos = prop_name.find('=');// 找到 =
        if (equal_pos == std::string::npos) {
            return Error() << "property trigger found without matching '='";
        }
    
        std::string prop_value(prop_name.substr(equal_pos + 1));// = 后面的是值
        prop_name.erase(equal_pos); // 等号前面的是属性名
    
        if (!IsActionableProperty(subcontext, prop_name)) {// 检查属性是否支持触发器
            return Error() << "unexported property trigger found: " << prop_name;
        }
        // 将属性名和值组成的触发器添加到 property_triggers
        if (auto [it, inserted] = property_triggers->emplace(prop_name, prop_value); !inserted) {
            return Error() << "multiple property triggers found for same property";
        }
        return {};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    到此,已经创建了Action,并获取了事件触发器和属性触发器。接下来解析它的Command命令列表

    ParseLineSection

    /// @system/core/init/action_parser.cpp
    Result<void> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
        return action_ ? action_->AddCommand(std::move(args), line) : Result<void>{};// 通过Action解析Command
    }
    
    • 1
    • 2
    • 3
    • 4

    Action::AddCommand

    /// @system/core/init/action.cpp
    Result<void> Action::AddCommand(std::vector<std::string>&& args, int line) {
        if (!function_map_) {
            return Error() << "no function map available";
        }
    
        auto map_result = function_map_->Find(args); // 匹配函数表
        if (!map_result.ok()) {
            return Error() << map_result.error();
        }
        // 找到匹配的函数,将新创建的 Command 添加到commands_列表
        commands_.emplace_back(map_result->function, map_result->run_in_subcontext, std::move(args),
                               line);
        return {};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    创建 Command

    Command::Command(BuiltinFunction f, bool execute_in_subcontext, std::vector<std::string>&& args,
                     int line)
        : func_(std::move(f)), // 函数
          execute_in_subcontext_(execute_in_subcontext), // 是否在subcontext中执行
          args_(std::move(args)), // 参数
          line_(line) /* 命令在文件行号*/ {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    function_map_ 实际上是KeywordMap的实例,看看它的实现。

    KeywordMap::Find
    Result<Value> Find(const std::vector<std::string>& args) const {
        if (args.empty()) return Error() << "Keyword needed, but not provided";
        // 以 copy /proc/cmdline /dev/urandom 为例
        auto& keyword = args[0]; // 取出关键字 copy
        auto num_args = args.size() - 1; // 关键字copy 后的其他参数
    
        auto result_it = map_.find(keyword); // 找到copy对应的 MapValue
        if (result_it == map_.end()) {
            return Errorf("Invalid keyword '{}'", keyword);
        }
    
        auto result = result_it->second; // MapValue
    
        auto min_args = result.min_args;
        auto max_args = result.max_args;
        if (min_args == max_args && num_args != min_args) {// 检查参数的数量
            return Errorf("{} requires {} argument{}", keyword, min_args,
                          (min_args > 1 || min_args == 0) ? "s" : "");
        }
    
        if (num_args < min_args || num_args > max_args) { // 检查是否缺参数,多参数
            if (max_args == std::numeric_limits<decltype(max_args)>::max()) {
                return Errorf("{} requires at least {} argument{}", keyword, min_args,
                              min_args > 1 ? "s" : "");
            } else {
                return Errorf("{} requires between {} and {} arguments", keyword, min_args,
                              max_args);
            }
        }
    
        return result.value;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    看一下KeywordMap的实现

    // Value is the return value of Find(), which is typically either a single function or a struct with
    // additional information.
    template <typename Value>
    class KeywordMap {
      public:
        struct MapValue {
            size_t min_args;
            size_t max_args;
            Value value;
        };
    
        KeywordMap() {}
        KeywordMap(std::initializer_list<std::pair<const std::string, MapValue>> init) : map_(init) {}
        Result<Value> Find(const std::vector<std::string>& args) const { ... }
    
      private:
        std::map<std::string, MapValue> map_; // 函数名+MapValue组合
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    BuiltinFunctionMap

    function_map_ 是一些内置函数映射表,通过GetBuiltinFunctionMap(),然后通过Action::set_function_map设置进来的。BuiltinFunctionMap 是KeywordMap的别名。

    /// @system/core/init/builtins.h
    using BuiltinFunction = std::function<Result<void>(const BuiltinArguments&)>;
    
    struct BuiltinFunctionMapValue {
        bool run_in_subcontext;
        BuiltinFunction function;
    };
    
    using BuiltinFunctionMap = KeywordMap<BuiltinFunctionMapValue>;
    
    /// 内置函数映射表,当Command执行 copy 时, 会调用 do_copy 函数
    /// @system/core/init/builtins.cpp
    // Builtin-function-map start
    const BuiltinFunctionMap& GetBuiltinFunctionMap() {
        constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
        // clang-format off
        static const BuiltinFunctionMap builtin_functions =
            // 函数名, MapValue{ min_args,max_args,BuiltinFunctionMapValue{ run_in_subcontext, BuiltinFunction } }
            {"bootchart",               {1,     1,    {false,  do_bootchart}}},
            {"chmod",                   {2,     2,    {true,   do_chmod}}},
            {"chown",                   {2,     3,    {true,   do_chown}}},
            {"class_reset",             {1,     1,    {false,  do_class_reset}}},
            {"class_reset_post_data",   {1,     1,    {false,  do_class_reset_post_data}}},
            {"class_restart",           {1,     1,    {false,  do_class_restart}}},
            {"class_start",             {1,     1,    {false,  do_class_start}}},
            {"class_start_post_data",   {1,     1,    {false,  do_class_start_post_data}}},
            {"class_stop",              {1,     1,    {false,  do_class_stop}}},
            {"copy",                    {2,     2,    {true,   do_copy}}},
            {"copy_per_line",           {2,     2,    {true,   do_copy_per_line}}},
            {"domainname",              {1,     1,    {true,   do_domainname}}},
            {"enable",                  {1,     1,    {false,  do_enable}}},
            {"exec",                    {1,     kMax, {false,  do_exec}}},
            {"exec_background",         {1,     kMax, {false,  do_exec_background}}},
            {"exec_start",              {1,     1,    {false,  do_exec_start}}},
            {"export",                  {2,     2,    {false,  do_export}}},
            {"hostname",                {1,     1,    {true,   do_hostname}}},
            {"ifup",                    {1,     1,    {true,   do_ifup}}},
            {"init_user0",              {0,     0,    {false,  do_init_user0}}},
            {"insmod",                  {1,     kMax, {true,   do_insmod}}},
            {"installkey",              {1,     1,    {false,  do_installkey}}},
            {"interface_restart",       {1,     1,    {false,  do_interface_restart}}},
            {"interface_start",         {1,     1,    {false,  do_interface_start}}},
            {"interface_stop",          {1,     1,    {false,  do_interface_stop}}},
            {"load_exports",            {1,     1,    {false,  do_load_exports}}},
            {"load_persist_props",      {0,     0,    {false,  do_load_persist_props}}},
            {"load_system_props",       {0,     0,    {false,  do_load_system_props}}},
            {"loglevel",                {1,     1,    {false,  do_loglevel}}},
            {"mark_post_data",          {0,     0,    {false,  do_mark_post_data}}},
            {"mkdir",                   {1,     6,    {true,   do_mkdir}}},
            // TODO: Do mount operations in vendor_init.
            // mount_all is currently too complex to run in vendor_init as it queues action triggers,
            // imports rc scripts, etc.  It should be simplified and run in vendor_init context.
            // mount and umount are run in the same context as mount_all for symmetry.
            {"mount_all",               {0,     kMax, {false,  do_mount_all}}},
            {"mount",                   {3,     kMax, {false,  do_mount}}},
            {"perform_apex_config",     {0,     0,    {false,  do_perform_apex_config}}},
            {"umount",                  {1,     1,    {false,  do_umount}}},
            {"umount_all",              {0,     1,    {false,  do_umount_all}}},
            {"update_linker_config",    {0,     0,    {false,  do_update_linker_config}}},
            {"readahead",               {1,     2,    {true,   do_readahead}}},
            {"remount_userdata",        {0,     0,    {false,  do_remount_userdata}}},
            {"restart",                 {1,     1,    {false,  do_restart}}},
            {"restorecon",              {1,     kMax, {true,   do_restorecon}}},
            {"restorecon_recursive",    {1,     kMax, {true,   do_restorecon_recursive}}},
            {"rm",                      {1,     1,    {true,   do_rm}}},
            {"rmdir",                   {1,     1,    {true,   do_rmdir}}},
            {"setprop",                 {2,     2,    {true,   do_setprop}}},
            {"setrlimit",               {3,     3,    {false,  do_setrlimit}}},
            {"start",                   {1,     1,    {false,  do_start}}},
            {"stop",                    {1,     1,    {false,  do_stop}}},
            {"swapon_all",              {0,     1,    {false,  do_swapon_all}}},
            {"enter_default_mount_ns",  {0,     0,    {false,  do_enter_default_mount_ns}}},
            {"symlink",                 {2,     2,    {true,   do_symlink}}},
            {"sysclktz",                {1,     1,    {false,  do_sysclktz}}},
            {"trigger",                 {1,     1,    {false,  do_trigger}}},
            {"verity_update_state",     {0,     0,    {false,  do_verity_update_state}}},
            {"wait",                    {1,     2,    {true,   do_wait}}},
            {"wait_for_prop",           {2,     2,    {false,  do_wait_for_prop}}},
            {"write",                   {2,     2,    {true,   do_write}}},
        };
        // clang-format on
        return builtin_functions;
    }
    // Builtin-function-map end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    当解析完一个action,会执行EndSection函数

    ActionParser::EndSection

    Result<void> ActionParser::EndSection() {
        if (action_ && action_->NumCommands() > 0) {
            action_manager_->AddAction(std::move(action_)); // 将当前解析的action添加到集合
        }
    
        return {};
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    动作、内置动作和事件触发器

    • 动作(Action)
      通常是在rc中使用 on 声明的动作,action通常需要一些事件来触发
    • 内置动作(Builtin Action)
      只在代码里面调用QueueBuiltinAction的action,其他action在rc里使用 on 声明。
    • 事件触发器(Trigger)
      调用QueueEventTrigger插入事件触发器。这种触发器通常用一个字符串表示,会有一些action与之对应。

    看下 Action 构造函数

    Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line,
                   const std::string& event_trigger,
                   const std::map<std::string, std::string>& property_triggers)
        : property_triggers_(property_triggers),//属性触发器集合
          event_trigger_(event_trigger), // 事件触发器名字
          oneshot_(oneshot), // 一次性标记
          subcontext_(subcontext), // 执行上下文
          filename_(filename), // action所在文件和行号
          line_(line) {}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    action通常在事件发生时触发,事件都存放在event_queue_集合里

    std::vector<std::unique_ptr<Action>> actions_; // action集合
    std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_
            GUARDED_BY(event_queue_lock_); // 事件队列
    mutable std::mutex event_queue_lock_;
    std::queue<const Action*> current_executing_actions_; // 正在出现的action队列
    std::size_t current_command_; // 已执行的命令数量
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ActionManager::QueueBuiltinAction

    void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
        auto lock = std::lock_guard{event_queue_lock_};
    		// 创建action,注意第一个参数为true 表示一次性的 oneshot
        auto action = std::make_unique<Action>(true, nullptr, "", 0, name,
                                               std::map<std::string, std::string>{});
        action->AddCommand(std::move(func), {name}, 0);// fun 添加到命令列表,执行action的命令时会被调用
    
        event_queue_.emplace(action.get());  // 添加到事件队列
        actions_.emplace_back(std::move(action)); // 添加到action队列
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    ActionManager::QueueEventTrigger

    void ActionManager::QueueEventTrigger(const std::string& trigger) {
        auto lock = std::lock_guard{event_queue_lock_};
        event_queue_.emplace(trigger); // 添加到事件队列
    }
    
    • 1
    • 2
    • 3
    • 4

    QueueBuiltinAction和QueueEventTrigger只是将相关action和事件添加进队列,实际上没有真正去执行,而实际去执行是在其主循环里面触发的,通过 ActionManager#ExecuteOneCommand

    ActionManager::ExecuteOneCommand

    /// @system/core/init/action_manager.cpp
    void ActionManager::ExecuteOneCommand() {
        {
            auto lock = std::lock_guard{event_queue_lock_};
            // Loop through the event queue until we have an action to execute
            while (current_executing_actions_.empty() && !event_queue_.empty()) { // 当前没有执行的action,但是有事件
                for (const auto& action : actions_) { // 找到此事件对应要处理的action,可能对应多个
                    if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
                                   event_queue_.front())) {
                        current_executing_actions_.emplace(action.get()); // 一个事件可以对应多个 action
                    }
                }
                event_queue_.pop();
            }
        }
    
        if (current_executing_actions_.empty()) {
            return;
        }
        // 返回 queue 中第一个元素的引用,而不是删除
        auto action = current_executing_actions_.front();
    
        if (current_command_ == 0) { // 处理此action的第一条命令时打印
            std::string trigger_name = action->BuildTriggersString();
            LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
                      << ":" << action->line() << ")";
        }
    
        action->ExecuteOneCommand(current_command_); // 回调每个action匹配的命令
    
        // 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_;  // 每执行一次数量加1
        if (current_command_ == action->NumCommands()) { // 如果此 action的命令全部执行完毕
            current_executing_actions_.pop(); // 从正执行列表删除
            current_command_ = 0;
            if (action->oneshot()) { // 如果是一次性的 还有从action列表移除。 通常Builtin Action是一次性的
                auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; };
                actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser),
                               actions_.end());
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    Action::CheckEvent

    检查event 与 action 是否匹配

    bool Action::CheckEvent(const EventTrigger& event_trigger) const { // 检查事件触发器
        return event_trigger == event_trigger_ && CheckPropertyTriggers();//触发器满足并且所有实现也匹配
    }
    
    bool Action::CheckEvent(const PropertyChange& property_change) const { // 检查属性变化事件
        const auto& [name, value] = property_change;
        return event_trigger_.empty() && CheckPropertyTriggers(name, value);
    }
    
    bool Action::CheckEvent(const BuiltinAction& builtin_action) const { // 检查内置action,其event和action是同一个对象
        return this == builtin_action;
    }
    
    
    // This function checks that all property triggers are satisfied, that is
    // for each (name, value) in property_triggers_, check that the current
    // value of the property 'name' == value.
    //
    // It takes an optional (name, value) pair, which if provided must
    // be present in property_triggers_; it skips the check of the current
    // property value for this pair.
    bool Action::CheckPropertyTriggers(const std::string& name, const std::string& value) const {// 检查所有属性是否匹配
        if (property_triggers_.empty()) { // 需要包含属性trigger -> property:aa.bb.cc=xxx
            return true;
        }
    
        if (!name.empty()) { // 如果指定key,需要检查value是否满足指定触发值
            auto it = property_triggers_.find(name);
            if (it == property_triggers_.end()) {
                return false;
            }
            const auto& trigger_value = it->second;
            if (trigger_value != "*" && trigger_value != value) {
                return false;
            }
        }
        // 指定值满足 或 指定值为空。 判断所有非指定的属性键值要满足触发值
        for (const auto& [trigger_name, trigger_value] : property_triggers_) {
            if (trigger_name != name) { // 判断除了指定触发键之外的
                std::string prop_value = android::base::GetProperty(trigger_name, "");
                if (trigger_value == "*" && !prop_value.empty()) {
                    continue;
                }
                if (trigger_value != prop_value) return false;
            }
        }
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    Action::ExecuteOneCommand

    执行一条Command

    /// @system/core/init/action.cpp
    void Action::ExecuteOneCommand(std::size_t command) const {
        // We need a copy here since some Command execution may result in
        // changing commands_ vector by importing .rc files through parser
        Command cmd = commands_[command];
        ExecuteCommand(cmd);
    }
    
    // 执行某一条命令
    void Action::ExecuteCommand(const Command& command) const {
        android::base::Timer t;
        auto result = command.InvokeFunc(subcontext_); // 调用执行对应的命令
        auto duration = t.duration();
    
        // Any action longer than 50ms will be warned to user as slow operation
        if (!result.has_value() || duration > 50ms ||
            android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
            std::string trigger_name = BuildTriggersString();
            std::string cmd_str = command.BuildCommandString();
    
            LOG(INFO) << "Command '" << cmd_str << "' action=" << trigger_name << " (" << filename_
                      << ":" << command.line() << ") took " << duration.count() << "ms and "
                      << (result.ok() ? "succeeded" : "failed: " + result.error().message());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    Command::InvokeFunc

    /// @system/core/init/action.cpp
    Result<void> Command::InvokeFunc(Subcontext* subcontext) const {
        if (subcontext) { // 指定了subcontext
            if (execute_in_subcontext_) { // 如果指定在 subcontext 下执行
                return subcontext->Execute(args_);
            }
    
            auto expanded_args = subcontext->ExpandArgs(args_);
            if (!expanded_args.ok()) { // 膨胀处理失败,则结束处理
                return expanded_args.error();
            }
            return RunBuiltinFunction(func_, *expanded_args, subcontext->context());
        }
    
        return RunBuiltinFunction(func_, args_, kInitContext);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 当指定了不为空的subcontext,
    • 若execute_in_subcontext_为true,则会直接调用subcontext->Execute
    • 否则会先subcontext->ExpandArgs通过subcontext进程对args进行膨胀处理(主要是将 ${prop_name} 解析成对应的属性值),然后在调用RunBuiltinFunction
    • 未指定subcontext则直接调用RunBuiltinFunction

    RunBuiltinFunction

    执行内置的函数

    Result<void> RunBuiltinFunction(const BuiltinFunction& function,
                                    const std::vector<std::string>& args, const std::string& context) {
        auto builtin_arguments = BuiltinArguments(context);
    
        builtin_arguments.args.resize(args.size());
        builtin_arguments.args[0] = args[0];
        for (std::size_t i = 1; i < args.size(); ++i) {
           // ExpandProps函数将属性 ${prop_name} 解析成对应的属性值,在system/core/init/util.cpp 实现
            auto expanded_arg = ExpandProps(args[i]);
            if (!expanded_arg.ok()) {
                return expanded_arg.error();
            }
            builtin_arguments.args[i] = std::move(*expanded_arg);
        }
    
        return function(builtin_arguments); // 调用对应的函数
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    比如对于如下Command,则会调用do_setprop去将vendor.qemu.timezone的属性值设置给persist.sys.timezone。

    setprop persist.sys.timezone ${vendor.qemu.timezone}
    
    • 1
  • 相关阅读:
    python14 字典类型
    数据结构初阶--二叉树介绍(基本性质+堆实现顺序结构)
    Euler diagram
    python小玩意——点菜单程序
    Ubuntu下无法输入中文问题解决
    Git企业开发级讲解(一)
    python使用matplotlib可视化线图(line plot)、将可视化图像的图例(legend)放置在图像外部、左侧区域
    maven构建拉依赖Malformed \uxxxx encoding
    广州搬砖第三年,从一枚小菜鸡到架构师
    中创人民云|党管数据是如何保证国家数据安全的
  • 原文地址:https://blog.csdn.net/qq_28261343/article/details/128107170