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 这个函数  

相关文章
相关标签/搜索