Linux 内核编译
环境 Vmware + CentOS4.6
一、下载 Linux 内核源码包
查看当前系统的 linux 内核版本
# uname –r
2.6.9-67.ELsmp
查看 CentOS 发行版版本
# cat /etc/redhat-release
CentOS release 4.6 (Final)
发行版版本信息一般保存在 /etc/issue 文件中,也可以用 cat /etc/issue 命令 查看
Linux内核发布的网站是 http://www.kernel.org ,但需要打补丁。可到 centos网站上,下载带 CentOS补丁的 rpm包。
rpm包有两种,
- Source RPM ( .src.rpm )包含一个 SPEC 文件( .spec ),源码包( .tar.gz, .tar.bz2 ),还有其它的一些源文件和补丁
- Binary RPM ( .i386.rpm, .i686.rpm, .sparc64.rpm ),包括一些已编译文件,文档, 配置文件和 pre/post install/uninstall的脚本。
此处要编译源文件,下载前者。
到 CentOS网站上找到相应的内核版本 kernel-`uname -r`.src.rpm
在 RPMS文件夹中放着 Binary RPM, SPRAMS文件夹中存放着 Source RPM文件。
下载 http://vault.centos.org/4.6/apt/i386/SRPMS.os/kernel-2.6.9-67.EL.src.rpm 到本地系统中。
二、安装 Linux 内核源码树
安装 rpm 包
# rpm -ivh kernel-2.6.9-67.EL.src.rpm
-i 安装, -v 显示安装包的真实名称 * 1 , -h显示安装进度
主要是一个解压的过程。
在 /usr/src/redhat 目录下生成两个文件夹 SOURCES 和 SPECS
# cd /usr/src/redhat/;ls
SOURCES SPECS
- SOURCES 。 SOURCES 存储源代码。
- SPECS 。 SPECS 包含 spec 文件 。
SOURCE S目 录下主要 linux内核源码包 linux-2.6.9.tar.bz2和 1000多个 patch文件及 .config文件。
SPECS目录下包含 kernel-2.6.spec文件
Spec文件可看作 rpm工作的脚本文件。
它包含了软件包的诸多信息,如软件包的名字、版本、类别、 说明摘要、创建时要执行什么指令、安装时要执行什么操作、以及软件包所要包含的文件列表等等。
它主要包括
- 文件头 包括软件包名,版本,开发者等
- %prep 段 这个段是预处理段,通常用来执行一些解开源程序包的命令,为下一步的编译安装作准 备。
- % b uild 段 本段是建立段,所要执行的命令为生成软件包服务,如 make 命令。
- %install 段 本段是安装段,其中的命令在安装软件包时将执行,如 make install 命令。
- %files 段 本段是文件段,用于定义软件包所包含的文件 。
- %changelog 段 修改日志段 。
# cd /usr/src/SPECS
# rpmbuild -bp --target=`uname –m` kernel-2.6.spec
-bp build through %prep (unpack sources and app ly patches) from <specfile>, 从 <specfile> 文件的 %prep 段开始建立(解开源码包并打补丁)。
-bp 命令只执行 %prep 段,解压源码包并打补丁。
执 行完这一步后将会在 /usr/src/redhat/BUILD/kernel-2.6.9/linux-2.6.9 目录下生成完整的内核源码树。
三、 配置 Linux 内 核
将 linux-2.6.9目录链接到 /usr/src/linux
# cd /usr/src/
# ln -s /usr/src/redhat/BUILD/ker nel-2.6.9/linux-2.6.9/ linux
切 换到 linux 目 录下
# cd /usr/src/linux
# vi Makefile
修 改 Makefile 文 件,修改 EXTRAVERSION 选 项,给自己编译的内核盖个戳。
把 当前内核的配置文件拷贝到 linux 目 下下重命名为 .config
# cp /boot/config-`uname – r` .config
.config 文 件本应该用 make menuconfig 来 生成,在本实验中,直接把当前内核的配置信息复制过来。就省去了 make me nuconfig 的麻烦。
# make menuconfig
此 处只是一个流程,选择默认 ,退出。
四、编译内核及内核模块
# make
这 是最主要的一步。 Makefile 的编译流程,
- 使用命令行或者图形界面配置工具,对内核进行裁 减,生成 .config 配置文件
- 保存内核版本信息到 include/linux/version.h
- 产生符号链接 include/asm, 指向实际目录 include/asm-$(ARCH)
- 为最终目标文件的生成进行必要的准备工作
- 递归进入 /init 、 /core 、 /dri vers、 /net、 /lib等目录和其中的子目录来编译生成所有的目标文件
- 链接上述过程产生的目标文件生成 vmlinux , vmlinux 存放在内核代码树的根目录下
- 最后根据 arch/$(ARCH)/Makefile 文件定义的后期编译的处理规则建立最终的映象 bootimage, 包括创建引导记录、准备 initrd 映象和相关处理
五、安装内核
Insert 内核模块,理解是,很多的 insmod 操作 * 2
# make modules_install
安 装内核
# make install
在 boot 目 录下多出了以下 文件
v mlinuz-2.6.9-lunix1.0是可引导的、压缩的内核。
System.map-2.6.9-lunix1.0内核符号表 , Linux内核不使用符号名,而是通过变量或函数的地址来识别变量或 函数名 . 符号表是所有符号连同它们的地址的列表。
关于 initrd-2.6.9-lunix1.0.img 文件
在 /boot/grub/menu.lst 中除了配置 root, kernel还要配置 initrd。 Initrd指定系统启动访问真正的根文件系统前,访问的 ramdisk映象。
initrd***.im g把一段程序打包到 img里,然后在开机的时候在内存里开辟一段区域,一般是 2m,释放到那里运行,都是一些初始化的程序,比如 sisc_mod、 ext3、 sd_mod等模块和 insmod、 nash等命令。不同内核,初始化的 img可以相同,也可以不同,如果没有,可以在 grub.conf里加上 no initrd,它就跳过 initrd的检测和执行了。
它的作用是在没有 mount / 分区以前,系统要执行一些操作,比如挂载 scsi 驱动,它就把 initrd 释放到内存里,作一个虚拟的 / 。
现在解压 initrd, 并查看里面的文件
# mkdir initrd
# cd initrd/
# cp /boot/initrd-2.6.9-lunix1.0.img initrd.gz
# gunzip initrd.gz
# cpio -ivmd < initrd
# ls
bin dev etc init initrd lib loopfs proc sbin sys sysroot
在 initrd 目录中就是系统启动时临时 root 的内容。目录下有一个 init 文件,该文件最为重要,它就是内核启动后执行的第一个脚本。实际 上内核启动后寻找的就是 /init ; bin/init ;/bin/init,找 到任何一个就执行它。整个的初始化从它开始。用 file和 cat命令查看一下
# file init
init: a /bin/nash script text executable
# cat init
#!/bin/nash
mount -t proc /proc /proc
setquiet
echo Mounted /proc filesystem
echo Mounting sysfs
mount -t sysfs non e /sys
echo Creating /dev
mount -o mode=0755 -t tmpfs none /dev
mknod /dev/console c 5 1
mknod /dev/null c 1 3
mknod /dev/zero c 1 5
mkdir /dev/pts
mkdir /dev/shm
echo Starting udev
/sbin/udevstart
echo -n "/sbin/hotplug" > /proc/sys/kernel/hotplug
echo "L oading scsi_mod.ko module"
insmod /lib/scsi_mod.ko
echo "Loading sd_mod.ko module"
insmod /lib/sd_mod.ko
echo "Loading mptbase.ko module"
insmod /lib/mptbase.ko
echo "Loading mptscsi.ko module"
insmod /lib/mptscsi.ko
echo "Loading mptspi.ko module"
insmod /lib/mptspi.ko
echo "Loading mptsas.ko module"
insmod /lib/mptsas.ko
echo "Loading mptscsih.ko module"
insmod /lib/mptscsih.ko
echo "Loading libata.ko module"
insmod /lib/libata.ko
echo "Loading ata_piix.ko module"
insmod /lib/ata_piix.ko
echo "Loading jbd .ko module"
insmod /lib/jbd.ko
echo "Loading ext3.ko module"
insmod /lib/ext3.ko
/sbin/udevstart
echo Creating root device
mkrootdev /dev/root
umount /sys
echo Mounting root filesystem
mount -o defaults --ro -t ext3 /dev/root /sysroot
mount -t tmpfs --bind /dev /sysroot/dev
echo Switching to new root
switchroot /sysroot
umount /initrd/dev
第一行 #!/bin/nash 是一个 redhat 自己的微型解释器。不是 bash 。
它的主要流程是
mount 命令加载各种内核文件系统 proc,sys 等 。
mknod 创建系统启动所必须的 /dev 设备节 点。
insmod 开始安装 scsi 等设 备。
udevstart 开始监听这些设备 。
m krootdev 使它后面的参数 /dev/root成为一个块节点从而使得根分区设备被挂载 ,其中根分区设备由 grub.conf里面的 kernel命令后面所带的参数 root=决定。
mount -o defaults --ro -t ext3 /dev/root /sysroot
加载 /dev/root到 /sysroot下。这时真正的 root才被加载到了系统中。至此 /sysroot下是真正的 root分区。 /是 initrd的内存盘。
switchroot 切换到新的 root,卸载 /dev,/proc,/sys文件系统,寻找新的 init。
六、启动新内核
查看 /boot/grub/menu.lst文件,多了 title CentOS(2.6.9-lunix1.0)设 置为默认启动项。
重新启动 reboot
启动菜单,多了 2.6.9-lunix1.0
用自行编译的内核启动,输入 uname –r显示
* 1 显示操作过程中详细信息
* 2 将新编译内核树中的模块( .ko)文件拷贝到 /lib/modules/<version>下,并做模块相关性处理 (depmod);此时不会做 insmod操作