和一般的Linux系統開發流程一樣,Android平台開發的一個很重要的基礎工作就是對其內核的編譯和移植。本文的目的就在於構建出可以在Android自帶的ARM QEMU模擬器上運行的內核映像,希望對於大家做內核的移植和系統構建有幫助。
請先參考我的另一篇文章
如何取得Android源代碼
,確保正確地拿到了Android
kernel/common項目
的
Goldfish分支(該分支用於構建運行在emulator上的系統內核,而主線則是用於構建運行在實際設備上的內核代碼)上的內核代碼。另外,需要提
醒一下大家的是Android的sourcecode目前只能在Linux或者Mac
OS下做交叉編譯編譯,Windows並沒有被支持,以下將以Ubuntu 8.04為Host OS來說明。
Android對Linux Kernel做了不少的改進,比如添加對yaffs2文件系統的支持,改進藍牙的支持,改進電源管理機制,以及為模擬器版本添加的Goldfish平台等等,不過內核的編譯方式和標准的kernel並沒有區別。
這裡唯一需要注意的是,Android 1.0_r2以後,整個項目的sourcecode就全部轉移到git了,
Google Code
上不會再有更新,請確保從Git上拿到了android-goldfish-2.6.27分支上的內核代碼。
1、在Host OS上准備編譯環境
盡管很多人安裝完Ubuntu後第一件事情就是裝上build-essential,不過我在這裡還是要提醒一下大家,另外做menuconfig的時候ncurses-devel庫也是必須的。運行以下命令,一次搞定:
sudo apt-get install build-essential ncurses-dev
2、准備交叉編譯工具鏈
Android代碼樹中有一個prebuilt項目,包含了我們編譯內核所需的交叉編譯工具,如果你拿了完整的Android 1.5代碼樹,它就會在prebuilt目錄下。如果沒有拿完整的代碼樹也沒有關系,只要用Git clone一個或者到從GitWeb下載一個
prebuilt項目
,如果是從GitWeb下載的話記得解壓縮就行。
3、設定環境變量
把剛才下載的prebuilt中的arm-eabi編譯器加入$PATH
$export PATH=$PATH:/home/william/android-source/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin
設定目標arch為arm
$export ARCH=arm
4、設定交叉編譯參數
打開kernel目錄下的Makefile文件,把CROSS_COMPILE指向剛才下載的prebuilt中的arm-eabi編譯器
CROSS_COMPILE ?= arm-eabi-
把
LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
$(call ld-option, -Wl$(comma)–build-id,))
這一行注釋掉,並且添加一個空的LDFLAGS_BUILD_ID定義,如下:
LDFLAGS_BUILD_ID =
下面的這段解釋來自
陳罡的blog
把它注釋掉的原因是目前android的內核還不支持這個選項。–build-id選項,主要是用於在生成的elf可執行
文件中加入一個內置的id,這樣在core
dump,或者debuginfo的時候就可以很快定位這個模塊是哪次build的時候弄出來的。這樣就可以避免,每次都把整個文件做一遍效驗,然後才能
得到該文件的是由哪次build產生的。對於內核開發者來說,這是很不錯的想法,可以節約定位模塊版本和其影響的時間。目前,該功能還出於early
stage的狀態,未來的android或許會支持,但至少目前的版本是不支持的。
對這個–build-id選項感興趣的朋友,可以訪問下面的網址,它的作者已經解釋得非常明白了:
http://fedoraproject.org/wiki/Releases/FeatureBuildId
5、從1.5_r1捆綁的SDK中獲得內核配置文件
大家都知道,內核編譯中有一步make menuconfig,用於配置kernel,這裡我們可以先獲取官方的配置,如果必要的話再作改動。先啟動模擬器,然後通過adb pull命令(該命令用於從設備上復制文件到本地)即可完成。
$adb pull /proc/config.gz ~/
現在我們用gunzip把config.gz解開,把得到的config文件移動到kernel source所在的目錄,然後重命名為.config即可。
$ gunzip config.gz
$ mv config ~/sources/goldfish-kernel/.config
6、開始編譯
因為我們之前已經吧1.5_r1中的.config復制到了kernel目錄下,如果需要修改配置,可以使用
make menuconfig
修改並保存配置,如果沒有特殊需要的話就可以直接用
make
命令來編譯內核了
7、測試生成的zImage
編譯內核的過程應該很順利,因為默認的配置對內核作了大幅的精簡,大約5~6分鐘就可以編譯完成了,會在最終會在arch/arm/boot目錄下面生成一個zImage,這個就是我們所要的運行在模擬器上的內核映像了。
下面我們就在模擬器中測試一下我們所生成的zImage。
emulator @1.5_L2 -kernel ./zImage
其中1.5_L2是我之前創建的
AVD
,如果想輸出kernel log,請加上-show-kernel參數。
一切順利的話,我們應該可以看到Android順利啟動了。
通過adb shell,我們可以查看version信息,如下圖:
關於為實際設備編譯kernel
如果要為一個實際的設備比如說G1重新編譯內核映像,步驟和上述為一個運行在模擬器上的內核映像步驟基本一致,只是所需要的源代碼應當來自主線而不是goldfish分支。另外,編譯完成以後載入映像的方式也不同,需要通過USB將映像燒入nand flash。