
1. 项目概述与背景在Android开发与内核研究领域goldfish内核是一个特殊的存在。作为Android模拟器的专用内核版本它为我们提供了在虚拟环境中进行驱动开发、内核调试的绝佳平台。不同于物理设备的内核编译goldfish内核的编译过程相对简单且能直接在Android模拟器中运行极大降低了学习门槛。我最近在Ubuntu 22.04环境下完整走通了goldfish内核的编译和运行流程过程中遇到了不少坑也积累了一些实用技巧。本文将详细记录从环境准备到最终在模拟器中运行自定义内核的全过程特别适合想深入了解Android系统底层或需要进行驱动开发的开发者参考。2. 环境准备与内核下载2.1 系统环境要求推荐使用Ubuntu 20.04或22.04 LTS版本其他Linux发行版也可但可能需要调整部分命令。以下是必须的基础软件包sudo apt update sudo apt install -y git build-essential libncurses-dev bison flex libssl-dev libelf-dev注意如果使用虚拟机请确保已启用CPU虚拟化支持。在VMware中需要关闭虚拟机后在设置中勾选虚拟化Intel VT-x/EPT或AMD-V/RVI选项。2.2 获取goldfish内核源码goldfish内核源码托管在AOSP仓库中国内用户可以使用清华镜像加速下载git clone https://aosp.tuna.tsinghua.edu.cn/android/kernel/goldfish.git cd goldfishgoldfish内核有多个版本分支选择合适的分支很重要android-goldfish-3.18较老版本兼容早期Androidandroid-goldfish-4.14对应Android 10/11android-goldfish-5.4较新版本对应Android 12/13我选择的是4.14分支git checkout android-goldfish-4.14-gchips2.3 NDK工具链准备由于goldfish内核默认使用GCC编译而新版NDK已移除GCC支持我们需要使用较旧的NDK版本。推荐NDK r16b从Android官网下载NDK r16b解压到合适目录如~/Android/ndk/16.1.4479499设置环境变量export NDK_PATH~/Android/ndk/16.1.4479499 export PATH$NDK_PATH/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin:$PATH3. 内核编译配置与实战3.1 创建编译脚本新建build.sh文件内容如下#!/bin/bash export ARCHx86_64 export SUBARCHx86_64 export CROSS_COMPILEx86_64-linux-android- make x86_64_ranchu_defconfig # 启用内核调试符号 sed -i s/# CONFIG_DEBUG_INFO is not set/CONFIG_DEBUG_INFOy/ .config make -j$(nproc)给脚本添加执行权限chmod x build.sh3.2 常见编译问题解决问题1secclass_map需要更新error: New address family defined, please update secclass_map.解决方法 编辑security/selinux/include/classmap.h找到PF_MAX相关代码修改为#undef PF_MAX #define PF_MAX 44 #if PF_MAX 44 #error New address family defined, please update secclass_map. #endif问题2yylloc重复定义multiple definition of yylloc解决方法 编辑scripts/dtc/dtc-lexer.l将YYLTYPE yylloc;改为extern YYLTYPE yylloc;3.3 编译成功标志当终端输出以下信息时表示编译成功Kernel: arch/x86/boot/bzImage is ready (#1)生成的bzImage文件路径为arch/x86/boot/bzImage4. 在模拟器中运行自定义内核4.1 创建合适的AVD打开Android Studio创建新的虚拟设备选择x86_64架构的系统镜像建议Android 10 API 29设备类型建议选择Pixel 2分辨率适中重要提示AVD的Android版本应与内核版本匹配。4.14内核最好搭配Android 10。4.2 通过命令行启动模拟器配置SDK环境变量export ANDROID_HOME~/Android/Sdk export PATH$ANDROID_HOME/emulator:$ANDROID_HOME/platform-tools:$PATH启动命令emulator -avd Your_AVD_Name -kernel path/to/bzImage -show-kernel -no-snapshot参数说明-show-kernel显示内核启动日志-no-snapshot禁用快照确保每次都是全新启动4.3 验证内核版本进入模拟器后可以通过以下方式验证设置 → 关于模拟器 → Android版本或通过adb命令adb shell uname -a应该能看到类似这样的输出包含你编译的时间和版本信息。5. 内核调试与日志分析5.1 查看内核日志adb shell dmesg对于Android 8.0设备需要先获取root权限adb root adb shell dmesg | grep 关键信息5.2 使用KGDB调试修改build.sh在make命令前添加echo CONFIG_KGDBy .config echo CONFIG_KGDB_SERIAL_CONSOLEy .config重新编译后启动模拟器时添加参数emulator -avd Your_AVD_Name -kernel bzImage -qemu -serial tcp::1234,server在另一个终端中gdb vmlinux (gdb) target remote localhost:12346. 实用技巧与注意事项增量编译修改内核代码后只需再次运行make -j$(nproc)即可增量编译内核配置调整使用make menuconfig可以图形化调整内核配置选项性能优化编译时可以添加-j$(nproc)参数利用所有CPU核心加速编译常见问题如果遇到文件系统错误尝试在启动参数中添加-wipe-data模拟器卡在启动界面时可以尝试增加内存参数-memory 4096驱动开发准备编译时确保开启以下选项CONFIG_MODULESy CONFIG_MODULE_UNLOADy CONFIG_DEBUG_FSy7. 进阶应用开发简单内核模块创建一个简单的内核模块测试环境创建test_module目录添加test.c文件#include linux/module.h #include linux/kernel.h static int __init test_init(void) { printk(KERN_INFO Test module loaded\n); return 0; } static void __exit test_exit(void) { printk(KERN_INFO Test module unloaded\n); } module_init(test_init); module_exit(test_exit); MODULE_LICENSE(GPL);添加Makefileobj-m : test.o KERNELDIR : /path/to/your/goldfish/kernel PWD : $(shell pwd) all: $(MAKE) -C $(KERNELDIR) M$(PWD) modules编译并推送到模拟器make adb push test.ko /data/local/tmp adb shell insmod /data/local/tmp/test.ko adb shell dmesg | grep Test module通过这个完整流程你不仅能够编译运行goldfish内核还能在此基础上进行内核模块开发和调试为深入Android系统底层开发打下坚实基础。