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程序。
…………



你可能感兴趣的:(linux内核,操作系统)