Linux启动过程调试:自定义内核切换根文件系统失败及无发行版内核调试方法咨询
问题分析与解决方案
一、initrd-switch-root失败的原因及修复步骤
你遇到的切换根失败问题,核心原因基本是自定义内核缺少根分区所需的磁盘驱动,或者initramfs没有正确打包这些驱动,导致initrd阶段无法识别/dev/sda3。具体排查和修复步骤如下:
1. 检查自定义内核的磁盘驱动配置
QEMU默认通过IDE控制器挂载你的fedora.qcow2磁盘,所以内核必须包含IDE相关驱动。打开内核配置文件(.config),确认以下选项是否开启:
CONFIG_IDE=y或CONFIG_IDE=m(如果选模块,需确保dracut将其加入initramfs)CONFIG_IDE_GENERIC=yCONFIG_SATA_AHCI=y(若虚拟机磁盘用AHCI模式,不过默认是IDE)- 若之前切换过virtio磁盘模式,需确保
CONFIG_VIRTIO_BLK=y
建议把这些选项设为内置(y),避免initramfs遗漏驱动模块,之后重新编译内核。
2. 重新生成正确的initramfs
你用dracut生成initramfs时,可能没有指定主机专属模式或关联自定义内核的模块路径。尝试用以下命令重新生成:
dracut --hostonly --kver 6.19.0+ --modules "base ide scsi virtio" initramfs-6.19.0+.img
--hostonly:只打包当前QEMU虚拟机需要的驱动,避免冗余同时防止遗漏--kver:明确指定自定义内核版本,确保dracut找到对应模块--modules:强制包含磁盘相关模块组,兜底保障驱动存在
3. 优化cmdline参数
你的root=/dev/sda3是正确的,但可以换成UUID(更可靠,避免设备名变动):
- 启动原Fedora虚拟机,执行
blkid /dev/sda3获取UUID - 将append参数改为
root=UUID=xxx-xxx rw console=ttyS0 nokaslr
另外,确认启动命令没有磁盘参数冲突——如果原虚拟机用了virtio模式,需在自定义内核启动命令中添加-device virtio-blk-pci,drive=hd0,并调整-drive参数为-drive file=~/work/vms/fedora.qcow2,format=qcow2,id=hd0。
二、用空白qcow2启动调试内核的可行性及步骤
完全可以!这种方式适合快速调试内核,无需完整发行版。具体操作如下:
1. 创建空白qcow2并格式化
# 创建空白镜像 qemu-img create -f qcow2 blank.qcow2 10G # 用losetup挂载并格式化(无需启动虚拟机) losetup -fP blank.qcow2 mkfs.ext4 /dev/loop0p1 losetup -d /dev/loop0
2. 制作最小化rootfs(可选,替代发行版)
如果不想安装完整发行版,可用busybox制作极简rootfs:
mkdir rootfs && cd rootfs # 安装busybox工具集 busybox --install -s # 创建必要目录结构 mkdir proc sys dev etc tmp chmod 1777 tmp # 编写init脚本 cat > init << EOF #!/bin/sh mount -t proc none /proc mount -t sysfs none /sys mount -t devtmpfs none /dev exec /bin/sh EOF chmod +x init # 打包成cpio镜像(可直接作为initramfs使用) find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../minimal-initramfs.img
3. 启动调试命令
- 如果用空白qcow2作为根分区:
qemu-system-x86_64 -kernel ~/work/linux/arch/x86_64/boot/bzImage -initrd ~/work/linux/initramfs-6.19.0+.img -append "root=/dev/sda1 rw console=ttyS0 nokaslr" -drive file=blank.qcow2,format=qcow2 -m 2G -s -S -nographic
- 如果直接用busybox的initramfs(无需磁盘):
qemu-system-x86_64 -kernel ~/work/linux/arch/x86_64/boot/bzImage -initrd minimal-initramfs.img -append "console=ttyS0 nokaslr" -m 2G -s -S -nographic
之后在另一个终端运行gdb vmlinux并执行target remote :1234即可开始调试。
内容的提问来源于stack exchange,提问作者babon




