Android init.rc文件解析过程详解(三)
Android init.rc文件解析过程详解(三)
三、相关结构体
1、listnode
listnode结构体用于建立双向链表,这种结构广泛用于kernel代码中, android源代码中定义了listnode结构体以及相关操作双向链表的方法,与kernel中的定义类似。
这个实现的核心思想是:在用户自定义的结构体xx中定义一个listnode类型的成员,
这个listnode类型成员的作用就是能将xx类型的变量组成一个双向链表。下面我们来看一下是listnode是怎么做到的。
//listnode类型里面只有两个指针prev,next
struct listnode
{
struct listnode *next;
struct listnode *prev;
};
//将链表中的一个node转换成自定义结构体中的一个对象
#define node_to_item(node, container, member) \
(container *) (((char*) (node)) - offsetof(container, member))
//初始化一个链表
void list_init(struct listnode *node)
{
node->next = node;
node->prev = node;
}
//将一个节点到链表
void list_add_tail(struct listnode *head, struct listnode *item)
{
item->next = head;
item->prev = head->prev;
head->prev->next = item;
head->prev = item;
}
//删除一个节点
void list_remove(struct listnode *item)
{
item->next->prev = item->prev;
item->prev->next = item->next;
}
理解node_to_item宏是理解listnode用法的关键,这个宏的作用是将一个listnode指针转换成了一个指定类型(自定义)的指针,这个宏先使用offsetof函数获取到指定结构体中指定成员变量的地址偏移量,然后通过指针运算获得listnode指针变量所在结构体变量的指针。
这种实现与我们课堂上所学的链表实现方法不太一样,教科书上的实现是在listnode中存储了自定义的数据,而这个实现是在自定义的数据当中存储listnode指针。
2、action结构体
前面已经讲过on类型的section解析之后会生成一个双向链表action_list, 这个action_list每个node表示就是action结构体的对象,也就是说一个on类型的section都会生成一个action结构体的对象。
action结构体定义如下:
struct action {
/* node in list of all actions */
struct listnode alist;
/* node in the queue of pending actions */
struct listnode qlist;
/* node in list of actions for a trigger */
struct listnode tlist;
unsigned hash;
const char *name;
struct listnode commands; //节点为command结构体的双向链表
struct command *current;
};
action结构体除了用在on类型的section, 也用在service类型的section,下面介绍service结构体时会说明。
3、command结构体
Command结构体定义如下:
struct command
{
/* list of commands in an action */
struct listnode clist;
int (*func)(int nargs, char **args);
int nargs;
char *args[1];
};
command结构体比较简单, 用于标识一个命令,包含双向链表指针、对应的执行函数、参数个数以及命令关键字。
4、service结构体
struct service {
/* list of all services */
struct listnode slist; //将结构体链接成service_list用
const char *name;
const char *classname;
unsigned flags;
pid_t pid;
time_t time_started; /* time of last start */
time_t time_crashed; /* first crash within inspection window */
int nr_crashed; /* number of times crashed within window */
uid_t uid;
gid_t gid;
gid_t supp_gids[NR_SVC_SUPP_GIDS];
size_t nr_supp_gids;
#ifdef HAVE_SELINUX
char *seclabel;
#endif
struct socketinfo *sockets;
struct svcenvinfo *envvars;
struct action onrestart; /* Actions to execute on restart. */
/* keycodes for triggering this service via /dev/keychord */
int *keycodes;
int nkeycodes;
int keychord_id;
int ioprio_class;
int ioprio_pri;
int nargs;
/* "MUST BE AT THE END OF THE STRUCT" */
char *args[1];
};
service结构体存储了service的相关信息, 包括进程号、启动时间、名字等, 字段onrestart
就用到了action结构体, onrestart这个option后面通常跟着一个命令,所以也用action结构体来表示。
注:本文基于android4.2的源代码分析
最后我们分析一下init.c中的main()函数
01
|
int main( int argc, char **argv)
|
02
|
{
|
03
|
... ...
|
04
|
/* Get the basic filesystem setup we need put
|
05
|
* together in the initramdisk on / and then we'll
|
06
|
* let the rc file figure out the rest.
|
07
|
*/
|
08
|
// 创建一些linux根文件系统中的目录
|
09
|
mkdir( "/dev" , 0755);
|
10
|
mkdir( "/proc" , 0755);
|
11
|
mkdir( "/sys" , 0755);
|
12
|
13
|
mount( "tmpfs" , "/dev" , "tmpfs" , MS_NOSUID, "mode=0755" );
|
14
|
mkdir( "/dev/pts" , 0755);
|
15
|
mkdir( "/dev/socket" , 0755);
|
16
|
mount( "devpts" , "/dev/pts" , "devpts" , 0, NULL);
|
17
|
mount( "proc" , "/proc" , "proc" , 0, NULL);
|
18
|
mount( "sysfs" , "/sys" , "sysfs" , 0, NULL);
|
19
|
20
|
//open_devnull_stdio();
|
21
|
klog_init();
|
22
|
23
|
... ...
|
24
|
25
|
printf ( "Parsing init.rc ...\n" );
|
26
|
// 读取并且解析init.rc文件
|
27
|
init_parse_config_file( "/init.rc" );
|
28
|
29
|
... ...
|
30
|
31
|
// 取得硬件名
|
32
|
get_hardware_name();
|
33
|
snprintf(tmp, sizeof (tmp), "/init.%s.rc" , hardware);
|
34
|
35
|
// 读取并且解析硬件相关的init脚本文件
|
36
|
parse_config_file(tmp);
|
37
|
38
|
... ...
|
39
|
40
|
# 触发在init脚本文件中名字为early-init的action,并且执行其commands,其实是: on early-init
|
41
|
action_for_each_trigger( "early-init" , action_add_queue_tail);
|
42
|
43
|
queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done" );
|
44
|
queue_builtin_action(property_init_action, "property_init" );
|
45
|
queue_builtin_action(keychord_init_action, "keychord_init" );
|
46
|
# 控制台相关初始化,在这里会加载启动动画,如果动画打开失败,则在屏幕上打印: A N D R O I D字样。
|
47
|
queue_builtin_action(console_init_action, "console_init" );
|
48
|
queue_builtin_action(set_init_properties_action, "set_init_properties" );
|
49
|
50
|
/* execute all the boot actions to get us started */
|
51
|
# 触发在init脚本文件中名字为init的action,并且执行其commands,其实是:on init
|
52
|
action_for_each_trigger( "init" , action_add_queue_tail);
|
53
|
54
|
/* skip mounting filesystems in charger mode */
|
55
|
if ( strcmp (bootmode, "charger" ) != 0) {
|
56
|
action_for_each_trigger( "early-fs" , action_add_queue_tail);
|
57
|
action_for_each_trigger( "fs" , action_add_queue_tail);
|
58
|
action_for_each_trigger( "post-fs" , action_add_queue_tail);
|
59
|
action_for_each_trigger( "post-fs-data" , action_add_queue_tail);
|
60
|
}
|
61
|
62
|
// 启动系统属性服务: system property service
|
63
|
queue_builtin_action(property_service_init_action, "property_service_init" );
|
64
|
queue_builtin_action(signal_init_action, "signal_init" );
|
65
|
queue_builtin_action(check_startup_action, "check_startup" );
|
66
|
67
|
queue_builtin_action(queue_early_property_triggers_action, "queue_early_propety_triggers" );
|
68
|
69
|
if (! strcmp (bootmode, "charger" )) {
|
70
|
action_for_each_trigger( "charger" , action_add_queue_tail);
|
71
|
} else {
|
72
|
// 触发在init脚本文件中名字为early-boot和boot的action,并且执行其commands,其实是:on early-boot和on boot
|
73
|
action_for_each_trigger( "early-boot" , action_add_queue_tail);
|
74
|
action_for_each_trigger( "boot" , action_add_queue_tail);
|
75
|
}
|
76
|
77
|
/* run all property triggers based on current state of the properties */
|
78
|
// 启动所有属性变化触发命令,其实是: on property:ro.xx.xx=xx
|
79
|
queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers" );
|
80
|
81
|
// 进入死循环
|
82
|
for (;;) {
|
83
|
int nr, i, timeout = -1;
|
84
|
85
|
execute_one_command();
|
86
|
// 启动所有init脚本中声明的service
|
87
|
restart_processes();
|
88
|
... ...
|
89
|
// 多路监听设备管理,子进程运行状态,属性服务
|
90
|
nr = poll(ufds, fd_count, timeout);
|
91
|
... ...
|
92
|
}
|
93
|
94
|
return 0;
|
95
|
}
|
转载:http://blog.itpub.net/7232789/viewspace-758168/
http://blog.csdn.net/mk1111/article/details/16357327
Android init.rc文件解析过程详解(三)相关推荐
- 安卓 linux init.rc,[原创]Android init.rc文件解析过程详解(二)
Android init.rc文件解析过程详解(二) 3.parse_new_section代码如下: void parse_new_section(struct parse_state *state ...
- Android init.rc文件解析过程详解(二)
Android init.rc文件解析过程详解(二) 3.parse_new_section代码如下: void parse_new_section(struct parse_state *state ...
- Android init.rc文件解析过程详解(一)
Android init.rc文件解析过程详解(一) 一.init.rc文件结构介绍 init.rc文件基本组成单位是section, section分为三种类型,分别由三个关键字(所谓关键字 ...
- Android init.rc文件格式解析
/****************************************************************************** Android init.rc文件格式解 ...
- 加载vue文件步骤_vue中.vue文件解析步骤详解
这次给大家带来vue中.vue文件解析步骤详解,vue中.vue文件解析的注意事项有哪些,下面就是实战案例,一起来看一下. 我们平时写的 .vue 文件称为 SFC(Single File Compo ...
- php android 图片上传,android上传图片到PHP的过程详解
这篇文章主要介绍了android上传图片到PHP的过程详解,需要的朋友可以参考下 今天在做上传头像的时候,总是提交连接超时错误,报错信息如下:XXXXXXSokcetTimeOutXXXXXXXX 然 ...
- Android签名机制之---签名验证过程详解
一.前言 今天是元旦,也是Single Dog的嚎叫之日,只能写博客来祛除寂寞了,今天我们继续来看一下Android中的签名机制的姊妹篇:Android中是如何验证一个Apk的签名.在前一篇文章中我们 ...
- Android之手机文件夹目录详解
android系统的手机文件夹目录详解 一.文件夹 1./acct/ 系统回收站,删除的系统文件. 2./cache/ 缓存 3./data/ 用户的所有程序相关数据 app/ ...
- Android 系统服务管家servicemanager启动过程详解
Android考虑到移动设备耗电以及跨进程通信效率等因素,基于OpenBinder专门为进程通信开发了一套框架:binder.例如,客户端程序需要获取WindowManager,TelephonyMa ...
最新文章
- Ubuntu14.04 64位上配置终端显示git分支名称
- U.S.News最新美国大学排名:普林斯顿蝉联总榜第一,MIT领跑计算机,弗罗里达成新贵...
- linux 系统监控 php,Linux系统资源监控命令简介
- 江苏省2013年会计从业资格考试《会计基础》全真模拟试题
- 解决AJAX表单用POST方式提交Checkbox复选框的问题
- 《Windows核心编程》---Interlocked原子访问系列函数
- python 识别数字字母 训练集_Python 实现训练集、测试集随机划分
- c++分治法求最大最小值实现_程序员:算法导论,分治法、归并排序,伪代码和Java实现...
- javascript php 性能,浅谈页面装载js及性能分析方法_javascript技巧
- EasyExcel简单使用
- 【数据库基础知识】plsql安装及配置
- C# 中关闭当前线程的四种方式 .
- 4. CSS id 选择器
- java毕业设计_基于ssm的毕业设计管理系统
- neo4j各个版本下载
- 【python】蔡勒公式计算日期
- matlab和r语言做热图,R语言画图与MATLAB画图PK
- 上海庆科EMW3162 WiFi模块 串口透传
- Java递归查询某个节点下所有子节点多级信息(递归部门查询,递归树形结构数据查询)
- 内部类和匿名类的介绍