控制板

使用 QEMU 模拟嵌入式 Linux 系统

使用 QEMU 模拟嵌入式 Linux 系统

 

1. 简介

嵌入式软件开发依赖于嵌入式硬件设备,如开发板、外部模块设备等,但如果调试工作与外设无关,则无需购买硬件即可使用QEMU模拟内核调试。

它可用于 Linux 和 Windows 主机以及模拟的 PowerPC、ARM、MIPS 和 SPARC 目标。 QEMU 采用在主机和目标处理器之间提供最小转换层的方法。 主机处理器是运行仿真器的处理器,目标处理器是被仿真的处理器。

下面详细介绍搭建QEMU开发环境的过程。

 

2。 环境

2.1 使用环境

* Ubuntu-18.04.1

或者:

* 电脑:Windows10

* 虚拟机:VirtualBox-5.18

* 虚拟操作系统:Ubuntu-18.04.1

* 模拟开发板:vexpres

2.2 搭建环境时用到的工具

* qemu-4.2.0

* linux-4.14.172 (Linux 内核)

* u-boot-2017.05

*busybox-1.31.1

*arm-linux-gnueabi-gcc

将所有相关文件放在 /home/joe/qemu

3.安装交叉编译工具

# sudo apt 安装 gcc-arm-linux-gnueabi

 

检查是否安装成功

$arm-linux-gnueabi-gcc -v

使用内置规格。

COLLECT_GCC=arm-linux-gnueabi-gcc

COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/arm-linux-gnueabi/7/lto-wrapper

目标:arm-linux-gnueabi

配置:../src/configure -v –with-pkgversion='Ubuntu/Linaro 7.5.0-3ubuntu1~18.04′--with-bugurl=file:///usr

线程模型:posix

gcc 版本 7.5.0(Ubuntu/Linaro 7.5.0-3ubuntu1~18.04)

 

4.配置和编译Linux内核

4.1 下载Linux内核

从 www.kernel.org 下载所需的内核版本。

这里我下载了相对最新的长期支持的内核版本linux-4.4.157

wget的 https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.157.tar.xz  到 /qemu 目录

4.2 解压Linux内核

# tar xvJf linux-4.4.157.tar.xz

4.3 编译Linux内核

// 进入内核源文件目录

# cd linux-4.4.157

使 CROSS_COMPILE=arm-linux-gnueabi-ARCH=arm vexpress_defconfig

make CROSS_COMPILE=arm-linux-gnueabi-ARCH=arm menuconfig

如果运行 menuconfig 显示缺少 ncurses 包,只需运行以下命令安装即可)

$ sudo apt-get 安装 libncurses5-dev

进入菜单配置,进行如下设置

使用交叉工具链编译

编译成功后,在目录下生成内核镜像文件

arch/arm/boot, zImage 和 dtb 可以复制到单独的文件夹中,方便使用

 

5. 安装 QEMU 工具

5.1 安装 QEMU

* wget https://download.qemu.org/qemu-4.2.0.tar.xz

* tar xvJf qemu-4.2.0.tar.xz

* cd qemu-4.2.0

5.2 配置QEMU前安装依赖包

# apt 安装 zlib1g-dev
# apt 安装 libglib2.0-0 libglib2.0-dev
# apt 安装 libsdl1.2-dev
# apt 安装 libpixman-1-dev libfdt-dev

为了防止编译后文件杂乱,创建builder目录作为编译的中间目标路径。

配置、编译和安装 QEMU。

5.3 配置QEMU支持arm架构下的所有板卡

# ../configure --target-list=arm-softmmu --audio-drv-list=

如果出现以下提示时缺少pixman,

使用 sudo apt-get install libpixman-1-dev 安装它。

5.4 查看QEMU版本

5.5 查看QEMU支持的开发板

5.6 运行 QEMU

# qemu-system-arm -M vexpress-a9 -m 512M -kernel ./zImage -dtb ./vexpress-v2p-ca9.dtb -ngraphic -append “console=ttyAMA0”

要么:

$密码

/家/乔/qemu

# qemu-system-arm -M vexpress-a9 -m 512M -kernel linux-.4.157/arch/arm/boot/zImage -dtb linux-4.4.157/arch/arm/boot/dts/vexpress-v2p-ca9. dtb -nographic -append “console=ttyAMA0”

