Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android-init進程(1)

Android-init進程(1)

編輯:關於Android編程

init進程是android啟動的第一個進程 進程pid為1.其主要做了如下幾件事:

*解析配置文件

*根據配置文件執行操作early_init init early_boot boot

*設置屬性服務

init主要內容

本節主要內容講解如何解析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等
2>定義結構體數組keyword_info,把KEYOWRD宏改變成結構體,通過宏定義找出symbol與func解析init.rc文件
如關鍵字section的symbol為chdir 則找到如int do_chdir(int nargs, char **args)的聲明查看對應定義
>>>關鍵字有:OPTION,COMMAND,SECTION
/**init.rc*/
on init #表示on的SECTION名稱為init 基本步驟為early-init init early-boot boot
#從一個section開始 到下一個section開始標簽前結束

export ANDROID_ROOT /system #表示export為一個COMMAND

*如下圖

\



2.分析zygote

/**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定義信息------------------
-維護所有生成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動作
};

------------------------------------------------


/**init_parse.c*/
#主要執行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函數

>>設置service的啟動時間 pid等等


**********init 重啟zygote**********
>>綁定操作 響應事件
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

restart_processes();//改變flag標識


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved