前言
在 二、Android系統源碼編譯及刷機實戰 一文中,我們成功編譯了Android 4.4.4_r1源碼並刷入系統了 Nexus 5 設備,下面是設置界面的信息。上面顯示的內核版本信息是3.4.0-gd59db4e
,內核的編譯時間是Mon Mar 17 15:16:36 PDT 2014
,也就是說內核之前就已經編譯過了,我們編譯系統源碼的時候並沒有編譯內核源碼!那麼編譯好的內核文件放在了哪裏呢?答案是device/<vendor>/<name>
目錄,針對Nexus 5 設備,就是device/lge/hammerhead-kernel
目錄
系統源碼和內核源碼是可以分開編譯的,如果僅僅對內核修改,就沒必要編譯系統源碼。所以下面的過程是在假設我們沒有下載系統源碼的情況下操作的!爲了編譯成功,沒下載系統源碼的同學一定要 參考 一、Android系統源碼下載實戰一文把編譯環境配置一下。類似於Android源碼根目錄,可以新建一個內核編譯項目的根目錄文件夾AndroidKernal
,把後面的各種操作下載在該目錄下進行。至於已經下載系統源碼的同學,就在Android系統源碼根目錄下新建kernel
文件夾作爲根目錄。Google 官方教程:https://source.android.com/source/building-kernels
一、選擇內核項目
我們首先應當確定自己設備所對應的內核。Google官方給出了二進制文件的名稱及內核源代碼所在Android源碼樹中的位置:(這時內核源代碼還沒有下載本地)
各個版本內核源碼項目所對應的下載命令:Google也給出了相應的下載命令:
$ git clone https://android.googlesource.com/kernel/common.git
$ git clone https://android.googlesource.com/kernel/hikey-linaro
$ 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
由於網絡連接問題,可以把上面所有
git clone
命令中https://android.googlesource.com/
網址換成清華鏡像站的https://aosp.tuna.tsinghua.edu.cn/
網址。
各個內核項目所支持的設備
goldfish
項目包含適用於所模擬的平臺的內核源代碼。msm
項目包含適用於 ADP1、ADP2、Nexus One、Nexus 4、Nexus 5、Nexus 6、Nexus 5X、Nexus 6P、Nexus 7 (2013)、Pixel 和 Pixel XL 的源代碼,可用作使用 Qualcomm MSM 芯片組的起點。omap
項目用於 PandaBoard 和 Galaxy Nexus,可用作使用 TI OMAP 芯片組的起點。samsung
項目用於 Nexus S,可用作使用 Samsung Hummingbird 芯片組的起點。tegra
項目用於 Xoom、Nexus 7 (2012)、Nexus 9,可用作使用 NVIDIA Tegra 芯片組的起點。exynos
項目包含適用於 Nexus 10 的內核源代碼,可用作使用 Samsung Exynos 芯片組的起點。x86_64
項目包含適用於 Nexus Player 的內核源代碼,可用作使用 Intel x86_64 芯片組的起點。hikey-linaro
項目用於 HiKey 參考板,可用作使用 HiSilicon 620 芯片組的起點。
我用是Nexus 5手機, 代號 harmmerhead
(錘頭),查找上表知道,內核二進制文件所在系統源碼樹的device/lge/hammerhead-kernel
目錄,內核源碼在系統源碼樹的kernel/msm
目錄,內核對應的編譯配置爲hammerhead_defconfig
, 該版本內核項目對應的下載命令爲
git clone https://aosp.tuna.tsinghua.edu.cn/kernel/msm.git
二、下載內核源碼項目,檢出內核分支代碼
msm
內核項目是Google公司針對高通msm移動芯片組(驍龍處理器)而開發的內核項目,我們在之前創建的AndroidKernel
目錄下執行git命令下載該項目(已經下載Android系統源碼的同學在系統根目錄下創建kernel
目錄下進行下載)
$ git clone https://aosp.tuna.tsinghua.edu.cn/kernel/msm.git
這時msm
項目的.git
倉庫 下載到了新創建的msm
目錄中,而msm內核的代碼還沒有從本地.git
倉庫中檢出來,所以整個msm
目錄空空的。
進入 msm
目錄後,查看msm項目的所有分支。下面的只列出了Nexus 5(代號:harmmerhead)相關的內核分支
aosp444@aosp444-virtual-machine:~/AndroidKernel/msm$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/android-4.4
remotes/origin/android-4.4.y
remotes/origin/android-msm-2.6.35
remotes/origin/android-msm-3.9-usb-and-mmc-hacks
......
remotes/origin/android-msm-hammerhead-3.4-kitkat-mr1
remotes/origin/android-msm-hammerhead-3.4-kitkat-mr2
remotes/origin/android-msm-hammerhead-3.4-kk-fr1
remotes/origin/android-msm-hammerhead-3.4-kk-fr2
remotes/origin/android-msm-hammerhead-3.4-kk-r1
remotes/origin/android-msm-hammerhead-3.4-l-preview
remotes/origin/android-msm-hammerhead-3.4-lollipop-mr1
remotes/origin/android-msm-hammerhead-3.4-lollipop-mr1.1
remotes/origin/android-msm-hammerhead-3.4-lollipop-release
remotes/origin/android-msm-hammerhead-3.4-m-preview
remotes/origin/android-msm-hammerhead-3.4-marshmallow
remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr1
remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr2
remotes/origin/android-msm-hammerhead-3.4-marshmallow-mr3
......
該檢出哪個分支呢?由於我不是特別熟悉git 命令操作,並不能根據git日誌詳細區分各個版本之間的區別。AOSP前技術領導人Jean-Baptiste Queru在給一位內核開發提交者的郵件中寫道,在安卓分支後綴中,mr = "maintenance release", fr = "factory rom".
,分支的名字在開發中是不斷變化,最好以commid id
進行提交。那麼我們就以commid id
進行檢出。官方給出的實例是按分支名進行下載,但是我暫時確定不了分支,所以採用了commid id
這種方式。
那麼我們怎麼獲得內核的版本信息與其中commid id
呢?
官方給出了一條通用的命令,來獲得指定二進制內核文件的版本信息
dd if=kernel bs=1 skip=$(LC_ALL=C grep -a -b -o $'\x1f\x8b\x08\x00\x00\x00\x00\x00' kernel | cut -d ':' -f 1) | zgrep -a 'Linux version'
例:
而Nexus 5 設備的內核名爲zImage-dtb
,官方給出的針對該設備的命令是:
$ dd if=zImage-dtb bs=1 skip=$(LC_ALL=C od -Ad -x -w2 zImage-dtb | grep 8b1f | cut -d ' ' -f1 | head -1) | zgrep -a 'Linux version'
事實上,我們可以在設置 > 關於手機 > 內核版本
中直接查看內核版本信息,也可以通過cat /proc/version
命令查看。內核版本信息的格式爲kernel version-gXXXXXXX
,其中 XXXXXXX
部分的值是git提交中 的short commit id
的值(即kernel version-g<short commit id>
),short commit id
的值爲commit id
值的前7位。Nexus 5 設備Adnroid 4.4.4_r1
版本 AOSP自帶的內核值是`3.4.0-gd59db4e
, 並且刷入手機能正常運行。
檢出帶代碼有兩種方式(推薦第二種):
一、直接 short commit id = d59db4e
來檢出分支。
$ git checkout d59db4e
檢出代碼後的msm
目錄:
二、確定 short commit id 所在的分支,按分支進行檢出(推薦)
在本地 git clone
msm
項目後,本地只有一個’master’ 分支,我們可以執行git branch -r --contains d59db4e
命令來查看包含 d59db4e
commit id 的分支
然後我們可以在遠程分支的基礎上在本地分化出一個新的分支來
$ git checkout -b android-msm-hammerhead-3.4-kitkat-mr2 origin/android-msm-hammerhead-3.4-kitkat-mr2
我們輸入git log
命令,發現d59db4e
值就是android-msm-hammerhead-3.4-kitkat-mr2
最後一次提交的 short commit id
三、下載預編譯工具鏈,添加路徑到PATH中
1.下載 gcc交叉編譯工具鏈
之前下載過AOSP源碼樹的同學,就不用再下載預編譯工具鏈了,AOSP跟目錄中後該工具鏈。沒有下載AOSP源碼樹的同學,在AndroidKernel
目錄下執行該執行進行下載:
$ git clone https://aosp.tuna.tsinghua.edu.cn/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6
2.配置交叉工具鏈路徑到環境變量中
已經下載 AOSP源碼樹的同學,進入的源碼樹根目錄下 ,重新執行source build/envsetup.sh
命令就會自動配置好環境變量。
沒有下載源樹的同學,在AndroidKernel目錄下執行export PATH=$(pwd)/arm-eabi-4.6/bin:$PATH
就會配置到環境變量中。
注意上述兩種方法都是在命令行中配置的,計算機重啓後會消失需重新配置,可將交叉編譯工具的的bin路徑寫到~/.bashrc
文件中
四、配置編譯選項,進行編譯
編譯前,一定要確定交叉工具鏈的路徑在PATH
變量中。
在內核交叉編譯前,配置一下編譯選項
$ export ARCH=arm //指明目標體系架構,arm、x86、arm64、
$ export CROSS_COMPILE=arm-eabi- //指定使用的交叉編譯器的前綴
進入到msm
目錄,配置
$ cd msm
$ make hammerhead_defconfig
執行 make
命令進行編譯
$ make
編譯成功後,會提示
這時會在arch/arm/boot/
目錄生成 Image
、zImage
、zImage-dtb
三個文件 。其中zImage-dtb
就是之前使用的內核二進制文件。
五、對boot.img 文件進行重打包
一、準備bootimg-tools工具
bootimg-tools工具是一款基於mkbootimg開發的boot.img 解包重打包C語言工具,github地址:https://github.com/pbatard/bootimg-tools
在烏班圖上用下面的命令下載:
$ git clone https://github.com/pbatard/bootimg-tools.git
下載後進入bootimg-tools
目錄,執行make
命令編譯該項目,在 makebootimg目錄下生成了相應的二進制執行文件,將該二進制文件所在路徑添加到 PATH
路徑中
$ make
二、使用 unmkbootimg
二進制文件進行解包
$ unmkbootimg -i boot.img
解包後生成 kernel
和 ramdisk.cpio.gz
兩個文件
三、用unmkbootimg
將之前編譯生成的 zImage-dtb
替換kernel
進行重打包
$ mkbootimg --base 0 --pagesize 2048 --kernel_offset 0x00008000 --ramdisk_offset 0x02900000 --second_offset 0x00f00000 --tags_offset 0x02700000 --cmdline 'console=ttyHSL0,115200,n8 androidboot.hardware=hammerhead user_debug=31 maxcpus=2 msm_watchdog_v2.enable=1' --kernel zImage-dtb --ramdisk ramdisk.cpio.gz -o bootnew.img
六、將新生成的bootnew.img刷入設備
輸入下面的命令進入fastboot 模式,並解鎖
$ adb reboot bootloader
$ fastboot oem unlock
在bootloader
模式下輸入下面的命令將bootnew.img
刷入boot
分區
$ fastboot flash boot bootnew.img
七、修改內核源碼中的調試標誌位
如果我們用推薦的第二種方式下載內核源碼,輸入git branch
命令可以查看當前已經切換到分支
我們可用git 工具對修改的內核源碼進行版本控制。
下面修改相應的調試標誌位:
第一處 msm/fs/proc/base.c
文件 273行 proc_pid_wchan
函數修改爲(主要對285行進行了修改)
static int proc_pid_wchan(struct task_struct *task, char *buffer)
{
unsigned long wchan;
char symname[KSYM_NAME_LEN];
wchan = get_wchan(task);
if (lookup_symbol_name(wchan, symname) < 0)
if (!ptrace_may_access(task, PTRACE_MODE_READ))
return 0;
else
return sprintf(buffer, "%lu", wchan);
else{
if (strstr(symname, "trace")) {
return sprintf(buffer, "%s", "sys_epoll_wait");
}
return sprintf(buffer, "%s", symname);
}
}
第二處 msm/fs/proc/array.c
文件 134行
static const char * const task_state_array[] = {
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"S (sleeping)", /* 4 */
"S (sleeping)", /* 8 */
"Z (zombie)", /* 16 */
"X (dead)", /* 32 */
"x (dead)", /* 64 */
"K (wakekill)", /* 128 */
"W (waking)", /* 256 */
};
第三處 msm/fs/proc/array.c
文件 180行
seq_printf(m,
"State:\t%s\n"
"Tgid:\t%d\n"
"Pid:\t%d\n"
"PPid:\t%d\n"
"TracerPid:\t%d\n"
"Uid:\t%d\t%d\t%d\t%d\n"
"Gid:\t%d\t%d\t%d\t%d\n",
get_task_state(p),
task_tgid_nr_ns(p, ns),
pid_nr_ns(pid, ns),
ppid, /*tpid*/0,
cred->uid, cred->euid, cred->suid, cred->fsuid,
cred->gid, cred->egid, cred->sgid, cred->fsgid);
修改完成後,將修改後的base.c
和 array.c
文件提交到本地倉庫
$ git add array.c base.c
$ git commit -m "change kernel anti flags"
再次按 上面的 三~ 六 步驟 編譯內核重新生成boot.timg刷入手機
測了一下 TracerPid值爲0
參考資料:
1.https://groups.google.com/forum/#!msg/android-building/5SKMilqvXys/LgbF576GF-YJ
2.https://softwarebakery.com/building-the-android-kernel-on-linux
3.http://marcin.jabrzyk.eu/posts/2014/05/building-and-booting-nexus-5-kernel
4.http://blog.csdn.net/qq1084283172/article/details/54880488