博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Init.rc配置文件Action字段解析
阅读量:2383 次
发布时间:2019-05-10

本文共 24684 字,大约阅读时间需要 82 分钟。

Parser

class Parser {                                                                       public:                                                                              //  LineCallback is the type for callbacks that can parse a line starting with a given prefix.    //                                                                                 //  They take the form of bool Callback(std::vector
&& args, std::string* err) // // Similar to ParseSection() and ParseLineSection(), this function returns bool with false // indicating a failure and has an std::string* err parameter into which an error string can // be written. using LineCallback = std::function
(std::vector
&&)>; Parser(); bool ParseConfig(const std::string& path); bool ParseConfig(const std::string& path, size_t* parse_errors); void AddSectionParser(const std::string& name, std::unique_ptr
parser); void AddSingleLineParser(const std::string& prefix, LineCallback callback); private: void ParseData(const std::string& filename, const std::string& data, size_t* parse_errors); bool ParseConfigFile(const std::string& path, size_t* parse_errors); bool ParseConfigDir(const std::string& path, size_t* parse_errors); std::map
> section_parsers_; std::vector
> line_callbacks_; };

Parser中包括SectionParser类型的容器section_parsers_。

SectionParser

class SectionParser {                                                             public:                                                                           virtual ~SectionParser() {}                                                     virtual Result
ParseSection(std::vector
&& args, const std::string& filename, int line) = 0; virtual Result
ParseLineSection(std::vector
&&, int) { return Success(); }; virtual Result
EndSection() { return Success(); }; virtual void EndFile(){}; };

SectionParser是一个抽象类。

ActionParser

class ActionParser : public SectionParser {                                          public:                                                                              ActionParser(ActionManager* action_manager, std::vector
* subcontexts) : action_manager_(action_manager), subcontexts_(subcontexts), action_(nullptr) {} Result
ParseSection(std::vector
&& args, const std::string& filename, int line) override; Result
ParseLineSection(std::vector
&& args, int line) override; Result
EndSection() override; private: ActionManager* action_manager_; std::vector
* subcontexts_; std::unique_ptr
action_; };

ImportParser

class ImportParser : public SectionParser {                                                                                                                                                                   public:                                                                              ImportParser(Parser* parser) : parser_(parser) {}                               Result
ParseSection(std::vector
&& args, const std::string& filename, int line) override; void EndFile() override; private: Parser* parser_; // Store filename for later error reporting. std::string filename_; // Vector of imports and their line numbers for later error reporting. std::vector
> imports_; };

ServiceParser

class ServiceParser : public SectionParser {                                         public:                                                                              ServiceParser(ServiceList* service_list, std::vector
* subcontexts) : service_list_(service_list), subcontexts_(subcontexts), service_(nullptr) {} Result
ParseSection(std::vector
&& args, const std::string& filename, int line) override; Result
ParseLineSection(std::vector
&& args, int line) override; Result
EndSection() override; private: bool IsValidName(const std::string& name) const; ServiceList* service_list_; std::vector
* subcontexts_; std::unique_ptr
service_; };

2. 创建section

  1. 创建parser
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {     Parser parser;                                                                                                                                                  parser.AddSectionParser("service", std::make_unique
(&service_list, subcontexts)); parser.AddSectionParser("on", std::make_unique
(&action_manager, subcontexts)); parser.AddSectionParser("import", std::make_unique
(&parser)); return parser; }
  1. 通过AddSectionParser函数,把ServiceParser,ActionParser和ImportParser添加到Paser中的section_parsers_中。
    setction_parsers_类型是map, std::map<std::string, std::unique_ptr>。
    key是"service",“on"和"import”。value是SectionParser,如果是"service",则是ServiceParser;如果是"on",则是ActionParser;如果是"import",则是ImportParser。
class Parser { public:	void AddSectionParser(const std::string& name, std::unique_ptr
parser);private: std::map
> section_parsers_; }void Parser::AddSectionParser(const std::string& name, std::unique_ptr
parser) { section_parsers_[name] = std::move(parser);}

