您的位置:首页 > 移动开发 > Android开发

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

2015-10-19 18:09 686 查看
本文转载自

http://blog.itpub.net/7232789/viewspace-758168/

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结构体来表示。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: