Introducción
De los papeles que cumple el sistema operativo, probablemente el que más
consciente tengan en general sus usuarios es el de la gestión del espacio de almacenamiento,
esto es, la organización de la información en un sistema de archivos.
Al día de hoy, todos los usuarios de equipo de cómputo dan por sentado y
comprenden a grandes rasgos la organización del espacio de almacenamiento
en un directorio jerárquico, con unidades de almacenamiento llamadas archivos,
de diferentes tipos según su función. En el presente capítulo se revisará la semántica
que compone a este modelo, para que en el capítulo 7 se continúe con
los detalles de la gestión del espacio físico donde éstos están alojados.
La abstracción que hoy se conoce como sistemas de archivos es una de las
que más tiempo ha vivido y se ha mantenido a lo largo de la historia de la
computación, sobreviviendo a lo largo de prácticamente todas las generaciones
de sistemas operativos. Sin embargo, para poder analizar cómo es que el
sistema operativo representa la información en el dispositivo físico, el presente
capítulo inicia discutiendo cómo es que esta información es comprendida por
los niveles más altos —por los programas en espacio de usuario.
Concepto de archivo En primer término, un archivo es un /tipo de datos abstracto/— esto es, podría verse como una estructura que exclusivamente permite la manipulación por medio de una interfaz orientada a objetos: los procesos en el sistema sólo pueden tener acceso a los archivos por medio de la interfaz ofrecida por el sistema operativo.3 La siguiente sección describe las principales operaciones provistas por esta interfaz. Para el usuario, los archivos son la unidad lógica mínima al hablar de almacenamiento: todo el almacenamiento persistente (que sobrevive en el tiempo, sea a reinicios del sistema, a pérdida de corriente o a otras circunstancias en el transcurso normal de ejecución) en el sistema al que tiene acceso, se efectúa dentro de archivos; el espacio libre en los diferentes dispositivos no tiene mayor presencia fuera de saber que está potencialmente disponible.
Operaciones con archivos Cada sistema operativo definirá la interfaz de archivos acorde con su semántica, pero en líneas generales, las operaciones que siempre estarán disponibles con un archivo son:
Borrar Elimina al archivo del directorio y, de ser procedente, libera el espacio del dispositivo
Abrir Solicita al sistema operativo verificar si el archivo existe o puede ser creado (dependiendo del modo requerido) y se cuenta con el acceso para el modo de acceso al archivo indicado y si el medio lo soporta (por ejemplo, a pesar de contar con todos los permisos necesarios, el sistema operativo no debe permitir abrir para escritura un archivo en un CD-ROM u otro medio de sólo lectura). En C, esto se hace con la función
Cerrar Indica al sistema que el proceso en cuestión terminó de trabajar con el archivo; el sistema entonces debe escribir los buffers a disco y eliminar la entrada que representa a esta combinación archivo-proceso de las tablas activas, invalidando al descriptor de archivo. En C, para cerrar un descriptor de archivo se usa fclose(). Dado que todas las operaciones se realizan por medio del descriptor de archivo, si un proceso cierra un archivo y requiere seguir utilizándolo, tendrá que abrirlo de nuevo para obtener un nuevo descriptor.
Leer Si se solicita al sistema la lectura leer de un archivo hacia determinado buffer, éste copia el siguiente pedazo de información al. Este pedazo podría ser una línea o un bloque de longitud definida, dependiendo del modo en que se solicite la lectura. El sistema mantiene un apuntador a la última posición leída, para poder continuar con la lectura de forma secuencial.
Escribir Teniendo un archivo abierto, guarda información en él. Puede ser que escriba desde su primer posición (truncando al archivo, esto es, borrando toda la información que pudiera ya tener), o agregando al archivo, esto es, iniciando con el apuntador de escritura al final del mismo. La función C para escribir a un descriptor de archivo es fwrite().
Reposicionar Tanto la lectura como la escritura se hacen siguiendo un apuntador, que indica cuál fue la última posición del archivo a la que accesó el proceso actual. Al reposicionar el apuntador, se puede saltar a otro punto del archivo. La función que reposiciona el apuntador dentro de un descriptor de archivos es fseek().
Hay varias otras operaciones comunes que pueden implementarse con llamadas compuestas a estas operaciones (por ejemplo, copiar un archivo puede verse como crear un archivo nuevo en modo de escritura, abrir en modo de lectura al archivo fuente, e ir leyendo de éste y escribiendo al nuevo hasta llegar al fin de archivo fuente).
Tablas de archivos abiertos Tanto el sistema operativo como cada uno de los procesos mantienen normalmente tablas de archivos abiertos. Éstas mantienen información acerca de todos los archivos actualmente abiertos, presentándolos hacia el proceso por medio de un descriptor de archivo; una vez que un archivo fue abierto, las operaciones que se realizan dentro de éste no son empleando su nombre, sino su descriptor de archivo. En un sistema operativo multitareas, más de un proceso podría abrir el mismo archivo a la vez; lo que cada uno de ellos pueda hacer, y cómo esto repercute en lo que vean los demás procesos, depende de la semántica que implemente el sistema; un ejemplo de las diferentes semánticas posibles es el descrito en la sección
Conteo de usuarios del archivo Requiere saberse cuántos procesos están empleando en todo momento a determinado archivo. Esto permite, por ejemplo, que cuando el usuario solicite desmontar una partición (puede ser para expulsar una unidad removible) o eliminar un archivo, el sistema debe poder determinar cuándo es momento de declarar la solicitud como efectuada. Si algún proceso tiene abierto un archivo, y particularmente si tiene cambios pendientes de guardar, el sistema debe hacer lo posible por evitar que el archivo desaparezca de su visión.
Modos de acceso Aunque un usuario tenga permisos de acceso a determinado recurso, el sistema puede determinar negarlo si llevaría a una inconsistencia. Por ejemplo, si dos procesos abren un mismo archivo en modo de escritura, es probable que los cambios que realice uno sobreescriban a los que haga el otro.
Ubicación en disco El sistema mantiene esta infromación para evitar que cada proceso tenga que consultar las tablas en disco para encontrar al archivo, o cada uno de sus fragmentos.
Información de bloqueo En caso de que los modos de acceso del archivo requieran protección mutua, puede hacerlo por medio de un bloqueo.
Por otro lado, el proceso necesita:
Descriptor de archivo Relación entre el nombre del archivo abierto y el identificador numérico que maneja internamente el proceso. Un archivo abierto por varios procesos tendrá descriptores de archivo distintos en cada uno de ellos. Al detallar la implementación, el descriptor de archivo otorgado por el sistema a un proceso es simplemente un número entero, que podría entenderse como el n-ésimo archivo empleado por el proceso.
Permisos Los modos válidos de acceso para un archivo. Esto no necesariamente es igual a los permisos que tiene el archivo en cuestión en disco, sino que el subconjunto de dichos permisos bajo los cuales está operando para este proceso en particular —si un archivo fue abierto en modo de sólo lectura, por ejemplo, este campo únicamente permitirá la lectura.
Acceso concurrente: bloqueo de archivos Dado que los archivos pueden emplearse como mecanismo de comunicación entre procesos que no guarden relación entre sí, incluso a lo largo del tiempo, y para emplear un archivo basta indicar su nombre o ruta, los sistemas operativos multitarea implementan mecanismos de bloqueo para evitar que varios procesos intentando emplear de forma concurrente a un archivo se corrompan mutuamente.
Compartido (Shared lock) Podría verse como equivalente a un bloqueo (o candado) para realizar lectura — varios procesos pueden adquirir al mismo tiempo un bloqueo de lectura, e indica que todos los que posean dicho candado tienen la expectativa de que el archivo no sufrirá modificaciones.
Exclusivo (Exclusive lock) Un bloqueo o candado exclusivo puede ser adquirido por un sólo proceso, e indica que realizará operaciones que modifiquen al archivo (o, si la semántica del sistema operativo permite expresarlo, a la porción del archivo que indica).
Mandatorio u obligatorio (Mandatory locking) Una vez que un proceso adquiere un candado obligatorio, el sistema operativo se encargará de imponer las restricciones corresponidentes de acceso a todos los demás procesos, independientemente de si éstos fueron programados para considerar la existencia de dicho bloqueo o no.
Tipos de archivo Si los archivos son la unidad lógica mínima con la que se puede guardar información en almacenamiento secundario, naturalmente sigue que hay archivos de diferentes tipos: cada uno podría ser un documento de texto, un binario ejecutable, un archivo de audio o video, o un larguísimo etcetera, e intentar emplear un archivo como uno de un tipo distinto puede resultar desde una frustración al usuario porque el programa no responde como éste quiere, hasta en pérdidas económicas.
Números mágicos La alternativa que emplean los sistemas Unix es, como siempre, simple y elegante, aunque indudablemente presenta eventuales lagunas: el sistema mantiene una lista compilada de las huellas digitales de los principales formatos que debe manejar,7 para reconocer el contenido de un archivo basado en sus primeros bytes.
Metadatos externos Los sistemas de archivos empleado por las Apple Macintosh desde 1984 separan en dos divisiones (forks) la información de un archivo: los datos que propiamente constituyen al archivo en cuestión son la división de datos (data fork), y la información acerca del archivo se guardan en una estructura independiente llamada división de recursos (resource fork).
Estructura de los archivos y métodos de acceso La razón principal del uso de sistemas de archivos son, naturalmente, los archivos. En estos se almacena información de algún tipo, con o sin una estructura predeterminada. La mayor parte de los sistemas operativos maneja únicamente archivos sin estructura —cada aplicación es responsable de preparar la información de forma congruente, y la responsabilidad del sistema operativo es únicamente entregarlo como un conjunto de bytes. Históricamente, hubo sistemas operativos, como IBM CICS (1968), IBM MVS (1974) o DEC VMS (1977), que administraban ciertos tipos de datos en un formato básico de base de datos.
Acceso secuencial Mantiene la semántica por medio de la cual permite leer de los archivos, de forma equivalente a como lo harían las unidades de cinta mencionadas en la sección 6.2.1, y como lo ilustra la figura 6.2: el mecanismo principal para leer o escribir es ir avanzando consecutivamente por los bytes que conforman al archivo hasta llegar a su final.
Acceso aleatorio El empleo de gestores como SQLite u otros muchos motores de base de datos más robustos no exime al usuario de pensar en el archivo como una tabla estructurada, como lo ilustra la figura 6.3. Si la única semántica por medio de la cual el sistema operativo permitiera trabajar con los archivos fuera la equivalente a una unidad de cinta, implementar el acceso a un punto determinado del archivo podría resultar demasiado costoso.
Acceso relativo a índice En los últimos años se han popularizado los gestores de base de datos débilmente estructurados u orientados a documentos, llamados genéricamente NoSQL. Estos gestores pueden guardar registros de tamaño variable en disco, por lo que, como lo ilustra la figura 6.4, no pueden encontrar la ubicación correcta por medio de los mecanismos de acceso aleatorio. Para implementar este acceso, se divide al conjunto de datos en dos secciones (incluso, posiblemente, en dos archivos independientes): la primer sección es una lista corta de identificadores, cada uno con el punto de inicio y término de los datos a los que apunta. Para leer un registro, se emplea acceso aleatorio sobre el índice, y el apuntador se avanza a la ubicación específica que se solicita.
Archivos especiales Los sistemas de archivos son estructuras de tan fácil manejo y comprensión que resulta natural que los diseñadores de sistemas operativos buscaran aprovecharlos para presentar todo tipo de estructuras, no sólo archivos. En este sentido, la máxima Unix, todo es un archivo, resulta el ejemplo natural. Este concepto fue brevemente presentado en la sección 2.8; complementando dicha sección, en un sistema Unix estándar, un archivo puede pertenecer a las siguientes categorías:
Archivo estándar Aunque suene obvio, el tipo básico de archivo es, precisamente, el archivo. Representa directamente la información que lo conforma. Su semántica de uso es la presentada en el transcurso de este capítulo.
Objetos del sistema de archivos La información acerca del sistema de archivos se almacena también dentro de archivos, aunque su tratamiento es especial (con una reminiscencia de los sistemas históricos mencionados en la sección 6.2.5): El sistema operativo oculta al archivo real, y gestiona su información procesada para que lo emplee el usuario. Este tipo de archivos puede referirse a directorios o a ligas simbólicas. Ambos se detallan en la sección
Dispositivos Permiten el acceso directo a un dispositivo externo. Como fue presentado en la sección 2.8, pueden ser de bloques o de caracteres. El contenido del archivo son dos números, el mayor y el menor; tradicionalmente, el mayor indica de qué clase de dispositivo se trata, y el menor, la instancia de que se trata.
Por ejemplo, tanto los discos duros como sus particiones llevan por número mayor el ocho; los números menores para los duros son 0, 16, 32, 48. Cada uno de los discos puede tener hasta 15 particiones: 1 a 15, 17 a 31, etcétera.
Comunicación entre procesos Los archivos pueden representar tuberías nombradas y sockets. Ambos son mecanismos que permiten intercambiar información entre distintos procesos; la tubería nombrada es más sencilla de emplear, pero permite únicamente la comunicación unidireccional, en tanto que el socket permite comunicación bidireccional como si se tratara de una conexión por red.
Transferencias orientadas a bloques Un sistema de archivos es la representación que se da a un conjunto de archivos y directorios sobre un dispositivo de bloques, esto es, un dispositivo que, para cualquier transferencia solicitada desde o hacia él, responderá con un bloque de tamaño predefinido. Esto es, si bien el sistema operativo presenta una abstracción por medio de la cual la lectura (read()) puede ser de un tamaño arbitrario, todas las 240 transferencias de datos desde cualquiera de los discos serán de un múltiplo del tamaño de bloques, definido por el hardware (típicamente 512 bytes).
Organización de archivos Hasta este punto, el enfoque ha sido en qué es y cómo se maneja un archivo. Sin embargo, no tendría sentido hablar de sistemas de archivos si no hubiera una gran cantidad de archivos. Es común que un sólo medio de almacenamiento de un equipo de uso casero aloje decenas de miles de archivos, y en equipos dedicados, no está fuera de lugar tener cientos o miles de veces tanto. Por tanto, se tiene que ver también cómo organizar una gran cantidad de archivos.
Evolución del concepto de directorio El concepto dominante en almacenamiento hoy en día es el de directorios jerárquicos. Esto no siempre fue así; conviene revisar brevemente su historia para explicar la razón de ciertos detalles de implementación del esquema actualmente dominante
Convenciones de nomenclatura Cada sistema de archivos puede determinar cuántos y qué caracteres son válidos para designar a uno de sus elementos, y cuáles son separadores válidos. El caracter que se emplea para separar los elementos de un directorio no es un estándar a través de todos los sistemas operativos —los más comunes en uso hoy en día son la diagonal (/), empleada en sistemas tipo Unix y derivados (incluyendo MacOS X y Android), y la diagonal invertida (\), empleada en CP/M y derivados, incluyendo MS-DOS y Windows
Sistema de archivos plano Los primeros sistemas de archivos limitaban el concepto de directorio a una representación plana de los archivos que lo conformaban, sin ningún concepto de jerarquía de directorios como el que hoy resulta natural a los usuarios. Esto se debía, en primer término, a lo limitado del espacio de almacenamiento de las primeras computadoras en implementar esta metáfora (por lo limitado del espacio de almacenamiento, los usuarios no dejaban sus archivos a largo plazo en el disco, sino que los tenían ahí meramente mientras los requerían), y en segundo término, a que no se había aún desarrollado un concepto de separación, permisos y privilegios como el que poco después aparecería.
Directorios de profundidad fija Las primeras implementaciones de directorios eran de un sólo nivel: el total de archivos en un sistema podía estar dividido en directorios, fuera por tipo de archivo (separando, por ejemplo, programas de sistema, programas de usuario y textos del correo), por usuario (facilitando una separación lógica de los archivos de un usuario de pertenecientes a los demás usuarios del sistema) El directorio raíz (base) se llama en este esquema MFD (master file directory, directorio maestro de archivos), y cada uno de los directorios derivados es un UFD (user file directory, directorio de archivos de usuario).
Directorios estructurados en árbol El siguiente paso natural para este esquema es permitir una jerarquía ilimitada: en vez de exigir que haya una capa de directorios, se le puede dar la vuelta al argumento, y permitir que cada directorio pueda contener a otros archivos o directorios anidados arbitrariamente. Esto permite que cada usuario (y que el administrador del sistema) estructure su información siguiendo criterios lógicos y piense en el espacio de almacenamiento como un espacio a largo plazo.
El directorio como un grafo dirigido Si bien parecería que muchos de los sistemas de archivos empleados hoy en día pueden modelarse suficientemente con un árbol, donde hay un sólo nodo raíz, y donde cada uno de los nodos tiene un sólo nodo padre, la semántica que ofrecen es en realidad un superconjunto estricto de ésta: la de un grafo dirigido. En un grafo dirigido como el presentado en la figura 6.7, un mismo nodo puede tener varios directorios padre, permitiendo, por ejemplo, que un directorio de trabajo común sea parte del directorio personal de dos usuarios. Esto es, el mismo objeto está presente en más de un punto del árbol.
Liga o enlace duro La entrada de un archivo en un directorio Unix es la relación entre la ruta del archivo y el número de i-nodo en el sistema de archivos.12 Si a partir de un archivo en cualquier punto del árbol se crea una liga dura a él, ésta es sencillamente otra entrada en el directorio apuntando al mismo i-nodo. Ambas entradas, pues, son el mismo archivo —no hay uno maestro y uno dependiente. En un sistema Unix, este mecanismo tiene sólo dos restricciones:
1. Sólo se pueden hacer ligas duras dentro del mismo volumen.
2. No pueden hacerse ligas duras a directorios, sólo a archivos.
Liga o enlace simbólico Es un archivo especial, que meramente indica a dónde apunta. El encargado de seguir este archivo a su destino (esto es, de resolver la liga simbólica) es el sistema operativo mismo; un proceso no tiene que hacer nada especial para seguir la liga. Una liga simbólica puede apuntar a directorios, incluso creando ciclos, o a archivos en otros volúmenes.
Operaciones con directorios Al igual que los archivos, los directorios tienen una semántica básica de acceso. Éstos resultan también tipos de datos abstractos con algunas operaciones definidas. Muchas de las operaciones que pueden realizarse con los directorios son análogas a las empleadas para los archivos.15 Las operaciones básicas a presentar son:
Abrir y cerrar Como en el caso de los archivos un programa que requiera trabajar con un directorio deberá abrirlo para hacerlo, y cerrarlo cuando ya no lo requiera. Para esto, en C, se emplean las funciones opendir() y closedir(). Estas funciones trabajan asociadas a un flujo de directorio (directory stream), que funciona de forma análoga a un descriptor de archivo.
Listado de archivos Para mostrar los archivos que conforman a un directorio, una vez que se abrió el directorio se abre, el programa lee (con readdir()) cada una de sus entradas. Cada uno de los resultados es una estructura dirent (directory entry, esto es, entrada de directorio), que contiene su nombre en d_name, un apuntador a su i-nodo en d_ino, y algunos datos adicionales del archivo en cuestión.
Buscar un elemento Si bien en el transcurso del uso del sistema operativo resulta una operación frecuente que el usuario solicite el listado de archivos dentro de un directorio, es mucho más frecuente buscar a un archivo en particular. La llamada fopen() antes descrita efectúa una búsqueda similar a la presentada en el ejemplo de código anterior, claro está, deteniéndose cuando encuentra al archivo en cuestión.
Crear, eliminar o renombrar un elemento Si bien estas operaciones se llevan a cabo sobre el directorio, son invocadas por medio de la semántica orientada a archivos: un archivo es creado con fopen(), eliminado con remove(), y renombrado con rename
Recorriendo los directorios Es frecuente tener que aplicar una operación a todos los archivos dentro de cierto directorio, por ejemplo, para agrupar un directorio completo en un archivo comprimido, o para copiar todos sus contenidos a otro medio; procesar todas las entradas de un directorio, incluyendo las de sus subdirectorios, se denomina recorrer el directorio (en inglés, directory traversal). Si se trabaja sobre un sistema de archivos plano, la operación de recorrido completo puede realizarse con un programa tan simple como el presentado en la sección anterior
Otros esquemas de organización Por más que el uso de sistemas de archivos basados en directorios jerárquicos parece universal y es muy ampliamente aceptado, hay cada vez más casos de uso que apuntan a que se pueda estar por dar la bienvenida a una nueva metáfora de organización de archivos. Hay distintas propuestas, y claro está, es imposible aún saber cuál dirección obtendrá el favor del mercado —o, dado que no necesariamente siga habiendo un modelo apto para todos los usos, de qué segmento del mercado.
Montaje de directorios Para trabajar con el contenido de un sistema de archivos, el sistema operativo tiene que montarlo: ubicarlo en algún punto del árbol de archivos visible al sistema y al usuario. Es muy común, especialmente en los entornos derivados de Unix, que un sistema operativo trabaje con distintos sistemas de archivos al mismo tiempo. Esto puede obedecer a varias causas, entre las cuales se encuentran:
Distintos medios físicos Si la computadora tiene más de una unidad de almacenamiento, el espacio dentro de cada uno de los discos se maneja como un sistema de archivos indepentiente. Esto es especialmente cierto en la presencia de unidades removibles (CD, unidades USB, discos duros externos, etc.)
Diferentes usos esperados Como se verá más adelante, distintos esquemas de organización (esto es, distintos sistemas de archivos) presentan ventajas para diversos patrones de uso. Por ejemplo, tiene sentido que una base de datos resida sobre una organización distinta a la de los programas ejecutables (binarios) del sistema.
Abstracciones de sistemas no-físicos El sistema operativo puede presentar diversas estructuras con una estructura de sistema de archivos. El ejemplo más claro de esto es el sistema de archivos virtual /proc, presente en los sistemas Unix, que permite ver diversos aspectos de los procesos en ejecución (y, en Linux, del sistema en general). Los archivos bajo /proc no están en ningún disco, pero se presentan como si fueran archivos estándar
Razones administrativas El administrador del sistema puede emplear sistemas de archivos distintos para aislar espacios de usuarios entre sí: por ejemplo, para evitar que un exceso de mensajes enviados en la bitácora (típicamente bajo /var/log) saturen al sistema de archivos principal, o para determinar patrones de uso máximo por grupos de usuarios.
Control de acceso Parte importante de la información que se almacena respecto a cada uno de los archivos, directorios u otros objetos son sus permisos de acceso. Éstos indican al sistema qué puede hacerse y qué no con cada uno de los objetos, posiblemente diferenciando el acceso dependiendo del usuario o clase de usuarios de que se trate. Hay muchos esquemas de control de acceso; a continuación se presentan tres esquemas, comenzando por el más simple, y avanzando hacia los más complejos.
Sistemas FAT El sistema de archivos FAT19 fue diseñado a fines de los setenta, y al día de hoy es muy probablemente el sistema de archivos más ampliamente utilizado del mundo. Su diseño es suficientemente simple para ser incluido en dispositivos muy limitados; esta simplicidad se demostrará al analizar sus principales estructuras son analizadas en el capítulo 7. Y por otro lado, con sólo modificaciones relativamente menores a su diseño original, ha logrado extenderse de un sistema pensado para volúmenes de 150 KB hasta llegar a las decenas de gigabytes.
En cada una de las entradas del directorio en un sistema FAT, el byte número 12 almacena los siguientes atributos:
Oculto Si está encendido, el archivo no se deberá mostrar al usuario en listados de directorio.
Sólo lectura El sistema operativo debe evitar toda modificación al archivo, esto es, rechazar las llamadas al sistema que soliciten esta modificación.
Sistema Como se explicará en la sección 7.1.4, un sistema de archivos FAT tiende conforme se va utilizando a fragmentar los archivos que almacena. La carga del sistema operativo tiene que realizarse empleando código lo más compacto y sencillo posible: sin siquiera tener conocimiento del sistema de archivos. Este atributo indica que el sistema operativo debe cuidar no mover ni fragmentar al archivo en cuestión.
Archivado MS-DOS incluía herramientas bastante sencillas para realizar respaldos; estas basaban su operación en este atributo: Conforme se realizaba un respaldo, todos los archivos iban siendo marcados como archivados. Y cuando un archivo era modificado, el sistema operativo retiraba este atributo. De esta manera, el siguiente respaldo contendría únicamente los archivos que habían sido modificados desde el respaldo anterior
Estos atributos eran suficientes para las necesidades de un sistema de uso personal de hace más de tres décadas. Sin embargo, y dado que está reservado todo un byte para los atributos, algunos sistemas extendieron los atributos cubriendo distintas necesidades. Estos cuatro atributos son, sin embargo, la base del sistema.
Modelo tradicional Unix El sistema Unix precede a MS-DOS por una década. Sin embargo, su concepción es de origen para un esquema multiusuario, con las provisiones necesarias para que cada uno de ellos indique qué usuarios pueden o no tener diferentes tipos de acceso a los archivos. En Unix, cada uno de los usuarios pertenece a uno o más grupos. Estos grupos son gestionados por el administrador del sistema. Cada objeto en el sistema de archivos describe sus permisos de acceso por nueve bits, y con el identificador de su usuario y grupo propietarios.
Listas de control de acceso Una de las desventajas del modelo tradicional de usuarios Unix es que requiere de la intervención del administrador del sistema para cada nuevo proyecto: el administrador del sistema tuvo que crear al grupo factura antes de que pudiera realizarse ningún trabajo de forma colaborativa. Además, encontrar la representación justa para indicar un conjunto específico de permisos puede ser complicado. Dado que un archivo no puede pertenecer a más de un grupo, puede hacerse necesario crear conjuntos de grupos adicionales que intersectan aspectos específicos: una salida muy poco elegante
Sistemas de archivos remotos Uno de los principales y primeros usos que se dio a la comunicación en red fue el de compartir archivos entre computadoras independientes. En un principio, esto se realizaba de forma explícita, con transferencias manuales mediante de programas dedicados a ello, como sería hoy en día el FTP. Por otro lado, desde mediados de los ochenta, es posible realizar estas transferencias de forma implícita y automática, empleando sistemas de archivos sobre la red (o lo que es lo mismo, sistemas de archivos remotos). Éstos se presentan como caso particular de la abstracción de sistemas no-físicos que fueron mencionados en la sección anterior: si bien el sistema operativo no tiene acceso directo a los archivos y directorios que le solicitará el usuario, por medio de los módulos de red, sabe cómo obtenerlos y presentarlos como si fueran locales.
Network File System (NFS) El Sistema de Archivos en Red (Network File System, mejor conocido como NFS) fue creado por Sun Microsystems, y desde 1984 forma parte de su sistema operativo —resultó una implementación tan exitosa que a los pocos años formaba parte de todos los sistemas tipo Unix. Está construido sobre el mecanismo RPC (remote procedure call, llamada a procedimientos remotos), un mecanismo de mensajes y manejo básico de sesión que actúa como una capa superior a TCP/IP, incluyendo facilidades de descubrimiento de recursos y abstracción. RPC puede ser comparado con protocolos como DCE/RPC de OSF, DCOM de Microsoft, y hoy en día, SOAP y XML-RPC. Estos mecanismos permiten al programador delegar en un servicio el manejo de las conexiones de red, particularmente (en el caso particular aquí descrito) la persistencia de sesiones en caso de desconexión, y limitar su atención a una conexión virtual establecida. La motivación de ori
Common Internet File System (CIFS) El equivalente a NFS en los entornos donde predominan los sistemas Windows es el protocolo CIFS (Common Internet File System, Sistema de Archivos Común para Internet). Aparece en los sistemas primarios de Microsoft alrededor de 1990,23 originalmente bajo el nombre SMB (server message block, bloque de mensaje del servidor). Las primeras implementaciones estaban basadas en el protocolo NBF, frecuentemente conocido como NetBEUI, un protocolo no ruteable diseñado para redes pequeñas y entornos sencillos de oficina. A partir de Windows 2000 se ha reimplementado completamente para operar sobre TCP/IP. Es a partir de este momento que se le comienza a denominar CIFS, aunque el nombre SMB sigue siendo ampliamente utilizado.
Sistemas de archivos distribuidos: Andrew File System Los dos ejemplos de sistema de archivos en red presentados hasta ahora comparten una visión tradicional del modelo cliente-servidor: al ver el comando que inicializa una conexión, e incluso a ver la información que guarda el núcleo del cliente respecto a cualquiera de los archivos, resulta claro cuál es el servidor para cada uno de ellos.
La autenticación en AFS se basa fuertemente sobre el modelo de tickets y credenciales de Kerberos, 29 pero se aleja sensiblemente de la semántica de operación de archivos que hasta ahora se han presentado. Muchos eventos, operaciones y estados van ligados al momento en el tiempo en que se presentan, mediante un modelo de consistencia débil (weak consistency model). Muy a grandes rasgos, esto significa que:
Cuando se abre un archivo, éste se copia completo al cliente. Todas las lecturas y escrituras (a diferencia de los esquemas tradicionales, en que éstas son enviadas al servidor lo antes posible y de forma síncrona) se dirigen únicamente a la copia local.
Al cerrar el archivo, éste se copia de vuelta al servidor de origen, el cual se compromete a notificar a los clientes si un archivo abierto fue modificado (esto es, a hacer una llamada o callback). Los clientes pueden entonces intentar incorporar los cambios a su versión de trabajo, o continuar con la copia ya obtenida —es de esperarse que si un segundo cliente realiza alguna modificación, incorpore los cambios hechos por el primero, pero esta responsabilidad se deja a la implementación del programa en cuestión
Concepto de archivo En primer término, un archivo es un /tipo de datos abstracto/— esto es, podría verse como una estructura que exclusivamente permite la manipulación por medio de una interfaz orientada a objetos: los procesos en el sistema sólo pueden tener acceso a los archivos por medio de la interfaz ofrecida por el sistema operativo.3 La siguiente sección describe las principales operaciones provistas por esta interfaz. Para el usuario, los archivos son la unidad lógica mínima al hablar de almacenamiento: todo el almacenamiento persistente (que sobrevive en el tiempo, sea a reinicios del sistema, a pérdida de corriente o a otras circunstancias en el transcurso normal de ejecución) en el sistema al que tiene acceso, se efectúa dentro de archivos; el espacio libre en los diferentes dispositivos no tiene mayor presencia fuera de saber que está potencialmente disponible.
Operaciones con archivos Cada sistema operativo definirá la interfaz de archivos acorde con su semántica, pero en líneas generales, las operaciones que siempre estarán disponibles con un archivo son:
Borrar Elimina al archivo del directorio y, de ser procedente, libera el espacio del dispositivo
Abrir Solicita al sistema operativo verificar si el archivo existe o puede ser creado (dependiendo del modo requerido) y se cuenta con el acceso para el modo de acceso al archivo indicado y si el medio lo soporta (por ejemplo, a pesar de contar con todos los permisos necesarios, el sistema operativo no debe permitir abrir para escritura un archivo en un CD-ROM u otro medio de sólo lectura). En C, esto se hace con la función
Cerrar Indica al sistema que el proceso en cuestión terminó de trabajar con el archivo; el sistema entonces debe escribir los buffers a disco y eliminar la entrada que representa a esta combinación archivo-proceso de las tablas activas, invalidando al descriptor de archivo. En C, para cerrar un descriptor de archivo se usa fclose(). Dado que todas las operaciones se realizan por medio del descriptor de archivo, si un proceso cierra un archivo y requiere seguir utilizándolo, tendrá que abrirlo de nuevo para obtener un nuevo descriptor.
Leer Si se solicita al sistema la lectura leer de un archivo hacia determinado buffer, éste copia el siguiente pedazo de información al. Este pedazo podría ser una línea o un bloque de longitud definida, dependiendo del modo en que se solicite la lectura. El sistema mantiene un apuntador a la última posición leída, para poder continuar con la lectura de forma secuencial.
Escribir Teniendo un archivo abierto, guarda información en él. Puede ser que escriba desde su primer posición (truncando al archivo, esto es, borrando toda la información que pudiera ya tener), o agregando al archivo, esto es, iniciando con el apuntador de escritura al final del mismo. La función C para escribir a un descriptor de archivo es fwrite().
Reposicionar Tanto la lectura como la escritura se hacen siguiendo un apuntador, que indica cuál fue la última posición del archivo a la que accesó el proceso actual. Al reposicionar el apuntador, se puede saltar a otro punto del archivo. La función que reposiciona el apuntador dentro de un descriptor de archivos es fseek().
Hay varias otras operaciones comunes que pueden implementarse con llamadas compuestas a estas operaciones (por ejemplo, copiar un archivo puede verse como crear un archivo nuevo en modo de escritura, abrir en modo de lectura al archivo fuente, e ir leyendo de éste y escribiendo al nuevo hasta llegar al fin de archivo fuente).
Tablas de archivos abiertos Tanto el sistema operativo como cada uno de los procesos mantienen normalmente tablas de archivos abiertos. Éstas mantienen información acerca de todos los archivos actualmente abiertos, presentándolos hacia el proceso por medio de un descriptor de archivo; una vez que un archivo fue abierto, las operaciones que se realizan dentro de éste no son empleando su nombre, sino su descriptor de archivo. En un sistema operativo multitareas, más de un proceso podría abrir el mismo archivo a la vez; lo que cada uno de ellos pueda hacer, y cómo esto repercute en lo que vean los demás procesos, depende de la semántica que implemente el sistema; un ejemplo de las diferentes semánticas posibles es el descrito en la sección
Conteo de usuarios del archivo Requiere saberse cuántos procesos están empleando en todo momento a determinado archivo. Esto permite, por ejemplo, que cuando el usuario solicite desmontar una partición (puede ser para expulsar una unidad removible) o eliminar un archivo, el sistema debe poder determinar cuándo es momento de declarar la solicitud como efectuada. Si algún proceso tiene abierto un archivo, y particularmente si tiene cambios pendientes de guardar, el sistema debe hacer lo posible por evitar que el archivo desaparezca de su visión.
Modos de acceso Aunque un usuario tenga permisos de acceso a determinado recurso, el sistema puede determinar negarlo si llevaría a una inconsistencia. Por ejemplo, si dos procesos abren un mismo archivo en modo de escritura, es probable que los cambios que realice uno sobreescriban a los que haga el otro.
Ubicación en disco El sistema mantiene esta infromación para evitar que cada proceso tenga que consultar las tablas en disco para encontrar al archivo, o cada uno de sus fragmentos.
Información de bloqueo En caso de que los modos de acceso del archivo requieran protección mutua, puede hacerlo por medio de un bloqueo.
Por otro lado, el proceso necesita:
Descriptor de archivo Relación entre el nombre del archivo abierto y el identificador numérico que maneja internamente el proceso. Un archivo abierto por varios procesos tendrá descriptores de archivo distintos en cada uno de ellos. Al detallar la implementación, el descriptor de archivo otorgado por el sistema a un proceso es simplemente un número entero, que podría entenderse como el n-ésimo archivo empleado por el proceso.
Permisos Los modos válidos de acceso para un archivo. Esto no necesariamente es igual a los permisos que tiene el archivo en cuestión en disco, sino que el subconjunto de dichos permisos bajo los cuales está operando para este proceso en particular —si un archivo fue abierto en modo de sólo lectura, por ejemplo, este campo únicamente permitirá la lectura.
Acceso concurrente: bloqueo de archivos Dado que los archivos pueden emplearse como mecanismo de comunicación entre procesos que no guarden relación entre sí, incluso a lo largo del tiempo, y para emplear un archivo basta indicar su nombre o ruta, los sistemas operativos multitarea implementan mecanismos de bloqueo para evitar que varios procesos intentando emplear de forma concurrente a un archivo se corrompan mutuamente.
Compartido (Shared lock) Podría verse como equivalente a un bloqueo (o candado) para realizar lectura — varios procesos pueden adquirir al mismo tiempo un bloqueo de lectura, e indica que todos los que posean dicho candado tienen la expectativa de que el archivo no sufrirá modificaciones.
Exclusivo (Exclusive lock) Un bloqueo o candado exclusivo puede ser adquirido por un sólo proceso, e indica que realizará operaciones que modifiquen al archivo (o, si la semántica del sistema operativo permite expresarlo, a la porción del archivo que indica).
Mandatorio u obligatorio (Mandatory locking) Una vez que un proceso adquiere un candado obligatorio, el sistema operativo se encargará de imponer las restricciones corresponidentes de acceso a todos los demás procesos, independientemente de si éstos fueron programados para considerar la existencia de dicho bloqueo o no.
Tipos de archivo Si los archivos son la unidad lógica mínima con la que se puede guardar información en almacenamiento secundario, naturalmente sigue que hay archivos de diferentes tipos: cada uno podría ser un documento de texto, un binario ejecutable, un archivo de audio o video, o un larguísimo etcetera, e intentar emplear un archivo como uno de un tipo distinto puede resultar desde una frustración al usuario porque el programa no responde como éste quiere, hasta en pérdidas económicas.
Números mágicos La alternativa que emplean los sistemas Unix es, como siempre, simple y elegante, aunque indudablemente presenta eventuales lagunas: el sistema mantiene una lista compilada de las huellas digitales de los principales formatos que debe manejar,7 para reconocer el contenido de un archivo basado en sus primeros bytes.
Metadatos externos Los sistemas de archivos empleado por las Apple Macintosh desde 1984 separan en dos divisiones (forks) la información de un archivo: los datos que propiamente constituyen al archivo en cuestión son la división de datos (data fork), y la información acerca del archivo se guardan en una estructura independiente llamada división de recursos (resource fork).
Estructura de los archivos y métodos de acceso La razón principal del uso de sistemas de archivos son, naturalmente, los archivos. En estos se almacena información de algún tipo, con o sin una estructura predeterminada. La mayor parte de los sistemas operativos maneja únicamente archivos sin estructura —cada aplicación es responsable de preparar la información de forma congruente, y la responsabilidad del sistema operativo es únicamente entregarlo como un conjunto de bytes. Históricamente, hubo sistemas operativos, como IBM CICS (1968), IBM MVS (1974) o DEC VMS (1977), que administraban ciertos tipos de datos en un formato básico de base de datos.
Acceso secuencial Mantiene la semántica por medio de la cual permite leer de los archivos, de forma equivalente a como lo harían las unidades de cinta mencionadas en la sección 6.2.1, y como lo ilustra la figura 6.2: el mecanismo principal para leer o escribir es ir avanzando consecutivamente por los bytes que conforman al archivo hasta llegar a su final.
Acceso aleatorio El empleo de gestores como SQLite u otros muchos motores de base de datos más robustos no exime al usuario de pensar en el archivo como una tabla estructurada, como lo ilustra la figura 6.3. Si la única semántica por medio de la cual el sistema operativo permitiera trabajar con los archivos fuera la equivalente a una unidad de cinta, implementar el acceso a un punto determinado del archivo podría resultar demasiado costoso.
Acceso relativo a índice En los últimos años se han popularizado los gestores de base de datos débilmente estructurados u orientados a documentos, llamados genéricamente NoSQL. Estos gestores pueden guardar registros de tamaño variable en disco, por lo que, como lo ilustra la figura 6.4, no pueden encontrar la ubicación correcta por medio de los mecanismos de acceso aleatorio. Para implementar este acceso, se divide al conjunto de datos en dos secciones (incluso, posiblemente, en dos archivos independientes): la primer sección es una lista corta de identificadores, cada uno con el punto de inicio y término de los datos a los que apunta. Para leer un registro, se emplea acceso aleatorio sobre el índice, y el apuntador se avanza a la ubicación específica que se solicita.
Archivos especiales Los sistemas de archivos son estructuras de tan fácil manejo y comprensión que resulta natural que los diseñadores de sistemas operativos buscaran aprovecharlos para presentar todo tipo de estructuras, no sólo archivos. En este sentido, la máxima Unix, todo es un archivo, resulta el ejemplo natural. Este concepto fue brevemente presentado en la sección 2.8; complementando dicha sección, en un sistema Unix estándar, un archivo puede pertenecer a las siguientes categorías:
Archivo estándar Aunque suene obvio, el tipo básico de archivo es, precisamente, el archivo. Representa directamente la información que lo conforma. Su semántica de uso es la presentada en el transcurso de este capítulo.
Objetos del sistema de archivos La información acerca del sistema de archivos se almacena también dentro de archivos, aunque su tratamiento es especial (con una reminiscencia de los sistemas históricos mencionados en la sección 6.2.5): El sistema operativo oculta al archivo real, y gestiona su información procesada para que lo emplee el usuario. Este tipo de archivos puede referirse a directorios o a ligas simbólicas. Ambos se detallan en la sección
Dispositivos Permiten el acceso directo a un dispositivo externo. Como fue presentado en la sección 2.8, pueden ser de bloques o de caracteres. El contenido del archivo son dos números, el mayor y el menor; tradicionalmente, el mayor indica de qué clase de dispositivo se trata, y el menor, la instancia de que se trata.
Por ejemplo, tanto los discos duros como sus particiones llevan por número mayor el ocho; los números menores para los duros son 0, 16, 32, 48. Cada uno de los discos puede tener hasta 15 particiones: 1 a 15, 17 a 31, etcétera.
Comunicación entre procesos Los archivos pueden representar tuberías nombradas y sockets. Ambos son mecanismos que permiten intercambiar información entre distintos procesos; la tubería nombrada es más sencilla de emplear, pero permite únicamente la comunicación unidireccional, en tanto que el socket permite comunicación bidireccional como si se tratara de una conexión por red.
Transferencias orientadas a bloques Un sistema de archivos es la representación que se da a un conjunto de archivos y directorios sobre un dispositivo de bloques, esto es, un dispositivo que, para cualquier transferencia solicitada desde o hacia él, responderá con un bloque de tamaño predefinido. Esto es, si bien el sistema operativo presenta una abstracción por medio de la cual la lectura (read()) puede ser de un tamaño arbitrario, todas las 240 transferencias de datos desde cualquiera de los discos serán de un múltiplo del tamaño de bloques, definido por el hardware (típicamente 512 bytes).
Organización de archivos Hasta este punto, el enfoque ha sido en qué es y cómo se maneja un archivo. Sin embargo, no tendría sentido hablar de sistemas de archivos si no hubiera una gran cantidad de archivos. Es común que un sólo medio de almacenamiento de un equipo de uso casero aloje decenas de miles de archivos, y en equipos dedicados, no está fuera de lugar tener cientos o miles de veces tanto. Por tanto, se tiene que ver también cómo organizar una gran cantidad de archivos.
Evolución del concepto de directorio El concepto dominante en almacenamiento hoy en día es el de directorios jerárquicos. Esto no siempre fue así; conviene revisar brevemente su historia para explicar la razón de ciertos detalles de implementación del esquema actualmente dominante
Convenciones de nomenclatura Cada sistema de archivos puede determinar cuántos y qué caracteres son válidos para designar a uno de sus elementos, y cuáles son separadores válidos. El caracter que se emplea para separar los elementos de un directorio no es un estándar a través de todos los sistemas operativos —los más comunes en uso hoy en día son la diagonal (/), empleada en sistemas tipo Unix y derivados (incluyendo MacOS X y Android), y la diagonal invertida (\), empleada en CP/M y derivados, incluyendo MS-DOS y Windows
Sistema de archivos plano Los primeros sistemas de archivos limitaban el concepto de directorio a una representación plana de los archivos que lo conformaban, sin ningún concepto de jerarquía de directorios como el que hoy resulta natural a los usuarios. Esto se debía, en primer término, a lo limitado del espacio de almacenamiento de las primeras computadoras en implementar esta metáfora (por lo limitado del espacio de almacenamiento, los usuarios no dejaban sus archivos a largo plazo en el disco, sino que los tenían ahí meramente mientras los requerían), y en segundo término, a que no se había aún desarrollado un concepto de separación, permisos y privilegios como el que poco después aparecería.
Directorios de profundidad fija Las primeras implementaciones de directorios eran de un sólo nivel: el total de archivos en un sistema podía estar dividido en directorios, fuera por tipo de archivo (separando, por ejemplo, programas de sistema, programas de usuario y textos del correo), por usuario (facilitando una separación lógica de los archivos de un usuario de pertenecientes a los demás usuarios del sistema) El directorio raíz (base) se llama en este esquema MFD (master file directory, directorio maestro de archivos), y cada uno de los directorios derivados es un UFD (user file directory, directorio de archivos de usuario).
Directorios estructurados en árbol El siguiente paso natural para este esquema es permitir una jerarquía ilimitada: en vez de exigir que haya una capa de directorios, se le puede dar la vuelta al argumento, y permitir que cada directorio pueda contener a otros archivos o directorios anidados arbitrariamente. Esto permite que cada usuario (y que el administrador del sistema) estructure su información siguiendo criterios lógicos y piense en el espacio de almacenamiento como un espacio a largo plazo.
El directorio como un grafo dirigido Si bien parecería que muchos de los sistemas de archivos empleados hoy en día pueden modelarse suficientemente con un árbol, donde hay un sólo nodo raíz, y donde cada uno de los nodos tiene un sólo nodo padre, la semántica que ofrecen es en realidad un superconjunto estricto de ésta: la de un grafo dirigido. En un grafo dirigido como el presentado en la figura 6.7, un mismo nodo puede tener varios directorios padre, permitiendo, por ejemplo, que un directorio de trabajo común sea parte del directorio personal de dos usuarios. Esto es, el mismo objeto está presente en más de un punto del árbol.
Liga o enlace duro La entrada de un archivo en un directorio Unix es la relación entre la ruta del archivo y el número de i-nodo en el sistema de archivos.12 Si a partir de un archivo en cualquier punto del árbol se crea una liga dura a él, ésta es sencillamente otra entrada en el directorio apuntando al mismo i-nodo. Ambas entradas, pues, son el mismo archivo —no hay uno maestro y uno dependiente. En un sistema Unix, este mecanismo tiene sólo dos restricciones:
1. Sólo se pueden hacer ligas duras dentro del mismo volumen.
2. No pueden hacerse ligas duras a directorios, sólo a archivos.
Liga o enlace simbólico Es un archivo especial, que meramente indica a dónde apunta. El encargado de seguir este archivo a su destino (esto es, de resolver la liga simbólica) es el sistema operativo mismo; un proceso no tiene que hacer nada especial para seguir la liga. Una liga simbólica puede apuntar a directorios, incluso creando ciclos, o a archivos en otros volúmenes.
Operaciones con directorios Al igual que los archivos, los directorios tienen una semántica básica de acceso. Éstos resultan también tipos de datos abstractos con algunas operaciones definidas. Muchas de las operaciones que pueden realizarse con los directorios son análogas a las empleadas para los archivos.15 Las operaciones básicas a presentar son:
Abrir y cerrar Como en el caso de los archivos un programa que requiera trabajar con un directorio deberá abrirlo para hacerlo, y cerrarlo cuando ya no lo requiera. Para esto, en C, se emplean las funciones opendir() y closedir(). Estas funciones trabajan asociadas a un flujo de directorio (directory stream), que funciona de forma análoga a un descriptor de archivo.
Listado de archivos Para mostrar los archivos que conforman a un directorio, una vez que se abrió el directorio se abre, el programa lee (con readdir()) cada una de sus entradas. Cada uno de los resultados es una estructura dirent (directory entry, esto es, entrada de directorio), que contiene su nombre en d_name, un apuntador a su i-nodo en d_ino, y algunos datos adicionales del archivo en cuestión.
Buscar un elemento Si bien en el transcurso del uso del sistema operativo resulta una operación frecuente que el usuario solicite el listado de archivos dentro de un directorio, es mucho más frecuente buscar a un archivo en particular. La llamada fopen() antes descrita efectúa una búsqueda similar a la presentada en el ejemplo de código anterior, claro está, deteniéndose cuando encuentra al archivo en cuestión.
Crear, eliminar o renombrar un elemento Si bien estas operaciones se llevan a cabo sobre el directorio, son invocadas por medio de la semántica orientada a archivos: un archivo es creado con fopen(), eliminado con remove(), y renombrado con rename
Recorriendo los directorios Es frecuente tener que aplicar una operación a todos los archivos dentro de cierto directorio, por ejemplo, para agrupar un directorio completo en un archivo comprimido, o para copiar todos sus contenidos a otro medio; procesar todas las entradas de un directorio, incluyendo las de sus subdirectorios, se denomina recorrer el directorio (en inglés, directory traversal). Si se trabaja sobre un sistema de archivos plano, la operación de recorrido completo puede realizarse con un programa tan simple como el presentado en la sección anterior
Otros esquemas de organización Por más que el uso de sistemas de archivos basados en directorios jerárquicos parece universal y es muy ampliamente aceptado, hay cada vez más casos de uso que apuntan a que se pueda estar por dar la bienvenida a una nueva metáfora de organización de archivos. Hay distintas propuestas, y claro está, es imposible aún saber cuál dirección obtendrá el favor del mercado —o, dado que no necesariamente siga habiendo un modelo apto para todos los usos, de qué segmento del mercado.
Montaje de directorios Para trabajar con el contenido de un sistema de archivos, el sistema operativo tiene que montarlo: ubicarlo en algún punto del árbol de archivos visible al sistema y al usuario. Es muy común, especialmente en los entornos derivados de Unix, que un sistema operativo trabaje con distintos sistemas de archivos al mismo tiempo. Esto puede obedecer a varias causas, entre las cuales se encuentran:
Distintos medios físicos Si la computadora tiene más de una unidad de almacenamiento, el espacio dentro de cada uno de los discos se maneja como un sistema de archivos indepentiente. Esto es especialmente cierto en la presencia de unidades removibles (CD, unidades USB, discos duros externos, etc.)
Diferentes usos esperados Como se verá más adelante, distintos esquemas de organización (esto es, distintos sistemas de archivos) presentan ventajas para diversos patrones de uso. Por ejemplo, tiene sentido que una base de datos resida sobre una organización distinta a la de los programas ejecutables (binarios) del sistema.
Abstracciones de sistemas no-físicos El sistema operativo puede presentar diversas estructuras con una estructura de sistema de archivos. El ejemplo más claro de esto es el sistema de archivos virtual /proc, presente en los sistemas Unix, que permite ver diversos aspectos de los procesos en ejecución (y, en Linux, del sistema en general). Los archivos bajo /proc no están en ningún disco, pero se presentan como si fueran archivos estándar
Razones administrativas El administrador del sistema puede emplear sistemas de archivos distintos para aislar espacios de usuarios entre sí: por ejemplo, para evitar que un exceso de mensajes enviados en la bitácora (típicamente bajo /var/log) saturen al sistema de archivos principal, o para determinar patrones de uso máximo por grupos de usuarios.
Control de acceso Parte importante de la información que se almacena respecto a cada uno de los archivos, directorios u otros objetos son sus permisos de acceso. Éstos indican al sistema qué puede hacerse y qué no con cada uno de los objetos, posiblemente diferenciando el acceso dependiendo del usuario o clase de usuarios de que se trate. Hay muchos esquemas de control de acceso; a continuación se presentan tres esquemas, comenzando por el más simple, y avanzando hacia los más complejos.
Sistemas FAT El sistema de archivos FAT19 fue diseñado a fines de los setenta, y al día de hoy es muy probablemente el sistema de archivos más ampliamente utilizado del mundo. Su diseño es suficientemente simple para ser incluido en dispositivos muy limitados; esta simplicidad se demostrará al analizar sus principales estructuras son analizadas en el capítulo 7. Y por otro lado, con sólo modificaciones relativamente menores a su diseño original, ha logrado extenderse de un sistema pensado para volúmenes de 150 KB hasta llegar a las decenas de gigabytes.
En cada una de las entradas del directorio en un sistema FAT, el byte número 12 almacena los siguientes atributos:
Oculto Si está encendido, el archivo no se deberá mostrar al usuario en listados de directorio.
Sólo lectura El sistema operativo debe evitar toda modificación al archivo, esto es, rechazar las llamadas al sistema que soliciten esta modificación.
Sistema Como se explicará en la sección 7.1.4, un sistema de archivos FAT tiende conforme se va utilizando a fragmentar los archivos que almacena. La carga del sistema operativo tiene que realizarse empleando código lo más compacto y sencillo posible: sin siquiera tener conocimiento del sistema de archivos. Este atributo indica que el sistema operativo debe cuidar no mover ni fragmentar al archivo en cuestión.
Archivado MS-DOS incluía herramientas bastante sencillas para realizar respaldos; estas basaban su operación en este atributo: Conforme se realizaba un respaldo, todos los archivos iban siendo marcados como archivados. Y cuando un archivo era modificado, el sistema operativo retiraba este atributo. De esta manera, el siguiente respaldo contendría únicamente los archivos que habían sido modificados desde el respaldo anterior
Estos atributos eran suficientes para las necesidades de un sistema de uso personal de hace más de tres décadas. Sin embargo, y dado que está reservado todo un byte para los atributos, algunos sistemas extendieron los atributos cubriendo distintas necesidades. Estos cuatro atributos son, sin embargo, la base del sistema.
Modelo tradicional Unix El sistema Unix precede a MS-DOS por una década. Sin embargo, su concepción es de origen para un esquema multiusuario, con las provisiones necesarias para que cada uno de ellos indique qué usuarios pueden o no tener diferentes tipos de acceso a los archivos. En Unix, cada uno de los usuarios pertenece a uno o más grupos. Estos grupos son gestionados por el administrador del sistema. Cada objeto en el sistema de archivos describe sus permisos de acceso por nueve bits, y con el identificador de su usuario y grupo propietarios.
Listas de control de acceso Una de las desventajas del modelo tradicional de usuarios Unix es que requiere de la intervención del administrador del sistema para cada nuevo proyecto: el administrador del sistema tuvo que crear al grupo factura antes de que pudiera realizarse ningún trabajo de forma colaborativa. Además, encontrar la representación justa para indicar un conjunto específico de permisos puede ser complicado. Dado que un archivo no puede pertenecer a más de un grupo, puede hacerse necesario crear conjuntos de grupos adicionales que intersectan aspectos específicos: una salida muy poco elegante
Sistemas de archivos remotos Uno de los principales y primeros usos que se dio a la comunicación en red fue el de compartir archivos entre computadoras independientes. En un principio, esto se realizaba de forma explícita, con transferencias manuales mediante de programas dedicados a ello, como sería hoy en día el FTP. Por otro lado, desde mediados de los ochenta, es posible realizar estas transferencias de forma implícita y automática, empleando sistemas de archivos sobre la red (o lo que es lo mismo, sistemas de archivos remotos). Éstos se presentan como caso particular de la abstracción de sistemas no-físicos que fueron mencionados en la sección anterior: si bien el sistema operativo no tiene acceso directo a los archivos y directorios que le solicitará el usuario, por medio de los módulos de red, sabe cómo obtenerlos y presentarlos como si fueran locales.
Network File System (NFS) El Sistema de Archivos en Red (Network File System, mejor conocido como NFS) fue creado por Sun Microsystems, y desde 1984 forma parte de su sistema operativo —resultó una implementación tan exitosa que a los pocos años formaba parte de todos los sistemas tipo Unix. Está construido sobre el mecanismo RPC (remote procedure call, llamada a procedimientos remotos), un mecanismo de mensajes y manejo básico de sesión que actúa como una capa superior a TCP/IP, incluyendo facilidades de descubrimiento de recursos y abstracción. RPC puede ser comparado con protocolos como DCE/RPC de OSF, DCOM de Microsoft, y hoy en día, SOAP y XML-RPC. Estos mecanismos permiten al programador delegar en un servicio el manejo de las conexiones de red, particularmente (en el caso particular aquí descrito) la persistencia de sesiones en caso de desconexión, y limitar su atención a una conexión virtual establecida. La motivación de ori
Common Internet File System (CIFS) El equivalente a NFS en los entornos donde predominan los sistemas Windows es el protocolo CIFS (Common Internet File System, Sistema de Archivos Común para Internet). Aparece en los sistemas primarios de Microsoft alrededor de 1990,23 originalmente bajo el nombre SMB (server message block, bloque de mensaje del servidor). Las primeras implementaciones estaban basadas en el protocolo NBF, frecuentemente conocido como NetBEUI, un protocolo no ruteable diseñado para redes pequeñas y entornos sencillos de oficina. A partir de Windows 2000 se ha reimplementado completamente para operar sobre TCP/IP. Es a partir de este momento que se le comienza a denominar CIFS, aunque el nombre SMB sigue siendo ampliamente utilizado.
Sistemas de archivos distribuidos: Andrew File System Los dos ejemplos de sistema de archivos en red presentados hasta ahora comparten una visión tradicional del modelo cliente-servidor: al ver el comando que inicializa una conexión, e incluso a ver la información que guarda el núcleo del cliente respecto a cualquiera de los archivos, resulta claro cuál es el servidor para cada uno de ellos.
La autenticación en AFS se basa fuertemente sobre el modelo de tickets y credenciales de Kerberos, 29 pero se aleja sensiblemente de la semántica de operación de archivos que hasta ahora se han presentado. Muchos eventos, operaciones y estados van ligados al momento en el tiempo en que se presentan, mediante un modelo de consistencia débil (weak consistency model). Muy a grandes rasgos, esto significa que:
Cuando se abre un archivo, éste se copia completo al cliente. Todas las lecturas y escrituras (a diferencia de los esquemas tradicionales, en que éstas son enviadas al servidor lo antes posible y de forma síncrona) se dirigen únicamente a la copia local.
Al cerrar el archivo, éste se copia de vuelta al servidor de origen, el cual se compromete a notificar a los clientes si un archivo abierto fue modificado (esto es, a hacer una llamada o callback). Los clientes pueden entonces intentar incorporar los cambios a su versión de trabajo, o continuar con la copia ya obtenida —es de esperarse que si un segundo cliente realiza alguna modificación, incorpore los cambios hechos por el primero, pero esta responsabilidad se deja a la implementación del programa en cuestión
Comentarios
Publicar un comentario