FUSE——用户空间文件系统


  用户空间文件系统(Filesystem in Userspace,简称FUSE)是操作系统中的概念,指完全在用户态实现的文件系统。
目前Linux通过内核模块对此进行支持。一些文件系统如ZFS,glusterfs和luster使用FUSE实现。   
  
  Linux用于支持用户空间文件系统的内核模块名叫FUSE,FUSE一词有时特指Linux下的用户空间文件系统。   
  
  文件系统是一个通用操作系统重要的组成部分。传统上操作系统在内核层面上对文件系统提供支持。而通常内核态的代码难以调试,生产率较低。   

  Linux从2.6.14版本开始通过FUSE模块支持在用户空间实现文件系统。   

  在用户空间实现文件系统能够大幅提高生产率,简化了为操作系统提供新的文件系统的工作量,特别适用于各种虚拟文件系统和网络文件系统。ZFS和glusterfs都属于网络文件系统。但是,在用户态实现文件系统必然会引入额外的内核态/用户态切换带来的开销,对性能会产生一定影响。

  使用 FUSE 您可以开发功能完备的文件系统:其具有简单的 API 库,可以被非特权用户访问,并可以安全的实施。更重要的是,FUSE 以往的表现充分证明了其稳定性。

  使用 FUSE,您可以像可执行二进制文件一样来开发文件系统,它们需要链接到 FUSE 库上 —— 换言之,这个文件系统框架并不需要您了解文件系统的内幕和内核模块编程的知识。 

http://fuse.sourceforge.net/

The FUSE kernel module and the FUSE library communicate via a special file descriptor which is obtained by opening /dev/fuse.  This file can be opened multiple times, and the obtained file descriptor is passed to the mount syscall, to match up the descriptor with the mounted filesystem.

=================
  浏览了下sourceforge,知道FUSE支持kernel2.4.X和2.6.X,就直接把latest stable release下下来了,2.8.2,./configure;make;make install之后跑了下example里的hello,出现device not found error,用modprobe fuse查看,cannot locate fuse module.果然,FUSE虽说是支持2.4.X,不过该版本kernel里面没有fuse内核模块。查了下wiki,kernel 2.6.14之后才开始有自带fuse。有2种解决方案,一种是将fuse编译进current kernel module中,另一种将fuse source code配置好放于相应目录中recompile kernel。显然前者更方便,不过由于下下来的是最新稳定版本,configure选项没有--enable-kernel-module参数,退而求其次,下了个蛮早的版本,2.4.2,证实有--enable-kernel-module,安装完之后modprobe fuse不再报错,./hello pathname -d下就可以跑个最简单的程序了。该文件系统只有单个文件hello,只含hello world一句话,然后将其mount到pathname下,跑完之后无论cat还是ls都看得到了。

  接下去一分为二,FUSE的一些实现以及API Reference,并且在fuse的源pack里也有相应doc,kernel文件夹下就是source code;另外就是实际的编码实现,无论是商业抑或学术的项目,基于fuse实现的有很多,cvsfs,ftpfs...wiki上有详细list,不过都笼统介绍了下。在IBM developerworks里搜到篇比较详细的说明定制和创建新fs的过程的文章,刚上手的话推荐看下,很有实用价值。

FUSE工作流程:
  fuse_main()(lib/helper.c):fuse用户空间主函数,用户程序调用它时,fuse_main()函数解析相关参数(如mountpoint,multithreaded),并调用fuse_mount()函数。调用fuse_new(),为fuse文件系统数据分配存储空间。调用fuse_loop()函数实现会话的接受与处理。

  fuse_mount()(lib/mount.c):创建UNIX本地套接口,创建并运行子进程fusermount。并返回fuse模块文件fd给fuse_main()函数。

  fusermount(util/fusermount.c):确保fuse模块已经加载,通过UNIX套接口返回fuse模块的文件fd给fuse_mount()函数。

  fuse_new()(lib/fuse.c):为fuse创建数据结构空间,用来存储文件系统数据。

  fuse_loop()(lib/fuse.c)(fuse_loop_mt()(lib/fuse_mt.c)):从/dev/fuse读取文件系统调用,调用fuse_operations结构中的处理函数,返回调用结果给/dev/fuse

几个key:
  (1)处于用户态的文件系统要和kernel通讯的话要通过一个特殊的FD,打开/dev/fuse即可得到
  (2)让不具备相应优先级的用户做mount syscall:两个提升优先级的解决方案,一是你创建的文件系统有device file,打开device即可。或者创建的文件系统包含suid,sgid的程序,然后执行改程序,suid,sgid可以帮助非授权用户在执行含有其的程序时能够访问受限的资源。

FUSE operations: 


  这个就跟编码有关系了,要实现的文件系统有些特殊功能,只要实现上述fuse_operations的部分函数即可,比较重要的像mkdir,read,open,write...因此在fuse的帮助下实现user态的文件系统,编码架构就非常清晰了,
给出需要使用的文件系统功能的函数指针,

static struct fuse_operations my_operations = {  
.getattr = my_getattr,  
.readdir = my_readdir,  
.open = my_open,  
.read = my_read,  
... ...
};  
定义完之后在main函数里面直接丢给fuse_main()即可。当然my_open,my_read之类的功能函数要自己实现好,最后完成后fusemount下就可以测试新创建的文件系统了。也有其他应用,比如让老内核通过fuse调用新内核下的文件系统等等。下一步要着眼的是项目所需要的功能,以此来选取fuse_operations中需要实现的函数,以及这些函数需要的coding skills,目前,看了几个利用fuse搭起来的fs源码,很多函数和宏定义都不理解其意。快过年了,导师仍然不待见,sigh...这阶段要复习下基础知识了,从ulk看起,os学的不理想。

from:http://hi.baidu.com/bulletup/blog/item/fa612c7052f823178701b0ac.html

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页