ubuntu-base(arm64与riscv64) 根文件系统, 并用qemu启动

ubuntu-base(arm64与riscv64) 根文件系统

有个小需求,是在 arm64riscv64 上都跑起来 speccpu 2017

首先在 Qemu 上跑起来,需要考虑需要的【Linux 内核、根文件系统、Bootloader 】,其中 Bootloader 在 Qemu 中可以很简化,对于内核可以使用kernel参数加载,对于根文件系统则要费一些功夫

提前结论:我使用过程中在 qemuapt 从网上下载包是有问题的(上网对目前的我还是有点困难,还得学习,后续学会网络再写一份博客),但是本地挂载文件系统,然后 chrootapt 是可以正常下载的,所以暂时折衷了以下,需要的包通过本地 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安装、交叉编译工具链、内核编译

这些内容可以参考我的其他博客:

其中对于内核的编译,有一点要说明

配置、编译都要指定架构 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.imageext4 格式的虚拟磁盘

也可以是其他名字,我这里只是为了区分 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

注:我使用过程中在 qemuapt 从网上下载包是有问题的(上网还是有点困难),但是本地挂载文件系统,然后 chrootapt 是可以正常下载的,所以折衷了以下,需要的包通过本地 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
相关推荐
新子-存在了6 分钟前
linux中 mysql备份
linux·运维·mysql
最后一个bug8 分钟前
rt-linux中使用mlockall与free的差异
linux·c语言·arm开发·单片机·嵌入式硬件·算法
ZHOUPUYU8 分钟前
VMware虚拟机超详细安装Linux教程(最新版)
linux·运维·服务器·windows·微软·centos·虚拟机
初级代码游戏18 分钟前
关于linux的ld.so.conf.d
linux·运维·服务器
xianwu54324 分钟前
反向代理模块。开发
linux·开发语言·网络·c++·git
m0_7482323929 分钟前
在Linux centos7环境下部署wblogic使用weblogic部署war包项目
linux·运维·服务器
李先静43 分钟前
用 gdbserver 调试 arm-linux 上的 AWTK 应用程序
linux·arm开发·awtk
地球空间-技术小鱼1 小时前
YUM(Yellowdog Updater, Modified)和DNF(Dandified YUM)简介
linux·运维·服务器·笔记·学习
忆源1 小时前
Linux高级--2.4.2 linux TCP 系列操作函数 -- 深层理解
linux·网络·tcp/ip
ZHOUPUYU1 小时前
Centos常用命令,按功能分类,用户和权限管理等
linux·运维·centos