init进程code位置:system/core/init

system/core/init/README.md,这个文件是描述rc文件语法的。

在.rc文件中,有3中类型:

1. service

2. on(action)

3. import

init.cpp

Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {Parser parser;parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, subcontexts));parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, subcontexts));parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));return parser;
}

  

以service开头,表示是service;以on开头表示是Action。

对于service行或者on行,调用ParseSection(),在ParseSection中会创建Servcie或者Action对象。

然后处理service或者on行后的行(service或者action的子行)。对于每个子行,都会调用ParseLineSection(),在这个函数中,对于service,会执行对应的函数,比如对于writepid,会调用Servcie::ParseWritepid();

对于action,会执行AddCommand()。

等这个service或者action的所有子行都parse完后,在parse下一个servcie或者action前(调用ParseSection之前),会call endSection(),这个函数会call EndSection。在EndSection()中,对于service,会执行add service;对于action,会add action到action manager。

对于service,对应文件是service.cpp;对于action,对应文件是action_parser.cpp。

parse .rc文件的入口:init.cpp/LoadBootScripts()

Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {Parser parser;parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, subcontexts));parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, subcontexts));parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));return parser;
}static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {Parser parser = CreateParser(action_manager, service_list);std::string bootscript = GetProperty("ro.boot.init_rc", "");if (bootscript.empty()) {parser.ParseConfig("/init.rc");if (!parser.ParseConfig("/system/etc/init")) {late_import_paths.emplace_back("/system/etc/init");}if (!parser.ParseConfig("/product/etc/init")) {late_import_paths.emplace_back("/product/etc/init");}if (!parser.ParseConfig("/odm/etc/init")) {late_import_paths.emplace_back("/odm/etc/init");}if (!parser.ParseConfig("/vendor/etc/init")) {late_import_paths.emplace_back("/vendor/etc/init");}} else {parser.ParseConfig(bootscript);}
}

ParseData()函数中通过next_token(&state)将一行中的所有单词(以比如空格分隔)走T_TEXT case调用args.emplace_back(state.text)加到args中。当一行结束时(\n符),next_token()会返回T_NEWLINE,在T_NEWLINE case中处理这一行。处理完后,将args clear。

void Parser::ParseData(const std::string& filename, const std::string& data, size_t* parse_errors) {// TODO: Use a parser with const input and remove this copystd::vector<char> data_copy(data.begin(), data.end());data_copy.push_back('\0');parse_state state;state.line = 0;state.ptr = &data_copy[0];state.nexttoken = 0;SectionParser* section_parser = nullptr;int section_start_line = -1;std::vector<std::string> args;auto end_section = [&] {if (section_parser == nullptr) return;if (auto result = section_parser->EndSection(); !result) {(*parse_errors)++;LOG(ERROR) << filename << ": " << section_start_line << ": " << result.error();}section_parser = nullptr;section_start_line = -1;};for (;;) {switch (next_token(&state)) {case T_EOF:end_section();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.for (const auto& [prefix, callback] : line_callbacks_) {if (android::base::StartsWith(args[0], prefix)) {end_section();if (auto result = callback(std::move(args)); !result) {(*parse_errors)++;LOG(ERROR) << filename << ": " << state.line << ": " << result.error();}break;}}if (section_parsers_.count(args[0])) {end_section();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) {(*parse_errors)++;LOG(ERROR) << filename << ": " << state.line << ": " << result.error();section_parser = nullptr;}} else if (section_parser) {if (auto result = section_parser->ParseLineSection(std::move(args), state.line);!result) {(*parse_errors)++;LOG(ERROR) << filename << ": " << state.line << ": " << result.error();}}args.clear();break;case T_TEXT:args.emplace_back(state.text);break;}}
}

service class有一个Action的成员--onrestart_

在parse一个service时,例如下面的audioserver.rc,对于service里的onrestart行,就是对应一个command。这个command会被add到onrestart_ Action中,是通过如下的方法add的:

在service.cpp里有一个Service::OptionParserMap::map()函数,根据key onrestart找到其对应的函数:Service::ParseOnrestart(),然后执行这个函数。这个函数会调用Action.cpp中的addcommand函数。

frameworks/av/media/audioserver/audioserver.rc

service audioserver /system/bin/audioserverclass coreuser audioserver# media gid needed for /dev/fm (radio) and for /data/misc/media (tee)group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acctioprio rt 4writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasksonrestart restart vendor.audio-hal-2-0# Keep the original service name for backward compatibility when upgrading# O-MR1 devices with framework-only.onrestart restart audio-hal-2-0on property:vts.native_server.on=1stop audioserver
on property:vts.native_server.on=0start audioserver

  

const Service::OptionParserMap::Map& Service::OptionParserMap::map() const {constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();// clang-format offstatic const Map option_parsers = {{"capabilities",{1,     kMax, &Service::ParseCapabilities}},{"class",       {1,     kMax, &Service::ParseClass}},{"console",     {0,     1,    &Service::ParseConsole}},{"critical",    {0,     0,    &Service::ParseCritical}},{"disabled",    {0,     0,    &Service::ParseDisabled}},{"enter_namespace",{2,     2,    &Service::ParseEnterNamespace}},{"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::ParseGroup}},{"interface",   {2,     2,    &Service::ParseInterface}},{"ioprio",      {2,     2,    &Service::ParseIoprio}},{"priority",    {1,     1,    &Service::ParsePriority}},{"keycodes",    {1,     kMax, &Service::ParseKeycodes}},{"oneshot",     {0,     0,    &Service::ParseOneshot}},{"onrestart",   {1,     kMax, &Service::ParseOnrestart}},{"override",    {0,     0,    &Service::ParseOverride}},{"oom_score_adjust",{1,     1,    &Service::ParseOomScoreAdjust}},{"memcg.swappiness",{1,     1,    &Service::ParseMemcgSwappiness}},{"memcg.soft_limit_in_bytes",{1,     1,    &Service::ParseMemcgSoftLimitInBytes}},{"memcg.limit_in_bytes",{1,     1,    &Service::ParseMemcgLimitInBytes}},{"namespace",   {1,     2,    &Service::ParseNamespace}},{"rlimit",      {3,     3,    &Service::ParseProcessRlimit}},{"seclabel",    {1,     1,    &Service::ParseSeclabel}},{"setenv",      {2,     2,    &Service::ParseSetenv}},{"shutdown",    {1,     1,    &Service::ParseShutdown}},{"socket",      {3,     6,    &Service::ParseSocket}},{"file",        {2,     2,    &Service::ParseFile}},{"user",        {1,     1,    &Service::ParseUser}},{"writepid",    {1,     kMax, &Service::ParseWritepid}},};// clang-format onreturn option_parsers;
}

Action.cpp中的addcommand函数会根据builtins.cpp中的Map builtin_fucnctions找到对应的函数,比如上面例子中的onrestart restart vendor.audio-hal-2-0,就是根据key restart找到对应的函数do_restart。

然后会根据找到的这个函数和args等其它参数构造一个Command,然后将这个Command对象add到commands_中。

const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();// clang-format offstatic const Map 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_restart",           {1,     1,    {false,  do_class_restart}}},{"class_start",             {1,     1,    {false,  do_class_start}}},{"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}}},{"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}}},{"mkdir",                   {1,     4,    {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",               {1,     kMax, {false,  do_mount_all}}},{"mount",                   {3,     kMax, {false,  do_mount}}},{"umount",                  {1,     1,    {false,  do_umount}}},{"readahead",               {1,     2,    {true,   do_readahead}}},{"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",              {1,     1,    {false,  do_swapon_all}}},{"symlink",                 {2,     2,    {true,   do_symlink}}},{"sysclktz",                {1,     1,    {false,  do_sysclktz}}},{"trigger",                 {1,     1,    {false,  do_trigger}}},{"verity_load_state",       {0,     0,    {false,  do_verity_load_state}}},{"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 onreturn builtin_functions;
}

对于service来说,只有onrestart才有对应的command,像writepid、group等等其它都是没有对应的command的。

对于service定义的command(onrestart),什么时候执行这个command呢?

这个是在service.cpp中的onrestart_.ExecuteAllCommands()的时候去执行的。

这个onrestart_.ExecuteAllCommands()对于media进程来说,它没有添加command(如下面的mediaserver.rc),所以不会做什么事情。

frameworks/av/media/mediaserver/mediaserver.rc

service media /system/bin/mediaserverclass mainuser mediagroup audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrmioprio rt 4writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks

  

  

  

转载于:https://www.cnblogs.com/aspirs/p/11405877.html

[android] init进程 .rc文件中service、action的parsing相关推荐

  1. Android Init Language(RC文件)介绍

    Android Init Language介绍 基本概念 什么是rc文件? Android Init进程用rc做了什么? 相关内容 Android RC文件应用 Android rc文件语法解析 Li ...

  2. A20 init.sun7i.rc 文件

    如果需要在开机的时候,自动加载一些ko文件,或者通过chmod修改一些设备文件的属性,都可以再 init.sun7i.rc文件中添加insmod和chmod命令来实现. init.sun7i.rc文件 ...

  3. android5.1 init对rc文件解析执行顺序

    android5.1 init对rc文件解析执行顺序 备注,下面on对应的section下面内容的数字,代表内核启动log所在的行数 比如我们的init.rc文件部分内容如下: import /ini ...

  4. android提取pdf中文字,使用iTextG從Android上的pdf文件中提取文本

    當我試圖從SD卡中讀取pdf文件並從中提取文本時,什麼也沒有發生. 沒有錯誤,沒有警告,通知,也沒有結果文件. 我將源文件和結果都存儲在設備的SD卡的根文件夾中. 你們能幫我解決這個問題嗎? 這裏是我 ...

  5. Android 读取本地txt文件中的内容

    Android 读取本地txt文件中的内容 import java.io.BufferedReader; import java.io.File; import java.io.FileInputSt ...

  6. 第四周作业——统计/etc/init.d/functions文件中每个单词的出现次数,并排序(用grep和sed两种方法分别实现)

    统计/etc/init.d/functions文件中每个单词的出现次数,并排序(用grep和sed两种方法分别实现) 方法一:grep实现 grep -o "\<[[:alpha:]] ...

  7. android 自定义view xml ,Android实现在xml文件中引用自定义View的方法分析

    本文实例讲述了Android实现在xml文件中引用自定义View的方法.分享给大家供大家参考,具体如下: 在xml中引用自定义view 方法一: android:layout_width=" ...

  8. Android Studio在xml文件中编写代码时,关键词没有代码提示补全

    问题描述: Android Studio在xml文件中编写代码时,无法自动补全 例如在TextView中输入textSize,没有出现任何代码提示 解决方式: File->Project Str ...

  9. 在自启动的.rc文件中添加服务

    1:根据rc语法格式添加新增service: service btwlansn /vendor/bin/btwlansnclass mainuser rootgroup rootdisabledone ...

  10. rc文件中增加控件,菜单,子菜单

    来自windows核心编程教程 一直以来,都是拖控件,或者用delphi的控件动态创建, 在看核心编程时,发现例子中根本没dfm窗体文件,而且编译出的exe大小十几k. 上代码吧 项目同名的  .RC ...

最新文章

  1. Caught exception java.lang.interruptedException(在集群上进行多个文件合并压缩时出错)
  2. 使用Tesseract-OCR训练文字识别记录
  3. 比赛:小奔与不等四边形solution
  4. windows nt service 框架
  5. 倒立摆自动起摆_今天起,中山街坊可以去唱K、游泳、看电影、摆喜酒了!
  6. spring中bean的作用域属性single与prototype的区别
  7. linux子系统停止运行,linux 系统部署spring boot 退出连接端后项目停止运行问题
  8. 安装npm_微信小程序使用npm安装第三方库
  9. android中实现“再按一次退出”功能
  10. tshark查看、指定网卡
  11. poj 2976 Dropping tests 01分数规划
  12. 后序非递归遍历二叉树的应用
  13. deep-sort 代码阅读(https://github.com/nwojke/deep_sort)
  14. 大数据即席查询与分析
  15. 职称计算机为啥要现场拍照,网上确认/现场确认的照片还没拍?你需要这份拍照攻略!...
  16. 七年级下册政治知识点总结
  17. linux运行igv报错,IGV 哐当就不能用了,除了换台电脑还能怎么办?
  18. Incorrect string value: '\xF0\x9F\x98\x82' for column '' at row 1
  19. 采用高德地图 实现打车功能代码
  20. python写完后打不开门_感觉自己python已经入门了,为什么还是没法用Python写好程序?...

热门文章

  1. OpenGl 游戏编程笔记 第七章:纹理映射 (texture mapping) (一)
  2. caffe FCN Ubuntu16.0
  3. Python基于ImageAI实现完整的流程:数据集构建、模型训练、识别预测
  4. python求解括号匹配的相关问题
  5. 运行PCL代码出现C2988,C2143,C2913等错误
  6. 支持向量机_支持向量机(SVM)说明及示例
  7. latex 行内公式
  8. FISCO BCOS源码(2)启动顺序
  9. 并发(concurrent)、并行(parallel)、顺序(sequential)、串行(serial)是什么 区别
  10. 数组中常用几种的Arrays方法