FreeBSD?kernel
是一個(gè)膨大的系統(tǒng)
,?
對(duì)于這樣一個(gè)大系統(tǒng)
,?
里面往往包含了大量的子系統(tǒng)和
??
模塊
,
當(dāng)系統(tǒng)初始化時(shí)這些模塊就需要初始化
,?
按照通常的思路
,
這些初始化過(guò)程必須在某處
??
被顯式地調(diào)用
,
這樣一來(lái)
,
當(dāng)你新增某個(gè)模塊
,
你必須再修改那個(gè)系統(tǒng)初始化的地方來(lái)調(diào)用這
??
個(gè)新增模塊的初始化過(guò)程
,?
而且由于
ANSI?C
語(yǔ)言的限制
,
調(diào)用某個(gè)函數(shù)最好先聲明
,
這樣當(dāng)系
??
統(tǒng)的初始化過(guò)程開(kāi)始增加時(shí)
,?
那個(gè)調(diào)用初始化過(guò)程的文件開(kāi)始大量包含那些本來(lái)不相關(guān)的頭
??
文件
,?
偶合度就增加了
,?
這是一種不好的設(shè)計(jì)
.??
FreeBSD
為了應(yīng)付這種情況
,?
使用一種叫做
SYSINIT
的機(jī)制
.?
我們知道
FreeBSD
使用一種叫做
??
ELF
的二進(jìn)制目標(biāo)執(zhí)行文件格式
.?
這種文件格式允許文件內(nèi)部組織成結(jié)構(gòu)化的方式
,?
文件內(nèi)
??
部可以由不同的組成部分
(section),?FreeBSD
正是利用了這種機(jī)制
.???
FreeBSD
使用
GNU?GCC
作為其
C
語(yǔ)言編譯器
,?
這種編譯器允許在
C
源程序中嵌入?yún)R編語(yǔ)言代碼
,??
FreeBSD
通過(guò)在
C
源程序中加入?yún)R編指令來(lái)在目標(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
宏指令
,?
就會(huì)將相應(yīng)的匯編符號(hào)加入到目標(biāo)文件
.?
例如
:??
int?myint;??
DATA_SET(myset,?myint);??
這兩句話將導(dǎo)致在目標(biāo)文件中創(chuàng)建一個(gè)
myset?section,?
并且
myint
的地址將被放入這個(gè)
??
section
中
.??
系統(tǒng)的初始化必須按嚴(yán)格的順序進(jìn)行
,?
為此
FreeBSD
定義了很多子系統(tǒng)的順序號(hào)
,?
這些順序
??
連同
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)還有順序號(hào)
:??
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
為每個(gè)想要在系統(tǒng)初始化時(shí)被調(diào)用的函數(shù)
,?
定義兩個(gè)函數(shù)類(lèi)型
:??
typedef?void?(*sysinit_nfunc_t)?__P((void?*));??
typedef?void?(*sysinit_cfunc_t)?__P((const?void?*));??
它們是系統(tǒng)初始化被調(diào)用時(shí)使用的函數(shù)原型
.??
兩個(gè)重要的宏使得初始化函數(shù)能夠在系統(tǒng)開(kāi)始時(shí)被執(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)??
其中每個(gè)初始化函數(shù)被存儲(chǔ)成這樣一個(gè)結(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?*/??
????????};??
這個(gè)結(jié)構(gòu)包含了子系統(tǒng)編號(hào)
,?
子系統(tǒng)中的順序號(hào)
,?
初始化函數(shù)的地址
,?
以及這個(gè)函數(shù)
??
使用的參數(shù)
.??
現(xiàn)在如果有個(gè)函數(shù)想要在系統(tǒng)啟動(dòng)時(shí)自動(dòng)被調(diào)用
,?
并且知道這個(gè)函數(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)??
這樣聲明的初始化過(guò)程分布在很多目標(biāo)文件中
,?
當(dāng)
gcc
的連接編輯器
ld
運(yùn)行時(shí)就會(huì)把屬于同
??
一個(gè)
section
的數(shù)據(jù)合并到一個(gè)連續(xù)的地址塊中
.??
由于在這個(gè)
section
中包含的只能是指向
sysinit
結(jié)構(gòu)的指針
,
這樣
FreeBSD
就可以把這個(gè)地址
??
當(dāng)成一個(gè)
sysinit*?
的數(shù)組
,?FreeBSD
找出這個(gè)
sysinit_set
地址
,?
邊歷這個(gè)數(shù)組并調(diào)用其中
??
的初始化函數(shù)
.?
為了確切知道這個(gè)
section
的大小
(
直接讀
ELF
是可能的
,
但是那樣太復(fù)雜
,
要
??
知道
kernel
調(diào)用初始化過(guò)程時(shí)文件系統(tǒng)可能還沒(méi)有初始化呢
),?
系統(tǒng)中包含一個(gè)工具
??
gensetdefs,?
這個(gè)工具能掃描給出的一組
.o
目標(biāo)文件
,?
并找到任何名字是由
.set.
開(kāi)頭的
??
section,?
它統(tǒng)計(jì)有多少個(gè)這樣的的初始化函數(shù)
,?
并在
sysinit_set
的開(kāi)頭生成一個(gè)長(zhǎng)整形
??
計(jì)數(shù)器
.?gensetdefs
生成三個(gè)文件
:??
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?*/??
這個(gè)
DEFINE_SET
在某個(gè)
section
中放入一個(gè)
?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
被連接時(shí)
,?
在
Makefile
中
setdef0.o
被安排最前面
,?
這樣
ld
就把這個(gè)初始化函數(shù)的
??
計(jì)數(shù)器安排在這個(gè)
section
的最前面
.?FreeBSD?kernel
就能從這個(gè)
section
的開(kāi)頭讀到這個(gè)計(jì)
??
數(shù)器
,?
也就知道了有多少個(gè)初始化函數(shù)
.?
在
Makefile
中被安排在中間的的是
FreeBSD
的其他
??
.o
文件
,?
最后由
setdef1.o
壓陣
.?setdef1.c
定義了一個(gè)空指針
,
用以表示這個(gè)
section
的結(jié)束
??
,
這種安排
,?
我把它叫做夾三明治
.??
初始化過(guò)程的調(diào)用被安排在內(nèi)核
?/sys/kern/init_main.c
的
mi_startup
函數(shù)中
,?mi_startup??
是系統(tǒng)啟動(dòng)過(guò)程中
,?
第一個(gè)被執(zhí)行的
C
語(yǔ)言函數(shù)
,??
它做的第一件事情就是調(diào)用這些初始化函
??
數(shù)
,?
開(kāi)始時(shí)對(duì)所有的初始化過(guò)程做優(yōu)先級(jí)排序
,?
然后順序調(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)先級(jí)別排序
,?
這里沒(méi)有使用那個(gè)在
setdef0.c
中定義的計(jì)數(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號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
