這幾天可能要接個Android的項目,基於x86平臺。因此先了解一下android的安裝過程。在其官方網站上下載了Android的img,先面就解壓出來看看吧,須要說明的是如下的操做都是在root用戶下進行的。linux
mkdir android mount android-x86-4.3-20130725.iso android
經過以上的命令能夠把咱們下載的android鏡像掛載到android目錄下,下面咱們能夠看一下他的目錄結構:android
├── initrd.img ├── install.img ├── isolinux │ ├── android-x86.png │ ├── boot.cat │ ├── isolinux.bin │ ├── isolinux.cfg │ ├── TRANS.TBL │ └── vesamenu.c32 ├── kernel ├── ramdisk.img ├── system.sfs └── TRANS.TBL
對以上文件詳細的瞭解能夠參考csdn的這篇博文shell
http://blog.csdn.net/liujixin8/article/details/4029887
接下來看一下install.img這個文件,咱們用file命令看一下這個文件屬性app
android# file install.img install.img: gzip compressed data, from Unix, last modified: Fri Jul 26 02:05:58 2013, max compression
能夠看到這個文件是一個gzip的文件,因此咱們能夠解壓出來看看,命令以下:ide
mkdir install cp /tmp/android/install.img /tmp/install mv install.img install.img.gz gunzip install.img.gz cpio -i -F install.img
這個時候咱們看下install這個目錄的結構:函數
install# ls bin grub install.img lib sbin scripts
能夠看出經過這個文件的解壓多出瞭如下目錄:oop
bin grub lib sbin scripts
不過經過以上的目錄能夠看出,基於x86結構的android是用grub引導的。接下來看一下他的啓動流程,在看啓動流程以前咱們先看一下isolinux.cfg這個文件,這個文件的具體做用在上面的內容中已經說過,在此不在贅述,文件內容以下:post
default vesamenu.c32 timeout 600 menu background android-x86.png menu title Android-x86 Live & Installation CD 4.3-test menu color border 0 #ffffffff #00000000 menu color sel 7 #ffffff00 #ff000000 menu color title 0 #ffffffff #00000000 menu color tabmsg 0 #ffffffff #00000000 menu color unsel 0 #ffffffff #00000000 menu color hotsel 0 #ffffff00 #ff000000 menu color hotkey 7 #ffffff00 #00000000 label livem menu label Live CD - ^Run Android-x86 without installation kernel /kernel append initrd=/initrd.img root=/dev/ram0 androidboot.hardware=android_x86 video=-16 quiet SRC= DATA= label vesa menu label Live CD - ^VESA mode kernel /kernel append initrd=/initrd.img root=/dev/ram0 androidboot.hardware=android_x86 video=-16 quiet nomodeset vga=788 SRC= DATA= label debug menu label Live CD - ^Debug mode kernel /kernel append initrd=/initrd.img root=/dev/ram0 androidboot.hardware=android_x86 video=-16 vga=788 DEBUG=2 SRC= DATA= label install menu label Installation - ^Install Android-x86 to harddisk kernel /kernel append initrd=/initrd.img root=/dev/ram0 androidboot.hardware=android_x86 video=-16 INSTALL=1 DEBUG=
咱們主要看下面的label這幾個選項。一共有四個label選項,前面的兩個不太熟悉,不過在這裏不影響咱們。第三個爲debug模式,第四個爲install模式,也就是android的安裝,從加在這裏的內核參數能夠看出,系統啓動的是initrd.img裏的內容,那接下來咱們就分析一下initrd.img 這個文件。咱們用file命令看一下這個文件的屬性就能夠知道他和上文說的install.img的文件屬性是同樣的,咱們用一樣的方法把他解壓出來,內容以下:學習
initrd# ls
android bin hd init lib mnt proc sbin scripts sfs sys tmp
以上就是把initrd.img文件解壓出來的內容,系統的啓動就是從這個地方開始,熟悉linux的朋友看到這個就知道是從那個文件開始執行了。接下來咱們看一下init這個文件,這個文件是一個文本文件,能夠看一下它的文件屬性網站
initrd# file init init: a /bin/busybox sh script, ASCII text executable
下面能夠看一下這個腳本的內容:
echo -n Detecting Android-x86... mount -t tmpfs tmpfs /android cd /android while :; do for device in ${ROOT:-/dev/sr* /dev/[hs]d[a-z]*}; do check_root $device && break 2 mountpoint -q /mnt && umount /mnt done sleep 1 echo -n . done
這個是腳本的初始函數,至關於c語言的mian函數,首先看到的地一個mount命令掛載了tmpfs文件系統,對這個不是很熟悉,等有時間了學習了一下這個在把這個補上。看看接下來while循環,在這一段內容裏重點看一下 check_root,這個是定義的一個函數,這個函數定義以下:
try_mount() { RW=$1; shift if [ "${ROOT#*:/}" != "$ROOT" ]; then # for NFS roots, use nolock to avoid dependency to portmapper RW="nolock,$RW" fi # FIXME: any way to mount ntfs gracefully? mount -o $RW $@ || mount.ntfs-3g -o rw,force $@ } check_root() { try_mount ro $1 /mnt && [ -e /mnt/$SRC/ramdisk.img ] [ $? -ne 0 ] && return 1 zcat /mnt/$SRC/ramdisk.img | cpio -id > /dev/null if [ -e /mnt/$SRC/system.sfs ]; then mount -o loop /mnt/$SRC/system.sfs /sfs mount -o loop /sfs/system.img system elif [ -e /mnt/$SRC/system.img ]; then mount -o loop /mnt/$SRC/system.img system elif [ -d /mnt/$SRC/system ]; then remount_rw mount --bind /mnt/$SRC/system system else rm -rf * return 1 fi mkdir cache mnt mnt/sdcard mount -t tmpfs tmpfs cache echo " found at $1" }
這個函數的做用主要是掛載ramdisk.img和system.sfs,這兩個文件能夠看看咱們最初始解壓的文件。這裏須要說明的是system.sfs這個文件解壓出來是system.img。system.img裏包含的就是具體的系統文件了。這個到後面會講到。
ln -s mnt/$SRC /src
ln -s android/system /
ln -s ../system/lib/modules /lib
ln -s ../system/lib/firmware /lib
if [ -n "$INSTALL" ]; then
cd /
zcat /src/install.img | cpio -iud > /dev/null
fi
if [ -x system/bin/ln -a \( -n "$DEBUG" -o -n "$BUSYBOX" \) ]; then
mv /bin /lib .
system/bin/ln -s android/lib /lib
system/bin/ln -s android/bin /bin
sed -i 's|\(PATH *\)\(/sbin\)|\1/bin:\2|' init.rc
mv /sbin/* sbin
rmdir /sbin
ln -s android/sbin /
fi
# ensure keyboard driver is loaded
[ -n "$INSTALL" -o -n "$DEBUG" ] && modprobe atkbd
if [ 0$DEBUG -gt 0 ]; then
echo -e "\nType 'exit' to continue booting...\n"
debug_shell debug-found
fi
# load scripts
for s in `ls /scripts/* /src/scripts/*`; do
test -e "$s" && source $s
done
以上作的就是一些初始化的工做,而且根據不一樣啓動參數,所作的操做也略有不一樣。能夠看看上面標出的紅色部分,此處的主要做用是若是判斷出系統啓動時所帶的參數爲install,則進入安裝模式。接着往下看
[ "$AUTO" != "1" ] && detect_hardware && FOUND=1 [ -n "$INSTALL" ] && do_install load_modules mount_data mount_sdcard setup_tslib setup_dpi post_detect find_network_dev_name if [ 0$DEBUG -gt 1 ]; then echo -e "\nUse Alt-F1/F2/F3 to switch between virtual consoles" echo -e "Type 'exit' to enter Android...\n" debug_shell debug-late fi [ -n "$DEBUG" ] && SWITCH=${SWITCH:-chroot} # We must disable mdev before switching to Android # since it conflicts with Android's init echo > /proc/sys/kernel/hotplug exec ${SWITCH:-switch_root} /android /init # avoid kernel panic while :; do echo echo ' Android-x86 console shell. Use only in emergencies.' echo debug_shell fatal-err done
能夠看出上面的代碼用紅色標註了兩處,其中第一處是用來判斷是不是install模式,在這個地方須要注意下,若是是正常的啓動此處是不會執行到的,若是是安裝模式則會調用安裝腳本,這個安裝腳本是放在install.img 這個文件裏。這個文件的目錄在上文我已經列過了。具體的看看do_install這個函數,這個函數是定義在install.img 解壓出文件的scripts/1-install這個文件當中,在這個腳本中爲何能調用這個函數呢,注意這一句:
# load scripts
for s in `ls /scripts/* /src/scripts/*`; do
test -e "$s" && source $s
done
這一段代碼遍歷了/scripts/和 /src/scripts/這兩個目錄下的腳本文件。注意後面的source $s,正是有了這一句,咱們才能夠在在init腳本里調用1-install這個腳本的函數。這個install.sh就是實現了咱們的安裝功能。咱們將在下一篇中分析do_install 這個函數