Android系统(2)---init.rc知识

  在解析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.   
  6. Triggers are subdivided into event triggers and property triggers.  
  7.   
  8. Event triggers are strings triggered by the 'trigger' command or by  
  9. the QueueEventTrigger() function within the init executable.  These  
  10. take the form of a simple string such as 'boot' or 'late-init'.  
  11.   
  12. Property triggers are strings triggered when a named property changes  
  13. value to a given new value or when a named property changes value to  
  14. any new value.  These take the form of 'property:<name>=<value>' and  
  15. 'property:<name>=*' respectively.  Property triggers are additionally  
  16. evaluated and triggered accordingly during the initial boot phase of  
  17. init.  
  18.   
  19. An Action can have multiple property triggers but may only have one  
  20. event trigger.  
  21.   
  22. For example:  
  23. 'on boot && property:a=b' defines an action that is only executed when  
  24. the 'boot' event trigger happens and the property a equals b.  
  25.   
  26. 'on property:a=b && property:c=d' defines an action that is executed  
  27. at three times,  
  28.    1) During initial boot if property a=b and property c=d  
  29.    2) Any time that property a transitions to value b, while property  
  30.       c already equals d.  
  31.    3) Any time that property c transitions to value d, while property  
  32.       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.   
  5.     # Disable sysrq from keyboard  
  6.     write /proc/sys/kernel/sysrq 0  
  7.   
  8.     # Set the security context of /adb_keys if present.  
  9.     restorecon /adb_keys       //为adb_keys 重置安全上下文  
  10.   
  11.     # Shouldn't be necessary, but sdcard won't start without it. http://b/22568628.  
  12.     mkdir /mnt 0775 root system    //创建mnt目录  
  13.   
  14.     # Set the security context of /postinstall if present.  
  15.     restorecon /postinstall  
  16.   
  17.     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.   
  5. chmod <octal-mode> <path>  //改变文件的权限  
  6.    Change file access permissions.  
  7.   
  8. chown <owner> <group> <path>  //改变文件的群组  
  9.    Change file owner and group.  
  10.   
  11. class_start <serviceclass>   //启动所有具有特定class的services  
  12.    Start all services of the specified class if they are  
  13.    not already running.  
  14.   
  15. class_stop <serviceclass>      //将具有特定class的所有运行中的services给停止或者diasble  
  16.    Stop and disable all services of the specified class if they are  
  17.    currently running.  
  18.   
  19. class_reset <serviceclass>   //先将services stop掉, 之后可能会通过class_start再重新启动起来  
  20.    Stop all services of the specified class if they are  
  21.    currently running, without disabling them. They can be restarted  
  22.    later using class_start.  
  23.   
  24. copy <src> <dst>    //复制文件  
  25.    Copies a file. Similar to write, but useful for binary/large  
  26.    amounts of data.  
  27.   
  28. domainname <name>      
  29.    Set the domain name.  
  30.   
  31. enable <servicename>  //如果services没有特定disable,就将他设为enable  
  32.    Turns a disabled service into an enabled one as if the service did not  
  33.    specify disabled.          
  34.    If the service is supposed to be running, it will be started now.  
  35.    Typically used when the bootloader sets a variable that indicates a specific  
  36.    service should be started when needed. E.g.  
  37.      on property:ro.boot.myfancyhardware=1  
  38.         enable my_fancy_service_for_my_fancy_hardware  
  39.   
  40. exec [ <seclabel> [ <user> [ <group> ]* ] ] -- <command> [ <argument> ]*    //创建执行程序.比较重要,后面启动service要用到  
  41.    Fork and execute command with the given arguments. The command starts  
  42.    after "--" so that an optional security context, user, and supplementary  
  43.    groups can be provided. No other commands will be run until this one  
  44. export <name> <value>      //在全局设置环境变量  
  45.    Set the environment variable <name> equal to <value> in the  
  46.    global environment (which will be inherited by all processes  
  47.    started after this command is executed)  
  48.   
  49. hostname <name>       //设置主机名称  
  50.    Set the host name.  
  51.   
  52. ifup <interface>       //启动网络接口  
  53.    Bring the network interface <interface> online.  
  54.   
  55. insmod <path>    //在某个路径安装一个模块  
  56.    Install the module at <path>  
  57.   
  58. load_all_props    //加载所有的配置  
  59.    Loads properties from /system, /vendor, et cetera.  
  60.    This is included in the default init.rc.  
  61.   
  62. load_persist_props  //当data加密时加载一些配置  
  63.    Loads persistent properties when /data has been decrypted.  
  64.    This is included in the default init.rc.  
  65.   
  66. loglevel <level>       //设置kernel log level  
  67.    Sets the kernel log level to level. Properties are expanded within <level>.  
  68.   
  69. mkdir <path> [mode] [owner] [group]    //创建文件夹  
  70.    Create a directory at <path>, optionally with the given mode, owner, and  
  71.    group. If not provided, the directory is created with permissions 755 and  
  72.    owned by the root user and root group. If provided, the mode, owner and group  
  73.    will be updated if the directory exists already.  
  74.   
  75. mount_all <fstab> [ <path> ]*      //挂载  
  76.    Calls fs_mgr_mount_all on the given fs_mgr-format fstab and imports .rc files  
  77.    at the specified paths (e.g., on the partitions just mounted). Refer to the  
  78.    section of "Init .rc Files" for detail.  
  79.   
  80. mount <type> <device> <dir> [ <flag> ]* [<options>]   //在dir文件夹下面挂载设备  
  81.    Attempt to mount the named device at the directory <dir>  
  82.    <device> may be of the form mtd@name to specify a mtd block  
  83.    device by name.  
  84.    <flag>s include "ro""rw""remount""noatime", ...  
  85.    <options> include "barrier=1""noauto_da_alloc""discard", ... as  
  86.    a comma separated string, eg: barrier=1,noauto_da_alloc  
  87.   
  88. powerctl  
  89.    Internal implementation detail used to respond to changes to the  
  90.    "sys.powerctl" system property, used to implement rebooting.  
  91. restart <service>          //重启服务  
  92.    Like stop, but doesn't disable the service.  
  93.   
  94. restorecon <path> [ <path> ]*      //重置文件的安全上下文  
  95.    Restore the file named by <path> to the security context specified  
  96.    in the file_contexts configuration.  
  97.    Not required for directories created by the init.rc as these are  
  98.    automatically labeled correctly by init.  
  99.   
  100. restorecon_recursive <path> [ <path> ]*//一般都是 selinux完成初始化之后又创建、或者改变的目录  
  101.    Recursively restore the directory tree named by <path> to the  
  102.    security contexts specified in the file_contexts configuration.  
  103.   
  104. rm <path>         //删除文件  
  105.    Calls unlink(2) on the given path. You might want to  
  106.    use "exec -- rm ..." instead (provided the system partition is  
  107.    already mounted).  
  108.   
  109. rmdir <path>     //删除文件夹  
  110.    Calls rmdir(2) on the given path.  
  111.   
  112. setprop <name> <value>    //设置属性  
  113.    Set system property <name> to <value>. Properties are expanded  
  114.    within <value>.  
  115.   
  116. setrlimit <resource> <cur> <max>  
  117.    Set the rlimit for a resource.  
  118.   
  119. start <service>     //如果service没有启动,就将他启动起来  
  120.    Start a service running if it is not already running.  
  121.   
  122. stop <service> //将运行的服务停掉  
  123.    Stop a service from running if it is currently running.  
  124.   
  125. swapon_all <fstab>  
  126.    Calls fs_mgr_swapon_all on the given fstab file.  
  127.   
  128. symlink <target> <path>  
  129.    Create a symbolic link at <path> with the value <target>  
  130.   
  131. sysclktz <mins_west_of_gmt>  
  132.    Set the system clock base (0 if system clock ticks in GMT)  
  133. trigger <event>      //触发一个事件  
  134.    Trigger an event.  Used to queue an action from another  
  135.    action.  
  136.   
  137. verity_load_state  
  138.    Internal implementation detail used to load dm-verity state.  
  139.   
  140. verity_update_state <mount_point>  
  141.    Internal implementation detail used to update dm-verity state and  
  142.    set the partition.<mount_point>.verified properties used by adb remount  
  143.    because fs_mgr can't set them directly itself.  
  144.   
  145. wait <path> [ <timeout> ]     //等待  
  146.    Poll for the existence of the given file and return when found,  
  147.    or the timeout has been reached. If timeout is not specified it  
  148.    currently defaults to five seconds.  
  149.   
  150. write <path> <content>   //写文件  
  151.    Open the file at <path> and write a string to it with write(2).  
  152.    If the file does not exist, it will be created. If it does exist,  
  153.    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.   
  6. critical     //表示该service非常重要,如果退出四次以上在4分钟内,设备就会重启进入recovery模式  
  7.   This is a device-critical service. If it exits more than four times in  
  8.   four minutes, the device will reboot into recovery mode.  
  9.   
  10. disabled    //该services不能通过class启动,只能通过name将他启动  
  11.   This service will not automatically start with its class.  
  12.   It must be explicitly started by name.  
  13.   
  14. setenv <name> <value>   //设置环境变量  
  15.   Set the environment variable <name> to <value> in the launched process.  
  16.   
  17. socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]  
  18.   Create a unix domain socket named /dev/socket/<name> and pass  
  19.   its fd to the launched process.  <type> must be "dgram""stream" or "seqpacket".  
  20.   User and group default to 0.  
  21.   'seclabel' is the SELinux security context for the socket.  
  22.   It defaults to the service security context, as specified by seclabel or  
  23.   computed based on the service executable file security context.  
  24.   
  25. user <username>  
  26.   Change to username before exec'ing this service.  
  27.   Currently defaults to root.  (??? probably should default to nobody)  
  28.   As of Android M, processes should use this option even if they  
  29.   require linux capabilities.  Previously, to acquire linux  
  30.   capabilities, a process would need to run as root, request the  
  31.   capabilities, then drop to its desired uid.  There is a new  
  32.   mechanism through fs_config that allows device manufacturers to add  
  33.   linux capabilities to specific binaries on a file system that should  
  34.   be used instead. This mechanism is described on  
  35.   http://source.android.com/devices/tech/config/filesystem.html.  When  
  36.   using this new mechanism, processes can use the user option to  
  37.   select their desired uid without ever running as root.  
  38.   
  39. group <groupname> [ <groupname> ]*  
  40.   Change to groupname before exec'ing this service.  Additional  
  41.   groupnames beyond the (required) first one are used to set the  
  42.   supplemental groups of the process (via setgroups()).  
  43.   Currently defaults to root.  (??? probably should default to nobody)  
  44.   
  45. seclabel <seclabel>  
  46.   Change to 'seclabel' before exec'ing this service.  
  47.   Primarily for use by services run from the rootfs, e.g. ueventd, adbd.  
  48.   Services on the system partition can instead use policy-defined transitions  
  49.   based on their file security context.  
  50.   If not specified and no transition is defined in policy, defaults to the init context.  
  51.   
  52. oneshot   
  53.   Do not restart the service when it exits.  
  54.   
  55. class <name>   //一个特定的name, 所有有这个name的service统一管理,一起启动,一起stop  
  56.   Specify a class name for the service.  All services in a  
  57.   named class may be started or stopped together.  A service  
  58.   is in the class "default" if one is not specified via the  
  59.   class option.  
  60.   
  61. onrestart      //当服务重启时执行  
  62.   Execute a Command (see below) when service restarts.  
  63.   
  64. writepid <file...>  
  65.   Write the child's pid to the given files when it forks. Meant for  
  66.   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.   
  9.     data.push_back('\n'); // TODO: fix parse_config.  
  10.     ParseData(path, data);     //解析内容  
  11.     for (const auto& sp : section_parsers_) {  
  12.         sp.second->EndFile(path);       //解析完init.rc文件后, 调用Import_parse.cpp的EndFile函数,解析引用的rc文件  
  13.     }  
  14.   
  15.     // Turning this on and letting the INFO logging be discarded adds 0.2s to  
  16.     // Nexus 9 boot time, so it's disabled by default.  
  17.     if (false) DumpState();  
  18.   
  19.     NOTICE("(Parsing %s took %.2fs.)\n", path.c_str(), t.duration());  //打印出解析哪个文件,花费多长时间, 来查找耗时点  
  20.     return true;  
  21. }  
