2. 内核开发环境搭建:交叉编译工具链配置、内核源码获取与编译、QEMU模拟器与Android模拟器环境搭建

嵌入式Linux与Android内核驱动开发的第一步,是构建一个稳定、可复现的开发环境。本章将系统讲解交叉编译工具链的配置、内核源码的获取与编译方法,以及QEMU与Android模拟器的搭建流程。掌握这些基础技能,是后续编写和调试驱动程序的前提。

学习目标:
  • 理解交叉编译的原理与工具链结构
  • 掌握从官方仓库获取内核源码的方法
  • 独立完成内核编译与设备树生成
  • 搭建QEMU模拟环境与Android模拟器

2.1 交叉编译工具链配置

交叉编译是指在宿主机(通常是x86架构的PC)上编译生成目标平台(如ARM、AArch64、RISC-V)可执行代码的过程。Android内核与嵌入式Linux内核均依赖交叉编译工具链。

2.1.1 工具链组成

一个完整的交叉编译工具链包含以下核心组件:

组件 说明 典型名称(ARM64)
编译器 将C/C++源码编译为目标架构的汇编 aarch64-linux-gnu-gcc
汇编器 将汇编代码转换为机器码 aarch64-linux-gnu-as
链接器 将目标文件链接为可执行文件或内核镜像 aarch64-linux-gnu-ld
库文件 目标架构的C标准库与内核头文件 libc.so.6 (ARM64)
调试器 用于目标架构的远程调试 aarch64-linux-gnu-gdb
二进制工具 objdump、objcopy、strip等 aarch64-linux-gnu-objdump

2.1.2 安装预编译工具链

推荐使用Linaro或Android NDK提供的预编译工具链,避免从源码构建的复杂性。以下以Ubuntu 22.04 LTS为例:

# 安装ARM64交叉编译工具链(用于QEMU与Android内核)
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu

# 安装ARM32交叉编译工具链(用于旧版Android设备)
sudo apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf

# 安装Android NDK(用于编译Android内核模块)
wget https://dl.google.com/android/repository/android-ndk-r26d-linux.zip
unzip android-ndk-r26d-linux.zip
export PATH=$PATH:$(pwd)/android-ndk-r26d/toolchains/llvm/prebuilt/linux-x86_64/bin
注意:Android NDK从r23版本开始,默认使用Clang/LLVM工具链,不再包含GCC。如果编译旧版Android内核(4.19以下),建议使用Linaro GCC工具链。

2.1.3 验证工具链

安装完成后,通过以下命令验证工具链是否正常工作:

# 检查编译器版本
aarch64-linux-gnu-gcc --version

# 编译一个简单的测试程序
cat > hello.c << EOF
#include <stdio.h>
int main() {
    printf("Hello, ARM64 Kernel!\n");
    return 0;
}
EOF

# 交叉编译
aarch64-linux-gnu-gcc -o hello.arm64 hello.c

# 查看生成文件的架构信息
file hello.arm64
# 输出示例:ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV)

2.1.4 工具链配置对比

工具链来源 适用场景 编译器类型 推荐版本
Linaro GCC 通用嵌入式Linux内核编译 GCC 13.2-2023.11
Android NDK Android内核模块与HAL编译 Clang/LLVM r26d
Buildroot 定制化根文件系统与内核 GCC (自编译) 2024.02
Yocto/OpenEmbedded 企业级嵌入式Linux发行版 GCC (自编译) Kirkstone (4.0)
最佳实践:对于Android内核驱动开发,建议同时安装Linaro GCC(用于内核编译)和Android NDK(用于内核模块与用户态测试程序),两者互补。
交叉编译工具链工作流程 宿主机 (x86_64) Ubuntu 22.04 LTS 交叉编译工具链 aarch64-linux-gnu-* 目标平台 (ARM64) QEMU / 真实硬件 输出产物 vmlinux / Image / .ko 说明: 交叉编译工具链在宿主机上运行,生成目标架构的二进制代码。内核镜像(Image/vmlinux)和内核模块(.ko) 均通过此流程生成,然后部署到目标平台执行。

2.2 内核源码获取与编译

2.2.1 获取内核源码

Linux内核源码可以从多个渠道获取,推荐使用git克隆官方仓库,便于版本切换与补丁管理。

# 方法一:克隆Linux官方主线仓库(推荐)
git clone --depth=1 -b v6.6 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux

# 方法二:克隆Android Common Kernel仓库(用于Android设备)
git clone --depth=1 -b android-14-6.6 https://android.googlesource.com/kernel/common
cd common

# 方法三:下载稳定版tar包(适合网络受限环境)
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.8.tar.xz
tar -xf linux-6.6.8.tar.xz
cd linux-6.6.8
版本选择建议:
  • 学习阶段:使用LTS版本(如6.6.x),稳定性好,社区支持完善
  • Android开发:使用Android Common Kernel(ACK),与AOSP兼容性最佳
  • 生产环境:使用芯片厂商提供的BSP内核(如Qualcomm、MTK)

2.2.2 内核配置

内核编译前需要进行配置,选择需要编译的模块与功能。常用的配置方法有三种:

配置命令 交互方式 适用场景
make defconfig 自动生成默认配置 快速开始,适用于标准平台
make menuconfig 基于ncurses的文本菜单 手动选择模块,最常用
make ARCH=arm64 defconfig 指定架构的默认配置 交叉编译时使用
# 以ARM64架构为例,配置内核
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

# 生成默认配置(基于ARM64 virt平台,适用于QEMU)
make defconfig

# 或者使用menuconfig进行自定义配置
make menuconfig

# 查看生成的配置文件
ls -la .config

2.2.3 编译内核

内核编译过程包括编译内核镜像、设备树(DTB)和内核模块。以下是完整的编译流程:

# 设置环境变量(每次新终端都需要执行)
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
export INSTALL_MOD_PATH=./modules_install

# 编译内核镜像(使用-jN指定并行任务数,N为CPU核心数+1)
make -j$(nproc) Image.gz

# 编译设备树(DTB)
make -j$(nproc) dtbs

# 编译内核模块
make -j$(nproc) modules

# 安装内核模块到指定目录
make modules_install

# 查看编译产物
ls -lh arch/arm64/boot/Image.gz
ls -lh arch/arm64/boot/dts/qemu/
编译时间参考:在8核CPU、32GB内存的机器上,首次编译ARM64内核约需15-30分钟。后续增量编译通常在1-5分钟内完成。

2.2.4 编译产物说明

文件 路径 说明
vmlinux 源码根目录 未压缩的ELF格式内核镜像,包含调试信息
Image arch/arm64/boot/ 未压缩的原始内核镜像(无ELF头)
Image.gz arch/arm64/boot/ gzip压缩的内核镜像,QEMU常用
*.dtb arch/arm64/boot/dts/ 编译后的设备树二进制文件
*.ko 各子目录 可加载内核模块(驱动)
System.map 源码根目录 内核符号表,用于调试与地址解析
Linux内核编译流程 内核源码 linux-6.6.8 内核配置 defconfig / menuconfig 编译决策 make -j$(nproc) 内核镜像 Image.gz / vmlinux 设备树 *.dtb 内核模块 *.ko

2.3 QEMU模拟器环境搭建

QEMU是一款支持多种架构的硬件模拟器,可以在没有真实硬件的情况下运行和调试内核。对于驱动开发,QEMU提供了快速迭代和断点调试的能力。

2.3.1 安装QEMU

# 安装QEMU(支持ARM64架构)
sudo apt-get install -y qemu-system-arm qemu-efi-aarch64

# 验证安装
qemu-system-aarch64 --version
# 输出示例:QEMU emulator version 8.2.0

2.3.2 制作根文件系统

内核启动后需要根文件系统(rootfs)来运行用户态程序。推荐使用Buildroot或BusyBox制作最小根文件系统。

# 使用BusyBox制作最小根文件系统
# 1. 下载BusyBox
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar -xf busybox-1.36.1.tar.bz2
cd busybox-1.36.1

# 2. 配置并编译
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- install

# 3. 制作根文件系统镜像
cd _install
mkdir -p proc sys dev etc/init.d
cat > etc/init.d/rcS << EOF
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
echo "Welcome to QEMU ARM64 Linux!"
EOF
chmod +x etc/init.d/rcS

# 4. 打包为cpio归档
find . | cpio -o --format=newc > ../rootfs.cpio
cd ..
gzip -c rootfs.cpio > rootfs.cpio.gz

2.3.3 启动QEMU

# 使用编译好的内核与根文件系统启动QEMU
qemu-system-aarch64 \
  -machine virt \
  -cpu cortex-a72 \
  -smp 4 \
  -m 2G \
  -kernel arch/arm64/boot/Image.gz \
  -initrd /path/to/rootfs.cpio.gz \
  -append "console=ttyAMA0 root=/dev/ram rdinit=/sbin/init" \
  -nographic \
  -netdev user,id=net0 \
  -device virtio-net-pci,netdev=net0

# 启动后,在QEMU终端中应看到内核启动日志,最终进入shell提示符
QEMU调试技巧:
  • 添加 -s -S 参数可在启动时暂停,等待GDB连接(端口1234)
  • 使用 -d in_asm -D qemu.log 记录指令执行日志
  • 使用 -drive file=disk.img,format=raw 挂载磁盘镜像

2.3.4 QEMU与真实硬件对比

特性 QEMU模拟器 真实硬件(如Raspberry Pi)
启动速度 快(10-30秒) 慢(1-3分钟)
调试能力 支持GDB断点、单步、内存查看 需要JTAG或串口调试
硬件外设 模拟通用设备(virtio、PL011) 真实外设(GPIO、I2C、SPI)
驱动验证 适合逻辑验证与原型开发 必须进行最终验证
成本 免费 需要硬件采购
QEMU ARM64 模拟器架构 QEMU 用户态进程 qemu-system-aarch64 运行在宿主机上 模拟硬件层 CPU: Cortex-A72 内存: 2GB, 4核 客户机内核 Linux 6.6 ARM64 运行在模拟硬件上 外设模拟 virtio / PL011 / GIC 调试接口 GDB Server (端口1234)

2.4 Android模拟器环境搭建

Android模拟器(基于QEMU)是Android内核驱动开发的另一重要平台。与通用QEMU不同,Android模拟器集成了Goldfish平台专用驱动和Android系统服务。

2.4.1 安装Android Studio与模拟器

# 1. 下载并安装Android Studio
wget https://redirector.gvt1.com/edgedl/android/studio/ide-zips/2023.3.1.18/android-studio-2023.3.1.18-linux.tar.gz
tar -xf android-studio-2023.3.1.18-linux.tar.gz
cd android-studio/bin
./studio.sh

# 2. 在Android Studio中安装SDK与模拟器
# 通过Tools -> SDK Manager 安装:
#   - Android SDK Platform 34
#   - Android SDK Build-Tools 34
#   - Android Emulator (最新版)
#   - ARM64系统镜像 (如: system-images;android-34;google_apis;arm64-v8a)

# 3. 命令行创建模拟器(可选)
export ANDROID_HOME=~/Android/Sdk
$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "system-images;android-34;google_apis;arm64-v8a"
$ANDROID_HOME/tools/bin/avdmanager create avd -n test_device -k "system-images;android-34;google_apis;arm64-v8a"

2.4.2 编译Android内核(Goldfish)

Android模拟器使用Goldfish内核,该内核包含模拟器专用驱动(如Goldfish RTC、Goldfish Audio等)。

# 1. 克隆Goldfish内核
git clone --depth=1 -b android-14-6.6 https://android.googlesource.com/kernel/goldfish
cd goldfish

# 2. 设置环境变量
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
export PATH=$PATH:~/Android/Sdk/emulator

# 3. 使用Goldfish默认配置
make goldfish_arm64_defconfig

# 4. 编译内核
make -j$(nproc) Image.gz

# 5. 查看编译产物
ls -lh arch/arm64/boot/Image.gz

2.4.3 使用自定义内核启动模拟器

# 1. 找到Android模拟器的内核参数
# 默认内核路径:~/Android/Sdk/system-images/android-34/google_apis/arm64-v8a/kernel-ranchu

# 2. 使用自定义内核启动模拟器
emulator \
  -avd test_device \
  -kernel /path/to/goldfish/arch/arm64/boot/Image.gz \
  -show-kernel \
  -verbose \
  -no-snapshot \
  -memory 2048

# 3. 验证内核版本(在模拟器终端中执行)
adb shell
uname -a
# 输出应显示自定义内核版本信息
注意事项:
  • Android模拟器内核必须与系统镜像的API级别匹配,否则可能无法启动
  • 使用 -show-kernel 参数可以查看内核启动日志,便于调试
  • 如果模拟器启动失败,检查 ~/.android/avd/test_device.avd/config.ini 中的配置

2.4.4 QEMU与Android模拟器对比

对比维度 通用QEMU Android模拟器
目标平台 通用ARM64/ARM32/RISC-V