我发现 FUSE 用户空间库和内核接口(interface)自从它在 Linux 上诞生以来就已经被移植到许多其他系统,并提供了一个相对稳定的 API,据说表面面积很小。如果我想在用户空间中编写文件系统,并且我不在 Plan 9 或 Hurd 上,我会认为 FUSE 是我的最佳选择。
但是,我不会使用 libfuse。这部分是因为实用主义。在我选择的语言 (Monte) 中使用 C 很难。也是因为我对编写 C 支持代码完全不感兴趣,而且 libfuse 的推荐用法与 Monte 哲学不兼容。这应该不是问题,因为 C 并不神奇,并且/dev/fuse 可以通过标准系统调用打开。
要查找文档,但是,我找不到任何文档。我找不到关于/dev/fuse ABI/API 的文档,也没有其他人采用相同的非 C 绑定(bind)路线的故事。令人沮丧。
是否存在关于如何以与语言无关的方式与/dev/fuse 和内核的 FUSE 子系统进行交互的任何类型的文档?如果是这样,你能指出我吗?谢谢!
更新:存在 go-fuse ,这是在 Go 中,一种比 C 更易读的语言。但是,它也不包含任何 ABI/API 文档。
更新:我注意到人们投票决定关闭它。别担心,没有那个必要。我对自己想要的文档尚不存在感到满意。我将自己编写文档,发布它,然后在接受的答案中链接到它。希望下一个搜索此文档的人不会失望。
最佳答案
(在完成之前我不会接受它。在此期间,欢迎进行编辑!)
FUSE session 的基本大纲:
open()
在/dev/fuse
上调用。我将生成的 FD 称为控制 FD。mount()
使用目标挂载点、普通模式的文件系统类型“fuse”或 block 设备模式的“fuseblk”以及包括“fd=X”在内的选项进行调用,其中 X 是控制 FD。- FUSE 特定的结构在控制 FD 上重复传输。通信的一般模式遵循请求-响应模式,其中程序
read()
来自控制 FD 的文件系统命令,然后write()
返回响应。< umount()
使用目标挂载点调用。close()
在控件 FD 上调用。
综上所述,人们应该注意一些并发症。首先,mount()
几乎总是特权系统调用,因此您必须是 root 才能挂载 FUSE 文件系统。但是,正如您可能已经注意到的那样,FUSE 程序通常可以以非根用户身份启动!怎么办?
有一个助手,/bin/fusermount
,安装了 setuid。用法完全没有记录,但这就是我来这里的目的。代替 open()
ing /dev/fuse
自己,运行 fusermount
作为子进程,将目标挂载点作为参数传递,任何额外的使用 -o
安装您喜欢的选项,并且(至关重要的)使用环境变量 _FUSE_COMMFD
导出并设置为打开的 FD 的 ASCII 字符串,我将其称为 < strong>comm FD。您必须使用例如自己创建 comm FD 管道()
。 fusermount
将为您调用open()
和mount()
,并通过comm FD 将控制FD 共享给您,使用sendmsg()
共享 FD 的技巧。使用 recvmsg()
读回。
社论:我真的不明白为什么这个结构如此困难。 FD被子进程继承;在顶层进程中open()
控制FD 并将其传递到fusermount
会容易得多。的确,有一些令人困惑的副危险,但是 fusermount
已经安装并且 setuid 和 dangerous。
无论如何! fusermount
将粗暴地守护进程并负责调用 umount()
和 close()
以在主进程退出后进行清理。
尚未涵盖的内容:
- 如何处理对 FUSE 的非阻塞访问? control FD 可以直接进入非阻塞模式吗?它实际上不阻止,还是像普通文件一样在访问时 secret 阻止?
- 结构布局。这些可以或多或少地从 C 或 Go 源代码中重新发现,但这不是借口。当我有足够的自虐倾向时,我会更认真地记录它们。
关于linux - 如何在不使用 libfuse 的情况下使用 FUSE 创建用户空间文件系统?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31601272/