Android系統(tǒng)鏡像文件的打包過程分析_第1頁
Android系統(tǒng)鏡像文件的打包過程分析_第2頁
Android系統(tǒng)鏡像文件的打包過程分析_第3頁
Android系統(tǒng)鏡像文件的打包過程分析_第4頁
Android系統(tǒng)鏡像文件的打包過程分析_第5頁
已閱讀5頁,還剩18頁未讀 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

Android系統(tǒng)鏡像文件的打包過程分析在前面一篇文章中,我們分析了Android模塊的編譯過程。當(dāng)Android系統(tǒng)的所有模塊都編譯好之后,我們就可以對編譯出來的模塊文件進(jìn)行打包了。打包結(jié)果是獲得一系列的鏡像文件,例如system.img、boot.img、ramdisk.img、userdata.img和recovery.img等。這些鏡像文件最終可以燒錄到手機(jī)上運(yùn)行。在本文中,我們就詳細(xì)分析Android系統(tǒng)的鏡像文件的打包過程。Android系統(tǒng)鏡像文件的打包工作同樣是由Android編譯系統(tǒng)來完成的,如圖1所示:從前面和這兩篇文章可以知道,Android編譯系統(tǒng)在初始化的過程中,會(huì)通過根目錄下的Makefile腳本加載build/core/main.mk腳本,接著build/core/main.mk腳本又會(huì)加載build/core/Makefile腳本,而Android系統(tǒng)鏡像文件就是由build/core/Makefile腳本負(fù)責(zé)打包生成的。在build/core/main.mk文件中,與Android系統(tǒng)鏡像文件打包過程相關(guān)的內(nèi)容如下所示:[plain]viewplaincopyifdefFULL_BUILD#Thebaselistofmodulestobuildforthisproductisspecified#bytheappropriateproductdefinitionfile,whichwasincluded#byproduct_duct_MODULES:=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES)#Filterouttheoverriddenpackagesbeforedoingexpansionproduct_MODULES:=$(filter-out$(foreachp,$(product_MODULES),\$(PACKAGES.$(p).OVERRIDES)),$(product_MODULES))$(callexpand-required-modules,product_MODULES,$(product_MODULES))product_FILES:=$(callmodule-installed-files,$(product_MODULES))else#We'renotdoingafullbuild,andareprobablyonlyincluding#asubsetofthemodulemakefiles.Don'ttrytobuildanymodules#requestedbytheproduct,becauseweprobablywon'thaverules#duct_FILES:=endifmodules_to_install:=$(sort\$(ALL_DEFAULT_INSTALLED_MODULES)\$(product_FILES)\$(foreachtag,$(tags_to_install),$($(tag)_MODULES))\$(callget-tagged-modules,shell_$(TARGET_SHELL))\$(CUSTOM_MODULES)\)#SomepackagesmayoverrideothersusingLOCAL_OVERRIDES_PACKAGES.#Filterout(donotinstall)anyoverriddenpackages.overridden_packages:=$(callget-package-overrides,$(modules_to_install))ifdefoverridden_packages#old_modules_to_install:=$(modules_to_install)modules_to_install:=\$(filter-out$(foreachp,$(overridden_packages),$(p)%/$(p).apk),\$(modules_to_install))endif#Installallofthehostmodulesmodules_to_install+=$(sort$(modules_to_install)$(ALL_HOST_INSTALLED_FILES))#build/core/Makefilecontainsextrastuffthatwedon'twanttopollutethis#top-levelmakefilewith.ItexpectsthatALL_DEFAULT_INSTALLED_MODULES#containseverythingthat'sbuiltduringthecurrentmake,butitalsofurther#extendsALL_DEFAULT_INSTALLED_MODULES.ALL_DEFAULT_INSTALLED_MODULES:=$(modules_to_install)include$(BUILD_SYSTEM)/Makefilemodules_to_install:=$(sort$(ALL_DEFAULT_INSTALLED_MODULES))ALL_DEFAULT_INSTALLED_MODULES:=.PHONY:ramdiskramdisk:$(INSTALLED_RAMDISK_TARGET).PHONY:userdataimageuserdataimage:$(INSTALLED_USERDATAIMAGE_TARGET).PHONY:bootimagebootimage:$(INSTALLED_BOOTIMAGE_TARGET)如果定義在FULL_BUILD這個(gè)變量,就意味著我們是要對整個(gè)系統(tǒng)進(jìn)行編譯,并且編譯完成之后,需要將編譯得到的文件進(jìn)行打包,以便可以得到相應(yīng)的鏡像文件,否則的話,就僅僅是對某些模塊進(jìn)行編譯。在前面一篇文章中,我們提到,變量INTERNAL_PRODUCT描述的是執(zhí)行l(wèi)unch命令時(shí)所選擇的產(chǎn)品所對應(yīng)的產(chǎn)品Makefile文件,而變量PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES描述的是在該產(chǎn)品Makefile文件中通過變量PRODUCT_PACKAGES所定義的模塊名稱列表。因此,我們得到的變量product_MODULES描述的就是要安裝的模塊名稱列表。我們知道,Android源碼中自帶了很多默認(rèn)的APK模塊。如果我們想用自己編寫的一個(gè)APK來代替某一個(gè)系統(tǒng)自帶的APK,那么就可以通過變量PACKAGES.<new>.OVERRIDES:=<old>來說明。其中,<new>表示用來替換的APK,而<old>表示被替換的APK。在這種情況下,被替換的APK是不應(yīng)該被打包到系統(tǒng)鏡像中去的。因此,我們需要從上一步得到的模塊名稱列表中剔除那些被替換的APK,這是通過Makefile腳本提供的filter-out函數(shù)來完成的。一個(gè)模塊可以通過LOCAL_REQUIRED_MODULES變量來指定它所依賴的其它模塊,因此,當(dāng)一個(gè)模塊被安裝的時(shí)候,它所依賴的其它模塊也會(huì)一起被安裝。調(diào)用函數(shù)expand-required-modules獲得的就是所有要安裝的模塊所依賴的其它模塊,并且將這些被依賴的模塊也一起保存在變量product_MODULES中。注意,這時(shí)候我們得到的product_MODULES描述的僅僅是要安裝的模塊的名稱,但是我們實(shí)際需要的這些模塊對應(yīng)的具體文件,因此,需要進(jìn)一步調(diào)用函數(shù)module-installed-files來獲得要安裝的模塊所對應(yīng)的文件,也就是要安裝的模塊經(jīng)過編譯之后生成的文件,這些文件就保存在變量product_FILES中。最終需要安裝的文件除了變量product_FILES所描述的文件之后,還包含以下四類模塊文件:1.變量ALL_DEFAULT_INSTALLED_MODULES描述的文件。2.變量CUSTOM_MODULES描述的文件。3.與當(dāng)前編譯類型對應(yīng)的模塊文件。例如,如果當(dāng)前設(shè)定的編譯類型為debug,那么所有通過將變量LOCAL_MODULE_TAGS將自己設(shè)置為debug的模塊也會(huì)被打包到系統(tǒng)鏡像文件中去。4.與當(dāng)前shell名稱對應(yīng)的模塊文件。例如,如果當(dāng)前使用的shell是mksh,那么所有通過將變量LOCAL_MODULE_TAGS將自己設(shè)置為shell_mksh的模塊也會(huì)被打包到系統(tǒng)鏡像文件中去。最后,modules_to_install就描述當(dāng)前需要打包到系統(tǒng)鏡像中去的模塊文件。實(shí)際上,我們除了可以通過PACKAGES.$(p).OVERRIDES來描述要替換的APK之后,還可以在一個(gè)模塊中通過LOCAL_OVERRIDES_PACKAGES來描述它所替換的模塊。因此,我們需要通過函數(shù)get-package-overrides來獲得此類被替換的模塊文件,并且將它們從modules_to_install中剔除,這樣得到的模塊文件才是最終需要安裝的。確定了要安裝的所有模塊文件之后,就可以將build/core/Makefile文件加載進(jìn)來了。注意,文件build/core/Makefile是通過變量ALL_DEFAULT_INSTALLED_MODULES來獲得當(dāng)前所有要打包到系統(tǒng)鏡像文件中去的模塊文件的。文件build/core/Makefile主要就是用來打包各種Android系統(tǒng)鏡像文件的,當(dāng)然它也是通過make規(guī)則來執(zhí)行各種Android系統(tǒng)鏡像文件打包命令的。每一個(gè)Android鏡像文件都對應(yīng)有一個(gè)make偽目標(biāo)。例如,在build/core/main.mk文件中,就定義了三個(gè)make偽目標(biāo)ramdisk、userdataimage和bootimage,它們分別依賴于變量INSTALLED_USERDATAIMAGE_TARGET、INSTALLED_USERDATAIMAGE_TARGET和INSTALLED_BOOTIMAGE_TARGET所描述的文件,并且它們分別表示的就是ramdisk.img、userdata.img和boot.img文件。變量INSTALLED_USERDATAIMAGE_TARGET、INSTALLED_USERDATAIMAGE_TARGET和INSTALLED_BOOTIMAGE_TARGET都是在build/core/Makefile文件中定義的。此外,build/core/Makefile文件還定義了另外兩個(gè)鏡像文件system.img和recovery.img的生成規(guī)則。接下來,我們就分別對這些鏡像文件的打包過程進(jìn)行分析。一.system.imgsystem.img鏡像文件描述的是設(shè)備上的system分區(qū),即/system目錄,它是在build/core/Makefile文件中生成的,相關(guān)的內(nèi)容如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片#Rulesthatneedtobepresentforthealltargets,even#iftheydon'tdoanything..PHONY:systemimagesystemimage:INSTALLED_SYSTEMIMAGE:=$(PRODUCT_OUT)/system.img$(INSTALLED_SYSTEMIMAGE):$(BUILT_SYSTEMIMAGE)$(RECOVERY_FROM_BOOT_PATCH)|$(ACP)@echo"Installsystemfsimage:$@"$(copy-file-to-target)$(hide)$(callassert-max-image-size,$@$(RECOVERY_FROM_BOOT_PATCH),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE),yaffs)systemimage:$(INSTALLED_SYSTEMIMAGE).PHONY:systemimage-nodepssnodsystemimage-nodepssnod:$(filter-outsystemimage-nodepssnod,$(MAKECMDGOALS))\|$(INTERNAL_USERIMAGES_DEPS)@echo"make$@:ignoringdependencies"$(callbuild-systemimage-target,$(INSTALLED_SYSTEMIMAGE))$(hide)$(callassert-max-image-size,$(INSTALLED_SYSTEMIMAGE),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE),yaffs)從這里就可以看出,build/core/Makefile文件定義了兩個(gè)偽目標(biāo)來生成system.img:1.systemimg;2.systemimg-nodeps或者snod。偽目標(biāo)systemimg表示在打包system.img之前,要根據(jù)依賴規(guī)則重新生成所有要進(jìn)行打包的文件,而偽目標(biāo)systemimg-nodeps則不需要根據(jù)依賴規(guī)則重新生成所有需要打包的文件而直接打包system.img文件。因此,執(zhí)行systemimg-nodep比執(zhí)行systemimg要快很多。通常,如果我們在Android源碼中修改了某一個(gè)模塊,并且這個(gè)模塊不被其它模塊依賴,那么對這個(gè)模塊進(jìn)行編譯之后,就可以簡單地執(zhí)行makesystemimg-nodeps來重新打包system.img。但是,如果我們修改的模塊會(huì)被其它模塊引用,例如,我們修改了Android系統(tǒng)的核心模塊framework.jar和services.jar,那么就需要執(zhí)行makesystemimg來更新所有依賴于framework.jar和services.jar的模塊,那么最后得到的system.img才是正確的鏡像。否則的話,會(huì)導(dǎo)致Android系統(tǒng)啟動(dòng)失敗。接下來,我們就主要關(guān)注偽目標(biāo)systemimg生成system.img鏡像文件的過程。偽目標(biāo)systemimg依賴于INSTALLED_SYSTEMIMAGE,也就是最終生成的$(PRODUCT_OUT)/system.img文件。INSTALLED_SYSTEMIMAGE又依賴于BUILT_SYSTEMIMAGE、RECOVERY_FROM_BOOT_PATCH和ACP。注意,BUILT_SYSTEMIMAGE、RECOVERY_FROM_BOOT_PATCH和ACP之間有一個(gè)管道符號(hào)相隔。在一個(gè)make規(guī)則之中,一個(gè)目標(biāo)的依賴文件可以劃分為兩類。一個(gè)類是普通依賴文件,它們位于管道符號(hào)的左則,另一類稱為“order-only”依賴文件,它們位于管理符號(hào)的右側(cè)。每一個(gè)普通依賴文件發(fā)生修改后,目標(biāo)都會(huì)被更新。但是"order-only"依賴文件發(fā)生修改時(shí),卻不一定會(huì)導(dǎo)致目標(biāo)更新。只有當(dāng)目標(biāo)文件不存在的情況下,"order-only"依賴文件的修改才會(huì)更新目標(biāo)文件。也就是說,只有在目標(biāo)文件不存在的情況下,“order-only”依賴文件才會(huì)參與到規(guī)則的執(zhí)行過程中去。ACP描述的是一個(gè)Android專用的cp命令,在生成system.img鏡像文件的過程中是需要用到的。普通的cp命令在不同的平臺(tái)(MacOSX、MinGW/Cygwin和Linux)的實(shí)現(xiàn)略有差異,并且可能會(huì)導(dǎo)致一些問題,于是Android編譯系統(tǒng)就重寫了自己的cp命令,使得它在不同平臺(tái)下執(zhí)行具有統(tǒng)一的行為,并且解決普通cp命令可能會(huì)出現(xiàn)的問題。例如,在Linux平臺(tái)上,當(dāng)我們把一個(gè)文件從NFS文件系統(tǒng)拷貝到本地文件系統(tǒng)時(shí),普通的cp命令總是會(huì)認(rèn)為在NFS文件系統(tǒng)上的文件比在本地文件系統(tǒng)上的文件要新,因?yàn)榍罢叩臅r(shí)間戳精度是微秒,而后者的時(shí)間戳精度不是微秒。Android專用的cp命令源碼可以參考build/tools/acp目錄。RECOVERY_FROM_BOOT_PATCH描述的是一個(gè)patch文件,它的依賴規(guī)則如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片#Thesystempartitionneedsroomfortherecoveryimageaswell.We#nowstoretherecoveryimageasabinarypatchusingthebootimage#asthesource(sincetheyareverysimilar).Generatethepatchso#wecanseehowbigit'sgoingtobe,andincludethatinthesystem#imagesizecheckcalculation.ifneq($(INSTALLED_RECOVERYIMAGE_TARGET),)intermediates:=$(callintermediates-dir-for,PACKAGING,recovery_patch)RECOVERY_FROM_BOOT_PATCH:=$(intermediates)/recovery_from_boot.p$(RECOVERY_FROM_BOOT_PATCH):$(INSTALLED_RECOVERYIMAGE_TARGET)\$(INSTALLED_BOOTIMAGE_TARGET)\$(HOST_OUT_EXECUTABLES)/imgdiff\$(HOST_OUT_EXECUTABLES)/bsdiff@echo"Constructrecoveryfromboot"mkdir-p$(dir$@)PATH=$(HOST_OUT_EXECUTABLES):$$PATH$(HOST_OUT_EXECUTABLES)/imgdiff$(INSTALLED_BOOTIMAGE_TARGET)$(INSTALLED_RECOVERYIMAGE_TARGET)$@endif這個(gè)patch文件的名稱為recovery_from_boot.p,保存在設(shè)備上system分區(qū)中,描述的是recovery.img與boot.img之間的差異。也就是說,在設(shè)備上,我們可以通過boot.img和recovery_from_boot.p文件生成一個(gè)recovery.img文件,使得設(shè)備可以進(jìn)入recovery模式。INSTALLED_SYSTEMIMAGE描述的是system.img鏡像所包含的核心文件,它的依賴規(guī)則如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片systemimage_intermediates:=\$(callintermediates-dir-for,PACKAGING,systemimage)BUILT_SYSTEMIMAGE:=$(systemimage_intermediates)/system.img#$(1):outputfiledefinebuild-systemimage-target@echo"Targetsystemfsimage:$(1)"@mkdir-p$(dir$(1))$(systemimage_intermediates)&&rm-rf$(systemimage_intermediates)/system_image_info.txt$(callgenerate-userimage-prop-dictionary,$(systemimage_intermediates)/system_image_info.txt)$(hide)PATH=$(foreachp,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH\./build/tools/releasetools/build_image.py\$(TARGET_OUT)$(systemimage_intermediates)/system_image_info.txt$(1)endef$(BUILT_SYSTEMIMAGE):$(FULL_SYSTEMIMAGE_DEPS)$(INSTALLED_FILES_FILE)$(callbuild-systemimage-target,$@)INSTALLED_SYSTEMIMAGE描述的是$(systemimage_intermediates)/system.img文件,它依賴于FULL_SYSTEMIMAGE_DEPS和INSTALLED_FILES_FILE,并且是通過調(diào)用函數(shù)build-systemimage-target來生成,而函數(shù)build-systemimage-target實(shí)際上又是通過調(diào)用Python腳本build_image.py來生成system.img文件的。INSTALLED_FILES_FILE的依賴規(guī)則如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片##installedfilelist#Dependingonanythingthat$(BUILT_SYSTEMIMAGE)dependson.#Weputinstalled-files.txtaheadofimageitselfinthedependencygraph#sothatwecangetthesizestatevenifthebuildfailsduetotoolarge#systemimage.INSTALLED_FILES_FILE:=$(PRODUCT_OUT)/installed-files.txt$(INSTALLED_FILES_FILE):$(FULL_SYSTEMIMAGE_DEPS)@echoInstalledfilelist:$@@mkdir-p$(dir$@)@rm-f$@$(hide)build/tools/fileslist.py$(TARGET_OUT)>$@INSTALLED_FILES_FILE描述的是$(PRODUCT_OUT)/installed-files.txt文件,該文件描述了要打包在system.img鏡像中去的文件列表,同時(shí)它與INSTALLED_SYSTEMIMAGE一樣,也依賴于FULL_SYSTEMIMAGE_DEPS。FULL_SYSTEMIMAGE_DEPS的定義如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片F(xiàn)ULL_SYSTEMIMAGE_DEPS:=$(INTERNAL_SYSTEMIMAGE_FILES)$(INTERNAL_USERIMAGES_DEPS)INTERNAL_USERIMAGES_DEPS描述的是制作system.img鏡像所依賴的工具。例如,如果要制作的system.img使用的是yaffs2文件系統(tǒng),那么對應(yīng)工具就是mkyaffs2image。INTERNAL_SYSTEMIMAGE_FILES描述的是用來制作system.img鏡像的文件,它的定義如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片INTERNAL_SYSTEMIMAGE_FILES:=$(filter$(TARGET_OUT)/%,\$(ALL_PREBUILT)\$(ALL_COPIED_HEADERS)\$(ALL_GENERATED_SOURCES)\$(ALL_DEFAULT_INSTALLED_MODULES)\$(PDK_FUSION_SYSIMG_FILES)\$(RECOVERY_RESOURCE_ZIP))從這里就可以看出,INTERNAL_SYSTEMIMAGE_FILES描述的就是從ALL_PREBUILT、ALL_COPIED_HEADERS、ALL_GENERATED_SOURCES、ALL_DEFAULT_INSTALLED_MODULES、PDK_FUSION_SYSIMG_FILES和RECOVERY_RESOURCE_ZIP中過濾出來的存放在TARGET_OUT目錄下的那些文件,即在目標(biāo)產(chǎn)品輸出目錄中的system子目錄下那些文件。ALL_PREBUILT是一個(gè)過時(shí)的變量,用來描述要拷貝到目標(biāo)設(shè)備上去的文件,現(xiàn)在建議使用PRODUCT_COPY_FILES來描述要拷貝到目標(biāo)設(shè)備上去的文件。ALL_COPIED_HEADERS描述的是要拷貝到目標(biāo)設(shè)備上去的頭文件。ALL_GENERATED_SOURCES描述的是要拷貝到目標(biāo)設(shè)備上去的由工具自動(dòng)生成的源代碼文件。ALL_DEFAULT_INSTALLED_MODULES描述的就是要安裝要目標(biāo)設(shè)備上的模塊文件,這些模塊文件是在build/core/main.mk文件中設(shè)置好并且傳遞給build/core/Makefile文件使用的。PDK_FUSION_SYSIMG_FILES是從PDK(PlatformDevelopmentKit)提取出來的相關(guān)文件。PDK是Google為了解決Android碎片化問題而為手機(jī)廠商提供的一個(gè)新版本的、還未發(fā)布的Android開發(fā)包,目的是為了讓手機(jī)廠商跟上官方新版Android的開發(fā)節(jié)奏。具體可以參考這篇文章:http://www.xinwengao.NET/release/af360/67079.shtml。RECOVERY_RESOURCE_ZIP描述的是Android的recovery系統(tǒng)要使用的資源文件,對應(yīng)于/system/etc目錄下的recovery-resource.dat文件。注意,ALL_DEFAULT_INSTALLED_MODULES描述的文件除了在build/core/main.mk文件中定義的模塊文件之外,還包含以下這些文件:1.通過PRODUCT_COPY_FILES定義的要拷貝到目標(biāo)設(shè)備上去的文件[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片unique_product_copy_files_pairs:=$(foreachcf,$(PRODUCT_COPY_FILES),\$(if$(filter$(unique_product_copy_files_pairs),$(cf)),,\$(evalunique_product_copy_files_pairs+=$(cf))))unique_product_copy_files_destinations:=$(foreachcf,$(unique_product_copy_files_pairs),\$(eval_src:=$(callword-colon,1,$(cf)))\$(eval_dest:=$(callword-colon,2,$(cf)))\$(callcheck-product-copy-files,$(cf))\$(if$(filter$(unique_product_copy_files_destinations),$(_dest)),\$(infoPRODUCT_COPY_FILES$(cf)ignored.),\$(eval_fulldest:=$(callappend-path,$(PRODUCT_OUT),$(_dest)))\$(if$(filter%.xml,$(_dest)),\$(eval$(callcopy-xml-file-checked,$(_src),$(_fulldest))),\$(eval$(callcopy-one-file,$(_src),$(_fulldest))))\<spanstyle="color:#FF0000;"><strong>$(evalALL_DEFAULT_INSTALLED_MODULES+=$(_fulldest))\</strong></span>$(evalunique_product_copy_files_destinations+=$(_dest))))2.由ADDITIONAL_DEFAULT_PROPERTIES定義的屬性所組成的p文件[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片INSTALLED_DEFAULT_PROP_TARGET:=$(TARGET_ROOT_OUT)/p<spanstyle="color:#FF0000;"><strong>ALL_DEFAULT_INSTALLED_MODULES+=$(INSTALLED_DEFAULT_PROP_TARGET)</strong></span>ADDITIONAL_DEFAULT_PROPERTIES:=\$(callcollapse-pairs,$(ADDITIONAL_DEFAULT_PROPERTIES))ADDITIONAL_DEFAULT_PROPERTIES+=\$(callcollapse-pairs,$(PRODUCT_DEFAULT_PROPERTY_OVERRIDES))ADDITIONAL_DEFAULT_PROPERTIES:=$(calluniq-pairs-by-first-component,\$(ADDITIONAL_DEFAULT_PROPERTIES),=)$(INSTALLED_DEFAULT_PROP_TARGET):@echoTargetbuildinfo:$@@mkdir-p$(dir$@)$(hide)echo"#">$@;\echo"#ADDITIONAL_DEFAULT_PROPERTIES">>$@;\echo"#">>$@;$(hide)$(foreachline,$(ADDITIONAL_DEFAULT_PROPERTIES),\echo"$(line)">>$@;)build/tools/post_process_props.py$@3.由ADDITIONAL_BUILD_PROPERTIES等定義的屬性所組成的p文件[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片INSTALLED_BUILD_PROP_TARGET:=$(TARGET_OUT)/p<spanstyle="color:#FF0000;"><strong>ALL_DEFAULT_INSTALLED_MODULES+=$(INSTALLED_BUILD_PROP_TARGET)</strong></span>ADDITIONAL_BUILD_PROPERTIES:=\$(callcollapse-pairs,$(ADDITIONAL_BUILD_PROPERTIES))ADDITIONAL_BUILD_PROPERTIES:=$(calluniq-pairs-by-first-component,\$(ADDITIONAL_BUILD_PROPERTIES),=)BUILDINFO_SH:=build/tools/buildinfo.sh$(INSTALLED_BUILD_PROP_TARGET):$(BUILDINFO_SH)$(INTERNAL_BUILD_ID_MAKEFILE)$(BUILD_SYSTEM)/version_defaults.mk$(wildcard$(TARGET_DEVICE_DIR)/p)@echoTargetbuildinfo:$@@mkdir-p$(dir$@)$(hide)TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)"\TARGET_DEVICE="$(TARGET_DEVICE)"\PRODUCT_NAME="$(TARGET_PRODUCT)"\PRODUCT_BRAND="$(PRODUCT_BRAND)"\PRODUCT_DEFAULT_LANGUAGE="$(calldefault-locale-language,$(PRODUCT_LOCALES))"\PRODUCT_DEFAULT_REGION="$(calldefault-locale-region,$(PRODUCT_LOCALES))"\PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)"\PRODUCT_MODEL="$(PRODUCT_MODEL)"\PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)"\PRIVATE_BUILD_DESC="$(PRIVATE_BUILD_DESC)"\BUILD_ID="$(BUILD_ID)"\BUILD_DISPLAY_ID="$(BUILD_DISPLAY_ID)"\BUILD_NUMBER="$(BUILD_NUMBER)"\PLATFORM_VERSION="$(PLATFORM_VERSION)"\PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)"\PLATFORM_VERSION_CODENAME="$(PLATFORM_VERSION_CODENAME)"\BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)"\TARGET_BOOTLOADER_BOARD_NAME="$(TARGET_BOOTLOADER_BOARD_NAME)"\BUILD_FINGERPRINT="$(BUILD_FINGERPRINT)"\TARGET_BOARD_PLATFORM="$(TARGET_BOARD_PLATFORM)"\TARGET_CPU_ABI="$(TARGET_CPU_ABI)"\TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)"\TARGET_AAPT_CHARACTERISTICS="$(TARGET_AAPT_CHARACTERISTICS)"\bash$(BUILDINFO_SH)>$@$(hide)if[-f$(TARGET_DEVICE_DIR)/p];then\cat$(TARGET_DEVICE_DIR)/p>>$@;\fi$(if$(ADDITIONAL_BUILD_PROPERTIES),\$(hide)echo>>$@;\echo"#">>$@;\echo"#ADDITIONAL_BUILD_PROPERTIES">>$@;\echo"#">>$@;)$(hide)$(foreachline,$(ADDITIONAL_BUILD_PROPERTIES),\echo"$(line)">>$@;)$(hide)build/tools/post_process_props.py$@4.用來描述event類型日志格式的event-log-tags文件[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片all_event_log_tags_file:=$(TARGET_OUT_COMMON_INTERMEDIATES)/all-event-log-tags.txtevent_log_tags_file:=$(TARGET_OUT)/etc/event-log-tags#Includetagsfromallpackagesthatweknowaboutall_event_log_tags_src:=\$(sort$(foreachm,$(ALL_MODULES),$(ALL_MODULES.$(m).EVENT_LOG_TAGS)))#PDKbuildswillalreadyhaveafulllistoftagsthatneedstogetmerged#inwiththeonesfromsourcepdk_fusion_log_tags_file:=$(patsubst$(PRODUCT_OUT)/%,$(_pdk_fusion_intermediates)/%,$(filter$(event_log_tags_file),$(ALL_PDK_FUSION_FILES)))$(all_event_log_tags_file):PRIVATE_SRC_FILES:=$(all_event_log_tags_src)$(pdk_fusion_log_tags_file)$(hide)mkdir-p$(dir$@)$(hide)build/tools/merge-event-log-tags.py-o$@$(PRIVATE_SRC_FILES)#Includetagsfromallpackagesincludedinthisproduct,plusall#tagsthatarepartofthesystem(ie,notinavendor/ordevice/#directory).event_log_tags_src:=\$(sort$(foreachm,\$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES)\$(callmodule-names-for-tag-list,user),\$(ALL_MODULES.$(m).EVENT_LOG_TAGS))\$(filter-outvendor/%device/%out/%,$(all_event_log_tags_src)))$(event_log_tags_file):PRIVATE_SRC_FILES:=$(event_log_tags_src)$(pdk_fusion_log_tags_file)$(event_log_tags_file):PRIVATE_MERGED_FILE:=$(all_event_log_tags_file)$(event_log_tags_file):$(event_log_tags_src)$(all_event_log_tags_file)$(pdk_fusion_log_tags_file)$(hide)mkdir-p$(dir$@)$(hide)build/tools/merge-event-log-tags.py-o$@-m$(PRIVATE_MERGED_FILE)$(PRIVATE_SRC_FILES)event-log-tags:$(event_log_tags_file)<strong><spanstyle="color:#FF0000;">ALL_DEFAULT_INSTALLED_MODULES+=$(event_log_tags_file)</span></strong>關(guān)于Android系統(tǒng)的event日志,可以參考和這個(gè)系列的文章。5.由于使用了BSD、GPL和Apache許可的模塊而必須在發(fā)布時(shí)附帶的Notice文件[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片target_notice_file_txt:=$(TARGET_OUT_INTERMEDIATES)/NOTICE.txttarget_notice_file_html:=$(TARGET_OUT_INTERMEDIATES)/NOTICE.htmltarget_notice_file_html_gz:=$(TARGET_OUT_INTERMEDIATES)/NOTICE.html.gztools_notice_file_txt:=$(HOST_OUT_INTERMEDIATES)/NOTICE.txttools_notice_file_html:=$(HOST_OUT_INTERMEDIATES)/NOTICE.htmlkernel_notice_file:=$(TARGET_OUT_NOTICE_FILES)/src/kernel.txtpdk_fusion_notice_files:=$(filter$(TARGET_OUT_NOTICE_FILES)/%,$(ALL_PDK_FUSION_FILES))#Installthehtmlfileat/system/etc/NOTICE.html.gz.#Thisisnotideal,butthisisverylateinthegame,afteralotof#themoduleprocessinghasalreadybeendone--infact,weusedthe#factthatallthathasbeendonetogetthelistofmodulesthatwe#neednoticefilesfor.$(target_notice_file_html_gz):$(target_notice_file_html)|$(MINIGZIP)$(hide)$(MINIGZIP)-9<$<>$@installed_notice_html_gz:=$(TARGET_OUT)/etc/NOTICE.html.gz$(installed_notice_html_gz):$(target_notice_file_html_gz)|$(ACP)$(copy-file-to-target)#ifwe'vebeenrunmymm,mmm,etc,don'treinstallthiseverytimeifeq($(ONE_SHOT_MAKEFILE),)<spanstyle="color:#FF0000;"><strong>ALL_DEFAULT_INSTALLED_MODULES+=$(installed_notice_html_gz)</strong></span>endif6.用來驗(yàn)證OTA更新的證書文件[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片<spanstyle="color:#FF0000;"><strong>ALL_DEFAULT_INSTALLED_MODULES+=$(TARGET_OUT_ETC)/security/otacerts.zip</strong></span>$(TARGET_OUT_ETC)/security/otacerts.zip:KEY_CERT_PAIR:=$(DEFAULT_KEY_CERT_PAIR)$(TARGET_OUT_ETC)/security/otacerts.zip:$(addsuffix.x509.pem,$(DEFAULT_KEY_CERT_PAIR))$(hide)rm-f$@$(hide)mkdir-p$(dir$@)$(hide)zip-qj$@$<.PHONY:otacertsotacerts:$(TARGET_OUT_ETC)/security/otacerts.zip二.boot.img從前面的分析可以知道,build/core/main.mk文件定義了boot.img鏡像文件的依賴規(guī)則,我們可以通過執(zhí)行makebootimage命令來執(zhí)行。其中,bootimage是一個(gè)偽目標(biāo),它依賴于INSTALLED_BOOTIMAGE_TARGET。INSTALLED_BOOTIMAGE_TARGET定義在build/core/Makefile文件中,如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片ifneq($(strip$(TARGET_NO_KERNEL)),true)##thebootimage,whichisacollectionofotherimages.INTERNAL_BOOTIMAGE_ARGS:=\$(addprefix--second,$(INSTALLED_2NDBOOTLOADER_TARGET))\--kernel$(INSTALLED_KERNEL_TARGET)\--ramdisk$(INSTALLED_RAMDISK_TARGET)INTERNAL_BOOTIMAGE_FILES:=$(filter-out--%,$(INTERNAL_BOOTIMAGE_ARGS))BOARD_KERNEL_CMDLINE:=$(strip$(BOARD_KERNEL_CMDLINE))ifdefBOARD_KERNEL_CMDLINEINTERNAL_BOOTIMAGE_ARGS+=--cmdline"$(BOARD_KERNEL_CMDLINE)"endifBOARD_KERNEL_BASE:=$(strip$(BOARD_KERNEL_BASE))ifdefBOARD_KERNEL_BASEINTERNAL_BOOTIMAGE_ARGS+=--base$(BOARD_KERNEL_BASE)endifBOARD_KERNEL_PAGESIZE:=$(strip$(BOARD_KERNEL_PAGESIZE))ifdefBOARD_KERNEL_PAGESIZEINTERNAL_BOOTIMAGE_ARGS+=size$(BOARD_KERNEL_PAGESIZE)endifINSTALLED_BOOTIMAGE_TARGET:=$(PRODUCT_OUT)/boot.imgifeq($(TARGET_BOOTIMAGE_USE_EXT2),true)tmp_dir_for_image:=$(callintermediates-dir-for,EXECUTABLES,boot_img)/bootimgINTERNAL_BOOTIMAGE_ARGS+=--tmpdir$(tmp_dir_for_image)INTERNAL_BOOTIMAGE_ARGS+=--genext2fs$(MKEXT2IMG)$(INSTALLED_BOOTIMAGE_TARGET):$(MKEXT2IMG)$(INTERNAL_BOOTIMAGE_FILES)$(callpretty,"Targetbootimage:$@")$(hide)$(MKEXT2BOOTIMG)$(INTERNAL_BOOTIMAGE_ARGS)--output$@else#TARGET_BOOTIMAGE_USE_EXT2!=true$(INSTALLED_BOOTIMAGE_TARGET):$(MKBOOTIMG)$(INTERNAL_BOOTIMAGE_FILES)$(callpretty,"Targetbootimage:$@")$(hide)$(MKBOOTIMG)$(INTERNAL_BOOTIMAGE_ARGS)$(BOARD_MKBOOTIMG_ARGS)--output$@$(hide)$(callassert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE),raw)endif#TARGET_BOOTIMAGE_USE_EXT2else#TARGET_NO_KERNEL#HACK:Thetop-leveltargetsdependonthebootimage.Notalltargets#canproduceabootimage,though,andemulatortargetsneedtheramdisk#instead.Fakeitoutbycallingtheramdisktheotimage.#TODO:maketheemulatorusebootimages,andmakemkbootimgaccept#kernel-lessinputs.INSTALLED_BOOTIMAGE_TARGET:=$(INSTALLED_RAMDISK_TARGET)endif在介紹boot.img之前,我們首先要介紹BootLoader。我們都知道,PC啟動(dòng)的時(shí)候,首先執(zhí)行的是在BIOS上的代碼,然后再由BIOS負(fù)責(zé)將Kernel加載起來執(zhí)行。在嵌入式世界里,BootLoader的作用就相當(dāng)于PC的BIOS。BootLoader的啟動(dòng)通常分為兩個(gè)階段。第一階段在固態(tài)存儲(chǔ)中(Flash)執(zhí)行,負(fù)責(zé)初始化硬件,例如設(shè)置CPU工作模式、時(shí)鐘頻率以及初始化內(nèi)存等,并且將第二階段拷貝到RAM去準(zhǔn)備執(zhí)行。第二階段就是在RAM中執(zhí)行,因此速度會(huì)更快,主要負(fù)責(zé)建立內(nèi)存映像,以及加載Kernel鏡像和Ramdisk鏡像。BootLoader的第二階段執(zhí)行完成后,就開始啟動(dòng)Kernel了。Kernel負(fù)責(zé)啟動(dòng)各個(gè)子系統(tǒng),例如CPU調(diào)度子系統(tǒng)和內(nèi)存管理子系統(tǒng)等等。Kernel啟動(dòng)完成之后,就會(huì)將Ramdisk鏡像安裝為根系統(tǒng),并且在其中找到一個(gè)init文件,將其啟動(dòng)為第一個(gè)進(jìn)程。init進(jìn)程啟動(dòng)就意味著系統(tǒng)進(jìn)入到用戶空間執(zhí)行了,這時(shí)候各種用戶空間運(yùn)行時(shí)以及守護(hù)進(jìn)程就會(huì)被加載起來。最終完成整個(gè)系統(tǒng)的啟動(dòng)過程。BootLoader的第一階段是固化在硬件中的,而boot.img的存在就是為BootLoader的第一階段提供第二階段、Kernel鏡像、Ramdisk鏡像,以及相應(yīng)的啟動(dòng)參數(shù)等等。也就是說,boot.img主要包含有BootLoader的第二階段、Kernel鏡像和Ramdisk鏡像。當(dāng)然,BootLoader的第二階段是可選的。當(dāng)不存在BootLoader的第二階段的時(shí)候,BootLoader的第一階段啟動(dòng)完成后,就直接進(jìn)入到kernel啟動(dòng)階段。boot.img鏡像的文件格式定義在system/core/mkbootimg/bootimg.h中,如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片/***++**|bootheader|1page**++**|kernel|npages**++**|ramdisk|mpages**++**|secondstage|opages**++****n=(kernel_size+page_size-1)/page_size**m=(ramdisk_size+page_size-1)/page_size**o=(second_size+page_size-1)/page_size****0.allentitiesarepage_sizealignedinflash**1.kernelandramdiskarerequired(size!=0)**2.secondisoptional(second_size==0->nosecond)**3.loadeachelement(kernel,ramdisk,second)at**thespecifiedphysicaladdress(kernel_addr,etc)**4.preparetagsattag_addr.kernel_args[]is**appendedtothekernelcommandlineinthetags.**5.r0=0,r1=MACHINE_TYPE,r2=tags_addr**6.ifsecond_size!=0:jumptosecond_addr**else:jumptokernel_addr*/它由4部分組成:bootheader、kernel、ramdisk和secondstate。每一個(gè)部分的大小都是以頁為單位的,其中,bootheader描述了kernel、ramdisk、sencondstage的加載地址、大小,以及kernel啟動(dòng)參數(shù)等等信息。bootheader的結(jié)構(gòu)同樣是定義在system/core/mkbootimg/bootimg.h中,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片structboot_img_hdr{unsignedcharmagic[BOOT_MAGIC_SIZE];unsignedkernel_size;/*sizeinbytes*/unsignedkernel_addr;/*physicalloadaddr*/unsignedramdisk_size;/*sizeinbytes*/unsignedramdisk_addr;/*physicalloadaddr*/unsignedsecond_size;/*sizeinbytes*/unsignedsecond_addr;/*physicalloadaddr*/unsignedtags_addr;/*physicaladdrforkerneltags*/unsignedpage_size;/*flashpagesizeweassume*/unsignedunused[2];/*futureexpansion:shouldbe0*/unsignedcharname[BOOT_NAME_SIZE];/*asciizproductname*/unsignedcharcmdline[BOOT_ARGS_SIZE];unsignedid[8];/*timestamp/checksum/sha1/etc*/};各個(gè)成員變量的含義如下所示:magic:魔數(shù),等于“ANDROID!”。kernel_size:Kernel大小,以字節(jié)為單位。kernel_addr:Kernel加載的物理地址。ramdisk_size:Ramdisk大小,以字節(jié)為單位。ramdisk_addr:Ramdisk加載的物理地址。second_size:BootLoader第二階段的大小,以字節(jié)為單位。second_addr:BootLoader第二階段加載的物理地址。tags_addr:Kernel啟動(dòng)之前,它所需要的啟動(dòng)參數(shù)都會(huì)填入到由tags_addr所描述的一個(gè)物理地址中去。unused:保留以后使用。page_size:頁大小。name:產(chǎn)品名稱。id:時(shí)間戳、校驗(yàn)碼等等。理解了BootLoader的啟動(dòng)過程,以及boot.img的文件結(jié)構(gòu)之后,就不難理解boot.img文件的生成過程了。首先檢查變量TARGET_NO_KERNEL的值是否等于true。如果等于true的話,那么就表示boot.img不包含有BootLoader第二階段和Kernel,即它等同于Ramdisk鏡像。如果不等于true的話,那么就通過INSTALLED_2NDBOOTLOADER_TARGET、INSTALLED_KERNEL_TARGET和INSTALLED_RAMDISK_TARGET獲得BootLoader第二階段、Kernel和Ramdisk對應(yīng)的鏡像文件,以及通過BOARD_KERNEL_CMDLINE、BOARD_KERNEL_BASE和BOARD_KERNEL_PAGESIZE獲得Kernel啟動(dòng)命令行參數(shù)、內(nèi)核基地址和頁大小等參數(shù)。最后根據(jù)TARGET_BOOTIMAGE_USE_EXT2的值來決定是使用genext2fs還是mkbootimg工具來生成boot.img。三.ramdisk.img從前面的分析可以知道,build/core/main.mk文件定義了ramdisk.img鏡像文件的依賴規(guī)則,我們可以通過執(zhí)行makeramdisk命令來執(zhí)行。其中,ramdisk是一個(gè)偽目標(biāo),它依賴于INSTALLED_RAMDISK_TARGET。INSTALLED_RAMDISK_TARGET定義在build/core/Makefile文件中,如下所示:[plain]viewplaincopy在CODE上查看代碼片派生到我的代碼片INTERNAL_RAMDISK_FILES:=$(filter$(TARGET_ROOT_OUT)/%,\$(ALL_PREBUILT)\$(ALL_COPIED_HEADERS)\$(ALL_GENERATED_SOURCES)\$(ALL_DEFAULT_INSTALLED_MODULES))BUILT_RAMDISK_TARGET:=$(PRODUCT_OUT)/ramdisk.img#Wejustbuildthisd

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論