Android内核之运行自定义内核
获取Android系统核心组件的方法共有两种途径可选:其一是可以从设备内部进行提取操作,在我的另一篇文章"Android系统开发之核心组件解析"中有详细介绍关于镜像文件格式的相关说明;其二是通过官方渠道获取最新版本的核心代码包,并完成编译流程后通过特定方法将其安装至智能手机上。在这里我们将重点讲解第二种方法的具体实现步骤
我的编译环境是Mac10.10,android设备是Nexus4,AOSP版本是Android4.4。
1. 获取内核源码
获取不同设备的内 kernel 源 code 途径繁多, 具体取决于 device 的 owner 谁负责. 例如 Google 提供了基于 Android One Source Project (AOSP) 架构的支持型 device 的 Linux 源代码存储位置, 而其他厂商可能采用不同的方法来分发各自的开源版本. 不管怎样最终都会将 Linux 核心代码开放给外界使用, 因为 Linux 核心遵循 GPL 协议. 这里咱们主要讲 AOSP 相关的 Linux 内 kernel 源 code.
getprop ro.hardware
代码解读
还有怎么查询设备芯片型号呢?在设备命令行输入下面命令:
shell@mako:/data $ ls /dev/block/platform/
msm_sdcc.1
代码解读
我的手机型号为Pixel手机(Nexus4),其设备编码为mako。该设备搭载了骁龙8系列 MSM处理器。通过此方法我已经定位到了内核源码的位置。你可以按照以下步骤操作:首先前往你的AOSP根目录下的Android Oreo主控文件夹;其次执行相应的编译指令以获取内核源码地址。
BriansdeMacBook-Pro:Android4.4 brian$ mkdir kernel && cd $_
BriansdeMacBook-Pro:kernel brian$ git clone https://android.googlesource.com/kernel/msm
代码解读
几秒钟后就完成了吗?但令人意想不到的是,在此期间并没有生成任何文件。仔细思考一下就会发现原因:即使是在master分支下运行一段时间后,在AOSP内核树中也没有存储任何数据。在Git存储库中,请注意观察位于当前目录下的特殊目录——.git目录实际上保存了整个项目的所有开发历史数据。请注意,在你的设备上运行时所使用的内核代码实际上是某个特定版本的工作副本。你需要先定位到该特定版本的工作副本,并切换至该版本以进行操作。要找到该特定version的方法很简单:打开设备上的终端并执行以下操作:
shell@mako:/data $ cat /proc/version
Linux version 3.4.0-perf-ga6edd5e (android-build@kpdm5.cbf.corp.google.com) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Wed Apr 16 09:33:17 PDT 2014
代码解读
在输出结果中显示的a6edd5e这7个十六进制数字即为commit版本。通过执行命令git checkout a6edd5e则可以直接获取内核源码。
2. 编译内核源码
为了实现内核源码的编译需求,首要任务是搭建完善的开发环境.在此情境下,默认条件是认为你的开发环境配置能够顺利处理AOSP源码的构建过程.其中基本配置包括Java JDK以及必要的交叉编译工具套装等基础设施已经成功配置完成.那么下一步咱们进入到AOSP的根目录,输入下面的命令:
BriansdeMacBook-Pro:Android4.4 brian$ source build/envsetup.sh
including device/asus/deb/vendorsetup.sh
including device/asus/flo/vendorsetup.sh
including device/asus/grouper/vendorsetup.sh
including device/asus/tilapia/vendorsetup.sh
including device/generic/armv7-a-neon/vendorsetup.sh
including device/generic/mips/vendorsetup.sh
including device/generic/x86/vendorsetup.sh
including device/lge/hammerhead/vendorsetup.sh
including device/lge/mako/vendorsetup.sh
including device/samsung/manta/vendorsetup.sh
including sdk/bash_completion/adb.bash
BriansdeMacBook-Pro:Android4.4 brian$ lunch
You're building on Darwin
17. Lunch menu... pick a combo:
1. aosp_arm-eng
2. aosp_x86-eng
3. aosp_mips-eng
4. vbox_x86-eng
5. aosp_deb-userdebug
6. aosp_flo-userdebug
7. aosp_grouper-userdebug
8. aosp_tilapia-userdebug
9. mini_armv7a_neon-userdebug
10. mini_mips-userdebug
11. mini_x86-userdebug
12. aosp_hammerhead-userdebug
13. aosp_mako-userdebug
14. aosp_manta-userdebug
33. Which would you like? [aosp_arm-eng] aosp_mako-userdebug
35. ============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.4.4
TARGET_PRODUCT=aosp_mako
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
TARGET_CPU_VARIANT=krait
HOST_ARCH=x86
HOST_OS=darwin
HOST_OS_EXTRA=Darwin-14.5.0-x86_64-i386-64bit
HOST_BUILD_TYPE=release
BUILD_ID=KTU84P
OUT_DIR=out
============================================
代码解读
首先需要运行build/envsetup.sh以初始化编译环境,并在该脚本完成后将建立若干系统变量。
随后确定目标配置和必要的参数。
此外还需配置三个关键参数以确保流程顺利进行。
如果不进行这些设置可能会导致错误。
BriansdeMacBook-Pro:Android4.4 brian$ export CROSS_COMPILE=arm-eabi-
BriansdeMacBook-Pro:Android4.4 brian$ export SUBARCH=arm
BriansdeMacBook-Pro:Android4.4 brian$ export ARCH=arm
代码解读
采用的是arm-eabi编译器,并非arm-linux-androideabi编译器;错误的应用将导致无法完成编译过程。
在进行编译操作之前,请先对系统内核进行相应的配置设置。由于Linux内 kernel具备广泛的兼容性和硬件支持能力,在构建特定设备版本时,它采用了灵活可扩展的模块化设计.这种设计不仅能够实现不同硬件架构和软件组件的有效整合与协同工作,还为开发人员提供了多样的调试手段.此外,针对不同的开发需求,在界面设计上也进行了充分考虑与优化.
但逐个设置显得繁琐费时,为此Linux内核专门设计了一套高效的配置模板系统,为不同类型的硬件设备预先编定了相应的配置模板,只需选择并引用相应的模板即可。在源代码管理界面左侧有一个列表选项,在此列表中你可以轻松找到与当前硬件兼容的模板。找到所需模板后,请前往项目根目录目录下执行以下操作即可完成整个配 configuring流程,而我的默认设置正是基于mako_defconfig这一模块实现的。
BriansdeMacBook-Pro:msm brian$ make mako_defconfig
代码解读
当执行上述命令时,
内核编译系统将首先进行这些与处理配置模板相关的依赖构建。
随后将读取相应的配置模板,
并将其保存到名为.config的文件中。
执行make命令后成功完成了内核的编译。生成了目标路径下的内核镜像文件 arch-arm-linux-gnu-gcc-8。
3. 制作boot.img镜像文件并安装
之前我们已经获取了内核的镜像文件。那如何将这些镜像文件传输至手机中呢?如果你阅读过相关文章《Android内核之内核提取》,就会了解手机中的boot分区包含内核镜像文件以及根分区镜像文件等信息。因此我们需要做的是编译出内核镜像,并制作一个新的boot.img文件;随后将其传输至手机中即可完成安装过程。
请从您的手机中提取...文件至电脑环境中;之后,请您使用名为abootimg的工具(参考前述文章获取下载链接)来将您编译生成的内核镜像文件导入并替换到当前...中。
BriansdeMacBook-Pro:boot brian$ abootimg -u boot.img -k zImage-new
reading kernel from zImage-new
Writing Boot Image boot.img
代码解读
当内核镜像变得过大时,系统会报错信息'new-boot.img:update is too big for the Boot Image (4534272 vs 4505600 bytes)';这时,请确保将整个boot.img文件进行解压以便进一步处理。
BriansdeMacBook-Pro:boot brian$ abootimg -x boot.img
writing boot image config in bootimg.cfg
extracting kernel in zImage
extracting ramdisk in initrd.img
代码解读
然后输入下面命令:
BriansdeMacBook-Pro:boot brian$ abootimg --create new-boot.img -f bootimg.cfg -k zImage-new -r initrd.img -c "bootsize=4534272"
代码解读
按回车键即可完成操作。请注意该尺寸即为整个$ boot.img$的大小,请确保已下载完整版本。关于$ abootimg$的操作方法在此从略,默认情况下已经生成了完整的$ boot镜像文件$。安装前,请确保将手机置于fastboot模式下,并执行以下命令:
BriansdeMacBook-Pro:boot brian$ adb reboot bootloader
代码解读
设备将重新启动并进入fastboot模式。有两种方法可以让手机执行编译好的内核:第一种方法是通过加载新的boot.img文件启动;另一种方法则是将新生成的boot.img文件复制到设备的boot分区目录中。第一种方式的优势在于如果操作失误可立即重启恢复;但其缺点是恢复后效果仅可持续一次;第二种方法则能实现永久生效的效果。
先看第一种方法,在电脑的命令行中输入命令:
BriansdeMacBook-Pro:boot brian$ fastboot boot new-boot.img
代码解读
第二种方法,在电脑的命令行中输入:
BriansdeMacBook-Pro:boot brian$ fastboot flash boot new-boot.img
BriansdeMacBook-Pro:boot brian$ fastboot reboot
代码解读
随后将重新启动。
在手机的命令行界面中运行以下指令:
shell@mako:/ $ cat /proc/version
Linux version 3.4.0-perf-gc7ee689-dirty (brian@BriansdeMacBook-Pro.local) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Fri Nov 11 12:06:19 CST 2016
代码解读
可以看到和之前的输出不一样了。
到此为止我们已经能够顺利完成自定义内核的构建并将其实现于实际设备上了。您能在内存环境中插入自己的代码块并对其执行各种操作包括但不限于修改或删除关键指令序列同时还可以通过简单的调试功能来校验程序逻辑;另外一种方法则是编写自定义的动态加载机制通过insmod指令将新模块注入内存空间从而完成扩展功能的具体实现过程。如果您对这些技术细节还有更多的疑问或是想深入了解其中的工作原理不妨稍后再讨论这个问题相信下期的文章会为您带来更多的解答与启发!
