安卓系统中各镜像介绍
背景
对于安卓开发⽽⾔,了解各镜像的意义、内容以及如何制作,有极⼤的意义。
注意,ROM中的5个镜像⽂件的扩展名都是img,但其格式却不同,也就是说不能使⽤同⼀种⽅法对其进⾏格式解析。
系统镜像(System.img)
系统镜像⽤于存储Android系统的核⼼⽂件,将其解压出来,就是设备中/system⽬录,⾥⾯包含了Android系统主要的⽬录和⽂件。⼀般这些⽂件是不允许修改的。
系统镜像对应的⽂件名⼀般叫system.img。
当然,系统镜像的⽂件可以任意命名,之所以叫system.img是为了与⽣成镜像⽂件之前的system⽬录保持⼀致,这样⽐较容易与其他类型的镜像⽂件区分。
system.img可以添加:
Android系统应⽤
更多的library
为了搞清楚system.img镜像中的内容,可以将其解压:
旧版的镜像是yaffs格式的(通过mkyaffs2image⼯具制作的),可以使⽤unyafss命令对其解压。
unyaffs system.img
如果对编译Android源代码⽣成的system.img⽂件执⾏上⾯的命令,可以完美的将system.img⽂件还原成system⽬录,会从system⽬录中看到相应的⼦⽬录,例如,/system/app、/system/lib等,实际上,system.img⽂件就是out/target/product/generic/system中的⽂件压缩⽣成的。
另外,⾼版本Android的system.img通常是ext4格式的⽂件系统镜像(通过make_ext4⼯具制作),可以使⽤simg2img⼯具进⾏转换后挂载。
由于system.img是压缩格式,所以并不能直接使⽤mount命令挂载。在编译Android 源代码后会在Android源代码⽬录/out/host/linux-x86/bin⽬录⽣成⼀个simg2img命令⾏⼯具
建议将该⽬录加到PATH环境变量中,因为当中的各种命令⾏⼯具会被经常使⽤。
simg2img可以通过如下的命令将system.img转化为普通的Linux镜像⽂件(system.img.raw);
# 转换
$ simg2img system.img system.img.raw
# 查看镜像格式
$ file system.img
system.img: Android sparse image, version: 1.0, Total of 229673 4096-byte output blocks in 22 input chunks.
# 查看镜像格式
$ file system.img.raw
system.img.raw: Linux rev 1.0 ext2 filesystem data, UUID=efee3fdf-d4f1-5e88-9f69-57632c5d8db4 (extents) (large files) (huge files)
此后,我们就可以进⾏挂载了:
## 挂载到 ~/debug/system
mkdir /mnt/system -p
sudo mount system.img.raw /mnt/system
执⾏⽂上⾯的命令后,进到挂载⽬录,所有的⽬录都是可读写的。
⽂件列表如下:
⽬录意义
app存放⼀般的apk⽂件。
bin存放⼀些Linux的⼯具,但是⼤部分都是toolbox的链接.
etc存放系统的配置⽂件。
fonts存放系统的字体⽂件。
framework存放系统平台所有jar包和资源⽂件包。
priv-app android4.4开始新增加的⽬录,存放系统核⼼的apk⽂件。
⽬录意义
tts存放系统的语⾔合成⽂件。
usr存放各种键盘布局,时间区域⽂件。
vendor存放⼀些第三⽅⼚商的配置⽂件、firmware以及动态库。
xbin存放系统管理⼯具,这个⽂件夹的作⽤相当于标准Linux⽂件系统中的sbin.
build.prop⽂件系统属性的定义⽂件。
将system.img.raw挂载出来后,该⽬录中的内容实际上与system.img中的内容完全⼀样,现在可以任意修改⽬录中的内容,再进⾏打包以达到更新system.img的⽬的。
例如,添加或替换⽬录中的apk⽂件,或更换开机动画。
在修改完系统镜像后,还需要使⽤make_extfs命令将挂载⽬录重新⽣成system.img⽂件(EXT4⽂件系统)。
我们可以在Linux终端执⾏如下的命令⽣成system.img⽂件。
make_ext4fs -s -l 1024M -a system system.img /mnt/system
在执⾏make_ext4fs 命令使⽤了3个命令⾏参数,这些参数的含义如下:
-s:⽣成Spare格式的镜像。这种格式的镜像⽂件的尺⼨会更⼩,但⽆法直接使⽤mount命令挂载。要想挂载Spare格式的镜像⽂件,需要⾸先使⽤simg2img命令按着前⾯描述的⽅式进⾏转换。如果不加-s参数,⽣成的system.img⽂件是可以直接通过mount挂载。不过不管是不是Spare格式的系统镜像⽂件,Nexus 7都可以使⽤(其他的Android设备应该也可以),但建议⽣成Spare格式的镜像⽂件,因为这样的镜像⽂件尺⼨更⼩。
-l : 镜像的尺⼨。该参数指定的值并不是⽣成镜像⽂件(r如system.img)的实际尺⼨,⽽是⽂件系统的尺⼨。这有些类似在Windows中建⽴的⼼得逻辑分区,⽽该参数指定的值就是逻辑分区的尺⼨,⽣成的镜像⽂件的尺⼨不能⼤于⽂件系统的尺⼨。例如官⽅提供的⽤于Nexus 7的system.img⽂件(Spare格式的镜像⽂件)的尺⼨⼤⼩越是480M,
-a: 指定挂载点,这⾥是system.
重新⽣成经过修改的system.img⽂件后,⾸先让设备进⼊Bootloader模式,然后执⾏下⾯的命令即可
刷机:
fastboot flash system system.img
⽤户数据镜像(userdata.img)
⽤户镜像⽤来存储与⽤户相关的数据,⼀般对应的⽂件名是userdata.img(也可以是任何⽂件名,为了⽅便,我们将userdata称为⽤户镜像⽂件)。
这些数据⼤多都是有⽤户在使⽤Android设备的过程中产⽣的,例如,通过Google play安装的第三⽅APK程序,⽤户的配置⽂件等。当然,在制作ROM时,也可以将部分数据放到userdata.img中。
例如,如果允许⽤户使⽤普通的⽅法卸载ROM内置的应⽤,就可以将APK⽂件放到userdata.img⽂件中 (这⾥是普通的应⽤程
序,⽽system.img放⼊的是系统应⽤程序)
userdata.img有如下两个功能:
封装与⽤户相关的⽂件(如果是APK程序,还允许卸载这些程序),并连同ROM⼀起发布,或单独刷userdata.img⽂件。
规定Android设备存储空间的⼤⼩。
在Android设备中可供⽤户操作的存储区域通常有如下:
RAM :RAM就是传统意义上的内存,与PC的内存是⼀个概念,只有在通电时才能存储数据,断点后所有数据将⾃动消失,所有要运⾏的程序都需要调⽤RAM。
存储空间:现在所有的Android设备都有都带有⼀定⼤⼩的内部存储器(嵌⼊到芯⽚上,类似于内部嵌⼊⼀个SD卡),⽤于存储⼀些随机器发布的系统和应⽤程序。⽽PC除了RAM,就是硬盘了。
外部存储器(通常是SD卡):有的Android系统加⼊了OTG(On-The-Go)⽀持,所以通过OTG连接的U盘、移动硬盘也应属于外部存储器,有⼀些Android设备(如Nexus 7) 不⽀持插⼊SD卡。
Android系统通过Linux ⽂件系统将可⽤的存储空间划分成不同区域,userdata.img就属于userdata分区,该分区就是前⾯所说的存储空间。⽽剩余的内存空间就会将其作为外部存储器。
如果Android设备不⽀持外部存储器,userdata.img就不能太⼤,否则系统将⽆法利⽤剩余的空间映射SD卡(/sdcard,⽬录)。
学习userdata.img的第⼀步就是解剖他。⽅法与解剖system类似。
⾸先需要使⽤simg2img命令将userdata.img⽂件还原成⾮压缩格式的镜像⽂件,这样可以直接使⽤mount命令将userdata.img⽂件挂载到某个⽬录,进⽽查看userdata.img中的内容。
# ⽣成还原后的userdata.img.raw⽂件
simg2img userdata.img userdata.img.raw
mkdir -p /mnt/rom/userdata
mount userdata.img.raw /mnt/rom/userdata
如果挂载成功,会在/mnt/rom/userdata ⽬录看到userdata.img 中的内容。
通常该⽬录除了“lost+found”(该⽬录⼀般为空,在系统⾮法关机时会存放⼀些⽂件) 系统⽬录外,什么都没有。
读者可以执⾏下⾯的命令查看当前挂载的⽤户镜像尺⼨。
df -h
现在可以在/mnt/rom/userdata⽬录放⼀些⽬录或⽂件,例如,将Test.apk作为普通的Android应⽤放⼊
userdata.img,如要在/mnt/rom/userdata⽬录建⽴⼀个app⼦⽬录,然后将Test.apk⽂件放⼊app⽬录即可。
在修改完镜像挂载分区以后,需要使⽤下⾯的命令重新打包,为了与userdata.img区别,在这⾥将该⽬录打包成了w。
要注意,在打包的过程中会确定⽤户镜像对应的空间⼤⼩,例如,下⾯的命令⽣成了最⼤为128M的⽤户镜像⽂件
(w,ext4格式的镜像⽂件)。
make_ext4fs -s -l 128M -a data w /mnt/rom/userdata
注意:⽤户镜像占⽤的存储空间不能超过Android设备的内部存储器的总尺⼨,否则即使成功刷机,Android设备也可能会启动失败,即使启动也由于SD卡⽆法挂载⽽出现要求输⼊密码(实际上就是映射失败)的情况。
参数说明:
加上"-s"命令⾏,参数就表⽰⽣成的w ⽂件是压缩格式,不能直接使⽤mount命令挂载,需要按着签名的⽽⽅法通过simg2img命令来还原才能挂载到某⼀⽬录。
“-a”命令⾏参数后⾯的是⽂件系统,这⾥需要制定data。
接下来可以使⽤下⾯的命令将w⽂件刷到Android设备上(加上⽬录Android设备正处于正常的启动状态,并通过USB线PC相连)。
注意:在刷w⽂件之前,⼀定要备份Android设备上已安装的应⽤程序、配置和其他数据,否则这些数据将全部丢失(SD卡中的数据不会丢失)。
adb reboot bootloader
fastboot flash userdata w
fastboot reboot
上⾯的命令在刷完w 后,会重启Android设备。通过“设置”->"存储"可以查看使⽤情况。
内存磁盘镜像(ramdisk.img)
内存磁盘镜像存储了Linux内核启动时要装载的核⼼⽂件,通常的镜像⽂件名为ramdisk.img。
之所以称ramdisk.img为内存磁盘镜像,是因为ramdisk.img中的⽂件映射的实际上都是内存中的⽂件,也就是说,即使有权修改等⽂件,也只是修改原始⽂件在内存中的镜像,重新启动Android设备后,⼜会恢复到最初的状态。⽽修改这些⽂件的唯⼀⽅法就是重新制
作ramdisk.img⽂件,并连同Linux内核⼆进制⽂件(zImage)⽣成boot.img⽂件,并且刷⼊设备中才可以⽣效。
ramdisk.img是boot.img中重要的组成部分之⼀,尽管ramdisk.img需要放在Linux内核镜像(boot.img)中,但却属于Android源代码的⼀部分。也就是说,在编译Android 源代码后,会⽣成⼀个ramdisk.img⽂件,其实该⽂件就是root⽬录压缩后⽣成的⽂件。
ramdisk.img⽂件中封装的内容是Linux内核与Android系统杰出的第⼀批⽂件,其中有⼀个⾮常重要的init命令(在root⽬录中可以到该命名⽂件),该命令⽤于读取以及相关配置⽂件中的初始化命令。
其实ramdisk.img⽂件只是⼀个普通的zip压缩⽂件,可以直接使⽤gunzip命令解压,不过解压后并不是原⽂件和⽬录,⽽是有cpio命令备份的⽂件,所以还需要使⽤cpio继续还原。
假设ramdisk.img⽂件在当前⽬录下,则还原ramdisk.img⽂件的命令如下:
mkdir ramdisk
cp ramdisk
gunzip -c ../ramdisk.img > ../ramdisk.cpio
cpio -i < ../ramdisk.cpio
也可以将最后两⾏命令合成如下的⼀⾏。
gunzip -c ../ramdisk.img | cpio -i
执⾏上⾯的命令后,就会在ramdisk⽬录中看到内存磁盘镜像还原后的⽬录结构,如果现在要修改等配置⽂件,可以⾃⼰在ramdisk⽬录
修改完ramdisk⽬录的内容后,就需要使⽤下⾯的命令将ramdisk⽬录重新⽣成ramdisk.img⽂件。
为了与原来的ramdisk.img⽂件有所区别,这⾥⽣成了w⽂件,在执⾏下⾯的命令之前,要保证Linux终端的当前⽬录是ramdisk。
cd XX # ramdisk⽬录
mkbootfs . | minigzip > ../w
Linux内核镜像(boot.img)
Linux内核镜像包含了内核⼆进制(zImage)和内存磁盘镜像(ramdisk.img)。
⼀般对应的镜像⽂件是boot.img(也可以是任何其他的名字)。
由于ramdisk.img中包含的init命令是与Linux内核第⼀个交互的程序,所以在boot.img中需要同时包含Linux内核(zImage)和ramdisk.img。
当Linux内核调⽤init后,系统就会根据及其相关⽂件的代码对整个Android系统进⾏初始化。其中主要的初始化⼯作就是建⽴
如/system、/data等系统⽬录,然后使⽤mount命令将相应的镜像挂载到这些⽬录上。
Android源代码经过编译后,也可以在其中到对boot.img解压和⽣成boot.img⽂件的命令。
其中unpackbooting 为解压命令,mkbooting命令可以将zImage和ramdisk.img⽂件合并成boot.img。
下⾯先来⽤unpackbooting命令将boot.img解压,再看看boot.img是不是有zImage和ramdisk.img⽂件
组成的。
假设boot.img⽂件(我们可以使⽤从其他Rom压缩包中获得的boot.img,也可以使⽤通过Android源代码⽣成的boot.img)在当前⽬录中,使⽤下⾯的命令可以将boot.img⽂件解压到boot⽬录中。
mkdir boot
cd boot
unpackbootimg -i ../boot.img
执⾏完上⾯的命令后,会发现boot⽬录中多了⼏个⽂件,其中有两个主要的⽂件:boot.img-zImage 和。
前者是Linux 内核⽂件(与zImage⽂件完全⼀样),后者是内存磁盘镜像(与ramdisk.img完全⼀样)。为了证明
与ramdisk.img⽂件完全相等,可以使⽤下⾯的命令将 解压到ramdisk⽬录。
mkdir ramdisk
cd ramdisk
gunzip -c ../ | cpio -i
⽬录结构与ramdisk.img⼀样。
如果想向或其他⽂件中添加新的内容,或在内存磁盘镜像中添加新的命令,可以修改刚才由 ⽂件解压⽣成的ramdisk⽬录中的相应⽂件和⽬录的内容,然后使⽤下⾯的命令重新将ramdisk⽬录中的相应⽂件和⽬录的内容,然后使⽤下⾯的命令重新将ramdisk打包成w(当前⽬录是ramdisk)。
mkbootfs . | minigzip > ../w
接下来回到上⼀层⽬录,然后使⽤下⾯的命令将boot.img-zImage和w⽂件合并成w ⽂件(为了区分boot.img,这⾥⽣成了w ⽂件)。
安卓软件签名工具mkbootimg --kernel boot.img-zImage --ramdisk w -o w
如果想修改Linux内核,需要下载Linux内核源代码(官⽅和CM都提供了相应Android设备的Linux内核源代码)
接下来退到上⼀层⽬录,然后使⽤下⾯的命令将boot.img-zImage 和w
现在可以使⽤下⾯的命令重新刷Linux内核(加上Android系统处于正常启动状态,并通过USB线和PC相连)。不过要注意的是Linux内核必须与当前Android设备匹配,否则刷完后Android设备有可能起不来。刷Linux内核不会对系统(system.img)和⽤户数据(userdata.img)造成任何影响。
adb reboot bootloader
fastboot flash boot boot.img,new
fastboot reboot
重启Android设备后,如果我们修改了Linux内核和内存磁盘镜像,就会⽴刻⽣效。
注意:boot.img解压后,除了⽣成boot.img-zImage和⽂件外,还会⽣成⼀些其他的⽂件,如boot.img-base、boot.img-cmdline、boot.img-pagesize等,这些⽂件都是⼀些配置⽂件。
例如boot.img-cmdline⽂件中包含了Linux内核启动时传⼊的参数。通常并不需要管这些⽂件,只需要保持默认值即可)。
熟悉嵌⼊式Linux的读者应该知道,现在的BootLoader(通常是uboot)⼀般与dtb⽂件相配合,以告知Linux有关驱动节点。
因此,这个⼀般和boot.img相互作⽤,由于⼀般⼿机⽤户很难修改这⼀部分的内容,因此不做展开。
Recovery镜像(recovery.img)
Recovery镜像只⽤于刷机,通常的镜像⽂件名为:receovery.img。
在学习定制Recovery.img之前,先了解recovery.img到底是个什么东西。
关于如何更深⼊定制recovery.img,请参考recovery的源代码。
从本质上说,recovery.img和boot.img基本⼀样。这就意味着,recovery.img也是Linux内核(zImage)和内存磁盘镜像(ramdisk.img)组成的。这两个镜像中的Linux内核是完全⼀样的,区别只是ramdisk.img中的少部分⽂件存在差异:
最主要的差异是recovery.img和ramdisk.img中的sbin⽬录中多了⼀个recovery命令进⼊Recovery主界⾯,⽽不会正常启动Android系统。
实现的原理是:
Recovery.img和boot.img在⾃⼰的分区各⾃有⼀个Linux内核(zImage),彼此的Linux内核调⽤的init命令解析的及其相关⽂件的内容有⼀定的差异。
⽽Bootloader根据⽤户的选择决定使⽤boot.img中Linux内核,还是使⽤Recovery.img中的Linux内核启动系统。如果使⽤前
者,Android系统就会正常启动,如果使⽤后者,就会进⼊Recovery选择菜单,所以recovery.img和boot.img的第⼆个差异就是其中的及其相关配置⽂件的内容略有不同。
从前⾯的描述还可以看出,recovery.img和boot.img其实都是⼀个最⼩的运⾏系统,也就是说他们都各⾃带⼀个满⾜最低要求的运⾏环境(ramdisk.img)。boot.img利⽤这个运⾏环境监理更⼤的运⾏环境(system.img),⽽recovery.img就直接使⽤了这个运⾏环境进⾏基本的操作(复制⽂件、删除⽂件、加压⽂件、mount等),这些操作也就是Recovery模式下刷机要进⾏的⼀些操作。
既然了解了recovery.img是什么东西,那么就可以解压recovery.img,并且重写⽣成recovery.img⽂件。
假设recovery.img⽂件在当前⽬录下,解压recovery.img:
mkdir recovery
cd recovery
uppackbootimg -i ../recovery.img
执⾏下⾯的命令会在recovery⽬录下⽣成如下5个⽂件:
recovery.img-zImage
recovery.img-cmdline
recovery.img-pagesize
recovery.img-base
其中前两个分别为recovery.img中的Linux内核和内存磁盘镜像。可以使⽤下⾯的命令解压⽂件:
mkdir ramdisk
cd ramdisk
gunzip -c ../ | cpio -i
现在回到上⼀层⽬录,最后按着4.2.4⼩节的⽅法重新⽣成内存镜像⽂件(这⾥为w),并使⽤下⾯的命令重新⽣成Recovery镜像(这⾥为w )。
重新⽣成Recovery镜像⽂件:
mkbootimg --kernel recovery.img-zImage --ramdisk w -o w
现在可以使⽤下⾯的命令重新刷Recovery(加上Android 处在正常启动状态),并进⼊Recovery模式。
adb reboot bootloader
fastboot flash recovery w
fastboot reboot
adb reboot recovery
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论