1.引言
深入理解Android 卷1.第三章講解了Android系統(tǒng)的init過程绳军。我在學(xué)習(xí)這章的時(shí)候前前后后看了4遍。也看了很多很多博客。最后慢慢慢慢的理解了一點(diǎn),當(dāng)然對(duì)細(xì)節(jié)性代碼還是不懂扇单。只知道一個(gè)大概的流程。現(xiàn)在記錄下整個(gè)init過程奠旺。
2正題
2.1 init.rc 文件的介紹
init.rc很重要一定要搞懂蜘澜。詳細(xì)文章請(qǐng)參見這個(gè)大佬的http://www.reibang.com/p/d08e1affd5ec。
Action的格式如下:
on <trgger> [&& <trigger>]*
<command>
<command>
<command>
...
on 關(guān)鍵字 后面加觸發(fā)器响疚。中間的都是command命令:
init.rc 的部分文件鄙信。init.rc文件很有順序的:按照section執(zhí)行到先后順序排布的。其中重要的步驟是:
on-early init
on init
on late-init
on boot
為什么會(huì)提到這些稽寒。因?yàn)樵趇nit.cpp中會(huì)對(duì)這四個(gè)步驟扮碧。調(diào)用代碼進(jìn)行執(zhí)行。
2.2 解析init.rc的過程
init_parser.cpp文件:
當(dāng)遇到section的時(shí)候就會(huì)走case T_NEWLINE杏糙。 進(jìn)而執(zhí)行到parse_new_section();
parse_new_section()
我們來看下解析case k_on的情況:
分析parse_line_action
list_add_tail 是一個(gè)雙向鏈表慎王。都command都添加到list的尾部(tail)。之后依次執(zhí)行
on early-init ,init,late-init,boot宏侍,調(diào)用代碼 如下所示:
總結(jié)init.rc過程:
通過parse_new_section ->parse_line_action 最終將command都添加進(jìn)雙向列表赖淤。然后在init.cpp中依次執(zhí)行 以下section中的caommand 。
on early-init
init
late-init
boot
現(xiàn)在有一個(gè)問題:command是怎么去執(zhí)行的谅河?
答案: 每個(gè)command 都對(duì)應(yīng)一個(gè) 執(zhí)行函數(shù)咱旱。這樣知道了command 就了執(zhí)行函數(shù)。這個(gè)執(zhí)行函數(shù)在keywords.cpp 里面绷耍。
3.啟動(dòng)zygote線程
在on boot section 下面有一個(gè) class_start core 的命令吐限。根據(jù)keywords class_start 對(duì)應(yīng)的函數(shù)就是do_class_start().
service_start_if_not_disabled() 方法:
這個(gè)service_start() 是在 init.cpp中的。這個(gè)方法通過條用 fork()方法 產(chǎn)生zygote方法褂始。
4 屬性服務(wù)器工作流程
屬性服務(wù)器也不是特別了解诸典,我就按照書上,博客上走一遍流程崎苗,加深影響狐粱。Android 6.0 和4.4的 代碼差別存在。好多4.4上提供的代碼參考胆数,6.0上都沒得肌蜻。
屬性服務(wù)就像window的注冊(cè)表采用key-value的形式保存數(shù)據(jù)。所以萬變不離其宗必尼,跟蹤代碼總會(huì)發(fā)現(xiàn)set(key,value)的字樣蒋搜。
按照init.cpp中對(duì)property_service流程進(jìn)行分析:
property_init() ----->start_property_service
property_init():
初始化屬性服務(wù),主要是初始化內(nèi)存區(qū)域,并且該內(nèi)存區(qū)域是內(nèi)存共享的豆挽。想來也對(duì)酸休,就像在Android中使用sh,肯定要?jiǎng)?chuàng)建一塊內(nèi)存區(qū)域祷杈,不然怎么去保存數(shù)據(jù)呢斑司?
start_property_service
create_socket創(chuàng)建了一個(gè)專門用來接收請(qǐng)求的socket。很顯然但汞,其他進(jìn)程是能通過ipc 與此socket進(jìn)行通信的宿刮。
該方法目的就是將handler_property_set_fd 與socket綁定起來。register_epoll_handler的方法在init.cpp
私蕾。
這樣當(dāng)socket接受到一個(gè)請(qǐng)求,handle_property_set_fd就負(fù)責(zé)處理請(qǐng)求:
handle_property_set_fd:找到這段代碼
property_set(key,value)最終調(diào)用 的是:
注意是property_service中的 property_set()方法僵缺。
property_set_iml(name,value)就是對(duì)文件中的key.value進(jìn)行保存。
總結(jié):上述 屬性服務(wù)器算是啟動(dòng)完畢踩叭,工作流程如上所示磕潮。那么問題來了客戶端是怎么調(diào)用呢?
4.1 客戶端與屬性服務(wù)器通信
客戶端與服務(wù)器進(jìn)行交互是通過調(diào)用如下代碼:
_system_property_set(key,value) 代碼:
通過socket與屬性服務(wù)器接受的socket進(jìn)行連接容贝,發(fā)送消息自脯,接受端的socket收到之后就會(huì)執(zhí)行handler_proerty_set_fd().然后寫入到文件中。