如何使用FUSE创build用户空间文件系统而不使用libfuse?

我发现FUSE的用户空间库和内核接口自Linux上开始就已经被移植到许多其他系统,并且提供了一个相对稳定的API,并具有所谓的小表面积。 如果我想在用户空间创build一个文件系统,而且我不是Plan 9或Hurd,那么我认为FUSE是我的最佳select。

但是,我不打算使用libfuse。 这部分是因为实用主义; 使用C是我的select语言(蒙特)很难。 这也是因为我对编写C支持代码完全不感兴趣,libfuse的推荐用法与Monte哲学不兼容。 这不应该是一个问题,因为C不是神奇的,并且可以用标准的系统调用打开/ dev / fuse。

去寻找文件,但是,我没有find。 我没有find/ dev / fuse ABI / API的文档,也没有其他人使用相同的非C路由的故事。 令人沮丧。

是否存在关于如何使用/ dev / fuse和内核的FUSE子系统以与语言无关的方式进行交互的任何types的文档? 如果是这样,你能指出我吗? 谢谢!

更新:Go中存在go-fuse ,这是一种比C更易读的语言,但它不包含任何ABI / API文档。

更新:我注意到有人投票结束了这个。 别担心,这是没有必要的。 我已经满意自己,我想要的文档还不存在。 我将自己编写文档,发布它,然后在接受的答案中链接到它。 希望下一个search这个文档的人不会感到失望。

(我不接受,直到完成,在此期间,欢迎编辑!)

FUSE会话的基本概述:

  • /dev/fuse上调用open() 。 我会打电话给FD 控制FD
  • mount()用目标挂载点,正常模式下的文件系统类型“fuse”或块设备模式下的“fuseblk”以及包含“fd = X”的选项调用,其中X是控制FD。
  • 将FUSE特定的结构反复传送到控制FD上。 一般的通信模式遵循请求 – 响应模式,程序从控制FD read() s文件系统命令,然后write() s响应。
  • 用目标挂载点调用umount()
  • 在控制FD上调用close()

所有人都说,有一些应该注意的并发症。 首先, mount()几乎总是一个特权的系统调用,所以你必须是root用来挂载一个FUSE文件系统。 但是,正如人们已经注意到的那样,FUSE程序通常可以以非root用户身份启动! 怎么样?

有一个助手/bin/fusermount ,安装了setuid。 用法完全没有记录,但这就是我在这里。 将fusermount作为一个子fusermount运行,将目标安装点作为参数传递,使用-o和(至关重要的)环境变量_FUSE_COMMFD导出并设置为的任何额外安装选项,而不是将open() ing /dev/fuse一个打开的FD的ASCII字符串,我将其称为通讯FD 。 你必须使用例如pipe()自己创建comm FD。 fusermount会为你调用open()mount() fusermount ,并使用sendmsg()技巧来共享控制FD, 使用recvmsg()将其读回来。

编辑:我真的不明白为什么这是如此困难。 FD由子进程继承; 在最上面的过程中open()控制FD并将其传递给fusermount 。 诚然,有一些混淆的副危险,但fusermount已经安装,setuid和危险的。

无论如何! fusermount将会粗暴地守护进程,并在您的主进程退出时调用umount()close()来清理。

尚未涵盖的事物:

  • 如何处理对FUSE的非阻塞访问? 控制FD能否被踢入非阻塞模式? 它实际上是不是阻止,或者它像一个普通的文件,并暗中阻止访问?
  • 结构布局。 这些可以或多或少地从C或者Go来源重新发现,但这不是理由。 当我处理足够的受虐狂时,我会更认真地记录他们。