在解析Init.rc之前需要对init.rc文件有一个认识,init.rc是由一种被称为"Android初始化语言"(Android Init Language,这里简称为AIL)的脚本写成的文件.该语言是由语句组成的,主要包含了五种类型的语句:

  1. Action
  2. Commands
  3. Services
  4. Options
  5. Import

 在init.rc文件中一条语句通常占用一行,单词之间是用空格符来相隔的。如果一行写不下,可以在行尾加上反斜杠,来连接下一行。也就是说,可以用反斜杠将多行代码连接成一行代码。并且使用#来进行注释。在init.rc中分成三个部分(Section),而每一部分的开头需要指定on(Actions)、service(Services)或import。也就是说,每一个Actions, import或 Services确定一个Section。而所有的Commands和Options只能属于最近定义的Section。如果Commands和 Options在第一个Section之前被定义,它们将被忽略。Actions和Services的名称必须唯一。如果有两个或多个Actions或Services拥有同样的名称,那么init在执行它们时将抛出错误,并忽略这些Action和Service。

我们在之前分析init进程时讲到过在init.cpp的main函数中将service, on, import设置为三个Section.

[cpp] view plain copy
  1. Parser& parser = Parser::GetInstance();
  2. parser.AddSectionParser("service",std::make_unique<ServiceParser>());
  3. parser.AddSectionParser("on", std::make_unique<ActionParser>());
  4. parser.AddSectionParser("import", std::make_unique<ImportParser>());

下面来看一下Action,Service,Import都是该怎么定义的.

在system/core/init/readme.txt中详细说明

Action的格式如下:

[cpp] view plain copy
  1. on <trigger> [&& <trigger>]*     //设置触发器
  2. <command>
  3. <command>                  //动作触发之后要执行的命令
  4. <command>
[plain] view plain copy
  1. Triggers                    //对trigger的详细讲解
  2. --------
  3. Triggers are strings which can be used to match certain kinds of
  4. events and used to cause an action to occur.
  5. Triggers are subdivided into event triggers and property triggers.
  6. Event triggers are strings triggered by the 'trigger' command or by
  7. the QueueEventTrigger() function within the init executable.  These
  8. take the form of a simple string such as 'boot' or 'late-init'.
  9. Property triggers are strings triggered when a named property changes
  10. value to a given new value or when a named property changes value to
  11. any new value.  These take the form of 'property:<name>=<value>' and
  12. 'property:<name>=*' respectively.  Property triggers are additionally
  13. evaluated and triggered accordingly during the initial boot phase of
  14. init.
  15. An Action can have multiple property triggers but may only have one
  16. event trigger.
  17. For example:
  18. 'on boot && property:a=b' defines an action that is only executed when
  19. the 'boot' event trigger happens and the property a equals b.
  20. 'on property:a=b && property:c=d' defines an action that is executed
  21. at three times,
  22. 1) During initial boot if property a=b and property c=d
  23. 2) Any time that property a transitions to value b, while property
  24. c already equals d.
  25. 3) Any time that property c transitions to value d, while property
  26. a already equals b.

在init.cpp中设置的trigger有early-init, init, late-init等, 当trigger被触发时就执行command,

我们来看一个标准的Action:

[cpp] view plain copy
  1. on early-init     //trigger为early-init,在init.cpp的main函数中设置过
  2. # Set init and its forked children's oom_adj.
  3. write /proc/1/oom_score_adj -1000   //调用do_write函数, 写入oom_score_adj为-1000
  4. # Disable sysrq from keyboard
  5. write /proc/sys/kernel/sysrq 0
  6. # Set the security context of /adb_keys if present.
  7. restorecon /adb_keys       //为adb_keys 重置安全上下文
  8. # Shouldn't be necessary, but sdcard won't start without it. http://b/22568628.
  9. mkdir /mnt 0775 root system    //创建mnt目录
  10. # Set the security context of /postinstall if present.
  11. restorecon /postinstall
  12. start ueventd       //调用函数do_start, 启动服务uevent,

下面对所有命令详细讲解.

