日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

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

發布時間:2025/4/5 Android 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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()函數

01int?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文件解析过程详解(三)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。