BOSS要求提高安卓系統的啟動速度,優化bootloader和kernel后,發現還是達不到要求,沒辦法才打起zygote的注意。
============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=4.2.2 TARGET_PRODUCT=sabresd_6dq TARGET_BUILD_VARIANT=user TARGET_BUILD_TYPE=release TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv7-a-neon HOST_ARCH=x86 HOST_OS=linux HOST_OS_EXTRA=Linux-3.5.0-41-generic-x86_64-with-Ubuntu-12.04-precise HOST_BUILD_TYPE=release BUILD_ID=1.0.0-rc3 OUT_DIR=out ============================================
以下參考shuaiff同學的部分研究成果:http://blog.csdn.net/shuaiff/article/details/5894646,感謝shuaiff同學的研究成果。
摘要:介紹了利用blcr對android啟動速度進行優化的原理、實施步驟和注意點,在虛擬機上驗證獲得縮短10秒以上啟動時間。
關鍵詞:blcr android 啟動速度 zygote 類加載
引言 隨着google的android操作系統在手機、平板電腦等領域大量使用,android的啟動速度慢也成為許多使用者抱怨的缺點。相比手機這類平時較少開關機的設備,平板電腦在實際使用中開關的頻率相對頻繁,開機速度是影響客戶感受的一個重要因素。Android啟動過程分為linux內核載入,文件系統掛接,zygote進程啟動和軟件包掃描幾個主要過程。其中耗時大戶發生在zygote的類載入和軟件包掃描過程兩處,只要減少這兩處的時間,啟動速度就會發生明顯的改變。如何有效加快啟動速度是眾多android產品制造者都感興趣的技術。本文就縮短android 啟動過程中公用類加載部分的一種技術做介紹,利用該方法,在虛擬機實際測試獲得良好的結果。
背景知識 Zygote是android中的核心進程,其負責android其他應用和服務的孵化,zygote啟動過程慢的一個原因在於
啟動過程中需要提前加載公用類(由文件preloaded-classes定義),這種加載是android設計人員特意根據linux和嵌入式系統特性設計的,網絡上有人嘗試將這些類的加載去除以加快開機速度,這種違背設計者初衷的方法被否決(參考1)。對於單個進程而言,如果使用到這些公共類,都必須完成對應類的載入並初始化,由於zygote是后續所有android的父進程,采用Class.forName處理的公共類會被載入到內存並完成靜態初始化,提前加載可以避免每個子進程調用時候需要生成公用類的副本(linux Copy-on-write特點),進而減少內存占用量以及后續啟動其他程序的花銷。這個加載過程關系到后續的性能,所以不能簡單的跳過。載入的過程主要是對內存的操作過程,其中包括了大量的內存分配釋放過程,該過程由於有上千個類需要操作而變得耗時較長。在實際應用中,由於framework部分較少升級,故這些公共類是不會被動態刪減,考慮到這些特點,采用check point方式每次直接將zygote還原到完成類加載的階段避開頻繁的類操作顯然可以提高速度。
BLCR (BerkeleyLab Checkpoint/Restart)是應用於linux下的check point/restore軟件,它可以將正在運行於linux上的應用當前的運行點保存成為一個文件並且在以后的時間可以按照需要將該程序直接恢復到保存時候的狀態。該軟件官方網站在:http://ftg.lbl.gov/checkpoint。根據其FAQ介紹BLCR對保存和恢復的程序有部分限制:1 無法保存和恢復打開的sockets(TCP/IP,Unix domain等)2 無法保存和恢復Sys V IPC對象。3 在處理還沒有回收僵屍子進程的父進程是需要注意。盡管有部分限制,只要在使用時候注意這些限制,利用其保存和恢復程序運行點和內存的能力完全可以避免程序每次不必要的初始化動作。Zygote在加載公共類前時候除了堆外其他資源使用很少,通過仔細的調整/恢復BLCR無法恢復的一些狀態,是可以用check point形式來跳過類加載以縮短啟動時間。 BLCR 包括內核驅動和應用庫兩部分,外部應用通過鏈接應用庫和內核驅動進行交換實現應用的保存和恢復。下面就針對內核為3.0.35的android4.2介紹實現blcr的具體過程。
實施過程:
1.需要的軟件和工具:
blcr-0.8.5,截止目前最新的版本是這個
A machine that is running a supported architecture (x86 and x86_64 are fully supported and PPC/PPC64 and ARM are "Experimental") and Linux kernel 2.6.x or 3.x.y.
android源代碼,我的機器是freescale的imx6系列,android4.2,內核版本為3.0.35.
i.MX 6系列處理器推出了業界首個具有真正擴展性的多核平台,包括基於ARM® Cortex™-A9架構的單核、雙核和四核系列產品。 在強大的生態體系支持下,i.MX 6系列成為開發一系列基於單一硬件設計的終端產品的理想平台。
http://sourceforge.net/projects/android-dfb/pthread的補丁
編譯android和內核在這里不詳述,需要指出的有兩點。
1 編譯內核時候注意加入可加載模塊支持(Enable loadablemodule support),缺省的goldfish內核配置是不支持的。
2 需要對android的bionic的線程庫進行擴展,擴展方法是采用上述軟件的pthread文件替換相應線程庫文件。
在做所有工作之前,請在blcr的解壓根目錄下面新建一個shell文件,名字隨便起,你可以起“cross-configure.sh”。至於為什么要這么做,因為官方文檔推薦,也因為直接使用源碼目錄中的configure文件會帶來很多麻煩,聽好的沒錯。cross-configure.sh文件一開始的樣子,你可以這樣寫:
1 #!/bin/bash 2 curpath=`pwd` 3 rm -rf `find ./ -name Makefile`
在做下面所有工作之前,請提前編譯好kernel,切記!
以下參考yihui8同學的部分研究成果,再次表示感謝:http://blog.csdn.net/yihui8/article/details/6101224
直接使用android內建的編譯器即可對內核驅動進行編譯。編譯過程只要指定正確的編譯器路徑和內核路徑即可順利編譯。
編譯不出blcr的兩個內核文件的同學,大多數都是因為arm工具鏈沒有設置正確,導致blcr的編譯工程不能正確識別要生成的目標平台。出現下面的configue錯誤都是如此
1.LinuxThreads是kernel2.6之前的多線程庫,而2.6以后的內核都換成POSIX實現的NPTL(Native POSIX Thread Library),有什么區別,為什么要這么做,大家自己google。
checking whether default pthreads library is LinuxThreads... configure: error: When cross-compiling, variable cross_linuxthreads must be set.
因為android4.2的內核版本是3.0.35,故我們要去掉對LinuxThreads的支持,現在請打開你的cross-configure.sh文件,在后面加入一下代碼,現在它的樣子,應該是這樣:
1 #!/bin/bash 2 curpath=`pwd` 3 rm -rf `find ./ -name Makefile` 4 5 export TARGET_TYPE=%MISSING% 6 export cross_stack_direction=-1 7 export cross_signum=64 8 export cross_linuxthreads=0
2.下面兩個configure錯誤都是arm工具鏈設置錯誤導致,在這里我走了相當多的彎路,曾經懷疑過工具鏈問題,也曾經懷疑后目標平台設置問題,總之蛋都碎了一地...
1 checking for parameters to interface GNU automake with Linux kbuild... KBUILD_EXTMOD=$(builddir) 2 checking for flags to compile Linux kernel probes... FAILED 3 make: Entering directory `/home/inuyasha/SDB/myandroid/kernel_imx' 4 test -e include/generated/autoconf.h -a -e include/config/auto.conf || ( \ 5 echo; \ 6 echo " ERROR: Kernel configuration is invalid."; \ 7 echo " include/generated/autoconf.h or include/config/auto.conf are missing.";\ 8 echo " Run 'make oldconfig && make prepare' on kernel src to fix it."; \ 9 echo; \ 10 /bin/false)
和
1 checking size of void *... (cached) 8 2 configure: error: CC='gcc' yields sizeof(void *) = 8 when expecting 4.
第一個error是你指定了正確的arm工具鏈,但是沒有設置目標文件的平台。第二個error比較隱蔽,表面上看不出任何問題,實際上問題出在:configure: error: CC='gcc',這個什么意思呢?說明你的autotool根本不認識你的arm工具鏈,雖然你正確的指出了目標文件。具體原因不做熬述。其實你仔細觀察會發現在開頭有這么幾行:
1 checking host system type... arm-unknown-linux-gnu
1 checking for arm-linux-g++... no 2 checking for arm-linux-c++... no 3 checking for arm-linux-gpp... no 4 checking for arm-linux-aCC... no 5 checking for arm-linux-CC... no 6 checking for arm-linux-cxx... no 7 checking for arm-linux-cc++... no 8 checking for arm-linux-cl.exe... no 9 checking for arm-linux-FCC... no 10 checking for arm-linux-KCC... no 11 checking for arm-linux-RCC... no 12 checking for arm-linux-xlC_r... no 13 checking for arm-linux-xlC... no
這寫錯誤信息,都說明你指定的工具鏈不正確導致識別不了host system和找不到你指定的工具鏈,所以說遇到問題,還是要靜下心來,自己看看出錯信息,別一味的指望google。
怎么改:
目前測試來看,gnu的arm工具鏈是可以用的,android源代碼中自帶的和其他第三方的,autotool都識別不出來,現在你的cross-configure.sh應該是這個樣子:
1 #!/bin/bash 2 curpath=`pwd` 3 rm -rf `find ./ -name Makefile` 4 5 export TARGET_TYPE=%MISSING% 6 export cross_stack_direction=-1 7 export cross_signum=64 8 export cross_linuxthreads=0 9 export ARCH=arm 10 11 export PATH=$PATH:.../arm-none-linux-gnueabi/bin ---->這里請指定你的arm工具鏈目錄 12 TOOLCHAIN=.../arm-none-linux-gnueabi/bin ----->同上 13 14 ./configure KCC=$TOOLCHAIN/arm-none-linux-gnueabi-gcc LD=$TOOLCHAIN/arm-none-linux-gnueabi-ld --with-linux-src=$curpath/../../kernel_imx --with-linux=$curpath/../../kernel_imx --host=arm-none-linux-gnueabi
最后在上面的文件后面加入:
1 cd blcr_imports/ 2 make all 3 echo generated kernel module:`ls kbuild/*.ko` 4 cd ../cr_module/ 5 make all 6 echo generated kernel module:`ls kbuild/*.ko`
生成blcr的兩個內核模塊。
1 Building modules, stage 2. 2 MODPOST 1 modules 3 LD [M] /home/inuyasha/SDB/myandroid/external/blcr-0.8.5/cr_module/kbuild/blcr.ko 4 gmake[2]:正在離開目錄 `/home/inuyasha/SDB/myandroid/kernel_imx' 5 gmake[1]:正在離開目錄 `/home/inuyasha/SDB/myandroid/external/blcr-0.8.5/cr_module/kbuild' 6 Making all in . 7 gmake[1]: 正在進入目錄 `/home/inuyasha/SDB/myandroid/external/blcr-0.8.5/cr_module' 8 gmake[1]: 沒有什么可以做的為 `all-am'。 9 gmake[1]:正在離開目錄 `/home/inuyasha/SDB/myandroid/external/blcr-0.8.5/cr_module' 10 generated kernel module:kbuild/blcr.ko
zygote加入checkpoint 支持准備放在下一章來寫,敬請期待。
本作品采用知識共享署名-非商業性使用-禁止演繹 2.5 中國大陸許可協議進行許可。