linux fuse文件系统在 android fuse sdcard的 运用
一、android GB 及JB、KK版本内置sdcard效果对比图
从上面效果对比图,我们可以发现android fuse sdcard 有如下两个优点:
1、使用fuse后 /data 和 /sdcard0 是共离一块分区,这块分区的空间/data和/sdcard0 动态享用, 用户使用灵活。
2、去掉了fat32文件系统,这样也免去了一个license的风险。
二、fuse的标准工作流程图
![]() |
这里重点说明libfuse的作用:libfuse为开发者提供了接口fuse_operations开发者只需要实现这组接口,然后调用fuse初始化接口:fuse_mount()、fuse_new()、fuse_loop()即可实现一个用户空间文件系统。这样为开发多种fuse文件系统带来很多方便。
三、android fuse sdcard架构图及source code
android fuse sdcard 流程和标准fuse流程图最大不同点在于:
android没有直接移植标准的libfuse,而是重写了相关代码,将libfuse的功能集成到sdcard dameon。
这样做的我能想到的好处,可能就是函数调用的层次少了一些,可能效率会好点。
一直想不明白android为什么不移植libfuse。
3、fuse sdcard 的mount状态,如下图:
四、使用fuse sdcard 带来的一些问题及解决方法
1、/data和/sdcard 动态占用空间,如果用户通过/sdcard将整个分区填满,则会导致系统无法启动。
解决办法,就是设置一个/sdcard/可用的上限,不至于导致系统崩溃至无法启用。
具体可以参考mtk修改的代码:\kernel\fs\fuse\inode.c (LIMIT_SDCARD_SIZE包宏处)
static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
{
stbuf->f_type = FUSE_SUPER_MAGIC;
stbuf->f_bsize = attr->bsize;
stbuf->f_frsize = attr->frsize;
stbuf->f_blocks = attr->blocks;
stbuf->f_bfree = attr->bfree;
stbuf->f_bavail = attr->bavail;
stbuf->f_files = attr->files;
stbuf->f_ffree = attr->ffree;
stbuf->f_namelen = attr->namelen;
#ifdef LIMIT_SDCARD_SIZE
stbuf->f_blocks -= (u32)data_free_size_th/attr->bsize;
if(stbuf->f_bfree < ((u32)data_free_size_th/attr->bsize)){
stbuf->f_bfree = 0;
}else{
stbuf->f_bfree-= (u32)data_free_size_th/attr->bsize;
}
if(stbuf->f_bavail < ((u32)data_free_size_th/attr->bsize)){
stbuf->f_bavail = 0;
}else{
stbuf->f_bavail-= (u32)data_free_size_th/attr->bsize;
}
#endif
/* fsid is left zero */
}
2、清除用户数据或者recovey、ota等涉及到要format /data 目录时,/storage/sdcard0 的数据也会被清空掉。
解决办法:
3、不同size emmc 的兼容:同一款手机,可能需要兼容多个size emmc,比如16G版本,32G版本。
4、厂家的预置资源文件,如何导入到内置sdcard?
手机出货前,厂家通常会预置一些资源文件,比如,导航地图,广告视频等。
解决方法:将预置资源编译到/data/media/目录下,系统第一次启动时installd进程会自动将/data/media/目录的东西移到/data/media/0 目录,即sdcard根目录可见该预置资源。
见如下代码:frameworks\base\cmds\installd\installd.c
int initialize_directories() {
int res = -1;
// Read current filesystem layout version to handle upgrade paths
char version_path[PATH_MAX];
snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
int oldVersion;
if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
oldVersion = 0;
}
int version = oldVersion;
// /data/media.tmp
char media_tmp_dir[PATH_MAX];
snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path);
// Only copy when upgrade not already in progress
if (access(media_tmp_dir, F_OK) == -1) {
if (rename(android_media_dir.path, media_tmp_dir) == -1) {
ALOGE("Failed to move legacy media path: %s", strerror(errno));
goto fail;
}
}
// Create /data/media again
if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
goto fail;
}
// /data/media/0
char owner_media_dir[PATH_MAX];
snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path);
// Move any owner data into place
if (access(media_tmp_dir, F_OK) == 0) {
if (rename(media_tmp_dir, owner_media_dir) == -1) {
ALOGE("Failed to move owner media path: %s", strerror(errno));
goto fail;
}
}
version = 2;
// Persist layout version if changed
if (version != oldVersion) {
if (fs_write_atomic_int(version_path, version) == -1) {
ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
goto fail;
}
}
// Success!
res = 0;
}
通过上面的方法,确实可以将预置资源导入到sdcard,但在实际大量生产中,发现一个新问题:
预置资源可能会被移到/sdcard/0/ 目录(即/data/media/0/0),多了一级0目录。
为什么会发生这种问题呢? 经过长时间分析,应该是因为上面的代码稳定性极度依赖于函数fs_write_atomic_int()的原子操作性。
但实际上,该函数根本达不到原子操作效果。
如果解决该问题呢? 1、取消多用户 2、fs_write_atomic_int()函数后面添加sync()。
5、fuse sdcard对开机速度的影响
6、fuse sdcard 相对fat32 sdcard性能更差
相关文章
- [Android Memory] Linux下malloc函数和OOM Killer
- [Linux] linux文件系统学习
- [Android Pro] Android权限设置android.permission完整列表
- 每天一个linux命令(23):Linux 目录结构
- 导入旧版本Android项目时的“Unable to resolve target ‘android
- 【学习总结】快速上手Linux玩转典型应用-第6章-linux常用命令讲解
- Android开发学习---使用Intelij idea 13.1 进行android 开发
- android 5.0新特性学习--CardView
- 自行修改android.jar使其包含隐藏api
- android:keytool生成应用签名证书(java 15)
- Android 7.1预装系统preinstall目录可卸载应用
- Android报错提示:Failed to resolve: com.android.support.constraint:constraint-layout:1.1.3
- Android 10.0 Settings 去掉打开开发者模式和USB调试模式的广播
- Linux 下编译 VLC for Android
- ASM的基础使用 Android 自动化埋点方案原理剖析
- 【Android 逆向】Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )
- Appium - Android 对照 iOS
- L56.linux命令每日一练 -- 第八章 Linux磁盘与文件系统管理命令 -- swapoff和sync
- L51.linux命令每日一练 -- 第八章 Linux磁盘与文件系统管理命令 -- mkfs和dumpe2fs
- L50.linux命令每日一练 -- 第八章 Linux磁盘与文件系统管理命令 -- tune2fs和parted
- L40.linux命令每日一练 -- 第七章 Linux用户管理及用户信息查询命令 -- useradd和usermod
- L3.linux命令每日一练 -- 第一章 Linux命令行简介
- Android多媒体开发-- android中OpenMax的实现整体框架
- Linux以及Android开发中的小技巧和长繁命令记录收集
- Android 开发 --Unable to resolve target 'android-19'
- 在KVM虚拟机中安装Android-x86模拟器
- android 恢复出厂设置代码流程(Good!)