[cpp] view plain copy
  1. bootchart_init    //初始化bootchart,用于获取开机过程系统信息
  2. Start bootcharting if configured (see below).
  3. This is included in the default init.rc.
  4. chmod <octal-mode> <path>  //改变文件的权限
  5. Change file access permissions.
  6. chown <owner> <group> <path>  //改变文件的群组
  7. Change file owner and group.
  8. class_start <serviceclass>   //启动所有具有特定class的services
  9. Start all services of the specified class if they are
  10. not already running.
  11. class_stop <serviceclass>      //将具有特定class的所有运行中的services给停止或者diasble
  12. Stop and disable all services of the specified class if they are
  13. currently running.
  14. class_reset <serviceclass>   //先将services stop掉, 之后可能会通过class_start再重新启动起来
  15. Stop all services of the specified class if they are
  16. currently running, without disabling them. They can be restarted
  17. later using class_start.
  18. copy <src> <dst>    //复制文件
  19. Copies a file. Similar to write, but useful for binary/large
  20. amounts of data.
  21. domainname <name>
  22. Set the domain name.
  23. enable <servicename>  //如果services没有特定disable,就将他设为enable
  24. Turns a disabled service into an enabled one as if the service did not
  25. specify disabled.
  26. If the service is supposed to be running, it will be started now.
  27. Typically used when the bootloader sets a variable that indicates a specific
  28. service should be started when needed. E.g.
  29. on property:ro.boot.myfancyhardware=1
  30. enable my_fancy_service_for_my_fancy_hardware
  31. exec [ <seclabel> [ <user> [ <group> ]* ] ] -- <command> [ <argument> ]*    //创建执行程序.比较重要,后面启动service要用到
  32. Fork and execute command with the given arguments. The command starts
  33. after "--" so that an optional security context, user, and supplementary
  34. groups can be provided. No other commands will be run until this one
  35. export <name> <value>      //在全局设置环境变量
  36. Set the environment variable <name> equal to <value> in the
  37. global environment (which will be inherited by all processes
  38. started after this command is executed)
  39. hostname <name>       //设置主机名称
  40. Set the host name.
  41. ifup <interface>       //启动网络接口
  42. Bring the network interface <interface> online.
  43. insmod <path>    //在某个路径安装一个模块
  44. Install the module at <path>
  45. load_all_props    //加载所有的配置
  46. Loads properties from /system, /vendor, et cetera.
  47. This is included in the default init.rc.
  48. load_persist_props  //当data加密时加载一些配置
  49. Loads persistent properties when /data has been decrypted.
  50. This is included in the default init.rc.
  51. loglevel <level>       //设置kernel log level
  52. Sets the kernel log level to level. Properties are expanded within <level>.
  53. mkdir <path> [mode] [owner] [group]    //创建文件夹
  54. Create a directory at <path>, optionally with the given mode, owner, and
  55. group. If not provided, the directory is created with permissions 755 and
  56. owned by the root user and root group. If provided, the mode, owner and group
  57. will be updated if the directory exists already.
  58. mount_all <fstab> [ <path> ]*      //挂载
  59. Calls fs_mgr_mount_all on the given fs_mgr-format fstab and imports .rc files
  60. at the specified paths (e.g., on the partitions just mounted). Refer to the
  61. section of "Init .rc Files" for detail.
  62. mount <type> <device> <dir> [ <flag> ]* [<options>]   //在dir文件夹下面挂载设备
  63. Attempt to mount the named device at the directory <dir>
  64. <device> may be of the form mtd@name to specify a mtd block
  65. device by name.
  66. <flag>s include "ro", "rw", "remount", "noatime", ...
  67. <options> include "barrier=1", "noauto_da_alloc", "discard", ... as
  68. a comma separated string, eg: barrier=1,noauto_da_alloc
  69. powerctl
  70. Internal implementation detail used to respond to changes to the
  71. "sys.powerctl" system property, used to implement rebooting.
  72. restart <service>          //重启服务
  73. Like stop, but doesn't disable the service.
  74. restorecon <path> [ <path> ]*      //重置文件的安全上下文
  75. Restore the file named by <path> to the security context specified
  76. in the file_contexts configuration.
  77. Not required for directories created by the init.rc as these are
  78. automatically labeled correctly by init.
  79. restorecon_recursive <path> [ <path> ]*//一般都是 selinux完成初始化之后又创建、或者改变的目录
  80. Recursively restore the directory tree named by <path> to the
  81. security contexts specified in the file_contexts configuration.
  82. rm <path>         //删除文件
  83. Calls unlink(2) on the given path. You might want to
  84. use "exec -- rm ..." instead (provided the system partition is
  85. already mounted).
  86. rmdir <path>     //删除文件夹
  87. Calls rmdir(2) on the given path.
  88. setprop <name> <value>    //设置属性
  89. Set system property <name> to <value>. Properties are expanded
  90. within <value>.
  91. setrlimit <resource> <cur> <max>
  92. Set the rlimit for a resource.
  93. start <service>     //如果service没有启动,就将他启动起来
  94. Start a service running if it is not already running.
  95. stop <service> //将运行的服务停掉
  96. Stop a service from running if it is currently running.
  97. swapon_all <fstab>
  98. Calls fs_mgr_swapon_all on the given fstab file.
  99. symlink <target> <path>
  100. Create a symbolic link at <path> with the value <target>
  101. sysclktz <mins_west_of_gmt>
  102. Set the system clock base (0 if system clock ticks in GMT)
  103. trigger <event>      //触发一个事件
  104. Trigger an event.  Used to queue an action from another
  105. action.
  106. verity_load_state
  107. Internal implementation detail used to load dm-verity state.
  108. verity_update_state <mount_point>
  109. Internal implementation detail used to update dm-verity state and
  110. set the partition.<mount_point>.verified properties used by adb remount
  111. because fs_mgr can't set them directly itself.
  112. wait <path> [ <timeout> ]     //等待
  113. Poll for the existence of the given file and return when found,
  114. or the timeout has been reached. If timeout is not specified it
  115. currently defaults to five seconds.
  116. write <path> <content>   //写文件
  117. Open the file at <path> and write a string to it with write(2).
  118. If the file does not exist, it will be created. If it does exist,
  119. it will be truncated. Properties are expanded within <content>.

