• 如何使用qemu调试内核


    文件系统

    调试内核需要一个基本的文件系统,我们可以使用简单的 ramdisk来作为这个文件系统,如果,需要测试一些其它应用程序,我们还需要创建一个大一点根文件系统。

    Ramdisk

    也就是内核启动时的initrd.img,可以使用busybox来制作这个小文件系统,源码目录的INSTALL文件有编译和安装的说明。

    • make defconfig
    • make
    • make install : 默认目录 —— _install

    制作initrd.img

    1. 把 busybox拷贝到 initrd根目录,并切换到initrd根目录。

    2. 创建init: ln -s bin/busybox init

    3. 创建系统文件夹:mkdir dev etc proc sys

    4. 配置etc目录

      .创建文件 etc/init.d/rcS,输入如下内容:

    1. #!/bin/sh
    2. mount proc
    3. mount -o remount,rw /
    4. mount -a
    5. clear

         .创建文件 etc/fstab,输入如下内容:

    1. proc /proc proc defaults 0 0
    2. sysfs /sys sysfs defaults 0 0
    3. devtmpfs /dev devtmpfs defaults 0 0

       .创建文件 etc/inittab,输入如下内容:

    1. ::sysinit:/etc/init.d/rcS
    2. ::askfirst:-/bin/sh
    3. ::restart:/sbin/init
    4. ::ctrlaltdel:/sbin/reboot
    5. ::shutdown:/bin/umount -a -r
    6. ::shutdown:/sbin/swapoff -a

    5.创建img 磁盘文件

    find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initrd.img

    磁盘文件系统

    磁盘文件系统同 initrd.img的一个最大区别是需要bootloader,制作磁盘文件系统大概需要这么几个步骤:

    1. 先生成一个有MBR记录的磁盘文件(hda.img),文件系统是ext4,并mount.

    2. 安装grub到磁盘文件。

    3. 下载一个根文件系统(如:debootstrap --arch=i386 focal focal-rootfs)。

    4. 拷贝到磁盘文件,并做好配置。

    文件系统配置

    1:grub: 添加启动程序,设置sda1为rw, 下面的init是systemd的初始化进程。

    linux /boot/bzImage rw text root=/dev/sda1  init=/usr/sbin/init

    2:设置root密码,系统登陆时需要输入的密码

    1. mount hda.img 到 /mnt
    2. chroot, 进入chroot环境。
    3. password root,来设置初始密码。或者使用 useradd 来添加新的登陆账号。

    3: 配置自动登陆,或者其它登陆账号。

    vim lib/systemd/system/getty@.service,修改/sbin/agetty的输入参数.

    添加 -a root[或者其它账号], 实现自动登陆。

    qemu

    使用initrd.img

    qemu-system-x86_64 -kernel bzImage -boot c -m 1024 -initrd initrd.img -append "console=ttyS0, 115200" -serial stdio

    -serial stdio: 把控制台重定向到当前终端,还可以这样来配置控制台:

    "console=ttyS0,115200 console=tty0" -serial file:kernel.log

    使用虚拟机系统的终端,运行日志写到当前目录下的 kernel.log

    使用文件系统

    qemu-system-x86_64 -hda hda.img -chardev stdio,id=terminal,mux=on -device isa-debugcon,iobase=0x402,chardev=terminal -serial chardev:terminal

    qemu + gdb 调试内核

    1:运行qemu命令时,后面添加 "-s -S",这样虚拟机启动后会暂停 ——,如:

    qemu-system-x86_64 ...... -serial stdio -s -S

    2:gdb加载对应内核的vmlinux文件,在gdb命令行输入:

    (gdb) break start_kernel

    (gdb) target remote :1234

    (gdb) c

    3:qemu运行,并停止在 start_kernel处,此时可以使用gdb的命令来单步执行,查看寄存器的值。

    4:qemu在运行期间,也可以中断gdb,设置新的断点。

    附录一: 创建磁盘文件系统的shell脚本

    来源于网络,略作修改。

    1. #!/bin/bash
    2. # Echo commands to stdout as they execute.
    3. set -x
    4. set -eE
    5. clean () {
    6. rm .hda.img || true
    7. sudo umount tmpmnt || true
    8. rm -rf tmpmnt || true
    9. sudo losetup -d ${HDA_LOOP_DEV} || true
    10. }
    11. clean
    12. # Create an empty 1G disk image, 自行调整大小。
    13. truncate -s1G .hda.img
    14. /sbin/parted -s .hda.img mktable msdos
    15. /sbin/parted -s .hda.img mkpart primary ext4 1 "100%"
    16. /sbin/parted -s .hda.img set 1 boot on
    17. HDA_LOOP_DEV=$(sudo losetup -Pf --show .hda.img)
    18. FS_LOOP_DEV="${HDA_LOOP_DEV?}p1"
    19. sudo mkfs -t ext4 -v "${FS_LOOP_DEV?}"
    20. mkdir tmpmnt
    21. sudo mount "${FS_LOOP_DEV?}" tmpmnt
    22. sudo chown -R ${USER?} tmpmnt
    23. #安装grub
    24. mkdir -p tmpmnt/boot/grub
    25. echo "(hd0) ${HDA_LOOP_DEV?}" >tmpmnt/boot/grub/device.map
    26. sudo grub-install -v --directory=/usr/lib/grub/i386-pc \
    27. --boot-directory=tmpmnt/boot ${HDA_LOOP_DEV?} 2>&1
    28. cat >tmpmnt/boot/grub/grub.cfg <<EOF
    29. serial
    30. terminal_input serial
    31. terminal_output serial
    32. set root=(hd0,1)
    33. linux /boot/bzImage rw root=/dev/sda1 init=/usr/sbin/init
    34. boot
    35. EOF
    36. #拷贝内核和文件系统,修改为自己提供内容
    37. cp bzImage tmpmnt/boot/bzImage
    38. # Download a basic Debian system
    39. if [ ! -d focal-rootfs ]; then
    40. sudo debootstrap --arch=i386 focal focal-rootfs
    41. fi
    42. sudo cp -av focal-rootfs/* tmpmnt/
    43. mv .hda.img hda.img
    44. clean

     ---
    欢迎大家来我的公众号交流: 般若程序蝉

  • 相关阅读:
    如何保持 SSH 会话不中断?
    day10--232.用栈实现队列+ 225. 用队列实现栈+20. 有效的括号+ 1047. 删除字符串中的所有相邻重复项
    基于centos、alpine制作Java JDK基础镜像
    myeclipse 恢复默认工作布局
    Java开发常见英语词汇汇总
    关于SpringSecurity自定义方法权限
    28335之GPIO输入
    《Linux运维实战:基于银河麒麟V10+鲲鹏920CPU部署DM8数据库主备集群》
    【基于MBD开发模式的matlab持续集成(一)】
    容器化:MongoDB
  • 原文地址:https://blog.csdn.net/kartorz/article/details/128137702