<< >> Título

Descripción general del sistema


Las cuatro prácticas que se proponen tienen por objeto la construcción de componentes de un sistema de ficheros. El sistema se ha estructurado en estas capas de software:

Sistema de Disco

Su misión consiste en proporcionar un archivo, manejado de manera análoga a como se hace con las unidades de disco, donde almacenar y posteriormente recuperar al información contenida en los archivos. La implementación de este sistema constituye la primera práctica.

Sistema de Bloques Físicos (SBF)

Su misión es principalmente ofrecer una interfaz simple de acceso al disco. Aparte, puede contener una caché de bloques para agilizar los accesos a los bloques físicos del sistema de disco. El desarrollo de la caché constituye la segunda práctica.

Sistemas de Ficheros

Este nivel es el más complejo, puesto que se pasa de trabajar con una secuencia de bloques a trabajar con ficheros. Debido a esta complejidad se ha descompuesto a su vez en dos niveles: Sistema de Ficheros Básico (SFB) y Sistema de Ficheros Simbólico (SFS), de alto nivel). En el SFB se resuelven los problemas de mantaner una organización simple de ficheros dentro del disco y gestionar el espacio libre. El SFE se encarga de trabajar con ficheros que tienen nombre simbólico y a los que se puede acceder byte por byte.

La tercera y cuarta prácticas consisten en la implementación de estos dos subsistemas.

La única práctica realmente de simulación es la primera; las tres restantes serían desarrollos de software similares a los correspondientes módulos de un sistema operativo real. Eso sí, serán módulos muy simples y con escasas prestaciones comparados con los sistemas reales.

Las distintas organizaciones de los datos

El objeto de este apartado es describir cómo son "vistos", y por lo tanto manejados, los datos en cada práctica (subsistema), sin olvidar que nuestro sistema va a ser construido y ejecutado sobre un sistema UNIX de desarrollo; por tanto, cualquier petición de acceso a los datos perteneciente a los archivos del sistema diseñado finalmente desembocará en la ejecución de una función del sistema UNIX.

El Sistema de Disco

Como ya se ha mencionado, éste simula una unidad de disco genérica mediante un fichero de nuestro sistema de desarrollo, por tanto en la implementación de este módulo, se deberá hacer uso de las primitivas de manejo de ficheros de bajo nivel de UNIX (open, creat, read, write, lseek y close). A partir de estas primitivas se desarrollarán unas funciones que accederán a los datos del fichero UNIX de simulación como si éste fuese una unidad de disco. Es decir, partiendo de una especificación en forma de superficie, cilindro y sector (proveniente de los niveles superiores del sistema a implementar y que conceptualmente está asociado a un sector del disco simulado) las convertirán en una dirección de bajo nivel para acceder a datos en un fichero UNIX en forma de desplazamiento del origen del fichero y número de bytes para transferir (este campo siempre tomará el mismo valor y será igual al tamaño de un sector del disco simulado).

El Sistema de Bloques Físicos

A este nivel, los datos se organizan en forma de bloques de tamaño fijo e igual al tamaño de sector del disco simulado por el nivel anterior. La diferencia radica en que los bloques son identificados por un valor entero comprendido entre 0 y el número total de sectores que posee el disco simulado menos 1. A este bloque de datos lo llamaremos bloque físico.

Si se utiliza una caché de bloques, las operaciones de lectura y escritura de bloques no siempre se corresponden con accesos al disco simulado.

El Sistema de Ficheros Básico

Este nivel ve los datos almacenados en el disco virtual, como conjuntos de bloques de tamaño fijo (bloque de sistema de ficheros o bloque de datos) pertenecientes a entidades (ficheros) que poseen cada una un identificador numérico único. Los bloques de datos poseen un tamaño que será múltiplo exacto del tamaño del bloque físico.

El Sistema de Ficheros Simbólico

Este nivel ve los datos como un conjunto de ficheros, cuyos nombres serán cadenas de caracteres. Los datos de cada fichero son secuencias de bytes, con lo que se pierde la conciencia de los bloques. En este nivel se tienen que traducir peticiones de acceso a bytes de un fichero, a operaciones de acceso a bloques completos.

El fichero de simulación

Como ya se ha mencionado, nuestro sistema, mediante el Sistema de Disco, hace uso de un fichero regular UNIX para simular una unidad de disco de unas características dadas. En el nivel más alto de abstracción, tenemos al Subsistema de Ficheros, para el cual este fichero UNIX contiene un conjunto de estructuras de datos (ficheros, tablas descriptoras, mapas de bits, etc.) El nivel intermedio, el Sistema de bloques físicos, asumirá que el fichero de simulación está organizado como una secuencia de registros de tamaño fijo.

La pregunta que surge a continuación es ¿Cómo se compatibilizan estas distintas visiones? y la respuesta es: de la misma manera que ocurre en los sistemas operativos reales y esto consiste en:

Al Sistema de Ficheros le llegan especificaciones simbólicas de usuario asociadas a:

