亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

FreeBSD 內核中的SYSINIT分析

系統 2072 0

FreeBSD?kernel 是一個膨大的系統 ,? 對于這樣一個大系統 ,? 里面往往包含了大量的子系統和 ??
模塊 , 當系統初始化時這些模塊就需要初始化 ,? 按照通常的思路 , 這些初始化過程必須在某處 ??
被顯式地調用 , 這樣一來 , 當你新增某個模塊 , 你必須再修改那個系統初始化的地方來調用這 ??
個新增模塊的初始化過程 ,? 而且由于 ANSI?C 語言的限制 , 調用某個函數最好先聲明 , 這樣當系 ??
統的初始化過程開始增加時 ,? 那個調用初始化過程的文件開始大量包含那些本來不相關的頭 ??
文件 ,? 偶合度就增加了 ,? 這是一種不好的設計 .??

FreeBSD
為了應付這種情況 ,? 使用一種叫做 SYSINIT 的機制 .? 我們知道 FreeBSD 使用一種叫做 ??
ELF
的二進制目標執行文件格式 .? 這種文件格式允許文件內部組織成結構化的方式 ,? 文件內 ??
部可以由不同的組成部分 (section),?FreeBSD 正是利用了這種機制 .???

FreeBSD
使用 GNU?GCC 作為其 C 語言編譯器 ,? 這種編譯器允許在 C 源程序中嵌入匯編語言代碼 ,??
FreeBSD
通過在 C 源程序中加入匯編指令來在目標文件中增加額外的 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)??

程序一旦在某處調用 DATA_SET 宏指令 ,? 就會將相應的匯編符號加入到目標文件 .? 例如 :??
int?myint;??
DATA_SET(myset,?myint);??
這兩句話將導致在目標文件中創建一個 myset?section,? 并且 myint 的地址將被放入這個 ??
section
.??

系統的初始化必須按嚴格的順序進行 ,? 為此 FreeBSD 定義了很多子系統的順序號 ,? 這些順序 ??
連同 SYSINIT 的許多相關定義在 /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)*/??
????????...??
};??

子系統內還有順序號 :??
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
為每個想要在系統初始化時被調用的函數 ,? 定義兩個函數類型 :??
typedef?void?(*sysinit_nfunc_t)?__P((void?*));??
typedef?void?(*sysinit_cfunc_t)?__P((const?void?*));??
它們是系統初始化被調用時使用的函數原型 .??
兩個重要的宏使得初始化函數能夠在系統開始時被執行 :??

#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)??

其中每個初始化函數被存儲成這樣一個結構 :??
????????struct?sysinit?{??
???????????unsigned?int????subsystem;??????????????/*?subsystem?identifier*/??
???????????unsigned?int????order;??????????????????/*?init?order?within?subsystem*/??
???????????sysinit_cfunc_t?func;???????????????????/*?function?????????????*/??
???????????const?void??????*udata;?????????????????/*?multiplexer/argument?*/??
????????};??
這個結構包含了子系統編號 ,? 子系統中的順序號 ,? 初始化函數的地址 ,? 以及這個函數 ??
使用的參數 .??

現在如果有個函數想要在系統啟動時自動被調用 ,? 并且知道這個函數是為 VM 子系統做準備工 ??
,? 可以這樣申明 :??

long?myvar;??
void?init_myvar(void?*p)??
{??
?????*(long?*)p?=?2;??
}??
SYSINIT(init_myvar,?SI_SUB_VM,?1000,?init_myvar,?&myvar)??

這樣聲明的初始化過程分布在很多目標文件中 ,? gcc 的連接編輯器 ld 運行時就會把屬于同 ??
一個 section 的數據合并到一個連續的地址塊中 .??
由于在這個 section 中包含的只能是指向 sysinit 結構的指針 , 這樣 FreeBSD 就可以把這個地址 ??
當成一個 sysinit*? 的數組 ,?FreeBSD 找出這個 sysinit_set 地址 ,? 邊歷這個數組并調用其中 ??
的初始化函數 .? 為了確切知道這個 section 的大小 ( 直接讀 ELF 是可能的 , 但是那樣太復雜 , ??
知道 kernel 調用初始化過程時文件系統可能還沒有初始化呢 ),? 系統中包含一個工具 ??
gensetdefs,?
這個工具能掃描給出的一組 .o 目標文件 ,? 并找到任何名字是由 .set. 開頭的 ??
section,?
它統計有多少個這樣的的初始化函數 ,? 并在 sysinit_set 的開頭生成一個長整形 ??
計數器 .?gensetdefs 生成三個文件 :??
setdef0.c?setdef1.c?setdefs.h??

文件 setdef0.c 的內容 :??

--------------------------------------------------------??
/*?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 結構 :??
struct?linker_set?{??
????????int?????ls_length;??
????????void????*ls_items[1];???????????/*?really?ls_length?of?them,??
????????????????????????????????????????????????*?trailing?NULL?*/??
};??

文件 setdef1.c 的內容 :??

--------------------------------------------------------??
/*?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 的內容 :??

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);??

kernel 被連接時 ,? Makefile setdef0.o 被安排最前面 ,? 這樣 ld 就把這個初始化函數的 ??
計數器安排在這個 section 的最前面 .?FreeBSD?kernel 就能從這個 section 的開頭讀到這個計 ??
數器 ,? 也就知道了有多少個初始化函數 .? Makefile 中被安排在中間的的是 FreeBSD 的其他 ??
.o
文件 ,? 最后由 setdef1.o 壓陣 .?setdef1.c 定義了一個空指針 , 用以表示這個 section 的結束 ??
,
這種安排 ,? 我把它叫做夾三明治 .??

初始化過程的調用被安排在內核 ?/sys/kern/init_main.c mi_startup 函數中 ,?mi_startup??
是系統啟動過程中 ,? 第一個被執行的 C 語言函數 ,?? 它做的第一件事情就是調用這些初始化函 ??
,? 開始時對所有的初始化過程做優先級排序 ,? 然后順序調用它們 .??

void??????????????????????
mi_startup(void)??
{?????????????????
??????????????????????????
????????register?struct?sysinit?**sipp;?????????/*?system?initialization*/??
????????register?struct?sysinit?**xipp;?????????/*?interior?loop?of?sort*/??
????????register?struct?sysinit?*save;??????????/*?bubble*/??

restart:??????????
??????????
????????
這是優先級別排序 ,? 這里沒有使用那個在 setdef0.c 中定義的計數器 ,? 而是使用 ??
????????
setdef1.c 中定義的空指針作為結束標志 .??
??????????
????????/*????????
?????????*?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)*/??


這是按順序調用 :??
/*??
?????????*?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 內核中的SYSINIT分析


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 97高清国语自产拍中国大陆 | 久草视频播放器 | 日本福利片 | 色综合网亚洲精品久久久 | 日日操天天操夜夜操 | 九九精品国产兔费观看久久 | www.四虎影院.con | 老司机成人午夜精品福利视频 | 成年女人午夜毛片免费看 | zzz色| 久久久久女人精品毛片九一 | 伊人色婷婷 | 夜夜欢视频| 国产亚洲欧美在在线人成 | 国产精品一国产精品免费 | 国产午夜爽爽窝窝在线观看 | 久久爆操 | 国产69精品久久久久9999 | 亚洲五月综合网色九月色 | 日本视频中文字幕一区二区 | 精品国产九九 | 色婷婷色综合缴情在线 | 国产在线观看中文字幕 | 超清波多野结衣精品一区 | 欧美一级毛片aaa片 欧美一级毛片不卡免费观看 | 一级大片免费观看 | 97影院午夜午夜伦不卡 | 日本高清毛片视频在线看 | 亚洲国产精品免费 | 成人欧美视频在线观看播放 | 男女污污视频在线观看 | 亚洲精品久久精品h成人 | 四虎音影| 9久久这里只有精品国产 | 四虎新地址4hu 你懂的 | 日本人成年视频在线观看 | 色婷婷六月 | 成人凹凸短视频在线观看 | 视频一区二区在线 | 二区在线观看 | 国产乱叫456在线 |