[android] init进程 .rc文件中service、action的parsing
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相关推荐
- Android Init Language(RC文件)介绍
Android Init Language介绍 基本概念 什么是rc文件? Android Init进程用rc做了什么? 相关内容 Android RC文件应用 Android rc文件语法解析 Li ...
- A20 init.sun7i.rc 文件
如果需要在开机的时候,自动加载一些ko文件,或者通过chmod修改一些设备文件的属性,都可以再 init.sun7i.rc文件中添加insmod和chmod命令来实现. init.sun7i.rc文件 ...
- android5.1 init对rc文件解析执行顺序
android5.1 init对rc文件解析执行顺序 备注,下面on对应的section下面内容的数字,代表内核启动log所在的行数 比如我们的init.rc文件部分内容如下: import /ini ...
- android提取pdf中文字,使用iTextG從Android上的pdf文件中提取文本
當我試圖從SD卡中讀取pdf文件並從中提取文本時,什麼也沒有發生. 沒有錯誤,沒有警告,通知,也沒有結果文件. 我將源文件和結果都存儲在設備的SD卡的根文件夾中. 你們能幫我解決這個問題嗎? 這裏是我 ...
- Android 读取本地txt文件中的内容
Android 读取本地txt文件中的内容 import java.io.BufferedReader; import java.io.File; import java.io.FileInputSt ...
- 第四周作业——统计/etc/init.d/functions文件中每个单词的出现次数,并排序(用grep和sed两种方法分别实现)
统计/etc/init.d/functions文件中每个单词的出现次数,并排序(用grep和sed两种方法分别实现) 方法一:grep实现 grep -o "\<[[:alpha:]] ...
- android 自定义view xml ,Android实现在xml文件中引用自定义View的方法分析
本文实例讲述了Android实现在xml文件中引用自定义View的方法.分享给大家供大家参考,具体如下: 在xml中引用自定义view 方法一: android:layout_width=" ...
- Android Studio在xml文件中编写代码时,关键词没有代码提示补全
问题描述: Android Studio在xml文件中编写代码时,无法自动补全 例如在TextView中输入textSize,没有出现任何代码提示 解决方式: File->Project Str ...
- 在自启动的.rc文件中添加服务
1:根据rc语法格式添加新增service: service btwlansn /vendor/bin/btwlansnclass mainuser rootgroup rootdisabledone ...
- rc文件中增加控件,菜单,子菜单
来自windows核心编程教程 一直以来,都是拖控件,或者用delphi的控件动态创建, 在看核心编程时,发现例子中根本没dfm窗体文件,而且编译出的exe大小十几k. 上代码吧 项目同名的 .RC ...
最新文章
- Caught exception java.lang.interruptedException(在集群上进行多个文件合并压缩时出错)
- 使用Tesseract-OCR训练文字识别记录
- 比赛:小奔与不等四边形solution
- windows nt service 框架
- 倒立摆自动起摆_今天起,中山街坊可以去唱K、游泳、看电影、摆喜酒了!
- spring中bean的作用域属性single与prototype的区别
- linux子系统停止运行,linux 系统部署spring boot 退出连接端后项目停止运行问题
- 安装npm_微信小程序使用npm安装第三方库
- android中实现“再按一次退出”功能
- tshark查看、指定网卡
- poj 2976 Dropping tests 01分数规划
- 后序非递归遍历二叉树的应用
- deep-sort 代码阅读(https://github.com/nwojke/deep_sort)
- 大数据即席查询与分析
- 职称计算机为啥要现场拍照,网上确认/现场确认的照片还没拍?你需要这份拍照攻略!...
- 七年级下册政治知识点总结
- linux运行igv报错,IGV 哐当就不能用了,除了换台电脑还能怎么办?
- Incorrect string value: '\xF0\x9F\x98\x82' for column '' at row 1
- 采用高德地图 实现打车功能代码
- python写完后打不开门_感觉自己python已经入门了,为什么还是没法用Python写好程序?...
热门文章
- OpenGl 游戏编程笔记 第七章:纹理映射 (texture mapping) (一)
- caffe FCN Ubuntu16.0
- Python基于ImageAI实现完整的流程:数据集构建、模型训练、识别预测
- python求解括号匹配的相关问题
- 运行PCL代码出现C2988,C2143,C2913等错误
- 支持向量机_支持向量机(SVM)说明及示例
- latex 行内公式
- FISCO BCOS源码(2)启动顺序
- 并发(concurrent)、并行(parallel)、顺序(sequential)、串行(serial)是什么 区别
- 数组中常用几种的Arrays方法