单终端内后台运行QEMU并连接GDB调试的实现方法
问题说明
- 开发场景:卡内基梅隆大学计划明年发射的月球车项目ISIS OBC(星载计算机)飞控软件开发,需在预装全量兼容依赖的Docker容器内完成QEMU仿真+GDB调试,规避高版本GCC不兼容等环境问题
- 现存问题:直接使用
&将QEMU放入后台、或添加-daemonize参数启动时,QEMU的GDB监听服务会完全失效;原有依赖gnome-terminal新开窗口跑QEMU的方案,在无GUI的Docker容器内无法使用 - 目标:单终端窗口内完成QEMU后台启动、GDB连接调试全流程,无需额外GUI终端
故障原因
QEMU配置了-serial stdio参数时会持续占用标准输入输出:
- 直接用
&把QEMU丢后台时,后台进程没有当前tty的读写权限,会收到SIGTTIN信号被内核暂停,GDB服务自然无法正常监听 -daemonize参数会让QEMU主动脱离当前会话、重定向所有文件描述符,很容易打断GDB stub的初始化流程,导致1234端口的监听服务不启动
可直接使用的修复方案
用命名管道(FIFO)给QEMU提供独立的输入通道,彻底解绑QEMU和当前终端tty的关联,不需要新开窗口,完全适配Docker无GUI环境。修改后的调试脚本如下:
#!/bin/bash # 启动前先清理残留进程和临时文件 pkill -f iobc-loader 2>/dev/null || true rm -f /tmp/qemu-out /tmp/qemu-in # 创建命名管道作为QEMU的标准输入,避免后台进程读tty被暂停 mkfifo /tmp/qemu-in # 后台启动QEMU,输入走命名管道,输出和错误都重定向到临时文件 ./../obc-emulation-resources/obc-qemu/iobc-loader \ -f sdram build/app.isis-obc-rtos.bin \ -s sdram -o pmc-mclk \ -- -serial stdio -monitor none -s -S \ < /tmp/qemu-in > /tmp/qemu-out 2>&1 & QEMU_PID=$! # 后台实时打印QEMU输出到当前终端,不需要看QEMU串口输出可以删掉这两行 tail -f /tmp/qemu-out & TAIL_PID=$! # 等待QEMU完成GDB端口初始化,启动慢的环境可以把1改成2 sleep 1 # 启动GDB连接调试 ./third_party/gcc-arm-none-eabi-10.3-2021.07/bin/arm-none-eabi-gdb \ -ex='target remote localhost:1234' \ -ex='symbol-file build/isis-obc-rtos.elf' # GDB退出后自动清理所有进程和临时文件 kill $QEMU_PID $TAIL_PID 2>/dev/null || true wait $QEMU_PID $TAIL_PID 2>/dev/null || true rm -f /tmp/qemu-in /tmp/qemu-out clear
注意事项
- 不要给QEMU加
-daemonize参数,这个参数的fork逻辑会干扰GDB服务启动 - 如果不需要在当前终端看QEMU的串口输出,直接删掉
tail -f相关的两行即可,所有输出会保存在/tmp/qemu-out里 - 如果GDB启动时提示
localhost:1234连接失败,把脚本里的sleep 1调大到2-3秒,等QEMU完全启动后再连就行
内容的提问来源于stack exchange,提问作者Henry Howland
相关产品推荐
相关产品推荐

