second_stage 解析rc文件

目录

概述

android/system/core/init目录下,init进程解析rc文件

rc文件三个关键字打头:
on		为action
service		为service
import		引入其他rc文件

源码解析

1. ActionManager类

actionmanager用来收集action的

1.1 AddAction-存放action

void ActionManager::AddAction(std::unique_ptr<Action> action) {
    // 一个action,它有文件名,行号,event名字,属性名字,还要subcontext,还有oneshot_
    actions_.emplace_back(std::move(action));
}

1.2 QueueBuiltinAction-内建的action

void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
    // 加锁
    auto lock = std::lock_guard{event_queue_lock_};
    // 将函数变为action
    auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0, name,
                                           std::map<std::string, std::string>{});
    action->AddCommand(std::move(func), {name}, 0);
// action为指针,action.get()获得Action *指针,所以event_queue_存放的就是BuiltinAction类型的
    // 放进event_queue_就会执行命令
    event_queue_.emplace(action.get());
    actions_.emplace_back(std::move(action));
}

1.3 QueueEventTrigger-存放trigger的string

void ActionManager::QueueEventTrigger(const std::string& trigger) {
    auto lock = std::lock_guard{event_queue_lock_};
    // 这里存放的为string
    event_queue_.emplace(trigger);
}

1.4 ExecuteOneCommand

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_) {// CheckEvent是检查是否一致,检查字符串,property和action
                if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
                               // 从event_queue_中拿出一个action
                               event_queue_.front())) {
                    // 如果一致,就加入到current_executing_actions_中
                    current_executing_actions_.emplace(action.get());
                }
            }
            event_queue_.pop();
        }
    }

    if (current_executing_actions_.empty()) {
        return;
    }

    auto action = current_executing_actions_.front();
// 一开始,current_command_是为0的
    if (current_command_ == 0) {
        std::string trigger_name = action->BuildTriggersString();
        LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
                  << ":" << action->line() << ")";
    }
// 注意,这里只是执行一条action的command而已
    action->ExecuteOneCommand(current_command_);

    // 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_;
    // 执行完一个action的所有command之后
    if (current_command_ == action->NumCommands()) {
        current_executing_actions_.pop();
        current_command_ = 0;
        // oneshot:QueueBuiltinAction的是true的,rc文件中的默认是false的
        if (action->oneshot()) {
            auto eraser = [&action](std::unique_ptr<Action>& a) { return a.get() == action; };
            // oneshot的执行完之后就会被清除了
            actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser),
                           actions_.end());
        }
    }
}

2. ServiceList类-start命令的时候会使用到

2.1 FindService-寻找service

// 默认是Service::name函数
Service* FindService(T value, F function = &Service::name) const {
        auto svc = std::find_if(services_.begin(), services_.end(),
                                [&function, &value](const std::unique_ptr<Service>& s) {
                                    // 然后传入s实例,因为name函数是属于Service类的
                                    return std::invoke(function, s) == value;
                                });
        if (svc != services_.end()) {
            return svc->get();
        }
        return nullptr;
    }

2.2 AddService-放到services_中

void ServiceList::AddService(std::unique_ptr<Service> service) {
    services_.emplace_back(std::move(service));
}

3. Parser类

3.1 AddSectionParser-添加parser函数

void Parser::AddSectionParser(const std::string& name, std::unique_ptr<SectionParser> parser) {
    section_parsers_[name] = std::move(parser);
}

3.2 ParseConfig-分析rc文件

bool Parser::ParseConfig(const std::string& path) {
    if (is_dir(path.c_str())) {
        return ParseConfigDir(path);
    }
    return ParseConfigFile(path);
}

3.3 ParseConfigDir-分析文件夹

bool Parser::ParseConfigDir(const std::string& path) {
    LOG(INFO) << "Parsing directory " << path << "...";
    // 智能指针,析构的时候,closedir
    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) {
        // 解析rc文件
        if (!ParseConfigFile(file)) {
            LOG(ERROR) << "could not import file '" << file << "'";
        }
    }
    return true;
}

3.4 ParseConfigFile-解析rc文件

bool Parser::ParseConfigFile(const std::string& path) {
    LOG(INFO) << "Parsing file " << path << "...";
    android::base::Timer t;
    // 读文件,然后返回string
    auto config_contents = ReadFile(path);
    if (!config_contents.ok()) {
        LOG(INFO) << "Unable to read config file '" << path << "': " << config_contents.error();
        return false;
    }
// 解析rc文件的内容
    ParseData(path, &config_contents.value());

    LOG(VERBOSE) << "(Parsing " << path << " took " << t << ".)";
    return true;
}

3.5 ParseData-把rc中的action放在actionmanager中-把service放在service_list中

// /system/etc/init/hw/init.rc
struct parse_state
{
    char *ptr;	// 指向字符串data数据
    char *text;	// (on) (early-init)就为一个text
    int line;	// 记录文件的行号
    int nexttoken;	// 记录下一个token,如换行符\n
};
void Parser::ParseData(const std::string& filename, std::string* data) {
    data->push_back('\n');  // TODO: fix tokenizer
    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 = [&] {
        bad_section_found = false;
        if (section_parser == nullptr) return;
        // 这里执行section的endsection函数
        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)) {
            case T_EOF:
                // 分析完一个rc文件了
                end_section();

                for (const auto& [section_name, section_parser] : section_parsers_) {
                    // 这里再import另一个rc文件
                    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.
                // ueventd相关的命令
                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()) {
                    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])) {
                    // 这里先执行end_section
                    end_section();
                    // 获得section_prser函数,是on import service哪个
                    section_parser = section_parsers_[args[0]].get();
                    section_start_line = state.line;
                    if (auto result =
                        // 进行解析
                                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;
                    }
                    // 经过上面之后,这个就不为null了
                } else if (section_parser) {
                    // args:(start)(zygote)
                    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:
                args.emplace_back(state.text);
                break;
        }
    }
}

3.6 next_token-解析rc文件

