您的位置:首页 > 产品设计 > UI/UE

android ueventd 本地native部分源码分析

2014-07-09 16:24 459 查看
在init.rc启动脚本中

on early-init

start ueventd

就会调用ueventd,其源码位于system/core/init/ueventd.c,主函数int ueventd_main(int argc, char **argv),其中用到以下结构

parser.h

在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);添加到链表
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: