Fuse学习

注意
本文最后更新于 2024-01-20,文中内容可能已过时。

原文链接:https://ovea-y.cn/fuse_simple/

什么是Fuse?

Fuse是一个用户空间文件系统的运行框架。它由一个内核模块(fuse.ko)、一个用户空间的库(libfuse.*)和一个挂载工具(fusemount)组成。

Linux的文件系统都是运行在内核态的,因此如果想实现一个新的文件系统,就需要让其运行在Linux Kernel中。 Fuse,即implementing filesystems in user space,在用户空间实现文件系统。 有了Fuse之后,开发者就可以在用户态开发自己的文件系统,相比于必须要运行在内核态,在用户态开发文件系统更好调试,并且不会导致Kernel崩溃,可以大大地缩短开发周期。

Fuse的文件系统类型

这是最常用的挂载Fuse文件系统的方法。mount系统调用的第一个参数可能包含任意字符串,内核不会去解析这个字符串。 Untitled Untitled 1

基于块设备的文件系统。mount系统调用的第一个参数将被解释为块设备的名称。 Untitled 2

jsx

static struct fuse_chan *try_fuse_mount(char *mount_point)
{
    struct fuse_chan *fc = NULL;
    struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);
    /* The fuse_mount() options get modified, so we always rebuild it */    if ((fuse_opt_add_arg(&margs, "simpleFS") == -1 ||
         fuse_opt_add_arg(&margs, "-o") == -1 ||
         fuse_opt_add_arg(&margs, "fsname=/dev/sda2,blkdev,attr_timeout=600,entry_timeout=600") == -1)) {
        printf("Failed to set FUSE options.\n");
        goto free_args;
    }
    fc = fuse_mount(mount_point, &margs);
free_args:
    fuse_opt_free_args(&margs);
    return fc;
}

当时用fuseblk模式时,FUSE会注册块设备的操作函数。

一些定义

一种特殊的文件系统,其中数据和元数据由普通用户空间进程提供。 该文件系统可以通过内核接口来进行访问。

提供文件系统数据和元数据的进程。

由非root或其他高权限用户装载的用户空间文件系统。 文件系统守护进程以当前用户的权限运行。

Untitled 3 Untitled 4 Untitled 5

文件系统守护进程与内核的链接在守护进程死亡或文件系统卸载之前都会一致存在。

文件系统架构

Flowchart

VFS

VFS是Linux内核的子系统之一,它为用户程序提供文件和文件系统操作的统一接口,屏蔽不同文件系统的差异和操作细节。借助VFS可以直接使用open()、read()、write()这样的系统调用操作文件,而无须考虑具体的文件系统和实际的存储介质。

在对一个块设备进行mount的时候,实际上就是构建vfsmount、dentry、inode的过程。 其中inode结构的初始化非常重要,其存储的address_space、inode_operations、file_operations函数指针会初始化为对应文件系统的函数。因此在对文件进行访问的时候,只要找到了inode,就能知道这个文件存放在什么类型的文件系统中。 例如以下是Ext4定义的一些操作:

jsx

// kernel/fs/ext4/file.c
const struct file_operations ext4_file_operations = {
    .llseek     = ext4_llseek,
    .read_iter  = ext4_file_read_iter,
    .write_iter = ext4_file_write_iter,
    .iopoll     = iomap_dio_iopoll,
    .unlocked_ioctl = ext4_ioctl,
#ifdef CONFIG_COMPAT    .compat_ioctl   = ext4_compat_ioctl,
#endif
    .mmap       = ext4_file_mmap,
    .mmap_supported_flags = MAP_SYNC,
    .open       = ext4_file_open,
    .release    = ext4_release_file,
    .fsync      = ext4_sync_file,
    .get_unmapped_area = thp_get_unmapped_area,
    .splice_read    = generic_file_splice_read,
    .splice_write   = iter_file_splice_write,
    .fallocate  = ext4_fallocate,
};
const struct inode_operations ext4_file_inode_operations = {
    .setattr    = ext4_setattr,
    .getattr    = ext4_file_getattr,
    .listxattr  = ext4_listxattr,
    .get_acl    = ext4_get_acl,
    .set_acl    = ext4_set_acl,
    .fiemap     = ext4_fiemap,
    .fileattr_get   = ext4_fileattr_get,
    .fileattr_set   = ext4_fileattr_set,
};

Fuse的工作原理