这些命令在执行时会通过在BuiltinFunctionMap中的对应关系找到自己对应的函数.

Services格式如下:

[cpp] view plain copy
  1. service <name> <pathname> [ <argument> ]*   //service的名字,启动路径,以及参数
  2. <option>       //option影响什么时候,如何启动services
  3. <option>
  4. ...
[cpp] view plain copy
  1. Options        //所有的options命令如下
  2. -------
  3. Options are modifiers to services.  They affect how and when init
  4. runs the service.
  5. critical     //表示该service非常重要,如果退出四次以上在4分钟内,设备就会重启进入recovery模式
  6. This is a device-critical service. If it exits more than four times in
  7. four minutes, the device will reboot into recovery mode.
  8. disabled    //该services不能通过class启动,只能通过name将他启动
  9. This service will not automatically start with its class.
  10. It must be explicitly started by name.
  11. setenv <name> <value>   //设置环境变量
  12. Set the environment variable <name> to <value> in the launched process.
  13. socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]
  14. Create a unix domain socket named /dev/socket/<name> and pass
  15. its fd to the launched process.  <type> must be "dgram", "stream" or "seqpacket".
  16. User and group default to 0.
  17. 'seclabel' is the SELinux security context for the socket.
  18. It defaults to the service security context, as specified by seclabel or
  19. computed based on the service executable file security context.
  20. user <username>
  21. Change to username before exec'ing this service.
  22. Currently defaults to root.  (??? probably should default to nobody)
  23. As of Android M, processes should use this option even if they
  24. require linux capabilities.  Previously, to acquire linux
  25. capabilities, a process would need to run as root, request the
  26. capabilities, then drop to its desired uid.  There is a new
  27. mechanism through fs_config that allows device manufacturers to add
  28. linux capabilities to specific binaries on a file system that should
  29. be used instead. This mechanism is described on
  30. http://source.android.com/devices/tech/config/filesystem.html.  When
  31. using this new mechanism, processes can use the user option to
  32. select their desired uid without ever running as root.
  33. group <groupname> [ <groupname> ]*
  34. Change to groupname before exec'ing this service.  Additional
  35. groupnames beyond the (required) first one are used to set the
  36. supplemental groups of the process (via setgroups()).
  37. Currently defaults to root.  (??? probably should default to nobody)
  38. seclabel <seclabel>
  39. Change to 'seclabel' before exec'ing this service.
  40. Primarily for use by services run from the rootfs, e.g. ueventd, adbd.
  41. Services on the system partition can instead use policy-defined transitions
  42. based on their file security context.
  43. If not specified and no transition is defined in policy, defaults to the init context.
  44. oneshot
  45. Do not restart the service when it exits.
  46. class <name>   //一个特定的name, 所有有这个name的service统一管理,一起启动,一起stop
  47. Specify a class name for the service.  All services in a
  48. named class may be started or stopped together.  A service
  49. is in the class "default" if one is not specified via the
  50. class option.
  51. onrestart      //当服务重启时执行
  52. Execute a Command (see below) when service restarts.
  53. writepid <file...>
  54. Write the child's pid to the given files when it forks. Meant for
  55. cgroup/cpuset usage.

