FUSE文件系统

【源码+文档】基于FUSE的简单文件系统 可以说FUSE其实是一个用来帮助我们实现文件系统的库,我们可以通过库里面的各种方法和它给出的框架,来实现一个用户空间上的文件系统,这个系统里面对文件的各种操作由我们自己编写相应的函数来实现。编写好以后,就要编译这个.c文件,然后用编译出来的文件,通过fusermount3把一个文件夹挂载到OS上面,OS会认为自己的系统上多了一个存储设备,这个设备就是我们编写的用户空间上的文件系统了,上面的所有操作都是在.c文件中实现好的,进行什么文件操作,就会调用我们编写的相应函数。运行相应的操作函数,并获取返回结果; 阅读详情

Fuse(filesystem in userspace),是一个用户空间的文件系统。通过fuse内核模块的支持,开发者只需要根据fuse提供的接口实现具体的文件操作就可以实现一个文件系统。由于其主要实现代码位于用户空间中,而不需要重新编译内核,这给开发者带来了众多便利。Google在Android 11上,为了实现scoped storage,也引入了fuse。下面我们从Fuse的架构设计以及具体的实现细节来谈一谈fuse文件系统。

一、 Fuse架构设计

图片摘自《To FUSE or Not to FUSE: Performance of User-Space File Systems》

Fuse包含一个内核模块和一个用户空间守护进程(下文称fuse daemon)。内核模块加载时被注册成 Linux 虚拟文件系统的一个 fuse 文件系统驱动。此外,还注册了一个/dev/fuse的块设备。该块设备作为fuse daemon与内核通信的桥梁,fuse daemon通过/dev/fuse读取fuse request,处理后将reply写入/dev/fuse。

上图详细展示了fuse的构架。当application挂在fuse文件系统上,并且执行一些系统调用时,VFS会将这些操作路由至fuse driver,fuse driver创建了一个fuse request结构体,并把request保存在请求队列中。此时,执行操作的进程会被阻塞,同时fuse daemon通过读取/dev/fuse将request从内核队列中取出,并且提交操作到底层文件系统中(例如 EXT4 或 F2FS)。当处理完请求后,fuse daemon会将reply写回/dev/fuse,fuse driver此时把requset标记为completed,最终唤醒用户进程。

二、 Fuse实现细节

下面我们基于Android 11 AOSP 以及 kernel4.19的开源代码,讨论一些fuse的实现细节,包括:fuse 用户空间流程、内核队列、/dev/fuse的读写流程等。

1. fuse用户空间流程

(1) fuse mount

Fuse的挂载通过mount函数,将指定的fuse_path挂载到/dev/fuse设备上。之后对于fuse_path下的文件操作,都会通过fuse文件系统,并通过/dev/fuse被fuse daemon读取处理。

(2) fuse thread

Fuse  daemon还会创建一个服务线程,基于libfuse库来处理文件操作请求。这里主要关注fuse_session_new和fuse_session_loop_mt。通过fuse_session_new在libfuse中注册了fuse daemon实现的fuse_lowlevel_ops,之后通过fuse的所有的文件操作,都会通过libfuse回调到fuse daemon进行处理。

fuse_session_loop_mt在libfuse中实现了一个多线程模式来读取请求,相比单线程,在请求处理上效率更高。

(3) libfuse

由fuse_session_loop_mt在libfuse中的调用流程如下:

这里我们关注两点:

a) splice实现内存零拷贝。在默认情况下,fuse daemon必须通过read()从/dev/fuse读取请求,通过write()将请求回复写入/dev/fuse。每次读写系统调用都需要进行一次内核-用户空间的内存拷贝。这样对读写的性能损耗十分严重,因为一次内存拷贝需要处理大量数据。为了缓解这个问题,fuse支持了Linux内核提供的 splice 功能。splice 允许用户空间在两个内核内存缓冲区之间传输数据,而无需将数据复制给用户空间。如果fuse daemon实现了write_buf()方法,则 FUSE 从/dev/fuse读取数据,并以包含文件描述符的缓冲区的形式将数据直接传递给此方法处理,从而省去了一次内存申请与拷贝。

b) 多线程模式。在多线程模式下,fuse  daemon以一个线程开始,如果内核队列中有两个以上的request,则会自动生成其他线程。默认最大支持10个线程同时处理请求。

2. fuse内核队列

图片摘自《To FUSE or Not to FUSE: Performance of User-Space File Systems》

 

fuse在内核中维护了五个队列,分别为:Backgroud、Pending、Processing、Interrupts、Forgets。一个请求在任何时候只会存在于一个队列中。

