Uncompressing Linux done, booting the kernel

Building Kernels - Android Developers

Building Kernels – Android Developers

Android 前不久发布4.3版本,正值我在学习《Android系统源代码情景分析》一书,觉得不必要拘泥于该书所描述的版本(2.3),跟上潮流前线不是件坏事,况且 Android 在2.3到4.3并没有发生天翻地覆的改变,原理应该是想通的。于是升级 Android Source,随后是 Kernel Goldfish。

和往常一样,各种环境变量配置完毕,编译过程一切顺利,得到system.img、userdata.img和ramdisk.img,模拟器可以正常启动、运行。接下来,编译 Goldfish 得到zImage,但是,模拟器怎么也不能启动了。在终端输出下面的信息后,一切嘎然而止。


Uncompressing Linux…done, booting the kernel.

回忆自己编译内核的过程,严格参考了官方文档:Building Kernels,所做的不过是根据本机情况进行了调整。


$ export PATH=$(pwd)/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin:$PATH
$ export ARCH=arm
$ export SUBARCH=arm
$ export CROSS_COMPILE=arm-eabi-
$ make goldfish_defconfig
$ make

问题出在什么地方呢?此时想到了 Androird Source 为了方便开发者,已经包含了编译好的内核,官方内核总应该没有问题吧。

$ emulator -show-kernel -debug-all -avd android_4.3 -kernel prebuilts/qemu-kernel/arm/kernel-qemu

不幸再次发生,上述问题依旧,直叫我怀疑,官方是不是没有测试就发布了?此时,留意到prebuilts/qemu-kernel/arm/ 还有一个kernel-qemu-armv7,死马当活马医吧,试试这个。


$ emulator -show-kernel -debug-all -avd android_4.3 -kernel prebuilts/qemu-kernel/arm/kernel-qemu-armv7

出乎意外,这个竟然可以,模拟器正常启动,可以看到画面。这是为什么?在 kernel-qemu 和 kernel-qemu-armv7 之间,到底有什么差异呢?同时,我还留意到prebuilts/qemu-kernel/arm/,还有一个Readme 文件,于是打开看看有没有线索。

This directory contains the kernel images specific to the Android emulator.
They are built with the ‘external/qemu/distrib/build-kernel.sh’ script.

See external/qemu/docs/ANDROID-KERNEL.TXT for more details.

顺藤摸瓜,继续打开ANDROID-KERNEL.TXT,看到有这些片段内容:

To rebuild the ARMv5TE kernel:

cd $KERNEL_SOURCES
/path/to/rebuild-kernel.sh –out=$ANDROID/prebuilt/android-arm/kernel

To rebuild the ARMv7-A one:

cd $KERNEL_SOURCES
/path/to/rebuild-kernel.sh –armv7 –out=$ANDROID/prebuilt/android-arm/kernel

根据上面描述,编译 ARM 存在两个选择,前者默认,编译的是ARMv5TE,后者需要参数,编译的是 ARMv7-A。看到这里,疑惑稍稍明白了,我自行编译的内核 zImage 以及 Android Source 里的 kernel-qemu,对应的是 ARMv5TE。可还是不明白 kernel-qemu-armv7 怎么就行了?我从启动信息里找到了线索:

emulator: /Volumes/HDD0/android-avd/android-4.3/./config.ini: parsing as .ini file
emulator: 1: KEY=’avd.ini.encoding’ VALUE=’ISO-8859-1′
emulator: 2: KEY=’hw.lcd.density’ VALUE=’240′
emulator: 3: KEY=’sdcard.size’ VALUE=’512M’
emulator: 4: KEY=’skin.name’ VALUE=’WVGA800′
emulator: 5: KEY=’skin.path’ VALUE=’platforms/android-18/skins/WVGA800′
emulator: 6: KEY=’hw.cpu.arch’ VALUE=’arm’
emulator: 7: KEY=’abi.type’ VALUE=’armeabi-v7a’
emulator: 8: KEY=’hw.cpu.model’ VALUE=’cortex-a8′
emulator: 9: KEY=’vm.heapSize’ VALUE=’48’
emulator: 10: KEY=’hw.ramSize’ VALUE=’512′
emulator: 11: KEY=’image.sysdir.1′ VALUE=’system-images/android-18/armeabi-v7a/’
emulator: /Volumes/HDD0/android-avd/android-4.3/./config.ini: parsing finished

根据上面信息,可以看出所使用的 Android Virtual Device (AVD)所声明的CPU型号是 contrex-a8。通过检索资料,知道它恰恰基于 ARMv7-A 架构,于是当使用基于ARMv5架构的内核(自行编译的 zImage 和官方编译的 kernel-qemu)都无法正确启动。

根据 ANDROID-KERNEL.TXT,我尝试寻找 rebuild-kernel.sh,发现没有,但是存在一个 build-kernel.sh,走读该脚本程序,发现它就应该是 rebuild-kernel.sh。按图索骥,最后得到 ARMv7-A 的内核。再次启动模拟器,一切正常。

回顾整个过程,官方文档(截至2013/8/10,见附图)没有把内核这个问题解释情况,真是一件让人遗憾的事情,白白浪费了不少时间。

其次,我发现官方文档,以及《Android系统源代码情景分析》,都讲到指定 CROSS_COMPILEarm-eabi-,而 build-kernel.sh 中,却指定 arm-linux-androideabi-,查看 prebuilts/gcc/linux-x86/arm/,看到有

arm-eabi-4.6 arm-eabi-4.7 arm-linux-androideabi-4.6 arm-linux-androideabi-4.7

但尚不明白为什么二者兼有,并且会有两个版本。

1 Comment

Ritter31 12 月, 2013 at 10:42 上午

谢谢,有点启发

Leave a comment

Your comment