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

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


SI_ORDER_MIDDLE;=;0x1000000,;;;;/*;somewhere;in;the;middle;*/
SI_ORDER_ANY;;;;=;0xfffffff;;;;;/*;last*/
};



FreeBSD為每個(gè)想要在系統(tǒng)初始化時(shí)被調(diào)用的函數(shù),;定義兩個(gè)函數(shù)類型:
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)開始時(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)

這樣聲明的初始化過程分布在很多目標(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)用初始化過程時(shí)文件系統(tǒng)可能還沒有初始化呢),;系統(tǒng)中包含一個(gè)工具;gensetdefs,;這個(gè)工具能掃描給出的一組.o目標(biāo)文件,;并找到任何名字是由.set.開頭的;section,;它統(tǒng)計(jì)有多少個(gè)這樣的的初始化函數(shù),;并在sysinit_set的開頭生成一個(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的開頭讀到這個(gè)計(jì)數(shù)器,;也就知道了有多少個(gè)初始化函數(shù).;在Makefile中被安排在中間的的是FreeBSD的其他;.o文件,;最后由setdef1.o壓陣.;setdef1.c定義了一個(gè)空指針,用以表示這個(gè)section的結(jié)束;,這種安排,;我把它叫做夾三明治.;

推薦閱讀