重
新编译内核对于学习开发Linux驱动程序来说是必经的过程,但由于目前Linux的发布版数不胜数,且各个发布版都有各自的特色,这也就注定
了在不同的发布版下内核源代码的组织形式和编译方法有少许不同。区别虽然不大,但如果没有相关的了解的确给我们的学习造成很大的阻碍,本人就是因为类似的
原因痛苦地辗转于若干Linux发布版之间摇摆不定(当然并不是只因为编译内核这点破事儿)。经过若干次折磨后我忽然发现其实做Linux平台开发的乐趣
也恰恰于此,征服这些困难的本身就是一种极大的乐趣,只要你有时间、有精力、有勇气就大可以让自己畅游在Linux的世界里,毕竟所有的内核秘密全都以源
代码的形式暴露给你。
废话少说,马上开始,下面将没有一句是废话。
1.
从内核网站上下载到你需要的内核tar包,通常我们总是倾向于下载最新的东东,在我做这个实验的时候,最新的内核版本是2.6.27.7。下载的网站依然是地球人都知道的http://www.kernel.org/
首
页上便提供了若干比较新的内核版本的下载连接。这里需要注意的是每个版本后面都会有若干个符号,例如F V VI C这里F表示Full
Source即完整的源代码,而B则表示Patch
baseline,也就是说他是基于baseline的一个Patch,这个想必大家一定知道Patch和Full
Source的区别,V和VI则分别代表View Patch和View
incremental,这两项对于我们下载内核源代码来说是浮云,没有任何介绍的价值。
2.
因为接下来的工作都设计到根目录操作,所以我们需要先通过sudo
-i命令却换到root权限。获得root权限之后,我们需要把下载下来的内核文件复制到/usr/src/目录下,由于ubuntu默认情况下是不安装
内核源代码的,所以你可以看到目前/usr/src/目录下只有linux-header……这样的目录,也就是说只有一些头文件。现在需要将拷贝过来的
内核源代码压缩包在/usr/src路径下解压,为了方便说明,以我的内核源代码名字linux-2.6.27.7.tar.bz2为例,执行命令tar
-jxvf
linux2.6.27.7.tar.bz2。一坨坨解压log输出过后,你应该会在/usr/src目录下看到一个名字为linux-2.6.27.7
的新目录,这里面便是全部的内核源代码,如果你的目的只是阅读源代码的话便无需再进行后续的步骤。
3.
定制内核。这一步骤的目的是对新的内核进行一定的剪裁和定制,因为通常内核提供了所有的模块和功能,但某些功能模块是我们不需要或者当前发布版不支持的。
我们需要对此进行一定的定制,但通常,我们是无需对配置进行任何改变的,除非你有某些非常特殊的需求。但即使你不改变任何的配置,也最好执行一次这个操作
以生成相关的配置文件。
配置菜单有很多种,在ubuntu下推荐使用图形化的配置菜单,首先进入内核目录cd
/usr/src/linux-2.6.27.7 然后执行make
menuconfig,如果提示错误表示当前并没有安装ncurse库,可以通过命令apt-get install
libncurses5-dev下载安装ncurese库(在CentOS下是yum -y install
libncurses5-dev,如果出现Nothing to do 则使用yum install
ncurses-devel)。也可以适用纯字符的形式进入,命令为make
config,当然还可以进入X窗口模式,命令为make
xconfig,但是这种模式适用qt库,通常ubuntu是默认安装QT库的,如果没有可以通过apt-get install
libqt3-headers libqt3-mt-dev下载。
这里我选择使用make
menuconfig的方式,理由是……“需要理由吗?”。
网 上很多的文章建议在配置中修改General
Setup中的Local version - append to kernel
release这项以添加一些个性化的内核名字,我在最开始学习的时候就是因为没留意这点,搞得后来不得不自己手动把initromfs,config和
System.map等东东改变成自己喜欢的名字。这里强烈建议用一些个性化的名字来标示新内核,因为倘若以后需要编译更多的内核版本我们就可以在启动的
时候清楚的找到自己想要进入的内核,即便以后不编译那么多的版本,在内核后面加上女朋友或者男朋友的名字不也是一件和酷的事情吗?没准遇到哪个不懂得计算
机的朋友还可以吹一下说这个系统是自己开发的之类~~~~ 说远了。
4.
上面步骤完成之后会生成一个对应的.confg文件,接下来的工作就是编译内核,这一步进行之前你需要准备一杯咖啡和一部PSP之类消遣用的东西,因为编
译过程非常漫长。需要说明的是,如果你足够倒霉,在编译过程中突然遇到某些错误,那么最好在重新编译之前运行make
clean命令以清除上一次编译生成的内核文件。(说到这里忽然想到一个问题还没有说,就是在第3步中,如果想要将当前的配置全部清除,也就是说还原到最
初的情况,需要执行 make mrproper命令)。编译内核的命令为make。
5.
第4步骤结束之后我们会发现生成了一个压缩镜像文件bzImage,位于./arch/i386/boot下,make
zImage可以声场一个未经压缩的镜像文件,make过程还生成了大量的内核目标文件,也就是.ko的文件,单独运行make
modules也可以生成这些文件。
6. 将内核模块文件安装,命令为make
modules_install。
7. 安装内核,命令为make
install。
8.
现在检查一下是否生成了initrd镜像文件,目录为/lib/modules/,如果没有则需要生成这个东西,这一部组要执行的命令就与发布版有关了,据
我查得的资料显示redhat与ubuntu就不太一样,在ubuntu下我们需要使用mkinittramfs命令,运行
mkinitramfs -o initrd.img
-2.6.27.7
。
这个地方必须严肃对待,参数版本名字是非常非常必须的,。如果我定制的内核名字叫linux-2.6.27.7kevin那么这个命令我应该这么写
mkinitrdramfs -o initrd.img-2.6.27.7kevin 2.6.27.7kevin.
我的
是qingfeixu V1.0
9.
现在我们已经得到了三个非常重要的文件,分别是System.map,config和vmlinuz,其具体的文件名字是这三个文件名后接上内核版本还有
个性化定制的名字,这三个文件应该已经被拷贝到/boot/路径下,现在我们需要做的工作是在系统引导程序中加入我们新生成的内核,因为没有注册必经是黑
户:)。
用编辑器打开/boot/grub/menu.lst文件,我们可以目前我们内核的加载选项,就是如下形式的一坨:
title Ubuntu 8.04, kernel.....
root ....
kernel ....
root
initrd ...
我们需要照葫芦画瓢地弄出一个来,把这一坨拷贝一下,粘贴在前面,然后修改。
title这一项就是在Ubuntu启动的时候按ESC键进入GRUB加载菜单时候显示的东西,我们可以随心所欲地定制这个标题,比如定制为
My Ubuntu Kernel之类的文字,中文我没有试过。
非常重要的几项是kernel和initrd,我们需要把它设置为我们之前提及到的/boot路径下的那两个文件。
至此大功告成,重新启动之后我们便可以看到我们编译的内核,试验一下,99.99%的概率我们可以成功用我们的新内核引导启动到ubuntu下。