【android】根据init.rc启动action和service

一、init.rc语法规则

1.init.rc文件的内容主要分类

动作(Action)
命令(Commands)
服务(Services)
选项(Options)
触发(trigger)

2.动作和命令一起使用

  1. on  <trigger>  
  2.     <command>  
  3.     <command>  
  4.     <command>  

2.1.trigger是触发条件,为真执行命令
trigger有以下几种类型

  1. boot  
  2.    /init.conf加载完毕时触发  
  3. <name>=<value>  
  4.    当<name>被设置为<value>时触发    
  5. device-added-<path>  
  6. device-removed-<path>  
  7.    设备<path>被添加移除时触发  
  8. service-exited-<name>  
  9.    当服务<name>退出时触发  

3.服务和选项一起使用

  1. service <name> <pathname> [ <argument> ]*  
  2.     <option>  
  3.     <option>  

3.1.option选项

  1. critical  
  2. disabled  
  3. setenv <name> <value>  
  4. socket <name> <type> <perm> [ <user> [ <group> ] ]  
  5. user <username>  
  6. group <groupname> [ <groupname> ]*  
  7. oneshot  
  8. class <name>  
  9. onrestart  

 

二、init.rc文件的解析

1.init_parse_config_file

在system/core/init/init.c文件的main函数中调用

  1. init_parse_config_file("/init.rc");  

函数将init.rc作为参数读取进来

  1. int init_parse_config_file(const char *fn)  
  2. {  
  3.     char *data;  
  4.     data = read_file(fn, 0);    //读取init.rc文件到data中  
  5.     if (!data) return -1;  
  6.   
  7.     parse_config(fn, data);     //解析配置  
  8.     DUMP();  
  9.     return 0;  
  10. }  

2.解析配置parse_config

  1. static void parse_config(const char *fn, char *s)  
  2. {  
  3.     struct parse_state state;  
  4.     char *args[INIT_PARSER_MAXARGS];  
  5.     int nargs;  
  6.   
  7.     nargs = 0;  
  8.     state.filename = fn;  
  9.     state.line = 1;  
  10.     state.ptr = s;  //指向init.rc的数据  
  11.     state.nexttoken = 0;  
  12.     state.parse_line = parse_line_no_op;    //空操作  
  13.     for (;;) {  
  14.         switch (next_token(&state)) {   //-->3.next_token跳过注释等,筛选需要解析的行  
  15.         case T_EOF:     //文件末尾  
  16.             state.parse_line(&state, 0, 0); //后面参数为 0, 0所以直接返回  
  17.             return;  
  18.         case T_NEWLINE: //新行解析  
  19.             if (nargs) {    //有文本参数  
  20.                 int kw = lookup_keyword(args[0]);   //解析关键词-->4.lookup_keyword  
  21.                 if (kw_is(kw, SECTION)) {   //判断是否section类-->5.kw_is  
  22.                     state.parse_line(&state, 0, 0); //后面参数为 0, 0所以直接返回  
  23.                     parse_new_section(&state, kw, nargs, args); //6.parse_new_section  
  24.                 }   
  25.         else {  
  26.                     state.parse_line(&state, nargs, args);  //解析前一行parse_line_service或parse_line_action  
  27.                 }  
  28.                 nargs = 0;  //nargs参数个数清0  
  29.             }  
  30.             break;  
  31.         case T_TEXT:    //文本  
  32.             if (nargs < INIT_PARSER_MAXARGS) {  
  33.                 args[nargs++] = state.text; //保存文本参数,nargs++  
  34.             }  
  35.             break;  
  36.         }  
  37.     }  
  38. }  

T_TEXT分支记录参数信息 例如
on early-init 
     symlink /initlogo.rle.bak /initlogo.rle
