• Android x86镜像分析


    这几天可能要接个Android的项目,基于x86平台。所以先了解一下android的安装过程。在其官方网站上下载了Android的img,先面就解压出来看看吧,需要说明的是以下的操作都是在root用户下进行的。

    mkdir android
    mount android-x86-4.3-20130725.iso  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的这篇博文

    http://blog.csdn.net/liujixin8/article/details/4029887
    

    接下来看一下install.img这个文件,我们用file命令看一下这个文件属性

    android# file install.img 
    install.img: gzip compressed data, from Unix, last modified: Fri Jul 26 02:05:58 2013, max compression
    

    可以看到这个文件是一个gzip的文件,所以我们可以解压出来看看,命令如下:

    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
    

    可以看出通过这个文件的解压多出了以下目录:

    bin  grub   lib  sbin  scripts

     不过通过以上的目录可以看出,基于x86结构的android是用grub引导的。接下来看一下他的启动流程,在看启动流程之前我们先看一下isolinux.cfg这个文件,这个文件的具体作用在上面的内容中已经说过,在此不在赘述,文件内容如下:

    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 "
    Type 'exit' to continue booting...
    "
            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 "
    Use Alt-F1/F2/F3 to switch between virtual consoles"
            echo -e "Type 'exit' to enter Android...
    "
    
            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 这个函数  

      

  • 相关阅读:
    Handler详细说明系列(六)——View的post()详解
    2013年6月17日星期一
    2013年6月16日星期日
    线程管理四种方法
    java 线程 ProducerAndConsumer
    POJ 2948 DP
    Java的递归算法
    开机黑屏 仅仅显示鼠标 电脑黑屏 仅仅有鼠标 移动 [已成功解决]
    网络安全审查制度即将推出 手机App安全加密成必定趋势
    递归算法浅谈
  • 原文地址:https://www.cnblogs.com/jjxxjnzy/p/3368068.html
Copyright © 2020-2023  润新知