一、android GB 及JB、KK版本内置sdcard效果对比图

从上面效果对比图,我们可以发现android fuse sdcard 有如下两个优点:

1、使用fuse后 /data 和  /sdcard0 是共离一块分区,这块分区的空间/data和/sdcard0 动态享用, 用户使用灵活。

2、去掉了fat32文件系统,这样也免去了一个license的风险。


二、fuse的标准工作流程图

from:  http://en.wikipedia.org/wiki/Filesystem_in_Userspace
Filesystem in Userspace

这里重点说明libfuse的作用:libfuse为开发者提供了接口fuse_operations开发者只需要实现这组接口,然后调用fuse初始化接口:fuse_mount()、fuse_new()、fuse_loop()即可实现一个用户空间文件系统。这样为开发多种fuse文件系统带来很多方便。


三、android fuse sdcard架构图及source code

1、source code:

\system\core\sdcard\
\frameworks\base\cmds\installd\
\kernel\fs\fuse\

2、棱流程架构图:




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 的数据也会被清空掉。

 解决办法: 

       •如果需要清除data时(即format /data),不直接格式化,而采用删除方式(白名单/data/media/)

3、不同size emmc 的兼容:同一款手机,可能需要兼容多个size emmc,比如16G版本,32G版本。

  
  build阶段,userdata.img指定分区的大小是不变的,但不同emmc size,“/data”分区的大小是希望不同的。
  解决方法:利用ext4 resize功能,第一次开机自动调整“/data”分区的大小。
   source code :\external\e2fsprogs\resize
   http://www.ibm.com/developerworks/cn/linux/l-cn-ext4resize/

   后面再专门写一篇文章说明resize功能的实际使用。

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对开机速度的影响

    由于data和sdcard共享分区后, /data分区变大了很多,特别是32G、64G等大容量emmc 。
    这样系统启动时,调用如下命令,fs check花的时间就会长很多。
    •exec /sbin/e2fsck -pfD /emmc@usrdata  

  解决方法: 正常开机,不进行完整的check流程。 仅异常开机才进行完整fs check 。类似于PC 。

6、fuse sdcard 相对fat32 sdcard性能更差

  
   fuse sdcard 相比fat32 sdcard 读写性能会有15%左右的drop,这是fuse的 设计天性, 各位有什么好的解决方法呢?

linux fuse文件系统在 android fuse sdcard的 运用相关推荐

  1. 基于fuse文件系统的android sdcard存储方案:之二

    续<基于fuse文件系统的android sdcard存储方案:之一>,再聊聊基于fuse文件系统的android sdcard存储方案:之二, 以后有空再谈谈该方案的缺点,及优化方案. ...

  2. Android fuse文件系统

    一.fuse文件系统挂载 从android4.4 以来,第三方应用程序是不能再随便的访问sdcard,sdcard的权限管理是fuse 即用户空间文件系统(Filesystem in Userspac ...

  3. linux fuse安装脚本,Linux FUSE(用户态文件系统)的使用:用libfuse创建FUSE文件系统...

    说明 FUSE 是Linux Kernel的特性之一:一个用户态文件系统框架,a userspace filesystem framework. 形象的说就是可以在用户态运行一个程序,这个程序暴露出一 ...

  4. fuse文件系统调试环境

    libfuse源码:GitHub - libfuse/libfuse: The reference implementation of the Linux FUSE (Filesystem in Us ...

  5. python画画bup_用Python编写一个简单的FUSE文件系统的教程

    如果你是我的长期读者,那么你应该知道我在寻找一个完美备份程序,最后我写了一个基于bup的我自己的加密层. 在写encbup的时候,我对仅仅恢复一个文件就必须要下载整个巨大的档案文件的做法不甚满意,但仍 ...

  6. android fuse 检测原理,fuse 原理总结

    Fuse是filesystem in user space,一个用户空间的文件系统框架,允许非特权用户建立功能完备的文件系统,而不需要重新编译内核.fuse模块仅仅提供内核模块的入口,而本身的主要实现 ...

  7. 嵌入式Linux根文件系统制作

    嵌入式Linux根文件系统制作 一.根文件系统简介 根文件系统首先是一种文件系统,该文件系统不仅具有普通文件系统的存储数据文件的功能,但是相对于普通的文件系统而言它还是内核启动时所挂载(mount)的 ...

  8. Android研究-linux内核启动到android系统

    很多人阅读代码,总喜欢从头开始,这样觉得很安全,有依靠,无论如何总是能知道"头",有头就能找到任何需要的部分. Android生在linux内核基础上,linux内核启动的最后一步 ...

  9. 构建基本的嵌入式Linux根文件系统

    构建基本的嵌入式Linux根文件系统 其实在去年8月份我做系统移植时就构建好了一个可以用的根文件系统,但是那时是跟着别人的<Linux全线移植文档>做的.有些东西我也不清楚,只是跟着做,做 ...

最新文章

  1. 熵是什么?熵的公式是什么?决策树如何把熵的递减变换为信息增益进行树枝的分叉以及树的生长的?
  2. django(权限、认证)系统—— 基于Authentication backends定制
  3. oracle学习第一天
  4. 【重复制造精讲】定义重复制造参数文件
  5. 【ASP.NET Web API教程】2.3.5 用Knockout.js创建动态UI
  6. mysql 行转列分级输出_MySQL如何实现行转列分级输出?_MySQL
  7. Solr-5.3.1安装配置
  8. 关于搞技术的一点思考
  9. python 内置运算
  10. java生成excel到本地_java 将数据库中的数据导出成Excel文件 并保存到本地 将文件地址返回给前端...
  11. 机器学习之工程师入门路线
  12. 【手势识别】基于matlab k-means聚类手势识别【含Matlab源码 386期】
  13. 学计算机编程要考证吗,程序员可以考的证书有哪些_可以自学吗_上学吧
  14. 卡尔曼滤波与扩展卡尔曼滤波(EKF)
  15. 卡内基梅隆计算机硕士录取案例,大神offer | 恭喜再来人学员录取卡耐基梅隆大学-机器学习硕士!...
  16. 三星发布全球首款太阳能笔记本
  17. Mac电脑如何快速回到桌面?
  18. 中国中试工厂市场现状研究分析与发展前景预测报告
  19. 零基础语法入门第第二十三讲 动词的用法总结
  20. python爬虫--获取天猫店铺商品价格及销量

热门文章

  1. 转:移动网络下的性能优化之省电篇
  2. J2EE 架构师之路
  3. 车载娱乐系统 AppSupport
  4. Android开源库集合(控件)
  5. BestCoder Round #90 Kblack loves flag
  6. python函数参数定义顺序_18 Python - 函数定义与参数
  7. Javascript第七章cookie的读取和写入源码第一课
  8. 搭建SSM全流程框架过程
  9. 向指定的服务器端口发送信息,向指定服务器的指定端口发送UDP包
  10. linux多进程spawn,【Linux Shell脚本编程】expect解决脚本交互 + Shell的多进程处理