Android x86镜像分析 您所在的位置:网站首页 AndroidX86镜像下载 Android x86镜像分析

Android x86镜像分析

2023-09-26 13:21| 来源: 网络整理| 查看: 265

      这几天学习Android,基于x86平台。先了解一下android的安装过程。在其官方网站上下载了Android的iSO,就解压出来看看,需要说明的是以下的操作都是在root用户下进行的。以下是学习过程中,从网上找到的文件,这篇文章的主要参考链接为:https://www.cnblogs.com/jjxxjnzy/archive/2013/10/14/3368068.html,感谢!

1

2

mkdir android

mount android-x86-4.3-20130725.iso  android

通过以上的命令可以把我们下载的android镜像挂载到android目录下,看一目录结构:

1

2

3

4

5

6

7

8

9

10

11

12

13

├── 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的这篇博文

1

https://blog.csdn.net/ldq_sd/article/details/104196923

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

1

2

android# file install.img

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

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

1

2

3

4

5

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这个目录的结构:

1

2

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这个文件,这个文件是一个文本文件,可以看一下它的文件属性

1

2

initrd# file init

init: a /bin/busybox sh script, ASCII text executable

下面可以看一下这个脚本的内容:

1

2

3

4

5

6

7

8

9

10

11

12

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,这个是定义的一个函数,这个函数定义如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

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里包含的就是具体的系统文件了。这个到后面会讲到。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

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

下图为system.img文件内容:

 

app

主要存放的是常规下载的应用程序,可以看到都是以APK格式结尾的文件,在这个文件夹下的程序为系统默认的组件,自己安装的软件将不会出现在这里,而是\data\文件夹中。

应用举例:

\AlarmClock.apk 闹钟 \Browser.apk 浏览器 \Bugreport.apk 错误报告 \ Calculator.apk 计算器

bin

目录下的文件都是系统的本地程序,是binary二进制的程序,主要是Linux系统自带的组件: \app_process 系统进程 \dalvikvm Dalvik虚拟机宿主 \dbus-daemon 系统BUS总线监控 \debuggerd 调试器 \debug_tool 调试工具 \dexopt DEX选项 \dhcpcd DHCP服务器

etc

配置文件,如:

\bluetooth 蓝牙设备配置文件

fonts

字体,中文字库,unicode字库等

\fonts\DroidSans-Bold.ttf

\fonts\DroidSansFallback.ttf

framework

平台框架,如:

\am.jar \am.odex \android.awt.jar AWT库 \android.awt.odex

lib

系统运行库,如:

\libaes.so  \libagl.so \libandroid_runtime.so Android运行时库 \libandroid_servers.so 系统服务组件 \liba io.so 音频处理 \liba ioeq.so EQ均衡器 \liba ioflinger.so 音频过滤器 \libbltooth.so 蓝牙组件

media

各种铃声,系统提示音等

usr

用户文件夹,包含共享、键盘布局、时间区域文件等。

\keychars \keylayout \share \srec

 在文件系统中,android4层架构显现的很明显:app应用,framework框架,lib运行库。android系统4层架构(应用层,框架层,运行库层,内核层)之间,应用层通过框架对使用到库进行调用、内核负责内存管理进程调度等。通过在不同层上的裁剪可以实现部分功能的移出。例如:应用层上移出APK,相应应用无法使用;运行库层移出运行所需的库文件,所有调用该库文件均报错不能执行;在内核层上,通过config编译内核也可达到同样目的。 

以上做的就是一些初始化的工作,并且根据不同启动参数,所做的操作也略有不同。可以看看上面标出的红色部分,此处的主要作用是如果判断出系统启动时所带的参数为install,则进入安装模式。接着往下看

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

[ "$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这个文件当中,在这个脚本中为什么能调用这个函数呢,注意这一句:

1

2

3

4

# 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就是实现了我们的安装功能。

install.img文件中,我们先看一下这个包里有那些文件,在这里我以树的形式列出包含有那些文件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

install# tree

.

├── bin

│   ├── cfdisk

│   ├── dialog

│   └── pv

├── grub

│   ├── android-x86.xpm.gz

│   ├── e2fs_stage1_5

│   ├── fat_stage1_5

│   ├── iso9660_stage1_5

│   ├── ntfs_stage1_5

│   ├── stage1

│   ├── stage2

│   └── stage2_eltorito

├── lib

│   ├── libncursesw.so.5

│   ├── libntfs.so.10

│   ├── libtinfo.so.5

│   ├── libuuid.so.1

│   └── terminfo

│       └── l

│           └── linux

├── sbin

│   ├── grub

│   └── mkntfs

└── scripts

    └── 1-install

这个函数包含在1-install这个文件里,可以看一下这个函数的实现:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

do_install()

{

        until install_hd; do

                if [ $retval -eq 255 ]; then

                        dialog --title ' Error! ' --yes-label Retry --no-label Reboot \

                                --yesno '\nInstallation failed! Please check if you have enough free disk space to install Android-x

                        [ $? -eq 1 ] && rebooting

                fi

        done

 

        [ -n "$VESA" ] || runit="Run Android-x86"

        dialog --clear --title ' Congratulations! ' \

                --menu "\n Android-x86 is installed successfully.\n " 11 51 13 \

                "$runit" "" "Reboot" "" 2> $tempfile

        case "`cat $tempfile`" in

                Run*)

                        cd /android

                        umount system

                        if mountpoint -q /sfs; then

                                umount /sfs

                                mount -o loop /hd/$asrc/system.sfs /sfs

                                mount -o loop /sfs/system.img system

                        else

                                mount -o loop /hd/$asrc/system.img system

                        fi

                        if [ -d /hd/$asrc/data ]; then

                                mount --bind /hd/$asrc/data data

                        elif [ -e /hd/$asrc/data.img ]; then

                                mount -o loop /hd/$asrc/data.img data

                        fi

                        ;;

                *)

                        rebooting

                        ;;

        esac

在这个函数中使用了until这样一个关键字,这个是shell脚本的语句,具体的作用大家google吧,接下来调用了install_hd这个函数,这个函数也是在这个文件里定义的,具体实现如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

install_hd()

{

        select_dev || rebooting

        retval=1

        case "$choice" in

                [sh]d*)

                        install_to $choice

                        retval=$?

                        ;;

                Create*)

                        cfdisk

                        ;;

                Detect*)

                        dialog --title " Detecting... " --nocancel --pause "" 8 41 1

                        ;;

        esac

        return $retval

}

在这个函数里可以看到调用了一个select_dev的函数,这个函数也定义在该文件中,定义如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

select_dev()

{

        fdisk -l | grep ^/dev | cut -b6-12,55- | awk '{

                if (!match($2, "Extended")) {

                        printf("\"%-28s", $0)

                        system("echo -n `cat /sys/block/*/"$1"/../device/model`")

                        printf("\" \"\"\n")

                }

        } END {

                printf("\"Create/Modify partitions\" \"\"\n\"Detect devices\" \"\"")

        }' > $menufile

        choose "Choose Partition" "Please select a partition to install Android-x86:"

        return $retval

}

在上面的函数中还调用了另外一个函数,choose,该函数定义如下:

1

2

3

4

5

6

7

8

choose()

{

        dialog --clear --title " $1 " \

                --menu "$2" 20 71 13 --file $menufile 2> $tempfile

 

        retval=$?

        choice=`cat $tempfile`

}

在这个函数中需要注意的是最后一个choice值,这个值在后面会用到。接下来我们回到install_hd,这个函数,继续往下执行:

1

2

3

4

5

6

7

8

9

10

11

12

case "$choice" in

        [sh]d*)

                install_to $choice

                retval=$?

                ;;

        Create*)

                cfdisk

                ;;

        Detect*)

                dialog --title " Detecting... " --nocancel --pause "" 8 41 1

                ;;

esac

因为此处我们主要讲解安装,所以其他的来那个选项我们暂时不分析了,等后面在补上。我们看一下上述表红色的部分。其中retval=$?用来取得调用select_dev函数的返回值。接下来我们看一下install_to这个函数,这个函数也是定义在这个文件里,由于这个函数内容比较多,我们一段一段分析:

1

2

3

4

5

6

7

8

9

cd /

mountpoint -q /hd && umount /hd

while [ 1 ]; do

        format_fs $1

        try_mount rw /dev/$1 /hd && break

        dialog --clear --title " Error " --defaultno --yesno \

                "\n Cannot mount /dev/$1\n Do you want to format it?" 8 37

        [ $? -ne 0 ] && return 255

done

这一段代码的主要功能是完成对磁盘的分区与格式化,具体的调用是在format_fs中实现,该函数实现如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

format_fs()

{

        local cmd

        echo -e '"Do not format" ""\next3 ""\next2 ""\nntfs ""\nfat32 ""' > $menufile

        choose "Choose filesystem" "Please select a filesystem to format $1:"

        case "$choice" in

                ext3)

                        cmd="mke2fs -jL"

                        ;;

                ext2)

                        cmd="mke2fs -L"

                        ;;

                ntfs)

                        cmd="mkntfs -fL"

                        ;;

                fat32)

                        cmd="newfs_msdos -L"

                        ;;

                *)

                        ;;

        esac

        if [ -n "$cmd" ]; then

                dialog --title " Confirm " --no-label Skip --yesno \

                        "\n You chose to format $1 to $choice.\n All data in that partition will LOSE.\n\n Are you sure to format the partition $1?" 10

 51

                [ $? -ne 0 ] && return 1

                $cmd Android-x86 /dev/$1 | awk '{

                        # FIXME: very imprecise progress

                        if (match($0, "done"))

                                printf("%d\n", i+=33)

                }' | progress_bar "Formatting" "Formatting partition $1..."

        fi

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

fs=`cat /proc/mounts | grep /dev/$1 | awk '{ print $3 }'`

 

asrc=android-$VER

dialog --title " Confirm " --no-label Skip --defaultno --yesno \

        "\n Do you want to install boot loader GRUB?" 7 47

if [ $? -eq 0 ]; then

        cp -af /grub /hd

        d=0

        while [ 1 ]; do

                h=`echo $d | awk '{ printf("%c", $1+97) }'`

                [ -d /sys/block/[sh]d$h/$1 ] && break

                d=$(($d+1))

        done

        p=$((`echo $1 | cut -b4-`-1))

        create_menulst $p

        create_winitem $1 $d

        rm -f /hd/boot/grub/stage1

        echo "setup (hd$d) (hd$d,$p)" | grub > /dev/tty5

        [ $? -ne 0 ] && return 255

fi

 

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有