则会记录成
args[0]=on,  args[1]=early-init -->换行
args[0]=symlink, args[1]=/initlogo.rle.bak, args[2]=/initlogo.rle  -->换行
记录完后换新行会进入T_NEWLINE分支,分支会解析上一行的args[0],提取关键字,判断关键字类型做处理
如果是on和service关键词会调用parse_new_section处理,如果不是则调用state.parse_line函数处理,
parse_line函数可以是parse_line_service【service】或parse_line_action【on】
该parse_line函数主要是解析on/service后面带的command/options
正如例子中,on early-init 调用parse_new_section设置parse_line函数为parse_line_action
接着处理【on的command】symlink /initlogo.rle.bak /initlogo.rle的时候则调用parse_line函数parse_line_action
等到所有都处理完了则进入T_EOF分支,T_EOF分支return,跳出循环体
3.next_token

  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.             state->line++;   //行数++  
  19.             x++;  
  20.             state->ptr = x;  
  21.             return T_NEWLINE;  
  22.         case ' ':   //空格  
  23.         case '\t':  //tab制表  
  24.         case '\r':  //回车  
  25.             x++;  
  26.             continue;  
  27.         case '#':   //注释  
  28.             while (*x && (*x != '\n'))  //跳过注释直到换行  
  29.                 x++;  
  30.             state->line++;   //行数++  
  31.             state->ptr = x;  
  32.             return T_NEWLINE;  
  33.         default:    //文本  
  34.             goto text;  
  35.         }  
  36.     }  
  37.   
  38. textdone:  
  39.     state->ptr = x;  
  40.     *s = 0;  
  41.     return T_TEXT;  
  42. text:  
  43.     state->text = s = x;  
  44. textresume:  
  45.     for (;;) {  
  46.         switch (*x) {  
  47.         case 0:     //文本结束  
  48.             goto textdone;  
  49.         case ' ':   //空格  
  50.         case '\t':  //tab制表  
  51.         case '\r':  //回车  
  52.             x++;  
  53.             goto textdone;  
  54.         case '\n':  //换行  
  55.             state->nexttoken = T_NEWLINE;  
  56.             x++;  
  57.             goto textdone;  
  58.         case '"':   //引号括起  
  59.             x++;  
  60.             for (;;) {  
  61.                 switch (*x) {  
  62.                 case 0:  
  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:    //复制文本到s  
  109.             *s++ = *x++;  
  110.         }  
  111.     }  
  112.     return T_EOF;  
  113. }  

4.lookup_keyword

  1. int lookup_keyword(const char *s)  
  2. {  
  3.     switch (*s++) {  
  4.     case 'c':  
  5.         if (!strcmp(s, "opy")) return K_copy;  
  6.         if (!strcmp(s, "apability")) return K_capability;  
  7.         if (!strcmp(s, "hdir")) return K_chdir;  
  8.         if (!strcmp(s, "hroot")) return K_chroot;  
  9.         if (!strcmp(s, "lass")) return K_class;  
  10.         if (!strcmp(s, "lass_start")) return K_class_start;  
  11.         if (!strcmp(s, "lass_stop")) return K_class_stop;  
  12.         if (!strcmp(s, "onsole")) return K_console;  
  13.         if (!strcmp(s, "hown")) return K_chown;  
  14.         if (!strcmp(s, "hmod")) return K_chmod;  
  15.         if (!strcmp(s, "ritical")) return K_critical;  
  16.         break;  
  17.     case 'd':  
  18.         if (!strcmp(s, "isabled")) return K_disabled;  
  19.         if (!strcmp(s, "omainname")) return K_domainname;  
  20.         break;  
  21.     case 'e':  
  22.         if (!strcmp(s, "xec")) return K_exec;  
  23.         if (!strcmp(s, "xport")) return K_export;  
  24.         break;  
  25.     case 'g':  
  26.         if (!strcmp(s, "roup")) return K_group;  
  27.         break;  
  28.     case 'h':  
  29.         if (!strcmp(s, "ostname")) return K_hostname;  
  30.         break;  
  31.     case 'i':  
  32.         if (!strcmp(s, "oprio")) return K_ioprio;  
  33.         if (!strcmp(s, "fup")) return K_ifup;  
  34.         if (!strcmp(s, "nsmod")) return K_insmod;  
  35.         if (!strcmp(s, "mport")) return K_import;  
  36.         break;  
  37.     case 'k':  
  38.         if (!strcmp(s, "eycodes")) return K_keycodes;  
  39.         break;  
  40.     case 'l':  
  41.         if (!strcmp(s, "oglevel")) return K_loglevel;  
  42.         break;  
  43.     case 'm':  
  44.         if (!strcmp(s, "kdir")) return K_mkdir;  
  45.         if (!strcmp(s, "ount")) return K_mount;  
  46.         break;  
  47.     case 'o':  
  48.         if (!strcmp(s, "n")) return K_on;  
  49.         if (!strcmp(s, "neshot")) return K_oneshot;  
  50.         if (!strcmp(s, "nrestart")) return K_onrestart;  
  51.         break;  
  52.     case 'r':  
  53.         if (!strcmp(s, "estart")) return K_restart;  
  54.         break;  
  55.     case 's':  
  56.         if (!strcmp(s, "ervice")) return K_service;  
  57.         if (!strcmp(s, "etenv")) return K_setenv;  
  58.         if (!strcmp(s, "etkey")) return K_setkey;  
  59.         if (!strcmp(s, "etprop")) return K_setprop;  
  60.         if (!strcmp(s, "etrlimit")) return K_setrlimit;  
  61.         if (!strcmp(s, "ocket")) return K_socket;  
  62.         if (!strcmp(s, "tart")) return K_start;  
  63.         if (!strcmp(s, "top")) return K_stop;  
  64.         if (!strcmp(s, "ymlink")) return K_symlink;  
  65.         if (!strcmp(s, "ysclktz")) return K_sysclktz;  
  66.         break;  
  67.     case 't':  
  68.         if (!strcmp(s, "rigger")) return K_trigger;  
  69.         break;  
  70.     case 'u':  
  71.         if (!strcmp(s, "ser")) return K_user;  
  72.         break;  
  73.     case 'w':  
  74.         if (!strcmp(s, "rite")) return K_write;  
  75.         if (!strcmp(s, "ait")) return K_wait;  
  76.         break;  
  77.     }  
  78.     return K_UNKNOWN;  
  79. }  


5.kw_is

5.1.kw_is宏定义

  1. #define kw_is(kw, type) (keyword_info[kw].flags & (type))  

5.2.keyword_info全局数组的定义

  1. struct {  
  2.     const char *name;  
  3.     int (*func)(int nargs, char **args);  
  4.     unsigned char nargs;  
  5.     unsigned char flags;  
  6. } keyword_info[KEYWORD_COUNT] = {  
  7.     [ K_UNKNOWN ] = { "unknown", 0, 0, 0 },  
  8. #include "keywords.h"  
  9. };  

该数组包含了keywords.h文件

5.3.keywords.h文件内容

  1. #ifndef KEYWORD  
  2. int do_chroot(int nargs, char **args);  
  3. int do_chdir(int nargs, char **args);  
  4. int do_class_start(int nargs, char **args);  
  5. int do_class_stop(int nargs, char **args);  
  6. int do_domainname(int nargs, char **args);  
  7. int do_exec(int nargs, char **args);  
  8. int do_export(int nargs, char **args);  
  9. int do_hostname(int nargs, char **args);  
  10. int do_ifup(int nargs, char **args);  
  11. int do_insmod(int nargs, char **args);  
  12. int do_import(int nargs, char **args);  
  13. int do_mkdir(int nargs, char **args);  
  14. int do_mount(int nargs, char **args);  
  15. int do_restart(int nargs, char **args);  
  16. int do_setkey(int nargs, char **args);  
  17. int do_setprop(int nargs, char **args);  
  18. int do_setrlimit(int nargs, char **args);  
  19. int do_start(int nargs, char **args);  
  20. int do_stop(int nargs, char **args);  
  21. int do_trigger(int nargs, char **args);  
  22. int do_symlink(int nargs, char **args);  
  23. int do_sysclktz(int nargs, char **args);  
  24. int do_write(int nargs, char **args);  
  25. int do_copy(int nargs, char **args);  
  26. int do_chown(int nargs, char **args);  
  27. int do_chmod(int nargs, char **args);  
  28. int do_loglevel(int nargs, char **args);  
  29. int do_wait(int nargs, char **args);  
  30. #define __MAKE_KEYWORD_ENUM__  
  31. #define KEYWORD(symbol, flags, nargs, func) K_##symbol,  
  32. enum {  
  33.     K_UNKNOWN,  
  34. #endif  
  35.     KEYWORD(capability,  OPTION,  0, 0)  
  36.     KEYWORD(chdir,       COMMAND, 1, do_chdir)  
  37.     KEYWORD(chroot,      COMMAND, 1, do_chroot)  
  38.     KEYWORD(class,       OPTION,  0, 0)  
  39.     KEYWORD(class_start, COMMAND, 1, do_class_start)  
  40.     KEYWORD(class_stop,  COMMAND, 1, do_class_stop)  
  41.     KEYWORD(console,     OPTION,  0, 0)  
  42.     KEYWORD(critical,    OPTION,  0, 0)  
  43.     KEYWORD(disabled,    OPTION,  0, 0)  
  44.     KEYWORD(domainname,  COMMAND, 1, do_domainname)  
  45.     KEYWORD(exec,        COMMAND, 1, do_exec)  
  46.     KEYWORD(export,      COMMAND, 2, do_export)  
  47.     KEYWORD(group,       OPTION,  0, 0)  
  48.     KEYWORD(hostname,    COMMAND, 1, do_hostname)  
  49.     KEYWORD(ifup,        COMMAND, 1, do_ifup)  
  50.     KEYWORD(insmod,      COMMAND, 1, do_insmod)  
  51.     KEYWORD(import,      COMMAND, 1, do_import)  
  52.     KEYWORD(keycodes,    OPTION,  0, 0)  
  53.     KEYWORD(mkdir,       COMMAND, 1, do_mkdir)  
  54.     KEYWORD(mount,       COMMAND, 3, do_mount)  
  55.     KEYWORD(on,          SECTION, 0, 0)  
  56.     KEYWORD(oneshot,     OPTION,  0, 0)  
  57.     KEYWORD(onrestart,   OPTION,  0, 0)  
  58.     KEYWORD(restart,     COMMAND, 1, do_restart)  
  59.     KEYWORD(service,     SECTION, 0, 0)  
  60.     KEYWORD(setenv,      OPTION,  2, 0)  
  61.     KEYWORD(setkey,      COMMAND, 0, do_setkey)  
  62.     KEYWORD(setprop,     COMMAND, 2, do_setprop)  
  63.     KEYWORD(setrlimit,   COMMAND, 3, do_setrlimit)  
  64.     KEYWORD(socket,      OPTION,  0, 0)  
  65.     KEYWORD(start,       COMMAND, 1, do_start)  
  66.     KEYWORD(stop,        COMMAND, 1, do_stop)  
  67.     KEYWORD(trigger,     COMMAND, 1, do_trigger)  
  68.     KEYWORD(symlink,     COMMAND, 1, do_symlink)  
  69.     KEYWORD(sysclktz,    COMMAND, 1, do_sysclktz)  
  70.     KEYWORD(user,        OPTION,  0, 0)  
  71.     KEYWORD(wait,        COMMAND, 1, do_wait)  
  72.     KEYWORD(write,       COMMAND, 2, do_write)  
  73.     KEYWORD(copy,        COMMAND, 2, do_copy)  
  74.     KEYWORD(chown,       COMMAND, 2, do_chown)  
  75.     KEYWORD(chmod,       COMMAND, 2, do_chmod)  
  76.     KEYWORD(loglevel,    COMMAND, 1, do_loglevel)  
  77.     KEYWORD(ioprio,      OPTION,  0, 0)  
  78. #ifdef __MAKE_KEYWORD_ENUM__  
  79.     KEYWORD_COUNT,  
  80. };  
  81. #undef __MAKE_KEYWORD_ENUM__  
  82. #undef KEYWORD  
  83. #endif  

5.4.结合KEYWORD宏拆开全局keyword_info数组可得

  1. struct {  
  2.     const char *name;  
  3.     int (*func)(int nargs, char **args);  
  4.     unsigned char nargs;  
  5.     unsigned char flags;  
  6. } keyword_info[KEYWORD_COUNT] =   
  7. {  
  8. [ K_UNKNOWN     ] = { "unknown",        0,              0,      0       },  
  9. [ K_capability  ] = { "capability",     0,              0,      OPTION  },  
  10. [ K_chdir       ] = { "chdir",          do_chdir,       1,      COMMAND },  
  11. [ K_chroot      ] = { "chroot",         do_chroot,      1,      COMMAND },  
  12. [ K_class       ] = { "class",          0,              0,      OPTION, },  
  13. [ K_class_start ] = { "class_start",    do_class_start, 1,      COMMAND },  
  14. [ K_class_stop  ] = { "class_stop",     do_class_stop,  1,      COMMAND },  
  15. [ K_console     ] = { "console",        0,              0,      OPTION  },  
  16. [ K_critical    ] = { "critical",       0,              0,      OPTION  },  
  17. [ K_disabled    ] = { "disabled",       0,              0,      OPTION  },  
  18. [ K_domainname  ] = { "domainname",     do_domainname,  1,      COMMAND },  
  19. [ K_exec        ] = { "exec",           do_exec,        1,      COMMAND },  
  20. [ K_export      ] = { "export",         do_export,      2,      COMMAND },  
  21. [ K_group       ] = { "group",          0,              0,      OPTION  },  
  22. [ K_hostname    ] = { "hostname",       do_hostname,    1,      COMMAND },  
  23. [ K_ifup        ] = { "ifup",           do_ifup,        1       COMMAND },  
  24. [ K_insmod      ] = { "insmod",         do_insmod,      1,      COMMAND },  
  25. [ K_import      ] = { "import",         do_import,      1,      COMMAND },  
  26. [ K_keycodes    ] = { "keycodes",       0,              0,      OPTION  },  
  27. [ K_mkdir       ] = { "mkdir",          do_mkdir,       1,      COMMAND },  
  28. [ K_mount       ] = { "mount",          do_mount,       3,      COMMAND },  
  29. [ K_on          ] = { "on",             0,              0,      SECTION },///  
  30. [ K_oneshot     ] = { "oneshot",        0,              0,      OPTION  },  
  31. [ K_onrestart   ] = { "onrestart",      0,              0,      OPTION  },  
  32. [ K_restart     ] = { "restart",        do_restart,     1,      COMMAND },  
  33. [ K_service     ] = { "service",        0,              0,      SECTION },///  
  34. [ K_setenv      ] = { "setenv",         0,              2,      OPTION  },  
  35. [ K_setkey      ] = { "setkey",         do_setkey,      0,      COMMAND },  
  36. [ K_setprop     ] = { "setprop",        do_setprop,     2,      COMMAND },  
  37. [ K_setrlimit   ] = { "setrlimit",      do_setrlimit ,  3,      COMMAND },  
  38. [ K_socket      ] = { "socket",         0,              0,      OPTION  },  
  39. [ K_start       ] = { "start",          do_start,       1,      COMMAND },  
  40. [ K_stop        ] = { "stop",           do_stop,        1,      COMMAND },  
  41. [ K_trigger     ] = { "trigger",        do_trigger,     1,      COMMAND },  
  42. [ K_symlink     ] = { "symlink",        do_symlink,     1,      COMMAND },  
  43. [ K_sysclktz    ] = { "sysclktz",       do_sysclktz,    1,      COMMAND },  
  44. [ K_user        ] = { "user",           0,              0,      OPTION  },  
  45. [ K_wait        ] = { "wait",           do_wait,        1,      COMMAND },  
  46. [ K_write       ] = { "write",          do_write,       2,      COMMAND },  
  47. [ K_copy        ] = { "copy",           do_copy,        2,      COMMAND },  
  48. [ K_chown       ] = { "chown",          do_chown,       2,      COMMAND },  
  49. [ K_chmod       ] = { "chmod",          do_chmod,       2,      COMMAND },,  
  50. [ K_loglevel    ] = { "loglevel",       do_loglevel,    1,      COMMAND },  
  51. [ K_ioprio      ] = { "ioprio",         0,              0       OPTION  },  
  52. }  

5.5.同理可以理解

  1. #define kw_name(kw) (keyword_info[kw].name)     //根据关键词获取名字  
  2. #define kw_func(kw) (keyword_info[kw].func)     //根据关键词获取处理函数指针  
  3. #define kw_nargs(kw) (keyword_info[kw].nargs)   //根据关键词获取参数个数  

6.parse_new_section

  1. void parse_new_section(struct parse_state *state, int kw,int nargs, char **args)  
  2. {  
  3.     printf("[ %s %s ]\n", args[0],nargs > 1 ? args[1] : "");  
  4.     switch(kw) {  
  5.     case K_service: //service类型-->三、service的处理  
  6.         state->context = parse_service(state, nargs, args);  //解析service  
  7.         if (state->context) {  
  8.             state->parse_line = parse_line_service;  //设置parse_line函数,处理options  
  9.             return;  
  10.         }  
  11.         break;  
  12.     case K_on:      //on类型     -->四、action的处理  
  13.         state->context = parse_action(state, nargs, args);   //解析action  
  14.         if (state->context) {  
  15.             state->parse_line = parse_line_action;   //设置parse_line函数,处理command  
  16.             return;  
  17.         }  
  18.         break;  
  19.     }  
  20.     state->parse_line = parse_line_no_op;  
  21. }  

三、service的处理

1.相关结构体

  1. struct service {  
  2.     struct listnode slist;  
  3.     const char *name;  
  4.     const char *classname;  
  5.     unsigned flags;  
  6.     pid_t pid;  
  7.     time_t time_started;  
  8.     time_t time_crashed;  
  9.     int nr_crashed;  
  10.     uid_t uid;  
  11.     gid_t gid;  
  12.     gid_t supp_gids[NR_SVC_SUPP_GIDS];  
  13.     size_t nr_supp_gids;  
  14.     struct socketinfo *sockets;  
  15.     struct svcenvinfo *envvars;  
  16.     struct action onrestart;   
  17.     int *keycodes;  
  18.     int nkeycodes;  
  19.     int keychord_id;  
  20.     int ioprio_class;  
  21.     int ioprio_pri;  
  22.     int nargs;  
  23.     char *args[1];  
  24. }  

2.parse_service解析service

  1. static void *parse_service(struct parse_state *state, int nargs, char **args)  
  2. {  
  3.     struct service *svc;  
  4.     if (nargs < 3) { //至少要三个service 服务名 应用程序路径  
  5.         parse_error(state, "services must have a name and a program\n");  
  6.         return 0;  
  7.     }  
  8.     if (!valid_name(args[1])) {  
  9.         parse_error(state, "invalid service name '%s'\n", args[1]);  
  10.         return 0;  
  11.     }  
  12.   
  13.     svc = service_find_by_name(args[1]);    //根据服务名找到service  
  14.     if (svc) {  
  15.         parse_error(state, "ignored duplicate definition of service '%s'\n", args[1]);  
  16.         return 0;  
  17.     }  
  18.   
  19.     nargs -= 2; //参数个数调整  
  20.     svc = calloc(1, sizeof(*svc) + sizeof(char*) * nargs);  //分配service和参数内存  
  21.     if (!svc) {  
  22.         parse_error(state, "out of memory\n");  
  23.         return 0;  
  24.     }  
  25.     svc->name = args[1]; //服务名  
  26.     svc->classname = "default";  //默认设置service->classname为"default",在init.rc有一句class_start default  
  27.     memcpy(svc->args, args + 2, sizeof(char*) * nargs);  //复制参数,参数中移除argc[0]和argc[1],从argc[2]复制起  
  28.     svc->args[nargs] = 0;    //最后一个参数值为0表示参数结束  
  29.     svc->nargs = nargs;  //设置服务的参数个数为更新后的参数个数  
  30.     svc->onrestart.name = "onrestart";  
  31.     list_init(&svc->onrestart.commands); //初始化命令链表  
  32.     list_add_tail(&service_list, &svc->slist);   //添加到全局service_list链表中  
  33.     return svc;  
  34. }  

3.parse_line_service解析service的选项

  1. static void parse_line_service(struct parse_state *state, int nargs, char **args)   //解析service的选项options  
  2. {  
  3.     struct service *svc = state->context;  
  4.     struct command *cmd;  
  5.     int i, kw, kw_nargs;  
  6.   
  7.     if (nargs == 0) {   //参数个数为0直接返回  
  8.         return;  
  9.     }  
  10.   
  11.     svc->ioprio_class = IoSchedClass_NONE;  
  12.   
  13.     kw = lookup_keyword(args[0]);   //根据参数0获取关键词(选项Options)  
  14.     switch (kw) {  
  15.     case K_capability:  //capability  
  16.         break;  
  17.     case K_class:       //class  
  18.         if (nargs != 2) {  
  19.             parse_error(state, "class option requires a classname\n");  
  20.         } else {  
  21.             svc->classname = args[1];  
  22.         }  
  23.         break;  
  24.     case K_console:     //console  
  25.         svc->flags |= SVC_CONSOLE;  
  26.         break;  
  27.     case K_disabled:    //disabled  
  28.         svc->flags |= SVC_DISABLED;  
  29.         break;  
  30.     case K_ioprio:      //ioprio  
  31.         if (nargs != 3) {  
  32.             parse_error(state, "ioprio optin usage: ioprio <rt|be|idle> <ioprio 0-7>\n");  
  33.         } else {  
  34.             svc->ioprio_pri = strtoul(args[2], 0, 8);  
  35.   
  36.             if (svc->ioprio_pri < 0 || svc->ioprio_pri > 7) {  
  37.                 parse_error(state, "priority value must be range 0 - 7\n");  
  38.                 break;  
  39.             }  
  40.   
  41.             if (!strcmp(args[1], "rt")) {  
  42.                 svc->ioprio_class = IoSchedClass_RT;  
  43.             } else if (!strcmp(args[1], "be")) {  
  44.                 svc->ioprio_class = IoSchedClass_BE;  
  45.             } else if (!strcmp(args[1], "idle")) {  
  46.                 svc->ioprio_class = IoSchedClass_IDLE;  
  47.             } else {  
  48.                 parse_error(state, "ioprio option usage: ioprio <rt|be|idle> <0-7>\n");  
  49.             }  
  50.         }  
  51.         break;  
  52.     case K_group:   //group  
  53.         if (nargs < 2) {  
  54.             parse_error(state, "group option requires a group id\n");  
  55.         } else if (nargs > NR_SVC_SUPP_GIDS + 2) {  
  56.             parse_error(state, "group option accepts at most %d supp. groups\n",  
  57.                         NR_SVC_SUPP_GIDS);  
  58.         } else {  
  59.             int n;  
  60.             svc->gid = decode_uid(args[1]);  
  61.             for (n = 2; n < nargs; n++) {  
  62.                 svc->supp_gids[n-2] = decode_uid(args[n]);  
  63.             }  
  64.             svc->nr_supp_gids = n - 2;  
  65.         }  
  66.         break;  
  67.     case K_keycodes:    //keycodes  
  68.         if (nargs < 2) {  
  69.             parse_error(state, "keycodes option requires atleast one keycode\n");  
  70.         }   
  71.         else {  
  72.             svc->keycodes = malloc((nargs - 1) * sizeof(svc->keycodes[0]));  
  73.             if (!svc->keycodes) {  
  74.                 parse_error(state, "could not allocate keycodes\n");  
  75.             }   
  76.             else {  
  77.                 svc->nkeycodes = nargs - 1;  
  78.                 for (i = 1; i < nargs; i++) {  
  79.                     svc->keycodes[i - 1] = atoi(args[i]);  
  80.                 }  
  81.             }  
  82.         }  
  83.         break;  
  84.     case K_oneshot:     //oneshot  
  85.         svc->flags |= SVC_ONESHOT;  
  86.         break;  
  87.     case K_onrestart:   //onrestart  
  88.         nargs--;  
  89.         args++;  
  90.         kw = lookup_keyword(args[0]);  
  91.         if (!kw_is(kw, COMMAND)) {  
  92.             parse_error(state, "invalid command '%s'\n", args[0]);  
  93.             break;  
  94.         }  
  95.         kw_nargs = kw_nargs(kw);  
  96.         if (nargs < kw_nargs) {  
  97.             parse_error(state, "%s requires %d %s\n", args[0], kw_nargs - 1,kw_nargs > 2 ? "arguments" : "argument");  
  98.             break;  
  99.         }  
  100.   
  101.         cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);  
  102.         cmd->func = kw_func(kw);  
  103.         cmd->nargs = nargs;  
  104.         memcpy(cmd->args, args, sizeof(char*) * nargs);  
  105.         list_add_tail(&svc->onrestart.commands, &cmd->clist);  
  106.         break;  
  107.     case K_critical:    //critical  
  108.         svc->flags |= SVC_CRITICAL;  
  109.         break;  
  110.     case K_setenv:      //setenv  
  111.         { /* name value */  
  112.             struct svcenvinfo *ei;  
  113.             if (nargs < 2) {  
  114.                 parse_error(state, "setenv option requires name and value arguments\n");  
  115.                 break;  
  116.             }  
  117.             ei = calloc(1, sizeof(*ei));  
  118.             if (!ei) {  
  119.                 parse_error(state, "out of memory\n");  
  120.                 break;  
  121.             }  
  122.             ei->name = args[1];  
  123.             ei->value = args[2];  
  124.             ei->next = svc->envvars;  
  125.             svc->envvars = ei;  
  126.             break;  
  127.         }  
  128.     case K_socket:      //socket  
  129.         {/* name type perm [ uid gid ] */  
  130.         struct socketinfo *si;  
  131.             if (nargs < 4) {  
  132.                 parse_error(state, "socket option requires name, type, perm arguments\n");  
  133.                 break;  
  134.             }  
  135.             if (strcmp(args[2],"dgram") && strcmp(args[2],"stream")&& strcmp(args[2],"seqpacket")) {  
  136.                 parse_error(state, "socket type must be 'dgram', 'stream' or 'seqpacket'\n");  
  137.                 break;  
  138.             }  
  139.             si = calloc(1, sizeof(*si));  
  140.             if (!si) {  
  141.                 parse_error(state, "out of memory\n");  
  142.                 break;  
  143.             }  
  144.             si->name = args[1];  
  145.             si->type = args[2];  
  146.             si->perm = strtoul(args[3], 0, 8);  
  147.             if (nargs > 4)  
  148.                 si->uid = decode_uid(args[4]);  
  149.             if (nargs > 5)  
  150.                 si->gid = decode_uid(args[5]);  
  151.             si->next = svc->sockets;  
  152.             svc->sockets = si;  
  153.             break;  
  154.         }  
  155.     case K_user:        //user  
  156.         if (nargs != 2) {  
  157.             parse_error(state, "user option requires a user id\n");  
  158.         }   
  159.         else {  
  160.             svc->uid = decode_uid(args[1]);  
  161.         }  
  162.         break;  
  163.     default:  
  164.         parse_error(state, "invalid option '%s'\n", args[0]);  
  165.     }  
  166. }  