a) Backgroud:background 队列用于暂存异步请求。在默认情况下,只有读请求进入 background 队列;当writeback cache启用时,写请求也会进入 background 队列。当开启writeback cache时,来自用户进程的写请求会先在页缓存中累积,然后当bdflush 线程被唤醒时会下刷脏页。在下刷脏页时,FUSE会构造异步请求,并将它们放入 background 队列中。

b) Pending:同步请求(例如,元数据)放在 pending 队列中,并且pending队列会周期性接收来自background 的请求。但是pending队列中异步请求的个数最大为max_background(最大为12),当pending队列的异步请求未达到12时,background队列的请求将被移动到pending队列中。这样做的目的是为了控制pending队列中异步请求的个数,防止在突发大量异步请求的情况下,阻塞了同步请求。

c) Processing:当pending队列中的请求被转发到fuse daemon的同时,也被移动到processing队列。所以processing队列中的请求,表示正在被处理fuse daemon处理的请求。当fuse daemon真正处理完请求,通过/dev/fuse下发reply时,该请求将从processing队列中删除。

d) Interrupts:用于存放中断请求,比如当发送的请求被用户取消时,内核会发送一个Interrupts请求,来取消已被发送的请求。中断请求的优先级最高,Interrupts中的请求会最先得到处理。

e) Forgets:forget请求用于删除dcache中缓存的inode。

 

3. /dev/fuse 读写调用流程

Fuse driver加载过程中注册了对/dev/fuse的操作接口fuse_dev_operations。fuse_dev_do_read/fuse_dev_do_write分别对应fuse daemon从内核读取请求,以及处理完请求后写回reply的函数调用。我们分别看下具体的代码片段

当pending 、interrups、forgets队列都没有请求时,读进程进入休眠。一旦有请求到达,这个等待队列上的进程将被唤醒。Interrups 和 forgets的请求优先级高于pending队列。当请求的数据内容被拷贝至用户空间后,该请求会被移至processing队列,并且req->flags会保存当前请求的状态。

当fuse daemon处理完请求后,会将结果写回到/dev/fuse。写数据保存在struct  fuse_copy_state中,并且会根据unique id在fc(fuse_conn)中找到对应的req,并将写回的参数从fuse_copy_state拷贝至req->out。

 

最后我们以unlink为例,看下fuse整体是如何工作的:

图片摘自fuse内核官方文档

 

首先,fuse daemon会阻塞在读/dev/fuse,当app进程在fuse挂载点下面有新的文件操作(unlink),这时系统调用会调用fuse内核接口,并生成request,同时唤醒阻塞的fuse daemon。fuse daemon读到request后,在libfuse中进行解析,根据request的opcode来执行对应的ops,完成后会把处理结果返回给/dev/fuse。此时vfs调用阻塞的行为将被唤醒,最后返回vfs调用。

三、 总结

虽然Fuse简化了文件系统的实现,给开发者带来了便利。但是其额外的内核态/用户态切换带来的性能开销不能被忽视,所以fuse性能问题,一直是业界绕不开的话题。前面说到的splice、多线程、writeback cache都是为了改善其性能问题。后续,我们再具体谈谈fuse性能改善。

 

参考文献:

[1] Bharath Kumar Reddy Vangoor, Vasily Tarasov, Erez Zadok.To FUSE or Not to FUSE: Performance of User-Space File Systems. in Proceedings of the 15th USENIX Conference on File and Storage Technologies (FAST ’17), 2017 • Santa Clara, CA, USA

文件系统(十一)—fuse内核实现 用户文件系统会越来越广泛使用,目前andriod12中已经到了fuse的文件系统,Android 实现了自己的 FUSE 守护程序来拦截文件访问,实施额外的安全和隐私功能,并在运行时操作文件。 阅读详情

相关推荐

文件系统(十二)—图解如何使用fuse文件系统

我们真实的来看怎么实现一个简单的fuse文件系统,我们还是以之前的例子,对于用户空间需要实现基于libfuse实现的应用程序hello

奇小葩 2776

FUSE简单了解

FUSE(filesystem in userspace)是一个用户态文件系统框架。由内核模块(fuse.ko)、用户态库(libfuse.*)和挂载工具组成(fusermount)其中内核fuse.ko用于承接vfs下来的IO请求,封装成FUSE数据包转发给用户态中libfuse进行解析转给hello程序。文件系统通常工作在内核态,而fuse允许文件系统在用户态实现,这使得文件系统实现更加灵活。对于挂载hello程序实现的fuse在/tmp/fuse,执行。但内核态文件系统还是有很多优点。

iUcool的博客 1854

基于fuse的文件系统导出NFS的问题

