有关fuse的介绍和下载可以访问http://fuse.sourceforge.net查看。本文主要介绍如下将fuse移植到Android 4.4.2,并开发一个简单的文件系统。

本文中使用的fuse是2.9.3版本,可以从sourceforge.net/projects/fuse/files/fuse-2.X/2.9.3/下载。

在Android源码中的external目录中创建一个fuse目录,并将fuse-2.9.3.tar.gz解压于此。

进入fuse目录,执行./configure命令,生成Makefile和include/config.h。

在fuse目录中创建Android.mk,内容如下:

运行mm命令之后报错:

原因在于Android的bionic没有完全实现标准POSIX线程库和splice函数。所以做以下修改:

  • 把include/config.h中的#define HAVE_SPLICE 1注释掉
  • 在include/fuse_common.h中引入pthread.h头文件
  • 将lib/fuse.c中int fuse_start_cleanup_thread(struct fuse *f) 和 void fuse_stop_cleanup_thread(struct fuse *f)函数的定义注释掉
  • 将lib/fuse_mt.c中第68行之后的内容注释掉

再次编译报错:

做以下修改:

  • 把include/config.h中的#define HAVE_STRUCT_STAT_ST_ATIM 1 注释掉
  • 修改./lib/fuse.c文件,将2810行的tv[0] =attr->st_atim;修改为tv[0].tv_nsec =attr->st_atime;将2815行的tv[1] =attr->st_mtim;修改为tv[1].tv_nsec =attr->st_mtime;

再次编译:

在lib/mount_util.h中添加:

#ifndef _PATH_MOUNTED
#define _PATH_MOUNTED “/proc/mounts”
#endif

再次编译:

  • 将lib/fuse_misc.h中的#define FUSE_SYMVER(x) __asm__(x)改为#define FUSE_SYMVER(x)
  • 将lib/helper.c文件fuse_main_common函数中的:
    if (multithreaded)
    res = fuse_loop_mt(fuse);
    else
    注释掉。
  • 将lib/cuse_lowlevel.c文件cuse_lowlevel_main函数中的:
    if (multithreaded)
    res = fuse_session_loop_mt(se);
    else
    注释掉。

再次编译即可生成libfuse.so动态库。但在编译fusermount时依然报错:

将出错的四行注释掉即可。

这样我们就得到了libfuse.so库和fusermount工具。接下来就可以开发我们自己的文件系统了。

简单起见,我们直接使用fuse提供的例子,将下列语句添加到Android.mk中:

编译后可以得到hello可执行程序,它就是一个简单的文件系统处理程序,虽然它不会操作任何真实的文件。

接下来使用adb工具将libfuse.so push到Android设备或模拟器的/system/lib下,将fusermount和hello可执行程序push到/system/bin下并为它们添加可执行权限。

作为例子,我们可以在/data下创建一个fuse_hello目录作为挂载点,然后执行:

hello  /data/fuse_hello

这样hello文件系统就开始工作了。ll 命令查看文件:

# ll /data/fuse_hello/
-r–r–r– root root 13 1970-01-01 08:00 hello

cat 查看hello文件的内容:

# cat /data/fuse_hello/hello
Hello World!

但切换到非root用户,比如 su system后发现,system用户无法查看/data/fuse_hello/中的内容。这时我们需要在挂载时添加allow_other选项。

首先使用fusermount工具卸载文件系统:

fusermount -u /data/fuse_hello

然后重新挂载文件系统:

hello  -o  allow_other  /data/fuse_hello

这样任何用户都可以访问hello文件系统的内容了。