四、action的处理
1.相关结构体

  1. struct action {  
  2.     struct listnode alist;  
  3.     struct listnode qlist;  
  4.     struct listnode tlist;  
  5.     unsigned hash;  
  6.     const char *name;  
  7.     struct listnode commands;  
  8.     struct command *current;  
  9. };  
  10. struct command  
  11. {  
  12.     struct listnode clist;  
  13.     int (*func)(int nargs, char **args);  
  14.     int nargs;  
  15.     char *args[1];  
  16. };  

2.parse_action解析action

  1. static void *parse_action(struct parse_state *state, int nargs, char **args)  
  2. {  
  3.     struct action *act;  
  4.     if (nargs < 2) { //on类型的参数必须为2个 args[0]=on,args[1]=触发条件[trigger]  
  5.         parse_error(state, "actions must have a trigger\n");  
  6.         return 0;  
  7.     }  
  8.     if (nargs > 2) { //多了也不行  
  9.         parse_error(state, "actions may not have extra parameters\n");  
  10.         return 0;  
  11.     }  
  12.     act = calloc(1, sizeof(*act));  //分配action结构体内存  
  13.     act->name = args[1];  
  14.     list_init(&act->commands)    //初始化命令链表;  
  15.     list_add_tail(&action_list, &act->alist);    //添加到全局action_list链表中  
  16.     return act;  
  17. }  

