QEMU + Buildroot 调试环境
一、目标
零硬件搭建一个完整的嵌入式 Linux 开发环境:
- ARM vexpress-a9 / aarch64 virt
- 自定义内核
- 自定义 rootfs
- 远程调试(gdb + gdbserver)
- 文件共享(NFS / 9p)
二、安装依赖
# Ubuntu / Debian
sudo apt install -y \
build-essential git curl wget \
libncurses5-dev libncurses-dev \
flex bison \
libssl-dev \
bc \
rsync cpio \
device-tree-compiler \
u-boot-tools mtools dosfstools \
genisoimage \
qemu-system-arm qemu-user-static \
gdb-multiarch
三、Buildroot 方式(推荐)
1. 下载
git clone https://git.buildroot.net/buildroot
cd buildroot
git checkout 2024.02
2. 使用现成 defconfig
make qemu_arm_vexpress_defconfig
make menuconfig
# 主要调整:
# Filesystem images → [*] ext2/3/4 root filesystem
# Filesystem images → [*] cpio the root filesystem (for use as an initial RAM filesystem)
make -j$(nproc)
3. 输出
output/
├── images/
│ ├── rootfs.ext4 # 根文件系统
│ ├── rootfs.cpio # 初始 RAM disk
│ ├── vmlinux # 内核 ELF
│ ├── zImage # ARM 压缩内核
│ └── vexpress-v2p-ca9.dtb # 设备树
└── host/
└── bin/
└── arm-buildroot-linux-uclibc-gcc # 工具链
四、QEMU 启动
1. 直接内核 + initramfs
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-kernel output/images/zImage \
-dtb output/images/vexpress-v2p-ca9.dtb \
-initrd output/images/rootfs.cpio \
-append "console=ttyAMA0,115200" \
-nographic
2. 内核 + 硬盘镜像
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-kernel output/images/zImage \
-dtb output/images/vexpress-v2p-ca9.dtb \
-drive file=output/images/rootfs.ext4,if=sd,format=raw \
-append "console=ttyAMA0,115200 root=/dev/mmcblk0 rootfstype=ext4 rootwait" \
-nographic
3. 使用 U-Boot
# 下载
git clone https://source.denx.de/u-boot/u-boot
cd u-boot
make vexpress_ca9x4_defconfig
make CROSS_COMPILE=arm-linux-gnueabihf-
cd ..
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-kernel u-boot/u-boot \
-nographic
U-Boot 交互:
=> setenv bootargs "console=ttyAMA0,115200 root=/dev/mmcblk0 rootfstype=ext4 rootwait"
=> setenv bootcmd "load mmc 0:1 ${loadaddr} zImage; load mmc 0:1 ${fdt_addr_r} vexpress-v2p-ca9.dtb; bootz ${loadaddr} - ${fdt_addr_r}"
=> saveenv
=> boot
五、qemu-user 模拟用户态
# 单个程序
qemu-arm ./myapp
qemu-aarch64 ./myapp
# chroot
sudo qemu-arm-static -B /path/to/rootfs /bin/sh
六、网络配置
1. 用户网络(默认)
qemu-system-arm ... -net nic -net user,hostfwd=tcp::2222-:22
# 主机 ssh -p 2222 ...
2. tap 网络(高级)
# 创建 tap
sudo ip tuntap add dev tap0 mode tap user $USER
sudo ip link set tap0 up
sudo ip addr add 192.168.1.1/24 dev tap0
qemu-system-arm ... -net nic -net tap,ifname=tap0,script=no
# QEMU 中配置 eth0: 192.168.1.2
七、远程调试
1. QEMU 启动 + gdb server
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-kernel zImage \
-dtb vexpress-v2p-ca9.dtb \
-initrd rootfs.cpio \
-append "console=ttyAMA0,115200" \
-nographic \
-gdb tcp::1234 \
-S # 启动时暂停
2. 主机 GDB
arm-linux-gnueabihf-gdb vmlinux
(gdb) target remote :1234
(gdb) b start_kernel
(gdb) c
八、9p 文件共享(推荐)
# 主机:创建 rootfs_overlay
mkdir -p rootfs_overlay/root/myapp
arm-linux-gnueabihf-gcc -o rootfs_overlay/root/myapp/main main.c
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-kernel zImage -dtb vexpress-v2p-ca9.dtb \
-drive file=rootfs.ext4,if=sd,format=raw \
-append "..." \
-virtfs local,path=rootfs_overlay,mount_tag=hostshare,security_model=none \
-nographic
# 目标机内
mount -t 9p -o trans=virtio hostshare /mnt
九、NFS 根文件系统
1. 主机配置 NFS
sudo apt install nfs-kernel-server
echo "/path/to/rootfs 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)" | sudo tee -a /etc/exports
sudo exportfs -a
2. 启动 QEMU
qemu-system-arm \
-M vexpress-a9 -m 512M \
-kernel zImage -dtb vexpress-v2p-ca9.dtb \
-append "root=/dev/nfs ip=dhcp nfsroot=192.168.1.10:/path/to/rootfs,tcp,v3 console=ttyAMA0,115200" \
-net nic,model=lan9118 \
-net tap,ifname=tap0 \
-nographic
十、使用 Buildroot 的 cpio 自动重载
修改 rootfs_overlay 后:
make # 重新生成 rootfs.cpio
# 启动
qemu-system-arm ... -initrd output/images/rootfs.cpio
十一、调试技巧
1. 启动快
echo 0 > /proc/sys/kernel/printk # 减少启动日志
2. 监视 QEMU
- 添加
-monitor stdio进入 QEMU monitor info qtree、info mtree- 模拟寄存器:
system_reset、gpa2hva
3. 串口转发到文件
qemu-system-arm -serial file:serial.log ...
十二、推荐 QEMU 命令模板
保存为 run.sh:
#!/bin/bash
set -e
cd $(dirname $0)
qemu-system-arm \
-M vexpress-a9 \
-m 512M \
-kernel output/images/zImage \
-dtb output/images/vexpress-v2p-ca9.dtb \
-drive file=output/images/rootfs.ext4,if=sd,format=raw \
-append "console=ttyAMA0,115200 root=/dev/mmcblk0 rootfstype=ext4 rootwait" \
-nographic \
"$@"
chmod +x run.sh
./run.sh