編輯:關於Android編程
rc文件是linux中常見的啟動加載階段執行的文件,rc是run commands的縮寫,基本上可以理解為在啟動階段執行的一些列命令。android init進程啟動時,也會執行此啟動腳本文件,init.rc。init.rc的寫法稍有點復雜,詳細可參考 /system/core/init下的readme文件。腳本基本組成是由四類,為:
commands: 命令action: 動作services: 服務options: 選項該語言的語法包括下列約定:
所有類型的語句都是基於行(line-oriented)的,一個語句包含若干個tokens,token之間通過空格字符分隔。如果一個token中需要包含空格字符,則需要通過C語言風格的反斜線('')來轉義,或者使用雙引號把整個token引起來。反斜線還可以出現在一行的末尾,表示下一行的內容仍然屬於當前語句。以'#'開始的行是注釋行(注釋只能是行的第一個非空字符,這個千萬要注意)。動作(Actions)和服務(Services)語句隱含表示一個新的段落(section)的開始。所有的指令(commands)和選項(options)歸屬於上方最近的一個段落。在第一個段落之前的指令(commands)和選項(options)是無效的。動作(Actions)和服務(Services)擁有唯一性的名字。如果出現重名,那麼後出現的定義將被作為錯誤忽略掉【目前還是忽略,不是覆蓋!】。其實,嚴格來說,應該就只有兩種類別Action和Service:
Action是由特定trigger下的一堆command組成 Service是由一堆options描述的daemon服務組成動作(Action)
動作(Action)是一個有名字的指令(commands)序列。每個動作(Action)都定義一個觸發條件(trigger),用於指示什麼時候執行這個動作。在實際處理中,當與動作的觸發器匹配的事件發生時,該動作下的命令,將被添加到一個即將被執行的隊列的隊尾(除非它已經在隊列中)。
隊列中的每一個命令被依次取出執行。
一個動作定義的形式如下:
on
服務(Services)
服務是初始化程序需要啟動的一些程序,初始化程序還有可能會在這些程序退出之後重啟它們。Services take一個服務定義的形式如下:
service[ ]*
選項(Options)
選項將影響控制初始化程序運行服務的時機和方法。可能的選項如下表(注意,options只是作為服務的附屬部分的)..
說明:
disabled
服務在啟動所屬的class的時候,不會自動隨之啟動,只有明確指明要啟動此服務時才會啟動(通常每個服務都會屬於一個class中,由class關鍵字描述)
socket
Create a unix domain socket named/dev/socket/
user
在exec啟動此服務之前,改變進程的user,默認user是root
group
周期exec啟動服務之前,改變此服務進程的group. 默認group是root。將服務加入特定的group,可以獲取一些特定的權限。
capability [
Set linux capability before exec'ing this service
oneshot
服務只執行一次。對於非daemon程序,必須要使用onshot模式。
class
設定服務的class名字,所有的服務都必須設置一個,如果不設置,默認是屬於default class的。同一個class中的服務,可以通過命令class_start統一啟動。
觸發器(Triggers)
觸發器是一個字符串,用於匹配特定的事件,這些事件將觸發觸發器所屬動作(Action)的執行。
指令(Commands)
支持哪些指令,各個android版本不盡相同,詳情可參考/system/core/init下的readme或最好看代碼
屬性(Properties)
初始化程序(Init)可以根據需要修改一些系統的屬性。readme中說的三個:
init.action
Equal to the name of the action currently being executed or if none.
init.command
Equal to the command being executed or if none.
init.svc.
State of a named service (stopped, running, or restarting).
實際init進程只看到更新 init.svc.
void notify_service_state(const char *name, const char *state) { char pname[PROP_NAME_MAX]; int len = strlen(name); if ((len + 10) > PROP_NAME_MAX) return; snprintf(pname, sizeof(pname), init.svc.%s, name); property_set(pname, state); }
其他兩個沒意義,實際也沒用,可能當初設計有吧,但最後也沒用(comman/action都是開機時執行,且持續時間都很短,沒太大用處)。
Init的parser是比較簡單的自動機,代碼也不算復雜,主要parser的是三部分:
service: 每個service的描述及屬性,parser好了,放在service_list中,以便以後通過actions的命令啟動。actions: parser每個動作, on XXX及後繼的command,就是一個action,這個parser好後,也是放在action_list中,以便在init中啟動。import: init.rc 可以支持像c中的include一樣,包含其他init.rc,這個支持比較簡單,並不是相當於在import位置插入被import的代碼,而是在主init.rc都parser好後,再依次parser被包含的rc文件。
腳本解析好後,會將各個Actions按照時間順序,分別推到action_queue中,再一個一個執行。
actions按照trigger的時間順序,依次執行的是,默認trigger的順序如下:
action_for_each_trigger(early-init, action_add_queue_tail); action_for_each_trigger(init, action_add_queue_tail); action_for_each_trigger(early-fs, action_add_queue_tail); action_for_each_trigger(fs, action_add_queue_tail); action_for_each_trigger(post-fs, action_add_queue_tail); action_for_each_trigger(post-fs-data, action_add_queue_tail); action_for_each_trigger(early-boot, action_add_queue_tail); action_for_each_trigger(boot, action_add_queue_tail);
因此,各個命令需要特別注意處理好依賴。比如在init階段,是不可能訪問data分區的。另外還要注意一下, 同一個階段中,import的rc文件,是在後面一些執行的(根據import文件的parser順序)。
service的啟動時間,需要注意一下,也是通過action中的command執行的, 比如在on boot階段:
on boot ... class_start core
這樣,在boot階段執行到這個命令時,所有屬於core這一類的服務,都會被逐個啟動。
?
?? ?? ??
前幾天去參加了帶著自己的作品去參加服務外包大賽,因為簽位抽到的比較靠後就等待了蠻久,就跟坐在前面的一起參賽的選手開始討論Android的開發經驗,各自給對方展示了自己的作
在Android中,數據的存儲分為兩種方式:1、直接以文件的形式存儲在目錄中2、以json格式存儲在數據庫中將數據以文件的存儲又分為兩種方式:1、生成.txt文件2、生成
Android Studio 1.0 已經放出來了,以後的Android平台開發激昂逐步從Eclipse向Android Studio遷移,為了能不落伍我也特意從Goog
介紹A toast provides simple feedback about an operation in a small popup. It only fills