<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                zygote對應的service section內容是: **init.rc::zygote** ~~~ service zygote /system/bin/app_process -Xzygote/system/bin –zygote \ --start-system-server socketzygote stream 666 #socket是OPTION #下面的onrestart是OPTION,而write和restart是COMMAND onrestartwrite /sys/android_power/request_state wake onrestart write /sys/power/state on onrestartrestart media ~~~ 解析section的入口函數是parse_new_section,它的代碼如下所示: **parser.c** ~~~ void parse_new_section(struct parse_state*state, int kw, int nargs, char **args) { switch(kw) { caseK_service: //解析service,用parse_service和parse_line_service state->context = parse_service(state, nargs, args); if(state->context) { state->parse_line = parse_line_service; return; } break; caseK_on: //解析on section ......//讀者可以自己研究 break; } state->parse_line = parse_line_no_op; } ~~~ 其中,service解析時,用到了parse_service和parse_line_service兩個函數,在分別介紹它們之前,先看init是如何組織這個service的。 1. service結構體 init中使用了一個叫service的結構體來保存和service section相關的信息,不妨來看這個結構體,代碼如下所示: **init.h::service結構體定義** ~~~ struct service { //listnode是一個特殊的結構體,在內核代碼中用得非常多,主要用來將結構體鏈接成一個 //雙向鏈表。init中有一個全局的service_list,專門用來保存解析配置文件后得到的service。 struct listnode slist; constchar *name; //service的名字,對應我們這個例子就是”zygote”。 constchar *classname; //service所屬class的名字,默認是”defult” unsigned flags;//service的屬性 pid_tpid; //進程號 time_ttime_started; //上一次啟動的時間 time_ttime_crashed; //上一次死亡的時間 intnr_crashed; //死亡次數 uid_tuid; //uid,gid相關 gid_tgid; gid_tsupp_gids[NR_SVC_SUPP_GIDS]; size_tnr_supp_gids; /* 有些service需要使用socket,下面這個socketinfo用來描述socket的相關信息。 我們的zygote也使用了socket,配置文件中的內容是socket zygote stream 666。 它表示將創建一個AF_STREAM類型的socket(其實就是TCP socket),該socket的名為“zygote”, 讀寫權限是666。 */ structsocketinfo *sockets; //service一般運行在單獨的一個進程中,envvars用來描述創建這個進程時所需的環境變量信息。 structsvcenvinfo *envvars; /* 雖然關鍵字onrestart標示一個OPTION,可是這個OPTION后面一般跟著COMMAND, 下面這個action結構體可用來存儲command信息,馬上就會分析到它。 */ structaction onrestart; //和keychord相關的內容 int*keycodes; intnkeycodes; intkeychord_id; //io優先級設置 intioprio_class; intioprio_pri; //參數個數 intnargs; //用于存儲參數 char*args[1]; }; ~~~ 我們現在已了解的service的結構體,相對來說還算是清晰易懂的。而zygote中的那三個onrestart該怎么表示呢?請看service中使用的這個action結構體: **init.h::action結構體定義** ~~~ struct action { /* 一個action結構體可存放在三個雙向鏈表中,其中alist用于存儲所有action, qlist用于鏈接那些等待執行的action,tlist用于鏈接那些待某些條件滿足后 就需要執行的action。 */ structlistnode alist; structlistnode qlist; structlistnode tlist; unsigned hash; constchar *name; //這個OPTION對應的COMMAND鏈表,以zygote為例,它有三個onrestart option,所以 //它對應會創建三個command結構體。 structlistnode commands; structcommand *current; }; ~~~ 了解了上面的知識后,你是否能猜到parse_service和parse_line_service的作用了呢?馬上就來看它們。 2. parse_service parse_service的代碼如下所示: **parser.c** ~~~ static void *parse_service(struct parse_state*state, int nargs, char **args) { structservice *svc; //聲明一個service結構體 ...... //init維護了一個全局的service鏈表,先判斷是否已經有同名的service了。 svc =service_find_by_name(args[1]); if(svc) { ...... //如果有同名的service,則不能繼續后面的操作。 return 0; } nargs-= 2; svc =calloc(1, sizeof(*svc) + sizeof(char*) * nargs); ...... svc->name = args[1]; svc->classname= "default";//設置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); //把zygote這個service加到全局鏈表service_list中。 list_add_tail(&service_list, &svc->slist); returnsvc; } ~~~ parse_service函數只是搭建了一個service的架子,具體的內容尚需由后面的解析函數來填充。來看service的另外一個解析函數parse_line_service。 3. parse_line_service parse_line_service的代碼如下所示: **parser.c** ~~~ static void parse_line_service(structparse_state *state, int nargs, char **args) { structservice *svc = state->context; structcommand *cmd; int i,kw, kw_nargs; ...... svc->ioprio_class = IoSchedClass_NONE; //其實還是根據關鍵字來做各種處理。 kw =lookup_keyword(args[0]); switch(kw) { caseK_capability: break; caseK_class: if(nargs != 2) { ...... }else { svc->classname = args[1]; } break; ...... caseK_oneshot: /* 這是service的屬性,它一共有五個屬性,分別為: SVC_DISABLED:不隨class自動啟動。下面將會看到class的作用。 SVC_ONESHOT:退出后不需要重啟,也就是這個service只啟動一次就可以了。 SVC_RUNNING:正在運行,這是service的狀態。 SVC_RESTARTING:等待重啟,這也是service的狀態。 SVC_CONSOLE:該service需要使用控制臺 。 SVC_CRITICAL:如果在規定時間內該service不斷重啟,則系統會重啟并進入恢復模式。 zygote沒有使用任何屬性,這表明它:會隨著class的處理自動啟動; 退出后會由init重啟;不使用控制臺;即使不斷重啟也不會導致系統進入恢復模式。 */ svc->flags |= SVC_ONESHOT; break; caseK_onrestart: //根據onrestart的內容,填充action結構體的內容 nargs--; args++; kw= lookup_keyword(args[0]); ...... //創建command結構體 cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs); cmd->func = kw_func(kw); cmd->nargs = nargs; memcpy(cmd->args, args, sizeof(char*) * nargs); //把新建的command加入到雙向鏈表中。 list_add_tail(&svc->onrestart.commands, &cmd->clist); break; ...... caseK_socket: { //創建socket相關信息 struct socketinfo *si; ...... si= calloc(1, sizeof(*si)); if(!si) { parse_error(state, "out of memory\n"); break; } si->name = args[1]; //socket的名字 si->type = args[2]; //socket的類型 si->perm = strtoul(args[3], 0, 8); //socket的讀寫權限 if(nargs > 4) si->uid = decode_uid(args[4]); if(nargs > 5) si->gid = decode_uid(args[5]); si->next = svc->sockets; svc->sockets = si; break; } ...... default: parse_error(state, "invalid option '%s'\n", args[0]); } } ~~~ parse_line_service將根據配置文件的內容填充service結構體,那么,zygote解析完后會得到什么呢?圖3-1表示了zygote解析后的結果: :-: ![](http://img.blog.csdn.net/20150802095010545?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖3-1 zygote解析結果示意圖 從上圖中可知: - service_list鏈表將解析后的service全部鏈接到了一起,并且是一個雙向鏈表,前向節點用prev表示,后向節點用next表示。 - socketinfo也是一個雙向鏈表,因為zygote只有一個socket,所以畫了一個虛框socket做為鏈表的示范。 - onrestart通過commands指向一個commands鏈表,zygote有三個commands。 zygote這個service解析完了,現在就是“萬事俱備,只欠東風”了。接下來要了解的是,init是如何控制service的。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看