一次centos7、centos8编译内核后重启老是卡死案例分析

这个问题在centos7.6 和centos8.3都遇到过,以cenots7.6为例。卡死的过程是:centos7.6虚拟机里从红帽官网下载linux-3.10.0-957.27.2.el7内核源码后,按照命令make -j8 all;make modules_install -j8;make install -j8编译内核后重启,直接卡死,必现,什么打印都没有。莫名其妙,一脸懵逼!本文主要记录这个问题的排查和解决过程。

编译内核源码并安装后,在/boot主要生成了两个文件,/boot/vmlinuz-3.10.0 和/boot/initramfs-3.10.0.img,一个是内核镜像一个是内存型文件系统。在内核启动的第一阶段,就要加载并解压initramfs-3.10.0.img,作为根文件系统,做一些检查后才会挂载真正的磁盘根文件系统/dev/sda3(根文件系统在sda3盘)。

调试这个卡死问题就很麻烦,首先这是虚拟机,卡死时调试信息没有。如果要是在开发板调试,内核启动过程调试信息很多,我也可以在内核启动关键阶段添加调试信息,协助定位卡死位置,这些在虚拟机都实现不了!于是想到用qemu调试内核,使用如下命令:

qemu-kvm -nographic -kernel /boot/vmlinuz-3.10.0 -initrd /boot/initramfs-3.10.0.img -append "root=/dev/sda3 init=/init console=ttyS0"

最后打印如下,也卡死了

  1. [    1.203026] NET: Registered protocol family 1
  2. [    1.204665] pci 0000:00:00.0: Limiting direct PCI/PCI transfers
  3. [    1.206685] pci 0000:00:01.0: PIIX3: Enabling Passive Release
  4. [    1.209278] pci 0000:00:01.0: Activating ISA DMA hang workarounds
  5. [    1.212477] Unpacking initramfs...

我不知道是方法不对,还是真的用qemu复现卡死了。不过” Unpacking initramfs...”却给了我一个灵感,我认为编译新内核后生成配套的/boot/initramfs-3.10.0.img有问题,于是跟centos7.6自带的initramfs-3.10.0-957.27.2.el7.x86_64.img解压后对比了一下,没想到还真发现了问题。

解压后,initramfs-3.10.0.img的usr/lib/moduls/3.10/kernel 目录下的ko文件大小总结竟然有100多M,而initramfs-3.10.0-957.27.2.el7.x86_64.img的usr/lib/moduls/3.10.0-957.27.2.el7.x86_64/kernel 目录下的ko文件大小总结只有几十M,小了很多。再进一步查看,initramfs-3.10.0-957.27.2.el7.x86_64.img的usr/lib/moduls/3.10.0-957.27.2.el7.x86_64/kernel目录下的ko竟然被压缩了,是xz格式,如ext4.ko.xz,那怪不得usr/lib/moduls/3.10.0-957.27.2.el7.x86_64/kernel目录下的ko文件占空间少了很多。

我感觉已经找到原因了,在内核启动过程,要解压initramfs-3.10.0.img,而initramfs-3.10.0.img的usr/lib/moduls/3.10/kernel 目录下的驱动ko比正常的大了几倍,难道内存越界了?initramfs大小是有限制的!怎么验证我的想法?

首先,在我们make -j8 all;make modules_install -j8后,在/usr/lib/modules/3.10.0/kernel/目录就会生成本次编译内核的ko文件,在这个目录运行如下脚本会得到所有的ko文件及路径

  1. #bin/bash
  2. function listfiles()
  3. {
  4.         for file in `ls $1`;do
  5.             if [ -d "$1/file" ];then
  6.                     listfiles $1/file
  7.                 else if [ "${file##*.}" == "ko" ];then
  8.                          echo "$1/$file"
  9.                     fi
  10.                 fi
  11.         done
  12. }
  13. listfiles .

有了所有ko的路径,对他们依次执行xz进行压缩,压缩后ko源文件不再保留,比如fs/ext4/ext4.ko变为fs/ext4/ext4.ko.xz。然后再执行make install -j8安装内核,安装过程会把/usr/lib/modules/3.10.0/kernel/目录下已经压缩的ko打包到/boot/initramfs-3.10.0.img。等搞定后reboot重启,终于可以顺利进入控制台了!问题解决。

注意,这个问题在centos8有更好的解决方案,只用内核编译时make menuconfig配置上CONFIG_MODULE_COMPRESS和CONFIG_MODULE_COMPRESS_XZ,在编译安装内核时自动压缩ko为xz格式,然后打包到initramfs镜像,不用人为参与,效率增加了不少!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值