android build 過程 (ramdisk.img、sytem.img、userdata.img)和 啟動過程簡單分析

首先下載下android源碼並編譯,網上的資料特別多,可以參考一下這個:
/kf/201202/118141.html

按照上面網址的步驟,將android內核編譯成功,如果不出意外的話,在out/target/product/generic目錄下會生成三個文件,分別是ramdisk.img、sytem.img、userdata.img。這三個文件到底有什麼用呢?下面開始分析一下。
 
首先在linux終端下使用命令file ramdisk.img,打印出如下字符ramdisk.img: gzip compressed data, from Unix,可以看出,它是一個gzip壓縮的格式,下面對其進行解壓,使用fedora自帶的工具進行解壓,或者使用gunzip進行解壓(可能需要將擴展名改為.gz),可以看到解壓出一個新的ramdisk.img,這個ramdisk.img是使用cpio壓縮的,可以使用cpio命令對其進行解壓,cpio –i –F ramdisk.img,解壓後可以看到生成瞭一些文件夾和文件。看到這些文件就會明白,它和root目錄下的內容完全一樣。說明瞭ramdisk.img其實是對root目錄的打包和壓縮。
 
下面分析system.img的來源。在build/core/Makefile裡的629行,可以看到這麼一段文字
 
# The installed image, which may be optimized or unoptimized.
 
#
 
INSTALLED_SYSTEMIMAGE := $(PRODUCT_OUT)/system.img
 
從這裡可以看出,系統應該會在$(PRODUCT_OUT)目錄下生成system.img
 
再繼續往下看,在662行有一個copy-file-to-target,這實現瞭將system.img從一個中間目錄復制到/generic目錄。
 
BUILD_SYSTEM的定義在636行。
 
這裡的system.img不是/generic目錄下面我們看到的那個system.img,而是另一個中間目錄下的,但是是同一個文件。一開始看到的復制就是把out /target/product/generic/obj/PACKAGING/systemimage_unopt_intermediates目錄下面的system.img復制到/generic目錄下。
 
現在,知道瞭system.img的來歷,然後要分析它是一個什麼東西,裡面包含什麼??
 
Makefile line624
 
$(BUILT_SYSTEMIMAGE_UNOPT): $(INTERNAL_SYSTEMIMAGE_FILES) $(INTERNAL_MKUSERFS)
 
$(call build-systemimage-target,$@)
 
這裡調用瞭build-systemimg-target Makefile line605
 
ifeq ($(TARGET_USERIMAGES_USE_EXT2),true)
 
## generate an ext2 image
 
# $(1): output file
 
define build-systemimage-target
 
@echo "Target system fs image: $(1)"
 
$(call build-userimage-ext2-target,$(TARGET_OUT),$(1),system,)
 
endef
 
else # TARGET_USERIMAGES_USE_EXT2 != true
 
## generate a yaffs2 image
 
# $(1): output file
 
define build-systemimage-target
 
@echo "Target system fs image: $(1)"
 
@mkdir -p $(dir $(1))
 
*$(hide) $(MKYAFFS2) -f $(TARGET_OUT) $(1)*
 
endef
 
endif # TARGET_USERIMAGES_USE_EXT2
 
找不到TARGET_USERIMAGES_USE_EXT2的定義!!!不過從上面的分析可以推斷出應該是yaffs2文件系統。
 
其中MKYAFFS2:(core/config.mk line161)
 
MKYAFFS2 := $(HOST_OUT_EXECUTABLES)/mkyaffs2image$(HOST_EXECUTABLE_SUFFIX)
 
定義MKYAFFS2是目錄/media/disk/mydroid /out/host/linux-x86/bin下的一個可執行文件mkyaffs2image,運行這個程序可得到如下信息:
 
lzj@lzj-laptop:/media/disk/mydroid/out/host/linux-x86/bin$ ./mkyaffs2image
 
mkyaffs2image: image building tool for YAFFS2 built Nov 13 2009
 
usage: mkyaffs2image [-f] dir image_file [convert]
 
-f fix file stat (mods, user, group) for device
 
dir the directory tree to be converted
 
image_file the output file to hold the image
 
'convert' produce a big-endian image from a little-endian machine
 
得知這個程序可以生成yaffs2的文件系統映像。並且也清楚瞭上面*$(hide) $(MKYAFFS2) -f $(TARGET_OUT) $(1)*的功能,把TARGET_OUT目錄轉變成yaffs2格式並輸出成/media/disk/mydroid/out/target /product/generic/obj/PACKAGING/systemimage_unopt_intermediates /system.img(也就是我們最終在/generic目錄下看到的那個system.img)。
 
到現在已經差不多知道system.img的產生過程,要弄清楚system.img裡面的內容,就要分析TARGET_OUT目錄的內容瞭。 (想用mount把system.img掛載到linux下面看看裡面什麼東西,卻不支持yaffs和yaffs2文件系統!!!)
 
下一步:分析TARGET_OUT 在build/core/envsetup.sh文件(line205)中找到瞭TARGET_OUT的定義:
 
TARGET_OUT := $(PRODUCT_OUT)/system
 
也就是/media/disk/mydroid/out/target /product/generic目錄下的system目錄。
 
lzj@lzj-laptop:/media/disk/mydroid/out/target/product/generic/system$ tree -L 1
 
.
 
|– app
 
|– bin
 
|– build.prop
 
|– etc
 
|– fonts
 
|– framework
 
|– lib
 
|– usr
 
`– xbin
 
現在一切都明白瞭,我們最終看到的system.img文件是該目錄下的system目錄的一個映像,類似於linux的根文件系統的映像,放著android的應用程序,配置文件,字體等。
 
Userdata.img來來自於data目錄,默認裡面是沒有文件的。
 
Android啟動過程
 
Android在啟動的時候,會由UBOOT傳入一個init參數,這個init參數指定瞭開機的時候第一個運行的程序,默認就是init程序,這個程序在ramdisk.img中。可以分析一下它的代碼,看看在其中到底做瞭一些什麼樣的初始化任務,它的源文件在system/core/init/init.c中。
 
它會調用到init.rc初始化文件,這個文件在out/target/product/generic/root下,我們在啟動以後,會發現根目錄是隻讀屬性的,而且sdcard的owner是system,就是在這個文件中做瞭些手腳,可以將它改過來,實現根目錄的可讀寫。
 
通過分析這幾個文件,還可以發現,android啟動時首先加載ramdisk.img鏡像,並掛載到/目錄下,並進行瞭一系列的初始化動作,包括創建各種需要的目錄,初始化console,開啟服務等。System.img是在init.rc中指定一些腳本命令,通過init.c進行解析並掛載到根目錄下的/system目錄下的

摘自 andy_android的專欄

發佈留言