int next_token(struct parse_state *state)
{
    char *x = state->ptr;
    char *s;

    if (state->nexttoken) {
        // 在这里立刻返回,处理section
        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':
                // 省略空格,tag键
            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:
                // 默认是text
            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':
                // 这里是先返回一个t_text,然后再返回T_NEWLINE去处理section
            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':
                    /* \ <cr> <lf> -> line continuation */
                if (x[1] != '\n') {
                    x++;
                    continue;
                }
                x++;
                FALLTHROUGH_INTENDED;
            case '\n':
                    /* \ <lf> -> 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;
}

4. ServiceParser-对应rc中的service

4.1 ParseSection-解析service的

service ueventd /system/bin/ueventd
    class core
    critical
    seclabel u:r:ueventd:s0
    shutdown critical
Result<void> ServiceParser::ParseSection(std::vector<std::string>&& args,
                                         const std::string& filename, int line) {
    if (args.size() < 3) {
        return Error() << "services must have a name and a program";
    }
// 名字
    const std::string& name = args[1];
    if (!IsValidName(name)) {
        return Error() << "invalid service name '" << name << "'";
    }

    filename_ = filename;

    Subcontext* restart_action_subcontext = nullptr;
        // vendor和odm相关的
    if (subcontext_ && subcontext_->PathMatchesSubcontext(filename)) {
        restart_action_subcontext = subcontext_;
    }

    std::vector<std::string> str_args(args.begin() + 2, args.end());

    if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_P__) {
        if (str_args[0] == "/sbin/watchdogd") {
            str_args[0] = "/system/bin/watchdogd";
        }
    }
    if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) {
        if (str_args[0] == "/charger") {
            str_args[0] = "/system/bin/charger";
        }
    }
// name为ueventd,restart_action_subcontext为null或者vendor_init,str_args为/system/bin/ueventd,from_apex_为false的
        // 用的都是默认值
    service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args, from_apex_);
    return {};
}

4.2 ParseLineSection-service的命令行

Result<void> ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line) {
    if (!service_) {
        return {};
    }

    auto parser = GetParserMap().Find(args);

    if (!parser.ok()) return parser.error();
// 然后执行命令
    return std::invoke(*parser, this, std::move(args));
}

4.3 GetParserMap-找到service的东西,然后执行相应的函数

const KeywordMap<ServiceParser::OptionParser>& ServiceParser::GetParserMap() const {
    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
    // clang-format off
    // using OptionParser = Result<void> (ServiceParser::*)(std::vector<std::string>&& args);
    // OptionParser表示Result<void> ParseCapabilities(std::vector<std::string>&& args);这样的函数指针
    static const KeywordMap<ServiceParser::OptionParser> parser_map = {
        {"capabilities",            {0,     kMax, &ServiceParser::ParseCapabilities}},
        {"class",                   {1,     kMax, &ServiceParser::ParseClass}},
        {"console",                 {0,     1,    &ServiceParser::ParseConsole}},
        {"critical",                {0,     0,    &ServiceParser::ParseCritical}},
        {"disabled",                {0,     0,    &ServiceParser::ParseDisabled}},
        {"enter_namespace",         {2,     2,    &ServiceParser::ParseEnterNamespace}},
        {"file",                    {2,     2,    &ServiceParser::ParseFile}},
        {"group",                   {1,     NR_SVC_SUPP_GIDS + 1, &ServiceParser::ParseGroup}},
        {"interface",               {2,     2,    &ServiceParser::ParseInterface}},
        {"ioprio",                  {2,     2,    &ServiceParser::ParseIoprio}},
        {"keycodes",                {1,     kMax, &ServiceParser::ParseKeycodes}},
        {"memcg.limit_in_bytes",    {1,     1,    &ServiceParser::ParseMemcgLimitInBytes}},
        {"memcg.limit_percent",     {1,     1,    &ServiceParser::ParseMemcgLimitPercent}},
        {"memcg.limit_property",    {1,     1,    &ServiceParser::ParseMemcgLimitProperty}},
        {"memcg.soft_limit_in_bytes",
                                    {1,     1,    &ServiceParser::ParseMemcgSoftLimitInBytes}},
        {"memcg.swappiness",        {1,     1,    &ServiceParser::ParseMemcgSwappiness}},
        {"namespace",               {1,     2,    &ServiceParser::ParseNamespace}},
        {"oneshot",                 {0,     0,    &ServiceParser::ParseOneshot}},
        {"onrestart",               {1,     kMax, &ServiceParser::ParseOnrestart}},
        {"oom_score_adjust",        {1,     1,    &ServiceParser::ParseOomScoreAdjust}},
        {"override",                {0,     0,    &ServiceParser::ParseOverride}},
        {"priority",                {1,     1,    &ServiceParser::ParsePriority}},
        {"reboot_on_failure",       {1,     1,    &ServiceParser::ParseRebootOnFailure}},
        {"restart_period",          {1,     1,    &ServiceParser::ParseRestartPeriod}},
        {"rlimit",                  {3,     3,    &ServiceParser::ParseProcessRlimit}},
        {"seclabel",                {1,     1,    &ServiceParser::ParseSeclabel}},
        {"setenv",                  {2,     2,    &ServiceParser::ParseSetenv}},
        {"shutdown",                {1,     1,    &ServiceParser::ParseShutdown}},
        {"sigstop",                 {0,     0,    &ServiceParser::ParseSigstop}},
        {"socket",                  {3,     6,    &ServiceParser::ParseSocket}},
        {"stdio_to_kmsg",           {0,     0,    &ServiceParser::ParseStdioToKmsg}},
        {"task_profiles",           {1,     kMax, &ServiceParser::ParseTaskProfiles}},
        {"timeout_period",          {1,     1,    &ServiceParser::ParseTimeoutPeriod}},
        {"updatable",               {0,     0,    &ServiceParser::ParseUpdatable}},
        {"user",                    {1,     1,    &ServiceParser::ParseUser}},
        {"writepid",                {1,     kMax, &ServiceParser::ParseWritepid}},
    };
    // clang-format on
    return parser_map;
}

4.4 ParseClass-解析class关键字

Result<void> ServiceParser::ParseClass(std::vector<std::string>&& args) {
    service_->classnames_ = std::set<std::string>(args.begin() + 1, args.end());
    return {};
}

4.5 EndSection-一个section结束

Result<void> ServiceParser::EndSection() {
    if (!service_) {
        return {};
    }
// 这个为null了
    if (interface_inheritance_hierarchy_) {
        if (const auto& check_hierarchy_result = CheckInterfaceInheritanceHierarchy(
                    service_->interfaces(), *interface_inheritance_hierarchy_);
            !check_hierarchy_result.ok()) {
            return Error() << check_hierarchy_result.error();
        }
    }

    if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) {
        if ((service_->flags() & SVC_CRITICAL) != 0 && (service_->flags() & SVC_ONESHOT) != 0) {
            return Error() << "service '" << service_->name()
                           << "' can't be both critical and oneshot";
        }
    }
// 是否有重复的
    Service* old_service = service_list_->FindService(service_->name());
    if (old_service) {
        // override字段,可以覆盖
        if (!service_->is_override()) {
            return Error() << "ignored duplicate definition of service '" << service_->name()
                           << "'";
        }

        if (StartsWith(filename_, "/apex/") && !old_service->is_updatable()) {
            return Error() << "cannot update a non-updatable service '" << service_->name()
                           << "' with a config in APEX";
        }

        service_list_->RemoveService(*old_service);
        old_service = nullptr;
    }
// 没有的话就直接加入了
    service_list_->AddService(std::move(service_));

    return {};
}

4.6 ParseIoprio-设置io优先级

Result<void> ServiceParser::ParseIoprio(std::vector<std::string>&& args) {
    // 设置IO优先级
    if (!ParseInt(args[2], &service_->proc_attr_.ioprio_pri, 0, 7)) {
        return Error() << "priority value must be range 0 - 7";
    }

    if (args[1] == "rt") {
        service_->proc_attr_.ioprio_class = IoSchedClass_RT;
    } else if (args[1] == "be") {
        // 设置为BE
        service_->proc_attr_.ioprio_class = IoSchedClass_BE;
    } else if (args[1] == "idle") {
        service_->proc_attr_.ioprio_class = IoSchedClass_IDLE;
    } else {
        return Error() << "ioprio option usage: ioprio <rt|be|idle> <0-7>";
    }

    return {};
}

4.7 ParseWritepid-写pid的文件

Result<void> ServiceParser::ParseWritepid(std::vector<std::string>&& args) {
    args.erase(args.begin());
    service_->writepid_files_ = std::move(args);
    return {};
}

4.8 ParseShutdown-设置service的flags

Result<void> ServiceParser::ParseShutdown(std::vector<std::string>&& args) {
    if (args[1] == "critical") {
        service_->flags_ |= SVC_SHUTDOWN_CRITICAL;
        return {};
    }
    return Error() << "Invalid shutdown option";
}

4.9 ParseGroup-设置gid和uid和supp_gids

Result<void> ServiceParser::ParseGroup(std::vector<std::string>&& args) {
    // 解析uid和gid,可以传名字或者数字
    auto gid = DecodeUid(args[1]);
    if (!gid.ok()) {
        return Error() << "Unable to decode GID for '" << args[1] << "': " << gid.error();
    }
    service_->proc_attr_.gid = *gid;

    for (std::size_t n = 2; n < args.size(); n++) {
        gid = DecodeUid(args[n]);
        if (!gid.ok()) {
            return Error() << "Unable to decode GID for '" << args[n] << "': " << gid.error();
        }
        service_->proc_attr_.supp_gids.emplace_back(*gid);
    }
    return {};
}

4.10 ParseSocket-解析sockets

// socket adbd seqpacket 660 system system
// name type perm uid gid
struct SocketDescriptor {
    std::string name;
    int type = 0;
    uid_t uid = 0;
    gid_t gid = 0;
    int perm = 0;
    std::string context;
    bool passcred = false;

    Result<Descriptor> Create(const std::string& global_context) const;
};
Result<void> ServiceParser::ParseSocket(std::vector<std::string>&& args) {
    SocketDescriptor socket;
    // adbd
    socket.name = std::move(args[1]);

    auto types = Split(args[2], "+");
    if (types[0] == "stream") {
        socket.type = SOCK_STREAM;
    } else if (types[0] == "dgram") {
        socket.type = SOCK_DGRAM;
    } else if (types[0] == "seqpacket") {
        // type
        socket.type = SOCK_SEQPACKET;
    } else {
        return Error() << "socket type must be 'dgram', 'stream' or 'seqpacket', got '" << types[0]
                       << "' instead.";
    }

    if (types.size() > 1) {
        if (types.size() == 2 && types[1] == "passcred") {
            socket.passcred = true;
        } else {
            return Error() << "Only 'passcred' may be used to modify the socket type";
        }
    }

    errno = 0;
    char* end = nullptr;
    socket.perm = strtol(args[3].c_str(), &end, 8);
    if (errno != 0) {
        return ErrnoError() << "Unable to parse permissions '" << args[3] << "'";
    }
    if (end == args[3].c_str() || *end != '\0') {
        errno = EINVAL;
        return ErrnoError() << "Unable to parse permissions '" << args[3] << "'";
    }

    if (args.size() > 4) {
        auto uid = DecodeUid(args[4]);
        if (!uid.ok()) {
            return Error() << "Unable to find UID for '" << args[4] << "': " << uid.error();
        }
        socket.uid = *uid;
    }

    if (args.size() > 5) {
        auto gid = DecodeUid(args[5]);
        if (!gid.ok()) {
            return Error() << "Unable to find GID for '" << args[5] << "': " << gid.error();
        }
        socket.gid = *gid;
    }

    socket.context = args.size() > 6 ? args[6] : "";

    auto old = std::find_if(service_->sockets_.begin(), service_->sockets_.end(),
                            [&socket](const auto& other) { return socket.name == other.name; });

    if (old != service_->sockets_.end()) {
        return Error() << "duplicate socket descriptor '" << socket.name << "'";
    }

    service_->sockets_.emplace_back(std::move(socket));

    return {};
}

5. ActionParser-对应rc中的on

5.1 ParseSection-分析section

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());
    if (triggers.size() < 1) {
        return Error() << "Actions must have a trigger";
    }

    Subcontext* action_subcontext = nullptr;
    // std::vector<std::string>{"/vendor", "/odm"}开头的
    if (subcontext_ && subcontext_->PathMatchesSubcontext(filename)) {
        action_subcontext = subcontext_;
    }

    std::string event_trigger;
    std::map<std::string, std::string> property_triggers;
// event_trigger = zygote-start,property_triggers=(ro.crypto.state, unsupported)
    if (auto result =
                ParseTriggers(triggers, action_subcontext, &event_trigger, &property_triggers);
        !result.ok()) {
        return Error() << "ParseTriggers() failed: " << result.error();
    }
// 创建Action对象,oneshot为false,
    auto action = std::make_unique<Action>(false, action_subcontext, filename, line, event_trigger,
                                           property_triggers);
// 放到这里,用于下面为action添加command
    action_ = std::move(action);
    return {};
}

5.2 ParseTriggers-解析触发事件

// args:early-init,subcontext:null或者vendor_init,
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";
        }
// zygote-start && property:ro.crypto.state=unsupported
        // 奇数的为&&
        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 {
            // 剩下的都为event
            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 {};
}

5.3 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:");
    std::string prop_name(trigger.substr(prop_str.length()));
    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;
    }
// 放入
    if (auto [it, inserted] = property_triggers->emplace(prop_name, prop_value); !inserted) {
        return Error() << "multiple property triggers found for same property";
    }
    return {};
}
bool IsActionableProperty(Subcontext* subcontext, const std::string& prop_name) {
    // 这个为true
    static bool enabled = GetBoolProperty("ro.actionable_compatible_property.enabled", false);
// system的不理,vendor的才要兼容
    if (subcontext == nullptr || !enabled) {
        return true;
    }
// vendor的,这些开头的都可以
    static constexpr const char* kPartnerPrefixes[] = {
            "init.svc.vendor.", "ro.vendor.",    "persist.vendor.",
            "vendor.",          "init.svc.odm.", "ro.odm.",
            "persist.odm.",     "odm.",          "ro.boot.",
    };

    for (const auto& prefix : kPartnerPrefixes) {
        if (android::base::StartsWith(prop_name, prefix)) {
            return true;
        }
    }

    return CanReadProperty(subcontext->context(), prop_name);
}
bool CanReadProperty(const std::string& source_context, const std::string& name) {
    const char* target_context = nullptr;
    // 属性的context
    property_info_area->GetPropertyInfo(name.c_str(), &target_context, nullptr);

    PropertyAuditData audit_data;

    audit_data.name = name.c_str();

    ucred cr = {.pid = 0, .uid = 0, .gid = 0};
    audit_data.cr = &cr;
// 看vendor_init是否有权限去读这个context类型的属性
    return selinux_check_access(source_context.c_str(), target_context, "file", "read",
                                &audit_data) == 0;
}

5.4 ValidateEventTrigger-名字必须为_和-和字母和数字

Result<void> ValidateEventTrigger(const std::string& event_trigger) {
    if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) {
        for (const char& c : event_trigger) {
            if (c != '_' && c != '-' && !std::isalnum(c)) {
                return Error() << "Illegal character '" << c << "' in '" << event_trigger << "'";
            }
        }
    }
    return {};
}

5.5 ParseLineSection-添加命令

Result<void> ActionParser::ParseLineSection(std::vector<std::string>&& args, int line) {
    return action_ ? action_->AddCommand(std::move(args), line) : Result<void>{};
}

5.6 EndSection-action的尾部

Result<void> ActionParser::EndSection() {
    if (action_ && action_->NumCommands() > 0) {
        // 加入到action_manager中
        action_manager_->AddAction(std::move(action_));
    }

    return {};
}

6. ImportParser-对应rc中的import

6.1 ParseSection

Result<void> ImportParser::ParseSection(std::vector<std::string>&& args,
                                        const std::string& filename, int line) {
    if (args.size() != 2) {
        return Error() << "single argument needed for import\n";
    }
// import /system/etc/init/hw/init.${ro.zygote}.rc,会带有属性,所以需要解析下
    auto conf_file = ExpandProps(args[1]);
    if (!conf_file.ok()) {
        return Error() << "Could not expand import: " << conf_file.error();
    }

    LOG(INFO) << "Added '" << *conf_file << "' to import list";
    if (filename_.empty()) filename_ = filename;
    imports_.emplace_back(std::move(*conf_file), line);
    return {};
}

6.2 EndFile-文件结束,引入新的rc文件进行解析

void ImportParser::EndFile() {
    auto current_imports = std::move(imports_);
    imports_.clear();
    for (const auto& [import, line_num] : current_imports) {
        parser_->ParseConfig(import);
    }
}

7. Action类

7.1 AddCommand-添加action的命令

Result<void> Action::AddCommand(std::vector<std::string>&& args, int line) {
    if (!function_map_) {
        return Error() << "no function map available";
    }
// 先找builtins
    auto map_result = function_map_->Find(args);
    if (!map_result.ok()) {
        return Error() << map_result.error();
    }
// 然后放入commands_中
    commands_.emplace_back(map_result->function, map_result->run_in_subcontext, std::move(args),
                           line);
    return {};
}

void Action::AddCommand(BuiltinFunction f, std::vector<std::string>&& args, int line) {
    // 或者是自定义的function
    commands_.emplace_back(std::move(f), false, std::move(args), line);
}

7.2 GetBuiltinFunctionMap-action的命令

using BuiltinFunctionMap = KeywordMap<BuiltinFunctionMapValue>;
struct BuiltinFunctionMapValue {
    bool run_in_subcontext;
    BuiltinFunction function;
};
std::map<std::string, MapValue> map_;
struct MapValue {
        size_t min_args;
        size_t max_args;
        Value value;
    };
const BuiltinFunctionMap& GetBuiltinFunctionMap() {
    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
    // clang-format off
    static const BuiltinFunctionMap builtin_functions = {
        {"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}}},
        {"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_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;
}

7.3 CheckEvent-检查event是否一致

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 {
    return this == builtin_action;
}

7.4 CheckPropertyTriggers

bool Action::CheckPropertyTriggers(const std::string& name, const std::string& value) const {
    if (property_triggers_.empty()) {
        return true;
    }
// 检查属性的name是否一致
    if (!name.empty()) {
        auto it = property_triggers_.find(name);
        if (it == property_triggers_.end()) {
            return false;
        }
        const auto& trigger_value = it->second;
        // 先检查value
        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;
}

7.5 BuildTriggersString-返回触发的字符串

std::string Action::BuildTriggersString() const {
    std::vector<std::string> triggers;

    for (const auto& [trigger_name, trigger_value] : property_triggers_) {
        triggers.emplace_back(trigger_name + '=' + trigger_value);
    }
    if (!event_trigger_.empty()) {
        triggers.emplace_back(event_trigger_);
    }

    return Join(triggers, " && ");
}

7.6 ExecuteOneCommand-执行action中的一条命令

// 第一次执行的时候,command为0
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);
}

7.7 ExecuteCommand-执行命令

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());
    }
}

7.8 InvokeFunc-执行命令

Result<void> Command::InvokeFunc(Subcontext* subcontext) const {
    // vendor和odm目录下rc文件
    if (subcontext) {
        // 该builtin function是否可以运行在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);
}

7.9 RunBuiltinFunction-执行函数

// mkdir /acct/uid
Result<void> RunBuiltinFunction(const BuiltinFunction& function,
                                const std::vector<std::string>& args, const std::string& context) {
    // 包含args和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) {
        // 解析command中的属性的值
        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);
}

8. KeywordMap类

8.1 Find-找函数

    // args:class core
	Result<Value> Find(const std::vector<std::string>& args) const {
        if (args.empty()) return Error() << "Keyword needed, but not provided";

        auto& keyword = args[0];
        auto num_args = args.size() - 1;
// map_来找
        auto result_it = map_.find(keyword);
        if (result_it == map_.end()) {
            return Errorf("Invalid keyword '{}'", keyword);
        }

        auto result = result_it->second;

        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;
    }

9. service类

service有很多的属性

9.1 Start-启动服务进程

Result<void> Service::Start() {
    // service启动失败之后,会走这里
    auto reboot_on_failure = make_scope_guard([this] {
        // // rc中配置了reboot_on_failure的
        if (on_failure_reboot_target_) {
            // 会走重启流程
            trigger_shutdown(*on_failure_reboot_target_);
        }
    });
// apex的updatable相关,rc文件中配置了updatable关键字
    if (is_updatable() && !ServiceList::GetInstance().IsServicesUpdated()) {
        ServiceList::GetInstance().DelayService(*this);
        return Error() << "Cannot start an updatable service '" << name_
                       << "' before configs from APEXes are all loaded. "
                       << "Queued for execution.";
    }
// flags_都是和服务的启动和重启相关的
    bool disabled = (flags_ & (SVC_DISABLED | SVC_RESET));
    // Starting a service removes it from the disabled or reset state and
    // immediately takes it out of the restarting state if it was in there.
    flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));

    // Running processes require no additional work --- if they're in the
    // process of exiting, we've ensured that they will immediately restart
    // on exit, unless they are ONESHOT. For ONESHOT service, if it's in
    // stopping status, we just set SVC_RESTART flag so it will get restarted
    // in Reap().
    if (flags_ & SVC_RUNNING) {
        if ((flags_ & SVC_ONESHOT) && disabled) {
            flags_ |= SVC_RESTART;
        }
        // It is not an error to try to start a service that is already running.
        reboot_on_failure.Disable();
        return {};
    }
// 表明该服务是否要将标准输入输出重定向到串口上,默认是/dev/console设备
    bool needs_console = (flags_ & SVC_CONSOLE);
    if (needs_console) {
        if (proc_attr_.console.empty()) {
            proc_attr_.console = "/dev/" + GetProperty("ro.boot.console", "console");
        }

        // Make sure that open call succeeds to ensure a console driver is
        // properly registered for the device node
        // 尝试先打开,看能不能打开
        int console_fd = open(proc_attr_.console.c_str(), O_RDWR | O_CLOEXEC);
        if (console_fd < 0) {
            flags_ |= SVC_DISABLED;
            return ErrnoError() << "Couldn't open console '" << proc_attr_.console << "'";
        }
        close(console_fd);
    }

    struct stat sb;
    // 检查该服务的可执行文件是否存在
    if (stat(args_[0].c_str(), &sb) == -1) {
        flags_ |= SVC_DISABLED;
        return ErrnoError() << "Cannot find '" << args_[0] << "'";
    }

    std::string scon;
    // 该服务的scon
    if (!seclabel_.empty()) {
        scon = seclabel_;
    } else {
        auto result = ComputeContextFromExecutable(args_[0]);
        if (!result.ok()) {
            return result.error();
        }
        scon = *result;
    }

    if (!AreRuntimeApexesReady() && !pre_apexd_) {
        // If this service is started before the Runtime and ART APEXes get
        // available, mark it as pre-apexd one. Note that this marking is
        // permanent. So for example, if the service is re-launched (e.g., due
        // to crash), it is still recognized as pre-apexd... for consistency.
        pre_apexd_ = true;
    }
// 是否到post-fs-data阶段了
    post_data_ = ServiceList::GetInstance().IsPostData();

    LOG(INFO) << "starting service '" << name_ << "'...";

    std::vector<Descriptor> descriptors;
    // 定义的socket:socket adbd seqpacket 660 system system
    for (const auto& socket : sockets_) {
        // 创建socket
        if (auto result = socket.Create(scon); result.ok()) {
            descriptors.emplace_back(std::move(*result));
        } else {
            LOG(INFO) << "Could not create socket '" << socket.name << "': " << result.error();
        }
    }

    for (const auto& file : files_) {
        // file /dev/kmsg r
        // 打开文件
        if (auto result = file.Create(); result.ok()) {
            descriptors.emplace_back(std::move(*result));
        } else {
            LOG(INFO) << "Could not open file '" << file.name << "': " << result.error();
        }
    }

    pid_t pid = -1;
    if (namespaces_.flags) {
        // 创建namespace,如CLONE_NEWNS
        pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
    } else {
        // 创建进程
        pid = fork();
    }

    if (pid == 0) {
        // 设置umask为077,对应mode为700,会导致在串口remount会失败
        umask(077);
// namespace相关
        if (auto result = EnterNamespaces(namespaces_, name_, pre_apexd_); !result.ok()) {
            LOG(FATAL) << "Service '" << name_
                       << "' failed to set up namespaces: " << result.error();
        }
// env设置相关,setenv BORINGSSL_SELF_TEST_CREATE_FLAG true 
        for (const auto& [key, value] : environment_vars_) {
            setenv(key.c_str(), value.c_str(), 1);
        }

        for (const auto& descriptor : descriptors) {
            // 将fd设置到环境变量中
            descriptor.Publish();
        }
// 将pid写到/dev/cpuset/foreground/tasks,后台运行进程
        if (auto result = WritePidToFiles(&writepid_files_); !result.ok()) {
            LOG(ERROR) << "failed to write pid to files: " << result.error();
        }
// 设置的任务配置文件
        if (task_profiles_.size() > 0 && !SetTaskProfiles(getpid(), task_profiles_)) {
            LOG(ERROR) << "failed to set task profiles";
        }

        // As requested, set our gid, supplemental gids, uid, context, and
        // priority. Aborts on failure.
        // 设置gid和gids,context和优先级
        SetProcessAttributesAndCaps();
// exec进程,sigstop_没有设置
        if (!ExpandArgsAndExecv(args_, sigstop_)) {
            PLOG(ERROR) << "cannot execv('" << args_[0]
                        << "'). See the 'Debugging init' section of init's README.md for tips";
        }

        _exit(127);
    }

    if (pid < 0) {
        pid_ = 0;
        return ErrnoError() << "Failed to fork";
    }
// 设置分数oom_score_adjust -600
    if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
        std::string oom_str = std::to_string(oom_score_adjust_);
        std::string oom_file = StringPrintf("/proc/%d/oom_score_adj", pid);
        if (!WriteStringToFile(oom_str, oom_file)) {
            PLOG(ERROR) << "couldn't write oom_score_adj";
        }
    }

    time_started_ = boot_clock::now();
    pid_ = pid;
    flags_ |= SVC_RUNNING;
    start_order_ = next_start_order_++;
    process_cgroup_empty_ = false;
// memcg相关的
    bool use_memcg = swappiness_ != -1 || soft_limit_in_bytes_ != -1 || limit_in_bytes_ != -1 ||
                      limit_percent_ != -1 || !limit_property_.empty();
    errno = -createProcessGroup(proc_attr_.uid, pid_, use_memcg);
    if (errno != 0) {
        PLOG(ERROR) << "createProcessGroup(" << proc_attr_.uid << ", " << pid_
                    << ") failed for service '" << name_ << "'";
    } else if (use_memcg) {
        if (swappiness_ != -1) {
            if (!setProcessGroupSwappiness(proc_attr_.uid, pid_, swappiness_)) {
                PLOG(ERROR) << "setProcessGroupSwappiness failed";
            }
        }

        if (soft_limit_in_bytes_ != -1) {
            if (!setProcessGroupSoftLimit(proc_attr_.uid, pid_, soft_limit_in_bytes_)) {
                PLOG(ERROR) << "setProcessGroupSoftLimit failed";
            }
        }

        size_t computed_limit_in_bytes = limit_in_bytes_;
        if (limit_percent_ != -1) {
            long page_size = sysconf(_SC_PAGESIZE);
            long num_pages = sysconf(_SC_PHYS_PAGES);
            if (page_size > 0 && num_pages > 0) {
                size_t max_mem = SIZE_MAX;
                if (size_t(num_pages) < SIZE_MAX / size_t(page_size)) {
                    max_mem = size_t(num_pages) * size_t(page_size);
                }
                computed_limit_in_bytes =
                        std::min(computed_limit_in_bytes, max_mem / 100 * limit_percent_);
            }
        }

        if (!limit_property_.empty()) {
            // This ends up overwriting computed_limit_in_bytes but only if the
            // property is defined.
            computed_limit_in_bytes = android::base::GetUintProperty(
                    limit_property_, computed_limit_in_bytes, SIZE_MAX);
        }

        if (computed_limit_in_bytes != size_t(-1)) {
            if (!setProcessGroupLimit(proc_attr_.uid, pid_, computed_limit_in_bytes)) {
                PLOG(ERROR) << "setProcessGroupLimit failed";
            }
        }
    }

    if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
        // lmkd相关,用lmkd调节
        LmkdRegister(name_, proc_attr_.uid, pid_, oom_score_adjust_);
    }

    NotifyStateChange("running");
    // service正常,所以disable掉reboot_on_failure
    reboot_on_failure.Disable();
    return {};
}

9.2 Service构造函数-初始化值

// name: vold subcontext:null args: /system/bin/vold \
//        --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \
//        --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0
// from_apex:false
ParseLineSection函数会解析这些参数
//    class core	classnames_为core
//    ioprio be 2	service_->proc_attr_.ioprio_pri为2,service_->proc_attr_.ioprio_class = IoSchedClass_BE
//    writepid /dev/cpuset/foreground/tasks	service_->writepid_files_为/dev/cpuset/foreground/tasks,后台运行的进程
//    shutdown critical		service_->flags_ |= SVC_SHUTDOWN_CRITICAL
//    group root reserved_disk	service_->proc_attr_.gid为0 service_->proc_attr_.supp_gids为1065 可以通过id命令看uid
Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
                 const std::vector<std::string>& args, bool from_apex)
    : Service(name, 0, 0, 0, {}, 0, "", subcontext_for_restart_commands, args, from_apex) {}
//  其他为默认值
Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
                 const std::vector<gid_t>& supp_gids, int namespace_flags,
                 const std::string& seclabel, Subcontext* subcontext_for_restart_commands,
                 const std::vector<std::string>& args, bool from_apex)
    : name_(name),
      classnames_({"default"}),
      flags_(flags),
      pid_(0),
      crash_count_(0),
      proc_attr_{.ioprio_class = IoSchedClass_NONE,
                 .ioprio_pri = 0,
                 .uid = uid,
                 .gid = gid,
                 .supp_gids = supp_gids,
                 .priority = 0},
      namespaces_{.flags = namespace_flags},
      seclabel_(seclabel),
      onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0,
                 "onrestart", {}),
      oom_score_adjust_(DEFAULT_OOM_SCORE_ADJUST),
      start_order_(0),
      args_(args),
      from_apex_(from_apex) {}

9.3 ComputeContextFromExecutable-计算可执行文件的context

static Result<std::string> ComputeContextFromExecutable(const std::string& service_path) {
    std::string computed_context;

    char* raw_con = nullptr;
    char* raw_filecon = nullptr;
// 获取本进程的context
    if (getcon(&raw_con) == -1) {
        return Error() << "Could not get security context";
    }
    std::unique_ptr<char> mycon(raw_con);
// 获取文件的context
    if (getfilecon(service_path.c_str(), &raw_filecon) == -1) {
        return Error() << "Could not get file context";
    }
    std::unique_ptr<char> filecon(raw_filecon);

    char* new_con = nullptr;
    // 计算本进程context访问可执行文件的context,创建新的context
    int rc = security_compute_create(mycon.get(), filecon.get(),
                                     string_to_security_class("process"), &new_con);
    if (rc == 0) {
        computed_context = new_con;
        free(new_con);
    }
    if (rc == 0 && computed_context == mycon.get()) {
        return Error() << "File " << service_path << "(labeled \"" << filecon.get()
                       << "\") has incorrect label or no domain transition from " << mycon.get()
                       << " to another SELinux domain defined. Have you configured your "
                          "service correctly? https://source.android.com/security/selinux/"
                          "device-policy#label_new_services_and_address_denials";
    }
    if (rc < 0) {
        return Error() << "Could not get process context";
    }
    return computed_context;
}

9.4 SetProcessAttributesAndCaps-设置权限和用户

void Service::SetProcessAttributesAndCaps() {
    // Keep capabilites on uid change.
    // capabilities_使能root用户的某些权限;
    if (capabilities_ && proc_attr_.uid) {
        // If Android is running in a container, some securebits might already
        // be locked, so don't change those.
        unsigned long securebits = prctl(PR_GET_SECUREBITS);
        if (securebits == -1UL) {
            PLOG(FATAL) << "prctl(PR_GET_SECUREBITS) failed for " << name_;
        }
        securebits |= SECBIT_KEEP_CAPS | SECBIT_KEEP_CAPS_LOCKED;
        if (prctl(PR_SET_SECUREBITS, securebits) != 0) {
            PLOG(FATAL) << "prctl(PR_SET_SECUREBITS) failed for " << name_;
        }
    }
// 设置进程gid和uid
    if (auto result = SetProcessAttributes(proc_attr_); !result.ok()) {
        LOG(FATAL) << "cannot set attribute for " << name_ << ": " << result.error();
    }

    if (!seclabel_.empty()) {
        // 设置selinux的context
        if (setexeccon(seclabel_.c_str()) < 0) {
            PLOG(FATAL) << "cannot setexeccon('" << seclabel_ << "') for " << name_;
        }
    }
// 设置进程的能力
    if (capabilities_) {
        if (!SetCapsForExec(*capabilities_)) {
            LOG(FATAL) << "cannot set capabilities for " << name_;
        }// 如果设了用户
    } else if (proc_attr_.uid) {
        // Inheritable caps can be non-zero when running in a container.
        // 清除能力
        if (!DropInheritableCaps()) {
            LOG(FATAL) << "cannot drop inheritable caps for " << name_;
        }
    }
}

9.5 ExpandArgsAndExecv-执行命令

// sigstop信号是用来调试的
stop logd
setprop ctl.sigstop_on logd
start logd
ps -e | grep logd
> logd          4343     1   18156   1684 do_signal_stop 538280 T init
gdbclient.py -p 4343
b main
c
c
c
> Breakpoint 1, main (argc=1, argv=0x7ff8c9a488) at system/core/logd/main.cpp:427

static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {
    std::vector<std::string> expanded_args;
    std::vector<char*> c_strings;

    expanded_args.resize(args.size());
    c_strings.push_back(const_cast<char*>(args[0].data()));
    for (std::size_t i = 1; i < args.size(); ++i) {
        auto expanded_arg = ExpandProps(args[i]);
        if (!expanded_arg.ok()) {
            LOG(FATAL) << args[0] << ": cannot expand arguments': " << expanded_arg.error();
        }
        expanded_args[i] = *expanded_arg;
        c_strings.push_back(expanded_args[i].data());
    }
    c_strings.push_back(nullptr);

    if (sigstop) {
        kill(getpid(), SIGSTOP);
    }
// 执行命令
    return execv(c_strings[0], c_strings.data()) == 0;
}

10. BuiltinFunction解析

10.1 do_start

static Result<void> do_start(const BuiltinArguments& args) {
    // start vold
    // 先找到vold的Service
    Service* svc = ServiceList::GetInstance().FindService(args[1]);
    if (!svc) return Error() << "service " << args[1] << " not found";
    //  然后执行Start函数
    if (auto result = svc->Start(); !result.ok()) {
        return ErrorIgnoreEnoent() << "Could not start service: " << result.error();
    }
    return {};
}

11. service util类

11.1 FileDescriptor::Create-打开文件

Result<Descriptor> FileDescriptor::Create() const {
    int flags = (type == "r") ? O_RDONLY : (type == "w") ? O_WRONLY : O_RDWR;

    // Make sure we do not block on open (eg: devices can chose to block on carrier detect).  Our
    // intention is never to delay launch of a service for such a condition.  The service can
    // perform its own blocking on carrier detect.
    unique_fd fd(TEMP_FAILURE_RETRY(open(name.c_str(), flags | O_NONBLOCK | O_CLOEXEC)));

    if (fd < 0) {
        return ErrnoError() << "Failed to open file '" << name << "'";
    }

    // Fixup as we set O_NONBLOCK for open, the intent for fd is to block reads.
    fcntl(fd, F_SETFL, flags);

    LOG(INFO) << "Opened file '" << name << "', flags " << flags;

    return Descriptor(ANDROID_FILE_ENV_PREFIX + name, std::move(fd));
}

11.2 SocketDescriptor::Create-创建sockets

Result<Descriptor> SocketDescriptor::Create(const std::string& global_context) const {
    const auto& socket_context = context.empty() ? global_context : context;
    auto result = CreateSocket(name, type | SOCK_CLOEXEC, passcred, perm, uid, gid, socket_context);
    if (!result.ok()) {
        return result.error();
    }

    return Descriptor(ANDROID_SOCKET_ENV_PREFIX + name, unique_fd(*result));
}

11.3 Publish-清除FD_CLOEXEC标志,然后将fd和文件名设置到环境变量中

void Descriptor::Publish() const {
    auto published_name = name_;

    for (auto& c : published_name) {
        c = isalnum(c) ? c : '_';
    }

    int fd = fd_.get();
    // For safety, the FD is created as CLOEXEC, so that must be removed before publishing.
    auto fd_flags = fcntl(fd, F_GETFD);
    fd_flags &= ~FD_CLOEXEC;
    if (fcntl(fd, F_SETFD, fd_flags) != 0) {
        PLOG(ERROR) << "Failed to remove CLOEXEC from '" << published_name << "'";
    }

    std::string val = std::to_string(fd);
    setenv(published_name.c_str(), val.c_str(), 1);
}

11.4 SetProcessAttributes-设置属性

Result<void> SetProcessAttributes(const ProcessAttributes& attr) {
    // io优先级
    if (attr.ioprio_class != IoSchedClass_NONE) {
        if (android_set_ioprio(getpid(), attr.ioprio_class, attr.ioprio_pri)) {
            PLOG(ERROR) << "failed to set pid " << getpid() << " ioprio=" << attr.ioprio_class
                        << "," << attr.ioprio_pri;
        }
    }

    if (!attr.console.empty()) {
        // 如果要打开串口,则重新创建进程的session
        setsid();
        // 打开串口,设置标准输入输出到console上
        OpenConsole(attr.console);
    } else {
        if (setpgid(0, getpid()) == -1) {
            return ErrnoError() << "setpgid failed";
        }
        SetupStdio(attr.stdio_to_kmsg);
    }
// 设置进程的limits
    for (const auto& rlimit : attr.rlimits) {
        if (setrlimit(rlimit.first, &rlimit.second) == -1) {
            return ErrnoErrorf("setrlimit({}, {{rlim_cur={}, rlim_max={}}}) failed", rlimit.first,
                               rlimit.second.rlim_cur, rlimit.second.rlim_max);
        }
    }
// 设置进程gid,gids,uid等
    if (attr.gid) {
        if (setgid(attr.gid) != 0) {
            return ErrnoError() << "setgid failed";
        }
    }
    if (setgroups(attr.supp_gids.size(), const_cast<gid_t*>(&attr.supp_gids[0])) != 0) {
        return ErrnoError() << "setgroups failed";
    }
    if (attr.uid) {
        if (setuid(attr.uid) != 0) {
            return ErrnoError() << "setuid failed";
        }
    }

    if (attr.priority != 0) {
        // 设置进程优先级
        if (setpriority(PRIO_PROCESS, 0, attr.priority) != 0) {
            return ErrnoError() << "setpriority failed";
        }
    }
    return {};
}

问题

补充

1. c++

1.1 = default关键字

// C++ 的类有四类特殊成员函数,它们分别是:默认构造函数、析构函数、拷贝构造函数以及拷贝赋值运算符。
X() = default; // 表示使用自带的默认的构造函数,该函数比用户自己定义的默认构造函数获得更高的代码效率

1.2 = delete关键字

X3(const X3&) = delete;  // 声明拷贝构造函数为 deleted 函数,将函数禁用,禁止此类操作

1.3 匿名函数

[]        //未定义变量.试图在Lambda内使用任何外部变量都是错误的.
[x, &y]   //x 按值捕获, y 按引用捕获.
[&]       //用到的任何外部变量都隐式按引用捕获,引用捕获就是可以改变外部变量的值
[=]       //用到的任何外部变量都隐式按值捕获
[&, x]    //x显式地按值捕获. 其它变量按引用捕获
[=, &z]   //z按引用捕获. 其它变量按值捕获

1.4 std::variant-相当于union

variant<X, Y, Z> 是可存放 X, Y, Z 这三种类型数据的变体类型
v = variant<int, double, std::string> ,则 v 是一个可存放 int, double, std::string 这三种类型数据的变体类型的对象。
std::queue<std::variant<EventTrigger, PropertyChange, BuiltinAction>> event_queue_ GUARDED_BY(event_queue_lock_);
用户只要在自己的代码中用 GUARDED_BY 表明哪个成员变量是被哪个 mutex 保护的(用法见下图),就可以让 clang 帮你检查有没有遗漏加锁的情况了。别忘了用 clang -Wthread-safety 编译你的代码。
也就说,event_queue_可以存放EventTrigger或者PropertyChange或者BuiltinAction这三种类型数据的变体类型的对象。

2. clang

2.1 FALLTHROUGH_INTENDED [[clang::fallthrough]]

#define FALLTHROUGH_INTENDED [[clang::fallthrough]]  // NOLINT
Clang具有-Wimplicit-fallthrough警告。然后,您可以插入[[clang::fallthrough]];来使警告无效

参考

1. C++11中的匿名函数(lambda函数,lambda表达式)
https://www.cnblogs.com/pzhfei/archive/2013/01/14/lambda_expression.html

posted @ 2021-06-23 19:44  pyjetson  阅读(940)  评论(0编辑  收藏  举报