[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.   
  6.     parse_state state;  
  7.     state.filename = filename.c_str();  
  8.     state.line = 0;  
  9.     state.ptr = &data_copy[0];  
  10.     state.nexttoken = 0;  
  11.   
  12.     SectionParser* section_parser = nullptr;  
  13.     std::vector<std::string> args;  
  14.   
  15.     for (;;) {        //循环解析init.rc文件  
  16.         switch (next_token(&state)) {  //通过nextToken函数获得需要解析的这一行是文本内容还是action,services  
  17.         case T_EOF:             <span style="font-family:Arial, Helvetica, sans-serif;">//文件解析结束</span>  
  18.             if (section_parser) {  
  19.                 section_parser->EndSection();     
  20.             }  
  21.             return;  
  22.         case T_NEWLINE:      //解析新的一行, 可能是一个action,services或者import  
  23.             state.line++;  
  24.             if (args.empty()) {  
  25.                 break;  
  26.             }  
  27.             if (section_parsers_.count(args[0])) {  
  28.                 if (section_parser) {  
  29.                     section_parser->EndSection();   //section解析结束  
  30.                 }  
  31.                 section_parser = section_parsers_[args[0]].get();  
  32.                 std::string ret_err;  
  33.                 if (!section_parser->ParseSection(args, &ret_err)) {  //解析Action,Service, Import 三个Section  
  34.                     parse_error(&state, "%s\n", ret_err.c_str());  
  35.                     section_parser = nullptr;  
  36.                 }  
  37.             } else if (section_parser) {  
  38.                 std::string ret_err;      //解析section的内容  
  39.                 if (!section_parser->ParseLineSection(args, state.filename,  
  40.                                                       state.line, &ret_err)) {  
  41.                     parse_error(&state, "%s\n", ret_err.c_str());  
  42.                 }  
  43.             }  
  44.             args.clear();  
  45.             break;  
  46.         case T_TEXT:  
  47.             args.emplace_back(state.text);     //将文本放入args中  
  48.             break;  
  49.         }  
  50.     }  
  51. }  

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.   
  6.     if (state->nexttoken) {  
  7.         int t = state->nexttoken;  
  8.         state->nexttoken = 0;  
  9.         return t;  
  10.     }  
  11.   
  12.     for (;;) {   
  13.         switch (*x) {  
  14.         case 0:  
  15.             state->ptr = x;  
  16.             return T_EOF;  
  17.         case '\n':  
  18.             x++;  
  19.             state->ptr = x;  
  20.             return T_NEWLINE;  
  21.         case ' ':  
  22.         case '\t':  
  23.         case '\r':  
  24.             x++;  
  25.             continue;  
  26.         case '#':   
  27.             while (*x && (*x != '\n')) x++;  
  28.             if (*x == '\n') {  
  29.                 state->ptr = x+1;  
  30.                 return T_NEWLINE;  
  31.             } else {  
  32.                 state->ptr = x;  
  33.                 return T_EOF;  
  34.             }  
  35.         default:   
  36.             goto text;  
  37.         }  
  38.     }  
  39.   
  40. textdone:  
  41.     state->ptr = x;  
  42.     *s = 0;  
  43.     return T_TEXT;  
  44. text:  
  45.     state->text = s = x;  
  46. textresume:  
  47.     for (;;) {  
  48.         switch (*x) {  
  49.         case 0:  
  50.             goto textdone;  
  51.         case ' ':  
  52.         case '\t':  
  53.         case '\r':  
  54.             x++;  
  55.             goto textdone;  
  56.         case '\n':  
  57.             state->nexttoken = T_NEWLINE;  
  58.             x++;  
  59.             goto textdone;  
  60.         case '"':  
  61.             x++;  
  62.             for (;;) {  
  63.                 switch (*x) {  
  64.                 case 0:  
  65.                         /* unterminated quoted thing */  
  66.                     state->ptr = x;  
  67.                     return T_EOF;  
  68.                 case '"':  
  69.                     x++;  
  70.                     goto textresume;  
  71.                 default:  
  72.                     *s++ = *x++;  
  73.                 }  
  74.             }  
  75.             break;  
  76.         case '\\':  
  77.             x++;  
  78.             switch (*x) {  
  79.             case 0:  
  80.                 goto textdone;  
  81.             case 'n':  
  82.                 *s++ = '\n';  
  83.                 break;  
  84.             case 'r':  
  85.                 *s++ = '\r';  
  86.                 break;  
  87.             case 't':  
  88.                 *s++ = '\t';  
  89.                 break;  
  90.             case '\\':  
  91.                 *s++ = '\\';  
  92.                 break;  
  93.             case '\r':  
  94.                     /* \ <cr> <lf> -> line continuation */  
  95.                 if (x[1] != '\n') {  
  96.                     x++;  
  97.                     continue;  
  98.                 }  
  99.             case '\n':  
  100.                     /* \ <lf> -> line continuation */  
  101.                 state->line++;  
  102.                 x++;  
  103.                     /* eat any extra whitespace */  
  104.                 while((*x == ' ') || (*x == '\t')) x++;  
  105.                 continue;  
  106.             default:  
  107.                     /* unknown escape -- just copy */  
  108.                 *s++ = *x++;  
  109.             }  
  110.             continue;  
  111.         default:  
  112.             *s++ = *x++;  
  113.         }  
  114.     }  
  115.     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.   
  9.     auto action = std::make_unique<Action>(false);  
  10.     if (!action->InitTriggers(triggers, err)) {   //将triggers放入event_trigger_  
  11.         return false;  
  12.     }  
  13.   
  14.     action_ = std::move(action);   //赋值action_  
  15.     return true;  
  16. }  
