(2023)从零开始用qemu搭建虚拟arm环境 |
您所在的位置:网站首页 › Qemu虚拟机内内存和配置不一致 › (2023)从零开始用qemu搭建虚拟arm环境 |
用qemu搭建虚拟arm环境
引言安装版本
1. VMware + ubuntu20.04 + qemu安装2.安装交叉编译工具3.编译内核kernel4.u-boot编译5.制作根文件系统第一步:下载、编译和安装busybox第二步:形成根目录结构第三步:制作根文件系统镜像
测试HelloWorld应用程序如何关闭qemu虚拟机补充:**关于”make: arm-linux-gnueabihf-gcc: Command not found“问题**关于qemu启动ARM虚拟机运行指令解析
参考文献:
引言
Qemu是什么? Qemu是一个开源的托管虚拟机,通过纯软件来实现虚拟化模拟器,几乎可以模拟任何硬件设备。比如:Qemu可以模拟出一个ARM系统中的:CPU、内存、IO设备等,然后在这个模拟层之上,可以跑一台ARM虚拟机,这个ARM虚拟机认为自己在和硬件进行打交道,但实际上这些硬件都是Qemu模拟出来的。 Qemu的两种模式 1.用户模式(User mode):利用动态代码翻译机制来执行不同主机架构的代码,例如:在x86平台上模拟执行ARM代码,也就是说:我们写一条ARM指令,传入整个模拟器中,模拟器会把整个指令翻译成x86平台的指令,然后在x86的CPU中执行。 2.系统模式(System mode):模拟整个电脑系统,利用其它VMM(Xen, KVM)来使用硬件提供的虚拟化支持,创建接近于主机性能的全功能虚拟机。 简单方式:直接下载别人编译好的映像文件(包含了内核,根文件系统),直接执行即可。 缺点是:别人编译好的也许不适合你的需求,没法定制。 复杂方式:自己下载内核代码、根文件系统代码(例如:busybox),然后进行编译。 优点是:可以按照自己的实际需求,对内核、根文件系统机型裁剪。 在第2种复杂模式中,又可以有2个选择: 2-1. 内核代码、根文件系统代码全部自己手动编译,最后把这些编译结果手动组织在一个文件夹中,形成自己的根目录; 2-2. 利用 buildroot 整个框架,只需要手动进行配置(比如:交叉编译器在本机上的位置、输出路径、系统的裁剪),然后就可以一键编译出一个完整的系统,可以直接烧写到机器! 安装版本VMware Workstation Pro:16.1.1 ubuntu:20.04 64位 qemu:8.1.50 搭建虚拟arm开发板: busybox:1.36.0 kernel:5.10 u-boot:2020.10 1. VMware + ubuntu20.04 + qemu安装参考这篇文章:【VMware + ubuntu20.04 + qemu安装】 下面将正式开始搭建虚拟的arm开发板环境 2.安装交叉编译工具交叉编译器的作用就不需要详细解释了,因为我们是在x86平台上进行编译,而运行的平台是ARM系统,这2个平台的指令集不一样,所以需要交叉编译得到ARM系统上可以执行的程序。 sudo apt-get install gcc-arm-linux-gnueabi验证安装结果 dpkg -l gcc-arm-linux-gnueabi显示如下: 下载内核kernel压缩包 wget https://mirror.bjtu.edu.cn/kernel/linux/kernel/v5.x/linux-5.10.tar.xz这里我们使用 vexpress-a9 这款开发板。vexpress-a9 是 Arm 公司自己设计的一款 4 核 Cortex-A9 开发板,U-Boot、Linux Kernel 和 QEMU 对这款开发板都做了完整的支持。当然,如果想搭其它开发板,也不难,只要qemu和内核对它有成熟的支持就够了。 解压: tar -xvf linux-5.10.tar.xz在解压后的linux-5.10目录下,生成vexpress开发板子的config文件: make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm vexpress_defconfig编译32位kernel: make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm生成的内核镱像位于arch/arm/boot/zImage 设备树 arch/arm/boot/dts/vexpress-v2p-ca9.dtb 补充:编译64位kernel make ARCH=arm64 defconfig CROSS_COMPILE=aarch64-linux-gnu- # 如果需要调整配置选项,则使用menuconfig make ARCH=arm64 menuconfig CROSS_COMPILE=aarch64-linux-gnu- make ARCH=arm64 Image -j8 CROSS_COMPILE=aarch64-linux-gnu-生成的内核镱像位于arch/arm/boot/Image 4.u-boot编译拉取: wget https://ftp.denx.de/pub/u-boot/u-boot-2020.10.tar.bz2下载完后,可以看到 configs 目录下有针对这款开发板的配置文件。ca9x4表示cortexA9架构,4核心,vexpress_ca9x4_defconfig。 ls configs/ | grep vexpress
最终编译生成 elf 格式的可执行文件 u-boot 和纯二进制文件u-boot.bin,其中 QEMU 可以启动的为 elf 格式的可执行文件 u-boot 。 内核在启动之后、执行到最后步骤时,需要挂载根文件系统,然后执行文件系统中指定的执行程序(初始化程序,本文未设置),例如:/etc/rc.local。 如果没有跟文件系统,那么内核在执行到最后就提示:panic…。 根文件系统放在哪里? 其实依赖于每个开发板支持的存储设备,可以放到Nor Flash上,也可以放到SD卡,甚至外部磁盘上。最关键的一点是你要清楚知道开发板有什么存储设备。 本文介绍了使用SD卡做为存储空间,文件格式为ext3格式。 第一步:下载、编译和安装busybox下载busybox1.36.0: wget http://www.busybox.net/downloads/busybox-1.36.0.tar.bz2编译,安装: make defconfig make CROSS_COMPILE=arm-linux-gnueabi- make install CROSS_COMPILE=arm-linux-gnueabi-安装完成后,会在busybox目录下生成_install目录,该目录下的程序就是单板运行所需要的命令。 第二步:形成根目录结构先在Ubuntu主机环境下,形成目录结构,里面存放的文件和目录与单板上运行所需要的目录结构完全一样,然后再打包成镜像(在开发板看来就是SD卡),这个临时的目录结构称为根目录。 首先创建rootfs目录(根目录),根文件系统内的文件全部放到这里: mkdir -p rootfs/{dev,etc/init.d,lib} 把busybox中的文件复制到rootfs根目录下,主要是一些基本的命令: sudo cp busybox-1.20.2/_install/* -r rootfs/ 把交叉编译工具链中的库文件复制到rootfs根目录的lib文件夹下: sudo cp -P /usr/arm-linux-gnueabi/lib/* rootfs/lib/ 创建4个tty端终设备: sudo mknod rootfs/dev/tty1 c 4 1 sudo mknod rootfs/dev/tty2 c 4 2 sudo mknod rootfs/dev/tty3 c 4 3 sudo mknod rootfs/dev/tty4 c 4 4 第三步:制作根文件系统镜像制作根文件系统镜像 根文件系统镜像就相当于一个硬盘,就是把上面rootfs根目录中的所有文件复制到这个硬盘中。 第一种: 生成512M大小的镜像: dd if=/dev/zero of=a9rootfs.ext3 bs=1M count=32格式化成ext3文件系统: mkfs.ext3 a9rootfs.ext3挂载,将文件拷贝到镜像中: sudo mkdir tmpfs sudo mount -t ext3 a9rootfs.ext3 tmpfs/ -o loop sudo cp -r rootfs/* tmpfs/ sudo umount tmpfsqemu启动ARM虚拟机运行: qemu-system-arm -M vexpress-a9 -m 512M -kernel /path/to/kernel/dir/arch/arm/boot/zImage -dtb /path/to/kernel/dir/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 console=ttyAMA0" -sd a9rootfs.ext3“从内核启动打印,到命令行提示符出现” 第二种: 生成512M大小的磁盘镜像: qemu-img create -f raw disk.img 512M把磁盘镜像格式化成ext4文件系统: mkfs -t ext4 ./disk.img将rootfs根目录中的所有文件复制到磁盘镜像中 操作步骤是:创建挂载点-挂载-复制文件-卸载: mkdir tmpfs sudo mount -o loop ./disk.img tmpfs/ sudo cp -r rootfs/* tmpfs/ sudo umount tmpfs使用file指令检查一下: file disk.img
“从内核启动打印,到命令行提示符出现” 测试HelloWorld应用程序在Ubuntu任意一个目录,编写HelloWorld可执行程序hello.c: touch hello.c vi hello.c按i进入输入模式,复制下面代码,然后esc,shift+:,wq保存退出: #include int main() { printf("HelloWorld! \n"); return 0; }交叉编译hello.c,得到arm的可执行程序hello: arm-linux-gnueabi-gcc hello.c -o hello通过file指令,查看一下hello程序: file hello
执行hello程序 再次启动虚拟机,此时可以在根目录下面看到hello文件,直接执行即可看到输出结果。 总结: 在以上的操作步骤中,我们把一个ARM系统在启动应用程序之前,所需要的程序都手动编译、操作了一遍。看一遍很容易就明白,亲手操作一遍印象会更深刻。 这里的操作过程有些还需要继续深入,比如:在系统启动之后,自动挂载宿主机(Ubuntu系统)中的某个文件夹,这样就可以把hello等可执行程序复制到挂载目录中,然后在ARM系统中直接执行了,而不用再执行下面在一连串的操作(停止虚拟机-挂载磁盘镜像-复制文件-卸载-启动虚拟机)。 如何关闭qemu虚拟机停止虚拟机 在Ubuntu另一个终端窗口中,通过killall指令来停止。 killall qemu-system-arm或者直接 Ctrl+a 再按x,直接退出qemu环境。 补充: 关于”make: arm-linux-gnueabihf-gcc: Command not found“问题解决方法:sudo apt-get install gcc-arm* 参考:https://blog.csdn.net/HGGshiwo/article/details/120479087 关于qemu启动ARM虚拟机运行指令解析 qemu-system-arm -M vexpress-a9 -m 512M -kernel /path/to/kernel/dir/arch/arm/boot/zImage -dtb /path/to/kernel/dir/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 console=ttyAMA0" -sd a9rootfs.ext3-M vexpress-a9 模拟vexpress-a9单板,你可以使用-M ?参数来获取该qemu版本支持的所有单板 -m 512M 单板运行物理内存512M -kernel /path/to/kernel/dir/arch/arm/boot/zImage 告诉qemu单板运行内核镜像路径 -nographic 不使用图形化界面,只使用串口 -append “console=ttyAMA0” 内核启动参数,这里告诉内核vexpress单板运行,串口设备是那个tty。 因为不同单板串口驱动类型不尽相同,创建的tty设备名当然也是不相同的。那vexpress单板的tty设备名是哪个呢? 其实这个值可以从生成的.config文件CONFIG_CONSOLE宏找到。 如果搭建其它单板,需要注意内核启动参数的console=参数值,同样地,可从生成的.config文件中找到。 参考文献:一步步教你:如何用Qemu来模拟ARM系统 从零使用qemu模拟器搭建arm运行环境 【十】搭建基于qemu的仿真环境与应用 如果想了解更多细节,包括:创建设备结点,设置初始化进程/etc/rcS,u-boot加载内核等,可参考: 【宅学部落的qemu教程】 或者其他优秀教程 Linux利器:QEMU!用它模拟开发板能替代真开发板? qemu-system-arm功能选项整理 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |