日本免费全黄少妇一区二区三区-高清无码一区二区三区四区-欧美中文字幕日韩在线观看-国产福利诱惑在线网站-国产中文字幕一区在线-亚洲欧美精品日韩一区-久久国产精品国产精品国产-国产精久久久久久一区二区三区-欧美亚洲国产精品久久久久

FreeBSD的Loader和內(nèi)核初始化( 四 )


 static struct sysinit uniquifier ## _sys_init = { subsystem,
 order, func, ident }; DATA_SET(sysinit_set,uniquifier ##
 _sys_init);
#define SYSINIT(uniquifier, subsystem, order, func, ident) 
C_SYSINIT(uniquifier, subsystem, order,
(sysinit_cfunc_t)(sysinit_nfunc_t)func, (void *)ident)
宏DATA_SET()展開成MAKE_SET(),宏MAKE_SET()指向所有隱含的
sysinit幻數(shù):/usr/include/linker_set.h
#define MAKE_SET(set, sym) 
static void const * const __set_##set##_sym_##sym = &sym; 
__asm(".section .set." #set ","aw"");
__asm(".long " #sym); 
__asm(".previous")
#endif
#define TEXT_SET(set, sym) MAKE_SET(set, sym)
#define DATA_SET(set, sym) MAKE_SET(set, sym)
回到我們的例子中,經(jīng)過宏的展開過程,將會產(chǎn)生如下聲明:
static struct sysinit announce_sys_init = {
SI_SUB_COPYRIGHT,
SI_ORDER_FIRST,
(sysinit_cfunc_t)(sysinit_nfunc_t) print_CADdr_t,
(void *) copyright
};
static void const *const __set_sysinit_set_sym_announce_sys_init =
&announce_sys_init;
__asm(".section .set.sysinit_set" ","aw"");
__asm(".long " "announce_sys_init");
__asm(".previous");
第一個__asm指令在內(nèi)核可執(zhí)行文件中建立一個ELF節(jié)(section) 。這發(fā)生在內(nèi)核鏈接的時候 。
這一節(jié)將被命令為.set.sysinit_set 。這一節(jié)的內(nèi)容是一個32位值——announce_sys_init結(jié)構(gòu)的地址,這個結(jié)構(gòu)正是第二個__asm指令所定義的 。第三個__asm指令標(biāo)記節(jié)的結(jié)束 。
如果前面有名字相同的節(jié)定義語句,節(jié)的內(nèi)容(那個32位值)將被填加到已存在的節(jié)里,這樣就構(gòu)造出了一個32位指針數(shù)組 。用objdump察看一個內(nèi)核二進(jìn)制文件,也許你會注意到里面有這么幾個小的節(jié):% objdump -h /kernel
 7 .set.cons_set 00000014 c03164c0 c03164c0 002154c0 2**2
 CONTENTS, ALLOC, LOAD, DATA
 8 .set.kbddriver_set 00000010 c03164d4 c03164d4 002154d4 2**2
 CONTENTS, ALLOC, LOAD, DATA
 9 .set.scrndr_set 00000024 c03164e4 c03164e4 002154e4 2**2
 CONTENTS, ALLOC, LOAD, DATA
10 .set.scterm_set 0000000c c0316508 c0316508 00215508 2**2
 CONTENTS, ALLOC, LOAD, DATA
11 .set.sysctl_set 0000097c c0316514 c0316514 00215514 2**2
 CONTENTS, ALLOC, LOAD, DATA
12 .set.sysinit_set 00000664 c0316e90 c0316e90 00215e90 2**2
 CONTENTS, ALLOC, LOAD, DATA
這一屏信息顯示表明節(jié).set.sysinit_set有0x664字節(jié)的大小,所以0x664/sizeof(void *)個sysinit對象被編譯進(jìn)了內(nèi)核 。其它節(jié),如.set.sysctl_set表示其它鏈接器集合 。通過定義一個類型為struct linker_set的變量,節(jié).set.sysinit_set將被“收集到那個變量里:sys/kern/init_main.c:
 extern struct linker_set sysinit_set; /* XXX */
struct linker_set定義如下:/usr/include/linker_set.h:
 struct linker_set {
int ls_length;
void*ls_items[1];/* ls_length個項的數(shù)組, 以NULL結(jié)尾 */
};
譯者注: 實際上是說,用C語言結(jié)構(gòu)體linker_set來表達(dá)那個ELF節(jié) 。第一項是sysinit對象的數(shù)量,第二項是一個以NULL結(jié)尾的數(shù)組,數(shù)組中是指向那些對象的指針 ?;氐綄i_startup()的討論,我們清楚了sysinit對象是如何被組織起來的 。函數(shù)mi_startup()將它們排序,并調(diào)用每一個對象 。最后一個對象是系統(tǒng)調(diào)度器:/usr/include/sys/kernel.h:
enum sysinit_sub_id {
SI_SUB_DUMMY= 0x0000000,/* 不被執(zhí)行,僅供鏈接器使用 */
SI_SUB_DONE = 0x0000001,/* 已被處理*/
SI_SUB_CONSOLE = 0x0800000,/* 控制臺*/
SI_SUB_COPYRIGHT= 0x0800001,/* 最早使用控制臺的對象 */
...
SI_SUB_RUN_SCHEDULER= 0xfffffff /* 調(diào)度器:不返回 */
};
系統(tǒng)調(diào)度器sysinit對象定義在文件sys/vm/vm_glue.c中,這個對象的入口點是scheduler() 。這個函數(shù)實際上是個無限循環(huán),它表示那個進(jìn)程標(biāo)識(PID)為0的進(jìn)程——swapper進(jìn)程 。前面提到的proc0結(jié)構(gòu)正是用來描述這個進(jìn)程 。

推薦閱讀