Android x86鏡像分析

這幾天可能要接個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 這個函數  

相關文章
相關標籤/搜索