3.parse_line_action解析command

  1. static void parse_line_action(struct parse_state* state, int nargs, char **args)    //解析command  
  2. {  
  3.     struct command *cmd;  
  4.     struct action *act = state->context;  
  5.     int (*func)(int nargs, char **args);  
  6.     int kw, n;  
  7.   
  8.     if (nargs == 0) {   //参数个数为0直接返回  
  9.         return;  
  10.     }  
  11.   
  12.     kw = lookup_keyword(args[0]);   //根据参数0,查找关键词  
  13.     if (!kw_is(kw, COMMAND)) {      //是否命令类型  
  14.         parse_error(state, "invalid command '%s'\n", args[0]);  
  15.         return;  
  16.     }  
  17.   
  18.     n = kw_nargs(kw);   //根据命令获取参数个数  
  19.     if (nargs < n) {  
  20.         parse_error(state, "%s requires %d %s\n", args[0], n - 1,n > 2 ? "arguments" : "argument");  
  21.         return;  
  22.     }  
  23.     cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs); //分配命令和参数内存  
  24.     cmd->func = kw_func(kw); //设置命令对应的函数  
  25.     cmd->nargs = nargs;          //设置参数个数  
  26.     memcpy(cmd->args, args, sizeof(char*) * nargs);  //复制参数  
  27.     list_add_tail(&act->commands, &cmd->clist);   //添加到state->context链表  
  28. }  



