这里在实践角度上对日常内核编译更新过程进行讲述。

预备内容

下载内核

内核源代码能够在下面的 kernel.org FTP站点找到。有许多的站点分散在世界各地。

  • ftp.uk.kernel.org
  • ftp.us.kernel.org
  • ftp.de.kernel.org

你还可以在主站点 www.kernel.org 上面找到这些站点的更多的信息。

假设这里下载的内核是: linux-2.6.31.6.tar.bz2

编译内核

解压

$cp linux-2.6.31.6.tar.bz2 /home/quietheart/kernelSrc/
$cd $_
$tar -xjvf linux-2.6.31.6.tar.bz2

这样在 /home/quietheart/kernelSrc/ 下面会生成一个 linux-2.6.31.6/ 目录。目录里面的 README 最好看看。

配置内核

cp /boot/config-`uname -r` ./.config

这里,使用当前工作内核的配置文件做为新内核配置文件的基础。另外注意,使用 make xxx_config ,配置内核之前,应该先把 ./config 文件移走(备份)。

编译

具体按照后面的过程进行相应的编译,即可对当前使用系统内核及模块更新。

编译过程实践

在源代码里面运行配置命令(失败)

$make O=/home/quietheart/kernelSrc/build/ menuconfig

提示缺少 ncurses-devel :

'make menuconfig' requires the ncurses libraries.

安装缺失的库

$sudo apt-get install libncurses5-dev

ncurses 不仅仅封装了底层终端功能,而且提供了一个相当稳固的工作框架(Framework)可以在字符模式下产生美观的界面。

再次运行配置命令

$make O=/home/quietheart/kernelSrc/build/ menuconfig

这样生成的内容都在指定的目录 /home/quietheart/kernelSrc/build 中。

开始配置,配置的时候可以在选项上面按 ? 查看该选项的相关帮助信息,另外从 README 中知道需要注意的是:

  • 一些不需要的驱动会使内核变得更大,并且在一些时候会导致问题:例如寻找一个不存在的控制卡可能会让你的其他的控制卡产生问题。
  • 编译内核的时候 Processor type 被设置为比386更高,这会导致内核在386的处理器上面无法工作。
  • 一个内核如果在编译的时候具有math-emulation(和数学相关的特性),将会在coprocessor存在的时候仍然使用coprocessor:这时候math emulation将不会被使用到。
  • 这样内核会有一点大,但是将会工作在不同的机器上,这些机器可以有 math coprocessor 也可以没有。
  • kernel hacking 配置细节一般会导致内核更大更慢,甚至会导致内核不稳定,这些通过配置一些函数来主动地打断不好的代码来寻找内核的问题( kmalloc() )。

所以,对于一些 development, experimental, 或者 debugging 特性的问题,你应该回答 n.

编译内核

$make O=/home/quietheart/kernelSrc/build/

这里,我稍微计时了一下,从下午7:32到8:41.一个多小时。进入 build 目录查看,发现有一个 vmlinux 100多兆很大,上网查查看,原来内核镜像是 build 中的 arch/i386/boot/bzImage ,在我的机器上,这只是一个链接,指向位置是: ../../x86/boot/bzImage ,另外还有一个重要的文件就是 build 下的 System.map.

安装模块

我原来的机器的下面一个 /lib/modules/2.6.28-11-generic ,据说要把它备个份:

#cd /lib/modules/
#mkdir bak
#cd bak && tar -czvf 2.6.28-11-generic.tgz ../

这样在 bak 目录下面生成一个备份。文件100多兆,备份压缩的25M。

然后试试直接安装模块,如果采用的相同名字则应该先删掉 /lib/modules/2.6.28-11-generic ,不过先试试看,这一步比较危险:

#cd /home/quietheart/kernelSrc/linux-2.6.31.6
#make O=/home/quietheart/kernelSrc/build/ modules_install install

这一步在 /lib/modules/ 生成了 2.6.31.6myTestLocalVersion 目录(580多兆),原来的目录还存在;

另外在 /boot 生成了 System.map-2.6.31.6myTestLocalVersionvmlinuz-2.6.31.6myTestLocalVersionconfig-2.6.31.6myTestLocalVersion 三个文件。

这里前两个文件是编译的时候生成的,应该是 arch/i386/boot/bzImage/build/System.map (奇怪 bzImage 大小稍小), myTestLocalVersion 是配置的时候指定的一个后缀。

设置启动内核

=/boot/grub/menu.lst=增加如下行:

#myownKernel
title           Ubuntu 9.04, kernel 2.6.31-6-generic
#uuid           84511622-f2f2-4ca1-bacc-27addb2f1e39
kernel          /vmlinuz-2.6.31.6myTestLocalVersion root=UUID=79f02483-c01a-4752-9de9-6fb4b276e991 ro quiet splash 
initrd          /initrd.img-2.6.28-11-generic
quiet

这里发现一个小技巧:vim中在数字上面按 [Ctrl]a 可以增加数字值。这样文件系统不用改变,启动的时候选择这个选项就会自动自己编译的内核了。奇怪的是 initrd /initrd.img-2.6.28-11-generic 这里竟然能够成功。据说需要使用 /sbin/mkinitrd 相关命令的,可惜没有这个命令。

其他尝试

下面尝试将 arch/i386/boot/bzImage 替换 vmlinuz-2.6.31.6myTestLocalVersion

#cp build/arch/x86/boot/bzImage /boot/vmlinuz-2.6.31.6-generic

然后增加如下行:

title           Ubuntu 9.04, kernel 2.6.31-6-generic2
#uuid           84511622-f2f2-4ca1-bacc-27addb2f1e39
kernel          /vmlinuz-2.6.31.6-generic root=UUID=79f02483-c01a-4752-9de9-6fb4b276e991 ro quiet splash 
initrd          /initrd.img-2.6.28-11-generic
quiet

这样也能够启动内核。

其它

参考资料:
http://www.arm.linux.org.uk/docs/kerncomp.php
http://linux.chinaunix.net/docs/2006-11-21/3260.shtml