为了更好的测试和启动qemu,可以创建启动脚本start.sh,并赋予脚本运行权限chmod +x start.sh

 

#!/斌/庆典

 

qemu 系统臂 \

-M vexpress-a9 \

-m 512M \

-内核/home/joe/jemu/linux-4.4.157/arch/arm/boot/zImage \

-dtb /home/joe/jemu/linux-4.4.157/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \

-地理\

-附加“控制台= ttyAMA0”

 

6.制作根文件系统

使用busybox制作一个简单的根文件系统。

6.1 下载busybox工具

从 https://busybox.net/downloads/ 下载busybox

# wget https://busybox.net/downloads/busybox-1.31.1.tar.bz2

# tar xjvf busybox-1.31.1.tar.bz2

# cd busybox-1.31.1

# 进行定义

# 使 CROSS_COMPILE=arm-linux-gnueabi-

# 安装 CROSS_COMPILE=arm-linux-gnueabi-

提示如下信息,说明安装成功。

安装完成后,生成的目标文件默认在./_install目录下。

 

6.2 生成根文件系统

6.2.1 编译安装busybox

# mkdir 根文件系统

# sudo cp -r _install/* rootfs/

6.2.2 添加glibc库,在根文件系统中添加loader和动态库

# sudo cp -r _install/* rootfs/

# sudo cp -p /usr/arm-linux-gnueabi/lib/* rootfs/lib/

6.2.3 创建4个tty终端设备(c代表字符设备,4是主设备号,1~4分别是次设备号)

 

6.3 制作SD卡文件系统镜像

6.3.1 生成空的SD卡镜像

# dd if=/dev/zero of=rootfs.ext3 bs=1M count=32

6.3.2 将 SD 卡格式化为 exts 文件系统

# mkfs.ext3 根文件系统.ext3

6.3.3 烧录rootfs到SD卡

# sudo mount -t ext3 rootfs.ext3 /mnt -o 循环

# sudo cp -rf rootfs/* /mnt/

# sudo 卸载 /mnt

 

7. 验证

7.1 启动 Qemu

运行以下命令进行测试,检查编译后的内核是否可以成功运行

# sudo qemu-system-arm -M vexpress-a9 -m 512M -kernel ~/qemu/zImage –dtb ~/qemu/vexpress-v2p-ca9.dtb -ngraphic -append “console=ttyAMA0”

或者使用脚本:

 

在上面的测试中,内核会报panic,提示我们缺少根文件系统。

以上问题是由于x86环境下busybox工具生成的。

我们在安装busybox时使用了make install,所以你应该使用

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-安装

 

编译工具生成arm平台使用的busybox工具

# 文件 rootfs/bin/busybox

rootfs/bin/busybox:ELF 32 位 LSB 可执行文件,ARM,EABI5 版本 1 (SYSV),动态链接,解释器 /lib/ld-,适用于 GNU/Linux 3.2.0,BuildID[sha1]=cbcd33b8d6c946cb19408a5e8e714f554

 

7.2 再次验证

现在Qemu已经启动Linux内核并成功挂载文件系统,可以通过串口终端与系统进行简单的功能交互。 打印过程中无法运行/etc/init.d/rcS的问题,只需要添加/etc/init.d/rcS文件即可。 文件的内容可以是提示语句。

 

7.3 退出 QEMU

退出qemu的两种方式

* 在另一个终端输入中:kill all qemu-system-arm

* 在Qemu中输入:Ctrl+A; X

QEMU:终止

 

8.通过u-boot启动Linux内核

嵌入式系统通常包括:u-boot、kernel、rootfs、appfs。 这些部件在ARM开发板上的位置关系如下图所示

 

引导加载程序 引导参数 核心 根文件 应用程序

 

Rootfs 可以在板载或 PC 上运行

 

8.1 准备U-boot

8.1.1 下载u-boot

http://ftp.denx.de/pub/u-boot/,我们使用:u-boot-2021.01.tar.bz2

# tar -jxvf u-boot-2018.09.tar.bz2

8.1.2 编译u-boot

# vim 生成文件

CROSS_COMPILE = arm-linux-gnueabi-

# vim 配置.mk

ARCH = 手臂

# 制作 vexpress_ca9x4_defconfig,错误

需要:sudo apt install bison