2.1 ActionParser

ActionParser中包含ActionManager指针action_manager_,std::unique_ptr类型的action_。

class ActionParser : public SectionParser {                                       public:                                                                           ActionParser(ActionManager* action_manager, std::vector
* subcontexts) : action_manager_(action_manager), subcontexts_(subcontexts), action_(nullptr) {} Result
ParseSection(std::vector
&& args, const std::string& filename, int line) override; Result
ParseLineSection(std::vector
&& args, int line) override; Result
EndSection() override; private: ActionManager* action_manager_; std::vector
* subcontexts_; std::unique_ptr
action_; };

看下ActionManager中有个Action类型的容器actions_用来包含解析出各个Action。

class ActionManager {                                                             public:                                                                           static ActionManager& GetInstance();  private:     std::vector
> actions_;

每个Action中包含event_trigger_,有Command类型的vector。

class Action {                                                                    public: private: std::string event_trigger_;   std::vector commands_;  static const KeywordFunctionMap* function_map_; };

举例

on fs                                                                                   mount_all ./fstab.uml                                                                                                                                   on early-init                                                                                                                                                                                                   # Set init and its forked children's oom_adj.                                   write /proc/1/oom_score_adj -1000

解析步骤:

1)在main函数中,创建ActionManager对象am,并且调用函数LoadBootScripts。

int main(int argc, char** argv) { 711     ActionManager& am = ActionManager::GetInstance();                           712     ServiceList& sm = ServiceList::GetInstance();                               713                                                                                  714     LoadBootScripts(am, sm); }

2)在LoadBootScripts函数中,在111行使用CreateParser()函数创建Parser变量parser,在115行使用ParseConfig()函数解析配置文件init.rc。

110 static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {111     Parser parser = CreateParser(action_manager, service_list);                 112                                                                                                          113     std::string bootscript = GetProperty("ro.boot.init_rc", "");                114     if (bootscript.empty()) {                                                                            115         parser.ParseConfig("/init.rc"); 116    }

3)在函数CreateParser中,通过AddSectionParser()函数中,把“service”和ServiceParser类型对象section_parsers_。

std::make_unique(&service_list, subcontexts)放进Parser类中的.
parser.section_parsers_[“on”]=std::make_unique(&am,subcontexts);

100 Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) { 101     Parser parser;                                                              102                                                                                 103     parser.AddSectionParser("service", std::make_unique
(&service_list, subcontexts));104 parser.AddSectionParser("on", std::make_unique
(&action_manager, subcontexts));...........107 return parser; 108 } 34 void Parser::AddSectionParser(const std::string& name, std::unique_ptr
parser) { 35 section_parsers_[name] = std::move(parser); 36 } 61 class Parser { 84 std::map
> section_parsers_; 85 std::vector
> line_callbacks_; 86 };

4)parser.ParseConfig("/init.rc"),使用ParseConfig函数解析配置文件init.rc。

42 void Parser::ParseData(const std::string& filename, const std::string& data, size_t* parse_errors) { 43     // TODO: Use a parser with const input and remove this copy                  44     std::vector
data_copy(data.begin(), data.end()); 45 data_copy.push_back('\0'); 46 47 parse_state state; 48 state.line = 0; 49 state.ptr = &data_copy[0]; 50 state.nexttoken = 0; 51 52 SectionParser* section_parser = nullptr; 53 int section_start_line = -1; 54 std::vector
args; 55 56 auto end_section = [&] { 57 if (section_parser == nullptr) return; 58 59 if (auto result = section_parser->EndSection(); !result) { 60 (*parse_errors)++; 61 LOG(ERROR) << filename << ": " << section_start_line << ": " << result.error(); 62 } 63 64 section_parser = nullptr; 65 section_start_line = -1; 66 }; 67 68 for (;;) { 69 switch (next_token(&state)) { 70 case T_EOF: 71 end_section(); 72 return; 73 case T_NEWLINE: 74 state.line++; 75 if (args.empty()) break; 76 // If we have a line matching a prefix we recognize, call its callback and unset any 77 // current section parsers. This is meant for /sys/ and /dev/ line entries for 78 // uevent. 79 for (const auto& [prefix, callback] : line_callbacks_) { 80 if (android::base::StartsWith(args[0], prefix)) { 81 end_section(); 82 83 if (auto result = callback(std::move(args)); !result) { 84 (*parse_errors)++; 85 LOG(ERROR) << filename << ": " << state.line << ": " << result.error(); 86 } 87 break; 88 } 89 } 90 if (section_parsers_.count(args[0])) { 91 end_section(); 92 section_parser = section_parsers_[args[0]].get(); 93 section_start_line = state.line; 94 if (auto result = 95 section_parser->ParseSection(std::move(args), filename, state.line); 96 !result) { 97 (*parse_errors)++; 98 LOG(ERROR) << filename << ": " << state.line << ": " << result.error(); 99 section_parser = nullptr; 100 } 101 } else if (section_parser) { 102 if (auto result = section_parser->ParseLineSection(std::move(args), state.line);103 !result) { 104 (*parse_errors)++; 105 LOG(ERROR) << filename << ": " << state.line << ": " << result.error();106 } 107 } 108 args.clear(); 109 break; 110 case T_TEXT: 111 args.emplace_back(state.text); 112 break; 113 } 114 }

next_token函数参考这篇文章

下面是配置文件内容:

on fs                                                                                   mount_all ./fstab.uml                                                                                                                                   on early-init                                                                                                                                                                                                   # Set init and its forked children's oom_adj.                                   write /proc/1/oom_score_adj -1000

1)第1次执行next_token()后,第1个字符串是"on",保存在state.text;因为"on"后面跟着空格,则next_token()返回T_TEXT,执行111行args.emplace_back(state.text)则args[0]=“on”;

2)第2次执行next_token()后,第2个字符串是"on",保存在state.text;因为"on"后面跟着空格,则next_token()返回T_TEXT,执行111行args.emplace_back(state.text)则args[1]=“fs”;
3)第3次执行next_token()后,则返回T_NEWLINE。
4)
4.1)在90行中,通过section_parsers_.count(args[0]),判断section_parsers_是否有key是"on",在之前创建了"on"、“import"和"service”,所以进入91行。
4.2)在91行,执行end_section(),里面section_parser->EndSection();EndSection中会执行,
action_manager_->AddAction(std::move(action_));
把action_加入到ActionManager中的std::vector<std::unique_ptr> actions_的容器中。
4.3)在95行,执行ParseSection,刚好把args[1]=“fs”,赋值给event_trigger,组成action,赋值给ActionParser中的_action。
4.4) 处理配置文件第2行" mount_all ./fstab.uml",则args[0]=mount_all,args[1]=“fstab.uml”。
显然section_parsers_中查询"mount_all"的key值,没有这个key值。运行到101行,section_parser存在,执行函数ParseLineSection()。
4.5) 在ActionParser中的ParseLineSection函数中,执行action_->AddCommand函数。
4.6) AddCommand函数中,在93行的function_map_中的FindFunction函数,通过args[0]="mount_all"查询函数表中,是否存在这个函数,如果存在则把这个命令"mount_all"以及参数"fstab.uml"放入
commands_这个链表中。

查询表在这个函数中:

1030 const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {                1031     constexpr std::size_t kMax = std::numeric_limits
::max(); 1032 // clang-format off 1033 static const Map builtin_functions = { 1034 {"bootchart", {1, 1, {false, do_bootchart}}}, 1035 {"chmod", {2, 2, {true, do_chmod}}}, 1036 {"chown", {2, 3, {true, do_chown}}}, 1037 {"class_reset", {1, 1, {false, do_class_reset}}}, 1038 {"class_restart", {1, 1, {false, do_class_restart}}}, 1039 {"class_start", {1, 1, {false, do_class_start}}}, 1040 {"class_stop", {1, 1, {false, do_class_stop}}}, 1041 {"copy", {2, 2, {true, do_copy}}}, 1042 {"domainname", {1, 1, {true, do_domainname}}}, 1043 {"enable", {1, 1, {false, do_enable}}}, 1044 {"exec", {1, kMax, {false, do_exec}}}, 1045 {"exec_background", {1, kMax, {false, do_exec_background}}},1046 {"exec_start", {1, 1, {false, do_exec_start}}}, 1047 {"export", {2, 2, {false, do_export}}}, 1048 {"hostname", {1, 1, {true, do_hostname}}}, 1049 {"ifup", {1, 1, {true, do_ifup}}}, 1050 {"init_user0", {0, 0, {false, do_init_user0}}}, 1051 {"insmod", {1, kMax, {true, do_insmod}}}, 1052 {"installkey", {1, 1, {false, do_installkey}}}, 1053 {"load_persist_props", {0, 0, {false, do_load_persist_props}}},1054 {"load_system_props", {0, 0, {false, do_load_system_props}}},1055 {"loglevel", {1, 1, {false, do_loglevel}}}, 1056 {"mkdir", {1, 4, {true, do_mkdir}}}, 1057 // TODO: Do mount operations in vendor_init. 1058 // mount_all is currently too complex to run in vendor_init as it queues action triggers,1059 // imports rc scripts, etc. It should be simplified and run in vendor_init context.1060 // mount and umount are run in the same context as mount_all for symmetry.1061 {"mount_all", {1, kMax, {false, do_mount_all}}}, 1062 {"mount", {3, kMax, {false, do_mount}}}, 1063 {"umount", {1, 1, {false, do_umount}}}, 1064 {"readahead", {1, 2, {true, do_readahead}}}, 1065 {"restart", {1, 1, {false, do_restart}}}, 1066 {"restorecon", {1, kMax, {true, do_restorecon}}}, 1067 {"restorecon_recursive", {1, kMax, {true, do_restorecon_recursive}}},1068 {"rm", {1, 1, {true, do_rm}}}, 1069 {"rmdir", {1, 1, {true, do_rmdir}}}, 1070 {"setprop", {2, 2, {true, do_setprop}}}, 1071 {"setrlimit", {3, 3, {false, do_setrlimit}}}, 1072 {"start", {1, 1, {false, do_start}}}, 1073 {"stop", {1, 1, {false, do_stop}}}, 1074 {"swapon_all", {1, 1, {false, do_swapon_all}}}, 1075 {"symlink", {2, 2, {true, do_symlink}}}, 1076 {"sysclktz", {1, 1, {false, do_sysclktz}}}, 1077 {"trigger", {1, 1, {false, do_trigger}}}, 1078 {"verity_load_state", {0, 0, {false, do_verity_load_state}}},1079 {"verity_update_state", {0, 0, {false, do_verity_update_state}}},1080 {"wait", {1, 2, {true, do_wait}}}, 1081 {"wait_for_prop", {2, 2, {false, do_wait_for_prop}}}, 1082 {"write", {2, 2, {true, do_write}}}, 1083 }; 1084 // clang-format on 1085 return builtin_functions; 1086 }

转载地址:http://lafab.baihongyu.com/

你可能感兴趣的文章
Java语言程序设计(基础篇)
查看>>
大型网站技术架构:核心原理与案例分析
查看>>
JAVA并发编程实战
查看>>
RabbitMQ实战++高效部署分布式消息队列
查看>>
微服务设计
查看>>
Spring Cloud微服务实战
查看>>
C++ static 语义
查看>>
C++ static 语义
查看>>
Linux Cgroups概述
查看>>
centos7 硬盘性能测试
查看>>
cgroup使用--cpu资源限制
查看>>
cgroup使用--memory资源限制
查看>>
Redis 单机环境搭建
查看>>
elasticsearch 单机环境搭建
查看>>
spark 独立模式部署
查看>>
Redis 基础命令 --- String篇
查看>>
Redis 基础命令 --- Hash篇
查看>>
Redis 基础命令 --- List篇
查看>>
Redis 基础命令 --- Set篇
查看>>
Redis数据库篇 -- 生存时间
查看>>