FUSE(Filesystem in Userspace)是一个允许非特权用户在用户空间创建自己的文件系统的工具.
在fuse出现以前,Linux中的文件系统都是完全实现在内核态, 而内核下定制开发文件系统难度较高. 除此之外用户空间下调试工具/第三方库丰富,出问题不会导致内核崩溃,开发难度相对较低. 简而言之, fuse 有如下三个主要优势:
FUSE 由内核部分和用户级守护程序组成.内核部分作为 Linux 内核模块实现,加载时会向 Linux 的 VFS 注册文件系统驱动程序.此 Fuse 驱动程序充当由不同用户级守护程序实现的各种特定文件系统的代理.
除了注册一个新的文件系统之外,FUSE的内核模块还注册一个/dev/fuse
块设备.该设备充当用户空间 FUSE 守护进程和内核之间的接口.一般来说,守护进程从 /dev/fuse
读取 FUSE 请求,处理它们,然后将回复写回 /dev/fuse
.
下图展示了 FUSE 的高层架构.当用户应用程序在已安装的 FUSE 文件系统上执行某些操作时(黄色部分, 比如 ls), VFS 会将操作路由到 FUSE 的内核驱动程序(蓝色部分). 由驱动程序分配一个FUSE请求结构并将其放入FUSE队列中. 然后 FUSE 的用户级守护进程(绿色部分)通过读取 /dev/fuse
从内核队列中选取请求并处理该请求.
因此 FUSE 主要有如下三部分组件
提供的函数可以对fuse文件系统进行挂载卸载、从linux内核读取请求以及发送响应到内核.
当FUSE的内核驱动程序与用户空间守护进程通信时,它形成一个FUSE请求结构.请求根据其传达的操作而具有不同的类型. 下表列出了所有 43 种 FUSE 请求类型,按语义分组. 大多数请求都直接映射到传统的 VFS 操作:
大部分接口和内核 VFS 的 struct file_operation
接口含义相似, 值得一提的有如下的一些请求类型
在文件系统安装过程中,内核会生成INIT请求.这个请求的目的是让用户空间与内核进行协商,以确定运行的协议版本;相互支持的功能集,例如READDIRPLUS或FLOCK支持;各种参数设置,如FUSE预读大小和时间粒度.
用户可以在此时完成系统的初始化, 比如 superblock, gdt 的预读取等等
与INIT请求相对应,DESTROY请求在文件系统卸载时由内核发送.守护进程在接收到DESTROY请求时,需要执行必要的清理工作.此后,内核将不再发出任何请求,从/dev/fuse读取的数据将返回0,这将导致守护进程正常退出.
如果内核不再需要任何先前发送的请求(例如,当在READ上阻塞的用户进程终止时),它会发出INTERRUPT请求.每个请求都有一个唯一的序列号,INTERRUPT请求使用该序列号来识别需要中断的请求.序列号由内核分配,并在用户空间回复时用于定位已完成的请求.
当从dcache中删除一个inode时,内核将FORGET请求传递给用户空间守护进程,守护进程可以选择释放任何相应的数据结构.BATCH FORGET允许内核通过单个请求忘记多个inode.
当内核评估用户进程是否有权访问文件时,它会生成ACCESS请求.通过处理此请求,FUSE守护程序可以实现自定义权限逻辑.然而,通常用户使用默认权限选项安装FUSE,该选项允许内核根据文件的标准Unix属性(所有权和权限位)授予或拒绝对文件的访问.在这种情况下,不会生成ACCESS请求.
当程序触发文件系统接口并生成 FUSE 请求之后会进入 FUSE 的多级队列
上图展示了 FUSE(Filesystem in Userspace)的多级队列组织结构.FUSE 维护了五个不同的队列,每个请求在任何时候只属于一个队列.
/dev/fuse
读取时,会首先从待处理队列中获取请求.bdflush
线程异步刷新脏页.这些异步写请求随后被放入后台队列,并逐渐移入待处理队列.队列的组织方式允许 FUSE 根据请求的类型和优先级有效地管理请求处理.例如,中断请求和遗忘请求可以快速处理,以避免阻塞更重要的操作.同时,通过限制待处理队列和处理队列中的异步请求数量,FUSE 可以避免因大量后台请求而延迟重要的同步请求.
总体而言, FUSE 的完整工作流程如下所示
mount.fuse
或fusermount
)发出指令,请求挂载一个FUSE文件系统到特定的目录(挂载点)./dev/fuse
),用于后续的用户空间通信./dev/fuse
设备文件与内核进行交互.open
)、读取(read
)、写入(write
)、列出目录内容(readdir
)等.open
, read
, write
等系统调用来访问挂载点下的文件时,这些调用首先到达内核的VFS层./dev/fuse
设备文件发送到用户空间./dev/fuse
回传给内核模块.在Linux上,可以通过包管理器安装FUSE.如在Ubuntu上,可以使用以下命令安装:
sudo apt-get install fuse
在macOS上,可以使用Homebrew安装:
brew install osxfuse
fusermount
命令挂载文件系统.fusermount -u /mount/point