Sistema de Ficheros que serán convertidas a especificaciones numéricas de sistemas de ficheros. En nuestro sistema cada sistema de ficheros se identificará por el nombre del fichero que simula a un disco y en el está almacenado, cuando se activa el sistema de ficheros (se avisa al sistema que va a ser accedido) entonces se abre dicho fichero y el descriptor de fichero devuelto pasará a ser el identificador numérico asociado al sistema de ficheros. Dicho descriptor de fichero será pasado como parámetro a las capas inferiores del sistema.

Ficheros en forma de cadena de caracteres que será convertida a identificador numérico asociado a la entrada de directorio que contiene la información de control del archivo.

Cadena de bytes en forma de posición de comienzo dentro del fichero y longitud, que será transformada a una especificación de bloque del sistema de ficheros básico y desplazamiento dentro del bloque, en primera instancia por parte del Sistema de Ficheros Simbólico o Básico, y posteriormente es transformado por parte del Sistema de Bloques Físicos a sector lógico y desplazamiento dentro del sector.

Al Sistema de Bloques Físicos le llegan especificaciones de sector lógico, provenientes del Sistema de Ficheros Básico. En el caso de que el sector especificado no se encuentre en memoria entonces solicitará al Sistema de Disco una transferencia de dicho sector lógico y en última instancia la especificación de sector lógico se traduce a una del tipo (superficie, cilindro, sector).

Las interfaces de programación

Cada uno de los servicios de los cuatro niveles de este sistema de ficheros tiene su propia interfaz. Las interfaces vienen impuestas; como desarrolladores, ustedes se limitarán a implementar las funciones de interfaz que se describen para la práctica que se les ha asignado.

La interfaces de los módulos se describen en capítulos subsiguientes: subsistema de disco (capítulo ), caché de disco (capítulos y ), sistema de ficheros básico (capítulo ) y sistema de ficheros simbólico (capítulo ).

En cualquier caso, todos los módulos tienen cosas en común, a saber: tipos de datos, tratamiento de errores y valores de retorno de las funciones. De ello se tratará en las siguiente líneas.

Tipos de datos comunes

En el fichero /prac/include/tipos.h se definen unos cuantos tipos de datos fundamentales que se utilizarán por todo el código de este sistema de ficheros.

Los tipos son:

typedef unsigned char BYTE;

typedef unsigned short WORD;

typedef unsigned long DWORD;

Resultados y errores

Aunque los módulos funcionales de los cuatro niveles son bastante diferentes, todas las funciones comparten características tanto en su sintaxis como en su funcionamiento.

La mayoría de las funciones devuelven un int, que valdrá cero (0) si la función se ha cumplido correctamente. Si se produce cualquier anomalía o error, todas las funciones devuelven un -1.

Hay un mecanismo para obtener más información sobre el último error producido, que está inspirado directamente en las llamadas al sistema del UNIX. Consiste en utilizar una variable global llamada Error_SF cuyo valor se corresponde con un código de error.

Los códigos de error están preestablecidos y se muestran en el fichero /prac/include/errores.h, que habrán de incluir en sus fuentes en C.

Los códigos de error son valores numéricos, pero tienen su expresión simbólica, en la forma ERR_tipo. Así, por ejemplo, existe un símbolo de nombre ERR_RANGO que se usará para indicar que algún parámetro de la última función llamada estaba fuera de rango.

Si la variable Error_SF vale cero, no se ha producido ningún error.

La macro HAY_ERROR se puede usar como una expresión booleana que es cierta si se ha producido un error.

Hay algunas funciones que devuelven un valor útil, como las que abren ficheros, que devuelven un índice al fichero abierto. Si estas funciones fallan, también devuelven un -1.

Funciones de informe

No bastará con que se implementen los servicios esenciales de cada nivel. También hará falta saber qué está ocurriendo en su interior. Por ello se propone, para cada práctica, que se implemente una función que imprima por la salida estándar un informe del estado del sistema que estén implementando. Lo más típico sería dar unas estadísticas de uso de recursos, recursos libres, fallos detectados, etc. etc.

Las funciones de informe quedan al libre albedrío de los implementadores, siempre que cumplan su misión, esta es, dar una panorámica en tiempo de ejecución del estado del servicio que están implementando.

Las funciones de informe tendrán un prototipo similar a éste:

void InformeXXX (void);

Estas funciones no devuelven ningún valor y, en principio, no tienen por qué producir errores.

Archivos en el laboratorio

Para realizar los trabajos prácticos se han depositado varios fuentes en C con las interfaces (ficheros cabecera) más algunos ficheros de implementación. También se irán introduciendo documentos sobre la práctica, incluyendo este texto.

Todos ello pende del directorio /prac, estructurado de esta manera:

/prac/include

Ficheros cabeceras *.h
/prac/src
Fuentes de las implementaciones *.c
/prac/lib
Bibliotecas: implementaciones compiladas *.a
/prac/doc
Documentos relacionados

Para poder utilizar cómodamente las cabeceras y bibliotecas, habrán de modificar su fichero .profile, incluyendo una línea como la que sigue:

export CCOPTS=-Aa -D_HPUX_SOURCE -L/prac/lib -I/prac/include

Si, como es probable, ya tenían una línea similar en su fichero .profile, sustitúyanla por la que se muestra aquí.


<< >> Título