編輯:關於Android編程
init進程是android啟動的第一個進程 進程pid為1.其主要做了如下幾件事:
*解析配置文件
*根據配置文件執行操作early_init init early_boot boot
*設置屬性服務

本節主要內容講解如何解析init.rc文件和運行zygote.
1.解析init.rc配置文件
/**init.c*/
在main函數中,執行如下函數:
init_parse_config_file("/init.rc");/**init_parse.c*/int init_parse_config_file(const char *fn)
{
char *data;
data = read_file(fn, 0);
if (!data) return -1;
parse_config(fn, data);
DUMP();
return 0;
}
static void parse_config(const char *fn, char *s);
parse_config函數主要找到一個SECTION的節點開始解析
if (kw_is(kw, SECTION)) {
state.parse_line(&state, 0, 0);
parse_new_section(&state, kw, nargs, args);
}
kw_is函數執行了keywords文件 並找處指定標示 k_##symbol
/**keywords.h*/
1>定義枚舉.枚舉值為k_class k_mkdir等export ANDROID_ROOT /system #表示export為一個COMMAND
*如下圖

/**init.rc配置文件*/
在該文件中 zygote被定義為需要執行4個操作並且擁有一個socket為660的服務,他是init的一個子進程.<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjxicj4KPC9wPgo8cHJlIGNsYXNzPQ=="brush:java;">service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd ------------------------------------------------ >>設置service的啟動時間 pid等等 restart_processes();//改變flag標識
---------------Service定義信息------------------
-維護所有生成Service的一個雙向鏈表listnode
-service的name zygote的name為init.svc.zygote
-className 默認"default"
-屬性flag pid uid gid io優先級 參數(個數)
-time_started time_crashed nr_crashed 上次啟動死亡時 總死亡次數
-socketinfo(socket環境變量信息) svcenvinfo(進程所需環境變量信息)
-struct action onrestart; 保存OPTION後面的COMMAND信息
------------------------------------------------
---------------onrestart定義信息------------------
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;
struct command *current;//保存restart裡面的COMMOND動作
};
#主要執行parse_service 和parse_line_service
//創建service結構體主要框架,並添加到service_list雙向鏈表中
//socketinfo是一個單向鏈表 zygote只有一個660 的TCP scoket
//onrestart通過commond指向一個commonds鏈表 zygote如上在init.rc中可以看出有4個commond
static void *parse_service(struct parse_state *state, int nargs, char **args)
{
struct service *svc;
svc = calloc(1, sizeof(*svc) + sizeof(char*) * nargs);
if (!svc) {
parse_error(state, "out of memory\n");
return 0;
}
svc->name = args[1];
svc->classname = "default";
memcpy(svc->args, args + 2, sizeof(char*) * nargs);
svc->args[nargs] = 0;
svc->nargs = nargs;
svc->onrestart.name = "onrestart";
list_init(&svc->onrestart.commands);
list_add_tail(&service_list, &svc->slist);
return svc;
}
static void parse_line_service(struct parse_state *state, int nargs, char **args)
{
struct service *svc = state->context;
nargs--;
args++;
kw = lookup_keyword(args[0]);
//創建Commond結構體
cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);
cmd->func = kw_func(kw);
cmd->nargs = nargs;
memcpy(cmd->args, args, sizeof(char*) * nargs);
//添加到雙向列表中
list_add_tail(&svc->onrestart.commands, &cmd->clist);
}
**********init 啟動zygote**********
1)init.c::main>
// 將boot的commond加入到執行隊列中 因為zygote 包含在boot動作中
action_for_each_trigger("boot", action_add_queue_tail);
//執行隊列中的commond 並統一執行所有section的commond
queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
2)Bultins.c::do_class_start>
//因為class_start是一個COMMOND所以他會被執行 在這裡zygote是一個 "default"的className
//所以執行service_start_if_not_disabled函數
//如果service的flag被明確規定為disable 那麼執行該service必須單獨再執行
service_for_each_class(args[1],service_start_if_not_disabled);
3)Bultins.c::service_start_if_not_disabled>
if (!(svc->flags & SVC_DISABLED)) {
service_start(svc, NULL);//之前設置沒有創建flags 表示該service還未啟用 執行service_start
}
4)init.c::service_start>
>>判斷文件進程/system/bin/process文件是否存在 一般service有自己的進程
rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon);
>>啟動init子進程
pid = fork();
>>添加進程環境變量信息
>>添加socket環境變量信息並創建socket
>>設置uid gid並啟動/system/bin/app_process文件的main函數
>>綁定操作 響應事件
1)init.c::main>>
queue_builtin_action(signal_init_action, "signal_init");
2)init.c::signal_init_action>>
signal_init();
3)signal_handler::signal_init>>
struct sigaction act;//綁定2個方法 sigchld_handler handle_signal 其結構體還包括了一個sa_flags標示
>>zygote死後父進程init調用sigchld_handler
1)signal_handler::sigchld_handler>>
write(signal_fd, &s, 1);//往signal_fd中寫數據 signal_fd是socketpair中兩條socket中的一條
2)init.c::main>>
nr = poll(ufds, fd_count, timeout);
if (nr <= 0)
continue;
for (i = 0; i < fd_count; i++) {
if (ufds[i].revents == POLLIN) {
else if (ufds[i].fd == get_signal_fd())
handle_signal();
}
}
3)signal_handler::handle_signal>>
read(signal_recv_fd, tmp, sizeof(tmp));
while (!wait_for_one_process(0)) ;
4)signal_handler::wait_for_one_process>>
//殺掉zygote的所有子進程
//清除我們將要重建的scoket
//將所有onrestart的commond(zygote中有4個)添加到svc中的action結構體列表中
//改變svc狀態為restarting
5)init.c::main>>
//poll後進入下一輪循環 又執行main
execute_one_command();//執行所有COMMOND
Android 多分辨率自適應總結
這周的工作對Android項目多分辨率自適應進行調整。故對這方面知識進行不斷的嘗試學習。Android項目剛開始做的時候一定養成編程習慣,所有資源調用放在value中。統
Android5.x Notification應用解析
Notification可以讓我們在獲得消息的時候,在狀態欄,鎖屏界面來顯示相應的信息,很難想象如果沒有Notification,那我們的qq和微信以及其他應用沒法主動通
安卓可滑動的自定義日歷控件的實現
最近用到的一個日歷控件,記錄下來造福人類, 效果如圖 布局文件
總結Android中MD風格相關控件
要使用MD風格控件,首先需要在Gradle中加入Support Design Library,例如:compile com.android.support:design: