2. 开发环境搭建:交叉编译工具链配置、Android内核源码下载与编译、模拟器与真机调试环境搭建、ADB与内核日志查看

字符设备驱动开发的第一步,是搭建一个稳定、可复现的编译与调试环境。Android 内核驱动无法在 x86 宿主机上直接运行,必须通过交叉编译工具链生成 ARM64 或 ARM32 目标代码;同时,驱动验证需要内核镜像与运行时环境(模拟器或真机)的配合。本章将按“工具链 → 内核源码 → 编译 → 调试环境 → 日志查看”的顺序,完整搭建开发流水线。

环境概览:本课程使用 Ubuntu 22.04 LTS 作为宿主机,Android 内核分支为 android-14.0.0_r30(AOSP common 内核),目标架构为 aarch64。所有工具版本均经过验证,请勿随意替换大版本。

2.1 交叉编译工具链配置

交叉编译工具链负责在 x86_64 宿主机上生成 ARM64 架构的内核与驱动模块。推荐使用 Google 官方提供的 aarch64-linux-android- 预编译工具链,与 AOSP 内核完全兼容。

2.1.1 工具链下载与解压

# 创建工具链目录
mkdir -p ~/android/toolchains
cd ~/android/toolchains

# 下载 Android 官方预编译 GCC 工具链(aarch64)
wget https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/+archive/refs/tags/android-14.0.0_r30.tar.gz

# 解压
tar -xzf aarch64-linux-android-4.9.tar.gz
ls -l bin/aarch64-linux-android-*

2.1.2 环境变量配置

将工具链路径加入 PATH,并设置交叉编译前缀变量,方便后续内核编译时引用。

# 编辑 ~/.bashrc 或 ~/.zshrc,追加以下内容
export TOOLCHAIN_PATH=~/android/toolchains
export CROSS_COMPILE=aarch64-linux-android-
export PATH=$TOOLCHAIN_PATH/bin:$PATH

# 使配置生效
source ~/.bashrc

# 验证工具链
aarch64-linux-android-gcc --version
关键变量说明:CROSS_COMPILE 是内核 Makefile 识别交叉编译器的前缀;ARCH=arm64 需在编译时显式指定。如果使用 Clang,还需设置 CC=clang 并下载 LLVM 工具链。

2.1.3 工具链验证清单

组件 命令 预期输出
GCC 编译器 aarch64-linux-android-gcc --version 显示 4.9.x 版本信息
汇编器 aarch64-linux-android-as --version GNU assembler 版本
链接器 aarch64-linux-android-ld --version GNU ld 版本
目标文件工具 aarch64-linux-android-objdump --version GNU objdump 版本
常见错误:如果 gcc --version 显示的是 x86_64 本地编译器,说明 PATH 未正确覆盖,请检查工具链 bin 目录是否在 $PATH 最前面。
交叉编译工具链工作流程 x86_64 宿主机 Ubuntu 22.04 交叉编译工具链 aarch64-linux-android- ARM64 目标 内核 + 驱动模块 关键路径说明: 1. 宿主机上编写 C 源码(字符设备驱动 .c 文件) 2. 工具链将源码编译为 ARM64 指令集的 .ko 模块 3. 生成的 .ko 文件通过 ADB 推送到 Android 设备加载

2.2 Android 内核源码下载与编译

Android 内核源码采用 repo 工具管理多 Git 仓库。本课程使用 common-android14-5.15 内核分支,该分支基于 Linux 5.15 LTS,并包含 Android 特有补丁(如 Binder、ashmem、ion 等)。

2.2.1 安装 repo 与初始化

# 安装 repo 工具
mkdir -p ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH

# 创建内核源码目录
mkdir -p ~/android/kernel
cd ~/android/kernel

# 初始化 repo(使用清华镜像加速)
repo init -u https://aosp.tuna.tsinghua.edu.cn/kernel/manifest -b common-android14-5.15

# 同步源码(耗时较长,建议使用 -j4 或 -j8)
repo sync -j8

2.2.2 内核编译配置

Android 内核使用 build.config 文件管理编译参数。对于模拟器(goldfish)和真机(Pixel 6/7 等),配置不同。

目标环境 配置文件路径 输出镜像
模拟器 (ARM64) common/build.config.gki.aarch64 out/android14-5.15/dist/Image
Pixel 6/7 真机 private/gs-google/build.config.slider out/android14-5.15/dist/Image.lz4

2.2.3 执行编译

# 进入内核根目录
cd ~/android/kernel/common

# 设置架构与交叉编译器
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-android-

# 使用 build.sh 脚本编译(模拟器 GKI 内核)
BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh

# 编译完成后,检查内核镜像
ls -lh ../out/android14-5.15/dist/Image
编译加速技巧:在 build/build.sh 前设置 export SKIP_MRPROPER=1 可跳过清理步骤;设置 export CC=clang 可使用 LLVM/Clang 编译,生成代码质量更高。
Android 内核源码下载与编译流程 1. repo init 初始化清单 2. repo sync 同步全部仓库 3. 配置环境 ARCH + CROSS_COMPILE 4. build/build.sh 执行编译脚本 5. 生成镜像 Image / Image.lz4 6. 验证输出 file Image 编译产物说明: • Image — 未压缩内核镜像,用于模拟器(QEMU 直接加载) • Image.lz4 — LZ4 压缩内核镜像,用于 Pixel 真机(boot.img 打包)

2.3 模拟器与真机调试环境搭建

驱动开发需要快速迭代验证。模拟器适合早期功能测试,真机适合性能与硬件交互验证。两种环境各有优劣,建议开发初期以模拟器为主。

2.3.1 模拟器环境(QEMU + AOSP 模拟器)

使用 AOSP 预编译模拟器镜像,配合自定义内核启动。

# 下载模拟器镜像(ARM64 系统镜像)
sdkmanager "system-images;android-34;google_apis_playstore;arm64-v8a"

# 创建 AVD(使用命令行)
avdmanager create avd -n kernel_test -k "system-images;android-34;google_apis_playstore;arm64-v8a"

# 启动模拟器并指定自定义内核
emulator -avd kernel_test -kernel ~/android/kernel/out/android14-5.15/dist/Image -show-kernel -no-window
参数说明:-show-kernel 将内核日志输出到终端;-no-window 在无图形界面下运行,节省资源;-kernel 指定编译好的内核镜像,模拟器将使用该内核启动。

2.3.2 真机环境(Pixel 6/7)

真机调试需要解锁 bootloader 并刷入自定义内核。请确保设备已备份数据。

# 1. 解锁 bootloader(仅需一次)
adb reboot bootloader
fastboot flashing unlock

# 2. 刷入自定义内核(boot.img 打包)
# 使用 mkbootimg 工具将 Image.lz4 打包为 boot.img
mkbootimg --kernel Image.lz4 --ramdisk /dev/null --output boot.img

# 3. 刷入设备
fastboot flash boot boot.img
fastboot reboot

# 4. 验证内核版本
adb shell uname -a
对比维度 模拟器 (QEMU) 真机 (Pixel 6/7)
启动速度 快(10-30 秒) 慢(30-60 秒)
硬件访问 受限(虚拟设备) 完整(GPIO、I2C、SPI 等)
内核日志 终端直接输出 需 ADB + dmesg
刷机风险 无 有(变砖风险)
适用阶段 功能开发、单元测试 集成测试、性能调优
模拟器 vs 真机调试架构 模拟器调试环境 QEMU 模拟器 -kernel Image 宿主机终端 -show-kernel • 内核日志直接输出到终端 • 无需 ADB,即改即测 • 适合驱动逻辑快速验证 真机调试环境 Pixel 真机 fastboot flash ADB 调试桥 adb shell dmesg • 需要 ADB 连接获取日志 • 刷机流程:boot.img 打包 • 适合硬件外设驱动调试

2.4 ADB 与内核日志查看

ADB(Android Debug Bridge)是连接宿主机与 Android 设备的通用调试工具。内核日志通过 dmesg 或 logcat -b kernel 获取,是驱动开发中定位问题的第一手资料。

2.4.1 ADB 常用命令速查

命令 用途 示例
adb devices 列出已连接的设备 显示序列号与状态
adb shell 进入设备 shell 交互式命令行
adb push 推送文件到设备 adb push driver.ko /data/local/tmp/
adb pull 从设备拉取文件 adb pull /proc/kmsg ./
adb reboot 重启设备 刷入内核后验证

2.4.2 内核日志查看方法

内核日志分为 kmsg(实时流)和 dmesg(环形缓冲区)。驱动开发中推荐使用 dmesg -w 实时监控。

# 方法一:dmesg(查看历史日志 + 实时跟踪)
adb shell dmesg -w | grep "chardev"

# 方法二:logcat 内核日志(Android 特有)
adb logcat -b kernel -v time

# 方法三:直接读取 /proc/kmsg(需要 root)
adb shell su -c "cat /proc/kmsg"

# 方法四:模拟器终端直接查看(-show-kernel 模式)
# 日志会实时打印在启动模拟器的终端窗口中
权限说明:在 userdebug 或 eng 版本中,dmesg 无需 root 即可执行;user 版本受限,建议开发机刷入 userdebug 镜像。/proc/kmsg 始终需要 root 权限。

2.4.3 内核日志格式解析

典型内核日志行包含时间戳、CPU 编号、进程名和日志级别。驱动开发者应重点关注 KERN_ERR (3) 和 KERN_INFO (6) 级别的输出。

[   12.345678] [0003] [insmod] chardev: major number 240 registered
[   12.345789] [0003] [insmod] chardev: device class created
[   13.001234] [0005] [kworker] chardev: open() called by pid 1234
[   13.001567] [0005] [kworker] chardev: ioctl cmd=0x1234, arg=0x5678
字段 含义 调试价值
[12.345678] 系统启动后的秒数 定位事件发生顺序
[0003] CPU 核心编号 分析并发问题
[insmod] 进程名 区分调用者
chardev: 驱动名称(pr_fmt) 过滤特定驱动日志
major number 240 关键事件描述 验证驱动初始化
ADB 与内核日志查看架构 宿主机 ADB 客户端 dmesg -w | grep ADB 调试桥 USB / TCP/IP adb shell dmesg Android 设备 内核环形缓冲区 /proc/kmsg 日志查看最佳实践: 1. 开发阶段:模拟器 + -show-kernel,实时查看驱动加载日志 2. 真机阶段:adb shell dmesg -w | grep "驱动名" 过滤输出 3. 使用 logcat -b kernel 获取带 Android 时间戳的内核日志

2.5 环境验证清单

完成上述步骤后,执行以下验证脚本,确保所有组件正常工作。

#!/bin/bash
# environment_check.sh
echo "=== 1. 交叉编译工具链 ==="
aarch64-linux-android-gcc --version && echo "[OK]" || echo "[FAIL