在Android K和L版本里面,zygote会将sdcard指向/storage/emulated/0,而非从init启动的bin程序识别的/storage/emulated/legacy,也就是说如果将sdcard的路径传递给二进制服务的时候,必须要进行相应的转换。
类似于下面的code。
if (!strncasecmp("/storage/emulated/0", mImageUrl, 19)) {
using std::string;
string imagePath = string(mImageUrl);
imagePath = imagePath.substr(19);
imagePath = string("/storage/emulated/legacy") + imagePath;
strncpy(mImageUrl, imagePath.c_str(), imagePath.length() + 1);
ALOGD("setDataSource image path replaced %s", mImageUrl);
}
原理学习主要来自下面这篇blog,也转载于此。
http://www.cloudchou.com/android/post-689.html
引言
emultaed技术,即多用户挂载技术,是Android 4.2引入的一项新的Sd卡挂载技术,不同的用户看到的Sd卡挂载目录不一样。
比如使用adb shell查看sd卡目录可能得到的Sd卡目录是/storage/emulated/legacy,它实际上是一个链接目录:
|
|
这样/mnt/shell/emulated/0是sd卡的实际目录,但是在应用程序里即使用Root权限查看/storage/emulated/legacy目录,会发现该目录根本不存在。
应用程序通过系统api获取Sd卡路径时得到的Sd卡路径是/storage/emulated/0,同样我们使用adb shell去查看该目录时也会发现该目录不存在。
linux内核从2.6.x引入了共享挂载,从属挂载,私有挂载,绑定挂载,挂载传播技术。
Android 4.2就是利用了共享挂载和从属挂载来隔离挂载的命名空间,不同用户的挂载对别的进程或者用户不可见。
关于挂载技术的资料:
https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt
命名空间相关资料:
http://book.51cto.com/art/201005/200881.htm
多用户挂载原理
init.rc
首先我们看一下init.rc里storage,mnt目录的创建:
|
export EXTERNAL_STORAGE /storage/emulated/legacy
export EMULATED_STORAGE_SOURCE /mnt/shell/emulated
export EMULATED_STORAGE_TARGET /storage/emulated
# Support legacy paths
symlink /storage/emulated/legacy /sdcard
symlink /storage/emulated/legacy /mnt/sdcard
symlink /storage/emulated/legacy /storage/sdcard0
symlink /mnt/shell/emulated/0 /storage/emulated/legacy
mkdir /storage/external_storage 0666 system system
mount tmpfs tmpfs /storage/external_storage rec mode=0775,gid=1000
# Backward compatibility
symlink /storage/external_storage /mnt/usb
可以看到有如下链接关系:
|
|