五、service和action的执行

前面分析了:init解析init.rc文件并筛选出service和action,分别设置其结构体成员并添加进各自的全局链表service_list和action_list中

接着分析下service和action的执行

在init的main函数中除了解析init.rc(init_parse_config_file("/init.rc");)

还解析了跟硬件相关的

 get_hardware_name(hardware, &revision);
    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
    init_parse_config_file(tmp);

解析的结果都同样保存在全局链表service_list和action_list中

接着会有以下几行函数

  1. action_for_each_trigger("early-init", action_add_queue_tail);  
  2. queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");  
  3. queue_builtin_action(property_init_action, "property_init");  
  4. queue_builtin_action(keychord_init_action, "keychord_init");  
  5. queue_builtin_action(console_init_action, "console_init");  
  6. queue_builtin_action(set_init_properties_action, "set_init_properties");  
  7. action_for_each_trigger("init", action_add_queue_tail);  
  8. action_for_each_trigger("early-fs", action_add_queue_tail);  
  9. action_for_each_trigger("fs", action_add_queue_tail);  
  10. action_for_each_trigger("post-fs", action_add_queue_tail);  
  11. queue_builtin_action(property_service_init_action, "property_service_init");  
  12. queue_builtin_action(signal_init_action, "signal_init");  
  13. queue_builtin_action(check_startup_action, "check_startup");  
  14. action_for_each_trigger("early-boot", action_add_queue_tail);  
  15. action_for_each_trigger("boot", action_add_queue_tail);  
  16. queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers");  

