您没有指定编程语言,但FUSE是本地C++,本地Golang绑定在bazil.org/fuse处执行。
我想说的是,答案的主要部分需要包括以下内容:
- 的数据结构来处理文件系统树在内存中的节点
- 描述和他们的i节点
关系
- 用于捕获FUSE服务器请求以处理cli命令的钩子
- 用FUSE服务器装入文件夹的说明。
我最近用这个适配器写了一个内存中的文件系统:github.com/bbengfort/memfs。关于它的性能我写在这里:In-Memory File System with FUSE。很快,几个选择我做:
的内存中的数据结构包含2层主要结构,目录和文件是两个节点:
type Node struct {
ID uint64
Name string
Attrs fuse.Attr
Parent *Dir
}
type Dir struct {
Node
Children map[string]Node
}
type File struct {
Node
Data []byte
}
正如你可以看到,这是一个简单的树是穿越上下通过Children
和Parent
链接。文件的Data
属性保存文件的所有内容。因此,文件系统只需在挂载点创建一个名为"\"
的“根”目录,然后在mkdir
上将Dir
添加到其子节点,并在cp
上添加File
。在Go中,这很简单:
type FS struct {
root *Dir
}
func Mount(path string) error {
// Unmount the FS in case it was mounted with errors.
fuse.Unmount(path)
// Mount the FS with the specified options
conn, err := fuse.Mount(path)
if err != nil {
return err
}
// Ensure that the file system is shutdown
defer conn.Close()
// Create the root dir and file system
memfs := FS{
root: &Dir{
ID: 1,
Name: "\",
Parent: nil,
},
}
// Serve the file system
if err := fs.Serve(conn, memfs); err != nil {
return err
}
}
现在您需要挂钩来实现各种FUSE请求和调用。下面是mkdir
一个例子:
func (d *Dir) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) {
// Update the directory Atime
d.Attrs.Atime = time.Now()
// Create the child directory
c := new(Dir)
c.Init(req.Name, req.Mode, d)
// Set the directory's UID and GID to that of the caller
c.Attrs.Uid = req.Header.Uid
c.Attrs.Gid = req.Header.Gid
// Add the directory to the directory
d.Children[c.Name] = c
// Update the directory Mtime
d.Attrs.Mtime = time.Now()
return c, nil
}
最后,结束面试问题,以了解如何编译和运行服务器,安装的路径,也许如何FUSE拦截内核调用,并在它们传递给你的流程的讨论用户空间。
我明白这可能会绕过这个问题,但为什么不使用[tmpfs](http://en.wikipedia.org/wiki/Tmpfs)而不是通过FUSE来滚动自己的文件系统? –
@FrédéricHamidi:tmpfs是一个很好的选择,谢谢。但可悲的是,这并不能回答你提到的问题。 – Gautam
我想_stored in memory_意味着你必须分配某种缓冲区并将该缓冲区用作fs后端? –