下面看一下zygote服务示例代码位置system/core/rootdir/init.zygote64.rc;

service的名字为zygote, 启动路径为手机中/system/bin/app_process64后面的都是启动参数.

[cpp] view plain copy
  1. service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
  2. class main      //zygote的name为main,和class name为main的一块被启动
  3. socket zygote stream 660 root system   //为zygote创建socket
  4. onrestart write /sys/android_power/request_state wake  //当zygote重启时执行下面动作
  5. onrestart write /sys/power/state on
  6. onrestart restart audioserver
  7. onrestart restart cameraserver
  8. onrestart restart media
  9. onrestart restart netd
  10. writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks

对Action与Services了解之后就可以开始解析init.rc文件了.

在分析init进程时知道解析init.rc文件的入口在init.cpp的main函数中

[cpp] view plain copy
  1. parser.ParseConfig("/init.rc");

解析init.rc的核心在system/core/init/init_parse.cpp文件中

[cpp] view plain copy
  1. bool Parser::ParseConfig(const std::string& path) {
  2. if (is_dir(path.c_str())) {       //如果路径为文件夹,就调用解析文件夹的函数
  3. return ParseConfigDir(path);
  4. }
  5. return ParseConfigFile(path);  //解析init.rc文件
  6. }
[cpp] view plain copy
  1. bool Parser::ParseConfigFile(const std::string& path) {
  2. INFO("Parsing file %s...\n", path.c_str());  //根据之前讲解klog一文,可知该log打印不出
  3. Timer t;      //利用Timer计时,解析文件耗时多长时间
  4. std::string data;
  5. if (!read_file(path.c_str(), &data)) {   //读取文件
  6. return false;
  7. }
  8. data.push_back('\n'); // TODO: fix parse_config.
  9. ParseData(path, data);     //解析内容
  10. for (const auto& sp : section_parsers_) {
  11. sp.second->EndFile(path);       //解析完init.rc文件后, 调用Import_parse.cpp的EndFile函数,解析引用的rc文件
  12. }
  13. // Turning this on and letting the INFO logging be discarded adds 0.2s to
  14. // Nexus 9 boot time, so it's disabled by default.
  15. if (false) DumpState();
  16. NOTICE("(Parsing %s took %.2fs.)\n", path.c_str(), t.duration());  //打印出解析哪个文件,花费多长时间, 来查找耗时点
  17. return true;
  18. }