1.action_for_each_trigger

  1. void action_for_each_trigger(const char *trigger,void (*func)(struct action *act))  
  2. {  
  3.     struct listnode *node;  
  4.     struct action *act;  
  5.     list_for_each(node, &action_list) {     //遍历全局action_list  
  6.         act = node_to_item(node, struct action, alist);  
  7.         if (!strcmp(act->name, trigger)) {   //比较名字和trigger触发条件  
  8.             func(act);  //符合触发条件,则执行action_add_queue_tail函数  
  9.         }  
  10.     }  
  11. }  

1.1 action_add_queue_tail

  1. void action_add_queue_tail(struct action *act)  
  2. {  
  3.     list_add_tail(&action_queue, &act->qlist);  
  4. }  

综合上面的action_for_each_trigger函数集,可知main函数

依次处理脚本中on标志以 early-init init early-fs fs post-fs early-boot boot的trigger的action

执行action_add_queue_tail函数将action添加到全局action_queue队列链表

2.queue_builtin_action

  1. void queue_builtin_action(int (*func)(int nargs, char **args), char *name)  
  2. {  
  3.     struct action *act;  
  4.     struct command *cmd;  
  5.   
  6.     act = calloc(1, sizeof(*act));  //分配action内存  
  7.     act->name = name;    //设置名字  
  8.     list_init(&act->commands);   //初始化command链表  
  9.   
  10.     cmd = calloc(1, sizeof(*cmd));  //分配command  
  11.     cmd->func = func;    //设置执行函数为传递的第一个参数  
  12.     cmd->args[0] = name; //设置command的参数0  
  13.     list_add_tail(&act->commands, &cmd->clist);   //添加command到action的commands链表中  
  14.   
  15.     list_add_tail(&action_list, &act->alist);    //添加action到全局action_list链表中  
  16.     action_add_queue_tail(act); //添加action到全局action_queue队列链表  
  17. }  


