ubuntu-base(arm64与riscv64) 根文件系统
有个小需求,是在
arm64
和riscv64
上都跑起来speccpu 2017
首先在
Qemu
上跑起来,需要考虑需要的【Linux 内核、根文件系统、Bootloader 】,其中 Bootloader 在Qemu
中可以很简化,对于内核可以使用kernel参数加载,对于根文件系统则要费一些功夫提前结论:我使用过程中在
qemu
中apt
从网上下载包是有问题的(上网对目前的我还是有点困难,还得学习,后续学会网络再写一份博客),但是本地挂载文件系统,然后chroot
再apt
是可以正常下载的,所以暂时折衷了以下,需要的包通过本地 chroot 来进行安装依赖的包,然后进入 qemu 中使用以下两篇博客是我记录的在 x86 物理机上执行
speccpu 2017
以及qemu
运行(aarch64 & riscv64)Linux
的过程,有兴趣可以参考:Qemu 启动 Linux(aarch64 与 riscv64):https://blog.csdn.net/jingyu_1/article/details/135746098
SPEC CPU 2017 quick start:https://blog.csdn.net/jingyu_1/article/details/135695701
零、需求分析
不需要很复杂的文件系统,不需要像 Ubuntu
发行版那样包含各种各样的功能,也不需要桌面,只需要精简的文件系统并且支持 apt 等包管理,因为可能需要安装一些
-
ubuntu-server(x 支持 apt,但是有点太大,包含了很多其他的内容)
-
ubuntu-base(y 支持 apt,可以安装 gcc fortran 等)
-
busybox(x )
-
buildroot (x 不支持)
-
yocto(x 配置太复杂)
一、qemu安装、交叉编译工具链、内核编译
这些内容可以参考我的其他博客:
-
Qemu 之安装(源码安装):https://blog.csdn.net/jingyu_1/article/details/135625477?spm=1001.2014.3001.5502
-
构建 aarch64 以及 riscv64 交叉编译工具链(裸机):https://blog.csdn.net/jingyu_1/article/details/135631512?spm=1001.2014.3001.5502
-
Qemu 启动 Linux(aarch64 与 riscv64):https://blog.csdn.net/jingyu_1/article/details/135746098?spm=1001.2014.3001.5502
其中对于内核的编译,有一点要说明
配置、编译都要指定架构 ARCH
和交叉编译工具链 CROSS_COMPILE
,一般情况下选择 defconfig
够用,但是可能有时候要添加一些模块,这时候 menuconfig
可能更方便,例如在我的需求中,需要挂载 speccpu2017.iso
,需要添加 iso9600
的模块,但是 linux
内核默认是没有添加这个模块的,对于我的需要要补充,按如下操作:(这一步你不一定需要)
-
在
menuconfig
界面中,使用箭头键导航到File systems
部分 -
进入
CD-ROM/DVD Filesystems
子菜单 -
找到
ISO 9660 CDROM file system support
选项(通常标记为CONFIG_ISO9660_FS
) -
使用空格键选择该选项以编译为模块(通常会显示为
M
),这个更加常用 -
如果希望直接编译进内核,而不是作为模块,选择它为内核(通常显示为
*
)
模块
大多数情况下表示为驱动
,并且大多数情况下不会直接编入内核,而是配置为模块,在后续过程中启用模块
二、构建根文件系统
主要参考:https://www.cnblogs.com/phoebus-ma/p/17436089.html,并根据需求作了一定修改
Ubuntu-base 镜像: https://cdimage.ubuntu.com/ubuntu-base/releases/jammy/release/,你也可以选择你需要的版本进行安装
(包含了
arm64
以及riscv
的版本,这点还是很友好的)
1、安装依赖:
shell
sudo apt install binfmt-support qemu-user-static
# 如果没安装 qemu 以及交叉编译工具链,也可以使用 apt 安装 qemu-system-aarch64 gcc-aarch64-linux-gnu
我使用的是 ubuntu-base 22.04.3(arm64):ubuntu-base-22.04.3-base-arm64.tar.gz
关于 riscv 的版本可以从上面的官方 ubuntu-base 镜像中下载
2、编译内核:
如果未编译内核,则参考上面文档中的方式,执行
shell# 对于 arm64 make defconfig ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- # make menuconfig ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- make -j8 ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- # 对于 riscv make defconfig ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- # make menuconfig ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- make -j8 ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu-
当需要调整时,使用
menuconfig
配置,比如遇到我上面所说的情况,或者后续内核缺少某个模块的时候再来修改配置,重新编译,(以及后续提到的安装内核模块)
3、创建空磁盘:
我们这里依赖的是 ubuntu-base 的根文件系统,所以只需要创建一个空的虚拟磁盘镜像即可
一种是使用 qemu-img
命令
另一种是使用 dd
命令
下面举例创建名为 arm64.image
的 ext4
格式的虚拟磁盘
也可以是其他名字,我这里只是为了区分 arm 和 riscv 使用的磁盘,它们的文件系统不能共享
这里推荐 qemu-img
更加便捷(比如扩容十分方便)
shell
# 使用 qemu-img 创建20G的虚拟磁盘
qemu-img create -f raw arm64.image 20G
# 将虚拟磁盘格式化成 ext4 格式
sudo mkfs.ext4 arm64.image
使用 dd
也可以
shell
# arm64.ext4 为 1G 大小, 下面的内容根据需要进行配置
dd if=/dev/zero of=arm64.ext4 bs=1M count=1024
# 将其格式化成为 ext4 格式
mkfs.ext4 arm64.ext4
4、构建文件系统
shell
# 将其挂载在本地的 /mnt 目录, (这里不一定必须 /mnt 目录)
sudo mount -t ext4 arm64.ext4 /mnt/
# 将 ubuntu-base 解压到 文件系统中
sudo tar -xf ubuntu-base-22.04.3-base-arm64.tar.gz -C /mnt/
# sudo tar -xf ubuntu-base-22.04.3-base-riscv64.tar.gz -C /mnt/
# apt 下载安装 qemu-user-static, 包含了 qemu-aarch64-static
sudo cp /usr/bin/qemu-aarch64-static /mnt/usr/bin/
# sudo cp /usr/bin/qemu-riscv64-static /mnt/usr/bin/
# 拷贝主机中的网络信息到镜像中,方便后续用 apt 安装软件(参考的博客里说的,暂未进一步验证)
sudo cp /etc/resolv.conf /mnt/etc/
# 安装内核模块
# 进入 linux 的配置编译路径
# INSTALL_MOD_PATH 指定内核模块安装的目标路径
# 模块将被安装到挂载点 `/mnt` 下, 这通常用于当您正在为一个不同于当前运行的系统(如嵌入式系统或不同的根文件系统)构建模块
cd ~/linux-6.7
sudo make modules_install ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- INSTALL_MOD_PATH=/mnt
# sudo make modules_install ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- INSTALL_MOD_PATH=/mnt
注意:qemu-user-static 建议使用 apt 安装的
当我使用从 github 上下载的 qemu-aarch64-static,会存在问题,当时用
sudo apt install qemu-user-static
下载的 qemu-aarch64-static 就没有问题(暂时不清楚原因)
5、chroot
chroot
(change root)命令在 Unix 和类 Unix 系统中用于改变当前运行进程及其子进程的根目录。为了使
chroot
环境正常工作,您可能需要复制或挂载一些必要的文件和目录(如/dev
,/proc
,/sys
等)到新的根目录下。如果您的主系统和
chroot
环境的架构不同(例如,主系统是 x86_64,而chroot
环境是针对 ARM 构建的),则会出现执行格式错误。二进制文件需要与宿主系统的处理器架构相匹配。
上面的 qemu-aarch64-static
就是为了在 x86 上模拟 arm,如果不添加这个执行文件,chroot
则会失败
shell
# 执行 chroot 需要挂载一些必要的目录(也是参考的博客里说明的)
# 其中 proc、sys 可以让 lscpu 命令查看到当前 cpu 的信息
sudo mount -t proc /proc /mnt/proc
sudo mount -t sysfs /sys /mnt/sys
sudo mount -o bind /dev /mnt/dev
sudo mount -o bind /dev/pts /mnt/dev/pts
# 执行 chroot, 进入 ubuntu-base(arm64) 的根文件系统
sudo chroot /mnt
这里进入的终端,可以使用你使用的物理机的网络,使用 apt
安装一些包
shell
apt update
# 可能碰到证书等问题, 这就需要:
apt install ca-certificates
apt install systemd vim
# 根据需要安装一些包
# apt install gcc g++ gfortran flex bison
由于我的需求不需要设置用户密码这些,所以并未配置
需要的话 -> 可以参考我前面提到的文档
除此之外,参考文档中的 serial-getty\@.service
不存在,怀疑是本地 ubuntu
系统里的那一个文件
我并未配置,不影响使用
shell
# 当要退出时, 回到原本的终端中, 执行 exit
exit
# 然后卸载磁盘
sudo umount /mnt/proc
sudo umount /mnt/sys
sudo umount /mnt/dev/pts
sudo umount /mnt/dev
sudo umount /mnt
5、Qemu 运行 Ubuntu base
执行时注意路径即可(aarch64)
shell
sudo qemu-system-aarch64 \
-M virt \
-cpu cortex-a72 \
-nographic \
-smp 8 \
-m 16G \
-kernel ../linux-6.7/arch/arm64/boot/Image \
-append "root=/dev/vda rw console=ttyAMA0" \
-netdev tap,id=eth0 \
-device virtio-net-device,netdev=eth0 \
-drive file=arm64.image,if=none,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0
# 切换到 bash 使用体验更好
bash
# 挂载这两个文件系统, 可以让 ubuntu 探测到处理器的信息, lscpu 可以查到相关信息
mount -t proc proc /proc
mount -t sysfs sysfs /sys
# 下面是我的需求, 在前面添加了 iso 的模块之后, 可以挂载, 并且安装
mount -t iso9660 -o ro,exec,loop cpu2017-1_0_2.iso /mnt
启动 riscv 版本
shell
sudo qemu-system-riscv64 \
-M virt \
-nographic \
-smp 8 \
-m 16G \
-kernel ../linux-6.7/arch/riscv/boot/Image \
-append "root=/dev/vda rw console=ttyS0" \
-netdev tap,id=eth0 \
-device virtio-net-device,netdev=eth0 \
-drive file=riscv64.image,if=none,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0
# 切换到 bash 使用体验更好
bash
# 挂载这两个文件系统, 可以让 ubuntu 探测到处理器的信息, lscpu 可以查到相关信息
mount -t proc proc /proc
mount -t sysfs sysfs /sys
# 下面是我的需求, 在前面添加了 iso 的模块之后, 可以挂载, 并且安装我使用过程中在 `qemu` 中 `apt` 从网上下载包是有问题的(上网还是有点困难),但是本地挂载文件系统,然后 `chroot` 再 `apt` 是可以正常下载的,所以折衷了以下,**需要的包通过本地 chroot 来进行安装依赖的包,然后进入 qemu 中使用**
mount -t iso9660 -o ro,exec,loop cpu2017-1_0_2.iso /mnt
注:我使用过程中在 qemu
中 apt
从网上下载包是有问题的(上网还是有点困难),但是本地挂载文件系统,然后 chroot
再 apt
是可以正常下载的,所以折衷了以下,需要的包通过本地 chroot 来进行安装依赖的包,然后进入 qemu 中使用
Spec cpu2017
可以正常跑起来了
基本可以满足我的需求,但是还是有点取巧了
关于 qemu ubuntu-base
配置联网,还在学习中,有熟悉的大佬可以评论
附录:Qemu 运行 (ARM64、RISC-V)Ubuntu
关于这部分,正好有 Ubuntu 官方的示例:
https://wiki.ubuntu.com/ARM64/QEMU
https://wiki.ubuntu.com/RISC-V/QEMU
参考官方的示例,可以在 qemu 中执行 arm64 以及 riscv 版本的 ubuntu server
有一点比较隔应,arm64 的版本的 user 以及 password 不知道,也没在官网上找到,这个不敢保证
riscv 版本可以在上述文档中找到关于 user 以及 password 的描述
总体来说,这种方式很快并且便捷,但是体量比 ubuntu-base 大很多,所以也会慢很多,在 qemu 或嵌入式中还是推荐 ubuntu-base 制作根文件系统
其中 -m
指定内存、-smp
指定核心数量,可以给大一点,如下:
shell
# 其中的mac地址根据官方的脚本随机生成
sudo qemu-system-aarch64 \
-m 8G -smp 8 -cpu cortex-a57 -M virt -nographic \
-pflash /usr/share/AAVMF/AAVMF_CODE.fd \
-pflash flash1.img \
-drive if=none,file=jammy-server-cloudimg-arm64.img,id=hd0 -device virtio-blk-device,drive=hd0 \
-netdev type=tap,id=net0 -device virtio-net-device,netdev=net0,mac=00:16:3e:3d:74:0f
shell
qemu-system-riscv64 \
-machine virt -nographic -m 2048 -smp 4 \
-bios /usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.bin \
-kernel /usr/lib/u-boot/qemu-riscv64_smode/uboot.elf \
-device virtio-net-device,netdev=eth0 -netdev user,id=eth0 \
-device virtio-rng-pci \
-drive file=ubuntu-22.04.3-preinstalled-server-riscv64+unmatched.img,format=raw,if=virtio