android 8.0 rc 文件,Android8.0.0-r4 init.rc文件解析

当前某个服务的状态,可为"stopped","running", "restarting"

setprop 用于设置属性,on property可以用于判断属性,这里的属性在整个Android系统运行中都是一致的。init脚本的关键字可以参考init进程的system/core/init/keyword.h文件。init.rc的使用方法,可以参考说明文件system/core/init/readme.txt。如果想要修改启动过程只需要修改init.c(system/core/init)或者init.rc里的内容即可

四、init.rc 文件解析过程

文件结构

init.rc 基本单位是 section。

section 有三种类型:

1. on

2. service

3. import

解析 init.rc 的过程就是识别一个个 section 的过程。在 init.c 中的 main() 中去执行一个个命令。

(android采用双向链表来存储section的信息,解析完成之后,会得到三个双向链表action_list、service_list、import_list来分别存储三种section的信息上。)

system/core/init/init.c

在 init.c 中调用

init_parse_config_file("/init.rc");

其代码实现如下:

int init_parse_config_file(const char *fn)

{

char *data;

data = read_file(fn, 0); //read_file()调用open\lseek\read 将init.rc读出来

if (!data) return -1;

parse_config(fn, data); //调用parse_config开始解析

DUMP();

return 0;

}

parse_config() 代码:

static void parse_config(const char *fn, char *s)

{

struct parse_state state;

struct listnode import_list;

struct listnode *node;

char *args[INIT_PARSER_MAXARGS];

int nargs;

nargs = 0;

state.filename = fn; //文件名

state.line = 0;

state.ptr = s; //文字指针

state.nexttoken = 0;

state.parse_line = parse_line_no_op;

list_init(&import_list);

state.priv = &import_list;

for (;;) {

switch (next_token(&state)) { //next_token()根据从state.ptr开始遍历

case T_EOF: //遍历到文件结尾,然后goto解析import的.rc文件

state.parse_line(&state, 0, 0);

goto parser_done;

case T_NEWLINE: //到了一行结束

state.line++;

if (nargs) {

int kw = lookup_keyword(args[0]); //找到这一行的关键字

if (kw_is(kw, SECTION)) { //如果这是一个section的第一行

state.parse_line(&state, 0, 0);

parse_new_section(&state, kw, nargs, args);

} else { //如果这不是一个section的第一行

state.parse_line(&state, nargs, args);

}

nargs = 0;

}

break;

case T_TEXT: //遇到普通字符

if (nargs < INIT_PARSER_MAXARGS) {

args[nargs++] = state.text;

}

break;

}

}

parser_done:

list_for_each(node, &import_list) {

struct import *import = node_to_item(node, struct import, list);

int ret;

INFO("importing '%s'", import->filename);

ret = init_parse_config_file(import->filename);

if (ret)

ERROR("could not import file '%s' from '%s'\n",

import->filename, fn);

}

}

next_token() 解析完 init.rc 中一行之后,

会返回T_NEWLINE,这时调用 lookup_keyword 函数来找出这一行的关键字, lookup_keyword返回的是一个整型值,对应keyword_info[]数组的下标,keyword_info[]存放的是keyword_info结构体类型的数据,

struct {

const char *name; //关键字的名称

int (*func)(int nargs, char **args); //对应的处理函数

unsigned char nargs; //参数个数

unsigned char flags; //flag标识关键字的类型,包括COMMAND、OPTION、SECTION

} keyword_info

因此keyword_info[]中存放的是所有关键字的信息,每一项对应一个关键字。

根据每一项的flags就可以判断出关键字的类型,如新的一行是SECTION,就调用parse_new_section()来解析这一行,

如新的一行不是一个SECTION的第一行,那么调用state.parseline()来解析(state.parseline所对应的函数会根据section类型的不同而不同),在parse_new_section()中进行动态设置。

三种类型的section: service、on、import,

service对应的state.parseline为parse_line_service,

on对应的state.parseline为parse_line_action,

import section中只有一行所以没有对应的state.parseline。

五. 总结

5.1 服务名的命名规则

service 的名字长度不能超过16个字节

service 的名字只能是字母,数字和'-','_'

5.2 系统组

system/core/include/private/android_filesystem_config.h中的android_ids定义了系统中所有进程的gid值

"root" AID_ROOT

"system" AID_SYSTEM

5.3 系统中propertey属性

可以在makefile中用宏PRODUCT_DEFAULT_PROPERTY_OVERRIDES定义缺省的property

系统中有PROP_PATH_SYSTEM_BUILD和PROP_PATH_SYSTEM_DEFAULT

system/build.prop;

system/default.prop

system.prop

并且init 进程创建了/dev/socket/property_service socket去监听 设置prop的请求.

5.4 service的启动

执行完on boot以后,就会依次启动core,main,defualt类中的服务

最终init进程通过执行fork创建进程

5.5 init进程

所有的service都是init进程的子进程,当init进程执行完init.rc以后,就会监听所有service的退出状态,propertery的设置。

六. 其他工具

Bootcharting

init的这个版本包含运行”bootcharting”的代码:生成一个日志文件,后期能够被 www.bootchart.org

提供的工具处理。

在虚拟机中,使用-bootchart 选项来使启动的时候带有bootcharting持续秒。

在一个设备中,使用命令创建 /data/bootchart/start:

adb shell 'echo $TIMEOUT > /data/bootchart/start'

$TIMEOUT的值对应着期望bootchart持续的秒数。当这些时间过后,Bootcharting将会停止。

你可以通过下面的命令在任何时候停bootcharting:

adb shell 'echo 1 > /data/bootchart/stop'

注意,/data/bootchart/stop会在bootcharting最后被init自动删除。对于/data/bootchart/start

情况并非如此,所以当你收集完数据之后,不要忘记删除他。

日志文件被写入/data/bootchart中。一个脚本被提供去恢复他们,并且创建一个bootchart.tgz文件

,这个文件可以被bootchart命令行工具使用:

sudo apt-get install pybootchartgui

# grab-bootchart.sh uses $ANDROID_SERIAL.

$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh

一个需要注意的事情就是,bootchart将会显示init好像是他从0s的时候开始运行。当内核

开始init的时候,你必须查看dmesg的工作。

Debugging init

默认的,由init执行的程序将会把标准输出和标准错误丢入到/dev/null。为了帮助调试,

你可以通过安卓程序日志封装程序运行你的程序。这个将会重定向标准输出/标准错误到

安卓日志系统中。

例如

service akmd /system/bin/logwrapper /sbin/akmd

当在init中自己运行的时候,为了快速的转变,使用:

mm -j

m ramdisk-nodeps

m bootimage-nodeps

adb reboot bootloader

fastboot boot $ANDROID_PRODUCT_OUT/boot.img

可选的,使用虚拟机:

emulator -partition-size 1024 -verbose -show-kernel -no-window

在klog_init()调用之后,你可能想要调用klog_set_level(6),所以你需要在

dmesg或者是虚拟机输出中查看内核日志。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值