Android外部存储详要

参考: http://www.cnblogs.com/wetest/p/8536868.html
Android存储系统架构篇: http://gityuan.com/2016/07/23/android-io-arch/

引子:

  • 通过打印Android文件在内核ext4层和上层的全路径,会发现同样的文件绝对路径竟然不一样,例如:在libc层绝对路径为/storage/…,但在内核ext4层打印的为/media/… .。这里牵扯到Android对外存的管理方面的东西。

  • APP上层读写的文件进程id(getpid()),在内核中访问外存时变成了叫/system/bin/sdcard的守护进程。百思不得解。

  • 一个简简单单外部存储,会存在这么多奇奇怪怪的路径: /sdcard 、 /mnt/sdcard 、 /storage/extSdCard 、 /mnt/shell/emulated/0 、 /storage/emulated/0 、 /mnt/shell/runtime/default/emulated/0 … 其实这背后代表了一项项技术的成熟与发布:模拟外部存储、多用户、运行时权限…


1. 各版本外部存储特性
  1. Android 4.0
  • 支持模拟外部存储(通过FUSE实现)
  • 出现了主外部存储,以及二级外部存储(没有接口对外暴露)
  • 支持MTP(Media Transfer Protocol), PTP协议(Picture Transfer Protocol)
  1. Android 4.1
  • 开发者选项出现“强制应用读权限才可以进行读操作”的开关
  1. Android 4.2
  • 支持多用户,每个用户拥有独立的外部存储
  1. Android 4.4
  • 读操作需要声明READ_EXTERNAL_STORAGE权限
  • 应用读写在外部存储的应用目录(/sdcard/Android/< pkg >/)不需要声明权限。
  • 增加了Contest.getExternalFileDirs()接口,可以获取应用在主外部存储和其他二级外部存储下的files路径
  • 引入存储访问框架(SAF , Storage Access Framework)
  1. Android 6.0
  • 外部存储支持动态权限管理
  • Adoptable Storage特性
  1. Android 7.0
  • 引入作用域目录访问

在这里插入图片描述


补充一个点:

如果应用的minSdkVersion和targetSdkVersion设置成<=3,系统会默认授予READ_EXTERNAL_STORAGE权限。


额 好吧,这里有的我也不懂。

不过现在的FUSE已经被sdcardFS代替了。

sdcardFS简要介绍

  • sdcardfs:android中用于控制文件访问的权限。对内置SD卡的系统调用,先经过sdcardfs,然后把访问路径改为ext4文件系统的真正路径,再到达ext4文件系统。ext4执行完以后,把结果返回给sdcardfs,再返回给调用者。
  • Android将APP数据放置于:用户数据空间data目录和用户sdcard目录。其在物理上是同属一个分区。这个分区也采用同一个文件系统—ext4文件系统。为了控制文件访问的权限,用户sdcard目录用sdcardfs管理来进行其访问权限控制。
  • 所以,一个APP的数据对文件的访问关系如图 24所示:
    在这里插入图片描述

2. 部分特性讲解

1. 模拟外部存储
a. 必要性

  • FAT32属于微软专利,可能存在许可和法律问题(相关文章);
  • 可以定制Android自己的外部存储访问规则;
  • 为多用户做铺垫;

b.实现原理
系统/system/bin/sdcard守护进程,使用FUSE(现在已经被sdcardFS替代)实现类FAT格式SD卡文件系统的模拟,也就是我们经常说的内置SD卡。

  • 用户空间文件系统(Filesystem in Userspace,简称FUSE)是一个面向类Unix计算机操作系统的软件接口,它使无特权的用户能够无需编辑内核代码而创建自己的文件系统。目前Linux通过内核模式对此进行支持。

在这里插入图片描述


sdcard守护进程模拟外部存储大致流程(Android 4.0为例):

  • 首先,指定/data/media目录用于模拟外部存储。该路径的owner和group一般为media_rw, 这样保证只有sdcard程序或root进程能够访问该目录。

在这里插入图片描述


进过打印查看,/system/bin/sdcard 守护进程的 进程名 为: sdcard

  • sdcard守护进程启动后,打开/dev/fuse设备。
    在这里插入图片描述

  • 在/mnt/sdcard目录挂载fuse文件系统。

在这里插入图片描述


  • 开线程,在线程中处理文件系统事件,并将结果写回。

在这里插入图片描述


经过上面一系列步骤,sdcard进程在/mnt/sdcard路径上创建了一个FUSE文件系统,所有对/mnt/sdcard将转为事件由sdcard守护进程处理,并对应到/sdcard/media目录。

例如, 应用创建/mnt/sdcard/a文件,实际是创建/data/media/a文件。

c.优点

  • 模拟外部存储容量和/data分区是共享的,用户数据在内外存储的分配更加自由;
  • 模拟外部存储本身不可卸载,不会因为卸载导致应用访问出现问题,也减少了外部因素导致被破坏的情况;
  • 所有的访问都经过sdcard守护进程,Android可以定制访问规则;

d.劣势

  • 性能上存在一定损失

e. 影响

  • Android 6.0以后,由于动态权限管理的需要,会存在多个fuse挂载点,这导致inotify/FileObserver对外部存储进行文件事件监控时,会丢失事件。

inotify是Linux核心子系统之一,作为文件系统的附加功能,他可监控文件系统并将异动通知应用程序。 – 维基百科(https://zh.wikipedia.org/wiki/Inotify)

2. 多用户

a.支持版本

  • Android 4.2开始支持多用户,但仅限平板;
  • Android 5.0开始,设备制造商可以在编译时候开启多用户模块;

接下来http://www.cnblogs.com/wetest/p/8536868.html 这个博客对源码进行了分析,洞察事物本质,值得仔细看一看!!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值