sudo apt 安装 flex

然后:#make -j4 错误

需要:导出 CROSS_COMPILE=arm-linux-gnueabi-

出口 ARCH=臂

再次:# make vexpress_ca9x4_defconfig

#make -j4

 

 8.1.3 测试,启动u-boot

$ sudo qemu-system-arm -M vexpress-a9 -m 512M -kernel u-boot-2021.01/u-boot –ngraphic

 

8.2 内核配置编译

使用 u-boot 启动内核镜像:

需要将内核编译成uImage格式,

需要指定uImage在内存中的加载地址

编译内核时指定:make LOADADDR=? uImage -j4

 

# cd /home/joe/qemu/linux-4.4.157

# 使 LOADADDR=0x60003000 uImage -j4

 

u-boot编译完成后,在tool文件夹下会生成一个mkimage文件,把这个文件拷贝到交叉编译目录下的bin文件夹下。

$ cd qemu/linux-4.4.157

错误:

$ sudo apt 安装 u-boot-tools

获取 uImage

9.QEMU网络功能设置

当Qemu虚拟机在u-boot上启动时,需要将uImage加载到内存中,通过TFTP服务器可以将uImage下载到内存中的指定地址。

9.1 检查主机内核是否支持tun/tap模块

// 安装桥接网络依赖的两个工具

# sudo apt 安装 uml-utilities bridge-utils

创建tun设备文件:/dev/net/tun(一般是自动创建的)

修改/etc/network/interfaces(配置网络,重启生效)

# sudo vim /etc/网络/接口

auto loiface lo inet loopbackauto enp0s3 // 虚拟网卡名称auto br0iface br0 inet dhcpbridge_ports enp0s3

 

永不重启

# 重启

然后查看Qemu的网络环境

虚拟网口br0是Qemu虚拟机与Linux主机通信的网口。

 

10.安装TFTP服务器

Qemu仿真开发板启动uImage时创建TFTP服务器将uImage下载到内存

 

10.1 安装tftp工具

 

$ apt-get 安装 tftp-hpa tftpd-hpa xinetd

 

10.2 修改配置文件,设置TFTP服务器目录

# sudo vim /etc/default/tftpd-hpa

......

TFTP_DIRECTORY="/home/joe/tftpboot"

......

10.3 在Linux主机上创建tftp目录

# mkdir /home/joe/tftpboot

# chmod 777 /home/joe/tftpboot

 

10.4 重启tftp服务

# sudo /etc/init.d/tftpd-hpa 重启

 

10.5 在u-boot中设置内核启动参数

将 uImage 和 cexpress-v2p-ca9.dtb 复制到 tftpboot

启动Qemu进行验证

 

$ sudo qemu-system-arm -M vexpress-a9 -m 512M -kernel u-boot-2021.01/u-boot –nographic -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 -sd rootfs.分机3

 

现在rootfs目录就是一个简单的根文件系统,可以做成镜像文件,可以把镜像文件烧录到开发板上,也可以用Qemu中的u-boot启动Linux内核挂载到开发板上镜像文件。 它也可以设置为通过 NFS 网络文件系统启动。

 

11.挂载NFS文件系统

11.1 安装配置NFS服务

11.1.1安装

$ sudo apt 安装 nfs-kernel-server

 

11.1.2 配置

$ sudo mkdir /home/joe/qemu/rootfs

$ sudo chown nobody:nogroup /home/joe/qemu/rootfs

$ sudo chmod 777 /home/joe/qemu/rootfs

$ sudo nano /etc/exports

添加:/home/joe/qemu/rootfs *(rw,sync,no_root_squash)

 

重启 nfs 服务器:

$ sudo /etc/init.d/nfs-kernel-server restart

或者: $systemctl restart nfs-kernel-server

 

检查是否创建了NFS共享目录

$ sudo showmount –e

Linux主机在使用NFS网络文件系统时需要关闭系统防火墙,否则系统运行时会出现异常。

 

结论

希望在这篇博客的帮助下,您对 QEMU 有了更多的了解。 上面展示的所有技术都用于我们程序的各种提交。 没有一种单一的、固定的方式来模拟 QEMU。 探索不同的技术,看看什么适合你。 熟悉这些知识,您会惊讶于它如何以意想不到的方式帮助您。

联系我们