You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

自定义Linux内核启动调试时initrd切换根失败问题及无发行版镜像启动调试咨询

自定义Linux内核启动调试时initrd切换根失败问题及无发行版镜像启动调试咨询

一、initrd-switch-root.service启动失败问题排查

从你提供的错误日志来看,initramfs已成功加载并触发了切换根分区的流程,但最终执行失败。以下是针对性的排查方向和解决方法:

1. 检查initramfs是否包含根分区必需的核心模块

switch-root失败最常见的原因是initramfs缺少根分区的文件系统驱动磁盘控制器驱动,导致无法正常挂载根设备:

  • 先确认根分区的文件系统类型:在原Fedora VM中执行 blkid /dev/sda3,查看TYPE字段(Fedora默认使用XFS文件系统)。
  • 对比原系统与自定义initramfs的模块差异:
    # 查看原系统initramfs的关键模块
    lsinitrd /boot/initramfs-$(uname -r).img | grep -E "(xfs|virtio|ide)"
    # 查看自定义initramfs的关键模块
    lsinitrd ~/work/linux/initramfs-6.19.0+.img | grep -E "(xfs|virtio|ide)"
    
    如果自定义initramfs缺少对应模块,需重新生成并指定包含必要模块:
    # 先确保自定义内核模块已安装到系统模块目录
    make modules_install -C ~/work/linux
    # 用dracut生成包含核心模块的initramfs
    dracut --kver 6.19.0+ --modules "base systemd xfs virtio_blk virtio_pci" --force ~/work/linux/initramfs-6.19.0+.img
    
    注:如果原Fedora VM使用IDE磁盘接口(未指定if=virtio),需将virtio_blk替换为ide_disk模块。

2. 验证root设备路径的可靠性

虽然你确认原系统根分区是/dev/sda3,但自定义内核的驱动加载顺序可能导致设备命名变化。建议使用UUID指定root设备(避免命名漂移):

  • 在原Fedora VM中获取根分区UUID:blkid /dev/sda3,复制类似UUID=abcdef-1234-xxxx的字符串。
  • 修改QEMU启动参数的-append字段:
    -append "root=UUID=abcdef-1234-xxxx rw console=ttyS0 nokaslr selinux=0"
    
    同时添加selinux=0临时关闭SELinux(Fedora默认启用SELinux,自定义内核可能未适配SELinux安全标签导致切换失败)。

3. 查看详细错误日志定位根因

在紧急模式下,你可以执行以下命令获取具体失败信息:

# 查看initrd-switch-root服务的详细日志
journalctl -u initrd-switch-root.service
# 查看完整启动日志
journalctl -b
# 查看rdsosreport的诊断信息
cat /run/initramfs/rdsosreport.txt

这些日志会明确告诉你是挂载根分区失败、设备不存在,还是权限问题导致无法切换根目录。

4. 确认内核与initramfs版本匹配

确保生成initramfs时使用的内核版本与自定义内核完全一致:

  • 编译内核时,在make menuconfig中设置CONFIG_LOCALVERSION="-+",保证版本号与initramfs的6.19.0+对应。
  • 生成initramfs时必须通过--kver 6.19.0+指定内核版本,避免dracut误使用当前运行系统的内核模块。

二、无发行版镜像启动调试内核的方法

如果你想跳过发行版安装,直接用空白镜像+自定义内核/initramfs调试,可按以下步骤操作:

1. 创建空白qcow2镜像并分区格式化

# 创建10G空白镜像
qemu-img create -f qcow2 minimal-rootfs.qcow2 10G

# 构建临时busybox initramfs用于分区
mkdir -p busybox-initramfs/{bin,proc,sys,dev}
curl -O https://busybox.net/downloads/binaries/1.36.0-x86_64/busybox-x86_64
cp busybox-x86_64 busybox-initramfs/bin/
cd busybox-initramfs/bin && ln -s busybox sh && cd -
echo '#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs devtmpfs /dev
exec /bin/sh' > busybox-initramfs/init
chmod +x busybox-initramfs/init
# 打包成initramfs镜像
cd busybox-initramfs
find . -print0 | cpio --null -ov --format=newc | gzip > ../busybox-initramfs.img
cd ..

# 启动QEMU进行分区格式化
qemu-system-x86_64 -drive file=minimal-rootfs.qcow2,format=qcow2,if=virtio \
  -initrd busybox-initramfs.img -m 2G -nographic

在QEMU的shell中执行分区格式化:

# 用fdisk创建主分区
fdisk /dev/vda
# 按n创建新分区,接受默认参数,最后按w保存退出
# 格式化分区为ext4
mkfs.ext4 /dev/vda1

2. 构建最小可启动根文件系统

基于busybox构建满足内核启动需求的最小根文件系统:

mkdir -p minimal-rootfs/{bin,sbin,etc,proc,sys,dev,root,tmp,mnt}
cp busybox-x86_64 minimal-rootfs/bin/
cd minimal-rootfs/bin
# 为所有busybox支持的命令创建软链接
for cmd in $(./busybox --list); do
  ln -s busybox $cmd 2>/dev/null
done
cd -

# 创建init脚本,实现挂载根分区并进入shell
echo '#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs devtmpfs /dev
mount /dev/vda1 /mnt
exec switch_root /mnt /bin/sh' > minimal-rootfs/init
chmod +x minimal-rootfs/init

# 将根文件系统写入qcow2镜像
sudo losetup -fP --show minimal-rootfs.qcow2
sudo mount /dev/loop0p1 /mnt
sudo cp -r minimal-rootfs/* /mnt/
sudo umount /mnt
sudo losetup -d /dev/loop0

3. 启动调试最小系统

使用以下QEMU命令启动并调试自定义内核:

qemu-system-x86_64 -kernel ~/work/linux/arch/x86_64/boot/bzImage \
  -append "root=/dev/vda1 rw console=ttyS0 nokaslr" \
  -drive file=minimal-rootfs.qcow2,format=qcow2,if=virtio \
  -m 2G -s -S -nographic

在另一个终端启动gdb调试:

gdb ~/work/linux/vmlinux
(gdb) target remote :1234
(gdb) b start_kernel  # 可选:在start_kernel设置断点
(gdb) c

这样你就能完整调试内核启动流程,直到进入根文件系统的shell。


额外调试技巧

  • 在内核启动参数中添加init=/bin/sh,跳过initramfs的switch-root流程,直接进入initramfs的shell,验证是否能手动挂载根分区:
    -append "root=/dev/sda3 rw console=ttyS0 nokaslr init=/bin/sh"
    
    如果手动挂载失败,会直接提示缺少模块或设备不存在,可快速定位问题。
  • 使用-drive if=virtio明确指定QEMU使用virtio磁盘接口,virtio驱动在QEMU中性能更好,且内核对virtio的支持更稳定。

火山引擎 最新活动