最近在网上看了几个Linux内核编译方面的文章,由于很多这样的帖子,随便看了几个都差不多吧。在我真正自己动手去实践的时候,出现了很多的问题。感觉是不能完全按照别人的方法来,因为你们的当时的机器工作环境可能是不一样的。整个过程曲折坎坷。但是最后还是成功啦!下面我将给出自己的实践过程和注意点。
一,为什么要编译内核?
Linux作为一个自由软件,在广大爱好者的支持下,内核版本不断更新。新的内核修订了旧内核的bug,并增加了许多新的特性。如果用户想要使用这些新特性,或想根据自己的系统度身定制一个更高效,更稳定的内核,就需要重新编译内核。
通常,更新的内核会支持更多的硬件,具备更好的进程管理能力,运行速度更快、 更稳定,并且一般会修复老版本中发现的许多漏洞等,经常性地选择升级更新的系统内核是Linux使用者的必要操作内容。
为了正确的合理地设置内核编译配置选项,从而只编译系统需要的功能的代码,一般主要有下面四个考虑:
(1)自己定制编译的内核运行更快(具有更少的代码)
(2)系统将拥有更多的内存(内核部分将不会被交换到虚拟内存中)
(3)不需要的功能编译进入内核可能会增加被系统攻击者利用的漏洞
(4) 将某种功能编译为模块方式会比编译到内核内的方式速度要慢一些
二,内核编译模式
要增加对某部分功能的支持,比如网络之类,可以把相应部分编译到内核中(build-in),也可以把该部分编译成模块(module),动态调用。如果编译到内核中,在内核启动时就可以自动支持相应部分的功能,这样的优点是方便、速度快,机器一启动,你就可以使用这部分功能了;缺点是会使内核变得庞大起来,不管你是否需要这部分功能,它都会存在,这就是Windows惯用的招数,建议经常使用的部分直接编译到内核中,比如网卡。如果编译成模块,就会生成对应的.o文件,在使用的时候可以动态加载,优点是不会使内核过分庞大,缺点是你得自己来调用这些模块。
三、新版LINUX内核的获取与更新
linux内核的获取,可以通过购买光盘,从朋友那里拷贝,当然最直接方便的方式是到linux内核官方的网址:http://www.kernel.org上获取最新的版本,另一种就是补丁文件了,即patch文件。他们都是以tar.gz或者tar.bz2形式打包。注意编译内核的时候要求是root权限。以下的编译更新工作就是以root用户实现的。
四、内核配置
我从linux官方网上下载的内核包是:linux-2.6.26.2.tar.bz2,并将其拷贝到我的fc6(内核为2.6.18)下的/usr/src/kernels/目录下。本身我运行的系统的内核源码就在这个目录下名字为(2.6.18.1.2798.fc6-i686)。并把新内核包解压,用如下命令
#cp linux-2.6.26.2.tar.bz2 /usr/src/kernels/
#cd /usr/src/kernels/
#tar jvxf linux-2.6.26.2.tar.bz2
# tar cvzf 2.6.18.1.2798.fc6-i686 /*可以把旧的版本备份,可选,以防不测*/
说到这里还要将几个重要的文件,以防万一还是备份一下比较好。(可选)
1.备份内核启动文件/boot
#cd /boot
#tar cvzf boot.tar.gz boot
2.备份系统的头文件
#cd /usr/include
#tar cvzf linux.tar.gz linux
3.备份模块中的库文件
#cd /lib/modules
#tar cvzf 2.6.18.1.2798.fc6.tar.gz 2.6.18.1.2798.fc6
4.备份重要的配置目录
#cd /
#tar cvzf etc.tar.gz etc
接下来便是实际的工作啦。
#cd /usr/src/kernels/linux-2.6.26.2
#make mrproper
该命令确保源代码目录下没有不正确的.o文件以及文件的互相依赖。由于我们使用刚下载的完整的源程序包进行编译,所以本步可以省略。而如果你多次使用了这些源程序编译内核,那么最好要先运行一下这个命令。
接下来就是内核编译前的配置了,这一步要细心。配置的恰当与否与你日后linux的使用有很大的关系。但是绝大多数是只要用默认的配置就可以啦,除非你想要特殊的应用。配置内核一些常用的重要的选项的详解请参考:http://lamp.linux.gov.cn/Linux/kernel_options.html。
配置内核可以根据需要与爱好使用下面命令中的一个:
#make config(基于文本的最为传统的配置界面,不推荐使用)
#make menuconfig(基于文本选单的配置界面,字符终端下推荐使用)
#make xconfig(基于图形窗口模式的配置界面,Xwindow下推荐使用)
#make oldconfig(如果只想在原来内核配置的基础上修改一些小地方,会省去不少麻烦)
这三个命令中,我使用的是#make menuconfig命令,我想这个虽然是文本字符终端的操作,但是作为每个LINUX学习者,要习惯和享受在命令行下的操作。在选择相应的配置时,有必要对三种符号的含义做些解释:
Y--将该功能编译进内核
N--不将该功能编译进内核
M--将该功能编译成可以在需要时动态插入到内核中的模块
如果使用的是make menuconfig,则需要使用空格键进行选取。你会发现在每一个选项前都有个括号, 但有的是中括号有的是尖括号,还有一种圆括号。用空格键选择时可以发现,中括号里要么是空,要么是"*",而尖括号里可以是空,"*"和"M"这表示前者对应的项要么不要,要么编译到内核里;后者则多一样选择,可以编译成模块。而圆括号的内容是要你在所提供的几个选项中选择一项。
正如上面说的,实际上在配置时,大部分选项可以使用其缺省值,只有小部分需要根据用户不同的需要选择。选择的原则是将与内核其它部分关系较远且不经常使用的部分功能代码编译成为可加载模块,有利于减小内核的长度,减小内核消耗的内存,简化该功能相应的环境改变时对内核的影响;不需要的功能就不要选;与内核关心紧密而且经常使用的部分功能代码直接编译到内核中。
五、内核与内核模块编译
1.进入新内核源代码目录
#cd /usr/src/kernels/linux-2.6.26.2
2.读取配置过程中生成配置文件,创建对应于配置的依赖关系树,从而决定哪些需要编译与哪些不需要编译
#make dep
3.完全删除上步留下来的文件,避免发生错误。(如果是新下载内核没有编译过,可以跳过)
#make clean
4.编译内核
#make bzImage
在上面的命令成功编译以后会在/usr/src/kernels/linux-2.6.26.2/arch/x86/boot/
目录下产生新内核的映像bzImage
5.编译可加载内核模块
#make modules
6.把生成的模块拷贝到需要的目录下
#make modules_install
7.生成模块间的依赖关系,这样在启动新内核以后,使用modprobe命令加载模块时候能够正确定模块。
#depmod -a
注意第5-7步,只有在进行内核配置时候选上了Enable loadable module support (CONFIG_MODULES)才是必要的。
经过以上的步骤终于生成了新的内核和模块,为了能够使用上新版内核,还要做以下工作。
#cp /usr/src/kernels/linux-2.6.26.2/System.map /boot
#cp /usr/src/kernels/linux-2.6.26.2/arch/x86/boot/bzImage /boot
#cd /boot
#mv bzImage vmlinuz-2.6.26
注意上面的前面两条命令我没有像网上其他很多是帖子一样覆盖了原来内核的映像和内核符号隐射表。我把新的直接放在/boot下面,这样能在新内核启动不了的情况下,可以启动新内核。(我对这点深有感触,其实我一开始很顺利地编译成功了并且生成了bzImage,可是我把他拷贝错了,拷贝了同目录下的vmlinux,结果启动不起来啦,linux系统就进不了,后来我进了grub的命令行找到了旧内核映像启动,我们可以发现内核是更新啦,文件系统方面好像是没有什么更新。不知道有没有说错?)
六、修改并重启管理器
我用的grub引导内核的,至于lilo没有用过,不过网上有很多这样的帖子可以参考。下面是我的文件/boot/grub.conf。
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You do not have a /boot partition. This means that
# all kernel and initrd paths are relative to /, eg.
# root (hd0,7)
# kernel /boot/vmlinuz-version ro root=/dev/hda8
# initrd /boot/initrd-version.img
#boot=/dev/hda
default=1
timeout=5
splashimage=(hd0,7)/boot/grub/splash.xpm.gz
hiddenmenu
title Fedora Core (2.6.26.2.fc6)
root (hd0,7)
kernel /boot/vmlinuz-2.6.26 ro root=LABEL=/ rhgb quiet
initrd /boot/initrd-2.6.18-1.2798.fc6.img
title Fedora Core (2.6.18-1.2798.fc6)
root (hd0,7)
kernel /boot/vmlinuz-2.6.18-1.2798.fc6 ro root=LABEL=/ rhgb quiet
initrd /boot/initrd-2.6.18-1.2798.fc6.img
title Windows XP
rootnoverify (hd0,0)
chainloader +1
以上的黑体部分是后加入的,加入后保存该文件。原来的内核启动没有改变,这样在新内核启动失败以后,就可以成功启动旧内核!保留旧内核的启动项,这点很重要哦。接下来再重启电脑期待新内核的启动成功!
Linux内核编译过程在具体实践的时候可能出现很多的问题,只要针对问题各个击破,坚持到底,是一定会有惊喜的!
meilinli88 于 2008-08-22 20:54:01发表:
对内核的剪裁,制作启动光盘,要怎样做呢
dj.dujun 于 2008-08-21 17:11:30发表:
我改过,也没用。没改过我也试过也没用。
dj.dujun 于 2008-08-21 17:09:47发表:
f0rest 于 2008-08-21 13:02:12发表:
kernel /boot/vmlinuz-2.6.18-1.2798.fc6 ro root=LABEL=/ rhgb quiet
中把root=LABEL=/ 改成根目录所在的分区,比如root=/dev/sda5
dj.dujun 于 2008-08-19 16:09:10发表:
忘了告诉您我的邮箱:dj.dujun@163.com 如果您愿意给予解答的话,就按次地址给发个邮件说说吧。拜托!拜托!
dj.dujun 于 2008-08-19 16:04:50发表:
这位高人,偶有个问题想问问你不知是否可抽空给解答一下,偶在升级到2.6.26.2时,配置、编译好了之后为何重启系统时会出现下面的问题呢?
no filesystem could mount root, tried: iso 9660
kernel panic:VFS:unable to mount root fs on unknow-block(0,0)
对于ext3文件系统的支持本人不论是编译进系统也好,还是编译为模块也好,试过多次都同样出现了上面的问题,请问这是为何呀? 多谢能给予解答。