用户态文件系统fuse学习
FUSE概述
FUSE(用户态文件系统)是一个实现在用户空间的文件系统框架,通过FUSE内核模块的支持,使用者只需要根据fuse提供的接口实现具体的文件操作就可以实现一个文件系统。
在fuse出现以前,Linux中的文件系统都是完全实现在内核态,编写一个特定功能的文件系统,不管是代码编写还是调试都不太方便,就算是仅仅在现有传统文件系统上添加一个小小的功能,因为是在内核中实现仍需要做很大的工作量。在用户态文件系统FUSE出现后(2.6内核以后都支持fuse),就会大大的减少工作量,也会很方便的进行调试。编写FUSE文件系统时,只需要内核加载了fuse内核模块即可,不需要重新编译内核。
FUSE 特点
- 用户空间文件系统——类Unix OS的框架
- 允许非超户在用户空间开发文件系统
- 内核的API接口,使用fs-type操作
- 支持多种编程语言( c、c++、perl、java 等)
- 普通用户也可以挂载FUSE
- 不用重新编译内核
FUSE组成
fuse主要由三部分组成:FUSE内核模块、用户空间库libfuse以及挂载工具fusermount。
- fuse内核模块:实现了和VFS的对接,实现了一个能被用户空间进程打开的设备,当VFS发来文件操作请求之后,将请求转化为特定格式,并通过设备传递给用户空间进程,用户空间进程在处理完请求后,将结果返回给fuse内核模块,内核模块再将其还原为Linux kernel需要的格式,并返回给VFS;
- fuse库libfuse:负责和内核空间通信,接收来自/dev/fuse的请求,并将其转化为一系列的函数调用,将结果写回到/dev/fuse;提供的函数可以对fuse文件系统进行挂载卸载、从linux内核读取请求以及发送响应到内核。libfuse提供了两个APIs:一个“high-level”同步API 和一个“low-level” 异步API 。这两种API 都从内核接收请求传递到主程序(fuse_main函数),主程序使用相应的回调函数进行处理。当使用high-level API时,回调函数使用文件名(file names)和路径(paths)工作,而不是索引节点inodes,回调函数返回时也就是一个请求处理的完成。使用low-level API 时,回调函数必须使用索引节点inode工作,响应发送必须显示的使用一套单独的API函数。
- 挂载工具:实现对用户态文件系统的挂载
FUSE主要代码文件
in kernel:
- kernel/inode.c —> 主要完成fuse文件驱动模块的注册,提供对supper block的维护函数以及其它(驱动的组织开始文件)
- kernel/dev.c —> fuse 的(虚拟)设备驱动
- kernel/control.c —> 提供对于dentry的维护及其它
- kernel/dir.c —> 主要提供对于目录inode索引节点的维护
- kernel/file.c —> 主要提供对于文件inode索引节点的维护
in userspace:
- lib/helper.c —> “fuse_main()”调用的主入口
- lib/fuse_kern_chan.c—>主要实现fuse应用层访问(读写)fuse driver的功能
- lib/fuse_mt.c —> fuse 的mount管理
- lib/fuse.c —> lib库主框架文件,实现了主要框架及对”用户实现的文件系统操作代码”的封装
- lib/fuse_lowlevel.c –> 实现比较底层的函数封装,供fuse.c等使用
- lib/fuse_loop.c —> fuse lib循环监视”fuse driver”的通信缓存
- lib/fuse_loop_mt.c —> 同fuse_loop.c
- lib/fuse_session.c —> fuse会话管理
Fuse是怎么工作的(fuse-2.9)?
1. fuse库
- 1.在用户态程序调用fuse_main() (lib/helper.c)时,先调用fuse_setup_common()该函数先解析用户态程序传递过来的参数,然后调用fuse_mount_common()(该函数是fuse_kern_mount()函数的封装,lib/mount.c)。
fuse_main()是一个宏定义(include/fuse.h),如下:
#define fuse_main(argc, argv, op, user_data) \
fuse_main_real(argc, argv, op, sizeof(*(op)), user_data)
- 2.fuse_kern_mount()函数中调用fuse_mount_fusermount()使用socketpair()创建一个UNIX域套接字,然后使用创建子进程执行fusermount程序,将FUSE_COMMFD_ENV环境变量中套接字的一端传递给它。
- 3.fusermount(util/fusermount.c)确保fuse 模块已经被加载,然后打开/dev/fuse并通过一个UNIX套接字发送文件处理句柄。父进程等待子进程执行完毕回收,然后返回fuse_mount_fusermount()函数。
- 4.fuse_kern_mount()通过/dev/fuse返回文件句柄给fuse_kern_chan_new()负责处理内核数据,然后返回到fuse_mount_common()函数。
- 5.fuse_setup_common()函数调用fuse_new_common(lib/fuse.c),fuse_new_common()函数分配fuse数据结构,存储并维护一个文件系统数据镜像缓存cached,返回到fuse_main()。
- 6.最后,fuse_main()调用fuse_loop(lib/fuse.c)或者fuse_loop_mt()(lib/fuse_mt.c),这两个函数都可以从设备/dev/fuse读取文件系统调用,调用fuse_main()之前调用存储在fuse_operations结构体中的用户态函数。这些调用的结果回写到/dev/fuse设备(这个设备可以转发给系统调用)。
2.内核模块
内核模块由2个部分组成:
第一个是proc文件系统组件(在kernel/dev.c中);
第二个是文件系统调用(kernel/file.c、kernel/inode.c、kernel/dir.c)。
kernel/file.c、kernel/inode.c、kernel/dir.c中的所有系统调用要么调用request_send(),要么调用request_send_noreply()或者request_send_nonblock()。大部分都是调用request_send()函数,它添加请求到“list of request”结构体(fc->pending),然后等待一个响应。request_send_noreply()和request_send_nonblock()与request_send()函数相似,除了是非阻塞的和不响应一个回复。
kernel/dev.c中的proc文件系统组件响应文件IO请求,fuse_dev_read()处理文件读,并从请求列表结构体(list of requests)返回命令到调用程序。fuse_dev_write()处理文件写, 完成数据写并放入req->out结构体(它能返回系统调用通过请求列表结构体和request_send()函数),
用户进程和操作系统进行交互(read文件为例):
该fuse文件系统挂载在现有ext4文件系统之上.
1.一个用户进程发出read文件请求;
2.该请求被转换为一个内核系统调用,内核VFS层调用fuse文件系统内核模块;
3.fuse 内核模块通过/dev/fuse,将read请求传递到fuse 用户态进程;
4.fuse daemon根据用户实现的read接口,产生新的系统调用,最终调用ext4文件系统的read操作函数,从存储介质中提取读操作要求的数据(page cache中有,直接从其中获取,否则读磁盘);
5.内核将数据返回给fuse文件系统;
6.用户级文件系统再次调用内核操作,把数据返回给用户进程;
7.内核将数据传给用户进程完成操作。
库函数fuse_main()具体处理流程:
1.先打开设备文件/dev/fuse;
2.然后挂载FUSE文件系统;
3.产生FUSE文件系统指针;
4.初始化FUSE文件系统的操作函数集:
5.初始化信号处理函数集;
6.进入等待循环:
从设备文件/dev/fuse中读取来自内核模块的请求;
运行相应的操作函数,并获取返回结果;
将返回给内核的应答结果写入设备文件/dev/fuse中;
注意
fuse本质上(数据处理时)是处于现有文件系统之上的(具体实现是和现有文件系统处于同一个层次的),fuse不参与底层磁盘数据的存取,只负责处理对读取和写入的数据在逻辑上的操作而已。
安装使用fuse
软件包下载https://github.com/libfuse/libfuse/releases:
下载软件包,解压后,编译安装。
./configure
make
make install
解压后的目录中有名为example的目录,其中有fuse自带的几种fuse用户态实现例子,可以运行其进行测试。
fuse安装完后,该目录中的文件也已经编译成功,只需运行即可(目录dir为挂载点,挂载成功后,在该目录中对文件的操作就会调用fuse自己实现的操作函数):
//example/hello.c 部分代码,主要实现文件系统的取文件属性、打开目录、读文件、打开文件
static struct fuse_operations hello_oper = { //文件操作函数,为回调函数
.getattr = hello_getattr,
.readdir = hello_readdir,
.open = hello_open,
.read = hello_read,
};
int main(int argc, char *argv[])
{
return fuse_main(argc, argv, &hello_oper, NULL); //主函数,会调用文件操作结构体
}
ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ mkdir dir //创建挂载点
ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ ./hello dir //将hello fuse文件系统挂载在dir目录上
根据目前实现的四个功能进行测试如下:
ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ ls
hello
ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ cat hello
Hello World!
ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ ls -l hello
-r--r--r-- 1 root root 13 12月 31 1969 hello
ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ rm -fr hello
rm: cannot remove ‘hello’: Function not implemented
ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ touch test
touch: cannot touch ‘test’: Function not implemented
ty@ubuntu:~/program/fuse/fuse-2.9.6/example/dir$ mkdir test
mkdir: cannot create directory ‘test’: Function not implemented
由测试可以发现在dir目录中只能对文件进行实现的四个功能的操作,其他的操作都无法完成,会提示用户函数没有实现。
ty@ubuntu:~/program/fuse/fuse-2.9.6/example/$ dirfusermount -u dir //卸载fuse文件系统dir
用户态文件系统fuse学习相关推荐
- linux fuse安装脚本,Linux FUSE(用户态文件系统)的使用:用libfuse创建FUSE文件系统...
说明 FUSE 是Linux Kernel的特性之一:一个用户态文件系统框架,a userspace filesystem framework. 形象的说就是可以在用户态运行一个程序,这个程序暴露出一 ...
- 2022-06-06 FUSE用户态文件系统
目录 摘要: linux内核支持: 架构分析: 内核中的FUSE: fuse_i.h inode.c file.c dir.c dev.c 核心流程: hello_open hello_read 核心 ...
- 用户空间文件系统(FUSE)
女主宣言 今天小编为大家分享用户空间文件系统FUSE,文章从FUSE的架构,分析了各个部分的原理,并结合小编自身的使用,对FUSE进行了建议性的优化,希望能对大家有所帮助. PS:丰富的一线技术.多元 ...
- BlueStore——先进的用户态文件系统《一》
目录 为什么需要 BlueStore IO 放大 对象遍历 其他 BlueStore 介绍 逻辑架构 设计思想 总结 引言 分布式存储系统通过将数据分散到多台机器上来充分利用多台机器的资源提高系统的存 ...
- FUSE——用户空间文件系统
用户空间文件系统(Filesystem in Userspace,简称FUSE)是操作系统中的概念,指完全在用户态实现的文件系统. 目前Linux通过内核模块对此进行支持.一些文件系统如ZFS,glu ...
- linux 用户空间文件系统 filesystem in userspace fuse 简介
用户空间文件系统(Filesystem in Userspace,简称FUSE)是操作系统中的概念,指完全在用户态实现的文件系统.目前Linux通过内核模块对此进行支持.一些文件系统如ZFS,glus ...
- FUSE—用户空间文件系统
用户空间文件系统(Filesystem in Userspace,简称FUSE)是操作系统中的概念,指完全在用户态实现的文件系统.目前Linux通过内核模块对此进行支持.一些文件系统如ZFS,glus ...
- 趣谈Linux操作系统学习笔记:用户态内存映射:如何找到正确的会议室?(第25讲)...
一.mmap原理 在虚拟内存空间那一节,我们知道,每一个进程都有一个列表vm_area_struct,指向虚拟地址空间的不同内存块,这个变量名字叫mmap struct mm_struct {stru ...
- TP保护的研究和学习-用户态下调试附加篇(二)
TP保护的研究和学习-用户态下调试附加篇 引言: 本篇系列旨在研究学习腾讯保护系统的保护方案实现,文中尽量以"发现问题然后尝试解决问题"的模式来处理遇到的问题,此前网上有太多相 ...
最新文章
- 如何通过结构化智能体完成物理构造任务?| 技术头条
- 以后配置Nginx 用这款神器!
- python四大软件-PYPL 9月编程语言排行榜发布 Python一枝独秀
- flannel源码分析--newSubnetManager
- 新版手机浏览器_新版《野性的呼唤》IGN仅3分 烂番茄72% M站54分
- 微服务网关的设计与实现
- discuz中又拍云在ie8,chrome22下不能上传的问题
- 让开发人员变平庸的八个习惯,看看你中了几条
- 用得最多的altium版本_83版《神雕》有多猛?收视率破90%!金庸最满意的版本...
- linux mysql定时删除数据_让linux每天定时备份MySQL数据库并删除五天前的备份文件...
- mac securecrt程序无响应_Adobe庆祝Photoshop问世30周年 为Mac和iPad版本提供新功能
- sc.textFile()默认读取本地系统文件还是HDFS系统文件?
- 服务器内存条故障显示器,客户的电脑原故障是不开机,现在又变成蓝屏:变着法加钱就搞鬼...
- 为什么学习web前端,必须掌握JavaScript这门编程语言
- php 设置cors,php – 启用cors在.htaccess
- 移动警务综合应用平台(交警)解决方案
- java并发测试工具_Java并发测试工具类
- python爬取拉勾网_Python搭建代理池爬取拉勾网招聘信息
- 一起学libcef--正确关闭你创建的浏览器
- 5.10 自定义颜色至色板和全局色的使用 [Illustrator CC教程]
热门文章
- Lync 2013持久聊天迁移至Skype for Business
- Javascript的原型链
- html5 viewpor,FileViewPro
- python 空列表对象的布尔值_python – 从TensorFlow对象中检索数据 – 来自correct_prediction的布尔值列表...
- Javascript各种运算符第五课(小一节)
- linux buffer cache 过高_工作中经常用的linux命令 free
- 基于matlab的车牌识别系统设计错误,基于MATLAB的车牌识别系统设计
- idea怎么给方法快速添加注释_生完孩子胸部下垂怎么办?来看快速矫正的方法
- [PWA] Check Online Status by using the NavigatorOnLine API
- jiba中文分词原理