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

FreeBSD的Loader和內(nèi)核初始化( 三 )


另外還有一個(gè)附帶的好處:在仿真Linux時(shí),當(dāng)遇到FreeBSD內(nèi)核不支持的而又并非關(guān)鍵性的系統(tǒng)調(diào)用時(shí),內(nèi)核只會(huì)顯示一些出錯(cuò)信息,這使得程序能夠繼續(xù)運(yùn)行;而不是在真正執(zhí)行程序之前的初始化過程中就因?yàn)閯?dòng)態(tài)鏈接失敗而不允許程序運(yùn)行 。中斷描述符表最多可以有256 (0x100)條記錄 。內(nèi)核分配NIDT條記錄的內(nèi)存給中斷描述符表,這里NIDT=256,是最大值:sys/i386/i386/Machdep.c:
static struct gate_descriptor idt0[NIDT];
struct gate_descriptor *idt = &idt0[0]; /* 中斷描述符表 */
每個(gè)中斷都被設(shè)置一個(gè)合適的中斷處理程序 。系統(tǒng)調(diào)用關(guān)口INT 0x80也是如此:sys/i386/i386/machdep.c:
setidt(0x80, &IDTVEC(int0x80_syscall),
SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
所以當(dāng)一個(gè)用戶應(yīng)用程序提交INT 0x80指令時(shí),全系統(tǒng)的控制權(quán)會(huì)傳遞給函數(shù)_Xint0x80_syscall,這個(gè)函數(shù)在內(nèi)核代碼段中,將被以管理員權(quán)限執(zhí)行 。然后,控制臺(tái)和DDB(調(diào)試器)被初始化:sys/i386/i386/machdep.c:
cninit();
/* 以下代碼可能因?yàn)槲炊x宏DDB而被跳過 */
#ifdef DDB
kdb_init();
if (boothowto & RB_KDB)
Debugger("Boot flags requested debugger");
#endif
任務(wù)狀態(tài)段(TSS)是另一個(gè)x86保護(hù)模式中的數(shù)據(jù)結(jié)構(gòu) 。當(dāng)發(fā)生任務(wù)切換時(shí),任務(wù)狀態(tài)段用來讓硬件存儲(chǔ)任務(wù)現(xiàn)場(chǎng)信息 。局部描述符表(LDT)用來指向用戶代碼和數(shù)據(jù) 。系統(tǒng)定義了幾個(gè)選擇符,指向局部描述符表,它們是系統(tǒng)調(diào)用關(guān)口和用戶代碼、用戶數(shù)據(jù)選擇符:/usr/include/Machine/segments.h
#define LSYS5CALLS_SEL 0/* Intel BCS強(qiáng)制要求的 */
#define LSYS5SIGR_SEL1
#define L43BSDCALLS_SEL 2/* 尚無 */
#define LUCODE_SEL 3
#define LSOL26CALLS_SEL 4/* Solaris >=2.6版系統(tǒng)調(diào)用關(guān)口 */
#define LUDATA_SEL 5
/* separate stack, es,fs,gs sels ? 分別的棧、es、fs、gs選擇符? */
/* #define LPOSIXCALLS_SEL 5*/ /* notyet, 尚無 */
#define LBSDICALLS_SEL 16 /* BSDI system call gate, BSDI系統(tǒng)調(diào)用關(guān)口 */
#define NLDT(LBSDICALLS_SEL1)
然后,proc0(0號(hào)進(jìn)程,即內(nèi)核所處的進(jìn)程)的進(jìn)程控制塊(Process Control Block)(struct pcb)結(jié)構(gòu)被初始化 。proc0是一個(gè)struct proc 結(jié)構(gòu),描述了一個(gè)內(nèi)核進(jìn)程 。內(nèi)核運(yùn)行時(shí),該進(jìn)程總是存在,所以這個(gè)結(jié)構(gòu)在內(nèi)核中被定義為全局變量:sys/kern/kern_init.c:
struct proc proc0;
結(jié)構(gòu)struct pcb是proc結(jié)構(gòu)的一部分,它定義在/usr/include/machine/pcb.h之中,內(nèi)含針對(duì)i386硬件結(jié)構(gòu)專有的信息,如寄存器的值 。1.7.2 mi_startup()這個(gè)函數(shù)用冒泡排序算法,將所有系統(tǒng)初始化對(duì)象,然后逐個(gè)調(diào)用每個(gè)對(duì)象的入口:sys/kern/init_main.c:
for (sipp = sysinit; *sipp; sipp) {
/* ... 省略 ... */
/* 調(diào)用函數(shù) */
(*((*sipp)->func))((*sipp)->udata);
/* ... 省略 ... */
}
盡管sysinit框架已經(jīng)在《FreeBSD開發(fā)者手冊(cè)》中有所描述,我還是在這里討論一下其內(nèi)部原理 。每個(gè)系統(tǒng)初始化對(duì)象(sysinit對(duì)象)通過調(diào)用宏建立 。讓我們以announce sysinit對(duì)象為例 。這個(gè)對(duì)象打印版權(quán)信息:sys/kern/init_main.c:
static void
print_CADdr_t(void *data __unused)
{
printf("%s", (char *)data);
}
SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright)
這個(gè)對(duì)象的子系統(tǒng)標(biāo)識(shí)是SI_SUB_COPYRIGHT(0x0800001),數(shù)值剛好排在SI_SUB_CONSOLE(0x0800000)后面 。所以,版權(quán)信息將在控制臺(tái)初始化之后就被很早的打印出來 。
讓我們看一看宏SYSINIT()到底做了些什么 。它展開成宏C_SYSINIT() 。宏C_SYSINIT()然后展開成一個(gè)靜態(tài)結(jié)構(gòu)struct sysinit 。結(jié)構(gòu)里申明里調(diào)用了另一個(gè)宏DATA_SET:/usr/include/sys/kernel.h:
 #define C_SYSINIT(uniquifIEr, subsystem, order, func, ident)

推薦閱讀