GESTION DE MEMORIA

Anuncio
GESTION DE MEMORIA
Hay dos partes principales en cualquier sistema de gestión de memoria:
1_Protección: para evitar que una tarea acceda a la memoria o datos de otra tarea
o del sistema operativo. Y para evitar acceso indebido al hardware.
2_ Traducción de direcciones: para dar flexibilidad al sistema operativo a la hora de
asignar memoria a las tareas y de paso "puede" y de echo se utiliza como un
mecanismo clave de protección (según veremos mas adelante).
TRADUCCION DE DIRECCIONES
La memoria "física" de un ordenador es una secuencia de bytes, que empieza en el
0 y termina en....por ejemplo 64 megas. Es decir un "array" de bytes. Cada byte
tiene una dirección: el numero que ocupa posicionalmente en la memoria. Esta
dirección es conocida como "dirección física". (quiero "olvidarme, que además en
los procesadores 386 y superiores de Intel, existe la llamada "segmentación", pero
en principio vamos a obviar esto...... a propósito). Las direcciones que va a utilizar
un programa (en modo protegido), no son esas. Siempre son traducidas, o
mapeadas, en direcciones de memoria física por un mecanismo de "traducción de
direcciones". Este mecanismo, nos introduce en el concepto de "dirección virtual".
Se llama de esta manera porque no corresponde directamente a posiciones de
memoria "física", sino que a través de una "función de mapeado" equivale a una
dirección de memoria física. Es decir este mecanismo, al "apuntar" a una dirección
de memoria, lo que hace es buscar, por ejemplo en unas tablas internas, la
correspondencia entre esta dirección y la dirección real "física" del dato. La
traducción de dirección "virtual" a "física" también proporciona protección de
memoria, ya que podría disponerse por ejemplo, que ciertas direcciones físicas de
memoria no se mapeen desde ninguna dirección virtual. Además de esta
protección, en la función de traducción de direcciones, se pueden identificar ciertas
direcciones virtuales como "no validas". Esto amplía el mecanismo de protección.
Para no tener que generar una dirección física cuando se presenta un dirección
virtual no valida, el mecanismo de traducción de direcciones informa de una
"excepción", de forma que el software del sistema operativo, puede tomar la acción
que considere oportuna.
MEMORIA VIRTUAL
La memoria virtual es una técnica para proporcionar la ilusión de un espacio de
memoria mucho mayor que la memoria física de una maquina. Esta "ilusión"
permite que los programas se hagan sin tener en cuenta el tamaño exacto de la
memoria física. La ilusión de la memoria virtual está soportada por el mecanismo
de traducción de memoria, junto con una gran cantidad de almacenamiento rápido
en disco duro. En cualquier momento el espacio de direcciones virtuales, está
mapeado de tal forma que una pequeña parte de él, está en memoria real y el
resto almacenado en el disco. Debido a que solo la parte de memoria virtual que
está almacenada en la memoria principal, es accesible a la CPU, según un
programa va ejecutándose, la vecindad de referencias a memoria cambia,
necesitando que algunas partes de la memoria virtual se traigan a la memoria
principal desde el disco, mientras que otras ya ejecutadas, se pueden volver a
depositar en el disco (archivos de paginación).Por ejemplo, un programa de
aplicación grande, podría mostrar un menú con muchas funciones. Al seleccionar
una función del menú, se ejecutarían varias rutinas especificas de dicha función,
pero no se reverenciarían las rutinas de las funciones restantes. En un sistema de
memoria virtual, la ejecución de la función seleccionada del menú, se soportaría
trayendo el código y los datos para esa función a la memoria principal (si no
estuviese ya allí). El resto podría o no sacarse del disco a memoria real. Mientras la
memoria física fuese lo bastante grande para contener el código y datos de
cualquier función elemental de nuestro menú, el tamaño total de la memoria física,
podría ser mucho menor que el tamaño total de nuestro programa. El mecanismo
de paginación, también recoge estadísticas de utilización de las partes de memoria
virtual que están residentes en memoria real o física. Estas estadísticas ayudan al
sistema operativo a decidir que se puede devolver a disco cuando el espacio de
memoria principal está muy "achuchado".
PROTECCIÓN
Hay dos clases de protección usadas en el 386 y superiores (y en general en
cualquier CPU, incluso de los grandes sistemas).
 Habilidad de separar completamente las tareas, al poder dar a cada tarea un
espacio de direcciones virtuales diferentes. Esto se hace dando un mapa de
traducción de direcciones virtuales diferentes a cada tarea.
 Los otros mecanismos funcionan dentro de una tarea: para proteger al propio
sistema operativo de la intrusión por parte de esa tarea, y al uso de registros
especiales del procesador e instrucciones reservadas únicamente al sistema
operativo.
PROTECCION ENTRE TAREAS
Tal y como comentamos, se consigue poniendo cada tarea en un espacio de
direcciones virtuales diferentes, al asignar un mapa de traducción virtual a física
diferente. Ya que una tarea no puede generar una dirección virtual que se mapee a
otra parte de la memoria física usada por otra tarea, las tareas están aisladas unas
de otras. El sistema operativo se podría almacenar como una tarea independiente y
aislada del resto. Sin embargo el mecanismo de protección del sistema operativo,
es diferente y lo veremos mas adelante. Ese mecanismo, permite al sistema
operativo, el ser compartido por todas las tareas y accederse dentro de cada una
de ellas, mientras que por otra parte lo protege de las aplicaciones. El sistema
operativo es compartido por todas las tareas, disponiendo que una parte del mapa
de dirección virtual a física sea la misma para todas las tareas y almacenado el
sistema operativo en esa parte común del espacio de direcciones virtuales. Esta
parte del espacio de direcciones virtuales, que es común a todas las tareas, se
llama "espacio de direcciones GLOBAL". La parte de espacio de direcciones virtuales
que es única para una tarea simple, se llama "espacio de direcciones LOCAL". Una
consecuencia inmediata de tener un espacio de direcciones local diferente para
cada tarea, es que la referencia a la "misma" dirección virtual en cada tarea,
corresponde a diferentes direcciones "físicas". De esta manera se consigue el
aislamiento de tareas. Una referencia, en cambio, en el espacio de direcciones
global (donde está el SO), en cualquiera de las tareas se traducirá en la "misma"
dirección física para todas las tareas.
PROTECCION DENTRO DE UNA TAREA
Dentro de una tarea se definen 4 niveles de privilegio de ejecución, para proteger el
acceso a parte de la tarea de acuerdo con la sensibilidad de los datos. Los niveles
son numerados de 0 a 3, con un cero, el mas privilegiado, y con un 3 el menos
privilegiado. El nivel 0 se conoce como nivel de privilegio interno y el 3 como nivel
de privilegio externo. Cada segmento de memoria, esta asignado a un nivel de
privilegio. Este nivel de privilegio limita el acceso al segmento a los programas con
privilegio suficiente. Siempre que un programa intenta acceder a otro segmento
(evidentemente de su espacio virtual de direcciones), se comprueba el nivel de
privilegio del segmento en el cual se accede, con el nivel de privilegio del segmento
al cual queremos acceder. A un programa se le permite acceder a un segmento de
datos con un nivel de privilegio igual o menor al segmento en ejecución. Un intento
de ir a un nivel superior, es ilegal y provoca una "excepción" para informar del
intento de violación al sistema operativo. El uso típico de los niveles de privilegio,
es poner el núcleo del sistema operativo en el nivel 0, resto del sistema operativo al
nivel 1, y las aplicaciones al nivel 3. Esto deja el nivel 2 para los niveles de software
intermedio. Dada esta asignación, el sistema operativo (nivel 0) tiene derecho de
pernada sobre el resto de segmentos. El resto del sistema operativo (nivel 1) puede
acceder a todos los segmentos excepto el 0. La aplicación de nivel 3, solo puede
acceder a sus propios segmentos. Esta asignación, protege al núcleo del sistema
operativo de cualquier intruso.
SEGMENTACIÓN
La segmentación organiza la memoria virtual como una colección de unidades de
tamaño variable llamadas segmentos. Los segmentos forman la base del
mecanismo de traducción de direcciones virtuales a la dirección lineal (o física).
Cada segmento queda definido por tres parámetros:
1) Dirección de base: dirección de comienzo del segmento en el espacio de
direcciones lineal.
2) Limite del segmento: el mayor desplazamiento que se puede usar con ese
segmento de dirección virtual.
3) Los "atributos" del segmento, que indican por ejemplo, si el segmento se
puede leer, escribir o es únicamente de ejecución de programa, y una cosa
muy importante: el nivel de privilegio (recordar 0= máximo privilegio, 3
mínimo privilegio).
TABLAS DE DESCRIPTORES DE SEGMENTOS
Un sistema operativo, guarda una tabla de descriptores global (GDT) y la tabla de
descriptores local (LDT) correspondiente a una determinada tarea. Las tablas de
descriptores, "también" se almacenan en segmentos. En este caso unos especiales
mantenidos por el sistema operativo y referenciados por el HARDWARE
directamente. Esto es lo que lo hace importante. Lo maneja ya el hard. Está claro,
que estos segmentos "deberían" guardarse en memoria superprotegida, accesible
únicamente por el propio sistema operativo. El espacio de direcciones virtual está
mapeada en dos secciones iguales: una para la GDT y otra para la LDT. Cuando
entra en funcionamiento la MULTITAREA real, la LDT se cambia por la LDT de la
nueva tarea, pero la GDT permanece inalterable. Esto es por lo que la mitad del
espacio de direcciones virtuales, pertenece al sistema operativo. Esto es lo que se
denomina "conmutación de tarea".La LDT, además, contiene descriptores de
segmento para los segmentos privados de una tarea. Pero..... varia tareas podrían
compartir una LDT común. En este caso el mismo conjunto de segmentos está
disponible para todas ellas ya que tienen la misma LDT compartiendo una única
GDT.
IMPORTANTE:***** Lo anterior es el caso del subsistema de 16 bits de
Windows 98. Una sola LDT. Por tanto, un "cuelgue" en una tarea de 16 bits, por
desgracia, nos influye en "todo" el resto de tareas de 16 bits. Como bastante parte
del núcleo de Windows, por compatibilidad, es de 16 bits, esto implica que el
cuelgue de una aplicación de 16 bits, "puede" dejar al sistema totalmente inestable.
Dos tareas pueden tener también el mismo descriptor para un segmento
compartido en sus LDT respectivas, de esta manera se puede compartir un
segmento sin tener que poner su descriptor en la GDT. En este caso, el segmento
compartido debe ser tratado con especial atención por el sistema operativo ya que
realmente tiene dos descriptores en dos LDT distintas que deben ser actualizados
simultáneamente.
SELECTORES DE SEGMENTO:
Un selector de segmento identifica a un segmento. Aunque sea un poco técnico,
diremos que en la arquitectura de nuestro PC, un selector de segmento, es de 16
bites de tamaño y contiene tres subcampos:
1) los dos primeros bits, contienen el llamado RPL (Requested Privilege Level) o
nivel de privilegio solicitado. Un valor de 2 bits, puede contener de 0 a 3. Es
decir el sistema de protección anteriormente citado.
2) El siguiente BIT, indica un 0 para saber que este selector pertenece a la GDT,
o un 1 si pertenece a la LDT,
3) y los otros 13 bits, es un índice (numero de orden) del descriptor en las
tablas GDT o LDT en función del contenido del punto anterior.
USO DEL CAMPO RPL
Cada vez que un programa intenta acceder a un segmento, el nivel de privilegio
actual (CPL) se compara con el nivel de privilegio del segmento para determinar si
el acceso está permitido. En caso de no estar permitido, disparará una "excepción"
y por tanto el sistema operativo tomará control.
DESCRIPTORES DE SEGMENTO
Bien, cada descriptor de segmento es realmente pequeño. 8 bytes. Y contiene 3
campos:
1) Dirección de base de segmento
2) Limite del segmento
3) Atributos
La dirección de base es de 32 bits, para permitir que esa dirección comience en
cualquier byte de la memoria lineal (física). El limite, es también de 32 bits, pero
únicamente está especificado con 20 bits. Los limites de segmento, pueden ser
granulares de byte o granulares de pagina (4 Kb). El tipo de granularidad viene en
uno de los 12 bits que quedan en el descriptor. Por tanto, con 20 bits permite la
especificación de tamaños de segmento de 1 a 1 Mega si la granularidad es de
byte. o tamaños de 4 Kb a 4 Gigabytes en incrementos de 4 Kb. Los segmentos se
pueden extender de tamaño, simplemente modificando el "limite" (puede requerir
en este caso, mover segmentos dentro del espacio lineal de direcciones).
Atributos del segmento
En los 12 bits restantes, aparte de la granularidad, existen 2 bits para el nivel de
privilegio (de 0 a 3). A este campo se le llama DPL (Descriptor Privilege Level).
Otros bits interesantes:
** El BIT de presencia (P): Si está a 1 indica que el descriptor es válido para
utilizar en la traducción de direcciones virtuales a direcciones lineales. Si está a 0,
el descriptor no es valido, y su uso provocaría una "excepción"
** E BIT "Tipo D". Si es 1 es para un segmento de memoria. Si es 0 es para un
segmento del sistema o una "puerta" (lo veremos mas adelante). La LDT es por
ejemplo, un segmento del sistema.
** Otros dos bites de "tipo". Sirven para especificar el tipo de memoria. No voy a
detallarlo completamente, pero sepamos que aquí se guarda si es por ejemplo de
solo lectura, de escritura, si ha sido o no accedido últimamente (importante para
saber si se "debe" o no paginar. un segmento muy accedido no debe paginarse a
disco)..... etc.
Puertas:
Bien las puertas, realmente son también descriptores pero con otro formato. Los 48
primeros bits es un puntero completo y además tiene los 16 de atributos. La
puerta, es lo único que va a permitir a un programa con un nivel de privilegio
mayor, el saltar a las rutinas del sistema operativo que tiene mayor nivel de
privilegio. Recordemos que en principio no se puede saltar desde un programa de
aplicación, a ninguna rutina del sistema operativo, ya que esto provocaría una
"excepción". Por ello se utiliza el mecanismo de la puerta. La puerta tiene la
dirección "exacta" de llamada a la rutina del sistema operativo. Y el programa de
aplicación "únicamente" puede utilizar esa puerta.
PAGINACIÓN
La paginación es la otra parte del mecanismo de gestión de memoria con que
empezábamos estos artículos. Funciona por debajo de la segmentación para
completar los procesos de conversión de dirección virtual a física. El mecanismo de
paginación, es HARDWARE. Simplemente se habilita por el sistema operativo en su
carga incial, al situar un BIT, en un registro especial de la CPU que es solo accesible
desde el sistema operativo. A diferencia de la segmentación que funciona con
segmentos de memoria de tamaño variable, la paginación se hace con tamaños de
memoria fijos llamado "paginas". La paginación divide el espacio de direcciones
lineales en "paginas". Cualquier pagina en el espacio de direcciones lineales se
puede mapear sobre otra en el espacio de direcciones físicas.
** Esto ultimo es importante. Hasta ahora hemos hablado de direcciones lineales
como direcciones físicas. Pero debemos fijarnos que en el momento en que entra a
funcionar el mecanismo de paginación, existe otra indireccion, ya que una dirección
lineal puede estar mapeada en cualquier sitio del espacio de direcciones físico. Las
CPU s de los PCS actuales que conocemos, utilizan un tamaño de pagina de 4 Kb, y
evidentemente "alineados" en intervalos de 4 Kbs. Esto significa que el mecanismo
de paginación divide el espacio de direcciones lineal de 2 elevado a 32 bits (4 GB)
en 2 elevado a 20 paginas de 2 elevado a 12 bytes cada una (4 Kbs).La función de
traducción de dirección lineal a física se extiende para permitir que una dirección
lineal se marque como no valida, bien porque esa dirección no está soportada por
el sistema operativo, o bien, y esto es lo mas importante, porque corresponde a
una pagina que ha sido "paginada" (almacenada) en el disco y no está disponible
en ese momento en memoria física. Supongamos, que es el segundo caso.
Cualquier referencia de nuestro programa a esa pagina, provocará una excepción
llamada "fallo de pagina", lo cual invoca a manejador del sistema operativo
encargado de llamar al gestor de memoria para mover la pagina de disco a
memoria física. Estas paginas que residen en el disco se llaman pagina no
presentes, y se identifican por un atributo de la tabla de paginas llamado el atributo
de presente.
Con esto terminamos una introducción genérica que es valida para cualquier
procesador (con algún matiz del tamaño de pagina, y descriptor). Para cualquier
procesador, bien nuestro humilde 486 o Pentium o bien los gigantescos
"mainframes" de IBM. Todo el manejo de estos bits de paginación, los mecanismos
de excepciones, las tablas de paginas, etc..... las maneja directamente el
HARDWARE. El "creador" del sistema operativo, solo tiene que decir si quiere
activos estos mecanismos y las direcciones de las tablas de paginas, etc.... El
procesador vía hardware se encarga de la actualización de estos datos. Es decir,
una vez creadas las GDT del sistema, la tabla de paginación, las puertas y las
tablas de interrupciones (o excepciones), el propio hardware se encarga de esto.
Igualmente, el cambio de contexto en un cambio de tarea (en multitasking multitarea-) lo realiza mediante hardware el procesador. Otra cosa es que lo
anterior (cambio de contexto hardware), esté deshabilitado "a propósito" por
Windows y lo haga el "manualmente". Aparentemente y según las malas lenguas,
se debe a un error de diseño de Intel en sus primeros procesadores (386) en los
cuales fallaba el mecanismo hardware. Por herencia y compatibilidad, Windows ha
"heredado" esta malfunción.
Descargar