FUSE(The Filesystem in Userspace)介绍: 像ext4,xfs等本地文件系统都是在linux内核代码中,并且运行在内核态,如果要在内核中定制化开发一个文件系统,对程序员的能力要求是比较高的。fuse为用户态文件系统提供了与VFS交互的通道,fuse分为内核态fuse模块,用户态libfuse和fusemount工具。其中内核态fuse模块是其最核心的功...

qq_38444220的博客 2869

FUSE源码剖析

FUSE源码剖析 Posted by  Wang Alan  on 2013 年 6 月 28 日 Tweet 8  1. 前言        本文是对FUSE-2.9.2源码的学习总结。FUSE代码在用户空间和内核空间都有运行,为了突出重点,先简要描述了在基于FUSE的用户空间文件系统中执行write操作的一般

Fybon的专栏 2754

IAR编译相同工程生产hex文件checksum不一致问题

IAR Checksum

xqw19891201的博客 1382

学习笔记( 11 ) - 解决:finalshell连接虚拟机(ubuntu)超时,主机ping不通虚拟机,主机没有VMnet8网卡, Connection refused: connect

解决:finalshell连接虚拟机(ubuntu)超时,主机ping不通虚拟机,主机没有VMnet8网卡, Connection refused: connect

烟溪彭于晏的博客 2万+

用户态文件系统fuse学习

FUSE(用户态文件系统)是一个实现在用户空间的文件系统框架,通过FUSE内核模块的支持,使用者只需要根据fuse提供的接口实现具体的文件操作就可以实现一个文件系统。

ty_laurel的博客 2万+

STM32CubeMx搭建LWIP程序

  使用STM32CubeMx5.21,在stm32f745平台上搭建ethernet通信程序,PHY选用KSZ8081RNB。(LAN8742/DP83848使用一样) 1、系统时钟设置   RCC设置,勾选外部高速时钟源。   系统时钟配置。写入外部晶振频率、HSE提供PLCCLK、HCLK,其他参数自动生成。 2、ETH设置   勾选设置NVIC。   根据硬件设置对应GPIO引脚。   参数设置默认   根据硬件设置PHY地址,其他参数默认。 3、LWIP设置   勾选使能,通用参数设置

Gandalf94的博客 3237

FUSE,从内核到用户态文件系统的设计之路

FUSE(Filesystem in Userspace)是一个允许用户在用户态创建自定义文件系统的接口,诞生于 2001 年。FUSE 的出现大大降低了文件系统开发的门槛,使得开发者能够在不修改内核代码的情况下实现创新的文件系统功能。JuiceFS 就是基于 FUSE 构建的高性能分布式文件系统,充分发挥了 FUSE 的灵活性和扩展性。

JuiceFS的博客 1580

基于深度学习 YOLOv11 的快递包裹检测系统(Python + PySide6 界面 + 训练代码)

成为亟需优化的重要环节。随着电子商务的快速发展,物流行业面临着越来越大的压力,为了解决这些问题,我们提出了一种。目标检测算法,实现快递包裹的。的界面,供用户进行实时监控。本项目的主要目标是利用。

斌擎科技 762

Orange3实战教程:转换---预处理

