deepin v23 QEMU上运行X86 OpenHarmony——记一次曲折的鼠标事件响应踩坑过程
本文记录了在deepin v23系统上通过QEMU运行x86架构OpenHarmony系统时遇到的三个主要问题及解决方案:1) Windows与Linux平台QEMU加速技术差异,将Windows的whpx替换为Linux的kvm;2) 数据分区挂载失败问题,通过调整QEMU启动参数添加缺失的挂载点;3) 鼠标无响应问题,通过检查输入设备文件和系统日志定位问题原因。文章详细描述了每个问题的排查过程
deepin v23 QEMU上运行X86 OpenHarmony——记一次曲折的鼠标事件响应踩坑过程
前言
在上一篇文章《面向x86 QEMU运行环境的OpenHarmony系统镜像构建踩坑记录》中,笔者基于OHOS Porting Communities(下文简称OPC)提供的步骤,完成了OpenHarmony 6.0版本在x86 QEMU环境上的运行镜像构建。接下来就需要在x86 QEMU环境上把该镜像运行起来。
OPC提供的运行脚本只有一行命令,但就是这一行命令,笔者在运行时经历了系统kernel panic、鼠标指针无法移动等异常。由于笔者日常使用的是一台安装了deepin v23的小主机,笔者首先在这台小主机上使用通过deepin官方仓库安装的QEMU 10.1启动OpenHarmony编译镜像。而OPC提供的运行指引里提供的是Windows下的QEMU运行脚本。笔者使用同样的命令开始尝试运行,就遇到了本文前言里所述的一系列的问题。本着为社区添砖加瓦的态度,笔者不打算以Windows环境下能运行这种借口来绕开这个问题,开始了对这个问题的踩坑之旅,并将踩坑过程记录到本文中,以便后面有相近需求的读者参考。
1 问题一:QEMU的加速技术参数在Windows与Linux平台下的差异
笔者首先对OPC提供的Windows下的运行脚本qemu_x86_run_windows.ps1进行改造,使其可以在Linux bash环境中运行:
qemu-system-x86_64 -name OHemu \
-accel whpx \
-machine q35 \
-m 4G \
-smp 8 \
-drive if=none,file=./system-image/updater.img,format=raw,id=updater,index=0 \
-device virtio-blk-pci,drive=updater \
-drive if=none,file=./system-image/system.img,format=raw,id=system,index=1 \
-device virtio-blk-pci,drive=system \
-drive if=none,file=./system-image/vendor.img,format=raw,id=vendor,index=2 \
-device virtio-blk-pci,drive=vendor \
-drive if=none,file=./system-image/userdata.img,format=raw,id=userdata,index=3 \
-device virtio-blk-pci,drive=userdata \
-append "loglevel=7 ip=192.168.137.1:255.255.255.0::eth0:off sn=0023456789 console=tty0 console=ttyS0 init=/bin/init ohos.boot.hardware=x86_general root=/dev/ram0 rw ohos.required_mount.system=/dev/block/vdb@/usr@ext4@ro,barrier=1@wait,required ohos.required_mount.vendor=/dev/block/vdc@/vendor@ext4@ro,barrier=1@wait,required ohos.required_mount.misc=/dev/block/vda@/misc@none@none=@wait,required" \
-kernel ./system-image/bzImage \
-initrd ./system-image/ramdisk.img \
-nographic \
-vga none \
-device virtio-gpu-pci,xres=1280,yres=720,max_outputs=1,addr=08.0 \
-device virtio-mouse-pci \
-device virtio-keyboard-pci \
-device es1370 \
-k en-us \
-netdev user,id=net0,hostfwd=tcp::55555-:55555 -device e1000,netdev=net0 \
-display sdl,gl=off
这一步在deepin v23中直接提示:
qemu-system-x86_64: -accel whpx: invalid accelerator whpx
这是因为,前面的命令行中,-accel whpx是为Windows下特有的加速选项。whpx即Windows Hypervisor Platform,是Windows为QEMU、VirtualBox等虚拟化软件提供的硬件加速技术。在Linux下,对应的加速技术为KVM(Kernel-based Virtual Machine),这里的-accel whpx应该改为-accel kvm,同时也要确认宿主机已经启用了KVM:
grep -E "(vmx|svm)" /proc/cpuinfo | wc -l #这条命令的输出应大于0
lsmod | grep kvm #应能看到类似 `kvm_intel` 或 `kvm_amd` 的模块。
ls -l /dev/kvm #确认存在该设备文件且当前用户有读写权限。
如果/dev/kvm不存在,那么可以尝试加载模块:
sudo modprobe kvm
如果权限不足,可将用户加入 kvm 组
sudo usermod -aG kvm $USER
2 问题二:QEMU的加速技术参数在Windows与Linux平台下的差异
问题一解决完了之后,QEMU虚拟机可以运行起来了,但系统启动日志中提示:
Mount device /dev/block/sda4 to /data failed, err = 2。
另外还伴随着多处“Failed to change mode”和“Failed to change owner”的错误。该问题主要出现在数据分区(/data)未能正确挂载。这主要是由于我们的QEMU启动脚本中使用了userdata.img(对应/dev/block/vdd),但在内核命令行参数(-append)中没有指定挂载点。OpenHarmony期望userdata分区挂载到/data,但当前配置缺少这一项。
所以调整QEMU启动命令,为-append参数添加ohos.required_mount.misc=/dev/block/vda@/misc@none@none=@wait,required,完整的QEMU启动命令行如下:
qemu-system-x86_64 -name OHemu \
-accel kvm \
-machine q35 \
-m 4G \
-smp 8 \
-drive if=none,file=./system-image/updater.img,format=raw,id=updater,index=0 \
-device virtio-blk-pci,drive=updater \
-drive if=none,file=./system-image/system.img,format=raw,id=system,index=1 \
-device virtio-blk-pci,drive=system \
-drive if=none,file=./system-image/vendor.img,format=raw,id=vendor,index=2 \
-device virtio-blk-pci,drive=vendor \
-drive if=none,file=./system-image/userdata.img,format=raw,id=userdata,index=3 \
-device virtio-blk-pci,drive=userdata \
-append "loglevel=7 ip=192.168.137.1:255.255.255.0::eth0:off sn=0023456789 console=tty0 console=ttyS0 init=/bin/init ohos.boot.hardware=x86_general root=/dev/ram0 rw ohos.required_mount.system=/dev/block/vdb@/usr@ext4@ro,barrier=1@wait,required ohos.required_mount.vendor=/dev/block/vdc@/vendor@ext4@ro,barrier=1@wait,required ohos.required_mount.misc=/dev/block/vda@/misc@none@none=@wait,required ohos.required_mount.misc=/dev/block/vda@/misc@none@none=@wait,required" \
-kernel ./system-image/bzImage \
-initrd ./system-image/ramdisk.img \
-nographic \
-vga none \
-device virtio-gpu-pci,xres=1280,yres=720,max_outputs=1,addr=08.0 \
-device virtio-mouse-pci \
-device virtio-keyboard-pci \
-device es1370 \
-k en-us \
-netdev user,id=net0,hostfwd=tcp::55555-:55555 -device e1000,netdev=net0 \
-display sdl,gl=off
3 问题三:QEMU虚拟机启动进入锁屏界面后,鼠标移动无响应
问题二解决后,笔者通过QEMU启动编译后的OpenHarmony镜像,可以成功进入到OpenHarmony的锁屏界面了,但鼠标指针并没有跟随鼠标进行移动,将鼠标左键按住上划也没有响应。
对此,我们需要对系统输入设备情况进行确认。
3.1 输入设备文件确认
首先通过QEMU的模拟串口设备访问虚拟机控制台,输入ls -l /dev/input/event*命令,笔者的环境中得到。
crw-rw---- 1 root input 13, 64 2025-12-16 23:03 /dev/input/event0
crw-rw---- 1 root input 13, 65 2025-12-16 23:03 /dev/input/event1
crw-rw---- 1 root input 13, 66 2025-12-16 23:03 /dev/input/event2
crw-rw---- 1 root input 13, 67 2025-12-16 23:03 /dev/input/event3
crw-rw---- 1 root input 13, 68 2025-12-16 23:03 /dev/input/event4
crw-rw---- 1 root input 13, 69 2025-12-16 23:03 /dev/input/event5
这里主要检查每个输入事件设备文件/dev/input/eventX读写权限,每个输入事件设备文件应为rw-rw----权限(所有者和所属组有读写权限,其他用户无权限),然后所有者是 root,所属组是 input。另外,设备的主设备号应为13,次设备号应在64~95之间(含64和95),或在256以上(含256)。从这个要求来看,笔者的环境是通过该检查的。
然后就是要检查鼠标设备文件的可用性:
# ls -l /dev/input/mice
crw-rw---- 1 root input 13, 63 2025-12-16 23:03 /dev/input/mice
这里,/dev/input/mice的主设备号应为13,次设备号应63。然后该文件应为rw-rw----权限,所有者是 root,所属组是 input。笔者的环境同样也是通过该检查的。
接下来要确认内核是否识别到了输入设备:
# cat /proc/bus/input/devices
I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button"
P: Phys=LNXPWRBN/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXPWRBN:00/input/input0
U: Uniq=
H: Handlers=kbd event0
B: PROP=0
B: EV=3
B: KEY=10000000000000 0
I: Bus=0011 Vendor=0001 Product=0001 Version=ab41
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
S: Sysfs=/devices/platform/i8042/serio0/input/input1
U: Uniq=
H: Handlers=kbd event1
B: PROP=0
B: EV=120013
B: KEY=402000002 3803078f800d001 feffffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=7
I: Bus=0011 Vendor=0002 Product=0013 Version=0006
N: Name="VirtualPS/2 VMware VMMouse"
P: Phys=isa0060/serio1/input1
S: Sysfs=/devices/platform/i8042/serio1/input/input4
U: Uniq=
H: Handlers=mouse0 event2
B: PROP=0
B: EV=b
B: KEY=70000 0 0 0 0
B: ABS=3
I: Bus=0011 Vendor=0002 Product=0013 Version=0006
N: Name="VirtualPS/2 VMware VMMouse"
P: Phys=isa0060/serio1/input0
S: Sysfs=/devices/platform/i8042/serio1/input/input3
U: Uniq=
H: Handlers=mouse1 event3
B: PROP=1
B: EV=7
B: KEY=30000 0 0 0 0
B: REL=103
I: Bus=0003 Vendor=0627 Product=0001 Version=0111
N: Name="QEMU QEMU USB Keyboard"
P: Phys=usb-0000:00:1d.7-1/input0
S: Sysfs=/devices/pci0000:00/0000:00:1d.7/usb3/3-1/3-1:1.0/0003:0627:0001.0001/input/input5
U: Uniq=68284-0000:00:1d.7-1
H: Handlers=kbd event4
B: PROP=0
B: EV=120013
B: KEY=1000000000007 ff9f207ac14057ff febeffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=1f
I: Bus=0003 Vendor=0627 Product=0001 Version=0001
N: Name="QEMU QEMU USB Mouse"
P: Phys=usb-0000:00:1d.7-2/input0
S: Sysfs=/devices/pci0000:00/0000:00:1d.7/usb3/3-2/3-2:1.0/0003:0627:0001.0002/input/input6
U: Uniq=89126-0000:00:1d.7-2
H: Handlers=mouse2 event5
B: PROP=0
B: EV=17
B: KEY=1f0000 0 0 0 0
B: REL=903
B: MSC=10
这里看到有三个鼠标设备:QEMU QEMU USB Mouse和 两个VirtualPS/2 VMware VMMouse,其中QEMU QEMU USB Mouse的输入消息分发到了/dev/input/mouse2和/dev/input/event5,第一个VirtualPS/2 VMware VMMouse的输入消息分发到了/dev/input/mouse0和/dev/input/event2,第二个VirtualPS/2 VMware VMMouse的输入消息分发到了/dev/input/mouse1和/dev/input/event3。这说明QEMU虚拟机有识别到鼠标设备,问题可能出现在上层的消息处理上。
然后我们将这几个设备文件cat出来,看鼠标输入消息路由到了哪里。当我们对这几个设备文件分别进行cat的时候(cat输入设备文件时,需要按ctrl-c才能退出),如果输入消息能路由到对应的设备文件上,那么当我们把鼠标指针放到QEMU的模拟终端上移动鼠标时,cat命令会有一些字符的输出。笔者的情况是,/dev/input/mouse0和/dev/input/event2有消息输出,即是第一个VirtualPS/2 VMware VMMouse设备在起作用。这是一个PS/2接口设备,PS/2接口在目前已经很少使用,不排除OpenHarmony没有对其进行适配。
3.2 关键突破:跨平台对比分析
3.2.1 环境设置与观察
到这一步,直接的排查思路是会要从OpenHarmony的多模输入子系统服务multimodalinput入手,但考虑到OPC已经提供了一个Windows下运行QEMU的脚本,这个脚本应该是经过验证可行的。为了验证这个猜想,笔者在以前使用的一台Windows 11笔记本上运行了这个镜像,结果发现这个时候的鼠标指针是可以正常移动的。然后笔者也看了下/proc/bus/input/devices的内容,结果如下:
I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button"
P: Phys=LNXPWRBN/button/input0
S: Sysfs=/devices/LNXSYSTM:00/LNXPWRBN:00/input/input0
U: Uniq=
H: Handlers=kbd event0
B: PROP=0
B: EV=3
B: KEY=10000000000000 0
I: Bus=0006 Vendor=0627 Product=0002 Version=0002
N: Name="QEMU Virtio Mouse"
P: Phys=virtio4/input0
S: Sysfs=/devices/pci0000:00/0000:00:05.0/virtio4/input/input1
U: Uniq=
H: Handlers=mouse0 event1
B: PROP=0
B: EV=7
B: KEY=30400 1f0000 0 0 0 0
B: REL=103
I: Bus=0006 Vendor=0627 Product=0001 Version=0001
N: Name="QEMU Virtio Keyboard"
P: Phys=virtio5/input0
S: Sysfs=/devices/pci0000:00/0000:00:06.0/virtio5/input/input2
U: Uniq=
H: Handlers=kbd event2
B: PROP=0
B: EV=120003
B: KEY=400000007 ff803078f800dfff febeffff7bcfffff fffffffffffffffe
B: LED=7
I: Bus=0011 Vendor=0001 Product=0001 Version=ab41
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
S: Sysfs=/devices/platform/i8042/serio0/input/input3
U: Uniq=
H: Handlers=kbd event3
B: [ 196.270963] APPSPAWN: [appspawn_kickdog.c:83]Nweb enable -1
PROP=0
B: EV=120013
B: KEY=402000002 3803078f800d001 feffffdfffefffff fffffffffffffffe
B: MSC=10
B: LED=7
I: Bus=0011 Vendor=0002 Product=0006 Version=0000
N: Name="ImExPS/2 Generic Explorer Mouse"
P: Phys=isa0060/serio1/input0
S: Sysfs=/devices/platform/i8042/serio1/input/input5
U: Uniq=
H: Handlers=mouse1 event4
B: PROP=1
B: EV=7
B: KEY=1f0000 0 0 0 0
B: REL=143
这次,第一个设备是QEMU Virtio Mouse,也正好是这个设备对应的文件/dev/input/mouse0和/dev/input/event1能cat出内容。这为笔者后面的排查提供了重要线索:当前在deepin V23遇到的问题,与QEMU为虚拟机提供的硬件环境有关。起初笔者以为与QEMU的版本有关系,笔者在deepin V23上使用的QEMU为8.2.0版本,Windows 11上使用的QEMU为10.1版本。因此也尝试了在deepin V23编译了10.1版的QEMU,结果问题依旧。
下面是到目前为止,笔者在deepin V23和Windows 11上的QEMU环境对比:
| 对比维度 | deepin V23 (问题环境) | Windows 11 (正常环境) | 差异分析 |
|---|---|---|---|
| 宿主机系统 | Deepin V23 (基于Debian) | Windows 11 | 核心运行环境不同 |
| QEMU版本 | 自行编译的10.1 | 官方预编译10.1 | 版本一致,排除主版本差异 |
| 输入设备列表 | 出现VirtualPS/2 VMware VMMouse和QEMU Virtio Mouse |
仅有QEMU Virtio Mouse和ImExPS/2 |
Deepin下多出PS/2设备 |
| 事件流状态 | event1(Virtio)无数据,event4(PS/2)也无数据 |
event1(Virtio)有数据 |
事件路由目标明确 |
3.2.2 核心发现与推断
通过对比分析,笔者得出了几个关键结论:
- 问题与OpenHarmony镜像无关:同一镜像在Windows下正常工作,证明问题不在客户机系统内部。
- 问题根源在QEMU设备模拟层:Deepin环境下多出的
VirtualPS/2 VMware VMMouse设备暗示了QEMU设备模拟的差异。 - 事件路由混乱是直接原因:多个"鼠标"设备的存在导致输入子系统无法正确路由事件。
3.3 解决方案:基于理解的精准修复
基于对问题根源的理解,解决方案变得清晰:消除设备枚举的不确定性是关键。
通过QEMU参数精确控制虚拟设备的枚举:
qemu-system-x86_64 \
-machine q35,i8042=off,accel=kvm \ # 关键:禁用PS/2控制器
-cpu host -smp 4 -m 4G \
-hda ohos-x86.img \
-device virtio-mouse-pci \ # 明确指定Virtio鼠标
-device virtio-keyboard-pci \
-serial stdio
参数原理详解:
-machine q35,i8042=off:q35是现代PC平台架构,i8042=off彻底禁用传统的PS/2控制器-device virtio-mouse-pci:明确使用现代Virtio输入设备,避免兼容性设备冲突
3.4 验证效果
实施解决方案后,重新检查系统状态:
- 设备列表净化:
/proc/bus/input/devices显示只有单一的Virtio鼠标设备 - 事件流正常:
cat /dev/input/event1显示鼠标移动产生持续事件流 - 用户体验恢复:图形界面中鼠标指针流畅响应
4 OpenHarmony命令行串口调试技巧
某些读者可能会有疑问,如何能在OpenHarmony上执行Linux命令?这里实际上涉及到QEMU虚拟串口的使用,笔者最终的运行命令行如下:
qemu-system-x86_64 -name OHemu \
-accel kvm \
-machine q35 \
-m 4G \
-smp 4 \
-drive if=none,file=./updater.img,format=raw,id=updater,index=0 \
-device virtio-blk-pci,drive=updater \
-drive if=none,file=./system.img,format=raw,id=system,index=1 \
-device virtio-blk-pci,drive=system \
-drive if=none,file=./vendor.img,format=raw,id=vendor,index=2 \
-device virtio-blk-pci,drive=vendor \
-drive if=none,file=./userdata.img,format=raw,id=userdata,index=3 \
-device virtio-blk-pci,drive=userdata \
-append "loglevel=7 ip=192.168.137.1:255.255.255.0::eth0:off sn=0023456789 console=tty0 console=ttyS0 init=/bin/init ohos.boot.hardware=x86_general root=/dev/ram0 rw ohos.required_mount.system=/dev/block/vdb@/usr@ext4@rw,barrier=1@wait,required ohos.required_mount.vendor=/dev/block/vdc@/vendor@ext4@rw,barrier=1@wait,required ohos.required_mount.misc=/dev/block/vda@/misc@none@none=@wait,required ohos.required_mount.data=/dev/block/vdd@/data@ext4@rw,barrier=1@wait,required" \
-kernel ./bzImage \
-initrd ./ramdisk.img \
-device virtio-gpu-pci,xres=1280,yres=720,max_outputs=1,addr=08.0 \
-usb -device usb-kbd -device usb-mouse \
-device es1370 \
-device AC97 \
-k en-us \
-netdev user,id=net0,hostfwd=tcp::2222-:22 \
-device e1000,netdev=net0 \
-nographic \
-vga none \
-display sdl,gl=on \
-serial telnet:127.0.0.1:55555,server,nowait
这里的最后一行使用了-serial telnet:127.0.0.1:55555,server,nowait,就是让QEMU将串口设备的控制入口放到了QEMU虚拟机进程的55555端口上,这样我们就可以在宿主机上通过类似telnet localhost 55555这样的命令来访问QEMU虚拟机的串口。
实际上,这个编译出来的OHOS镜像还内置了一个dropbear服务,如果能将其调通,那么就可以通过SSH来访问该虚拟机,操作Linux命令行将更加方便。
5 总结与启示
5.1 方法论收获
这次排查经历的最大价值不在于解决了一个具体问题,而在于建立了一套系统级的问题排查方法论:
- 对比分析法:通过控制变量(同一镜像、同一QEMU版本)在不同环境下的表现差异来定位问题范围
- 分层排查策略:从应用层到底层硬件模拟层逐级验证,不盲目试错
- 工具链运用:掌握
/dev文件系统、设备节点监控等Linux调试利器
5.2 技术认知提升
通过这次深入排查,笔者对以下技术点有了更深刻的理解:
- Linux输入子系统的设备枚举和事件路由机制
- QEMU虚拟设备模拟的底层原理和参数控制
- 跨平台开发中环境差异对系统行为的潜在影响
5.3 对开源社区的思考
这次经历也让笔者意识到,详细的问题排查记录和跨平台测试数据对于开源项目同样宝贵。通过分享这类底层问题的完整分析过程,可以为社区积累重要的实践知识。
参考资料
更多推荐
所有评论(0)