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文件解析过程详解(三)相关推荐

  1. 安卓 linux init.rc,[原创]Android init.rc文件解析过程详解(二)

    Android init.rc文件解析过程详解(二) 3.parse_new_section代码如下: void parse_new_section(struct parse_state *state ...

  2. Android init.rc文件解析过程详解(二)

    Android init.rc文件解析过程详解(二) 3.parse_new_section代码如下: void parse_new_section(struct parse_state *state ...

  3. Android init.rc文件解析过程详解(一)

        Android init.rc文件解析过程详解(一) 一.init.rc文件结构介绍 init.rc文件基本组成单位是section, section分为三种类型,分别由三个关键字(所谓关键字 ...

  4. Android init.rc文件格式解析

    /****************************************************************************** Android init.rc文件格式解 ...

  5. 加载vue文件步骤_vue中.vue文件解析步骤详解

    这次给大家带来vue中.vue文件解析步骤详解,vue中.vue文件解析的注意事项有哪些,下面就是实战案例,一起来看一下. 我们平时写的 .vue 文件称为 SFC(Single File Compo ...

  6. php android 图片上传,android上传图片到PHP的过程详解

    这篇文章主要介绍了android上传图片到PHP的过程详解,需要的朋友可以参考下 今天在做上传头像的时候,总是提交连接超时错误,报错信息如下:XXXXXXSokcetTimeOutXXXXXXXX 然 ...

  7. Android签名机制之---签名验证过程详解

    一.前言 今天是元旦,也是Single Dog的嚎叫之日,只能写博客来祛除寂寞了,今天我们继续来看一下Android中的签名机制的姊妹篇:Android中是如何验证一个Apk的签名.在前一篇文章中我们 ...

  8. Android之手机文件夹目录详解

    android系统的手机文件夹目录详解 一.文件夹 1./acct/    系统回收站,删除的系统文件. 2./cache/    缓存 3./data/    用户的所有程序相关数据 app/    ...

  9. Android 系统服务管家servicemanager启动过程详解

    Android考虑到移动设备耗电以及跨进程通信效率等因素,基于OpenBinder专门为进程通信开发了一套框架:binder.例如,客户端程序需要获取WindowManager,TelephonyMa ...

最新文章

  1. Ubuntu14.04 64位上配置终端显示git分支名称
  2. U.S.News最新美国大学排名:普林斯顿蝉联总榜第一,MIT领跑计算机,弗罗里达成新贵...
  3. linux 系统监控 php,Linux系统资源监控命令简介
  4. 江苏省2013年会计从业资格考试《会计基础》全真模拟试题
  5. 解决AJAX表单用POST方式提交Checkbox复选框的问题
  6. 《Windows核心编程》---Interlocked原子访问系列函数
  7. python 识别数字字母 训练集_Python 实现训练集、测试集随机划分
  8. c++分治法求最大最小值实现_程序员:算法导论,分治法、归并排序,伪代码和Java实现...
  9. javascript php 性能,浅谈页面装载js及性能分析方法_javascript技巧
  10. EasyExcel简单使用
  11. 【数据库基础知识】plsql安装及配置
  12. C# 中关闭当前线程的四种方式 .
  13. 4. CSS id 选择器
  14. java毕业设计_基于ssm的毕业设计管理系统
  15. neo4j各个版本下载
  16. 【python】蔡勒公式计算日期
  17. matlab和r语言做热图,R语言画图与MATLAB画图PK
  18. 上海庆科EMW3162 WiFi模块 串口透传
  19. Java递归查询某个节点下所有子节点多级信息(递归部门查询,递归树形结构数据查询)
  20. 内部类和匿名类的介绍

热门文章

  1. 数据结构应用实例#栈#迷宫寻路
  2. 原 iOS面试题收集
  3. 毕业设计《MMORPG DEMO》——1
  4. UA MATH563 概率论的数学基础 中心极限定理17 0-1律的应用
  5. UA MATH571A 检验异方差的非参数回归方法
  6. Windows驱动开发 - 设备对象初步学习
  7. Eclipse开发Spring MVC入门示例
  8. 设计模式学习---策略模式
  9. SSH远程联机Linux服务器简易安全设定
  10. Java虚拟机5:常用JVM命令参数