qemu直接启动内核+内存文件系统+双终端+文件共享+USB直通
author: hjjdebugdate: 2026年 05月 02日 星期六 16:50:42 CSTdescrip: qemu直接启动内核内存文件系统双终端文件共享USB直通文章目录1. qemu 启动脚本文件1.1 脚本解释2 配套的制作根内存文件系统的脚本3 注意事项直接启动内核 内存文件系统 双终端 文件共享 USB 直通适合场景Linux 内核开发,驱动调试,usb驱动调试,嵌入式系统调试这些命令组合,本人花了不少时间来实验和体会. 是一个基础命令1. qemu 启动脚本文件$ cat qemu_run.sh #!/bin/bash qemu-system-x86_64 \-m2G-smp1\-enable-kvm-cpu host \-kernel arch/x86/boot/bzImage \-initrd~/test/rootfs/initramfs.cpio.gz \-appendroot/dev/ram0 consolettyS0 consolettyS1 nokaslr\-serial stdio \-serial telnet:127.0.0.1:5555,serveron,waitoff \-fsdev local,security_modelpassthrough,idhostshare,path/mnt/share \-device virtio-9p-pci,fsdevhostshare,mount_taghost_share \-usb \-device usb-host,vendorid0x067b,productid0x2303\-display none1.1 脚本解释-m2G # 给虚拟机分配2GB 内存-smp1# 给虚拟机分配1个CPU核心,调试时不会乱跳,如果不调试,可以给多个-enable-kvm # 开启Linux KVM 硬件虚拟化速度接近物理机-cpu host # 让虚拟机CPU模型和物理主机完全一致发挥cpu性能-kernel arch/x86/boot/bzImage直接使用编译好的 Linux 内核镜像不需要 ISO / 磁盘镜像适合内核开发 / 调试。-initrd~/test/rootfs/initramfs.cpio.gzinitramfs 是内存文件系统压缩包内核启动后直接把它加载到内存作为根目录不需要硬盘。-appendroot/dev/ram0 consolettyS0 consolettyS1 nokaslr内核启动参数root/dev/ram0告诉内核根文件系统在内存盘对应 initramfs/dev/ram0 是现代写法,代表主设备号1,次设备号0的内存盘.consolettyS0 consolettyS1把内核日志 / 终端输出重定向到两个串口nokaslr关闭内核地址随机化方便内核调试、GDB 跟踪-serial stdio:把串口0直接映射到你当前执行命令的终端内核日志会直接打印在这里-serial telnet:127.0.0.1:5555,serveron,waitoff串口 1 绑定到 localhost:5555serveron: localhost 服务器.你可以用telnet 127.0.0.1 5555 连接服务器,服务器时第二个串口终端设备waitoffQEMU 不用等待 Telnet 连接继续执行在启动脚本中你需要启动第二个shell-fsdev local,security_modelpassthrough,idhostshare,path/mnt/share \-device virtio-9p-pci,fsdevhostshare,mount_taghost_share这是主机和虚拟机共享文件夹的配置主机路径/mnt/share虚拟机挂载标签host_share虚拟机内挂载命令mount -t 9p -o transvirtio host_share /mnt-usb # 开启虚拟机USB控制器-device usb-host,vendorid0x067b,productid0x2303ust-host, USB 直通使用物理 USB / 串口硬件0x067b:0x2303 主机上开放的usb转串口的VID:PID虚拟机可以直接使用这个硬件-display none没有显卡、没有窗口、没有虚拟控制台tty0(键盘显示器终端)模拟了两路硬件串口ttyS0、ttyS1内核只能把日志 / 控制台绑到 存在的串口设备适合服务器 / 调试场景2 配套的制作根内存文件系统的脚本注释都在脚本中了.$ cat build_initramfs.sh #!/bin/bash # 配置项 BUSYBOX/bin/busybox# 改成你自己的静态 busybox 路径,要静态的,否则不能运行 OUTPUTinitramfs.cpio.gzWORKDIR./initramfs.tmp# 清理 rm-rf$WORKDIR$OUTPUTmkdir-p$WORKDIRcd$WORKDIR||exit1#1.创建目录结构 mkdir-p bin dev etc proc sys host #2.创建 etc/fstabmount-a 调用,9P 自动挂载 catetc/fstabEOFdevtmpfs/dev devtmpfs defaults00proc/proc proc defaults00sysfs/sys sysfs defaults00host_share/host9p transvirtio,version9p2000.L00EOF#3.创建 profile,login shell 调用 catetc/profileEOFalias lsls --coloralias llls -lalias hishistorymknod/dev/demo_drv c2470insmod/host/demo_drv.koEOF#4.生成 init 脚本,内核默认调用该用户态文件 catinitEOF#!/bin/sh # 按 fstab 自动挂载 mount-a#setsid,开新会话,是后面程序成为组长#cttyhack修复终端,我碰到的是消除一个Cant access tty;job control turned off的警告#sh跑shell#-l 会启用login shell,从而执行profile文件 setsid/bin/cttyhack/bin/sh-l#-c 是执行一个子shell命令 # 把当前 shell 的 键盘输入、屏幕输出、报错输出全部切换到/dev/ttyS1 这个串口上 # 用新sh替换当前进程 setsid sh-c exec0/dev/ttyS11020;exec shwaitEOFchmodx init #5.放入 busybox cp$BUSYBOXbin/chmodx bin/busybox # 建立软链接 cd bin||exit1forcmd in sh setsid cttyhack mount modprobe ls cat mkdir dmesg insmod rmmod;doln-s busybox$cmddone cd..#6.打包 cpiogzip find.|cpio-o-H newc|gzip-9../$OUTPUT# 完成 cd..rm-rf$WORKDIRecho✅ 生成成功$OUTPUT3 注意事项3.1 $ telnet 127.0.0.1:5555telnet: could not resolve 127.0.0.1:5555/telnet: Name or service not known注意,这是写法错误, 正确的写法是用空格分割ip地址和端口而不是冒号.$ telnet 127.0.0.1 5555则登录正常.还有,如果你想查看5555端口是否在监听,应该查看宿主机,而不是查看虚拟机.在宿主机上:$ netstat -antp可看到tcp 0 0 127.0.0.1:5555 0.0.0.0:* LISTEN 12737/qemu-system-x3.2 qemu_run.sh 启动时一定要加sudo 命令, 否则硬件设备透传不过来. 同时,如果你在虚拟机里调试pl2303 驱动, 要保证主机测不要抢占.(保证插拔硬件主机端不要生成/dev/ttyUSB0 文件, 采用的方法暴力的是把 系统pl2303.ko 改成其它名字, 温柔一点的方法是加入黑名单.反正记着如果你要在宿主机上用串行口,需要修改回来.查询是否已经透传的方法是虚拟机上查看/sys/bus/usb/devices 下插上时会多出2个链接拔出2个链接消失.默认也会有信息输出:[ 52.337476] usb 1-1: New USB device found, idVendor067b, idProduct2303, bcdDevice 2.02[ 52.343371] usb 1-1: New USB device strings: Mfr0, Product0, SerialNumber0这样才算环境搭好了.