linux-2.6.x内核发布后,与2.6.x内核配套的系统程序并没有相应的来得及更新, 升级过程会碰到很多问题。虽然网上已有很多关于升级到2.6.x文章,但总是有些细节没有作很好的总结,因此撰写本文将我的经验与大家分享一下。我是在虚拟机上将Linux系统从Redhat9.0升级到2.6.5内核,虚拟机软件为:VMware Workstation 4.0.5 build-6030。
准备工作
1、做好重要数据的备份工作,这是一个好习惯。
2、下载最新的2.6.x内核源码包
所有Linux内核的官方版本可以在http://www.kernel.org/ 找到。内核2.6.5 具体的下载地址是:http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.5.tar.gz。
3、升级module-init-tools软件包
要编译与正常运行新的内核你需要升级一些软件包,这些信息在源码目录下的Documentation/Changes文件中,请根据你的实际情况选择升级。
特别要说明的是,因为2.4.x下的modutils工具包已经不在适合新的2.6.x内核, 必需将其升级到module-init-tools工具包.,我下载module-init-tools-3.0.tar.gz源码包的地方是:http://www.kernel.org/pub/linux/kernel/people/rusty/modules/module-init-tools-3.0.tar.gz
接下来, 按照下列步骤安装module-init-tools工具包:
tar -zxvf module-init-tools-3.0.tar.gz
在module-init-tools-3.0目录下,
# configure --prefix=/
# make moveold
# make all install
# ./generate-modprobe.conf /etc/modprobe.conf
命令"make moveold"将把系统原来的modutils工具程序改名为"*.old"(比如,lsmod.old等等). NOTE! 这是非常重要的一步, 千万不要省略. 这将使得你可以继续使用原有的linux-2.4.x系统, 因为在2.4.x系统下, 新的module-init-tools工具包实际上是倚赖原来"*.old"程序来加载内核模块. 如果忘记了这一步也不要紧张, 可以先下载并安装原来的modutils程序包, 然后按照上面的步骤重来一遍就可以了.
新的module-init-tools工具包不再使用原来的/etc/modules.conf配置文件了, 而是使用新的配置文件/etc/modprobe.conf. 因此必需用命令"./generate-modprobe.conf /etc/modprobe.conf"来生成新的配置文件/etc/modprobe.conf.
如果你使用devfs系统你还需要复制modprobe.devfs 到/etc目录下。
当你升级完相关软件包之后,准备工作就算完成了,下面我们将进入到编译阶段。
配置,编译和安装linux-2.6.x内核
2.6的build系统与2.4有很大的不同,实际上是更加简单与方便了。
将linux-2.6.5.tar.gz 复制到 /usr/src/ 下
tar -zxvf linux-2.6.5.tar.gz
cd linux-2.6.5
如果是新内核没有编译过,就不需要用make mrproper 把原来编译产生的垃圾删除
make menuconfig,进入内核选项卡。选择相应的配置时,有三种选择:
Y--将该功能编译进内核
N--不将该功能编译进内核
M--将该功能编译成可以在需要时动态插入到内核中的模块
在编译内核的过程中,最烦杂的事情就是这步配置工作了,很多新手都不清楚到底该如何选取这些选项。实际上在配置时,大部分选项可以使用其缺省值,只有小部分需要根据用户不同的需要选择。选择的原则是将与内核其它部分关系较远且不经常使用的部分功能代码编译成为可加载模块,有利于减小内核的长度,减小内核消耗的内存,简化该功能相应的环境改变时对内核的影响;不需要的功能就不要选;与内核关心紧密而且经常使用的部分功能代码直接编译到内核中。关于这方面,有很多文章,就不作详细介绍了。
其中要注意的是:RH9.0使用的是ext3文件系统,要把ext3 fs编译进内核。如果系统是SCSI硬盘,并且root fs在SCSI硬盘上,配置内核时也要把SCSI装置支持编译进内核。总之,升级后的系统需要什么,就要把相应的内容编译进内核。
· make
· make modules
· make modules_install
· make install
该命令是最近的从2.5.69内核(按照内核发布时间算)开始才有的选项,他可以帮你完成很多东西: (1)把压缩内核映象拷贝到/boot目录下, 并创建相应的System.map符号链接; (2)修改bootloader的配置文件; (3)调用mkinitrd程序创建内核的initrd映象. 对于GRUB而言, 将在/boot/grub/grub.conf配置文件增加如下类似的配置行:
title Red Hat Linux (2.6.5)
root(hd0, 0)
kernel /boot/vmlinuz-2.6.5 ro root=LABEL=/
initrd /boot/initrd-2.6.5.img
注意:一定要先编译并安装模块,再运行make install;否则可能会出现错误,导致升级失败!
修改/boot/grub/grub.conf配置文件。新内核并不识别"root=LABEL=/"这个启动参数, 如果现在你就重新启动新内核的话, 将发生kernel panic错误。因此,必需把这个" LABEL=/"替换成你真实的根分区,就OK了。
如何知道你的根目录""在哪个partition上? 命令为: # df
以下是偶机器的部分输出:
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/hda2 3834496 1609188 2030520 45% /
/dev/hda1 101089 15154 80716 16% /boot
none 46548 0 46548 0% /dev/shm
可见,我的根目录在/dev/hda2上,需要将启动参数改为 "root=/dev/hda2"。
重启便可以看见kernel-2.6.5了。
Kernel 2.6x 编译过程
提要:在Kernel 2.6x和以前的版本的编译方法有点区别,所以就简单的把编译过程写出来,主要是帮助初学Linux的兄弟。
Kernle 2.6x 编译比较简单,最适合我等菜鸟!!
本文是以Redhat为例,内版本是2.6.0-test8
一、下载
http://www.kernel.org
二、解压
1.把下载好的内核放到/usr/src目录中,比如我下载的是linux-2.6.0-test8.tar.bz2
#mv linux-2.6.0-test8.tar.bz2 /usr/src
#tar jxvf linux-2.6.0-test8.tar.bz2
|
2.进入相应的目录编译和安装,进入内核选项设置
#cd linux-2.6.0-test8
#make mrproper
#make menuconfig
|
进入内核选项卡,M是以模快方式编译,*是直接编入内核
至于哪些要编入内核,哪些要编译成模块。在文章管理器和基础讨论区的帖子中都有,自己试着找一找。另外内核中的doc也有相应的文档
3.编译和安装内核
#make
#sudo make install
|
这个过程是编译和安装内核的过程,系统自动为我们做了哪些事?
1]系统会在/usr/src/linux/arch/i386/boot/目录中产生bzImage,并把bzImage复制为vmlinuz-2.6.0-test8到/boot目录中,并创建议vmlinuz-2.6.0-test8的链接vmlinuz;
2]在/boot目录中,系统会产生System.map-2.6.0-test8,以及创建它的链接System.map;
3]在/boot目录中,自动生为initrd-2.6.0-test8.img;
4]修改/etc/grub.conf 文件,加入了新内核的启动项。
[注]经大熊宝宝兄的提示,怕初学的弟兄不明白这个过程,所以就把这个过程详细的写出来,所以我也做了补充。以上的四点都是系统自动安装内核时所做的任务。查看一下/boot目录中的文件以及/etc/grub.conf就明白了。这一点和以往2.4.x不一样的地方。做个比喻就是2.4.x还是半自动的,上面的东西要执行好多个命令,而在2.6.x中,一步就到位,是全自动的!
4.编译和安装模快
#make modules
#make modules_install
|
5.设置/etc/grub.conf,我不用lilo,更确切的来说,我不太懂,所以只能说Grub的设置办法。
为什么要设置这个呢?其实在编译和安装内核的过程中,系统已经自动把新内核的启动项直接添加到了/etc/grub.conf中。当我们不对/etc/grub.conf进行改动,直接启用新内核会发现VFS错误之类的提示。
下面的是我安装后新内核后,没有改动过的/etc/grub.conf
title Fedora Core (2.6.0-test8)
root (hd0,7)
kernel /boot/vmlinuz-2.6.0-test8 ro root=LABEL=/
initrd /boot/initrd-2.6.0-test8.img
title Fedora Core (2.4.22-1.2061.nptl)
lock
root (hd0,7)
kernel /boot/vmlinuz-2.4.22-1.2061.nptl ro root=LABEL=/
initrd /boot/initrd-2.4.22-1.2061.nptl.img
|
改动后的就是
title Fedora Core (2.6.0-test8)
root (hd0,7)
kernel /boot/vmlinuz-2.6.0-test8 ro root=/dev/hda8
initrd /boot/initrd-2.6.0-test8.img
title Fedora Core (2.4.22-1.2061.nptl)
lock
root (hd0,7)
kernel /boot/vmlinuz-2.4.22-1.2061.nptl ro root=LABEL=/
initrd /boot/initrd-2.4.22-1.2061.nptl.img
|
对比改动过的/etc/grub.conf,我们不难发现,我们在新内核2.x中,指定root的根分区所在的位置时,没有用标签LABEL=/,而是用的是真正的分区位置。
请对Linux不太熟的弟兄,不要照搬我的分区设置。如果想知道这方面的,在基础讨论区中,有关于GRUB和分区访问的文章,在文章管理器中也有。
最后还有一点就是如果显示卡原来安装过驱动,就要在新内核中重新安装。比如我用的是NVIDIA的显卡,我下载的是LinuxSir.Org的下载区中,哈兄提供的打过补丁的NVIDIA的驱动。装上就OK了。
对比改动过的/etc/grub.conf,我们不难发现,我们在新内核2.x中,指定root的根分区所在的位置时,没有用标签LABEL=/,而是用的是真正的分区位置。
内核编译问题详解
对于用户,编译一个内核版本需要的不仅是升级内核和软件那么简单。一般来说,编译后的内核都能很好地工作,但是有些功能在初始化时(准确地说是在系统初始化阶段,即init执行rc.sysini和rcx.d时)会失败。失败的情况因人而异,比如有些人在笔记本上安装Red Hat 9.0的USB设备、Iptable和RPM就全部失败,而有些人在安装PCMCIA设备和FireWire设备时会失败。
如果发现某些软件包无法正常工作,可以尝试下载最新的版本或重新编译、安装旧的版本,也可以通过进行一些相应的修改来解决问题。注意请在操作前备份文件。这里将总结一些常见的错误。
典型问题及解决方法
RPM问题
进入编译好的内核后,与RPM相关的命令有些不能使用,并出现下列错误:
rpmdb: unable to join the environment
error: db4 error(11) from dbenv->open: Resource temporarily unavailable
error: cannot open Packages index using db3 - Resource temporarily unavailable (11)
error: cannot open Packages database in /var/lib/rpm
no packages
解决方法是执行“export LD_ASSUME_KERNEL =2.2.25”命令,也可以将其写入/etc/bashrc。
Glibc问题
用户可以升级Glibc标准库的软件包来解决该问题。因为有些发行版,例如Red Hat 9.0上默认安装的Glibc可能是被Red Hat内核小组修改过的。软件包的下载地址是:
ftp://ftp.rpmfind.net/linux/redhat/updates/9/en/os/i386/glibc-2.3.2-27.9.i386.rpm。
可以连同以下几个软件包一起升级:
ftp://ftp.rpmfind.net/linux/redhat/updates/9/en/os/i386/glibc-common-2.3.2-27.9.i386.rpm
ftp://ftp.rpmfind.net/linux/redhat/updates/9/en/os/i386/glibc-devel-2.3.2-27.9.i386.rpm
ftp://ftp.rpmfind.net/linux/redhat/updates/9/en/os/i386/glibc-utils-2.3.2-27.9.i386.rpm
如果使用“rpm -Uvh glibc*”失败,请用命令“rpm -e”先删除旧的Glibc,然后用命令“rpm -Uvh --force glibc*”强制安装。
Hotplug(热插拔)问题
内核对热插拔功能的支持与KMOD内核线程有关。
解决方法是将/etc/rc.sysinit中所有的/proc/ksyms替换为/proc/kallsyms。执行如下命令:
#mv /etc/rc.d/rc.sysinit /etc/rc.d/rc.sysinit.bak
#sed -e 's///proc//ksyms///proc//kallsyms/g' /etc/rc.d/rc.sysinit.bak > /etc/rc.d/rc.sysinit
Sysfs问题
解决方法是:
◆ 建立目录/sys:#mkdir /sys
◆ 在/etc/rc.d/rc.sysinit文件中找到“mount -f /proc”,在其下一行加入“mount -f /sys”。
◆ 同样在/etc/rc.d/rc.sysinit文件中找到“action $"Mounting proc filesystem: " mount -n -t proc /proc /proc”,在其下一行加入“action $"Mounting sysfs filesystem: " mount -n -t sysfs /sys /sys”。
◆ 在/etc/fstab文件中加入“none /sys sysfs defaults 0 0”。
◆ 在/etc/init.d/halt的halt_get_remaining函数中找到“awk '$2 ~ /^//$|^//proc|^//dev/{next}”,改为“awk '$2 ~ /^//$|^//proc|^//sys|^//dev/{next}”。
USB问题
新的2.6.0内核中使用的USB模块大多数已经改名,因此需要修改/etc/rc.sysinit中对USB子系统初始化的代码。将该文件中所有的“keybdev”改为“usbkbd”、“mousedev”改为“usbmouse”、“/proc/bus/usb”改为“/sys/bus/usb”,并在/etc/init.d/halt中进行同样的修改。此外,还要在/etc/rc.sysinit中找到“needusbstorage”,做如下修改:
needusbstorage=
if [ $usb = "1" ]; then
needusbstorage=`LC_ALL=C grep -e "^I.*Cls=08" /sys/bus/usb/devices 2>/dev/null`
action $"Initializing USB 1.1 host controller: " modprobe ohci-hcd 2> /dev/null
action $"Initializing USB HID interface: " modprobe hid 2> /dev/null
action $"Initializing USB keyboard: " modprobe usbkbd 2> /dev/null
action $"Initializing USB mouse: " modprobe usbmouse 2> /dev/null
fi
如果USB总线是2.0的,还需将“ohci-hcd”改为“ehci-hcd”。
Sound问题
声音部分的模块名也改变了。我的笔记本原来的声卡驱动是i810_audio,现在已改为snd-intel8x0。因此需要把下面的内容添加到/etc/modprobe.conf中:
alias char-major-14 soundcore
alias sound snd-intel8x0
alias sound-slot-0 snd-intel8x0
alias snd-card-0 snd-intel8x0
alias sound-service-0-0 snd-mixer-oss
alias sound-service-0-1 snd-seq-oss
alias sound-service-0-3 snd-pcm-oss
alias sound-service-0-8 snd-seq-oss
alias sound-service-0-12 snd-pcm-oss
install snd-intel8x0 /sbin/modprobe --ignore-install sound-slot-0 &&
{ /bin/aumix-minimal -f /etc/.aumixrc -L >/dev/null 2>&1; /bin/true; }
remove snd-intel8x0
{ /bin/aumix-minimal -f /etc/.aumixrc -S >/dev/null 2>&1; /bin/true; };
/sbin/modprobe -r --ignore-remove sound-slot-0
然后执行“modprobe sound”加载声音模块,并使用下列命令检验声卡驱动:
#cat /proc/asound/cards
显示结果如下:
0 [SI7012]: ICH - SiS SI7012
SiS SI7012 at 0xdc00, irq 11
VMware问题
解决方法是:
◆ 将/usr/bin/vmware-config.pl中所有的“/proc/ksyms”替换为“/proc/kallsyms”。使用“sed”命令可以达到这个目的。
◆ 重新运行该脚本,使用内核头文件编译新的内核模块。在编译过程中如发生错误,应该进入/usr/lib/vmware/modules/source,使用下面的命令将vmnet.tar解包:
#tar xvf vmnet.tar
◆ 进入vmnet-only目录修改bridge.c文件。将“atomic_add(skb->truesize, &sk->wmem_alloc);”修改为“atomic_add(skb->truesize, &sk->sk_wmem_alloc);”,并用类似的方式将“protinfo”改为“sk_protinfo”。
◆ 再次把vmnet-only目录用下面的命令重新打包为vmmon.tar:
#tar cvf vmmon.tar vmnet-only。
如果按照上面的操作依旧失败,另一解决方法是到http://ftp.cvut.cz/vmware/下载vmware-any-any-updateXX.tar.gz,将其解压到任何目录下,执行其中的runme.pl。
其它问题
大家也许还会遇到其它问题,但是无论遇上什么问题都可以依照下列步骤尝试解决:
1.内核组件尽可能编译为模块。执行如下命令可以快速重建内核:
#make all modules_install install
2.软件失败的大多数情况是由于模块名已被更改,而/etc/rc.d/rc.sysinit和/etc/rcX.d/*下的脚本却没有修改这些值而导致的。因此,依次修改相关条目可以改进,但是这也需要相当多的背景知识。如果觉得麻烦,可以把所有加载模块的命令集中在/etc/rc.d/rc.local中。例如:
modprobe eth0
modprobe isofs
modprobe loop
modprobe vfat
同时修改/etc/modoribe.conf文件。具体可参见“man modoribe.conf”获得更多的帮助信息。
3.如果想知道某模块变更后的名字,可以首先在“make menuconfig”时找到该选项,选择Help找到它的配置名称(CONFIG_*),然后到源代码相关目录下的makefile中寻找CONFIG_*。一般可以找到obj-$(CONFIG_*)一项,其值就是该模块的名字。