1 前言
在前一篇文章提到,从源代码树下载下来的最新Android源代码,是不包括内核代码的,也就是Android源代码工程默认不包含Linux Kernel代码,而是使用预先编译好的内核,也就是prebuilt/android-arm/kernel/kernel-qemu文件。那么,如何才能DIY自己的内核呢?这篇文章一一道来。
2 下载Linux Kernel for Android源代码然后编译
参考谷歌官网http://source.android.com/source/building-kernels.html
2.1 下载源码
谷歌官网上列举了所有类型Kernel源码的下载地址和说明:
Depending on which kernel you want,
$ git clone https://android.googlesource.com/kernel/common.git
$ git clone https://android.googlesource.com/kernel/x86_64.git
$ git clone https://android.googlesource.com/kernel/exynos.git
$ git clone https://android.googlesource.com/kernel/goldfish.git
$ git clone https://android.googlesource.com/kernel/msm.git
$ git clone https://android.googlesource.com/kernel/omap.git
$ git clone https://android.googlesource.com/kernel/samsung.git
$ git clone https://android.googlesource.com/kernel/tegra.git
• The goldfish project contains the kernel sources for the emulated platforms.
• The msm project has the sources for ADP1, ADP2, Nexus One, Nexus 4, Nexus 5, Nexus 6, and can be used as a starting point for work on Qualcomm MSM chipsets.
• The omap project is used for PandaBoard and Galaxy Nexus, and can be used as a starting point for work on TI OMAP chipsets.
• The samsung project is used for Nexus S, and can be used as a starting point for work on Samsung Hummingbird chipsets.
• The tegra project is for Xoom, Nexus 7, Nexus 9, and can be used as a starting point for work on NVIDIA Tegra chipsets.
• The exynos project has the kernel sources for Nexus 10, and can be used as a starting point for work on Samsung Exynos chipsets.
• The x86_64 project has the kernel sources for Nexus Player, and can be used as a starting point for work on Intel x86_64 chipsets.
我下载的是goldfish,因此我运行如下命令下载内核源码(必须先用vpn进行翻墙):
cd /Volumes/android/
mkdir kernel
cd kernel
git clone https://android.googlesource.com/kernel/goldfish.git
下载完成后切换到,会看见当前目录下多了一个goldfish目录。
2.2 配置编译环境
$ export PATH=$PATH:/Volumes/android/android-4.4.4_r2/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.6/bin/
$ export ARCH=arm
$ export SUBARCH=arm
$ export CROSS_COMPILE=arm-eabi-
第一个命令是将交叉编译工具所在目录添加到$PATH环境变量中去,中间两个命令设置体系结构为arm,第四个命令是设置交叉编译工具链前缀。
2.3 编译源码
2.3.1 首先要确定我要编译那个版本的内核源码,执行如下命令启动模拟器(也就是我上一篇博客中编译android源代码生成的模拟器):
$ cd /Volumes/android/android-4.4.4_r2/
$ emulator -partition-size 1024 &
$ adb shell
# cd proc
# cat version
Linux version 3.4.0-gd853d22 (nnk@nnk.mtv.corp.google.com) (gcc version 4.6.x-google 20120106 (prerelease) (GCC) ) #1 PREEMPT Tue Jul 9 17:46:46 PDT 2013
由上面命令运行的结果可以得知android4.4.4_r2用的Linux内核源码版本是3.4.0
因此首先我们执行如下命令来切换到对应版本:
cd /Volumes/android/kernel/goldfish/
chenyangdeMacBook-Pro:goldfish chenyang$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/android-3.10
remotes/origin/android-3.4
remotes/origin/android-goldfish-2.6.29
remotes/origin/android-goldfish-3.10
remotes/origin/android-goldfish-3.10-m-dev
remotes/origin/android-goldfish-3.4
remotes/origin/linux-goldfish-3.0-wip
remotes/origin/master
git checkout android-goldfish-3.4
2.3.2 将上一步启动的模拟器中的config.gz文件放到/Volumes/android/kernel/goldfish/目录中,因为我要指定该模拟器运行我编译的Linux内核,执行如下命令:
adb pull proc/config.gz
gunzip config.gz
mv config .config
2.3.4 执行如下命令开始编译
make
如果最后输出如下两句话,说明编译成功:
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
3 启动模拟器并且指定其运行我编译的Linux内核
emulator -kernel ../kernel/goldfish/arch/arm/boot/zImage -partition-size 1024 &
用adb工具连接模拟器,查看内核版本信息,看看模拟器上跑的内核是不是我们刚才编译出来的内核:
$ adb shell
root@generic:/ # cd proc
root@generic:/proc # cat v
version vmallocinfo vmstat
root@generic:/proc # cat version
Linux version 3.4.67-g49ef260 (chenyang@chenyangdeMacBook-Pro.local) (gcc version 4.7 (GCC) ) #1 PREEMPT Sun Aug 9 21:50:04 CST 2015
从机器名chenyang@chenyangdeMacBook-Pro.local和日期 Aug 9 21:50:04 CST 2015可以看出,模拟器使用的内核即为刚刚编译出来的内核。
4 遇到的问题
执行make命令后提示如下错误
scripts/mod/mk_elfconfig.c:4:10: fatal error: 'elf.h' file not found
#include <elf.h>
^
1 error generated.
解决方法:有错误可以很明显的看出mk_elfconfig.c文件中要引用elf.h文件,但是elf.sh文件不存在,其实这个文件可以从android源代码中得到,然后将其放到/usr/include/文件夹中即可,执行如下命令:
sudo cp /Volumes/android/android-4.4.4_r2/external/elfutils/libelf/elf.h /usr/include/