[cpp] view plain copy
  1. void Parser::ParseData(const std::string& filename, const std::string& data) {
  2. //TODO: Use a parser with const input and remove this copy
  3. std::vector<char> data_copy(data.begin(), data.end());     //数据copy
  4. data_copy.push_back('\0');
  5. parse_state state;
  6. state.filename = filename.c_str();
  7. state.line = 0;
  8. state.ptr = &data_copy[0];
  9. state.nexttoken = 0;
  10. SectionParser* section_parser = nullptr;
  11. std::vector<std::string> args;
  12. for (;;) {        //循环解析init.rc文件
  13. switch (next_token(&state)) {  //通过nextToken函数获得需要解析的这一行是文本内容还是action,services
  14. case T_EOF:             <span style="font-family:Arial, Helvetica, sans-serif;">//文件解析结束</span>
  15. if (section_parser) {
  16. section_parser->EndSection();
  17. }
  18. return;
  19. case T_NEWLINE:      //解析新的一行, 可能是一个action,services或者import
  20. state.line++;
  21. if (args.empty()) {
  22. break;
  23. }
  24. if (section_parsers_.count(args[0])) {
  25. if (section_parser) {
  26. section_parser->EndSection();   //section解析结束
  27. }
  28. section_parser = section_parsers_[args[0]].get();
  29. std::string ret_err;
  30. if (!section_parser->ParseSection(args, &ret_err)) {  //解析Action,Service, Import 三个Section
  31. parse_error(&state, "%s\n", ret_err.c_str());
  32. section_parser = nullptr;
  33. }
  34. } else if (section_parser) {
  35. std::string ret_err;      //解析section的内容
  36. if (!section_parser->ParseLineSection(args, state.filename,
  37. state.line, &ret_err)) {
  38. parse_error(&state, "%s\n", ret_err.c_str());
  39. }
  40. }
  41. args.clear();
  42. break;
  43. case T_TEXT:
  44. args.emplace_back(state.text);     //将文本放入args中
  45. break;
  46. }
  47. }
  48. }

nextToken函数在/system/core/init/parse.cpp中实现

