В файловой системе FUSE памяти

Напишите простую файловую систему FUSE, которая хранится в памяти. Файловая система должна поддерживать следующие команды:

ls, mkdir, cp

Этот вопрос был недавно задан в интервью, я не смог ответить на него. Поэтому я решил изучить его.

Был ли поиск и найден ряд руководств по созданию моей собственной файловой системы FUSE. Я действительно не знаю, как реализовать файловую систему в памяти.

Мои вопросы

  • Я направляюсь в правильном направлении?
  • Что еще я должен прочитать?
  • Какое решение?

Ссылки, которые я читаю:

В последней ссылке есть упоминание о кэшировании в памяти с PyFileSystem. Я не уверен, как это может помочь.

PS: Это было письменное интервью Вопрос, поэтому ответ должен быть достаточно простым, чтобы писать на бумаге в течение 10-15 минут.

Ответ 1

Я прошел курс, где нам нужно было создать распределенную файловую систему в памяти, похожую по дизайну, на Frangipani. Курс был сильно вдохновлен курс MIT Distributed Systems. Выполнение первых нескольких лабораторных заданий было бы хорошим упражнением.

Этот учебник также весьма полезен.

Ответ 2

Вы не указали язык программирования, хотя FUSE является родным С++, существуют встроенные привязки Golang, реализованные в bazil.org/fuse,

Я бы сказал, что основные части ответа должны включать следующее:

  • Структура данных для обработки дерева файловой системы в памяти
  • Описания узлов и их связь с iNodes
  • Крючки для захвата запросов сервера FUSE для обработки команд cli
  • Описание установки папки с сервером FUSE.

Недавно я написал файловую систему в памяти, используя этот адаптер: github.com/bbengfort/memfs. Моя запись о ее производительности приведена здесь: Файловая система с памятью с файлом FUSE. Быстро, несколько вариантов, которые я сделал:

Структура данных в памяти содержит 2 первичные структуры, dir и файл, которые являются обеими узлами:

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 a Dir и добавить cp a 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 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 перехватывает вызовы ядра и передает их вашему процессу в пользовательском пространстве.