创建以name标记的action,并添加进全局action_list中,同时添加进action_queue队列链表

所以全局action_queue队列链表中的顺序调整为

early-init [wait_for_coldboot_done] [property_init] [keychord_init] [console_init] [set_init_properties]

init early-fs fs post-fs [property_service_init] [signal_init] [check_startup] early-boot boot [queue_propety_triggers]

接着进入main的for(;;)循环体

3.execute_one_command执行一个command

  1. void execute_one_command(void)  
  2. {  
  3.     int ret;  
  4.     //第一次执行cur_action为0,执行完某个action下的所有command后cur_command为0,条件为真  
  5.     if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) {  
  6.         cur_action = action_remove_queue_head();    //获取下一个action  
  7.         cur_command = NULL;  
  8.         if (!cur_action)  
  9.             return;  
  10.         INFO("processing action %p (%s)\n", cur_action, cur_action->name);  
  11.         cur_command = get_first_command(cur_action);    //获取action的第一个command  
  12.     }   
  13.     else {  //循环执行某个action下的所有command  
  14.         cur_command = get_next_command(cur_action, cur_command);    //获取action的下一个command  
  15.     }  
  16.   
  17.     if (!cur_command)   //没有command可取了,则cur_command=0  
  18.         return;         //返回  
  19.   
  20.     ret = cur_command->func(cur_command->nargs, cur_command->args);    //执行command的处理函数  
  21.     INFO("command '%s' r=%d\n", cur_command->args[0], ret);  
  22. }  

因为execute_one_command套在for(;;)中所以会循环执行action_queue队列链表下的action的command

4.service_list下的服务的执行

4.1service由service_start启动

搜索代码遍历调用service_start的分支:

  1. KEYWORD(class_start, COMMAND, 1, do_class_start)  
  2. do_class_start->service_for_each_class->service_start_if_not_disabled->service_start  
  3.   
  4. KEYWORD(start,       COMMAND, 1, do_start)  
  5. do_start->service_start  
  6.   
  7. KEYWORD(restart,     COMMAND, 1, do_restart)  
  8. do_restart->service_start  
  9.   
  10. main[for(;;)]->restart_processes->service_for_each_flags->restart_service_if_needed->service_start  
  11.   
  12. main[for(;;)]->handle_property_set_fd->handle_control_message->msg_start->service_start  
  13.   
  14. main[for(;;)]->handle_keychord->service_start  

前三个分支是由处理command是调用的处理函数do_XXX调用的,也就是execute_one_command函数的处理过程会调用到
后三个分支是在init的main函数的循环体中调用
在init.rc中有一句class_start default
作为class_start命令在处理时会调用到do_class_start

  1. int do_class_start(int nargs, char **args)  //argc[1]=default  
  2. {  
  3.     service_for_each_class(args[1], service_start_if_not_disabled);  
  4.     return 0;  
  5. }  

