Linux内核编程遇到的最麻烦的问题在于内核崩溃,而崩溃的信息在屏幕一闪而过,特别是AS6(2.6.32-x86_64内核),崩溃之后过3~5秒便会自动重启。这对于远程服务器调试本来是好事情,因为程序员不必跑到机房去亲自按下重启按钮,但是,崩溃信息也找不到了。Kdump是崩溃转储程序,Crash是Kdump转储程序过来的分析程序。默认情况下,Kdump和Crash,以及需要的kexec程序在AS6中已经都有了,我们需要安装的仅仅是kernel-debuginfo和其支持包kernel-debuginfo-common。需要注意的是,由于是内核调试工具,版本号和内核版本号要严格一致!(由于我进行的是内核源码编译与安装,没有这两个工具也能在编译出来的目录中找到vmlinux,不知道没有这两个文件可行不可行)。

    安装完毕,开始进行配置。http://www.dedoimedo.com/computers/kdump.html中有完整的配置方法,特别是编译内核的时候很多选项必须打上(-kdump还是打上比较好,没有打上可能也行),按照默认编译选项,大部分都已经打上标记了。按照教程截图一步一步走,但是有的过程可以省略,因为实在不知道应该怎么配置,呵呵~~

    在/boot/grub/menu.lst/中需要添加这样的参数,即crashkernel=X@Y,其中X是转储空间大小(确切的讲,是转储文件的最大大小),Y是转储的内存偏移。各种参考资料,包括官方给出的资料都是填写128M@16M,但是有的时候,16M偏移的内存已经被占用。这个时候,需要改成32M,相应的,在make menuconfig 时候的编译选项CONFIG_PHYSICAL_START=0x1000000 也需要改成0x2000000。发生内存冲突时候,kdump服务起不来,报错是缺少crashkernel这个启动选项,而官方的文档中的解决方法只是说重新检查这个启动文件的书写,真是很迷惑人。我检查很多次都没有发现问题,最终搜索一下午,在网上的一个bug报告中发现了这个问题,唬人呀!

    在最后的配置过程中,官方文档给出这一步/usr/local/sbin/kexec -l /boot/vmlinuz-`uname -r` --initrd=/boot/initrd-`uname -r`--command-line=  `cat /proc/cmdline` ,而AS6加载的不是initrd,而是initramfs之类的镜像。两种都尝试了一通,结果都没成功。于是干脆不做了,居然没关系!可能是默认配置比较好吧。相关的,后面两个命令kexec -e 和kexec -p 也没法进行。

    此外,AS6中,如果没有手动安装kexec,其目录应该是在/sbin下,而不是官方文档给出的/usr/local/sbin/下面。

    配置完成后,重启,启用kdump服务,如果重启之前执行了chkconfig kdump on ,正常的话,kdump应该是起来的。使用echo c > /proc/sysrq-trigger 命令造成内核panic,会发现关机时候多了个copying data 的过程,下面还有个百分比的进度。Good,kdump起作用了。

    自动重启结束,会发现类似var/crash/(时间戳)/vmcore的文件,这就是崩溃转储文件。可以用crash工具进行查看了。crash的第一个参数是vmlinux的文件,应该是使用debuginfo工具生成的文件/usr/lib/debug/lib/modules/(uname -r)/vmlinux,但是不好使,报错。发现在编译内核的源码目录中也有个vmlinux文件,拿来试试,好使,意外收获,呵呵~~第二个参数就是刚才的那个转储文件vmcore了。log命令可以看到完整的日志,真的很全,其中有IP: [] sysrq_handle_crash+0x16/0x20的信息,sysrq就是刚才触发panic的那个,以及完整的函数调用栈、模块挂载信息等等。不过,这次试验,上面标记了partial dump。可能是我预留的空间太小了,下次把启动选项的X改大一些试试。crash还有很多其他命令,一定要学!

    这次执行完make modules_install make install之后,就进行了崩溃测试。而平时写程序调试的时候是不做这两步操作的,不知道光make之后会不会更新源码中的vmlinux,要是已经更新了就好了,又能省很多时间~~~

    折腾了一天多,还是很有成就感的。这比之前师兄们使用虚拟机调试,然后录屏幕的方法专业多了,而且能够脱离虚拟机,在实机中做,省的那么卡了。O(∩_∩)O哈哈~希望项目调试时候造成的panic也能用这种方法转储~~

    bless!