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