1. 准备交叉编译工具链
由于通常是在 x86 平台下开发 ARM64 程序,需要安装交叉编译工具链。以 Ubuntu/Debian 为例,可以通过以下命令安装并验证:sudo apt updatesudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu# 验证是否安装成功aarch64-linux-gnu-gcc --version
2. 编译 Linux 内核
下载目标版本的 Linux 内核源码并解压后,进入源码目录执行以下操作:
# 生成 arm64 平台的默认配置文件make ARCH=arm64 defconfig # 开始编译内核make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)
编译成功后,会在 arch/arm64/boot/ 目录下生成内核可执行文件 Image。3. 制作根文件系统 (Rootfs)
# 下载并解压 BusyBox 源码(以 1.36.1 版本为例)wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2tar -xf busybox-1.36.1.tar.bz2cd busybox-1.36.1# 生成默认配置make defconfig# 进入菜单配置,开启静态编译(推荐,避免缺少动态链接库的问题),去掉tc(编译不过)make menuconfig# 导航路径:Settings ---> # 选中:[*] Build static binary (no shared libs)# 或搜索 CONFIG_STATIC# Networking Utilities ---> tcexport ARCH=arm64export CROSS_COMPILE=aarch64-linux-gnu-# 编译并安装(默认安装到 _install 目录)make -j $(nproc)make install$ file _install/bin/busybox _install/bin/busybox: ELF 64-bit LSB executable, ARM aarch64, version 1 (GNU/Linux), statically linked...
基于 BusyBox 的安装目录,创建根文件系统所需的基础目录和设备节点:# 创建 initramfs 目录并复制 BusyBox 文件cd ..mkdir -p initramfscd initramfscp -r ../busybox-1.36.1/_install/* .# 创建必要的系统目录mkdir -p {bin,dev,proc,sys,etc,lib,tmp}# 创建必要的设备节点(用于控制台和空设备)sudo mknod -m 660 dev/console c 5 1sudo mknod -m 660 dev/null c 1 3
内核启动后需要执行初始化脚本来挂载必要的虚拟文件系统。在 initramfs 目录下创建 init 脚本:#!/bin/sh# 挂载必要的虚拟文件系统mount -t proc none /procmount -t sysfs none /sysmount -t devtmpfs none /devecho "Hello Linux(Arm64)"# 启动交互式 Shellexec /bin/sh
将构建好的目录打包为 cpio 格式并进行 gzip 压缩:find . | cpio -H newc -o | gzip > ../initramfs.img
打包完成后,你会在当前目录的上一级得到一个 initramfs.img 文件。
4. 使用 QEMU 启动内核
准备好内核镜像和根文件系统后,即可使用 qemu-system-aarch64 命令启动虚拟机。以下是常用的启动命令模板:
qemu-system-aarch64 -M virt -cpu cortex-a53 -smp 2 -m 512M -nographic -kernel Image -initrd initramfs.img -append "root=/dev/ram0 rootfstype=ramfs rw console=ttyAMA0 init=/init"
核心参数解析:
-M/-machine virt:指定 QEMU 模拟通用的 ARMv8 虚拟开发板模型,无需定制硬件支持。-cpu cortex-a53:指定模拟的具体 CPU 核心型号(也可使用 cortex-a57)。-nographic-smp 2-m 512-kernel-initrd-append:向内核传递启动参数。其中 ttyAMA0 是 QEMU virt 平台下 PL011 串口的设备名,root=/dev/ram0 指定根设备。
.......[ 0.709700] ohci-pci: OHCI PCI platform driver[ 0.710340] ohci-platform: OHCI generic platform driver[ 0.710972] ohci-exynos: OHCI Exynos driver[ 0.712939] usbcore: registered new interface driver usb-storage[ 0.723149] rtc-pl031 9010000.pl031: registered as rtc0[ 0.724311] rtc-pl031 9010000.pl031: setting system clock to 2026-06-06T09:46:33 UTC (1780739193)[ 0.725687] i2c /dev entries driver[ 0.733606] sdhci: Secure Digital Host Controller Interface driver[ 0.733824] sdhci: Copyright(c) Pierre Ossman[ 0.734605] Synopsys Designware Multimedia Card Interface Driver[ 0.736067] sdhci-pltfm: SDHCI platform and OF driver helper[ 0.738707] ledtrig-cpu: registered to indicate activity on CPUs[ 0.741667] usbcore: registered new interface driver usbhid[ 0.742014] usbhid: USB HID core driver[ 0.752502] NET: Registered protocol family 17[ 0.754599] 9pnet: Installing 9P2000 support[ 0.755348] Key type dns_resolver registered[ 0.757192] registered taskstats version 1[ 0.757329] Loading compiled-in X.509 certificates[ 0.767122] input: gpio-keys as /devices/platform/gpio-keys/input/input0[ 0.772392] clk: Disabling unused clocks[ 0.773125] ALSA device list:[ 0.773323] No soundcards found.[ 0.776872] uart-pl011 9000000.pl011: no DMA platform data[ 0.818253] Freeing unused kernel memory: 5952K[ 0.819256] Run /init as init processHello Linux(Arm64)/bin/sh: can't access tty; job control turned off~ #
启动 QEMU 时使用了 -nographic 参数,所有的串口输出和监控台都重定向到了当前终端,此时应使用官方推荐的快捷键组合:
操作步骤:先按下 Ctrl + A,松开后再按下 X 键。
效果:QEMU 会立即安全退出,并正确释放所有占用的端口和资源。