其中bootsect.S是生成引導(dǎo)扇區(qū)的匯編源碼,它完成加載動(dòng)作后直接跳轉(zhuǎn)到setup.S的程序入口。setup.S的主要功能就是將系 統(tǒng)參數(shù)(包括內(nèi)存、磁盤等,由BIOS返回)拷貝到特別內(nèi)存中,以便以后這些參數(shù)被保護(hù)模式下的代碼來讀取。此外,setup.S還將video.S中的 代碼包含進(jìn)來,檢測和設(shè)置顯示器和顯示模式。最后,setup.S將系統(tǒng)轉(zhuǎn)換到保護(hù)模式,并跳轉(zhuǎn)到 0x100000。
那么0x100000這個(gè)內(nèi)存地址中存放的是什么代碼?而這些代碼又是從何而來的呢?
0x100000這個(gè)內(nèi)存地址存放的是解壓后的內(nèi)核,因?yàn)镽ed Hat提供的內(nèi)核包含了眾多驅(qū)動(dòng)和功能而顯得比較大,所以在內(nèi)核編譯中使用了“makebzImage”方式,從而生成壓縮過的內(nèi)核,在RedHat中內(nèi) 核常常被命名為vmlinuz,在Linux的最初引導(dǎo)過程中,是通過"arch/i386/boot/compressed/"中的head.S利用 misc.c中定義的decompress_kernel()函數(shù),將內(nèi)核vmlinuz解壓到0x100000的。
當(dāng)CPU跳到0x100000時(shí),將執(zhí)行"arch/i386/kernel/head.S"中的startup_32,它也是vmlinux 的入口,然后就跳轉(zhuǎn)到start_kernel()中去了。start_kernel()是"init/main.c"中的定義的函 數(shù),start_kernel()中調(diào)用了一系列初始化函數(shù),以完成kernel本身的設(shè)置。start_kernel()函數(shù)中,做了大量的工作來建立 基本的Linux核心環(huán)境。如果順利執(zhí)行完start_kernel(),則基本的Linux核心環(huán)境已經(jīng)建立起來了。
在start_kernel()的最后,通過調(diào)用init()函數(shù),系統(tǒng)創(chuàng)建第一個(gè)核心進(jìn)程,啟動(dòng)了init過程。而核心進(jìn)程init()主要 是來進(jìn)行一些外設(shè)初始化的工作的,包括調(diào)用do_basic_setup()完成外設(shè)及其驅(qū)動(dòng)程序的加載和初始化。并完成文件系統(tǒng)初始化和root文件系 統(tǒng)的安裝。
當(dāng)do_basic_setup()函數(shù)返回init(),init()又打開了/dev/console設(shè)備,重定向三個(gè)標(biāo)準(zhǔn)的輸入輸出文件 stdin、stdout和stderr到控制臺,最后,搜索文件系統(tǒng)中的init程序(或者由init=命令行參數(shù)指定的程序),并使用 execve()系統(tǒng)調(diào)用加載執(zhí)行init程序。到此init()函數(shù)結(jié)束,內(nèi)核的引導(dǎo)部分也到此結(jié)束了
聯(lián)系客服