FreeBSD?kernel
是一個膨大的系統(tǒng)
,?
對于這樣一個大系統(tǒng)
,?
里面往往包含了大量的子系統(tǒng)和
??
模塊
,
當(dāng)系統(tǒng)初始化時這些模塊就需要初始化
,?
按照通常的思路
,
這些初始化過程必須在某處
??
被顯式地調(diào)用
,
這樣一來
,
當(dāng)你新增某個模塊
,
你必須再修改那個系統(tǒng)初始化的地方來調(diào)用這
??
個新增模塊的初始化過程
,?
而且由于
ANSI?C
語言的限制
,
調(diào)用某個函數(shù)最好先聲明
,
這樣當(dāng)系
??
統(tǒng)的初始化過程開始增加時
,?
那個調(diào)用初始化過程的文件開始大量包含那些本來不相關(guān)的頭
??
文件
,?
偶合度就增加了
,?
這是一種不好的設(shè)計
.??
FreeBSD
為了應(yīng)付這種情況
,?
使用一種叫做
SYSINIT
的機制
.?
我們知道
FreeBSD
使用一種叫做
??
ELF
的二進(jìn)制目標(biāo)執(zhí)行文件格式
.?
這種文件格式允許文件內(nèi)部組織成結(jié)構(gòu)化的方式
,?
文件內(nèi)
??
部可以由不同的組成部分
(section),?FreeBSD
正是利用了這種機制
.???
FreeBSD
使用
GNU?GCC
作為其
C
語言編譯器
,?
這種編譯器允許在
C
源程序中嵌入?yún)R編語言代碼
,??
FreeBSD
通過在
C
源程序中加入?yún)R編指令來在目標(biāo)文件中增加額外的
section,?
在文件
??
/sys/sys/linker_set.h
中定義如下
:??
#ifdef?__alpha__??
#define?MAKE_SET(set,?sym)??????????????????????????????????????????????\??
????????static?void?const?*?const?__set_##set##_sym_##sym?=?&sym;???????\??
????????__asm(".align?3");??????????????????????????????????????????????\??
????????__asm(".section?.set."?#set?",\"aw\"");?????????????????????????\??
????????__asm(".quad?"?#sym);???????????????????????????????????????????\??
????????__asm(".previous")??
#else??
#define?MAKE_SET(set,?sym)?????
#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)??
程序一旦在某處調(diào)用
DATA_SET
宏指令
,?
就會將相應(yīng)的匯編符號加入到目標(biāo)文件
.?
例如
:??
int?myint;??
DATA_SET(myset,?myint);??
這兩句話將導(dǎo)致在目標(biāo)文件中創(chuàng)建一個
myset?section,?
并且
myint
的地址將被放入這個
??
section
中
.??
系統(tǒng)的初始化必須按嚴(yán)格的順序進(jìn)行
,?
為此
FreeBSD
定義了很多子系統(tǒng)的順序號
,?
這些順序
??
連同
SYSINIT
的許多相關(guān)定義在
/sys/sys/kernel.h
頭文件中
:??
enum?sysinit_sub_id?{??
????????SI_SUB_DUMMY????????????=?0x0000000,????/*?not?executed;?for?linker*/??
????????SI_SUB_DONE?????????????=?0x0000001,????/*?processed*/??
????????SI_SUB_CONSOLE??????????=?0x0800000,????/*?console*/??
????????SI_SUB_COPYRIGHT????????=?0x0800001,????/*?first?use?of?console*/??
????????SI_SUB_TUNABLES?????????=?0x0700000,????/*?establish?tunable?values?*/??
????????SI_SUB_VM???????????????=?0x1000000,????/*?virtual?memory?system?init*/??
????????SI_SUB_KMEM?????????????=?0x1800000,????/*?kernel?memory*/??
????????SI_SUB_KVM_RSRC?????????=?0x1A00000,????/*?kvm?operational?limits*/??
????????SI_SUB_CPU??????????????=?0x1e00000,????/*?CPU?resource(s)*/??
????????SI_SUB_KLD??????????????=?0x1f00000,????/*?KLD?and?module?setup?*/??
????????SI_SUB_INTRINSIC????????=?0x2000000,????/*?proc?0*/??
????????SI_SUB_VM_CONF??????????=?0x2100000,????/*?config?VM,?set?limits*/??
????????SI_SUB_RUN_QUEUE????????=?0x2200000,????/*?the?run?queue*/??
????????SI_SUB_CREATE_INIT??????=?0x2300000,????/*?create?the?init?process?*/??
????????SI_SUB_DRIVERS??????????=?0x2400000,????/*?Let?Drivers?initialize?*/??
????????SI_SUB_CONFIGURE????????=?0x3800000,????/*?Configure?devices?*/??
????????SI_SUB_VFS??????????????=?0x4000000,????/*?virtual?file?system*/??
????????SI_SUB_CLOCKS???????????=?0x4800000,????/*?real?time?and?stat?clocks*/??
????????SI_SUB_MBUF?????????????=?0x5000000,????/*?mbufs*/??
????????SI_SUB_CLIST????????????=?0x5800000,????/*?clists*/??
????????SI_SUB_SYSV_SHM?????????=?0x6400000,????/*?System?V?shared?memory*/??
????????SI_SUB_SYSV_SEM?????????=?0x6800000,????/*?System?V?semaphores*/??
????????SI_SUB_SYSV_MSG?????????=?0x6C00000,????/*?System?V?message?queues*/??
????????SI_SUB_P1003_1B?????????=?0x6E00000,????/*?P1003.1B?realtime?*/??
????????SI_SUB_PSEUDO???????????=?0x7000000,????/*?pseudo?devices*/??
????????SI_SUB_EXEC?????????????=?0x7400000,????/*?execve()?handlers?*/??
????????SI_SUB_PROTO_BEGIN??????=?0x8000000,????/*?XXX:?set?splimp?(kludge)*/??
????????...??
};??
子系統(tǒng)內(nèi)還有順序號
:??
enum?sysinit_elem_order?{??
????????SI_ORDER_FIRST??????????=?0x0000000,????/*?first*/??
????????SI_ORDER_SECOND?????????=?0x0000001,????/*?second*/??
????????SI_ORDER_THIRD??????????=?0x0000002,????/*?third*/??
????????SI_ORDER_MIDDLE?????????=?0x1000000,????/*?somewhere?in?the?middle?*/??
????????SI_ORDER_ANY????????????=?0xfffffff?????/*?last*/??
};??
FreeBSD
為每個想要在系統(tǒng)初始化時被調(diào)用的函數(shù)
,?
定義兩個函數(shù)類型
:??
typedef?void?(*sysinit_nfunc_t)?__P((void?*));??
typedef?void?(*sysinit_cfunc_t)?__P((const?void?*));??
它們是系統(tǒng)初始化被調(diào)用時使用的函數(shù)原型
.??
兩個重要的宏使得初始化函數(shù)能夠在系統(tǒng)開始時被執(zhí)行
:??
#define?C_SYSINIT(uniquifier,?subsystem,?order,?func,?ident)????\??
????????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)??
其中每個初始化函數(shù)被存儲成這樣一個結(jié)構(gòu)
:??
????????struct?sysinit?{??
???????????unsigned?int????subsystem;??????????????/*?subsystem?identifier*/??
???????????unsigned?int????order;??????????????????/*?init?order?within?subsystem*/??
???????????sysinit_cfunc_t?func;???????????????????/*?function?????????????*/??
???????????const?void??????*udata;?????????????????/*?multiplexer/argument?*/??
????????};??
這個結(jié)構(gòu)包含了子系統(tǒng)編號
,?
子系統(tǒng)中的順序號
,?
初始化函數(shù)的地址
,?
以及這個函數(shù)
??
使用的參數(shù)
.??
現(xiàn)在如果有個函數(shù)想要在系統(tǒng)啟動時自動被調(diào)用
,?
并且知道這個函數(shù)是為
VM
子系統(tǒng)做準(zhǔn)備工
??
作
,?
可以這樣申明
:??
long?myvar;??
void?init_myvar(void?*p)??
{??
?????*(long?*)p?=?2;??
}??
SYSINIT(init_myvar,?SI_SUB_VM,?1000,?init_myvar,?&myvar)??
這樣聲明的初始化過程分布在很多目標(biāo)文件中
,?
當(dāng)
gcc
的連接編輯器
ld
運行時就會把屬于同
??
一個
section
的數(shù)據(jù)合并到一個連續(xù)的地址塊中
.??
由于在這個
section
中包含的只能是指向
sysinit
結(jié)構(gòu)的指針
,
這樣
FreeBSD
就可以把這個地址
??
當(dāng)成一個
sysinit*?
的數(shù)組
,?FreeBSD
找出這個
sysinit_set
地址
,?
邊歷這個數(shù)組并調(diào)用其中
??
的初始化函數(shù)
.?
為了確切知道這個
section
的大小
(
直接讀
ELF
是可能的
,
但是那樣太復(fù)雜
,
要
??
知道
kernel
調(diào)用初始化過程時文件系統(tǒng)可能還沒有初始化呢
),?
系統(tǒng)中包含一個工具
??
gensetdefs,?
這個工具能掃描給出的一組
.o
目標(biāo)文件
,?
并找到任何名字是由
.set.
開頭的
??
section,?
它統(tǒng)計有多少個這樣的的初始化函數(shù)
,?
并在
sysinit_set
的開頭生成一個長整形
??
計數(shù)器
.?gensetdefs
生成三個文件
:??
setdef0.c?setdef1.c?setdefs.h??
文件
setdef0.c
的內(nèi)容
:??
--------------------------------------------------------??
/*?THIS?FILE?IS?GENERATED,?DO?NOT?EDIT.?*/??
#define?DEFINE_SET(set,?count)??????????????????\??
__asm__(".section?.set."?#set?",\"aw\"");???????\??
__asm__(".globl?"?#set);????????????????????????\??
__asm__(".type?"?#set?",@object");??????????????\??
__asm__(".p2align?2");??????????????????????????\??
__asm__(#set?":");??????????????????????????????\??
__asm__(".long?"?#count);???????????????????????\??
__asm__(".previous")??
#include?"setdefs.h"????????????/*?Contains?a?`DEFINE_SET'?for?each?set?*/??
--------------------------------------------------------??
這里的
DEFINE_SET
效果就是申明一
C
結(jié)構(gòu)
:??
struct?linker_set?{??
????????int?????ls_length;??
????????void????*ls_items[1];???????????/*?really?ls_length?of?them,??
????????????????????????????????????????????????*?trailing?NULL?*/??
};??
文件
setdef1.c
的內(nèi)容
:??
--------------------------------------------------------??
/*?THIS?FILE?IS?GENERATED,?DO?NOT?EDIT.?*/??
#define?DEFINE_SET(set,?count)??????????????????????????\??
__asm__(".section?.set."?#set?",\"aw\"");???????\??
__asm__(".long?0");?????????????????????\??
__asm__(".previous")??
#include?"setdefs.h"????????????/*?Contains?a?`DEFINE_SET'?for?each?set?*/??
這個
DEFINE_SET
在某個
section
中放入一個
?long?0.??
--------------------------------------------------------??
文件
setdefs.h
的內(nèi)容
:??
DEFINE_SET(cons_set,?3);??
DEFINE_SET(kbddriver_set,?2);??
DEFINE_SET(periphdriver_set,?5);??
DEFINE_SET(scrndr_set,?9);??
DEFINE_SET(scterm_set,?1);??
DEFINE_SET(sysctl_set,?552);??
DEFINE_SET(sysinit_set,?323);??
DEFINE_SET(sysuninit_set,?155);??
DEFINE_SET(vga_set,?9);??
DEFINE_SET(videodriver_set,?4);??
當(dāng)
kernel
被連接時
,?
在
Makefile
中
setdef0.o
被安排最前面
,?
這樣
ld
就把這個初始化函數(shù)的
??
計數(shù)器安排在這個
section
的最前面
.?FreeBSD?kernel
就能從這個
section
的開頭讀到這個計
??
數(shù)器
,?
也就知道了有多少個初始化函數(shù)
.?
在
Makefile
中被安排在中間的的是
FreeBSD
的其他
??
.o
文件
,?
最后由
setdef1.o
壓陣
.?setdef1.c
定義了一個空指針
,
用以表示這個
section
的結(jié)束
??
,
這種安排
,?
我把它叫做夾三明治
.??
初始化過程的調(diào)用被安排在內(nèi)核
?/sys/kern/init_main.c
的
mi_startup
函數(shù)中
,?mi_startup??
是系統(tǒng)啟動過程中
,?
第一個被執(zhí)行的
C
語言函數(shù)
,??
它做的第一件事情就是調(diào)用這些初始化函
??
數(shù)
,?
開始時對所有的初始化過程做優(yōu)先級排序
,?
然后順序調(diào)用它們
.??
void??????????????????????
mi_startup(void)??
{?????????????????
??????????????????????????
????????register?struct?sysinit?**sipp;?????????/*?system?initialization*/??
????????register?struct?sysinit?**xipp;?????????/*?interior?loop?of?sort*/??
????????register?struct?sysinit?*save;??????????/*?bubble*/??
restart:??????????
??????????
????????
這是優(yōu)先級別排序
,?
這里沒有使用那個在
setdef0.c
中定義的計數(shù)器
,?
而是使用
??
????????
了
setdef1.c
中定義的空指針作為結(jié)束標(biāo)志
.??
??????????
????????/*????????
?????????*?Perform?a?bubble?sort?of?the?system?initialization?objects?by??
?????????*?their?subsystem?(primary?key)?and?order?(secondary?key).??
?????????*/???????
????????for?(sipp?=?sysinit;?*sipp;?sipp++)?{??
????????????????for?(xipp?=?sipp?+?1;?*xipp;?xipp++)?{??
????????????????????????if?((*sipp)->subsystem?< (*xipp)->subsystem?||??
?????????????????????????????((*sipp)->subsystem?==?(*xipp)->subsystem?&&??
??????????????????????????????(*sipp)->order?<= (*xipp)->order))??
????????????????????????????????continue;???????/*?skip*/??
????????????????????????save?=?*sipp;??
????????????????????????*sipp?=?*xipp;??
????????????????????????*xipp?=?save;??
????????????????}??
????????}??
????????/*??
?????????*?Traverse?the?(now)?ordered?list?of?system?initialization?tasks.??
?????????*?Perform?each?task,?and?continue?on?to?the?next?task.??
?????????*??
?????????*?The?last?item?on?the?list?is?expected?to?be?the?scheduler,??
?????????*?which?will?not?return.??
?????????*/??
????????for?(sipp?=?sysinit;?*sipp;?sipp++)?{??
????????????????if?((*sipp)->subsystem?==?SI_SUB_DUMMY)??
????????????????????????continue;???????/*?skip?dummy?task(s)*/??
這是按順序調(diào)用
:??
/*??
?????????*?Traverse?the?(now)?ordered?list?of?system?initialization?tasks.??
?????????*?Perform?each?task,?and?continue?on?to?the?next?task.??
?????????*??
?????????*?The?last?item?on?the?list?is?expected?to?be?the?scheduler,??
?????????*?which?will?not?return.??
?????????*/??
????????for?(sipp?=?sysinit;?*sipp;?sipp++)?{??
????????????????if?((*sipp)->subsystem?==?SI_SUB_DUMMY)??
????????????????????????continue;???????/*?skip?dummy?task(s)*/??
????????????????if?((*sipp)->subsystem?==?SI_SUB_DONE)??
????????????????????????continue;??
????????????????/*?Call?function?*/??
????????????????(*((*sipp)->func))((*sipp)->udata);??
????????????????/*?Check?off?the?one?we're?just?done?*/??
????????????????(*sipp)->subsystem?=?SI_SUB_DONE;??
????????????????/*?Check?if?we've?installed?more?sysinit?items?via?KLD?*/??
????????????????if?(newsysinit?!=?NULL)?{??
????????????????????????if?(sysinit?!=?(struct?sysinit?**)sysinit_set.ls_items)??
????????????????????????????????free(sysinit,?M_TEMP);??
????????????????????????sysinit?=?newsysinit;??
????????????????????????newsysinit?=?NULL;??
????????????????????????goto?restart;??
????????????????}??
????????}??
????????panic("Shouldn't?get?here!");??
}??
??????
SRC= http://www.moon-soft.com/program/bbs/readelite432617.htm
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
