1 环境及软件包准备
本教程是在ubuntu系统上进行的模拟,ubuntu系统可以安装在物理机或虚拟机上,考虑性能问题,优先选择物理机安装。本教程ubuntu系统选用软件版本如下表所示:
在进行模拟之前,需提前将软件包下载并上传至ubuntu目录(可选任意目录,本教程选择/home/xt目录),如下所示:
2 ubunut 操作系统更换国内源
为了提高下载速度,建议将ubuntu源更换成国内源,本教程选择更换成阿里源。更换步骤如下:
2.1 登录ubuntu后台,并切换成root用户
2.2 依次执行如下指令进行更换
#mv /etc/apt/sources.list /etc/apt/sourses.list.backup #备份sources.list文件
#vim /etc/apt/sources.list #新建sources.list文件并添加以下内容
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
添加截图如下所示
添加完成后按ESC进入命令模式然后:wq保存退出。
2.3 执行如下指令进行更新
#apt update #更新源
#apt upgrade #更新已安装的软件包
3 qemu安装
Qemu是一个开源的托管虚拟机,通过纯软件来实现虚拟化模拟器,几乎可以模拟任何硬件设备。本教程使用qemu来模拟aarch64架构的arm平台。
如果ubuntu系统已经安装了qemu,那么需要先参考8.1章节进行qemui卸载。
3.1进入ubuntu后台/home/xt目录下
#cd /home/xt
3.2解压qemu-6.0.0.tar.xz软件包
#tar xvf qemu-6.0.0.tar.xz
3.3进入qemu目录
#cd qemu-6.0.0
3.4执行./configure,报错找不到ninja
3.4.1 安装ninja
#git clone git://github.com/ninja-build/ninja.git && cd ninja #下载ninja并进入ninja目录
#./configure.py --bootstrap #执行配置文件,该步骤如果报错,执行如下指令
#apt-get install python
#apt-get install re2c
重新执行# ./configure.py --bootstrapa
#cp -r ninja /usr/bin/
执行如下指令确认ninja安装成功
#ninja --version
如果报错,执行如下指令
#apt-get install ninja-build
3.4.2 重新执行3.4
如果还报错ERROR: glib-2.48 gthread-2.0 is required to compile QEMU,执行如下指令:
#apt-get install build-essential zlib1g-dev pkg-config libglib2.0-dev binutils-dev libboost-all-dev autoconf libtool libssl-dev libpixman-1-dev libpython-dev python-pip python-capstone virtualenv
3.5 编译qemu(该步骤耗时大约30min)
#make
3.6安装qemu
#make install
3.7 验证qemu安装成功
安装完成之后,命令行输入qemu按tab键会自动补齐则说明安装成功(图下所示查询版本)
4 安装arm交叉编译器
因为我们是在x86平台上进行编译,而运行的平台是ARM系统,这2个平台的指令集不一样,所以需要交叉编译得到ARM系统上可以执行的程序。本次教程中使用的交叉编译工具为aarch64-linux-gnu-,依次执行如下指令进行交叉编译工具的安装。
4.1 查询当前可安装的版本
#apt-cache search aarch64
4.2 安装gcc交叉编译器
#sudo apt-get install gcc-8-aarch64-linux-gnu
4.3 安装g++交叉编译器
#sudo apt-get install g+±8-aarch64-linux-gnu
4.4安装没有版本号的gcc交叉编译器
#sudo apt-get install gcc-aarch64-linux-gnu
4.5 安装没有版本号的g++交叉编译器
#sudo apt-get install g+±aarch64-linux-gnu
5 内核配置及编译
内核kernel的作用也是不言而喻的,就相当于我们的Windows操作系统,没有这个操作系统,硬件就是一堆废铁。当系统启动的时候,会把内核加载到内存中,然后从内核的入口地址开始执行。
依次执行如下步骤进行内核的配置及编译。
5.1进入ubuntu后台/home/xt目录下
#cd /home/xt
5.2解压linux-5.12.9.tar.xz软件包
#tar xvf linux-5.12.9.tar.xz
5.3进入linux目录
#cd linux-5.12.9
5.4 执行如下指令进行内核配置
#export ARCH=arm64
#export CROSS_CONMPILE=aarch64-linux-gnu-
#make defconfig
#make menuconfig #如果该步报错,执行
#apt-get install libncurses* flex bison
重新执行make menuconfig,出现如下图所示界面
依次进行如下两项配置。
选择 “General setup ”,将“Initial RAM filesystem and RAM disk (initramfs/initrd) support”选中;
选择“Device Drivers”-“Block devices”,将RAM block device support选中,并设置Default RAM disk size (kbytes)为合适的大小(不小于文件系统镜像大大小)。
5.5 生成内核镜像(此步耗时大约30min)
#make Image
镜像编译成功后如图所示,编译得到内核文件arch/arm64/boot/Image,qemu启动时需要指定使用这个映像文件。
6 制作根文件系统
内核在启动之后、执行到最后步骤时,需要挂载根文件系统,然后执行文件系统中指定的执行程序。
6.1进入ubuntu后台/home/xt目录下
#cd /home/xt
6.2解压busybox-1.25.0.tar.bz2软件包
#tar xjvf busybox-1.25.0.tar.bz2
6.3进入busybox目录
#cd busybox-1.25.0
6.4 执行如下指令配置编译环境
#make defconfig
#make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
#make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- install
6.5 在/home/xt/下制作rootfs根目录
#cd /home/xt
#mkdir rootfs #创建rootfs文件夹
#cd rootfs #进入rootfs目录
#mkdir lib dev proc etc #创建lib dev proc etc文件夹
#cp busybox-1.25.0/_install/* -r rootfs/ #将_install文件夹下生成的命令文件等拷贝到rootfs文件夹下
#cp -P /usr/aarch64-linux-gnu/lib/* rootfs/lib/ #从工具链中复制运行库到lib目录下(首先创建lib目录)
#cp -r busybox-1.25.0/examples/bootfloppy/etc/* rootfs/etc/
修改文件rootfs/etc/init.d/rcS(增加mount -t proc proc /proc)
#vim rootfs/etc/init.d/rcS
进入rootfs目录
#cd /home/xt/rootfs
创建4个tty终端设备(c代表字符设备,4是主设备号,1~4分别是次设备号)
#mknod dev/tty1 c 4 1
#mknod dev/tty2 c 4 2
#mknod dev/tty3 c 4 3
#mknod dev/tty4 c 4 4
创建终端和回收站
#mknod console c 5 1
#mknod null c 1 3
6.6 执行如下指令生成SD卡镜像
#dd if=/dev/zero of=rootfs.ext3 bs=1M count=32 #创建一个大小为32M的文件rootfs.ext3
#mkfs.ext3 rootfs.ext3 #格式化生成的ext3文件系统
#mkdir tmpfs #创建tmpfs文件夹
#mount -t ext3 rootfs.ext3 tmpfs/ -o loop #挂载
#cp -r rootfs/* tmpfs/ #复制
#umount tmpfs #卸载
7 qemu启动及测试示例
根据测试目标的不同,分为如下两种测试方法。7.1适合不关注应用底层,只需要在os上层测试的应用程序;7.2适合在裸机(cpu)上进行测试的程序。
7.1 linux内核下应用程序测试
7.1.1 执行如下指令进行qemu启动arm虚拟机
#qemu-system-aarch64 -machine virt -cpu cortex-a72 -nographic -m 1024 -smp 2 -kernel linux-5.12.9/arch/arm64/boot/Image -initrd rootfs.ext3 -append “root=/dev/ram0 rdinit=/linuxrc console=ttyAMA0”
运行成功截图如下所示:
7.1.2 简单测试hello-world应用程序
a. 在Ubuntu任意一个目录(本教程为/home/xt),编写HelloWorld可执行程序hello.c:
#include <stdio.h>
int main()
{
printf(“HelloWorld! \n”);
return 0;
}
b. 交叉编译hello.c,得到可执行程序hello:
#aarch64-linux-gnu-gcc hello.c -o hello
c. 把hello可执行程序复制到磁盘镜像rootfs.ext3中
#mount -o loop rootfs.ext3 tmpfs/ #挂载
#cp myhello tmpfs/ #复制
#umount tmpfs #卸载
d. 执行hello程序
再次执行7.1步骤启动虚拟机,此时可以在根目录下面看到myhello文件,直接执行即可看到输出结果。
7.1.3 测试程序示例
将xt_dhry_os上传到ubuntu任意目录
#unzip xt_dhry_os #解压
#cd xt_dhry_os #进入xt_dhry_os目录
#make clean #清除之前的编译结果
#make #编译
#./run #启动arm虚拟机
运行截图如下所示(截图只显示一部分)
进入arm虚拟机之后,执行
#./dhry
执行结果如下所示(截图只显示一部分)
退出qemu模拟程序:先按Ctrl+A,再按X。
7.2 裸机测试程序
将如下xt_hello文件夹上传到ubuntu任意目录
#unzip xt_hello #解压
#cd xt_hello #进入xt_hello目录
#make clean #清除之前的编译结果
#make #编译
#./run #启动测试程序
运行截图如下所示
退出qemu模拟程序:先按Ctrl+A,再按X。
8 地址映射
请参考文件:xx(目录)/qemu-6.0.0/hw/arm/virt.c,部分内容如下所示。
如果需要测试源码,联系我:982833950@qq.com