service_for_each_class根据class类名查找service

  1. void service_for_each_class(const char *classname,void (*func)(struct service *svc))  
  2. {  
  3.     struct listnode *node;  
  4.     struct service *svc;  
  5.     list_for_each(node, &service_list) {    //遍历全局service_list  
  6.         svc = node_to_item(node, struct service, slist);  
  7.         if (!strcmp(svc->classname, classname)) {    //在前面parse_service函数中,将svc->classname = "default",所以为真  
  8.             func(svc);  //调用service_start_if_not_disabled  
  9.         }  
  10.     }  
  11. }  

service_start_if_not_disabled启动没有禁止启动的service

  1. static void service_start_if_not_disabled(struct service *svc)  
  2. {  
  3.     if (!(svc->flags & SVC_DISABLED)) {  //若没设置SVC_DISABLED标志,也就是init.rc中对应的service的options没有disabled  
  4.         service_start(svc, NULL);   //则会启动服务  
  5.     }  
  6. }  

到这里重要的正规的service就已经启动了

5.service_start的简单解析

  1. void service_start(struct service *svc, const char *dynamic_args)  
  2. {  
  3.     struct stat s;  
  4.     pid_t pid;  
  5.     int needs_console;  
  6.     int n;  
  7.   
  8.     svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING));  //去掉禁用和重启标志  
  9.     svc->time_started = 0;  
  10.       
  11.     if (svc->flags & SVC_RUNNING) {  //若已经运行了,则直接返回  
  12.         return;  
  13.     }  
  14.   
  15.     needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;  //需要console  
  16.     if (needs_console && (!have_console)) { //需要但没有console  
  17.         ERROR("service '%s' requires console\n", svc->name);  
  18.         svc->flags |= SVC_DISABLED;  
  19.         return;  
  20.     }  
  21.   
  22.     if (stat(svc->args[0], &s) != 0) {  
  23.         ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);  
  24.         svc->flags |= SVC_DISABLED;  
  25.         return;  
  26.     }  
  27.   
  28.     if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) { //没one-shot标志但使用了动态参数  
  29.         ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",svc->args[0]);  
  30.         svc->flags |= SVC_DISABLED;  
  31.         return;  
  32.     }  
  33.   
  34.     NOTICE("starting '%s'\n", svc->name);    //打印信息  
  35.   
  36.     pid = fork();   //创建进程  
  37.   
  38.     if (pid == 0) { //子进程  
  39.         struct socketinfo *si;  
  40.         struct svcenvinfo *ei;  
  41.         char tmp[32];  
  42.         int fd, sz;  
  43.   
  44.         if (properties_inited()) {  
  45.             get_property_workspace(&fd, &sz);  
  46.             sprintf(tmp, "%d,%d", dup(fd), sz);  
  47.             add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);  
  48.         }  
  49.   
  50.         for (ei = svc->envvars; ei; ei = ei->next)  
  51.             add_environment(ei->name, ei->value);  
  52.   
  53.         for (si = svc->sockets; si; si = si->next) {  
  54.             int socket_type = (!strcmp(si->type, "stream") ? SOCK_STREAM :(!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));  
  55.             int s = create_socket(si->name, socket_type,si->perm, si->uid, si->gid);  
  56.             if (s >= 0) {  
  57.                 publish_socket(si->name, s);  
  58.             }  
  59.         }  
  60.   
  61.         if (svc->ioprio_class != IoSchedClass_NONE) {  
  62.             if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {  
  63.                 ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno));  
  64.             }  
  65.         }  
  66.   
  67.         if (needs_console) {    //需要控制台  
  68.             setsid();  
  69.             open_console(); //打开控制台  
  70.         } else {  
  71.             zap_stdio();  
  72.         }  
  73.   
  74.         setpgid(0, getpid());  
  75.   
  76.         if (svc->gid) {  
  77.             setgid(svc->gid);  
  78.         }  
  79.         if (svc->nr_supp_gids) {  
  80.             setgroups(svc->nr_supp_gids, svc->supp_gids);  
  81.         }  
  82.         if (svc->uid) {  
  83.             setuid(svc->uid);  
  84.         }  
  85.   
  86.         if (!dynamic_args) {  
  87.             if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {//service 路径参数对应的应用程序  
  88.                 ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));  
  89.             }  
  90.         }   
  91.         else {  
  92.             char *arg_ptrs[INIT_PARSER_MAXARGS+1];  
  93.             int arg_idx = svc->nargs;  
  94.             char *tmp = strdup(dynamic_args);  
  95.             char *next = tmp;  
  96.             char *bword;  
  97.   
  98.             /* Copy the static arguments */  
  99.             memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));  
  100.   
  101.             while((bword = strsep(&next, " "))) {  
  102.                 arg_ptrs[arg_idx++] = bword;  
  103.                 if (arg_idx == INIT_PARSER_MAXARGS)  
  104.                     break;  
  105.             }  
  106.             arg_ptrs[arg_idx] = '\0';  
  107.             execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);   //service 路径参数对应的应用程序  
  108.         }  
  109.         _exit(127);  
  110.     }  
  111.   
  112.     if (pid < 0) {  
  113.         ERROR("failed to start '%s'\n", svc->name);  
  114.         svc->pid = 0;  
  115.         return;  
  116.     }  
  117.   
  118.     svc->time_started = gettime();   //记录service启动时间  
  119.     svc->pid = pid;  //记录service的pid号  
  120.     svc->flags |= SVC_RUNNING;   //添加已运行标志SVC_RUNNING  
  121.   
  122.     if (properties_inited())  
  123.         notify_service_state(svc->name, "running");  
  124. }  

这里execve(svc->args[0], (char**) arg_ptrs, (char**) ENV)中args[0]是init.rc中service <name> <pathname> [ <argument> ]*的<pathname>,

arg_ptrs指向[ <argument> ]*

例如:service servicemanager /system/bin/servicemanager就会执行execve(/system/bin/servicemanager,...........)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值