<< >> Título

Simulación de un disco


El objetivo de este trabajo práctico es la implementación de los conceptos teóricos vistos en clase sobre estructura física, organización de los datos y planificación de disco. En la práctica a realizar se distinguirán dos niveles lógicos bien definidos:

Nivel básico. Formado por todos aquellos módulos lógicos cuya misión es la de llevar a cabo las transferencias de datos solicitadas al más bajo nivel. Conceptualmente esta capa se correspondería con un manejador de disco.

Nivel de planificación. Cuya misión fundamental es la gestión de las peticiones de transferencia que llegan, por tanto en este nivel se encuentran implementadas las distintas políticas de planificación de disco. Otro aspecto importante es que en ella radica la interfaz con el sistema de memoria caché.

Cómo simular las unidades de disco

La aplicación a diseñar deberá ser capaz de manejar de forma simulada distintas unidades de disco hipotéticas con distintas características físicas, además debe tener la capacidad de manejar varias al mismo tiempo. En nuestro modelo, una unidad de disco se simulará mediante un fichero que posee la siguiente estructura:

Bloque de parámetros físicos. Se trata de una tabla de tamaño fijo, en la que se distinguen los siguientes campos:

Número de cilindros.

Número de superficies.

Número de sectores por pista.

Tamaño en bytes del sector.

Tiempo de desplazamiento del brazo (seek).

Tiempo de Latencia.

Tiempo de transferencia.

Tiempo de recalibrado.

Área de sectores simulados. Se trata de una zona compuesta por registros de tamaño fijo, tanto el tamaño de los registros como el número de éstos se obtienen en base a la información contenida en el bloque anterior. Los registros de simulación de sectores de disco se disponen de la siguiente manera: en primer lugar los correspondientes a la primera superficie, luego a la segunda y así sucesivamente, para los asociados a una superficie dada, éstos se disponen por pistas, esto es: primero los asociados a la primera pista, a continuación los de la segunda y así sucesivamente hasta completar el número de pistas (cilindros) por superficie. Teniendo en cuenta esta organización, un aspecto que ha de resolver el diseñador o diseñadora es como pasar de una especificación del tipo (superficie, cilindro, sector) a número de registro de esta zona.

Nivel básico

Como ya se ha descrito, esta capa es la responsable de efectuar las transferencias de datos entre disco y la caché, para ello se deberán desarrollar, entre otras que usted considere, las siguientes funciones:

Inicializa_Disco que crea un fichero para simular una unidad de disco con unas características dadas.

Monta_Disco que prepara al sistema para poder acceder a una unidad de disco dada, ésta se ha de inicializar previamente.

Transfiere_Sector que realiza una trasferencia (lectura o escritura) de un conjunto de sectores lógicos entre la caché y los discos disco.

Posiciona_Cabeza que sitúa la cabeza de lectura y escritura de una unidad de disco sobre un cilindro dado.

Lee_Posicion que informa en qué cilindro se encuentra la cabeza

de lectura y escritura de una unidad dada.

Recalibra_Disco que efectúa una operación de recalibrado en una unidad de disco dada.

Este conjunto de funciones enunciado equivale a un manejador de disco elemental de un sistema operativo real. Seguidamente se pasa a describir con más detalle cada una de las rutinas anteriores.

Interfaz del nivel básico

Inicializa_Disco Crea un fichero de simulación de disco

#define "Consta_DISCO.h"

#define "Tipos_DISCO.h"

#define "Error_SF.h"

int Inicializa_Disco(char *nombre, bloq_param desc);

Inicializa_Disco inicializa un fichero, cuyo pathname se especifica mediante el parámetro nombre, para simular una unidad de disco cuyas características se especifican mediante el parámetro desc, si el fichero especificado no existe entonces lo creará y si ya existía, entonces lo reescribirá (perdiéndose por tanto la información contenida en él). Si la función se ejecuta con éxito, entonces devolverá un valor positivo igual al número de registros de simulación escritos en el fichero de simulación. En el caso de que se produzca un error durante su ejecución, entonces devolverá -1 y la variable global Error_SF tomará un valor indicativo del motivo del error:

ERR_FORMATO Características inválidas de la nueva unidad.

ERR_ACCESO Error de lectura/escritura .

ERR_FICHERO No se ha podido abrir/crear fichero.

Monta_Disco Accede a las datos de control de una unidad

#include "Consta_DISCO.h"

#include "Tipos_DISCO.h"

#include "Error_DISCO.h"

int Monta_Disco(char *nombre)

Monta_Disco lee el bloque de parámetros almacenado en el fichero (que simula a una unidad de disco) cuyo pathname se especifica mediante el parámetro nombre, una vez leído este bloque, ya la unidad virtual estará preparada para ser accedida por el sistema. Si la función se ejecuta con éxito retornará un valor no negativo que se corresponderá con un índice a la tabla de descriptores de unidades de disco del sistema, dicho índice deberá especificarse como identificador de unidad para las posteriores operaciones. En cambio, si se produce un error durante su ejecución entonces retornará -1 y la variable global error_disc tomará uno de los siguientes valores:

ERR_ACCESO Error en la lectura del bloque de parámetros.

ERR_DISCO No se ha podido abrir/crear fichero.

ERR_RANGO Alcanzado número máximo de unidades de disco.

Desmonta_Disco Desactiva una unidad de disco

#include "Consta_DISCO.h"

#include "Tipos_DISCO.h"

#include "Error_SF.h"

int Desmonta_Disco(unidad fd);

Desmonta_Disco desactiva una unidad de disco previamente activada mediante la función Monta_Disco, la unidad se especifica mediante el parámetro fd que es el descriptor de unidad. Si la función se ejecuta con éxito, entonces devuelve 0, en caso contrario, se retornará -1y la variable global Error_SF tomará alguno de los siguienets valores:

ERR_INACTIVO No hay unidad de disco montada.

ERR_EFD Descriptor de unidad invalida.

Transferencia_Fisica Lee o escribe un sector físico de disco

#include "Consta_DISCO.h"

#include "Tipos_DISCO.h"

#include "Error_SF.h"

int Transferencia_Fisica(unidad fd, dir_fis direc, void *buff, int modo);

Tranf_Sector lleva a cabo la transferencia de datos entre la caché, a partir de la posición indicada por buff , y la unidad de disco especificada por fd, en el sector físico cuya dirección especifica direc. El tipo de transferencia se indicará mediante modo, pudiendo tomar este parámetro uno de los siguientes valores: LECTURA o ESCRITURA. Si la transferencia tiene éxito, entonces retornará 0, en caso contrario retornará -1 y la variable Error_SF tomará alguno de los siguientes valores:

ERR_INACTIVO No hay unidad de disco montada.

ERR_EFD Descriptor de unidad de disco inválido.

ERR_DIRECC Dirección física de sector inválida.

ERR_ACCESO Modo de transferencia inválido.

ERR_TRANSF Error de en la transferencia ( al leer o escribir en el fichero).

Nota: Esta función simula los tiempos de latencia y de transferencia internamente mediante la llamadas a las funciones Tiempo_Late y Tiempo_Transf que proporciona la librería específica de esta práctica y que se les suministrará como material.

Posiciona_Cabeza Posiciona la cabeza de lectura y escritura

#include "Consta_DISCO.h"

#include "Tipos_DISCO.h"

#include "Error_SF.h"

int Posiciona_Cabeza(unidad fd, unsigned short int cil);

Posiciona_Cabeza sitúa la cabeza de lectura y escritura de la unidad de disco especificada por el descriptor fd en el cilindro especificado por cil. Si la función se ejecuta con éxito entonces retornará 0, en caso contrario retornará -1 y la variable global Error_SF tomará alguno de los siguientes valores:

ERR_INACTIVO No hay unidad de disco montada.

ERR_EFD Descriptor de unidad de disco inválido.

ERR_PARAMETRO Especificación de cilindro inválido.

Nota: Esta función simula el tiempo de posicionamiento del brazo internamente mediante la llamada a la función Tiempo_Seek y que proporciona la librería específica de esta práctica y que se les suministrará como material.

lee_Posicion Informa en qué cilindro se encuentra la cabeza

#include "Consta_DISCO.h"

#include "Tipos_DISCO.h"

#include "Error_SF.h"

int Lee_Posicion(unidad fd);

Lee_Posicion devuelve el número de cilindro en el que se encuentra la cabeza de lectura y escritura de la unidad asociada a fd. Si fd posee un valor correcto entonces devolverá el cilindro en el que está la cabeza de lectura y escritura, en caso contrario, es decir si se produce un error, entonces la variable global Error_SF tomará alguno de los siguienets valores:

ERR_INACTIVO No hay unidad de disco montada.

ERR_EFD Descriptor de unidad de disco inválido

Recalibra_Disco Recalibra una unidad de disco

#include "Consta_DISCO.h"

#include "Tipos_DISCO.h"

#include "Error_SF.h"

int Recalibra_Disco(unidad fd);

Recalibra_Disco efectúa una operación de recalibrado en la unidad asociada a fd. Si se produce un error, entonces la variable global fd posee un valor incorrecto entonces devolverá -1 y la variable Error_SF toma alguno de los siguientes valores:

ERR_INACTIVO No hay unidad de disco montada.

ERR_EFD Descriptor de unidad de disco inválido

Nota: Todo hardware de control de disco incorpora una facilidad de recalibrado de los elementos mecánicos de las unidades de disco, esta operación tiene por finalidad anular las inercias que se producen en dichos elementos. La función Recalibra_Disco simula el tiempo de recalibrado invocando a la función Tiempo_Recal que se proporciona en la librería específica de esta práctica.

Informe_Disco Da un informe del estado del disco

#include "Consta_DISCO.h"

#include "Tipos_DISCO.h"

#include "Error_SF.h"

void Informe_Disco (void);

Esta función imprimirá por la salida estándar un informe de estadísticas de uso y estado general del disco simulado.

No producirá errores en ningún caso.

Nivel de planificación

Como ya se ha comentado se trata del nivel superior de la aplicación, por tanto, a él le van a llegar las peticiones del subsistema de caché mediante la función de interfaz Transfiere_Sector definida en esta capa. Un aspecto importante a destacar es que las peticiones de transferencia que le llegan e este nivel contienen especificaciones de sectores lógicos, que serán convertidas aquí en especificaciones de sectores físicos y a continuación serán sometidas a una política de planificación. Toda petición seleccionada para ser atendida, se comunicará al nivel básico mediante la función Transfiere_Disco. Otras dos funciones perteneciente a este nivel que han de desarrollarse son: direccion_fisica, que obtiene el sector físico asociado a un sector lógico, y planifica_peticiones que gestiona las peticiones de disco según una determinada política.

Qué es un sector lógico

Se trata de un bloque de datos de tamaño igual al sector físico pero que se referencia de forma diferente, pues a este nivel el disco se "ve" como una secuencia lineal de sectores, por ejemplo, el primer sector será el sector 0, el segundo será el sector 1, y así sucesivamente. Como consecuencia de la existencia de este disco lógico (formado por una secuencia de sectores lógicos) se ha de definir una correspondencia biunívoca entre sector lógico y sector físico, la forma que adopta esta correspondencia no es un aspecto irrelevante, pues influye en la rapidez con que se acceden a los datos de los archivos almacenados en disco, específicamente se ha facilitar el principio de localidad de los sectores que contienen los datos de un archivo, es decir, se ha de procurar que los datos de un fichero estén ubicados en registros lógicos continuos y que estos a su vez se correspondan con registros físicamente próximos (de esta manera se miniminiza el impacto de los tiempos de traslación de la cabeza de lectura y escritura y de latencia). la regla que se ha de utilizar en esta practica es la siguiente: primero empezamos por asociar los sectores lógicos a sectores físicos del primer cilindro, cuando agotemos la primera superficie se pasa a la segunda, y así sucesivamente, cuando se agote la última superficie del primer cilindro, se pasa al segundo cilindro y se procede de la misma manera y así hasta cubrir todos los cilindros de la unidad. Un aspecto a resolver en esta práctica es implementar esta regla de correspondencia.

Transfiere_Sector Transfiere un sector lógico

#include "Consta_DISCO.h"

#include "Tipos_DISCO.h"

#include "Error_SF.h"

int Transfiere_Sector(unidad fd, int num_sectores, sector_logico *sect , void *buff, int modo);

Transfiere_Sector lleva a cabo la transferencia de un conjunto de sectores lógicos, especificado por sect, entre la caché y la unidad de disco especificada por fd. buff ha de apuntar a una zona de memoria con capacidad suficiente para almacenar num_sectores sectores. El parámetro sect apunta a un vector de num_sectores números de sector. El tipo de transferencia se especifica en modo pudiendo adoptar éste parámetro los valores LECTURA o ESCRITURA. Si la transferencia se ejecuta con éxito entonces esta función retornará 0, en caso contrario retornará -1 y la variable global Error_SF tomará alguno de los siguientes valores:

ERR_INACTIVO No hay unidad de disco montada.

ERR_EFD Descriptor de unidad de disco inválido.

ERR_DIRECC Dirección física de sector inválida.

ERR_ACCESO Modo de transferencia inválido.

ERR_TRANSF Error de en la transferencia ( al leer o escribir en el fichero).

Direccion_Fisica Obtiene la dirección física de un sector

#include "Consta_DISCO.h"

#include "Tipos_DISCO.h"

#include "Error_SF.h"

int Dirección_Física(unidad fd, sector_logico sect, dir_fis *dir);

Dirección_Física obtiene la dirección del sector físico asociado al sector lógico, especificado por sect. El parámetro fd indica la unidad en donde se encuentra el sector. Si la función se ejecuta con éxito, entonces retornará 0 y el *dir contendrá la dirección física calculada, en el caso de que ocurra algún error, entonces retornará -1 y la variable global Error_SF tomará alguno de los valores siguientes:

ERR_INACTIVO No hay unidad de disco montada.

ERR_EFD Descriptor de unidad de disco inválido.

ERR_DIRECC Dirección física de sector inválida.


<< >> Título