Android内核之运行自定义内核

获取Android内核的途径有两种,一种是从设备中提取内核,可以看我另外一篇文章“Android内核之内核提取”,包括镜像文件的格式介绍都在这篇文章里;另一种方式是从官网去下载内核源码,编译然后刷到手机里。这里我们讲第二种方式。

我的编译环境是Mac10.10,android设备是Nexus4,AOSP版本是Android4.4。

1. 获取内核源码

获取内核源码的方式很多,取决于设备的内核由谁负责。谷歌提供了AOSP支持设备的内核git仓库,而OEM可能使用了不同的方法来发布内核源代码。但不管怎么样内核肯定会发布,因为Linux内核是遵循GPL协议的。这里咱们主要讲AOSP内核源码。
首先你先到http://source.android.com/source/building-kernels.html上面去查找和你设备名字对应的内核源码的git路径,那怎么知道你设备的名字呢?在设备的命令行输入下面命令就可以了:
getprop ro.hardware
还有怎么查询设备芯片型号呢?在设备命令行输入下面命令:
shell@mako:/data $ ls /dev/block/platform/                                     
msm_sdcc.1
我的设备是Nexus4,设备标识是mako,芯片是msm即高通的芯片。
这样内核源码的地址就找到了,在你的AOSP根目录下面输入下面命令就可以了:
BriansdeMacBook-Pro:Android4.4 brian$ mkdir kernel && cd $_
BriansdeMacBook-Pro:kernel brian$ git clone https://android.googlesource.com/kernel/msm
过几分钟就搞定了,但是你会发现并没有任何文件,这是因为master分支下面的AOSP内核树一直都是空的。在Git仓库中,.git目录包含了还原开发历史中任意一个工作副本所需要的全部信息。而你设备的内核是基于某一个commit版本的,你需要找到这个版本,并check out下来。找到这个commit版本的方法是在设备的命令行中输入下面命令:
shell@mako:/data $ cat /proc/version                                           
Linux version 3.4.0-perf-ga6edd5e ([email protected]) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Wed Apr 16 09:33:17 PDT 2014
上面的输出中a6edd5e这7个十六进制数字就是commit版本了,然后用命令git checkout a6edd5e就可以获取内核源码了。

2. 编译内核源码

要编译内核源码首先要搭建编译环境,这里假设你已经可以正确编译AOSP源码了,那么基础的东西比如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

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

Which would you like? [aosp_arm-eng] aosp_mako-userdebug

============================================
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内核支持很多架构和硬件组件,为了能够给任意一种配置组合编译内核镜像,Linux内核使用了一种可扩展的配置子系统。Linux内核还为配置子系统提供了多种配置界面,包括机遇QT的图形用户界面、基于文本的菜单和问答接口。Android开发者网站(http://source.android.com/devices/tech/config/kernel.html)的文档描述了Android内核中必须的和推荐的配置选项。
但是一项一项的去指定太过麻烦,所以Linux内核还提供了配置模版defconfig,针对不同的设备封装了对应的配置模版,你只需要去指定那个配置模版就可以了,在前面查找内核源码路径的那个页面开头有个表格,里面你可以找到与你设备对应的配置模版。找到你的配置模版后进入内核源码根目录,然后输入下面命令就完成配置了,我的配置模版是mako_defconfig。
BriansdeMacBook-Pro:msm brian$ make mako_defconfig
输入上面命令以后,内核编译系统会首先编译一些用来处理配置模版文件的依赖,然后读取配置模版,写入.config文件。
然后输入make命令就完成内核的编译了,得到内核镜像文件arch/arm/boot/zImage。

3. 制作boot.img镜像文件并安装

前面咱们得到了内核的镜像文件,那么怎么刷到手机里呢?如果你看过“ Android内核之内核提取”这篇文章就会知道,手机的boot分区镜像文件包含内核镜像文件和根分区镜像文件,所以我们需要将我们编译出的内核镜像制作新的boot.img文件然后刷到手机里就可以了。
首先从你手机里导出boot.img到电脑上,然后用abootimg工具(前面提到的文章里有下载地址)把我们编译的内核镜像文件更新到boot.img中:
BriansdeMacBook-Pro:boot brian$ abootimg -u boot.img -k zImage-new 
reading kernel from zImage-new
Writing Boot Image boot.img
如果内核镜像变大了,那么abootimg会提示类似错误"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的用法这里就不讲了,可以看github上的介绍。
到这里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 ([email protected]) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Fri Nov 11 12:06:19 CST 2016
可以看到和之前的输出不一样了。


到这里我们就可以成功的自己编译内核并刷入手机了,你就可以在内核中加入自己的代码,或者调试内核代码,甚至为所欲为了。当然你也可以自己写内核模块,然后用insmod直接装载进内核。更加深入的内容以后有想法再介绍吧,这篇就到这里了~。








发布了60 篇原创文章 · 获赞 44 · 访问量 34万+

猜你喜欢

转载自blog.csdn.net/beyond702/article/details/53175154