Вы не указали язык программирования, хотя FUSE является родным C ++, есть собственные привязки 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'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 перехватывает вызовы ядра и передает их вашему процессу в пространстве пользователя.