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

本文详细介绍了Android系统中init.rc文件的语法规则,包括动作、命令、服务和选项的使用。通过解析init.rc文件,了解service和action的处理流程,以及如何在系统启动时执行。主要内容涉及service_start的执行过程,解析了如何根据init.rc启动action和service。
摘要由CSDN通过智能技术生成

一、init.rc语法规则

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

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

2.动作和命令一起使用

on 	<trigger>
	<command>
	<command>
	<command>

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

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

3.服务和选项一起使用

service <name> <pathname> [ <argument> ]*
	<option>
	<option>

3.1.option选项

critical
disabled
setenv <name> <value>
socket <name> <type> <perm> [ <user> [ <group> ] ]
user <username>
group <groupname> [ <groupname> ]*
oneshot
class <name>
onrestart

 

二、init.rc文件的解析

1.init_parse_config_file

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

init_parse_config_file("/init.rc");

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

int init_parse_config_file(const char *fn)
{
    char *data;
    data = read_file(fn, 0);	//读取init.rc文件到data中
    if (!data) return -1;

    parse_config(fn, data);		//解析配置
    DUMP();
    return 0;
}

2.解析配置parse_config

static void parse_config(const char *fn, char *s)
{
    struct parse_state state;
    char *args[INIT_PARSER_MAXARGS];
    int nargs;

    nargs = 0;
    state.filename = fn;
    state.line = 1;
    state.ptr = s;	//指向init.rc的数据
    state.nexttoken = 0;
    state.parse_line = parse_line_no_op;	//空操作
    for (;;) {
        switch (next_token(&state)) {	//-->3.next_token跳过注释等,筛选需要解析的行
        case T_EOF:		//文件末尾
            state.parse_line(&state, 0, 0);	//后面参数为 0, 0所以直接返回
            return;
        case T_NEWLINE:	//新行解析
            if (nargs) {	//有文本参数
                int kw = lookup_keyword(args[0]);	//解析关键词-->4.lookup_keyword
                if (kw_is(kw, SECTION)) {	//判断是否section类-->5.kw_is
                    state.parse_line(&state, 0, 0);	//后面参数为 0, 0所以直接返回
                    parse_new_section(&state, kw, nargs, args); //6.parse_new_section
                } 
		else {
                    state.parse_line(&state, nargs, args);	//解析前一行parse_line_service或parse_line_action
                }
                nargs = 0;	//nargs参数个数清0
            }
            break;
        case T_TEXT:	//文本
            if (nargs < INIT_PARSER_MAXARGS) {
                args[nargs++] = state.text;	//保存文本参数,nargs++
            }
            break;
        }
    }
}

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

int next_token(struct parse_state *state)
{
    char *x = state->ptr;
    char *s;

    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':	//换行
            state->line++;	//行数++
            x++;
            state->ptr = x;
            return T_NEWLINE;
        case ' ':	//空格
        case '\t':	//tab制表
        case '\r':	//回车
            x++;
            continue;
        case '#':	//注释
            while (*x && (*x != '\n')) 	//跳过注释直到换行
				x++;
            state->line++;	//行数++
            state->ptr = x;
            return T_NEWLINE;
        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':	//tab制表
        case '\r':	//回车
            x++;
            goto textdone;
        case '\n':	//换行
            state->nexttoken = T_NEWLINE;
            x++;
            goto textdone;
        case '"':	//引号括起
            x++;
            for (;;) {
                switch (*x) {
                case 0:
                    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
            *s++ = *x++;
        }
    }
    return T_EOF;
}

4.lookup_keyword

int lookup_keyword(const char *s)
{
    switch (*s++) {
    case 'c':
    	if (!strcmp(s, "opy")) return K_copy;
        if (!strcmp(s, "apability")) return K_capability;
        if (!strcmp(s, "hdir")) return K_chdir;
        if (!strcmp(s, "hroot")) return K_chroot;
        if (!strcmp(s, "lass")) return K_class;
        if (!strcmp(s, "lass_start")) return K_class_start;
        if (!strcmp(s, "lass_stop")) return K_class_stop;
        if (!strcmp(s, "onsole")) return K_console;
        if (!strcmp(s, "hown")) return K_chown;
        if (!strcmp(s, "hmod")) return K_chmod;
        if (!strcmp(s, "ritical")) return K_critical;
        break;
    case 'd':
        if (!strcmp(s, "isabled")) return K_disabled;
        if (!strcmp(s, "omainname")) return K_domainname;
        break;
    case 'e':
        if (!strcmp(s, "xec")) return K_exec;
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值