日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

FreeBSD 內(nèi)核中的SYSINIT分析

系統(tǒng) 2340 0

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

FreeBSD 內(nèi)核中的SYSINIT分析


更多文章、技術(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ì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 彭阳县| 察雅县| 桃园县| 响水县| 青州市| 观塘区| 和龙市| 石门县| 沧州市| 教育| 汉中市| 长武县| 云安县| 龙游县| 南汇区| 图片| 永修县| 中西区| 淮北市| 门源| 柘城县| 阿拉善盟| 巴塘县| 义乌市| 武威市| 建昌县| 株洲县| 博乐市| 东明县| 水城县| 丰顺县| 阿瓦提县| 彭阳县| 定日县| 民乐县| 阳江市| 庐江县| 曲沃县| 南江县| 新乡县| 乳源|