没有合适的资源?快使用搜索试试~ 我知道了~
×−−FUSE用户空间文件系统BHARATHKUMAR REDDY VANGOOR,Avere Systems,Inc.普拉夫·阿加瓦尔、马努·马修、阿伦·拉玛钱德朗和斯瓦米纳坦·西瓦拉曼,石溪大学VASILY TARASOV,IBM研究院-AlmadenEREZ ZADOK,石溪大学传统上,文件系统是作为操作系统内核的一部分实现的,操作系统内核为程序员提供了一组有限的工具和设施。随着文件系统复杂性的增长,许多新的文件系统开始在用户空间中开发。低性能被认为是用户空间文件系统的主要缺点,但这个问题的程度从未被系统地探讨过。因此,用户空间文件系统的主题仍然是相当有争议的:虽然有些人认为用户空间文件系统是一个“玩具”,不能在生产中使用,但其他人则在用户空间中开发成熟的生产文件系统。在本文中,我们分析了一个著名的用户空间文件系统框架,FUSE,Linux的设计和实现。我们描述了它的性能和资源利用率为广泛的工作负载。我们使用在两种不同硬件配置上使用Filebench生成的45种不同工作负载,通过各种装载和配置选项展示FUSE性能和资源利用率。我们对FUSE进行了检测,以提取有用的统计数据和跟踪信息,这有助于我们分析其性能瓶颈并展示我们的分析结果。我们的实验表明,根据工作负载和所使用的硬件,性能下降(吞吐量)造成的FUSE可以完全察觉或高达83%,即使在优化;和lasting的FUSE文件系统操作可以从零增加到4时,COM-扩展到Ext4。在资源利用率方面,与Ext4相比,FUSE可以将相对CPU利用率提高31%,未充分利用磁盘带宽高达80%,尽管对于许多数据密集型工作负载,其影响在统计上无法区分。我们的结论是,用户空间文件系统确实可以用于生产(非CCS概念:·一般和参考→测量;性能;·软件及其工程→文件系统管理;软件性能;附加关键词和短语:用户空间文件系统,Linux FUSE这项工作之所以成为可能,部分要归功于Dell-EMC、IBM和IBM的支持; NSF授予CNS-1251137、CNS- 1302246、CNS-1305360和CNS-1622832;以及ONR授予12055763。作者地址:B。K. R. Vangoor,P. Agarwal,M.马修,A. Ramachandran和S. Sivaraman,336 New ComputerScience , Stony Brook University , Stony Brook , NY 11794-2424 , USA; 电 子 邮 件 : vangoor. gmail.com ,{praagarwal , manmathew}@cs.stonybrook.edu , {arunrm87 , sswaminathan92}@gmail.com; V. Tarasov , IBMResearch - Almaden,650 Harry Road,San Jose,California 95120-6099,USA;电子邮件:vtarasov@us.ibm.com; E.Zadok,349新计算机科学,石溪大学,石溪,纽约11794-2424,美国;电子邮件:ezk@cs.stonybrook.edu。允许免费制作本作品的全部或部分的数字或硬拷贝,以供个人或课堂使用,前提是制作或分发副本的目的不是为了盈利或商业利益,并且副本的第一页上有本声明和完整的引用。必须尊重作者以外的其他人拥有的本作品组件的版权。允许使用学分进行摘要。以其他方式复制、重新发布、在服务器上发布或重新分发到列表中,需要事先获得特定许可和/或付费。从permissions@acm.org请求权限。© 2019版权归所有者/作者所有。授权给ACM的出版权。1553-3077/2019/05-ART15 $15.00https://doi.org/10.1145/3310148ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月15十五:B. K. R. Vangoor等人ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月×ACM参考格式:Bharath Kumar Reddy Vangoor,Prafful Agarwal,Manu Mathew,Arun Ramachandran,SwaminathanSivara-man,Vasily Tarasov,and Erez Zadok.2019. FUSE用户空间文件系统的性能和资源利用率。ACM Trans. 存储15,2,第15条(2019年5月),49页。https://doi.org/10.1145/33101481介绍文件系统是应用程序访问其数据的最古老、可能也是最常见的接口之一。虽然在基于微内核的操作系统(OS)的年代,一些文件系统是在用户空间中实现的[1,29],但现状总是将文件系统作为单片OS内核的一部分来实现[12,37,51]。内核空间实现避免了在内核和用户空间守护进程(FUSE守护进程)之间传递请求的潜在高开销-用户空间和微内核实现固有的通信[15,27]。随着时间的推移,用户空间文件系统(尽管可能并不完全可靠)逐渐回到了当今的存储系统中。近年来,用户空间文件系统越来越受欢迎。有助于证明和支持这一趋势的一些迹象和指标如下:(1) 在基本文件系统之上添加专门功能的许多用户空间可堆叠文件系统获得了普及(例如,重复数据删除和压缩文件系统[32,48])。(2) 在学术研究和高级开发中,像FUSE这样的用户空间文件系统框架成为实验文件系统设计新方法的事实标准[8,17,28,58]。(3) 几个现有的内核级文件系统被移植到用户空间(例如,[62],[42])。有些人试图将部分文件系统作为专用解决方案[49,60]或移植到Windows [2]。(4) 也许最大的认可,越来越多的公司依赖于用户空间实现其存储产品:IBM一些在用户空间中实现文件系统,使用Google Drive,Amazon S3 [45]和DropBox [38]等服务将数据在线存储在云中。虽然用户空间文件系统并没有完全取代内核级文件系统,而且现在假设它是不正确的,而且还为时过早,但用户空间文件系统无疑占据了越来越多的利基市场。客户不断要求存储解决方案提供新功能(快照、重复数据删除、加密、自动分层、复制等)。供应商通过发布复杂性大大增加的新产品来回应这一需求。例如,当表示为代码行(LoC)时,最新的Btrfs版本包含超过85,000个LoC-至少比经典的Ext 3文件系统多5个LoC(大约15,000个LoC,包括日志代码)。对于现代分布式文件系统,特别是支持多平台的文件系统,LoC计数可以达到数百万(例如,IBM随着软件定义存储(SDS)[13]范例的不断出现,代码量和存储软件的复杂性只会增加。文件系统复杂性的增加是用户空间文件系统日益流行的一个主要因素。用户空间是开发、移植和维护代码的友好环境。NetBSDFUSE用户空间文件系统十五:ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月[40 ]第40段。出现了许多用于编写用户空间文件系统的框架[3,5,6,10,21,35,36]。我们现在讨论用户空间文件系统近年来越来越受欢迎的一些原因:(1) 发展容易。开发人员的工具箱现在包括许多用于跟踪、调试和分析用户程序的用户空间工具。意外的用户级错误不会使整个系统崩溃,也不需要长时间的重新启动,而是生成有用的核心内存转储,同时程序可以很容易地重新启动以进行进一步的调查。在用户空间中有很多有用的库开发人员不仅限于少数面向系统的编程语言(例如,但是可以很容易地使用几种更高级的语言,每种语言都最适合它的目标。(2) 便携性。 对于需要在多个平台上运行的文件系统,在用户空间开发可移植代码,而不是在内核中。这可以在分布式文件系统的情况下认识到,其客户端通常在多个操作系统上运行[60]。例如,如果文件系统最初是在用户空间开发的,那么Unix文件系统可以在Windows下轻松访问。(3) 图书馆. 在用户空间中有大量的库,在那里可以更容易地尝试新的和更有效的算法,用于实现文件系统,以提高性能。例如,预测预取可以使用AI算法来适应特定用户(4) 现有的代码和用户基础。 有更多的开发人员可以随时编写代码在用户空间中比在内核中,并且对于新手来说,入口栏要低得多当然,在用户空间可以做的一切都可以在内核中实现。而是为了保持开发的可伸缩性和文件系统的复杂性,许多公司更喜欢用户空间实现。用户空间文件系统的回归越明显,用户空间文件系统的支持者和反对者之间的争论就越激烈[33,57,59]。虽然有些人认为用户空间文件系统只是一个玩具,但其他人使用它们开发真正的生产系统。Red HatStorage官方博客中题为“Linus Torvalds doesn 't understand user-space filesystems”的文章争论集中在两个权衡因素上:(1)用户空间实现带来的性能开销有多大,(2)在用户空间中开发有多容易。 开发的易用性是高度主观的,很难形式化,因此很难评估;但是性能有几个定义良好的度量标准,可以系统地研究。奇怪的是,很少有关于用户空间文件系统框架性能的文章。在本文中,我们使用最常见的用户空间文件系统框架FUSEfor Linux,并描述它导致的性能下降及其资源利用率。我们首先详细解释FUSE(1) 关于FUSE内部结构的公开信息很少(2) FUSE(3) 随着用户空间文件系统和FUSE的普及,对它们的实现的详细分析对于至少两个群体变得很有价值:(a)工业中的工程师,因为他们设计和构建新系统;以及(b)研究人员,因为他们使用FUSE来对新解决方案进行原型设计;最后,(4) 理解FUSE十五:4B. K. R. Vangoor等人ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月××我们使用FUSE开发了一个简单的直通可堆叠文件系统,称为StackFS,我们将其置于Ext4之上。复杂的生产文件系统通常需要高度的灵活性,因此使用FUSE的低级API。由于复杂的文件系统是我们的主要关注点,我们使用FUSE的低级API实现了Stackfs。这也避免了高级API增加的开销.我们使用在不同硬件上运行的各种微和宏工作负载,评估了StackFS与原生Ext4相比的性能。此外,我们还测量了由FUSE引起的CPU利用率的增加。我们的研究结果表明,根据工作负载和使用的硬件,FUSE可以执行与原生Ext4文件系统一样好;但在最坏的情况下,FUSE的执行速度可能比底层Ext4文件系统慢3。对于最不友好的工作负载rnd-wr-32 th-1f,FUSE可能比Ext4多消耗18个CPU周期:在6%到24%之间。接下来,我们为FUSE设计并实现了一个丰富的仪器系统,使我们能够进行深入的性能分析。提取的统计数据适用于任何基于FUSE的系统。我们公开发布了我们的代码,可以在以下存储库位置的主GIT分支中找到,所有这些都可以从http://www.filesystems.org/fuse访问:(1) FUSE内核工具:https://github.com/sbu-fsl/fuse-kernel-instrumentation.git(2) FUSE库工具:https://github.com/sbu-fsl/fuse-library-instrumentation.git(3) 工作负载、结果和可堆叠文件系统实施:https://github.com/sbu-fsl/fuse-stackfs.git有关该代码的其他信息可以在上述链接http://www. filesystems.org/fuse/网站。然后,我们使用这种检测来识别FUSE中的瓶颈,并解释为什么它对某些工作负载表现良好,而对其他工作负载表现不佳。例如,我们证明,目前,FUSE不能预取或复合[14]小的随机读取,因此对于具有许多小操作的工作负载表现不佳。本文的其余部分组织如下。第2节讨论FUSE体系结构和实现细节。第3节描述了我们的可堆叠文件系统的实现和我们添加到FUSE内核和用户库中的有用的插装。第四节介绍了我们的实验方法。我们的大部分评估和分析在第5节中。第六节讨论了相关的工作。我们在第7节中总结并描述了未来的工作。除了上面提到的部分,我们还有一个在线附录[22],其中提到了FUSE库支持的各种挂载选项(参数)。此外,它还详细描述了FUSE2引信设计FUSE-使用空间中的文件系统-是一个著名的用户空间文件系统框架[52]。它的实现首先出现在基于Linux的操作系统上,但随着时间的推移,它被移植到其他几个操作系统上[34,62]。根据适度的估计,至少有100个基于FUSE的文件系统在Web上可用[53]。尽管存在其他用户空间文件系统的专门实现[47,49,60],但我们选择FUSE进行这项研究是因为它的流行性。许多文件系统都是使用FUSE实现的--这主要归功于它提供的简单API--但很少有人发表关于理解其内部架构、实现和性能的文章[44]。对于我们的评估来说,重要的是不仅要了解FUSE在本节中,我们首先描述FUSEFUSE可用于多种操作系统:我们选择Linux是因为它的广泛使用。我们分析了的代码,并在最新FUSE用户空间文件系统十五:5ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月Linux内核的稳定版本在项目开始时可用-v4.1.13。我们选择使用最新的FUSE库commit#386b1b(在项目开始时可用)而不是最新的版本v.2.9.4,因为该commit包括几个重要的补丁(65个文件更改,2,680个插入,3,693个删除),我们不希望从我们的评估中排除。大多数提交都包含了测试过程中遇到的各种缺陷的修复。在本节的其余部分,我们将详细介绍FUSE我们将在2.2节中描述FUSE守护进程和内核驱动程序如何通信。FUSE用户库中提供的几个不同的API级别在第2.3节中讨论(例如,高级API与低级API)。第2.4节描述了通过FUSE用户内核协议交换的每个连接会话信息。不同类型的队列是FUSE内核驱动程序的一部分,在第2.5节中描述。第2.6节描述了使用拼接和内部维护的相关特殊缓冲区第2.7节讨论了FUSE第2.8节描述了FUSE的库如何支持多线程和并行处理请求。在2.9节中,我们讨论了与FUSE的写回内核缓存相关的重要参数最后,我们在附录[22]中讨论2.1高级架构FUSE由内核部分和用户空间中的FUSE守护程序组成内核部分作为Linux内核模块fuse.ko实现,当加载时,它向虚拟文件系统(VFS)注册三种文件系统类型(所有在/proc/filesystems中可见):(1)fuse,(2)fuseblk和(3)fusectl。fuse和fuseblk都是由不同FUSE守护进程实现的各种特定FUSE文件系统的代理类型fuse类型的文件系统不需要底层块设备,通常是可堆叠的、内存中的或网络文件系统。但是,fuseblk类型用于部署在块设备之上的用户空间文件系统,与传统的本地文件系统非常fuse和fuseblk类型在实现上类似;但是,对于单设备文件系统,fuseblk类型提供以下功能:(1) 将闭锁装置锁定在安装件上,并在释放时解锁;(2) 共享文件系统以进行多个装载;以及(3) 允许交换文件在访问底层设备时绕过文件系统。除了这些功能之外,fuseblk还提供了同步卸载文件系统的能力:当文件系统是最后一个要卸载的文件系统时(没有惰性卸载或绑定挂载remain),那么卸载调用将等待,直到文件系统确认这一点(例如,刷新缓冲区)。我们将在后面的2.2节中讨论这种行为。从这里开始,我们将fuse和fuseblk都称为FUSE最后,fusectl文件系统为用户提供了控制和监视任何FUSE文件系统行为(例如,设置阈值并对未决请求的数量进行fuse和fuseblk文件系统类型与传统文件系统不同(例如,Ext4或XFS):它们代表了整个文件系统家族 为了区分不同的已装载FUSE文件系统,/proc/mounts文件包含一个附加名称标识符,并将每个特定的FUSE文件系统表示为[fuse| fuseblk]。<名称>(而不是[fuse|fuseblk])。的是由FUSE文件系统开发者指定的字符串标识符(例如,系统消除重复数据)。除了注册三个文件系统之外,FUSE该设备充当用户空间FUSE守护进程和内核之间的接口通常,FUSE守护程序从/dev/fuse读取FUSE请求,处理它们,然后将回复写回/dev/fuse。十五:6B. K. R. Vangoor等人ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月图1.一、FUSE高级架构。图1显示了FUSE当一个用户应用程序在一个挂载的FUSE文件系统上执行某些操作时,VFS会将该操作路由到FUSE驱动程序分配FUSE请求结构并将其放入FUSE队列中。此时,提交操作的进程通常处于等待状态。然后,FUSE守护进程通过读取/dev/fuse从内核队列中挑选请求并处理该请求。处理请求可能需要再次重新进入内核:例如,在可堆叠的FUSE文件系统的情况下,FUSE守护程序将操作提交给底层文件系统(例如,Ext4);在基于块的FUSE文件系统的情况下,FUSE守护程序从块设备读取或写入;并且在网络或内存中文件系统的情况下,FUSE守护程序可能仍然需要重新进入内核以获得某些系统服务(例如,创建套接字或获取一天中的处理完请求后,FUSE守护进程将响应写回/dev/fuse; FUSE应用程序调用的某些文件系统操作可以在不与用户级FUSE守护程序通信的情况下完成。例如,从页面缓存在内核页面缓存中的文件中读取数据,不需要转发到FUSE驱动程序。我们选择了可堆叠的用户空间文件系统而不是块、网络或内存文件系统进行研究,因为大多数现有的基于FUSE的文件系统都是可堆叠的(即,部署在其他文件系统之上,通常是内核文件系统)。2.2核心用户协议当FUSE头文件include/uapi/linux/fuse. h(用于FUSE特别是,结构fuse_in_header和fuse_out_header为所有输入请求(到FUSE守护程序)和输出应答(来自FUSE守护程序)定义了公共头它们还定义了特定于操作的标头:struct fuse_read_in/fuse_read_out(用于读取操作)、struct fuse_fsync_in/out(用于fsync操作),等等。请求具有不同的类型(存储在fuse_in_header的opcode字段中),这取决于它们编码的操作。参数MIN_BUFSIZE(等于136KB:132KB用于数据,4KB用于头文件)在FUSE库中定义,并确定库从FUSE用户空间文件系统十五:7ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月表1.按语义组(#)请求类型特殊(3)这是真的,真的元数据(14)LOOKk up,FORGET,bAT cH_FORGET,CREATE,unlI nk,lI nk,REnAME,REnAME 2,opE n,SAMPLE AsE,sTATFS,FSYnC,fLU sH,ACCESS数据(2)读写属性(2)gETATTR,SETATTR扩展属性(4)SETXATTR,gETXATTR,lISTXATTR,REMOVEXATTR(2)SYMlI nk,READlI nk目录(7)MkDIR,RMDIR,oPE nDIR,RSAsED iR,READDIR,READDIRpLU s,FSYnCDIR锁定(3)gET lk,SETlk,SETlkW其他(6)BMAP,falloCATE,MknoD,IOCTl,POll,noTIFY_REPly括号中的数字是相应组的大小我们在本文中讨论的请求类型以粗体显示从FUSE通道(在创建FUSE挂载点期间建立)读取时,内核然而,许多FUSE请求小于MIN_BUFSIZE(例如,4KB)。因此,MIN_ BUFSIZE仅定义请求的最大大小。当FUSE库将请求读入用户空间缓冲区时,它首先处理头部(例如,结构fuse_in_header和用于写入的结构fuse_write_in)。在从报头确定操作码和其他请求元数据之后,处理请求的剩余部分表1列出了所有43种FUSE请求类型,并按其语义分组如图所示,大多数请求都直接映射到传统的VFS操作:我们省略了对明显请求的讨论(例如,READ、CREATE),而不是关注那些不太直观的请求类型(在表1中以粗体突出显示)。当一个文件系统被挂载时,内核会产生inIT请求此时,用户空间和内核协商以下三项:(1) 它们将操作的协议版本(例如,v7.23,我们使用的版本);(2) 一组相互支持的能力(例如,READDIRPlUS orF loC k support),其中FUSE_CAP_x包含用户/内核的所有可能功能;以及(3) 各种参数设置(例如,FUSE预读大小,属性的时间粒度它们作为挂载选项传递相反,卸载请求由内核在文件系统卸载过程中发送当收到一个删除请求时,FUSE守护程序将执行所有必要的清理。对于这个会话,将不会再有来自内核的请求,并且后续从/dev/fuse的读取将返回0,从而导致FUSE守护程序正常退出。目前,仅在fuseblk的情况下,而不是在fuse文件系统类型的情况下(如第2.1节所述),才会将删除此外,这个销毁请求本质上是同步的,在从FUSE守护程序收到响应之前,它会阻止卸载进程。此行为的原因是因为fuseblk是使用特权用户凭据(访问块设备)装载的;在这种情况下,卸载需要在卸载期间处理所有剩余缓冲区的刷新。然而,在fuse文件系统的情况下卸载不需要等待非特权的FUSE守护进程[24]。中断请求是由内核生成的,如果先前请求并传递给FUSE守护进程的数据不再被该进程需要(例如,当在读取请求上阻塞的用户进程被终止/取消时)。中断请求优先于其他请求,因此用户空间文件系统将在任何请求之前接收排队的中断请求十五:8B. K. R. Vangoor等人ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月其他请求(已在等待中)。用户空间文件系统可以完全忽略中断请求(当未实现时),或者它可以通过发送对原始请求的回复来履行它们,错误设置为EINTR。每个请求都有一个唯一的序列#,中断使用它来识别受害者请求。序列号由内核分配,也用于在用户空间回复内核时定位已完成的请求每个请求还包含一个节点ID-一个无符号的64位整数,用于标识内核和用户空间中的inode(有时称为inode ID)。路径到索引节点的转换由LOOkUP请求执行FUSE每次查找现有的inode(或创建新的inode)时,内核都会将该inode保存在inode和目录条目缓存(dcache)中从dcache中删除inode时,内核将f或 gET请求传递给FUSE守护程序。FUSE对于GET请求,传递一个nlookups参数,该参数通知用户空间文件系统(FUSE守护程序)要忘记多少次查找此时,用户空间文件系统(FUSE守护进程)可能决定释放任何相应的数据结构(一旦它们的引用计数变为0)。BATCH_FORGET允许内核在单个请求中忽略当用户应用程序打开一个文件时,会生成一个操作请求冲洗每次关闭打开的文件时生成释放;并且当不再有对先前打开的文件的引用时发送释放对于每个操作n请求(当关闭时)生成一个释放请求,并且由于fork、dup等,每个操作n可能有多个FLUSHOPENDIR和RELEASEDIR请求分别具有与OPENDIR和releasedir相同的语义,但是用于目录。rEADDIRP lUS请求返回一个或多个目录条目,如rEADDIR,但它还包括每个条目的元数据信息。这允许内核预先填充其inode缓存,类似于NFSv3只有在两种特殊情况下才会生成CCESS请求:access(2)和chdir(2)。在所有 在其它情况下,在实际操作中进行访问检查(例如,则发送一个EACCESS请求,并且如果访问被拒绝,则Fuse守护进程可以返回EACCESS)。通过处理此访问请求,FUSE守护程序可以实现自定义权限的逻辑但是,通常用户使用default_permissions选项挂载FUSE,该选项允许 内 核 根 据 文 件 的 标 准 Unix 属 性 ( 即 , 所 有 权 和 许 可 位 ) 。 在 这 种 情 况 下(default_permissions),不会生成访问请求与REnAME相比,REnAME 2只是增加了一个flags字段; re nAME 2当前支持的flags如下:(1) RENAME_NOREPLACE:这个标志表明如果重命名的目标存在,那么重命名应该失败,并使用EEXIST而不是替换目标(正如POSIX所期望的那样)。(2) RENAME_EXCHANGE:此标志指示源和目标必须都存在,但可以是不同的类型(例如,一个可以是非空目录,另一个可以是符号链接)。如果它们中的任何一个都不存在,则重命名失败,返回ENOENT,而不是替换目标。否则,只要文件系统只在FUSE挂载中被修改,REnAME2将尝试原子地交换这两个名称。如果没有标志被传递,那么内核回退到使用常规的重新命名请求。FSYnC和FSYnCDIR分别用于同步文件和目录上的数据和元数据。这些请求还带有一个额外的标志dataforc,它允许开发者区分何时同步数据和元数据。也就是说,当databloc参数为非零时,则仅刷新用户数据,而不刷新元数据。FUSE用户空间文件系统十五:9ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月图二、FUSE库水平的相互作用FUSE支持使用以下请求类型进行文件锁定:(1) gET lk检查文件上是否已经有锁,但不设置锁。(2) 集合LkW获得所请求的锁。如果无法获得锁(例如,其他人已经拥有锁),然后等待(阻塞)直到锁被释放,然后为自己获取锁(3) 集合Lk几乎等同于集合LKW。唯一的区别是,如果它不能获得锁,它将不会等待。相反,它会立即返回一个错误。2.3库和API级别从概念上讲,FUSE库包括两个API级别,如图2所示。较低级别负责以下事项:(1) 接收并解析来自内核的请求(2) 发送格式正确的回复;(3) 促进文件系统配置和安装;以及(4) 隐藏内核和用户空间之间的潜在版本差异库的这一部分向开发人员公开了所谓的低级FUSE API。高级FUSE API构建在低级API之上,允许文件系统开发人员跳过路径到inode映射的实现因此,高级API中既不存在inode也不存在查找操作,从而简化了代码开发。 所有高级API方法都直接对文件路径进行操作,而不是使用inode。因此,在高级API中也不需要FOR g ETinode方法。高级API还处理请求中断并提供其他方便的功能;例如,开发人员可以使用更常见的chown(),chmod()和truncate()方法,而不是较低级别的setattr()方法。高级API从不直接与内核通信,只通过低级API。底层API实现库中的函数名如fuse_lib_x()(例如,fuse_lib_read)。这些函数根据功能在内部调用用户定义的高级API函数十五:B. K. R. Vangoor等人ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月文件系统开发人员必须通过平衡灵活性和开发易用性来决定使用哪个API。在这种情况下,开发人员需要在fuse_operations结构中实现42个方法。这些方法大致对应于传统的POSIX文件系统操作(例如,open、read、write、mkdir),并且几乎所有这些都将文件名作为参数之一。如果开发人员决定使用低级API,则fuse_lowlevel_ops中的42个不同方法需要有待落实。这两个API的方法名称相似,但主要不同之处在于参数和返回值。两种结构中的许多方法都是可选的。例如如果如果文件系统不支持扩展属性,则可以不实现相应的方法。此外,如果FUSE文件系统不缓存任何inode,则可以不实现f或gET两个API中的许多方法是相似的。我们强调低级和高级API之间的三个重要区别。首先,为了更灵活,低级方法总是将FUSE请求作为参数。其次,方法定义与Linux VFS方法有着更紧密的对应关系,因为它们经常对inode(或者更确切地说是inode号)进行操作。例如,VFS查找方法使用父索引节点号来查找内部,使用文件名来查找,使用标志来控制查找模式。然后,它递归地查找路径组件,并最终获得文件的dentry除了完整的FUSE请求之外,FUSE低级API中的查找方法还需要它执行类似的递归查找并获取目录条目的属性。第三,与lookup方法配对的是一个额外的forget方法,当内核从inode/dentry缓存中删除inode时会调用该方法。图2示意性地描述了FUSE的库水平的相互作用。当低级API从内核接收到请求时,它会解析请求并调用适当的方法在fuse_lowlevel_ops中。此结构中的方法要么由用户文件系统本身实现(如果选择低级API来开发用户文件系统),要么直接由FUSE库的高级部分。在后一种情况下,库的高级部分调用fuse_operations结构中的适当方法,该方法由使用FUSE的高级API开发2.4每个连接会话信息在2.2节中,我们描述了FUSE的用户内核协议如何帮助FUSE内核和用户守护进程之间的通信。FUSE的用户内核协议还提供了一种机制来为每个打开的文件/目录存储一些内存信息。存储或不存储信息的能力使协议分别是有状态的和无状态的。对于低级API中处理文件/目录的每个操作(在2.3节中讨论),都有一个结构体fuse_file_info作为参数传递。此结构由FUSE库维护,用于跟踪有关FUSE文件系统(用户空间)中文件的信息。此结构包含一个无符号的64位整数字段fh(文件句柄),可用于存储有关打开的文件的信息(有状态)。当回复类似于open和CREATE的请求时(在2.2节中讨论),FUSE守护程序可以在此字段中存储打开/创建的文件的64位文件句柄这样做的好处是,fh随后由内核传递给FUSE守护进程,以执行与打开的文件相关联的所有操作。如果一开始就没有设置,那么FUSE守护程序必须为每个文件操作打开和关闭文件(无状态),这可能会降低性能。这种有状态性甚至适用于像opendir和MKDIR这样的请求,其中与打开的目录相关联的目录指针可以被类型转换并存储在fh中。例如,可堆叠的FUSE文件系统可以将在底层文件系统中打开的文件的描述符存储为FUSE的文件句柄的一部分。不需要设置文件句柄;如果不设置,协议将是无状态的。FUSE用户空间文件系统十五:ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月图3.第三章。FUSE队列的组织,用其Head和Tail标记。 处理队列没有尾部,因为FUSE守护程序以任意顺序进行响应。2.5队列在2.1节中,我们描述了FUSE内核如何拥有一个请求队列,供用户空间处理。FUSE实际上维护五个不同的队列,如图3所示:(1)中断(2)忘记,(3) 未决,(4)背景,和(5)处理。一个请求在任何时候都只属于一个队列。FUSE最初将新的中断请求放在中断队列中,以便将GET请求放在forgets中。队列、等待时间敏感请求(例如,元数据相关的请求),以及其它请求(例如,数据读取或写入)。FUSE为中断请求使用单独的队列,因此可以以比其他请求更高的优先级处理这些请求类似地,FUSE为 forgetrequest使用一个单独的队列,以将它们与non-forget请求区分开来(以平衡这些请求的处理)。对于GET请求,当inode被逐出时发送:如果不存在单独的Forgets队列,则这些请求将与常规文件系统请求一起排队。如果处理了许多f或 gET请求,则不能继续进行其他文件系统操作。当一个拥有3200万个inode的FUSE文件系统在一台拥有大量内存的机器上,当所有这些inode都从icache中被驱逐时,可能会在长达30分钟的时间内变得无响应[25]。因此,FUSE为FORGET请求维护一个单独的队列,并实现一个公平的策略来处理它们,如下所当FUSE守护程序从/dev/fuse读取数据时,请求将被传输到FUSE守护程序,如下所示:(1) 中断队列中的请求(如果有的话)具有优先级;它们在任何其他请求之前被传输到用户空间。(2) 公平地选择FORGET和NON-FORGET请求:对于未决队列中的每8个NON-FORGET请求,传送遗忘队列中的16个 FORGET请求这平滑了FORGET请求的突发性,同时允许其他请求继续进行。挂起队列中最早的请求被传输到用户空间,同时被移动到处理队列。中断和FORGET请求没有应答(来自FUSE守护程序);因此,一旦FUSE守护程序读取这些请求,它们就会被终十五:B. K. R. Vangoor等人ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月止。FUSE用户空间文件系统十五:ACM Transactions on Storage,Vol.号152、第十五条。出版日期:2019年5月因此,处理队列请求当前由FUSE守护进程处理如果挂起队列为空,则FUSE守护进程在读取调用时被阻塞。当FUSE守护程序回复请求(通过写入/dev/fuse)时,相应的请求将从处理队列中删除,从而结束请求的生命周期。与此同时,被阻止的用户进程(例如,等待读取完成的那些)被通知它们可以继续。后台队列用于暂存被认为比直接进入挂起队列的请求不那么重要的请求例如,缓慢的数据读取和写入通常比缓慢的元数据请求更少地降低整体系统性能因此,在默认设置中(装载时没有FUSE参数),读取请求将转到后台队列。写操作也会转到后台队列,但仅在启用了写回缓存的情况此外,FUSE将请求和释放请求放入后台队列。当回写缓存被启用时,来自用户进程的写入首先累积在页面缓存中,随后bdflush线程唤醒以刷新脏页面[16]。在刷新页面时,FUSE形成异步写请求并将它们放入后台队列。来自后台队列的请求逐渐进入挂起队列。FUSE将同时驻留在挂起队列中的后台请求数限制为可配置的max_background参数(默认为12)。当挂起队列中的异步请求少于12个时,来自后台队列的请求将被移动到挂起队列。目的是限制后台请求突发对重要同步请求造成的延迟,并限制在多线程选项(在第2.8节中讨论)情况下调用的FUSE守护程序线程数。队列的长度没有明确限制。但是,当挂起和处理队列中的异步请求数量达到可调的congestion_ threshold参数的值(max_background的75%,默认为9)时,FUSE会通知Linux VFS它已经拥塞; VFS然后会限制向此文件系统提交请求的用户进程,以允许拥塞排出。2.6拼接和熔断缓冲器在其基本设置中,FUSE守护程序必须从/dev/fuse读取请求并向其写入回复。每个这样的调用都需要在内核和用户空间之间进行内存拷贝这对于写请求和读回复来说尤其为了缓解这个问题,FUSE可以使用Linux内核提供的拼接功能[56]。拼接允许用户空间在两个内核内存缓冲区之间传输数据,而无需将数据复制到用户空间。例如,这对于将数据直接传递到底层文件系统的可堆叠文件系统很为了无缝地支持拼接,FUSE以两种形式之一表示其缓冲区:(1) 由FUSE守护程序地址空间中的指针
下载后可阅读完整内容,剩余1页未读,立即下载
cpongm
- 粉丝: 5
- 资源: 2万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 前端协作项目:发布猜图游戏功能与待修复事项
- Spring框架REST服务开发实践指南
- ALU课设实现基础与高级运算功能
- 深入了解STK:C++音频信号处理综合工具套件
- 华中科技大学电信学院软件无线电实验资料汇总
- CGSN数据解析与集成验证工具集:Python和Shell脚本
- Java实现的远程视频会议系统开发教程
- Change-OEM: 用Java修改Windows OEM信息与Logo
- cmnd:文本到远程API的桥接平台开发
- 解决BIOS刷写错误28:PRR.exe的应用与效果
- 深度学习对抗攻击库:adversarial_robustness_toolbox 1.10.0
- Win7系统CP2102驱动下载与安装指南
- 深入理解Java中的函数式编程技巧
- GY-906 MLX90614ESF传感器模块温度采集应用资料
- Adversarial Robustness Toolbox 1.15.1 工具包安装教程
- GNU Radio的供应商中立SDR开发包:gr-sdr介绍
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功