<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國際加速解決方案。 廣告
                根據上面的代碼可知,在init中會解析兩個配置文件,其中一個是系統配置文件init.rc,另外一個是和硬件平臺相關的配置文件。以HTC G7手機為例,這個配置文件名為init.bravo.rc,其中bravo是硬件平臺的名稱。對這兩個配置文件進行解析,調用的是同一個parse_config_file函數。下面就來看這個函數,在分析過程中以init.rc為主。 **parser.c** ~~~ int parse_config_file(const char *fn) { char *data; data = read_file(fn, 0);//讀取配置文件的內容,這個文件是init.rc。 if (!data) return -1; parse_config(fn,data); //調用parse_config做真正的解析 return 0; } ~~~ 讀取完文件的內容后,將調用parse_config進行解析,這個函數的代碼如下所示: **parser.c** ~~~ static void parse_config(const char *fn, char*s) { struct parse_state state; char *args[SVC_MAXARGS]; int nargs; nargs = 0; state.filename = fn; state.line = 1; state.ptr = s; state.nexttoken = 0; state.parse_line = parse_line_no_op; //設置解析函數,不同的內容用不同的解析函數 for (;;) { switch(next_token(&state)) { case T_EOF: state.parse_line(&state, 0, 0); return; caseT_NEWLINE: if (nargs) { //得到關鍵字的類型 int kw = lookup_keyword(args[0]); if (kw_is(kw, SECTION)) { //判斷關鍵字類型是不是SECTION。 state.parse_line(&state,0, 0); parse_new_section(&state,kw, nargs, args);//解析這個SECTION。 } else { state.parse_line(&state, nargs, args); } nargs = 0; } break; case T_TEXT: ...... break; } } } ~~~ 上面就是parse_config函數,代碼雖短,實際卻比較復雜。從整體來說,parse_config首先會找到配置文件的一個section,然后針對不同的 section使用不同的解析函數來解析。那么,什么是section呢?這和init.rc文件的組織結構有關。先不必急著去看init.rc,還是先到代碼中去尋找答案。 1. 關鍵字定義 keywords.h這個文件定義了init中使用的關鍵字,它的用法很有意思,先來看這個文件,代碼如下所示: **keywords.h** ~~~ #ifndef KEYWORD //如果沒有定義KEYWORD宏,則走下面的分支 ......//聲明一些函數,這些函數就是前面所說Action的執行函數。 int do_class_start(int nargs, char **args); int do_class_stop(int nargs, char **args); ...... int do_restart(int nargs, char **args); ...... #define __MAKE_KEYWORD_ENUM__ //定義一個宏 /* 定義KEYWORD宏,雖然有四個參數,不過這里只用第一個,其中K_##symbol中的##表示連接 的意思,即最后得到的值為K_symbol。symbol其實就是init.rc中的關鍵字 */ #define KEYWORD(symbol, flags, nargs, func)K_##symbol, enum { //定義一個枚舉,這個枚舉定義了各個關鍵字的枚舉值。 K_UNKNOWN, #endif ...... //根據上面KEYWORD的定義,這里將得到一個枚舉值K_class, KEYWORD(class, OPTION, 0, 0) KEYWORD(class_start, COMMAND, 1, do_class_start)//K_class_start, KEYWORD(class_stop, COMMAND, 1, do_class_stop)//K_class_stop, KEYWORD(on, SECTION, 0, 0)//K_on, KEYWORD(oneshot, OPTION, 0, 0) KEYWORD(onrestart, OPTION, 0, 0) KEYWORD(restart, COMMAND, 1,do_restart) KEYWORD(service, SECTION, 0,0) ...... KEYWORD(socket, OPTION, 0, 0) KEYWORD(start, COMMAND, 1,do_start) KEYWORD(stop, COMMAND, 1,do_stop) ...... #ifdef __MAKE_KEYWORD_ENUM__ KEYWORD_COUNT, }; #undef __MAKE_KEYWORD_ENUM__ #undef KEYWORD //取消KEYWORD宏定義 #endif ~~~ keywords.h好像沒什么奇特,不過是個簡單的頭文件。為什么說它的用法很有意思呢?來看代碼中是如何使用它的,如下所示: **parser.c** ~~~ ......//parser.c中將包含keywords.h頭文件,而且還不只一次!! //第一次包含keywords.h,根據keywords.h的代碼,我們首先會得到一個枚舉定義 #include "keywords.h" /* 重新定義KEYWORD宏,這回四個參數全用上了,看起來好像是一個結構體。其中#symbol表示 一個字符串,其值為“symbol”。 */ #define KEYWORD(symbol, flags, nargs, func) \ [K_##symbol ] = { #symbol, func, nargs + 1, flags, }, //定義一個結構體keyword_info數組,它用來描述關鍵字的一些屬性,請注意里面的注釋內容。 struct { constchar *name; //關鍵字的名。 int(*func)(int nargs, char **args);//對應關鍵字的處理函數。 unsignedchar nargs;//參數個數,每個關鍵字的參數個數是固定的。 //關鍵字的屬性,有三種屬性,COMMAND、OPTION和SECTION。其中COMMAND有對應的處理函數 unsigned char flags; } keyword_info[KEYWORD_COUNT] = { [ K_UNKNOWN ] = { "unknown", 0, 0, 0}, /* 第二次包含keywords.h,由于已經重新定了KEYWORD宏,所以以前那些作為枚舉值的關鍵字 現在變成keyword_info數組的索引了。 */ #include "keywords.h" }; #undef KEYWORD //一些輔助宏,幫助我們快速操作keyword_info中的內容。 #define kw_is(kw, type) (keyword_info[kw].flags& (type)) #define kw_name(kw) (keyword_info[kw].name) #define kw_func(kw) (keyword_info[kw].func) #define kw_nargs(kw) (keyword_info[kw].nargs) ~~~ 現在領略了keywords.h的神奇之處了吧?原來它干了兩件事情: - 第一次包含keyworks.h時,它聲明了一些諸如do_classstart這樣的函數,另外還定義了一個枚舉,枚舉值為K_class,K_mkdir等關鍵字。 - 第二次包含keywords.h后,得到了一個keyword_info結構體數組,這個keyword_info結構體數組以前面定義的枚舉值為索引,存儲對應的關鍵字信息,這些信息包括關鍵字名、處理函數、處理函數的參數個數,以及屬性。 目前,關鍵字信息中最重要的就是symbol和flags了。什么樣的關鍵字被認為是section呢?根據keywords.h的定義,symbol為下面兩個的關鍵字表示section: ~~~ KEYWORD(on, SECTION, 0, 0) KEYWORD(service, SECTION, 0, 0) ~~~ 有了上面的知識,再來看配置文件init.rc的內容。 2. init.rc的解析 init.rc的內容如下所示:(我們截取了部分內容,注意,其中的注釋符號是#。) **init.rc** ~~~ on init #根據上面的分析,on關鍵字標示一個section,對應的名字是”init” ...... #下面所有的內容都屬于這個section,直到下一個section開始時。 exportPATH /sbin:/system/sbin:/system/bin:/system/xbin exportLD_LIBRARY_PATH /system/lib exportANDROID_BOOTLOGO 1 #根據keywords.h的定義,export表示一個COMMAND export ANDROID_ROOT /system exportANDROID_ASSETS /system/app ...... #省略部分內容 on boot #這是一個新的section,名為”boot” ifup lo#這是一個COMMAND hostname localhost domainname localdomain ...... #class_start也是一個COMMAND,對應函數為do_class_start,很重要,切記。 class_startdefault ...... #下面這個section的意思是:待屬性persist.service.adb.enable的值變為1后, #需要執行對應的COMMAND,這個COMMAND是start adbd onproperty:persist.service.adb.enable=1 start adbd //start是一個COMMAND on property:persist.service.adb.enable=0 stopadbd ...... #service也是section的標示,對應section的名為“zygote“ service zygote /system/bin/app_process -Xzygote/system/bin –zygote \ --start-system-server socketzygote stream 666 #socket關鍵字表示OPTION onrestart write /sys/android_power/request_state wake #onrestart也是OPTION onrestart write /sys/power/state on onrestart restart media #一個section,名為”media” service media /system/bin/mediaserver usermedia groupsystem audio camera graphics inet net_bt net_bt_admin net_raw iopriort 4 ~~~ 從上面對init.rc的分析中可知: - 一個section的內容從這個標示section的關鍵字開始,到下一個標示section的地方結束。 - init.rc中出現了名為boot和init的section,這里的boot和init,就是前面介紹的動作執行四個階段中的boot和init。也就是說,在boot階段執行的動作都是由boot這個section定義的。 另外還可發現,zygote被放在了一個servicesection中。下面以zygote這個section為例,介紹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>

                              哎呀哎呀视频在线观看