linux-1.2.13內核的編譯生成和引導

在linux目錄下運行命令 make zimage即生成內核,過程是這樣的。
linux/makefile中有這一句:include arch/$(ARCH)/Makefile,指向了linux/arch/i386/makefile,
其中有目標:
--linux/makefile--
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
zImage: vmlinux
@$(MAKEBOOT) zImage

而vmlinux由linux/arch/i386/boot/makefile生成:
--linux/arch/i386/boot/makefile--
zImage: $(CONFIGURE) bootsect setup compressed/vmlinux tools/build
tools/build bootsect setup compressed/vmlinux $(ROOT_DEV) > zImage


compressed/vmlinux: $(TOPDIR)/vmlinux
@$(MAKE) -C compressed vmlinux

其中壓縮內核compressed/vmlinux必須由子目錄compressed中的makefile的vmlinux目標生成。
--linux/arch/i386/boot/compressed/makefile--
HEAD = head.o
SYSTEM = $(TOPDIR)/vmlinux
OBJECTS = $(HEAD) inflate.o unzip.o misc.o


vmlinux: piggy.o $(OBJECTS)
$(LD) $(ZLINKFLAGS) -o vmlinux $(OBJECTS) piggy.o


piggy.o: $(SYSTEM) xtract piggyback
./xtract $(SYSTEM) | gzip -9 | ./piggyback > piggy.o


SYSTEM的生成又回到linux/makefile中的vmlinux目標:
--linux/makefile--
vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
$(ARCHIVES) \
$(FILESYSTEMS) \
$(DRIVERS) \
$(LIBS) -o vmlinux
$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System.map

由上可知,整個內核生成流程是這樣的:
1、編譯生成未壓縮內核vmlinux
2、./xtract把vmlinux去掉頭部。
3、gzip -9 對vmlinux進行壓縮
4、piggyback給壓縮的內核加上頭部和符號表輸出爲a.out格式的目標文件piggy.o,只包含了1個數據段(壓縮的內核)和符號表,
符號表輸出input_data和input_len(見piggyback.c的代碼),這兩個符號被解壓輔助程序misc.c中的fill_inbuf()函數使用(獲取壓縮數據補充到緩衝區)。
5、compressed/head.o,compressed/inflate.o,compressed/unzip.o,compressed/misc.o,compressed/piggy.o連接爲compressed/vmlinux
6、使用tools/build把bootsect、setup、compressed/vmlinux(去掉頭部)連接爲zImage。


引導過程:
1、計算機自舉將磁盤上的0道0頭1扇區上的bootsect讀入007c:0000,它將自身移動到9000:0000,臨時堆棧設置爲9000:0x4000-12
2、讀入setup扇區到9000:0200開始處,屏幕顯示Loading,把自解壓內核讀入0x10000處,跳轉到9000:0200處運行(setup的代碼)
3、setup進行一些設置(內存、鍵盤、中斷控制器、vga、A20線等),把內核移動到0x1000處,並開啓保護模式,跳轉到0000:1000處執行
4、0000:1000處是compressed/head.S的代碼,它首先將堆棧設置到user_stack[]數組尾端,然後檢查A20是否開啓,BSS段清零,調用
decompress_kernel()進行內核解壓,解壓後的內核位於內存0x100000處,解壓返回後跳轉到0x100000處運行內核代碼(arch/i386/head.S的
startup_32處)
5、head開始也是清BSS段,然後調用setup_idt設置idt,檢查cpu類型,開啓分頁機制,重新裝載gdt和idt,設置堆棧指向init_user_stack[]數組末端,跳轉到linux/init/main.c的start_kernel()運行。流程:start_kernel()->init(),然後調用execve運行init程序。
…………



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章