qemu模拟arm64环境-构建6.1内核以及debian12

一、背景

手头没有合适的arm64开发板,但是需要arm的环境,于是想到qemu模拟一个。除了硬件交互以外,软件层面的开发还是都可以实现的。

虚拟机还能自定义内存大小和镜像大小,非常适合上板前的验证,合适的话再买也不迟。

为了提高配置效率与实用性,我直接使用香橙派的构建脚本编译根文件。没有和其他作者一样使用busybox制作根文件系统,我使用debian来提供apt等常用功能。

二、构建流程

1、qemu

建议使用git clone 源码进行编译,减少匹配问题。

bash 复制代码
git clone https://github.com/qemu/qemu.git

或者官网压缩包下载地址:

Download QEMU - QEMUhttps://www.qemu.org/download/

以 git clone 为例编译源码:

bash 复制代码
cd qemu
./configure --enable-kvm --enable-debug --enable-vnc --enable-user --enable-slirp --target-list="aarch64-softmmu"
make -j8
sudo make install

需要注意配置源码时的configure指令,如果想要了解参数的配置见我另一篇文章。

qemu-system-aarch64开启user用户模式网络连接-CSDN博客https://blog.csdn.net/plmm__/article/details/142701489?spm=1001.2014.3001.5502

2、交叉编译工具链

可以使用apt安装,也可以下载arm官方的压缩包,解压后记得配置PATH环境变量。

bash 复制代码
sudo apt-get install gcc-aarch64-linux-gnu
sudo apt-get install libncurses5-dev  build-essential git bison flex libssl-dev

https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xzhttps://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz

3、kernel

内核源码我使用香橙派提供的6.1版本,使用Linux官方的也是可以的。

bash 复制代码
git clone --depth=1 -b orange-pi-6.1-rk35xx https://github.com/orangepi-xunlong/linux-orangepi

设置ARCH和CORSS_COMPILE。

bash 复制代码
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

内核config配置文件建议使用defconfig,使用rockchip的默认配置无法通过qemu启动,暂时不知道原因。对于qemu的虚拟机,不需要设备树,只需要镜像即可。

bash 复制代码
make defconfig
make Image -j8

4、debian根文件

使用香橙派的 orangepi-build 工具构建,这里只是简单介绍过程,详细流程可以查看任意开发板的使用手册。

下载工具:

bash 复制代码
git clone https://github.com/orangepi-xunlong/orangepi-build.git -b next

下载完成后,执行build脚本:

bash 复制代码
sudo ./build

选择构建Rootfs and all deb packages:

然后需要选择开发板类型,看心情选即可。

下一步是选择内核版本,由于内核选的6.1,这里需要选current。如果内核选择5.4,这里要选legacy。

选择rootfs类型,看需要选即可:

选择服务器版本还是桌面版本,建议服务器版本:

选择标准:

这一步回车跳过:

等待构建完成可以在**external/cache/rootfs/**目录下找到 lz4 压缩包,需要解压后创建一个可挂载的ext4文件镜像。

(1)创建一个空的磁盘镜像文件

bash 复制代码
qemu-img create -f raw rootfs.img 5G

(2)格式化磁盘镜像

bash 复制代码
sudo mkfs.ext4 rootfs.img

(3)挂载磁盘镜像

bash 复制代码
sudo mkdir -p /mnt/rootfs
sudo mount -o loop rootfs.img /mnt/rootfs

(4)将解压后的内容直接写入到挂载的目录

压缩包替换为生成的文件名。

bash 复制代码
sudo lz4 -d --stdout bookworm-cli-arm64.tar.lz4 | sudo tar -x -C /mnt/rootfs/

(5)卸载磁盘镜像

bash 复制代码
sudo umount /mnt/rootfs

三、启动虚拟机

创建一个工作目录 qemu_arm64,将生成的内核镜像,根文件系统放到目录。创建一个文件夹share_dir用于共享文件。

新建启动脚本 start.sh

bash 复制代码
#!/bin/bash

sudo qemu-system-aarch64 \
-M virt \
-cpu cortex-a57 \
-nographic \
-smp 4 \
-m 2048 \
-kernel Image \
-drive if=none,file=rootfs.img,format=raw,index=0,id=hd0 \
-device virtio-blk-device,drive=hd0 \
-append "rdinit=/linuxrc root=/dev/vda rw console=ttyAMA0 loglevel=8" \
-virtfs local,path=./share_dir,mount_tag=host0,security_model=passthrough,id=host0 \
-netdev user,id=net0,hostfwd=tcp::10022-:22 \
-device virtio-net-pci,netdev=net0

加sudo主要是用于隔离环境变量,防止意外。参数的大部分可以通过chatgpt分析,其中用于挂载根文件的指令:

bash 复制代码
-drive if=none,file=rootfs.img,format=raw,index=0,id=hd0 \
-device virtio-blk-device,drive=hd0 \

用于挂载共享文件的指令:

bash 复制代码
-virtfs local,path=./share_dir,mount_tag=host0,security_model=passthrough,id=host0 \

网络我没有使用桥接的方式,而是使用qemu自带的user方式联网,缺点是不能和宿主机通信。用于连接网络的指令:

bash 复制代码
-netdev user,id=net0,hostfwd=tcp::10022-:22 \
-device virtio-net-pci,netdev=net0

执行start.sh脚本即可启动虚拟机:

四、挂载和联网

启动虚拟机后,需要挂载共享文件夹,并根据模拟的网卡进行dhcp。

1、挂载共享文件夹

bash 复制代码
#!/bin/bash

mkdir -p /mnt/share
mount -t 9p -o trans=virtio,version=9p2000.L,access=any,rw host0 /mnt/share

这里的文件夹就是启动指令中的share_dir,宿主机可以将文件放到文件夹内,虚拟机可以读和访问,但是不能写,提示没有权限,暂时还未解决。

不过在网络设置成功后,可以使用scp命令传输文件到宿主机,形成数据回环。

2、dhcp

bash 复制代码
#!/bin/bash

INTERFACE=$(ls /sys/class/net/ | grep -v lo)

sudo ip link set dev $INTERFACE up
sudo dhclient $INTERFACE

这个脚本我采用临时设置的方式,原因是虚拟机有时候网卡名字会变,直接写入网络配置文件可能会失效。执行后会查询当前的网卡名,然后执行dhcp。

获取到ip后就可以apt更新了。

五、其他

如果使用busybox构建最小根文件系统,在编译根文件时交叉编译器最好使用arm官方原生的,使用其他第三方定制的工具链会引发内核崩溃。血的教训!排列组合三天才找到问题。

相关推荐
内核程序员kevin2 小时前
TCP Listen 队列详解与优化指南
linux·网络·tcp/ip
朝九晚五ฺ6 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
自由的dream7 小时前
Linux的桌面
linux
xiaozhiwise7 小时前
Makefile 之 自动化变量
linux
意疏9 小时前
【Linux 篇】Docker 的容器之海与镜像之岛:于 Linux 系统内探索容器化的奇妙航行
linux·docker
BLEACH-heiqiyihu9 小时前
RedHat7—Linux中kickstart自动安装脚本制作
linux·运维·服务器
一只爱撸猫的程序猿10 小时前
一个简单的Linux 服务器性能优化案例
linux·mysql·nginx
我的K840911 小时前
Flink整合Hudi及使用
linux·服务器·flink
19004311 小时前
linux6:常见命令介绍
linux·运维·服务器