在init.rc启动脚本中
on early-init
start ueventd
就会调用ueventd,其源码位于system/core/init/ueventd.c,主函数int ueventd_main(int argc, char **argv),其中用到以下结构
parser.h
//定义三个宏 #define T_EOF 0 #define T_TEXT 1 #define T_NEWLINE 2 struct parse_state { char *ptr; //读指针 char *text; int line; int nexttoken; //下一个标识符 void *context; void (*parse_line)(struct parse_state *state, int nargs, char **args); //读取行函数 const char *filename; };
system/core/init/ueventd.c
int ueventd_main(int argc, char **argv) { struct pollfd ufd; int nr; char tmp[32]; open_devnull_stdio(); log_init(); INFO("starting ueventd\n"); get_hardware_name(hardware, &revision); /* /ueventd.rc中以行为单位,除最后sysfs properties外,每一行由四部分组成: 如:/dev/diag 0660 radio radio 目录 权限 用户ID(uid) 组ID(gid) # sysfs properties 多一个属性 /sys/devices/virtual/input/input* enable 0660 root input 目录 属性 权限 用户ID(uid) 组ID(gid) */ ueventd_parse_config_file("/ueventd.rc"); snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware); ueventd_parse_config_file(tmp); //初始化uevent,建立socket,执行coldboot,用于检查当前service启动前操作系统已经处理的事件,add这些事件到应用层 device_init(); ufd.events = POLLIN; ufd.fd = get_device_fd(); //在死循环中处理触发事件 while(1) { ufd.revents = 0; nr = poll(&ufd, 1, -1); if (nr <= 0) continue; if (ufd.revents == POLLIN) handle_device_fd(); } }其中ueventd_parse_config_file用于解析rc文件
Uevent_parser.c
int ueventd_parse_config_file(const char *fn) { char *data; data = read_file(fn, 0); //读取文件内容返回给data if (!data) return -1; parse_config(fn, data); DUMP(); //空函数什么都不做 return 0; } static void parse_config(const char *fn, char *s) { struct parse_state state; char *args[UEVENTD_PARSER_MAXARGS]; //最多五个参数 int nargs; nargs = 0; state.filename = fn; state.line = 1; state.ptr = s; state.nexttoken = 0; state.parse_line = parse_line_device; for (;;) { int token = next_token(&state); //用于获得配置文件中特殊标记,如文件结尾(T_EOF),换行符(T_TEXT),文本(T_NEWLINE) switch (token) { case T_EOF: state.parse_line(&state, 0, 0); //state.parse_line 调用函数为parse_line_device; return; case T_NEWLINE: if (nargs) { state.parse_line(&state, nargs, args); nargs = 0; } break; case T_TEXT: if (nargs < UEVENTD_PARSER_MAXARGS) { args[nargs++] = state.text; } break; } } }
parser.c
int next_token(struct parse_state *state) { char *x = state->ptr; //读数据指针 char *s; /* #define T_EOF 0 #define T_TEXT 1 #define T_NEWLINE 2 非T_EOF时,直接返回下一个标记 */ if (state->nexttoken) { int t = state->nexttoken; state->nexttoken = 0; return t; } for (;;) { switch (*x) { case 0: state->ptr = x; return T_EOF; case '\n': x++; state->ptr = x; return T_NEWLINE; //换行符 case ' ': case '\t': case '\r': x++; continue; //跳过转义字符 :空格 tab 回车 case '#': while (*x && (*x != '\n')) x++; //单行注释 if (*x == '\n') { state->ptr = x+1; return T_NEWLINE; } else { state->ptr = x; return T_EOF; } default: goto text; } } textdone: state->ptr = x; *s = 0; return T_TEXT; text: state->text = s = x; textresume: for (;;) { switch (*x) { case 0: goto textdone; case ' ': case '\t': case '\r': x++; goto textdone; case '\n': state->nexttoken = T_NEWLINE; x++; goto textdone; case '"': x++; for (;;) { switch (*x) { case 0: /* unterminated quoted thing */ state->ptr = x; return T_EOF; case '"': x++; goto textresume; default: *s++ = *x++; } } break; case '\\': x++; switch (*x) { case 0: goto textdone; case 'n': *s++ = '\n'; break; case 'r': *s++ = '\r'; break; case 't': *s++ = '\t'; break; case '\\': *s++ = '\\'; break; case '\r': /* \ <cr> <lf> -> line continuation */ if (x[1] != '\n') { x++; continue; } case '\n': /* \ <lf> -> line continuation */ state->line++; x++; /* eat any extra whitespace */ while((*x == ' ') || (*x == '\t')) x++; continue; default: /* unknown escape -- just copy */ *s++ = *x++; } continue; default: *s++ = *x++; } } return T_EOF; }
static void parse_line_device(struct parse_state* state, int nargs, char **args) { set_device_permission(nargs, args); //nargs参数个数 args参数 }
在此函数中根据参数个数和参数内容解析ueventd.rc,获得路径名称 属性 权限 uid gid ,
最后调用add_dev_perms(name, attr, perm, uid, gid, prefix);添加到链表