在各种各样使用Linux的计算机系统中,系统启动的早期阶段,通常都会有这样一个环节,
boot loader程序将内核映像加载到内存中,然后跳转到映像的起始位置开始执行。
接下来,内核就跑起来了。
那么,这个内核映像到底是个什么东东呢。本文就来简单介绍一下Linux内核映像的生成过程。
不当之处,尽请指正。
这其实也就是真正意义上的内核了。系统中实际运行着的内核,其实就是他了。
这是一个elf格式的目标文件。
这个目标文件的入口代码在head.S中。例如,对于arm而言,就是arch\arm\kernel\head.S。
head.S执行到最后,会调用start_kernel(位于init/main.c中),从而进入C代码的世界。
好了,kernel.o虽然是真正的内核,但他不是一下子就能运行起来的。就像火箭的发射需要发射架一样。
kernel.o要想跑起来,也需要再搭几个支架。
接下来的事情,就是一步步地在搭这个架子。
注意,kernel.bin已经不是elf文件了。他里面只有纯粹的指令与数据。
只所以这样做,是因为启动阶段的系统,软件环境很简陋,没有代码来分析elf文件的结构。
要加载一个程序,就是将他拷到内存中某个位置,然后跳到该位置执行。
因此,程序必须经过精心的链接,再去除所有不需要的信息,只留下纯粹的指令与数据。
要将一个elf文件二进制化,通过命令“objcopy -O binary src_file dst_file”即可。
注意,zImage已经不是elf文件了。
b) 对于x86来说,步骤与arm略有不同。
用objcopy工具给 vmlinux 减肥,得到vmlinux.bin(raw binary格式)。
再将bootsect(raw binary格式) 、setup(raw binary格式)与vmlinux.bin拼接到vmlinux.bin前面,得到bzImage。
其中,bootsect对应于arch\i386\boot\bootsect.S,setup对应于arch\i386\boot\setup.S。
这两个文件有什么用呢?
(1) bootsect.S
其实是用于写到软盘的0扇区中(512字节),用于从软盘启动Linux内核。在2.6的内核中,这个文件已经不起作用了。
因此,2.6的内核中如果跑到他,他就简单打印一点错误信息,告诉用户需要由boot loader加载内核。
然后让用户按任意键重启。
而boot loader(例如,grub)在加载内核后,并没有跳转到内核映像起始位置执行,而是跳过了前面的512字节,即跳过了bootsect.S的内容。
(2) setup.S
一般来说,如果是从arm u-boot环境启动。u-boot会将单板基本硬件信息放到一个特定位置,然后内核可以由此获取硬件信息。
而对于pc机来说,则是由setup.S来获取(通过bios)基本硬件信息,放到合适的位置,然后内核再由此获取硬件信息。
如果安装内核的话,新编译的bzImage将被拷贝到类似/boot/vmlinuz-2.6.18-194.el5这样的路径,后者的路径则有可能同时再被更新到/boot/vmlinuz软链接中。这样一来,/boot/vmlinuz总是指向系统中最新安装的内核。
原文:http://blog.csdn.net/crazycoder8848/article/details/19156503