[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.   
  8.     if (args.empty()) {  
  9.         *err = "command needed, but not provided";  
  10.         return false;  
  11.     }  
  12.   
  13.     auto function = function_map_->FindFunction(args[0], args.size() - 1, err);   //根据命令找到对应的函数  
  14.     if (!function) {  
  15.         return false;  
  16.     }  
  17.   
  18.     AddCommand(function, args, filename, line);  
  19.     return true;  
  20. }  
  21.   
  22. void Action::AddCommand(BuiltinFunction f,  
  23.                         const std::vector<std::string>& args,  
  24.                         const std::string& filename, int line) {  
  25.     commands_.emplace_back(f, args, filename, line);  //将对应函数, 参数,文件名放入commans_中  
  26. }  
[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.   
  8.     if (old_action_it != actions_.end()) {  
  9.         (*old_action_it)->CombineAction(*action);  
  10.     } else {  
  11.         actions_.emplace_back(std::move(action));   //将所有的action加入actions_列表  
  12.     }  
  13. }  
解析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.   
  8.     const std::string& name = args[1];  
  9.     if (!IsValidName(name)) {    //检查name是否可用  
  10.         *err = StringPrintf("invalid service name '%s'", name.c_str());  
  11.         return false;  
  12.     }  
  13.   
  14.     std::vector<std::string> str_args(args.begin() + 2, args.end()); //获取执行程序与参数  
  15.     service_ = std::make_unique<Service>(name, "default", str_args);   //给service_赋值  
  16.     return true;  
  17. }  
[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.   
  22. bool Service::HandleLine(const std::vector<std::string>& args, std::string* err) {  
  23.     if (args.empty()) {  
  24.         *err = "option needed, but not provided";  
  25.         return false;  
  26.     }  
  27.   
  28.     static const OptionHandlerMap handler_map;   //获得option对应的函数表  
  29.     auto handler = handler_map.FindFunction(args[0], args.size() - 1, err); //根据option获取对应的函数名  
  30.   
  31.     if (!handler) {  
  32.         return false;  
  33.     }  
  34.   
  35.     return (this->*handler)(args, err);     
  36. }  
[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.   
  8.     std::string conf_file;  
  9.     bool ret = expand_props(args[1], &conf_file); //获取引用的conf_file文件,   
  10.     if (!ret) {  
  11.         *err = "error while expanding import";  
  12.         return false;  
  13.     }  
  14.   
  15.     INFO("Added '%s' to import list\n", conf_file.c_str());  
  16.     imports_.emplace_back(std::move(conf_file));   //将所有的conf_file添加到imports_列表  
  17.     return true;  
  18. }  
前面讲过当调用完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又是如何执行的呢? 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值