ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Ubuntu上QEMU模拟运行OpenHarmony:环境搭建与开发调试指南

Ubuntu上QEMU模拟运行OpenHarmony:环境搭建与开发调试指南 1. 为什么要在Ubuntu上折腾OpenHarmony加QEMU这套组合如果你最近在关注国产操作系统的开发大概率绕不开OpenHarmony这个名字。但很多人卡在第一步手上没有开发板也不想为了跑一个Hello World就去买一块Hi3861或者RK3588。这时候QEMU就派上用场了——它能在你的Ubuntu机器上模拟出一台ARM64设备让你不花一分钱硬件成本就能把OpenHarmony跑起来。我最初接触这套方案是因为手头只有一台x86的笔记本想验证一些系统层的改动又不想每次都烧录到真机上。试过Docker方案、试过直接交叉编译后scp到开发板最后发现QEMU加OpenHarmony的组合在灵活性和可复现性上是最平衡的。整套环境搭下来磁盘占用大概在15到20GB内存8GB就能跑对机器要求不算高。这篇文章面向的是有一定Linux基础的开发者至少你得知道apt怎么用、make是干什么的。如果你连Ubuntu都没装过建议先把系统装好再来看。我会从环境准备开始一步步带你走完整个流程包括我踩过的坑和最后总结出来的省事技巧。整个搭建过程大概需要两到三个小时取决于你的网络速度和机器性能。需要提前说明的是这套环境主要用于系统功能验证和应用开发调试不适合做性能测试——QEMU是模拟器跑出来的性能数据没有参考意义。另外如果你要做驱动开发或者硬件相关的调试最终还是得上真机。2. 环境准备Ubuntu版本选择与基础依赖安装2.1 Ubuntu版本的选择逻辑Ubuntu的版本选择上我建议用20.04 LTS或者22.04 LTS。这两个版本我都实测过20.04的兼容性最好22.04也没问题但偶尔会遇到Python版本导致的脚本报错。不推荐用最新的非LTS版本因为OpenHarmony的编译工具链对glibc版本有要求太新的系统反而容易出问题。磁盘空间方面源码下载加上编译产物预留30GB比较稳妥。如果你只是跑预编译好的镜像15GB也够。内存建议8GB起步编译的时候会同时跑多个进程内存不够会直接OOM。2.2 基础依赖的一站式安装Ubuntu装好之后先更新源然后安装编译所需的基础工具。下面这条命令是我整理过的涵盖了OpenHarmony编译和QEMU运行所需的核心依赖sudo apt update sudo apt install -y git curl wget python3 python3-pip \ build-essential gcc g make cmake ninja-build \ libssl-dev libncurses-dev flex bison \ qemu-system-arm qemu-system-x86 qemu-utils \ libglib2.0-dev libpixman-1-dev \ device-tree-compiler cpio rsync这里有几个包值得单独说一下。ninja-build是OpenHarmony编译系统gn的默认后端不装的话编译会直接报错。device-tree-compiler是QEMU加载设备树必需的很多人第一次搭环境就卡在这里。libpixman-1-dev是QEMU图形输出的依赖如果你打算用无头模式跑可以暂时不装但建议装上以备不时之需。2.3 Python环境的坑Ubuntu 22.04默认的Python是3.10而OpenHarmony的部分脚本对Python版本比较敏感。我的做法是不要动系统自带的Python而是用update-alternatives来管理。如果你在编译过程中遇到ModuleNotFoundError大概率是缺了某个pip包直接pip3 install补上就行。另外pip3的源建议换成国内镜像不然下载依赖的时候会非常慢pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple注意不要用sudo pip3除非你明确知道自己在做什么。用普通用户权限安装到用户目录下避免污染系统Python环境。3. 获取OpenHarmony源码与编译工具链配置3.1 源码获取的两种路径OpenHarmony的源码获取有两种方式一种是直接repo拉取全量代码另一种是下载官方发布的源码包。如果你只是想快速跑起来我建议用源码包的方式省时省力。全量repo同步动辄几十GB而且网络不稳定的时候经常断。源码包可以从OpenHarmony的官方发布渠道获取选择LTS版本比如3.2或者4.0。下载下来是一个压缩包解压之后大概5到8GB。解压命令tar -xzf ohos-sdk.tar.gz -C ~/openharmony如果你确实需要完整源码来做系统定制那就得用repo工具。先安装repomkdir ~/bin curl https://storage.googleapis.com/git-repo-downloads/repo ~/bin/repo chmod ax ~/bin/repo export PATH~/bin:$PATH然后初始化仓库并同步。这一步的耗时取决于网络我试过最快两个小时最慢一整天。建议在晚上挂着下载。3.2 编译工具链的配置OpenHarmony的编译依赖一套特定的工具链主要是gn和ninja。如果你下载的是源码包里面通常已经包含了预编译好的工具链。如果是全量源码需要先执行build/prebuilts_download.sh来下载预编译工具。配置环境变量的时候把工具链路径加到PATH里export PATH~/openharmony/prebuilts/build-tools/linux-x86/bin:$PATH export PATH~/openharmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin:$PATH这两行建议写进~/.bashrc不然每次开新终端都要重新设置。写完之后执行source ~/.bashrc生效。3.3 编译目标的选择OpenHarmony支持多种编译目标跑QEMU的话要选qemu-arm64或者qemu-x86_64。ARM64的生态更完整推荐优先选这个。编译命令大致是这样的./build.sh --product-name qemu-arm64 --ccache--ccache是开启编译缓存第二次编译的时候能省不少时间。第一次编译大概需要40分钟到1.5小时取决于机器性能。编译产物在out/qemu-arm64/目录下核心文件是images/里面的镜像。提示编译过程中如果报错说找不到某个头文件先检查是不是sysroot路径没设置对。这是最常见的问题通常是因为环境变量没生效。4. QEMU侧的网络与存储配置细节4.1 QEMU启动参数的核心逻辑QEMU启动OpenHarmony镜像的时候参数配置是关键。一个典型的启动命令长这样qemu-system-aarch64 \ -M virt \ -cpu cortex-a57 \ -smp 4 \ -m 4096 \ -kernel out/qemu-arm64/images/Image \ -initrd out/qemu-arm64/images/ramdisk.img \ -append consolettyAMA0 root/dev/ram0 \ -nographic \ -netdev user,idnet0,hostfwdtcp::5555-:5555 \ -device virtio-net-device,netdevnet0这里每个参数都有讲究。-M virt指定虚拟平台-cpu cortex-a57是ARM64的CPU型号-smp 4给四个核-m 4096给4GB内存。-nographic表示不开图形界面直接在当前终端输出串口日志调试的时候非常方便。4.2 网络配置user模式与tap模式的取舍QEMU的网络有两种常用模式user模式和tap模式。user模式最简单不需要额外配置QEMU会自动做NAT虚拟机内部可以访问外网。但user模式的缺点是外部无法主动访问虚拟机只能通过端口转发。tap模式则相当于给虚拟机分配了一个独立的网络接口虚拟机在局域网里就像一台真实的设备。配置tap模式需要创建虚拟网桥sudo ip tuntap add dev tap0 mode tap sudo ip link set tap0 up sudo ip link set tap0 master br0然后QEMU启动参数改成-netdev tap,idnet0,ifnametap0,scriptno,downscriptno \ -device virtio-net-device,netdevnet0tap模式的好处是可以用ssh直接连虚拟机传输文件也方便。但配置起来麻烦一些而且每次重启机器都要重新创建tap设备。我的建议是开发调试阶段用user模式加端口转发就够了需要做网络相关测试的时候再切到tap模式。4.3 存储挂载的注意事项如果你需要往虚拟机里传文件除了网络传输还可以用QEMU的虚拟磁盘挂载功能。创建一个qcow2格式的虚拟磁盘qemu-img create -f qcow2 data.qcow2 2G然后在启动参数里加上-drive filedata.qcow2,ifnone,iddrive0 \ -device virtio-blk-device,drivedrive0虚拟机启动后这个磁盘会显示为/dev/vda格式化之后就能用了。这种方式适合传大文件或者做持久化存储。注意QEMU的虚拟磁盘性能一般不要指望它能跑出SSD的速度。如果只是传几个小文件用scp走网络反而更快。5. 从零跑通第一个OpenHarmony镜像的完整过程5.1 镜像文件的确认与准备编译完成后先确认out/qemu-arm64/images/目录下有哪些文件。核心文件包括文件名作用是否必需Image内核镜像是ramdisk.img根文件系统是userdata.img用户数据分区否system.img系统分区视版本而定vendor.img厂商分区视版本而定不同版本的OpenHarmony产出的镜像文件略有差异。3.2版本通常只需要Image和ramdisk.img就能启动4.0版本可能需要额外的system.img。5.2 首次启动的串口日志解读第一次启动的时候串口会输出大量日志。重点关注几个阶段内核启动阶段看到Booting Linux on physical CPU就说明内核加载成功了。驱动初始化阶段virtio_blk和virtio_net的初始化信息会在这里出现。init进程启动看到init: init first stage started说明根文件系统挂载成功。系统服务启动最后会看到OpenHarmony的启动动画或者命令行提示符。如果卡在某个阶段不动了先看最后几行日志是什么。常见的卡点包括根文件系统挂载失败检查root参数、串口配置错误检查console参数、内存不足加大-m参数。5.3 登录与基本操作系统启动完成后默认会进入命令行界面。OpenHarmony的默认用户名是root密码通常是空的或者123456具体看版本。登录之后可以执行一些基本命令验证系统状态uname -a cat /proc/cpuinfo ifconfig如果ifconfig显示没有网络接口检查QEMU的网络参数是不是配对了。正常情况下应该能看到eth0或者enp0s1这样的接口。5.4 应用安装与调试OpenHarmony的应用是以HAP包的形式存在的。安装HAP需要用hdc工具这个工具在SDK的toolchains目录下。先把hdc加到PATHexport PATH~/openharmony/sdk/default/openharmony/toolchains:$PATH然后连接虚拟机hdc tconn 127.0.0.1:5555连接成功后就可以用hdc install安装HAP包了。调试的时候可以用hdc shell进入设备shell或者用hdc file send传文件。提示hdc的连接有时候不太稳定如果连不上先检查QEMU的端口转发是不是生效了。可以用telnet 127.0.0.1 5555测试一下端口通不通。6. 踩坑实录那些让我重装三次系统的问题6.1 编译报错gn和ninja版本不匹配这个问题我遇到过两次。症状是编译到一半突然报gn: command not found或者ninja: error: loading build.ninja。根本原因是PATH里的工具链顺序不对系统自带的ninja版本太老和OpenHarmony的gn不兼容。解决办法是确保OpenHarmony的工具链路径在PATH的最前面export PATH~/openharmony/prebuilts/build-tools/linux-x86/bin:$PATH然后用which gn和which ninja确认一下用的是哪个版本。如果还是不对可以直接用绝对路径调用。6.2 QEMU启动卡死设备树不匹配有一次编译出来的镜像怎么都启动不了串口日志停在Starting kernel ...就不动了。排查了半天发现是设备树的问题——QEMU的virt平台需要特定的设备树而编译出来的内核没有包含对应的dtb。解决办法是在QEMU启动参数里显式指定dtb文件-dtb out/qemu-arm64/images/qemu-arm64.dtb如果编译产物里没有dtb文件需要在内核编译配置里打开CONFIG_ARM64_VIRT选项重新编译。6.3 网络不通tap0没有加入网桥配置tap模式的时候我创建了tap0设备但忘了把它加到网桥里结果虚拟机死活上不了网。排查的时候用brctl show一看网桥里空空如也。正确的顺序是先创建网桥再把tap0加进去最后启动QEMU。网桥的配置命令sudo brctl addbr br0 sudo brctl addif br0 eth0 sudo ip link set br0 up sudo ip link set tap0 up sudo brctl addif br0 tap0注意把物理网卡加到网桥里会导致宿主机短暂断网如果是远程SSH连接的话要小心。建议在本地终端操作或者用screen/tmux保持会话。6.4 磁盘空间不足编译产物把根分区撑爆了OpenHarmony的编译产物非常大完整编译一次能产生20GB以上的中间文件。如果你的/home分区不够大编译到一半就会报No space left on device。解决办法有两个一是把源码和编译目录放到大分区上二是定期清理out/目录下的临时文件。可以用ccache -C清空编译缓存或者直接删掉out/目录重新编译。7. 日常开发中的效率技巧与工具链搭配7.1 用脚本封装QEMU启动命令每次手敲那一长串QEMU参数太累了我写了一个启动脚本run_qemu.sh#!/bin/bash QEMU_ARGS( -M virt -cpu cortex-a57 -smp 4 -m 4096 -kernel out/qemu-arm64/images/Image -initrd out/qemu-arm64/images/ramdisk.img -append consolettyAMA0 root/dev/ram0 -nographic -netdev user,idnet0,hostfwdtcp::5555-:5555 -device virtio-net-device,netdevnet0 ) qemu-system-aarch64 ${QEMU_ARGS[]} $这样每次只需要./run_qemu.sh就能启动要加额外参数直接跟在后面就行。7.2 用tmux管理多个会话调试的时候经常需要同时看串口日志、跑hdc命令、编辑代码。用tmux分屏可以大大提高效率。我的习惯是开三个窗格左边跑QEMU右上跑hdc shell右下用来编译或者编辑文件。tmux的基本操作Ctrlb然后按%是垂直分屏按是水平分屏按方向键切换窗格。7.3 增量编译的配置全量编译一次太慢日常开发只需要编译改动的模块。OpenHarmony支持增量编译只要不执行clean再次执行build.sh的时候只会编译改动的部分。配合ccache使用第二次编译通常只需要几分钟。如果增量编译出了问题比如报奇怪的链接错误可以先执行./build.sh --product-name qemu-arm64 --ccache --no-prebuilt-sdk试试。实在不行再全量编译。7.4 日志过滤与关键字监控QEMU的串口日志刷屏很快找关键信息很费劲。可以用grep过滤./run_qemu.sh 21 | grep -E error|fail|panic|OpenHarmony或者把日志重定向到文件然后用tail -f实时监控./run_qemu.sh 21 | tee qemu.log另一个终端里tail -f qemu.log | grep --colorauto -i error这样有错误的时候会高亮显示。8. 关于这套环境能做什么和不能做什么这套Ubuntu加QEMU加OpenHarmony的环境最适合的场景是应用层开发和系统功能验证。你可以用它来开发ArkTS应用、测试系统API、验证系统服务的改动。我平时用它来跑一些UI相关的测试比真机方便得多——快照恢复只要几秒钟真机刷机得等好几分钟。但它也有明显的边界。性能测试不要用QEMU模拟器的CPU指令是翻译执行的跑分数据没有任何参考价值。驱动开发也不适合QEMU模拟的硬件和真实设备差异很大在QEMU上能跑的驱动放到真机上大概率要重写。图形性能相关的测试同样不靠谱QEMU的GPU模拟能力很有限。如果你需要做上述这些事情最终还是得搞一块开发板。目前市面上比较流行的OpenHarmony开发板有RK3568、RK3588、Hi3861等价格从几十块到几百块不等。QEMU环境可以作为前期开发和调试的补充但不能完全替代真机。另外这套环境的可复现性很好。你可以把整个搭建过程写成一个脚本在新机器上一键部署。我自己的做法是把所有配置步骤整理成一个setup.sh换电脑的时候直接跑一遍半小时就能恢复完整的开发环境。这比手动一步步配置靠谱得多也避免了遗漏某个依赖导致的诡异问题。
返回列表