部件提供了多种预处理方法,这些方法可以在单个预处理流程中组合使用。某些方法也可作为独立部件提供,支持更高级的技术和参数调整。连接到测试与评分:在交叉验证的每个批次中应用预处理器,随后学习器的预处理器会作用于预处理后的子集。连接到学习器:覆盖学习器的默认预处理流程,仅应用自定义流程(各学习器的默认步骤详见其文档)。直接连接到原始数据并输出预处理后的数据集,可能导致模型过拟合。:从原始数据中随机选择固定数量或百分比的特征,主要用于高级测试或教学用途。的预处理器输入,同时传入数据和学习器(如。

err2008的专栏 147

Fuse 文件系统

例如 #ifdef linux 交叉编译的话需要修改5. 部分函数未定义android bionic c库未定义,尝试自己定义或者换一个接口。

Jeff_的博客 2457

YOLOv9电力巡检实战:绝缘子破裂/鸟巢识别+无人机自动定位

摘要:本文聚焦电力输电线路巡检的效率与安全痛点,提出基于YOLOv9与无人机的智能巡检解决方案。针对绝缘子破裂、鸟巢等高危缺陷,通过“无人机改装-模型训练-缺陷识别-工单生成”四阶段工程落地流程,实现全自动化巡检。系统采用大疆M300无人机搭载RTK模块与Jetson边缘计算盒,结合改进YOLOv9模型实时识别5类缺陷,通过4G传输将GPS定位与缺陷数据同步至工单系统。实测表明,该方案巡检效率达50公里/天(较人工提升10倍),缺陷发现率95%(提升40%),事故预防率98%。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1509

Android之FUSE文件系统

FUSE主要实现代码位于用户空间中,而不需要重新编译到内核,用户空间开发者可以通过FUSE的接口直接访问内核空间,不需要了解文件系统的内幕和内核模块编程的知识,这给用户空间开发者带来了众多便利。是的,该进程在ZFUSE挂载时由libfuse库代码中创建,作用是读取管道文件消息并根据消息的操作数来执行对应操作,在这里解析到的是FUSE_CREATE操作数,对应libfuse库中的fuse_lib_create函数。并且,用户空间下调试工具丰富,出问题不会导致系统崩溃,开发难度相对较低,开发周期较短。

zwylovemzj的博客 3015

Rockchip 自定义vendorstorages数据再u-boot通过cmdline给kernel传递数据

本文介绍通过vendorstorages,允许保存和读取自定义数据。通过在U-Boot中读取这些数据并将其添加到cmdline中,将这些数据传递给Linux内核,实现了一个灵活的方式来配置和定制系统的需求。

我其实什么都不会 1816

万字长文,YOLOv8 yaml 文件解析 | 一文搞定 YOLOv8 分类任务,检测任务,分割任务,关键点任务

YOLOv8 yaml 文件解析 | 一文搞定 YOLOv8 分类任务,检测任务,分割任务,关键点任务

Coding... 1万+

基于Fuse的最简单的文件系统

首先我们介绍一下什么是文件系统。文件系统是一个将硬盘的线性地址转换为层级结构的软件系统,其核心是给用户呈现层级结构的目录树(如下图所示)。在文件系统中有两个非常重要的概念,一个是文件,另外一个是目录(或者文件夹)。其中目录是一个容器,可以存储文件或者目录(称为子目录)。文件是存储数据的实体,我们的数据都是以文件的形态进行存储的。文件有很多种类,比如视频文件、音频文件、Word文档和文本文件等等。

shuningzhang的专栏 1689

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

基于FUSE的简单文件系统

基于FUSE的简单文件系统

825

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Linux下使用fuse编写自己的文件系统

一、前言 近几天调研了一下fuse编写文件系统的方法,先尝试拿fuse写一套类似tmpfs的简易文件系统,文件信息都保留在内存中。文件系统需要一个数据结构来管理文件节点 inode,正好《c语言实现map-使用内核红黑树》一文将rbtree结构拿出来了可以用上。 目标:支持文件读写操作:echo、cat;支持目录操作ls、mkdir、cd。 二、知识准备 FUSE(Filesystem i...

staticnetwind的专栏 1万+

FUSE文件系统介绍

文章目录导引:Fuse简介一、 Fuse架构设计二、 Fuse实现细节1. fuse用户空间流程2. fuse内核队列3. /dev/fuse 读写调用流程三、 总结 导引:Fuse简介 Fuse(filesystem in userspace),是一个用户空间的文件系统。 通过fuse内核模块的支持,开发者只需要根据fuse提供的接口实现具体的文件操作就可以实现一个文件系统。由于其主要实现代码位于用户空间中,而不需要重新编译内核,这给开发者带来了众多便利。Google在Android 11上,为了实现sc

流楚丶格念的博客 8524

FUSE 文件系统和 libfuse 介绍

前言这几天为了解决浏览器产品中的一个问题,研究了一下 FUSE(Filesystem in Userspace)。通常,应用程序开发只需要使用系统 API 进行文件读写操作,不需要了解文件系统的细节。在 Chromium 中为了实现跨平台,甚至对各操作系统的文件 API 进行了封装。在代码中使用封装 API,都不需要了解各操作系统所提供的文件系统 API。但由于我们的浏览器产品中使用了 FUSE ...

云水木石 2237

用户态文件系统fuse

FUSE(Filesystem in Userspace)是一种让非特权用户在用户空间实现文件系统的机制。文件系统的逻辑实现不在内核态运行,而是在用户态运行,通过与内核中的 FUSE 模块通信实现文件操作的响应。

congchp的博客 1148

用fuse构建自己的文件系统(指南篇)

0.适合学完操作系统课程还未做过课设的同学阅读 在优快云上搜索同名文章,大多是一些fuse的介绍,以及各自的复杂fuse和RPC对接实现,初学来看可能还是不知道怎么动手写代码,所以写点自己的理解。本文基于内存文件系统来写,无权限控制,尽可能简化文件系统功能来快速做一个demo。 本科时候用C写过一个完整的文件系统小系统(./a.out执行后才进入文件系统),其功能大致可以分为下图几个部分。 ...

github_36652477的博客 3315
上一篇: 红黑树原理浅谈(附Linux内核源码注释)
下一篇: 好网站,可以看各种数据结构的动态
废言Pro
博客等级 码龄16年 1092粉丝 142原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值