完整的fuse功能包括:

  1. 用户态customize文件系统
  2. 用户态fuse库(libfuse)
  3. 内核支持(fs/fuse/*)

他们的核心功能就是封装和解析fuse的协议。 Fuse在接到用户发出的请求之后,会使用FUSE协议与用户空间的文件系统通信(比如可以依赖libfuse来解析接收到的的FUSE协议),用户空间文件系统在接收到数据,并且完成自己像完成的功能之后,再通过FUSE协议将结果通过FUSE发回给用户。

简单使用Fuse

Recovery对Fuse的使用

Flowchart-2

附录

  • VFS是一个抽象层
  • VFS是Linux一切皆是文件的基石
  • Linux并未定义什么是文件系统,这个由设计者实现
  • 这是一个虚拟文件系统,Linux定义了hooks,开发文件系统的人可以在其中挂起自己需要的文件系统。
  • Linux的虚拟文件系统没有默认实现,它的功能完全是由文件系统的实现者决定的。 Flowchart-3

VFS的工作方式 Flowchart-4

什么是文件系统

  • Linux长期以来一直将文件系统定义为组织成目录、子目录和文件的数据的体系结构集合
  • Linux同样需要文件系统实现下列接口
    • open()
    • read()
    • write()
    • close() Untitled 6

/proc files

  • 在没有访问这个目录的文件时,它们实际上并不存在
  • 他们实际上是共享内存(共享内存对象),没有文件I/O操作
  • procfs提供了一个Linux内核状态的快照,以及在进程在用户空间的控制情况。
  • 在这里面可以看到中断、虚拟内存和调度程序的信息
  • 在/proc/sys可以看到从sysctl.conf产生的设置 Untitled 7 Sys
  • sys文件系统与proc不同,它包含实际可读写的文件
  • sys中的文件称为kobjects
  • 系统服务作为 kobjects 的引用计数器
  • 当计数器为零时,内核将删除kobject并回收它使用的任何资源
  • sys被称为用户空间的ABI(Application Binary Interface)

参考文献

https://github.com/libfuse/libfuse

https://en.wikipedia.org/wiki/Filesystem_in_Userspace

https://zhuanlan.zhihu.com/p/106719192

https://www.jianshu.com/p/c2b77d0bbc43

https://www.shuzhiduo.com/A/rV57O8p95P/

(24条消息) 用户态文件系统fuse学习_ty_laurel的博客-CSDN博客_fuse文件系统

Linux FUSE(用户态文件系统)的使用:用libfuse创建FUSE文件系统By李佶澳 (lijiaocn.com)

The Linux Kernel Archives (推荐,文档中讲的很清楚,在这里可以知道Fuse有自挂载和块设备挂载两种使用方式。文档中说最常用的是挂载Fuse自身我一开始还不知道是什么意思,直到看了NTFS-3G的源码)

https://github.com/lxc/lxcfs

https://github.com/Thorsten-Sick/vdfuse

自制文件系统 — 02 FUSE 框架,开发者的福音 - 知乎 (zhihu.com)

https://www.cnblogs.com/johnnyflute/p/3547384.html

https://docs.oracle.com/cd/E19253-01/819-7057/block-34861/index.html

https://www.youtube.com/watch?v=J4qWNNISdJk

SUSE Linux Enterprise Server 15 SP1: 第 20 章 使用 FUSE 访问文件系统 (管理指南)

UDEV

https://www.cnblogs.com/fah936861121/p/6496608.html

SUSE Linux Enterprise Server 15 SP1: 第 22 章 使用 udev 进行动态内核设备管理 (管理指南)

https://icefrozen.github.io/article/openerating-learning-vfs-1/

APFS

https://www.zixundingzhi.com/all/10b8152c87ef4aa2.html

F2FS

https://kknews.cc/zh-hk/news/gmn9mom.html

NTFS-3G (特别感谢NTFS-3G的代码,让我搞清楚了FUSE自身挂载和FuseBLK挂载的区别,网上完全没有任何教程讲解如何使用FuseBLK!!!包括各个论坛,还有Youtube,bilibili各个地方都没有!只讲了如何让FUSE自挂载,根本就不是我想的那种自制文件系统!不能处理外部磁盘的数据算什么文件系统!(特指一般认为的那种系统))

**https://github.com/tuxera/ntfs-3g**

FUSE

https://blog.csdn.net/u014104588/article/details/105271209

使用 fuse 编写文件系统 (1) – O 的笔记

https://github.com/baz1/SimpleFuse

https://github.com/andrinux/PCFS

原文链接:https://ovea-y.cn/fuse_simple/

相关内容