320 likes | 488 Views
Sistemas de ficheros virtual Introducción. David Borrego Viñas Borja Navarro Paradinas. Introducción. Función del sistema de ficheros Mantener los ficheros en estructura de árbol Los nodos hojas son los ficheros y el resto de nodos son los directorios
E N D
Sistemas de ficheros virtualIntroducción David Borrego Viñas Borja Navarro Paradinas
Introducción • Función del sistema de ficheros • Mantener los ficheros en estructura de árbol • Los nodos hojas son los ficheros y el resto de nodos son los directorios • La información de los nodos se guarda en las estructuras inode • La estructura del sistema de ficheros en la estructura de superbloque
Introducción • En 1993 Remy Card diseña el sistema de ficheros “ext”: • Mediante una capa de software “VFS” trabaja con sistemas de ficheros reales: ISO9660,vfat • VFS tiene: • un conjunto de estructuras en memoria principal • un conjunto de funciones para manejarlas • Para cada uno de los sistemas de ficheros reales • una serie de estructuras en disco • su conjunto particular de funciones para manejarlas.
Introducción • Para poder trabajar con sistemas de ficheros reales deben montarse (insertarse en el árbol en /mnt) • El sistema de ficheros trata los dispositivos como secuencias de bloques, el manejador del dispositivo será el encargado de traducir las peticiones de bloques en cabeza, cilindro, pista, etc… • El VFS oculta las características de los sistemas reales • Mantiene unas estructuras en memoria RAM y unos procedimientos para trabajar con estos
Estructura file_system_type • Al arrancar el PC se inicializa cada sistema de ficheros y se registra mediante la función “register_file_system” en una lista de estructuras de tipo “file_system_type”, apuntadas por la variable “file_system” • Podemos ver los sistemas de ficheros registrados en el sistema leyendo el fichero /proc/filesystems.
Estructrura file_system_type struct file_system_type { /* nombre del sistema de ficheros real ( ext2, minix, msdos) */ const char *name; /* flags para indicar si el sistema de ficheros precisa un dispositivo * de bloques para soportarlo */ int fs_flags; /* función particular de cada sistema de fichero real que lee * su superbloque en disco y escribe en el superbloque del VFS */ struct super_block *(*read_super) (struct super_block *, void *, int); struct module *owner; /* para kernel mount, si es un sistema de ficheros FS_SINGLE */ struct vfsmount *kern_mnt; struct file_system_type * next; };
Montaje sistema de ficheros real • Si ejecutamos la siguiente instrucción: mount –t sist_fichdispositivo puntomontaje • El VFS busca en la lista “file_system_type” si el sist_fich está soportado. • Busca el inode del puntomontaje. • Se llama al procedimiento “read_super” particular al sistema de ficheros para leer el superbloque almacenado en dispositivo y demás información para crear el superbloque del VFS en el vector “super_blocks” (super bloques montados)
Montaje sistema de ficheros real • Cada sistema de ficheros montado se describe por la estructura vfsmount que forman una lista apuntada por la variable vfsmntlist, en include/linux/mount.h
Montaje sistema de ficheros real struct vfsmount { struct list_head mnt_hash; struct vfsmount *mnt_parent; /* entrada al directorio cache que indica el inodo del punto de montaje o directorio de montaje*/ struct dentry *mnt_mountpoint; /* entrada al directorio cache que indica el inodo del directorio raiz del sistema de archivos */ struct dentry *mnt_root; /* root del arbol montado */ /* otros vsmonunts del mismo sistema de ficheros */ struct list_head mnt_instances; struct super_block *mnt_sb; /* puntero al superblock */ struct list_head mnt_mounts; /* lista de hijos, anclados aquí */ struct list_head mnt_child;/* y recorriendo a traves de su mnt_child */ atomic_t mnt_count; int mnt_flags; /* condiciones de montaje */ /* nombre del dispositivo de bloques que contiene el sistema de ficheros montado(/dev/cdrom) char *mnt_devname; /* lista de estructuras vfsmount (next) */ struct list_head mnt_list; uid_t mnt_owner; };
Montaje sistema de ficheros real • Para desmontar un sistema de ficheros “umount” no se debe estar usando ninguno de sus ficheros. • Si el campo dirty del superbloque está activado, se debe actualizar el superbloque de disco y liberar la estructura super_block de memoria y la estructura vfsmount. • Existen varias funciones que trabajan con esta estructura vfsmount • lookup_vfsmnt – busca un sistemas de archivos en la lista. • add_vfsmnt – añade un sistema de ficheros montado en la lista • remove_vfsmnt – quita de la lista un sistema de ficheros que se desmonta
Superbloque Al montar los sistemas de ficheros reales se representan en la tabla “super_blocks” struct super_block { /* lista doblemente enlazada de todos los superbloques activos */ struct list_head s_list; /* para sistemas de ficheros que requieren un bloque (dispositivo físico) para ser * montado en él. Se trata de un identificador de dicho dispositivo (ejem. 0x301 para el * disco IDE /dev/hda1) */ kdev_t s_dev; /* tamaño del bloque en bytes, (1024 bytes) */ unsigned long s_blocksize; /* tamaño del bloque en bytes expresado en potencia de 2 */ unsigned char s_blocksize_bits; /* indica si el superbloque ha sido modificado y debe escribirse en disco */ unsigned char s_dirt; /* tamaño maximo del fichero */ unsigned long long s_maxbytes; /* puntero a la estructura file_system_type que indica el tipo de sistema de fichero */ struct file_system_type *s_type; /* puntero a la estructura que contiene las funciones especificas de * este sistema de fichero real usadas para leer inodos y superbloque */ struct super_operations *s_op; /* puntero a las funciones relacionadas con la cuota de disco */ struct dquot_operations *dq_op;
Superbloque /* opciones para el montaje */ unsigned long s_flags; /* número que identifica a este sistema de ficheros y que servirá para que * Linux pueda reconocer dicho file system en cualquier partición */ unsigned long s_magic; /* puntero a la entrada de directorio donde esta el inodo raiz del sistema * de ficheros montado */ struct dentry *s_root; /* semáforo para bloquear el descriptor */ struct rw_semaphore s_umount; /* indica cuando un superbloque está actualmente bloqueado por lock_super()/unlock_super() */ struct semaphore s_lock; /* lista de todos los inodos del superbloque que han sido modificados */ struct list_head s_dirty; /* lista con los inodos que tienen que escribirse en disco */ struct list_head s_locked_inodes; /* lista de todos los ficheros abiertos en este superbloque */ struct list_head s_files; /* puntero a la estructura que contiene las características del dispositivo * que contiene el sistema de ficheros */ struct block_device *s_bdev; /* lista de estructuras vfsmount(s) de sistemas de archivos * montados pertenecientes a este superbloque */ struct list_head s_mounts; /* opciones de cuota de disco */ struct quota_info s_dquot;
Estructura inode • Todo fichero o directorio accedido es representado en el VFS con un struct inode. • Cada inode se llena mediante funciones especificas del sistema real. • Para un acceso más rápido se estructuran en listas en el inode caché. • Todos los inode se combinan en una lista global, además mediante una tabla de hash se acceden a lista con igual valor de hash. • Cuando se necesita un inodo y no está en caché, se busca en disco y se almacena en la caché, usando un count, para extraer un inodo de la caché. • El valor de hash se obtiene con el número de dispositivo y el de inode
Estructura inode • Cuando se extrae un inodo modificado (dirty=1) se debe escribir en disco. • Las funciones sobre un inode son especificas de cada sistema de fichero “inode_operations”
Estructura inode struct inode { struct list_head i_hash; /* lista de hash */ struct list_head i_list; /* lista global de inodos*/ struct list_head i_dentry; /* lista de inodos en la cache directorio */ /* lista de inodos que han sido modificado y precisan escribirse * en disco */ struct list_head i_dirty_buffers; unsigned long i_ino; /* número del inode, es único */ /* número de veces que se ha abierto este inodo, si esta a cero * este inodo se puede quitar de memoria */ atomic_t i_count; /* número de usos del inodo */ /* identificador del dispositivo que contiene el sistema de ficheros */ kdev_t i_dev; umode_t i_mode; /* tipo y derechos de acceso a este inodo */ nlink_t i_nlink; /* número de enlaces a este inodo*/ uid_t i_uid; /* identificador del propietario*/ gid_t i_gid; /* identificador de grupo del propietario */ kdev_t i_rdev; /* identificador de archivo especial */ loff_t i_size; /* tamaño del fichero en bytes */ time_t i_atime; /* fecha del último acceso */ time_t i_mtime; /* fecha de la última modificación */ time_t i_ctime; /* fecha de creación del inode*/
Estructura inode /* tamaño del bloque para este fichero en bytes (1024) */ unsigned long i_blksize; /* número de bloques asignado a este fichero */ unsigned long i_blocks; /* numero de versión, se incrementa con cada nuevo uso */ unsigned long i_version; unsigned short i_bytes; /*semaforo para los accesos concurrentes al inodo */ struct semaphore i_sem; struct rw_semaphore i_truncate_sem; struct semaphore i_zombie; /* puntero a funciones que operan con el inodo especificas del * sistema de ficheros real (define las operaciones que se pueden realizar con cada inodo )*/ struct inode_operations *i_op; /* puntero a funciones que operan con la estructura file */ struct file_operations *i_fop; /* former ->i_op->default_file_ops */ /* puntero a la estructura super_block de este sistema de ficheros */ struct super_block *i_sb; /* variable utilizada para sincronizar los accesos concurrentes a este inode */ wait_queue_head_t i_wait; /* puntero a las estructuras de bloqueo de este inodo en memoria*/ struct file_lock *i_flock;
Estructura inode /* puntero a las áreas y páginas de memoria de este inode */ struct address_space *i_mapping; struct address_space i_data; /* cuotas del disco asociadas con este inodo */ struct dquot *i_dquot[MAXQUOTAS]; /* puntero a la estructura pipe si el inodo representa un pipe */ struct pipe_inode_info *i_pipe; /* puntero a la estructura block_device si el inodo representa * un dispositivo de modo bloque */ struct block_device *i_bdev; /* puntero a la estructura char_device si el inodo representa * un dispositivo de modo carácter */ struct char_device *i_cdev; /* mascara para notificación de eventos a directorios */ unsigned long i_dnotify_mask; struct dnotify_struct *i_dnotify; /* para notificaciones a directorios */ unsigned long i_state; /* opciones de montaje del sistema de ficheros que contiene el inodo */ unsigned int i_flags; /* campo que indica si el inode representa a un socket */ unsigned char i_sock;
Estructura inode /* número de aperturas para escritura de este nodo */ atomic_t i_writecount; unsigned int i_attr_flags; __u32 i_generation; /* información especifica de cada sistema de ficheros */ union { struct minix_inode_info minix_i; struct ext2_inode_info ext2_i; struct ext3_inode_info ext3_i; struct hpfs_inode_info hpfs_i; struct ntfs_inode_info ntfs_i; struct msdos_inode_info msdos_i; …. struct jffs2_inode_info jffs2_i; /* campo para guardar la dirección de datos privados */ void *generic_ip; } u; };
Estructura inode (operaciones) struct inode_operations { /* crea una entrada en el directorio cache */ int (*create) (struct inode *,struct dentry *,int); /* busca en el directorio un inode */ struct dentry *(*lookup) (struct inode *,struct dentry *); /* crea un enlace a un inodo */ int (*link) (struct dentry *,struct inode *,struct dentry *); /* borra un enlace a un inodo */ int (*unlink) (struct inode *,struct dentry *); /* crea un enlace simbólico al inodo */ int (*symlink) (struct inode *,struct dentry *,const char *); /* crea un directorio */ int (*mkdir) (struct inode *,struct dentry *,int); /* borra un directorio */ int (*rmdir) (struct inode *,struct dentry *); /* crea un archivo especial */ int (*mknod) (struct inode *,struct dentry *,int,int); /* cambia el nombre de un fichero o directorio */ int (*rename) (struct inode *, struct dentry *,struct inode *, struct dentry *);
Estructura inode(operaciones) /* lee el contenido de un enlace simbólico */ int (*readlink) (struct dentry *, char *,int); /* resuelve un enlace simbólico */ int (*follow_link) (struct dentry *, struct nameidata *); /* modifica el tamaño de un fichero */ void (*truncate) (struct inode *); /* comprueba los permisos para acceder al fichero */ int (*permission) (struct inode *, int); /* detecta las nuevas caracteríaticas del dispositivo removible */ int(*revalidate) (struct dentry *); int (*setattr) (struct dentry *, struct iattr *); int (*getattr) (struct dentry *, struct iattr *); };
Estructura address_space • Estructura que contiene las VMA y las páginas de este inodo. struct address_space { struct list_head clean_pages; /* lista de páginas clean */ struct list_head dirty_pages; /* lista de páginas modificadas*/ struct list_head locked_pages; /* lista de páginas bloqueadas*/ unsigned long nrpages; /* número total de páginas*/ spinlock_t page_lock; /* bloqueo de páginas en memoria */ /* punteros a funciones que operan con el espacio de direcciones */ struct address_space_operations *a_ops; struct inode *host; /* inode del dispositvo de bloques */ /* lista de direcciones de memoria privadas*/ struct vm_area_struct *i_mmap; /* lista de direcciones de memoria compartidas*/ struct vm_area_struct *i_mmap_shared; spinlock_t i_shared_lock; /* bloqueo para protección */ int gfp_mask; /* como asignar las páginas */ };
Caché de directorios • Para mayor eficiencia en la búsqueda de un directorio o fichero se usan dos tablas de cache, con las entradas de directorio más usadas y sus inodos. • Se estructuran como una tabla de hash con varias listas, donde cada entrada apunta a una lista con el mismo valor de hash. • La función de hash usa el identificador de dispositivo y el nombre del directorio. (fs/dcache.c)
Buffer caché • Para minimizar accesos a disco se implementa un conjunto de buffer que actúan como interfaz entre usuario y dispositivo. • Las lecturas y escrituras se realizan sobre el buffer y el sistema escribe o lee del buffer en el bloque de disco. • Compartido por todos los sistemas de ficheros reales montados, puesto que es independiente de las características físicas de cada sistema
Buffer caché • Contiene uno o varios bloques referenciados por el número de bloque y de dispositivo. • Existen varias listas según el estado de los bloques: • Dirty,Shared, clean.
Estructura file • Es creada por el VFS al abrir un fichero, y se encadenan en una lista de estructuras file apuntadas por “first_file”. • Definida en “include/linux/fs.h”.
Estructura file struct file { struct list_head f_list; /* lista de estructuras file */ struct dentry *f_dentry; /* puntero al inodo de ese fichero */ /* puntero a la estructura de ficheros montados */ struct vfsmount *f_vfsmnt; /* conjunto de operaciones relacionadas con un fichero abierto */ struct file_operations*f_op; /* puntero a file_operations*/ atomic_t f_count; /* flag relacionado con el modo de apertura del fichero */ unsigned int f_flags; /* modo de apertura del fichero en la llamada open, conjunción * de FMODE_READ y FMODE_WRITE */ mode_t f_mode; /* posición actual desde el principio del fichero en bytes */ loff_t f_pos;
Estructura file /* número de bloques a leer en lectura anticipada */ unsigned long f_reada, /* número máximo de bloques a leer en lectura anticipada */ f_ramax, /* posición dentro del fichero, después de la última pagina leída * de forma anticipada */ f_raend, /* número de bytes leidos en la última lectura anticipada */ f_ralen, /* tamaño de la ventana para lectura anticipada */ f_rawin; /* estructura con información del proceso propietario */ struct fown_struct f_owner; /* identificador del propietario y de su grupo */ unsigned int f_uid, f_gid; int f_error; unsigned long f_version; /* necesario para algunos manejadores como el tty */ void *private_data; };
Operaciones sobre ficheros • Esta estructura tiene punteros a funciones que trabajan con la estructura file y son propias y se implementan en el sistema de ficheros real. struct file_operations { struct module *owner; /* modifica la posición actual del fichero */ loff_t (*llseek) (struct file *, loff_t, int); /* lectura en el fichero */ ssize_t (*read) (struct file *, char *, size_t, loff_t *); /* escritura en el fichero */ ssize_t (*write) (struct file *, const char *, size_t, loff_t *) /* lee entradas desde el directorio */ int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); /* realiza operaciones de control sobre un dispositivo */ int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); /* coloca el contenido de un fichero en la memoria del proceso */ int (*mmap) (struct file *, struct
Operaciones sobre ficheros /* abre un fichero */ int (*open) (struct inode *, struct file *); int (*flush) (struct file *); /* se llama al efectuar el último cierre de un archivo */ int (*release) (struct inode *, struct file *); /* escribe los bloques modificados del fichero en disco */ int (*fsync) (struct file *, struct dentry *, int datasync); /* activa o desactiva las entradas o salidas asincronas sobre el fichero */ int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); /* lectura adelantada de varios bloques */ ssize_t *readv) (struct file *, const struct iovec *, unsigned long, loff_t *); /* escritura de varios bloques */ ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area) (struct file *, unsigned long, unsigned long, unsigned long, unsigned long); };
Proceso Interfaz de llamada al sistema Sistema virtual de ficheros (caché de nombres) ext2fs minix proc Buffer cache Gestor de dispositivos (drivers) Máquina Llamada al sistema • Cuando un proceso hace una llamada al sistema es atendida por el VFS y es redirigida al sistema de ficheros particular de que se trate.