2012-01-25 28 views
11

Escriba un sistema de archivos FUSE simple que se almacena en la memoria. El sistema de ficheros tiene que apoyar los siguientes comandos:En la memoria Sistema de archivos FUSE

ls, mkdir, cp

Esta pregunta se le preguntó recientemente en una entrevista, que no era capaz de responder él. Así que he decidido aprenderlo.

Hice algunas búsquedas y encontré algunas guías para construir mi propio sistema de archivos FUSE. No tengo ni idea de cómo implementar el sistema de archivos en la memoria.

Mis preguntas son

  • Estoy yendo en la dirección correcta?
  • ¿Qué más debería leer?
  • ¿Cuál es la solución?

Enlaces que estoy leyendo:

En el último eslabón de la hay una mención sobre el almacenamiento en caché en memoria con PyFileSystem. No estoy seguro de cómo eso podría ayudar.

PD: Esta fue una pregunta de la entrevista escrita, por lo que la respuesta tiene que ser lo suficientemente simple como para escribir en papel dentro de 10-15 minutos.

+1

Entiendo que esto podría eludir la pregunta, pero ¿por qué no usar [tmpfs] (http://en.wikipedia.org/wiki/Tmpfs) en lugar de pasar su propio sistema de archivos a través de FUSE? –

+0

@ FrédéricHamidi: tmpfs es una buena alternativa gracias. Pero lamentablemente eso no responde la pregunta como mencionaste. – Gautam

+0

Supongo que "almacenado en la memoria" significa que debe asignar algún tipo de búfer y usar ese búfer como un back-end de fs. –

Respuesta

5

Había realizado un curso en el que tenía que crear un sistema de archivos distribuidos en memoria de diseño similar al Frangipani. El curso fue fuertemente inspirado por MIT's Distributed Systems course. Hacer sus primeras asignaciones de laboratorio sería un buen ejercicio.

This tutorial también es bastante útil.

3

No especificó un lenguaje de programación, aunque FUSE es C++ nativo existen enlaces de Golang nativos, implementados en bazil.org/fuse.

diría que las partes principales de la respuesta deben incluir lo siguiente:

  1. Una estructura de datos para manejar el árbol del sistema de archivos en la memoria
  2. Las descripciones de los nodos y su relación con inodos
  3. Ganchos para capturar solicitudes del servidor FUSE para manejar los comandos cli
  4. Una descripción del montaje de una carpeta con el servidor FUSE.

Recientemente escribí un sistema de archivos en memoria usando este adaptador: github.com/bbengfort/memfs. Mi informe sobre su rendimiento está aquí: In-Memory File System with FUSE. Rápidamente, unas cuantas opciones que hacen:

La memoria estructura de datos contiene 2 estructuras primarias, dir y de archivo que son ambos nodos:

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 
} 

Como se puede ver, se trata de un árbol simple que es transitable arriba y abajo a través de los enlaces Children y Parent. El atributo Data del archivo contiene todos los contenidos de los archivos. El sistema de archivos solo necesita crear un directorio "raíz" llamado "\" en el punto de montaje, y luego en mkdir se agrega un Dir a sus hijos, y en cp se agrega un File. En Go, esto es tan simple como:

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 
    } 
} 

Ahora necesita ganchos para implementar las diversas solicitudes y llamadas de FUSE. Aquí está un ejemplo para 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 
} 

Por último, cierre la pregunta de la entrevista con una discusión sobre cómo compilar y ejecutar el servidor, el montaje de un camino y quizás cómo FUSE intercepta las llamadas al kernel y los pasa a su proceso de espacio de usuario.

+0

¡Respuesta impresionante, código provisto, gracias! –

Cuestiones relacionadas