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