起因

使用了RK3588的板子,想在Ubuntu18.04的主机上使用QEMU安装Ubuntu20.04的arm64镜像进行交叉编译测试,调试程序更方便。之前尝试了用docker的方式,使用qemu-user-static的方式,但是遇到了一个很难解决的问题————使用catkin_make最多只能占用物理机器1个核CPU,运行nproc命令能看到和物理机器一样的核数,但是编译时只能使用1个核,导致编译速度极慢,最后放弃了docker方式,改用QEMU虚拟机方式。

~~docker版本的我测试了就算是自己编译的qemu-aarch64也不行,虽然版本是7.0,执行catkin_make的时候还是只能用1个核。~~实测使用catkin tool编译而不是catkin_make可以使用多核!!

暂时不清楚是不是因为重新编译了qemu-aarch64的原因。

解决方法

1 构建QEMU 7.0版本

由于Ubuntu18.04自带的QEMU版本过低,不支持多核arm64虚拟机,所以需要从源码编译QEMU 7.0版本。

执行编译之前需要保证目前配置的默认编译器是自带的gcc-7.5版本


# 和宿主机器做文件共享需要用到的库
sudo apt install libcap-ng-dev libattr1-dev
sudo apt install cloud-image-utils
# 克隆代码
git clone --depth 1 --branch v7.0.0 https://gitlab.com/qemu-project/qemu.git
cd qemu
# 配置编译选项
./configure --target-list=aarch64-softmmu --enable-tcg --enable-system --enable-user  --enable-virtfs --python=/usr/bin/python3
# 如果提示少什么库,自己看情况安装缺失的库,然后重新执行上面configure命令
# 编译安装
make -j10
# 等待安装完成后,安装到/usr/local/bin目录下
sudo make install

2 创建工作目录

mkdir -p ~/qemu
cd ~/qemu

3 下载Ubuntu20.04的arm64云镜像

使用云镜像的好处是体积小,启动快,而且不需要安装过程,直接启动即可使用。

wget https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-arm64.img
# 镜像站点下载
wget https://mirrors.tuna.tsinghua.edu.cn/ubuntu-cloud-images/focal/current/focal-server-cloudimg-arm64.img

4 创建QEMU虚拟机磁盘

cp focal-server-cloudimg-arm64.img ubuntu-arm64.qcow2
# 为了避免云镜像空间不够用,扩展磁盘大小到20G
qemu-img resize ubuntu-arm64.qcow2 20G

5 创建cloud-init配置文件

创建user-data文件:

cat > user-data <<EOF
#cloud-config
password: ubuntu
chpasswd: { expire: False }
ssh_pwauth: True
bootcmd:
  - sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="console=ttyAMA0"/' /etc/default/grub
  - update-grub
EOF

执行命令生成seed.img文件:

cloud-localds seed.img user-data

6 启动QEMU虚拟机

执行以下命令启动虚拟机:

qemu-system-aarch64 \
  -M virt \
  -cpu cortex-a57 \
  -smp 8 \
  -m 4096 \
  -bios /usr/local/share/qemu/edk2-aarch64-code.fd \
  -device virtio-net-pci,netdev=net0 \
  -netdev user,id=net0,hostfwd=tcp::2222-:22 \
  -drive if=virtio,format=qcow2,file=ubuntu-arm64.qcow2 \
  -drive if=virtio,format=raw,file=seed.img \
  -nographic \
  -serial mon:stdio \
  -accel tcg,thread=multi

如果需要挂载自己的宿主机目录,可以添加以下参数:

  -virtfs local,path=/home/yourusername/shared,security_model=mapped-xattr,mount_tag=workspace \

最终可以在虚拟机内通过以下命令挂载:

sudo mount -t 9p workspace /mnt

或者修改cloud-init文件,添加挂载命令:

runcmd:
  - [ sh, -lc, "mkdir -p /mnt" ]
  - [ sh, -lc, "modprobe 9pnet_virtio 9p 2>/dev/null || true" ]
  - [ sh, -lc, "mount -t 9p -o trans=virtio,version=9p2000.L,rw workspace /mnt || true" ]