本章描述了android的文件系统,以及root文件系统、/system分区、/data分区、/cache分区以及/vendor目录和SDk的细节。
root文件系统
android的root文件系统(/)是mount自ramdisk.img(initramfs)的文件。
每次启动时fastboot从boot分区中把这个镜像加载到内存中,并将其提交到内核进行管理。除非进行刷机(flashed)否则root文件系统将不会被更改。root系统中包含以后/init和与其相关的配置文件以及可执行文件,具体细节在下表:
目录或文件 | 注释 |
---|---|
default.prop | 编译时/build/core/main.mk 中ADDITIONAL_DEFAULT_PROPERTIES 变量的值,init根据它加载其他系统范围内的属性文件 |
file_contexts | 记录SELinux中文件的context。用于限制非授权用户访问系统文件和目录 |
init | 将会被内核以pid 1执行的二进制文件 |
init[…].rc | /init 的配置文件,主要是init.rc |
property_contexts | 记录SELinux中的系统属性的contexts |
seapp_contexts | 记录SELinux中的应用的context,限制应用的操作域 |
sepolicy | SELinux策略设置编译后的结果 |
sbin/ | 该目录中有abd、healthd以及recovery等可执行文件,即使不mount /system也能够使用 |
verity_key | 含有认证/system 所需要的DM_Verity RSA 密钥 |
/system分区
该分区是存放谷歌或者其他厂商提供andorid组件的位置,该目录及其下所有文件都属于root:root,其权限为0755,但是该文件系统是以只读方式mount的;这样做的目的是提高文件系统的稳定性和安全性。理论上对于绝大多数设备来说,本分区下的所有目录以及文件都是一样的。实际上,一些厂商和运营商都会向/system
添加自己的内容(android专门为厂商设计了/vendor
目录来放置相关内容),具体细节在下表:
目录 | 注释 |
---|---|
app | 存放系统应用,有谷歌预绑定的app,也有厂商提供的app |
bin | 存放二进制可执行文件,有守护进程的,也有一些命令行shell使用的 |
build.prop | 在编译时生成的属性文件,/init 根据它在启动过程中去加载其他的属性文件 |
etc | 存储了各种配置文件,它是/etc 的符号链接 |
fonts | 字体文件 |
framework | 存放android的框架,各个framework都会存放在各自的jar文件中,每个framework的dex文件经过优化后,会被存放在与jar文件同名的odex文件中 |
lib | 存放运行时的库文件 |
lost+found | 在/system 进行fsck操作时生成的目录,系统如果崩溃,该目录可能会含有不知道自己上一级目录是谁的inode |
media | 以ogg形式存放的各种音频、以及在系统启动时播放的动画 |
priv-app | 该目录存放了特权应用 |
usr | 支持文件,比如unicode的映射文件、设备和键盘的键盘布局文件 |
vendor | 用于存放厂商提供的文件,实际上厂商都不会放这里 |
xbin | 存放用途特殊的,正常操作过程中不需要的二进制可执行文件。在模拟器中,这个目录都是存放来自asop的/system/extras 的各种工具。各种提取su权限的root程序也放在这里 |
/system/bin
本目录放置andorid使用的各种可执行文件(包含调试工具)。具体可以分为5类:
用来提供服务的可执行文件,这类二进制文件都是在系统运行过程中有
/init
来进行调用的,他们调用的路径保存在/init
使用的rc文件中。可执行文件 功能 aoo_process 用户app的宿主进程,Zygote都是这个可执行文件的实例,它由Dalvik VM/ART初始化 applypatch[_static] 在OTA升级过程中使用–根据脚本来应用补丁 bootanimation 在图形界面子系统( surfacefliger
)加载时,播放的启动动画clatd ipv4转ipv6的转换器 dalvikvm 用于启动dalvik虚拟机的实例 debuggerd 在系统崩溃时产生tombstone,也可以和一个远程gdb相连接 drmserver DRM模块的宿主进程 dnsmasq 伪dns服务,在设备提供热点服务时,提供dns代理服务 hostpad wifi热点守护进程 keystore android的密钥存储和管理服务 linker android运行时的链接器 mdnsd 组播dns的守护进程,用来使相邻的设备能够通过和wifi直连的方式相互发现和通信 mediaserver 音视频录制以及播放 mtpd 用来支持ppp/l2tp netd 用来管理网卡以及防火墙 pppd 点对点协议守护进程,vpn需要使用 racoon 提供对vpn的支持 rlid 无线界面层守护进程 sdcard sd卡守护进程,实现了sd卡文件系统,通过fuse模拟多用户权限设置 sensorservice sensor hub,并发读取各种传感器 servicemanager 提供了服务的注册以及查找功能 surfaceflinger 画出图形界面的样子,并把他们加载到framebuffer中 vold Volume守护进程,用来mount和unmount文件系统,也有文件系统的解密功能 uncrypt 解密文件系统,在recovery前使用 wpa_supplicant 无线访问适配层,提供wifi和wifi p2p的客户端支持 调试工具,被归入这一类的事一些用于调试的原生二进制可执行文件(一般在模拟器中包含,厂商一般会在实机中删除)。
UNIX命令,unix相关的常用命令,和android特有的命令(getprop/setprop/watchprop),一般集成在
/system/bin/toolbox
中。调用Dalvik的脚本(upcall script),这些脚本通过shell与Dalvik进行交互(主要是调试),这些脚本都是从
/sysytem/bin/app_process
派生未来,用它们在/system/framework
目录中的同名框架,加载Dalvik类(zygote本身就是app_process的一个实例),使用时,脚本会把用户传给它的参数直接传递给Dalvik类。我们只需要看Dalvik脚本中的am就可以了解这些脚本的结构了。下表描述了/system/bin
中封装了app_process的脚本。脚本 用途 am 与ActivityManager进行交互,启动activity发起的intent bmgr 备份管理接口 bu 启动备份 content 与android content provider交互的接口 ime 控制输入法编辑器 input 与 InputManager
进行交互,注入输入事件media 控制当前的媒体播放器 monkey 用随机生成的输入时间运行一个APK pm 与包管理器进行交互,可以用来列出、安装、删除包以及列出权限 requestsync 同步账号 setting 获取、设置系统权限 svc 控制电源、数据、wifi和usb类服务 uiautomator 进行UI自动化测试,测试dump view之间的层次关系 wm 与窗口管理器进行交互、修改显示尺寸和分辨率等 厂商定制的二进制脚本文件,这类文件完全可以由厂商提供,通常为提供服务或者调试的工具。当然这些文件也可以按照aosp的约定放到
/vendor
中,但这也不是强制的。
/system/xbin
这个目录类似于unix中的/sbin
,这里面含有管理员可能会觉得非常有用的二进制可执行文件,一般不提供给普通用户使用。这里命名为“x”而不是“s”是为了避免与android自身的/sbin
(root文件系统中的一部分,含有系统操作时必须的二进制可执行文件)冲突。
这个目录中的可执行文件时从asop的/system/extras
目录中编译得来的。这个目录会不会出现取决于厂商(有的厂商会吧这个目录删除)。下表中包含模拟器在该目录中包含的文件:
可执行文件 | 功能 |
---|---|
add-property-tag | 向系统的.prop文件中添加属性 |
check-lost+found | 在fsck操作完成之后,检查lost+found目录 |
cpueater | 让cpu跑到100%的死循环 |
cpustats | 显示cpu和处理器调节器的统计信息 |
daemonize | 把一个可执行文件作为守护进程启动,并关闭stdin/stdout/stderr |
dexdump | dex文件dump工具,也能dump文件头和字节码 |
directiotest | 测试块设备io性能 |
kexecload | 使用kexec系统调用,用一个新的内核重写内核镜像 |
ksminfo | 显示ksm的使用信息 |
latencytop | 以可读性更强的形式显示/proc/sys/kernel/latencytop 中的数据 |
librank | 给出各个共享内存区域所在各个进程中的使用情况 |
memtrack | 跟踪进程的内存使用情况 |
micro_bench | 内存基准测试工具 |
nc | netcat,分析TCP和UDP的工具 |
netperf | 客户端网络性能分析工具 |
netserver | 服务端网络性能分析工具 |
procmem | 显示进程内存使用情况统计信息 |
procrank | 和librank互补,它可以逐个进程给出共享内存使用信息 |
rawbu | 在底层备份/恢复 /data 中的数据 |
sane_schedstat | 以刻度形式展示scheduler信息 |
showmap | 显示进程内存的分配情况 |
showslab | 显示内核slab分配器的信息 |
SQLite3 | 命令行工具 |
strace | 系统调用trace工具 |
su | 切换用户 |
taskstats | 提供liunx的taskstats接口的详细使用统计信息 |
tcpdump | 抓包工具 |
timeinfo | 输出时间的相关信息 |
在真实设备中,这些可执行文件作为调试工具特别有用,安装方法如下:
1 | adb pull /system/xbin #把模拟器中的文件复制到主机中 |
/system/lib[64]
该目录中包含/system/bin
和/system/xbin
中可执行文件所使用的共享库。在大多数的设备中,/system/lib
中包含有多个字目录,如下:
目录 | 介绍 |
---|---|
drm/ | 提供drm引擎。比如一些包含专利的so,libfwdlockengine.so |
egl/ | android版本的opengles |
hw/ | HAL模块 |
ssl/engines | 含有libkeystore.so,该库使得OpenSSL能够使用android的Keystore机能 |
在Intel设备中,本目录还包含有一个名为arm/的子目录,这个目录包含有arm架构编译的共享库的拷贝。这些库会被用在Intel二进制执行环境转换层(binary translation layer)Houdini上,用来为执行arm的可执行文件提供一个完整的运行时环境。
在android中几乎所有的二进制文件都是动态链接的。唯一例外的时/sbin
目录中的二进制可执行文件。因为这些可执行文件会在/system
被mount之前就会被用到。
/system/etc
这个目录和unix类似,里面都存放这配置文件。/etc
也是这个目录的符号链接,这样做的目的时为了让ASOP项目以外的项目也能找到配置文件(unix的配置文件目录就是/etc
)。
名称 | 描述 |
---|---|
NOTICE.html.gz | 法律文件 |
audio_effects.conf | 被android的HAL层使用的文件 |
audio_polic.conf | 被android的HAL层使用的文件 |
apns-conf.xml | 被com.android.providers.telephony.TelephonyProvider使用 |
asound.conf | 设备ALSA的配置文件 |
bluetooth | 蓝牙配置文件 |
clatd.conf | CLATd,实现ipv4 over ipv6的配置文件 |
event-log-tags | 各个android组件的日志log,被android.util.EventLog使用 |
fallback_fonts.xml | 列出了在加载system_fonts.xml中没有指定的font-family时所能选用的fallback font。它会被android中的layoutlib的FontLoader所使用 |
gps.conf | gps配置文件 |
hosts | 主机-IP表对应关系 |
media_codecs.xml | 列出了StageFright所支持的所有codec |
media_profiles.xml | 列出了LibMedia所支持的所有profile |
ppp/ | 存放启动/停止vpn和ppp连接活动的可执行文件 |
permissions | 存放了多个xml文件,每个文件规定了一个内置文件应用的权限,它会被PackageManager 使用 |
security | 这个目录存有被各种安全证书 |
system_fonts.xml | 列出字体样式,并把字体样式和/system/fonts 中的各个TTF文件一一对应起来 |
wifi | WPA supplicant适配层的配置目录,用于控制wifi和wifi p2p的连接活动 |
在不同的设备制造商手里,本目录中可能还有一些其他文件。
/data分区
这个分区使用来存放用户个人数据的,将用户的个人数据单独存放起来有如下的好处:
- 降低
/data
和android系统的耦合。系统在升级或者恢复的时候仅会对/system
目录进行操作(擦除或重写),而不会对/data
中的用户数据有其他的影响。系统在恢复出厂设置时则仅会格式化/data分区,而不会对系统有其他的影响。 - 在用户需要时,
/data
能够被加密,而加密以及解密都会对系统运行造成延迟。而由于这种设计,/system
中是没有敏感设备,加密用户的数据也就不会因加密而影响到系统,给系统带来相关的延迟。 /data
可以设置为不可执行,这样极大的加大了恶意软件的攻击难度。因为,恶意软件在设置为不可以执行后,就没有了可写又可执行的分区。因为DEX和OAT是运行在虚拟机里面的,所有这对Dalvik和ART app不会有任何影响。root后的设备是需要remount该分区的。
/data
分区是以nosuid的权限mount的,这使得root设备更加复杂了一些,因为su不能放在/data中运行而只能放在 /system
这样的只读分区中。如果系统在对/system
进行hash校验的话,则root就更加不容易执行了。
下表列出了存储在/data
分区中的内容:
目录 | 注释 |
---|---|
anr | dumpstate用来记录失去响应的应用的函数调用栈当前状态的地方 |
app | 用户自己安装的应用 |
app-asec | 存放asec的容器,每个asec加密的应用都对应一个asec容器 |
app-lib | 应用的JNI库都可以在这里被找到 |
app-private | 提供应用的私有存储空间,目前被asec替代 |
backup | 供备份服务使用 |
bugreports | bugreport专用,用来存放bugreport生成的报告 |
davlvik-cache | 用于存放优化过的系统应用和用户安装的应用的class.dex |
data | 各个已经安装的应用的目录,目录名为逆dns格式 |
dontpanic | 未使用 |
drm | 供android的数字版权管理器使用 |
local | 供uid shell使用的一个临时目录,在adb中也可以使用 |
lost+found | 对/data 分区执行fsck操作时自动生成的目录 |
media | 供sdcard服务吧sd卡mount到这个mount点上 |
mediadrm | 供Media DRM服务使用 |
misc | 各种其他文件的目录 |
nfc | 存储NFC参数 |
property | 存放持久性属性,文件名就是属性名 |
resource-cache | 供AssetManager 使用的资源缓存 |
security | 一般为空 |
ssh | 供那些ssh服务使用 |
system | 存放了大量的系统配置文件 |
tombstone | 存放由debuggerd生成的应用崩溃报告 |
user | 与4.1版本开始引入。不同的用户会把各自的数据和应用安装在/data/user/用户号 下的各个目录中,系统运行时,把/data/data 下的对应目录做符号链接,使之指向/data/user/用户号 下对应的目录。这样做可以使android系统支持多用户,/data/data 会被直接指向/data/user/0 |
/data/data
这个目录是所有应用(系统应用、用户安装的应用)都存储其对应数据的地方。每一个应用都对应有一个目录,每个子目录权限为0751
,而/data/data本身的权限为0771,system system
,这意味着这个目录本身是可以执行的(cd命令),但却不能读出其包含的子目录。在应用中,每个应用对应的子目录也是这样的,能够执行却不能被非拥有者读取。
/data/data下各个目录的字目录都是其对应应用在整个文件系统中唯一能够执行写入的位置。
/data/misc
和它的名字相反,这个目录有一些重要的文件。如下表:
目录 | 内容 |
---|---|
adb | 存储可信的允许进行链接的电脑公钥 |
bluetooth | BlueZ[<4.2]的配置文件 |
dhcp | 存储实现dhcp的ctdent守护进程的PID文件 |
keychain | 存放android内置证书pin码和黑名单 |
sensors | 用于存储传感器调试数据 |
sms | 存储短信codes数据库 |
systemkeys | 用来存储asec容器的密钥 |
vpn | 用来存储vpn状态配置文件 |
wifi | 用于存储wifi子系统的配置文件和套接字 |
/data/system
这个目录中含有对维护设备状态非常重要的文件。这个目录的访问权限也是被限制为system system
,如果设备没有root,则无法看到该目录下的各个文件。下表中列出了相关文件:
目录 | 注释 |
---|---|
appops.xml | 供控制应用权限的AppOps服务使用 |
batterystats.bin | 供BatteryStats 服务使用 |
called_pre_boots.dat | 供ActivityManager 记录每个Boot broadcast receiver |
device_policies.xml | DevicePolicyManagerService 使用的配置文件 |
dropbox | 供DropBox服务使用 |
entropy.dat | 供EntropyMixer 生成随机数使用 |
gesture.key | 锁屏图案的hash |
framework_atlas.config | 供负责将预加载的bitmap组装成纹理贴图的AssetAtlasService 使用 |
ifw/ | Intent防火墙规则库 |
locksettings.db | 锁屏设置,记录了设备的锁屏策略 |
netpolicy.xml | 供NetworkPolicyManagerService 使用的配置文件 |
netstats/ | 用来记录NetworkStatsService 按device、uid或xt得到的网络传输数据统计的目录 |
packages.list | PackageManager 列出的所有安装在系统中的包 |
packages.xml | PackageManager 列出的所有已安装包的元数据 |
password.key | 锁屏PIN码/口令的hash |
procstats/ | 供ProcessStats 服务存储文件的目录 |
registered_services/ | 供android.content.pm.RegisteredServicesCache 使用的目录 |
usagestats/ | 供UsageStats 服务存储文件,特别是usage-history.xml文件的目录 |
users/ | android的多用户支持 |
/cache分区
android在系统升级的过程中使用本分区。系统的升级包会被下载到这里。设备在recovery/
升级模式下启动时,会用到这个分区。
recovery这个可执行文件和系统在启动到recovery模式时,也会用到这个分区来交换信息。
/vendor分区
本分区是用来存储厂商对android系统的修改。这样做是避免在系统更新时厂商的修改也被抹除。一些专门的组件会在添加/system
目录之前,回先去检查/vendor
目录,具体会去检查哪些路径。
由于这个目录交由厂商处理,所以这些目录存储的内容在不同的设备上存在很大的区别。如/vendor/app目录是提供给厂商进行放置预装的应用,但实际上基本上没有人去用。
sd卡
大多数的sd卡都是exfat或者fat32文件系统,这两种系统都不支持权限管理。为了能实现权限管理、多用户配置,android通过FUSE(file user
,用户态下的文件系统)模拟sd卡的方式来解决这个问题.FUSE使我们在用户态进程中实现文件系统。FUSE会在内核中安装一个用于支持通用文件系统的小模块,同过这个模块和VFS对接实现基本的注册文件系统功能,而真正的文件系统是在一个用户态进程(/system/bin/sdcard
)中实现。在新版的android中,sd卡的mount点在/storage/ext_sd
中,对于没有sd的设备,这个mount点通常会指向/data分区中的目录(/data/media/0
)。
上面提到的一些目录都已经在android.os.Environment
类中被定义为了常量。
android还提供了模拟sd卡文件系统,无论有没有sd卡都可以使用。通过mount命令,可以观察到sd卡文件系统。