用Qemu模拟ARM(1)

本文详细介绍了如何使用QEMU模拟ARM平台,并通过编译和运行简单的C程序来验证QEMU的正确性。同时,展示了如何使用QEMU运行Linux内核,并制作最小化的文件系统来实现内核的启动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面已经安装并配置了编译链和qemu,现在可以用qemu来模拟arm平台了。

1. Hello, Qemu!

输入下面的代码:

hello.c - hello.c
#include<stdio.h>
int main()
{
    printf("Hello, Qemu!\n");
    return 0;
}

编译并运行:

$ arm-none-linux-gnueabi-gcc -o hello hello.c -static
$ qemu-arm ./hello
$ file hello
hello: ELF 32-bit LSB  executable, ARM, EABI5 version 1 (SYSV), \
 statically linked, for GNU/Linux 2.6.16, not stripped

不加-static变量的话,运行时则需要使用-L选项链接到相应的运行库

$ qemu-arm -L /home/dash/CodeSourcery/\
Sourcery_CodeBench_Lite_for_ARM_GNU_Linux/\
arm-none-linux-gnueabi/libc/  ./hello_1 
Hello, Qemu!
$ file hello_1
hello_1: ELF 32-bit LSB  executable, ARM, EABI5 version 1 (SYSV),\
 dynamically linked (uses shared libs), for GNU/Linux 2.6.16, not stripped

动态编译和静态编译生成的文件大小差别:

$ ls -l -h
total 656K
-rwxr-xr-x 1 dash root 640K Jul  7 18:46 hello
-rwxr-xr-x 1 dash root 6.6K Jul  7 18:48 hello_1

小插曲1:

系统里安装了两套编译链arm-none-eabi-和arm-none-linux-eabi-,很容易让人混淆,可参考编译链的命名规则:

arch(架构)-vendor(厂商名)–(os(操作系统名)–)abi(Application Binary Interface,应用程序二进制接口)

举例说明:

  • x86_64-w64-mingw32 = x86_64 “arch”字段 (=AMD64), w64 (=mingw-w64 是”vendor”字段), mingw32 (=GCC所见的win32 API)
  • i686-unknown-linux-gnu = 32位 GNU/linux编译链
  • arm-none-linux-gnueabi = ARM 架构, 无vendor字段, linux 系统, gnueabi ABI.
  • arm-none-eabi = ARM架构, 无厂商, eabi ABI(embedded abi)

两种编译链的主要区别在于库的差别,前者没有后者的库多,后者主要用于在有操作系统的时候编译APP用的。前者不包括标准输入输出库在内的很多C标准库,适合于做面向硬件的类似单片机那样的开发。因而如果采用arm-none-eabi-gcc来编译hello.c会出现链接错误。

小插曲2:

qemu-arm和qemu-system-arm的区别:

  • qemu-arm是用户模式的模拟器(更精确的表述应该是系统调用模拟器),而qemu-system-arm则是系统模拟器,它可以模拟出整个机器并运行操作系统
  • qemu-arm仅可用来运行二进制文件,因此你可以交叉编译完例如hello world之类的程序然后交给qemu-arm来运行,简单而高效。而qemu-system-arm则需要你把hello world程序下载到客户机操作系统能访问到的硬盘里才能运行。

2. 使用qemu-system-arm运行Linux内核

从www.kernel.org下载最新内核,而后解压

$ tar xJf linux-3.10.tar.xz
$ cd linux-3.10
$ make ARCH=arm versatile_defconfig
$ make menuconfig ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-

上面的命令指定内核架构为arm,交叉编译链为arm-none-linux-gnueabi, 需要在make menuconfig弹出的窗口中选择到 “Kernel Features”, 激活“Use the ARM EABI to compile the kernel”, 如果不激活这个选项的话,内核将无法加载接下来要制作的initramfs。

如果需要在u-boot上加载内核,就要编译为uImage的格式,uImage通过mkimage程序来压缩的,ArchLinux的yaourt仓库里可以找到这个包:

$ yaourt -S mkimage

安装好mkimage后,开始编译内核,因为CPU有4核,所以开启了-j8选项以加速编译:

$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- all -j8 uImage 

接下来我们可以在qemu-system-arm中测试我们的内核了

$ qemu-system-arm -M versatilepb -m 128M -kernel ./arch/arm/boot/uImage

在弹出的窗口中可以内核运行到了kernel panic状态,这是因为内核无法加载root镜像的缘故,我们将制作一个最简单的hello world的文件系统,告知kernel运行之。

init.c - init.c
#include <stdio.h>

void main() {
    printf("Hello World!\n");
    while(1);
}

编译并制作启动镜像:

$ arm-none-linux-gnueabi-gcc -o init init.c -static
$ echo init |cpio -o --format=newc > initramfs
1280 blocks
$ file initramfs 
initramfs: ASCII cpio archive (SVR4 with no CRC)

接下来我们回到编译目录下执行:

$ qemu-system-arm -M versatilepb -kernel ./arch/arm/boot/uImage  -initrd
../initramfs -serial stdio -append "console=tty1"

这时候可以看到,kernel运行并在Qemu自带的终端里打印出”Hello World!“。

如果我们改变console变量为ttyAMA0, 将在启动qemu-system-arm的本终端上打印出qemu的输出。



转自:http://feipengy.no-ip.biz/blog/2013/07/08/yong-qemumo-ni-arm-1/

### 使用 QEMU 模拟 ARM 架构 #### 安装 QEMU 和必要依赖项 为了能够在系统上使用 QEMU模拟 ARM 架构,首先需要确保已经安装了最新版本的 QEMU 及其相关组件。可以通过官方提供的链接下载并按照说明完成安装过程[^1]。 对于基于 Debian 或 Ubuntu 的 Linux 发行版来说,可以利用包管理器来简化这一流程: ```bash sudo apt-get update && sudo apt-get install -y qemu-system-arm ``` 这一步骤会自动处理所有必需的依赖关系,并将 QEMU 安装到环境中去。 #### 获取适合的 ARM 镜像文件 接着要准备一个适用于目标硬件平台的操作系统映像。通常可以从发行商处获得预构建好的 ISO 文件或者是现成的磁盘镜像;也可以自行编译定制化的内核与根文件系统以满足特定需求[^4]。 例如,在某些情况下可能需要用到专门针对 VExpress 平台优化过的 Linux 内核配置选项 `vexpress_defconfig` 进行重新编译: ```bash make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm vexpress_defconfig ``` 上述命令指定了交叉编译工具链前缀 (`CROSS_COMPILE`) 以及体系结构参数 (`ARCH`) 后执行默认配置脚本[^3]。 #### 创建和启动虚拟机实例 一旦拥有了所需的 OS 映像之后就可以创建一个新的 VM 实例了。下面给出了一种典型的方式用于启动带有指定 CPU 类型 (如 Cortex-A9) 和内存大小 (-machine virt,accel=kvm \ -cpu cortex-a7 \ -m 1024 \ -kernel /path/to/kernel.img \ -initrd /path/to/initramfs.cpio.gz \ -drive file=rootfs.ext4.qcow2,if=virtio,format=qcow2 \ -net nic,model=virtio-net-pci \ -net user \ -display sdl,gl=on \ -serial stdio ``` 此段代码片段展示了如何通过一系列参数定义了一个完整的 ARM 系统仿真环境,包括但不限于选择具体的处理器型号、分配 RAM 数量、加载核心二进制及初始化 ramdisk、挂载 root filesystems 作为持久存储介质等设置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值