在内存FUSE文件系统中

时间:2012-01-25 13:16:17

标签: linux filesystems fuse

  

编写一个存储在内存中的简单FUSE文件系统。文件系统必须支持以下命令:

     

ls,mkdir,cp

这个问题最近在接受采访时被问到,我无法回答。 所以我决定学习它。

进行了一些搜索并找到了一些关于构建我自己的FUSE文件系统的指南。 我真的对如何在内存中实现文件系统毫无头绪。

我的问题是

  • 我是朝着正确的方向前进吗?
  • 我还应该读些什么?
  • 解决方案是什么?

我正在阅读的链接:

在最后一个链接中提到了使用PyFileSystem的内存缓存。 我不确定这可能会有什么帮助。

PS:这是一个书面采访问题,所以答案很简单,可以在10-15分钟内写在纸上。

2 个答案:

答案 0 :(得分:5)

我选择了一个课程,我们必须在内部构建一个类似于Frangipani的内存分布式文件系统。该课程受到MIT's Distributed Systems course的启发。做他们的前几个实验作业将是一个很好的练习。

This tutorial也很有帮助。

答案 1 :(得分:3)

您没有指定编程语言,尽管FUSE是本机C ++,但存在本地Golang绑定,在bazil.org/fuse实现。

我要说答案的主要部分需要包含以下内容:

  1. 处理内存中文件系统树的数据结构
  2. 节点的描述及其与iNode的关系
  3. 用于捕获FUSE服务器请求以处理cli命令的挂钩
  4. 使用FUSE服务器安装文件夹的说明。
  5. 我最近使用此适配器编写了一个内存文件系统:github.com/bbengfort/memfs。我的关于其性能的文章在这里: In-Memory File System with FUSE 。很快,我做了一些选择:

    内存数据结构包含2个主要结构,dir和file都是节点:

    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 
    }
    

    如您所见,这是一个可以通过ChildrenParent链接上下移动的简单树。文件的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如何拦截内核调用并将它们传递给用户空间中的进程。