🔌嵌入式-002-使用qemu模拟arm64

type
status
date
slug
summary
tags
category
icon
password

更新记录

2022.03.29
编写文档
2022.07.03
增加 Uboot 制作章节
2022.11.20
适配 openEuler 22.09
2023.01.13
完善 qemu 测试代码
2023.06.15
增加 9p 文件系统

1. 前言

如果没有 aarch64 开发板,又想进行相关代码的实验学习,可以尝试使用 qemu 模拟硬件环境来达到目的。
网上教程很多,有些东西写的不够透彻,对新手而言过于困难。我在参照网友之前操作的基础上,结合自己实践经验,记录下操作过程,方便日后整理使用。
开始之前,有以下几点说明:
  1. 模拟器并不能真的代替开发板
硬件实际情况多种多样,有些东西还是要看真实硬件的设计参数,做出相应的调整,最后才可以达到目的。
  1. 尽量使用包管理代替手动编译
网上教程大多数都提供了手动编译的教程,此处我强烈不建议在“使用包管理可以达到相同目的的情况下,仍然机械的参考教程去手动编译,除非你弄懂了每个编译参数的含义”。
  1. 学会熟悉内核式的配置教程
现在很多软件的构建过程,都参考了内核的 menuconfig 设计,比如 uboot, buildroot, busybox 等等。

2. 环境准备

2.1. host 和 target

host 就是指宿主环境,target 就是目标环境,即能够编译的环境:
  1. 有可以编译的 ARM 机器
  1. 有可以编译的 X86 机器
如果手边有可以编译 ARM 的机器,可以不需要考虑交叉编译的事情。
如果手边只有一台 X86 机器,需要考虑交叉编译器的事情。在 X86 平台,交叉编译器后很多,有针对嵌入式优化的和没有针对嵌入式优化的。比如:gcc-arm-linux-gnueabi,gcc-arm-none-eabi,gcc-9-aarch64-linux-gnu 等,它们之间的区别不在本篇讨论范围内。

2.2. 实验环境

如果采用的编译机器为 X86 环境,则需要先安装交叉编译器。

2.2.1. Ubuntu 20.04

内容
版本
操作系统
Ubuntu 20.04 LTS
内核
4.19.130
交叉编译器
gcc-9-aarch64-linux-gnu
注:Ubuntu16 上内核编译,相同的方法依然通过,只是交叉编译器版本不同。Ubuntu 中安装交叉编译环境的方法如下,如果手边有 ARM 架构的可编译机器,跳过此步骤。

2.2.2. openEuler 22.09

通用方法:可以选择下载 linaro 编译好的交叉编译器,但是最新的版本只到 gcc7。下载地址:https://releases.linaro.org/components/toolchain/binaries/latest-7/ 。
专有方法:此处介绍 openEuler 22.09 下交叉编译器安装。
编辑 .bashrc 或 .zshrc,将 /home/test/openeuler_gcc_arm64le/bin 加入 PATH 变量。与 Ubuntu 不同的是,openEuler 的交叉编译器前缀为:aarch64-openeuler-linux-gnu-

2.3. 安装 qemu

2.3.1. 安装依赖

在 Ubuntu 下:
在 CentOS 下:

2.3.2. 异架构处理

所谓异架构,指的是 host 和 chroot 环境不同的情况,如想在 X86_64 切换到 arm64,或者反过来。
异架构模式需要借助特殊的技巧,这里使用 qmue 提供的 qemu-user-static 包。 CentOS 下没有提供这个包,因此可以自己编译、下载已经构建好的二进制。
  • Debian / Ubuntu
  • CentOS

2.3.3. 手动编译

3. UBoot 制作(可选)

注:本步骤非必要步骤,只是为了更加真实的模拟实际开发情况,一般不会用到。
下载 uboot 源码,编译适用于 QEMU 的 uboot。

3.1. 编译

3.2. 测试

在 QEMU 中模拟启动:

4. 内核制作

如果下载不下来,可以选择国内镜像站点进行加速,比如阿里云的内核站点:
内核配置需要注意的几点:
  1. 如果需要测试网络功能,需要打开 qemu 所支持的网卡,比较简单的可以使用 E1000:
  1. 如果需要使用 mtdparts 功能,确保打开 mtd 的支持:
  1. 如果要使用 ramfs 功能,需要如下配置:
  1. 示例配置如下:

4.1. 测试

4.2. 问题

  1. 如果出现卡主无法加载,请尝试更换版本大于 3.0 的 qemu 软件。
  1. 如果出现 unable mount root fs on unknown-block... 即表示内核可以启动,缺少文件系统的挂载。

5. 文件系统制作

5.1. 基于 Docker 镜像

定制根文件系统的方法有很多,这里介绍两种:基于 ubuntu base 项目和基于 Busybox 项目的划分。

5.1.1. 安装依赖

5.1.2. 制作 rootfs

5.1.3. 使用 qemu 测试

这里启动依然显示 /bin/sh: 0: can't access tty; job control turned off 不知道为什么……

5.2. 基于 busybox

首先要编译 busybox,可以选择默认配置(defconfig)、最小化配置(allnoconfig)或者全配置(allyesconfig)。

5.2.1. 默认配置

如果选择自定义配置,busybox 里面需要修改几点:
  1. 使用 make defconfig 生成默认配置
  1. build options 中,勾选 build static binary (no shared libs)
  1. 修改交叉编译器前缀为 aarch64-linux-gnu-
  1. 选择合适的 busybox 版本,比如(16.04 搭配 1.26,20.04 搭配 1.33)
notion image

5.2.2. 编译方法

5.2.3. 优化镜像

5.2.3.1. 创建结构文件

5.2.3.2. 创建 inittable

5.2.3.3. 创建 rcS

5.2.3.4. 创建 fstab

profile 文件内容如下:

5.2.4. 制作镜像

5.2.4.1. 制作 ramfs

5.2.4.2. 制作 image-initrd

5.2.4.3. 制作 cpio-initrd

5.2.4.4. 9p 文件系统

9p 文件系统测试:
虚拟机使用 9p 文件系统:

5.2.4.5. 制作 jffs2

5.2.4.6. busybox 存在的问题

  1. 静态编译的 busybox 无法使用 dns 功能,原因在于 dns 的依赖库 libnss 设计就是为了动态库实现。如果采用 GLibc 编译,则需要开启参数 -enable-libnss-static 参数,很多发行版没有开启该功能。

5.2.5. qemu 测试

5.2.5.1. ramdisk 测试

5.2.5.2. ramfs 测试

6. initramfs 与 ramdisk 比较

上面说的 ramfs 其实不是 内存文件系统,而是特指 initramfs。
ramfs 与 ramdisk 比较而言:
技术 => 实现 => 问题
initramfs => ramfs => 仅支持 cpio 格式
ramdisk => initrd => ramdisk 传统技术,占用空间大

6.1. 相同点

  1. 都是运行在内存中的根文件系统;
  1. 可以选择存储方式,比如可以跟内核打包到一块,也可以做成 img 单独烧写到 Flash;
  1. 都需要开启内核配置 General setup —>
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support

6.2. 不同点

  1. initramfs 仅支持 cpio 格式,可以压缩也可以不压缩,默认启动为 /init,而 ramdisk 默认是 /initrc;
  1. initramfs 可以独立于 initrd 单独存在,但是要支持 initrd 就必须先支持 ramdisk,即 CONFIG_BLK_INITRD 和 CONFIG_BLK_DEV_RAM;
  1. 实际使用中,initrd 用的基本都是 ramdisk 技术,最后解析、写入 ramdisk 设备 /dev/ram 或 /dev/ram0 中。
  1. 使用 initramfs,命令行参数不需要 "initrd=" 和 "root=" 参数,但需要指定 init 参数;
  1. initramfs 整体优于 ramdisk,启动速度更快,原因如下:
  • initramfs 主要经历 Memory Cache -> 内核 -> 用户 root 空间
  • ramdisk 主要经历 设备块/dev/ram -> 文件系统 -> 内核 -> 用户 root 空间
notion image

7. 参考

  1. 利用Qemu-4.0虚拟ARM64实验平台
  1. 【原创】从Ubuntu-base构建ubuntu rootfs 系统(以x86_64和arm为例)
嵌入式-001-串口入门使用指北-001-archlinux
飞行日志
常用链接
韭菜搞钱
三省吾身
无问东西
知行合一