[cpp] view plain copy
  1. int next_token(struct parse_state *state)
  2. {
  3. char *x = state->ptr;
  4. char *s;
  5. if (state->nexttoken) {
  6. int t = state->nexttoken;
  7. state->nexttoken = 0;
  8. return t;
  9. }
  10. for (;;) {
  11. switch (*x) {
  12. case 0:
  13. state->ptr = x;
  14. return T_EOF;
  15. case '\n':
  16. x++;
  17. state->ptr = x;
  18. return T_NEWLINE;
  19. case ' ':
  20. case '\t':
  21. case '\r':
  22. x++;
  23. continue;
  24. case '#':
  25. while (*x && (*x != '\n')) x++;
  26. if (*x == '\n') {
  27. state->ptr = x+1;
  28. return T_NEWLINE;
  29. } else {
  30. state->ptr = x;
  31. return T_EOF;
  32. }
  33. default:
  34. goto text;
  35. }
  36. }
  37. textdone:
  38. state->ptr = x;
  39. *s = 0;
  40. return T_TEXT;
  41. text:
  42. state->text = s = x;
  43. textresume:
  44. for (;;) {
  45. switch (*x) {
  46. case 0:
  47. goto textdone;
  48. case ' ':
  49. case '\t':
  50. case '\r':
  51. x++;
  52. goto textdone;
  53. case '\n':
  54. state->nexttoken = T_NEWLINE;
  55. x++;
  56. goto textdone;
  57. case '"':
  58. x++;
  59. for (;;) {
  60. switch (*x) {
  61. case 0:
  62. /* unterminated quoted thing */
  63. state->ptr = x;
  64. return T_EOF;
  65. case '"':
  66. x++;
  67. goto textresume;
  68. default:
  69. *s++ = *x++;
  70. }
  71. }
  72. break;
  73. case '\\':
  74. x++;
  75. switch (*x) {
  76. case 0:
  77. goto textdone;
  78. case 'n':
  79. *s++ = '\n';
  80. break;
  81. case 'r':
  82. *s++ = '\r';
  83. break;
  84. case 't':
  85. *s++ = '\t';
  86. break;
  87. case '\\':
  88. *s++ = '\\';
  89. break;
  90. case '\r':
  91. /* \ <cr> <lf> -> line continuation */
  92. if (x[1] != '\n') {
  93. x++;
  94. continue;
  95. }
  96. case '\n':
  97. /* \ <lf> -> line continuation */
  98. state->line++;
  99. x++;
  100. /* eat any extra whitespace */
  101. while((*x == ' ') || (*x == '\t')) x++;
  102. continue;
  103. default:
  104. /* unknown escape -- just copy */
  105. *s++ = *x++;
  106. }
  107. continue;
  108. default:
  109. *s++ = *x++;
  110. }
  111. }
  112. return T_EOF;

解析Action

调用ActionParser的ParseSection函数,代码位置system/core/init/action.cpp

[cpp] view plain copy
  1. bool ActionParser::ParseSection(const std::vector<std::string>& args,
  2. std::string* err) {
  3. std::vector<std::string> triggers(args.begin() + 1, args.end());  //获取trigger, 截取on后面的字符串
  4. if (triggers.size() < 1) {
  5. *err = "actions must have a trigger";    //检查是否存在trigger
  6. return false;
  7. }
  8. auto action = std::make_unique<Action>(false);
  9. if (!action->InitTriggers(triggers, err)) {   //将triggers放入event_trigger_
  10. return false;
  11. }
  12. action_ = std::move(action);   //赋值action_
  13. return true;
  14. }
[cpp] view plain copy
  1. bool ActionParser::ParseLineSection(const std::vector<std::string>& args,
  2. const std::string& filename, int line,
  3. std::string* err) const {
  4. return action_ ? action_->AddCommand(args, filename, line, err) : false;  //action_为true ,已经赋过值
  5. }
[cpp] view plain copy
  1. bool Action::AddCommand(const std::vector<std::string>& args,
  2. const std::string& filename, int line, std::string* err) {
  3. if (!function_map_) {        //function_map在分析init进程时有提到, 为true
  4. *err = "no function map available";
  5. return false;
  6. }
  7. if (args.empty()) {
  8. *err = "command needed, but not provided";
  9. return false;
  10. }
  11. auto function = function_map_->FindFunction(args[0], args.size() - 1, err);   //根据命令找到对应的函数
  12. if (!function) {
  13. return false;
  14. }
  15. AddCommand(function, args, filename, line);
  16. return true;
  17. }
  18. void Action::AddCommand(BuiltinFunction f,
  19. const std::vector<std::string>& args,
  20. const std::string& filename, int line) {
  21. commands_.emplace_back(f, args, filename, line);  //将对应函数, 参数,文件名放入commans_中
  22. }
[cpp] view plain copy
  1. void ActionParser::EndSection() {
  2. if (action_ && action_->NumCommands() > 0) {
  3. ActionManager::GetInstance().AddAction(std::move(action_));  //将一个action的所有command都加入action_后,将action_加入action列表
  4. }
  5. }
[cpp] view plain copy
  1. void ActionManager::AddAction(std::unique_ptr<Action> action) {
  2. auto old_action_it =
  3. std::find_if(actions_.begin(), actions_.end(),
  4. [&action] (std::unique_ptr<Action>& a) {
  5. return action->TriggersEqual(*a);
  6. });
  7. if (old_action_it != actions_.end()) {
  8. (*old_action_it)->CombineAction(*action);
  9. } else {
  10. actions_.emplace_back(std::move(action));   //将所有的action加入actions_列表
  11. }
  12. }

解析Services
调用ServiceParser的ParseSection函数,代码位置system/core/init/service.cpp

[cpp] view plain copy
  1. bool ServiceParser::ParseSection(const std::vector<std::string>& args,
  2. std::string* err) {
  3. if (args.size() < 3) {    //判断service是否有name与可执行程序
  4. *err = "services must have a name and a program";
  5. return false;
  6. }
  7. const std::string& name = args[1];
  8. if (!IsValidName(name)) {    //检查name是否可用
  9. *err = StringPrintf("invalid service name '%s'", name.c_str());
  10. return false;
  11. }
  12. std::vector<std::string> str_args(args.begin() + 2, args.end()); //获取执行程序与参数
  13. service_ = std::make_unique<Service>(name, "default", str_args);   //给service_赋值
  14. return true;
  15. }
[cpp] view plain copy
  1. bool ServiceParser::ParseLineSection(const std::vector<std::string>& args,
  2. const std::string& filename, int line,
  3. std::string* err) const {
  4. return service_ ? service_->HandleLine(args, err) : false;  //service_为true, 调用HandleLine
  5. }
[cpp] view plain copy
  1. Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
  2. constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
  3. static const Map option_handlers = {   //option对应的函数
  4. {"class",       {1,     1,    &Service::HandleClass}},
  5. {"console",     {0,     0,    &Service::HandleConsole}},
  6. {"critical",    {0,     0,    &Service::HandleCritical}},
  7. {"disabled",    {0,     0,    &Service::HandleDisabled}},
  8. {"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
  9. {"ioprio",      {2,     2,    &Service::HandleIoprio}},
  10. {"keycodes",    {1,     kMax, &Service::HandleKeycodes}},
  11. {"oneshot",     {0,     0,    &Service::HandleOneshot}},
  12. {"onrestart",   {1,     kMax, &Service::HandleOnrestart}},
  13. {"seclabel",    {1,     1,    &Service::HandleSeclabel}},
  14. {"setenv",      {2,     2,    &Service::HandleSetenv}},
  15. {"socket",      {3,     6,    &Service::HandleSocket}},
  16. {"user",        {1,     1,    &Service::HandleUser}},
  17. {"writepid",    {1,     kMax, &Service::HandleWritepid}},
  18. };
  19. return option_handlers;
  20. }
  21. bool Service::HandleLine(const std::vector<std::string>& args, std::string* err) {
  22. if (args.empty()) {
  23. *err = "option needed, but not provided";
  24. return false;
  25. }
  26. static const OptionHandlerMap handler_map;   //获得option对应的函数表
  27. auto handler = handler_map.FindFunction(args[0], args.size() - 1, err); //根据option获取对应的函数名
  28. if (!handler) {
  29. return false;
  30. }
  31. return (this->*handler)(args, err);
  32. }
[cpp] view plain copy
  1. void ServiceParser::EndSection() {
  2. if (service_) {
  3. ServiceManager::GetInstance().AddService(std::move(service_));
  4. }
  5. }
[cpp] view plain copy
  1. void ServiceManager::AddService(std::unique_ptr<Service> service) {
  2. Service* old_service = FindServiceByName(service->name());
  3. if (old_service) {    //service已经被定义过了就抛弃
  4. ERROR("ignored duplicate definition of service '%s'",
  5. service->name().c_str());
  6. return;
  7. }
  8. services_.emplace_back(std::move(service));  //将service添加services_列表
  9. }

解析Import
调用ImportParser的ParseSection函数,代码位置system/core/init/import_parser.cpp

[cpp] view plain copy
  1. bool ImportParser::ParseSection(const std::vector<std::string>& args,
  2. std::string* err) {
  3. if (args.size() != 2) {
  4. *err = "single argument needed for import\n";
  5. return false;
  6. }
  7. std::string conf_file;
  8. bool ret = expand_props(args[1], &conf_file); //获取引用的conf_file文件,
  9. if (!ret) {
  10. *err = "error while expanding import";
  11. return false;
  12. }
  13. INFO("Added '%s' to import list\n", conf_file.c_str());
  14. imports_.emplace_back(std::move(conf_file));   //将所有的conf_file添加到imports_列表
  15. return true;
  16. }

前面讲过当调用完ParseData函数后,会遍历所有section执行endFile函数

[cpp] view plain copy
  1. void ImportParser::EndFile(const std::string& filename) {
  2. auto current_imports = std::move(imports_);  //获取imports_
  3. imports_.clear();   //将imports_列表清空
  4. for (const auto& s : current_imports) {  //遍历列表
  5. if (!Parser::GetInstance().ParseConfig(s)) {   //调用ParseConfig函数,对其他配置进行解析, 流程遇上面的相同
  6. ERROR("could not import file '%s' from '%s': %s\n",
  7. s.c_str(), filename.c_str(), strerror(errno));
  8. }
  9. }
  10. }

到此init.rc文件就解析完了, 那么大家就想知道了解析完的actions与services又是如何执行的呢?

Android系统(2)---init.rc知识相关推荐

  1. Android初始化语言 (init.*.rc、init.conf文件格式)

    2019独角兽企业重金招聘Python工程师标准>>> 下文转载自:http://hi.baidu.com/zhlg_hzh/blog/item/4ad24a807c71d3db90 ...

  2. android系统手机的基本知识和介绍

    android系统手机的基本知识和介绍 2011年11月14日 android系统手机的基本知识和介绍 Android系统的手机现在是越来越受欢迎了.看到周边的同事个个都换上了android系统的手机 ...

  3. Android如何配置init.rc中的开机启动进程(service)【转】

    本文转载自:http://blog.csdn.net/qq_28899635/article/details/56289063 开篇:为什么写这篇文章 先说下我自己的情况,我是个普通的大四学生,之前在 ...

  4. Android启动脚本init.rc(2)

    在Android中使用启动脚本init.rc,可以在系统的初始化中进行简单的操作. init.rc启动脚本路径:system/core/rootdir/init.rc 内容: Commands:命令 ...

  5. Android 7.0 init.rc的一点改变

    点击打开链接 在Android 7之前的版本中,系统Native服务,不管它们的可执行文件位于系统什么位置都定义在根分区的init.*.rc文件中.这造成init*.rc文件臃肿庞大,给维护带来了一些 ...

  6. Android程序暂停sh,init进程 解析Android启动脚本init.rc 修改它使不启动android init.rc中启动一个sh文件...

    Android启动后,系统执行的第一个进程是一个名称为init 的可执行程序.提供了以下的功能:设备管理.解析启动脚本.执行基本的功能.启动各种服务.代码的路径: system/core/init,编 ...

  7. 旧手机android系统 新手机上,手机知识:安卓旧手机导入新手机

    科技本身,支配宇宙的自然规律是充满魅力的!因此越来越多的人开始关注科技的相关动态,近来安卓旧手机导入新手机的消息也是引起了很多人的关注,那么既然现在大家都想要知道安卓旧手机导入新手机,小编今天就来给大 ...

  8. android系统新手刷机知识普及

    一.关于Root. 1.什么是"root"? "Root"权限相当于电脑的管理员权限,"Root"后用户可以完全权限访问Linux内核:&q ...

  9. Android系统开机启动流程及init进程浅析

    Android系统启动概述 Android系统开机流程基于Linux系统,总体可分为三个阶段: Boot Loader引导程序启动 Linux内核启动 Android系统启动,Launcher/app ...

最新文章

  1. Jmeter JDBC执行多条SQL
  2. 常见的数据结构——栈、队列、数组、链表和红黑树
  3. 第九天2017/04/18(1、友元函数、运算符重载)
  4. java protobuf 例子_用Maven实现一个protobuf的Java例子
  5. 学习ASP.NET Core,怎能不了解请求处理管道[2]: 服务器在管道中的“龙头”地位
  6. java原始类型和引用类型_Java中的8种原始类型
  7. flink连接kafka整合hbase,scala
  8. 12.Memcached 与 Redis 区别
  9. typeorm 更新_typeORM 多对多关系不同情况的处理
  10. python标准库os中的方法startfile_如何使用Python 打开exel等各种文件或者应用,就用:os.startfile...
  11. 手机播放云服务器中的视频文件在哪里,手机播放云服务器中的视频文件
  12. Office:手动卸载 Office 系统
  13. Windows10重装系统教程(超详细)
  14. Android Camera HAL3 - 开篇词
  15. [观点]中国传统文化的遗失清单上我们丢掉了什么(作者:侯虹斌)
  16. linux的密码重置命令
  17. java switch语句作用域,switch语句
  18. 微信支付接口加密技术详解
  19. python读取微博文本数据,对微博文本进行分句(分句主要以特定的标点符号为主)。...
  20. 微信短视频怎么提取gif?三步教你在线提取gif动画

热门文章

  1. [一分钟先生]涂勇:通过跳槽走上管理岗位不可取
  2. 【JAVA SE】第七章 继承和多态
  3. 力扣1232.缀点成线
  4. P2024 [NOI2001]食物链[扩展域并查集]
  5. 3rd,Python登录模拟
  6. WIN7系统程序放在中文文件夹打开报错及界面汉字变乱码
  7. js中的preventDefault与stopPropagation详解(转)
  8. abi-api, arm target triplet https://en.wikipedia.org/wiki/ARM_architecture
  9. 夺命雷公狗---Smarty NO:19 html_options函数
  10. c#中字符串截取使用的方法