redhat9成功升级至2.6.36内核备忘

来源:互联网 发布:昆山cnc编程培训班 编辑:程序博客网 时间:2024/05/22 02:05

有一台linux服务器使用RH9, 一直没有升级,最近需要装oracle,而且服务器有大量的服务应用,比如ftp,nfs,svn代码仓库,webserver,防火墙配置,LVM1,等等,重装可能更复杂。所以考虑升级了。没想到过程一点都不简单。

首先下载了内核源码,最新版2.6.36,10月20日release的。我们都热爱新版本的软件不是吗:-)

 

首先下载了2个可能用到的软件包,最重要的,module-init-tools-3.12.tar.bz2, mkinitrd-4.2.0.3.tar.bz2,make-3.81或3.82其他不需要。注意,升级gmake在内核的Change中提到了,事实也是,不升级会报一个

经过一番仔细配置,make menuconfig完成。

make,编译内核遇到错误,错误为:

/usr/src/linux-2.6.35.7/arch/x86/include/asm/arch_hweight.h: In function `__arch_hweight32':
/usr/src/linux-2.6.35.7/arch/x86/include/asm/arch_hweight.h:29: parse error before string constant

看看源码,直接修改

/usr/src/linux-2.6.35.7/arch/x86/include/asm/arch_hweight.h:29行,
 : "="REG_OUT (res)

 :"=a" (res)

编译没问题了,看来gcc3.2已经没法编译像"="REG_OUT的合法代码,但Changes中仍然说gcc3.2可以。只能摇头作罢。我在csdn回复了一个网友的提问,他遇到此问题,内核为2.6.35-*。但事实证明,事情没那么简单!后面再说。编译完成后,make modules_install install; reboot,在grub界面选择2.6.36 ......

KERNEL panic!!!!!!!!!!!!      错误如下:

Init[1]: segfault at 21 ip 00000021 sp bf8624d8 orror 4 In init[
8048000+6000]
[    3.785218]  init used greatest stack depth : 6016 bytes left    
[    3.785451]  Kernel panic - not syncing: Attempte to kill init!
[    3.785541]  Pid: 1. comm: init Not tainte 2. 6 .36 #1
[    3.785721]  Call Trace:
[    3.786812]   [(cI1125c96] panic
[    3.786141]   [(cI1127bbc] reparent_leader.             
[    3.786151]   [(cI1127cb5] forget_original_parent
[    3.711631]   [ (c11127d ] exit_notify        
[    3.711631]   [(cI1128I1a] do_exit
[    3.786481]   [(cI112822a] do_group_exit
[    3.786518]   [(cI1132f95] get_signal_to_deliver
[    3.786615]   [(cII111267] do_signal
[    3.786711]   (cllllllc]7]       ?bad_area
[    3.786851]   (c135a674? ] ?do_page_fault
[    3.786691]   (c189]dd8] ? remove_vma
[    3.786911]   [(cI895]d3?] ? remove_vma_list
[    3.787711]   [(cI11958I1] ? do_munmap
[    3.787711]   [(cI35a]4b?] do_page_fault
[    3.787797]   [(cII111277] do_notify_resume
[    3.787798]   [(cI35821le] work_notifysig
[    3.787388]   [(cI35a34b?] do_page_fault

 (不好意思,trace时间和地址都不对,偷个懒ocr后拷贝的,但函数名我手工修改过了).

why!!! 首先这不是initrd和无法加载硬盘的错误,我很熟悉这个。nash mount root成功,我调试了nash源码,switchroot本身都是成功的,switchroot最后一步启动硬盘root分区的/sbin/init后panic。

开始了漫长的探索,虽然差不多一个星期的业余时间,但还是感觉像很久一样,过程中编译了2.6.18, 2.6.24,2.6.32,除了2.6.18成功启动,其他统统panic。网上看到有很多人有同样的错误,都没有解决。但从此我只能用2.6.18的内核吗?我在遇到困难时的心理偏执起了作用,不停的配置-〉编译->配置....   这个堆栈trace给了我很多误导,错误显示因为地址21,ip也是21,由于是init引起的,那就肯定是userspace的指令指针无效,但哪有为21代码段指针。开始以为是虚拟内存分配错误(remove_vma.),最后确定,这个堆栈只显示了内核处理错误地址访问的过程,用户空间如何错的看不出来。写了一个hello world程序,加内核参数init=/sbin/hello,没有打印hello world就panic。改成静态链接试试,竟然看到了hello world!,啊!看来跟动态链接器ld-linux.so有关。再试,下载bash源码,编译成静态链接。加启动参数init=/sbin/bash. 竟然给了我一个shell!!!没有segfault。但任何其他命令,包括ls都segfault 21 ip 21。基本确定动态链接器的问题。但为什么2.6.18的内核以前的没问题呢??一定是2.6.18-2.6.24的某个版本内核做了什么改动引起了动态链接器/或和旧RH9的程序不兼容。由于升级动态链接器需要升级glibc。深知glibc在系统的心脏地位。我可不想惹太大的麻烦。否则宁愿重装系统。那就试试gcc吧。首先找了一个gcc-3.4.6.i386.以及和它依赖的包binutils,libgcc,cpp. 卸载这些包的旧版本时rpm死锁,删除/var/lib/rpm/__db*; rpm --rebuilddb 解决问题。提醒一下,最好同时禁用/etc/cron.daily的rpm。这就是死锁的原因。不然以后还会锁。回到正题,升级gcc后gcc -v显示gcc 3.4.6. ok。然后重新编译内核->安装->重启。竟然成功启动2.6.36内核。

最后修改/etc/rc.sysinit。消除系统启动模块加载错误。创建并移动modprobe.conf到/etc/modprobe.d目录中,配置sysfs,和udev动态/dev系统。至此升级完成。

 

总结一下原因,

1. 2.6.18-2.6.24的某个版本内核的改动引起gcc3.2编译内核产生错误执行代码,非常可能跟VSYSCALL/VDSO的汇编代码有关,或syscall中断调用handler的汇编代码有关。众所周知,加载DSO是个系统调用过程,而linux执行syscall是通过int 0x80来完成的,VSYSCALL的加入提升了系统调用性能。而且VSYSCALL和VDSO都是内核2.6.18-2.6.24之间改动最多的,而且和动态链接过程相关。从而最后导致正常的DSO不能加载,非常奇怪为什么现在的内核不能将VSYSCALL和VDSO作为可选项呢!!而且kernel维护那帮人非常喜欢写一些very trick的代码,尤其是汇编。这本身就非常容易导致编译器在优化代码时产生不期望的结果。

2. 纠其根本原因是gcc3.2有bug,不要忘了刚开始编译我就遇到了一个gcc3.2的bug(arch_hweight.h:29行),以为改好那里就行了。3. 但如果kernel做过详细的测试,适当的改变gcc版本号,再release它的Documents/Changes。人们就可以节省大量的时间。知道该使用哪个版本的Gcc了。
 

为了方便大家升级我列出我所使用的版本,可以按照这个顺序编译/安装/升级。注意:rpm安装前最好卸载旧的对应包。

make-3.81.tar.bz2                                (gmake,必须升级到这个版本,否则编译出错)

mkinitrd-4.2.0.3.tar.bz2                        (为了生产initrd映像,必须升级, 但不一定是这个版本,但需要支持2.6内核的版本)

binutils-2.15.92.0.2-25.i386.rpm           (升级gcc所必须的,根据gcc的版本,要求的这个版本号会有不同)

libgcc-3.4.6-11.i386.rpm                        (升级gcc所必须的,版本和gcc一样)

cpp-3.4.6-11.i386.rpm                           (升级gcc所必须的,版本和gcc一样)

gcc-3.4.6-11.i386.rpm                           (gcc编译器,必须升级,我估计gcc 3.3的就行,不一定要这个版本。网上比较多,所以我用了这个)

module-init-tools-3.12.tar.bz2              (模块工具,安装/卸载/列表 driver的工具, 必须升级,版本号可以根据Changes降低一些,建议一切就绪后再安装这个,升级内核后可能刚开始你无法访问网络,包括拷贝文件进来)

kernel-2.6.36.tar.bz2                            (内核,不说了,必须的,你肯定想要最新版本的)

udev-164.tar.bz2                                  (动态/dev创建守护进程,可选,不会影响内核升级,但会影响使用(内核有devtmpfs),解决热插拔driver的加载问题,比如USB。提醒一下,udev编译所需的依赖是个名副其实的"依赖地狱",没时间的人强烈建议不使用它)

LVM2.2.02.74.tgz                                  (dev-mapper和LVM2,设备映射层和逻辑卷管理器,如果没有LVM卷可选,不会影响内核升级,版本号无所谓,RH9用LVM的没几个人吧!?但我确实用)

原创粉丝点击