android ueventd 本地native部分源码分析

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mociml/article/details/6801004

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);添加到链表






展开阅读全文

没有更多推荐了,返回首页