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

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

loader也是一個 BTX 客戶,在這里不作詳述 。已有一部內(nèi)容全面的手冊 loader(8) ,由Mike Smith書寫 。比loader更底層的BTX的機理已經(jīng)在前面討論過 。loader 的主要任務是引導內(nèi)核 。當內(nèi)核被裝入內(nèi)存后,即被loader調(diào)用:sys/boot/common/boot.c:
/* 從loader中調(diào)用內(nèi)核中對應的exec程序 */
module_formats[km->m_loader]->l_exec(km);loader跳轉(zhuǎn)至哪里呢?那就是內(nèi)核的入口點 。讓我們來看一下鏈接內(nèi)核的命令:sys/conf/Makefile.i386:ld -elf -Bdynamic -T /usr/src/sys/conf/ldscript.i386 -export-dynamic
-dynamic-linker /red/herring -o kernel -X locore.o在這一行中有一些有趣的東西 。首先,內(nèi)核是一個ELF動態(tài)鏈接二進制文件,可是動態(tài)鏈接器卻是/red/herring,一個莫須有的文件 。其次,看一下文件sys/conf/ldscript.i386,可以對理解編譯內(nèi)核時ld的選項有一些啟發(fā) 。閱讀最前幾行,字符串sys/conf/ldscript.i386:ENTRY(btext)
表示內(nèi)核的入口點是符號 `btext' 。這個符號在locore.s中定義:sys/i386/i386/locore.s:
.text
/**********************************************************************
*
* This is where the bootblocks start us, set the ball rolling...
* 入口
*/
NON_GPROF_ENTRY(btext)
首先將寄存器EFLAGS設為一個預定義的值0x00000002,然后初始化所有段寄存器:sys/i386/i386/locore.s
/* 不要相信BIOS給出的EFLAGS值 */
pushl$PSL_KERNEL
popfl
/*
* 不要相信BIOS給出的%fs、%gs值 。相信引導過程中設定的%cs、%ds、%es、%ss值
*/
mov %ds, %ax
mov %ax, %fs
mov %ax, %gs
btext調(diào)用例程recover_bootinfo(),identify_CPU(),create_pagetables() 。這些例程也定在locore.s之中 。這些例程的功能如下:recover_bootinfo
這個例程分析由引導程序傳送給內(nèi)核的參數(shù) 。引導內(nèi)核有3種方式:由loader引導(如前所述), 由老式磁盤引導塊引導,無盤引導方式 。這個函數(shù)決定引導方式,并將結(jié)構(gòu)struct bootinfo存儲至內(nèi)核內(nèi)存 。identify_CPU 這個函數(shù)偵測CPU類型,將結(jié)果存放在變量_cpu中 。create_pagetables 這個函數(shù)為分頁表在內(nèi)核內(nèi)存空間頂部分配一塊空間,并填寫一定內(nèi)容 下一步是開啟VME(如果CPU有這個功能):
testl$CPUID_VME, R(_cpu_feature)
jz 1f
movl%cr4, 陎
orl $CR4_VME, 陎
movl陎, %cr4
然后,啟動分頁模式:/* Now enable paging */
movlR(_IdlePTD), 陎
movl陎,%cr3/* load ptd addr into mmu */
movl%cr0,陎/* get control Word */
orl $CR0_PE|CR0_PG,陎 /* enable paging */
movl陎,%cr0/* and let's page NOW! */
由于分頁模式已經(jīng)啟動,原先的實地址尋址方式隨即失效 。
隨后三行代碼用來跳轉(zhuǎn)至虛擬地址:pushl$begin
/* jump to high virtualized address */
ret
/* 現(xiàn)在跳轉(zhuǎn)至KERNBASE,那里是操作系統(tǒng)內(nèi)核被鏈接后真正的入口 */
begin:
函數(shù)init386()被調(diào)用;隨參數(shù)傳遞的是一個指針,指向第一個空閑物理頁 。
隨后執(zhí)行mi_startup() 。init386是一個與硬件系統(tǒng)相關(guān)的初始化函數(shù),mi_startup()是個與硬件系統(tǒng)無關(guān)的函數(shù)(前綴'mi_'表示Machine Independent,不依賴于機器) 。內(nèi)核不再從mi_startup()里返回;調(diào)用這個函數(shù)后,內(nèi)核完成引導:sys/i386/i386/locore.s:
movlphysfree, %esi
pushl%esi/* 送給init386()的第一個參數(shù) */
call_init386/* 設置386芯片使之適應Unix工作 */
call_mi_startup /* 自動配置硬件,掛接根文件系統(tǒng),等 */
hlt /* 不再返回到這里! */
1.7.1 init386()init386()定義在sys/i386/i386/Machdep.c中,它針對Intel 386芯片進行低級初始化 。loader已將CPU切換至保護模式 。loader已經(jīng)建立了最早的任務 。譯者注: 每個"任務"都是與其它“任務相對獨立的執(zhí)行環(huán)境 。
任務之間可以分時切換,這為并發(fā)進程/線程的實現(xiàn)提供了必要基礎 。對于Intel 80x86任務的描述,在這個任務中,內(nèi)核將繼續(xù)工作 。在討論其代碼前,我將處理器對保護模式必須完成的一系列準備工作一并列出:

推薦閱讀