lunes, 28 de mayo de 2012

6 Memoria virtual

La memoria virtual es el mecanismo más general para la ejecución de programas no 
enteros en memoria. Se basa en un sistema de paginación (o combinado) en el que 
sólo un subconjunto de las páginas del programa están cargadas en memoria. El 
resto reside en un dispositivo de almacenamiento secundario, análogamente al de 
swap7
. La memoria virtual presenta, adicionalmente a su  capacidad para ejecutar 
programas mayores que la memoria física disponible, un conjunto de interesantes 
ventajas con respecto a la paginación con programas enteros: 
• Reduce la latencia en la ejecución de los programas, al no tener éstos que 
cargarse completamente para comenzar a ejecutarse. 
• Permite gestionar más eficientemente la memoria física. Cualquier espacio 
libre, incluso una única página, puede ser aprovechado para cargar un nuevo 
programa y comenzar a ejecutarlo. Por otra parte, si una página de un 
programa no se referencia durante la ejecución, no habrá que cargarla. 
• Al aumentar el grado de multiprogramación a costa de reducir el número de 
páginas cargadas de cada programa, permite incrementar la eficiencia de la 
CPU en sistemas multiprogramados
8
. 
• Ahora la independencia de los programas con respecto a la máquina es 
completa. Además del direccionamiento virtual que aporta la paginación, la 
cantidad de memoria física disponible para ejecutar el programa sólo es 
relevante para la velocidad de ejecución del programa.  

6.1 Soporte hardware


Además del soporte hardware para la traducción de direcciones de los sistemas
paginados, la memoria virtual requiere mecanismos hardware adicionales:
• Espacio para paginación en un dispositivo de almacenamiento secundario
(disco).
• Bit de validez, V. Para cada entrada de la tabla de páginas es necesario un bit
que indique si la página correspondiente está cargada en memoria o no.
• Trap de fallo de página. Cuando la página referenciada no está cargada en
memoria, el mecanismo de interrupciones produce el  salto a la  rutina de
tratamiento del fallo de página (que promoverá la carga de la página en
memoria). A diferencia de una interrupción normal, el fallo de página puede
ocurrir en cualquier referencia a memoria durante la ejecución de la
instrucción, por lo que la arquitectura debe proporcionar los mecanismos
adecuados para establecer un estado del procesador consistente antes de saltar
a la rutina de tratamiento.
• Información adicional para la gestión del fallo de  página (bit de página
modificada, referenciada, …). Se verá más adelante.

6.2 Carga de programas y reubicación


El cargador carga la tabla de páginas del programa  y una o más páginas,
estableciendo las direcciones de las páginas cargadas en las entradas de la tabla de
páginas y los valores de los bits de validez. Almacena también las direcciones de
disco donde se encuentran las páginas no cargadas en memoria. Como en
paginación, la reubicación se hace independientemente para cada página, cuando
éstas se cargan tras un fallo de página.
Básicamente, hay dos estrategias para cargar las páginas de un programa:
(a) Cargar sólo la primera página de código y dejar que el resto se cargue por fallo
de página (paginación por demanda).
(b) Cargar un cierto número de páginas o todas, dependiendo de la memoria
disponible y del tamaño del programa (prepaginación).

6.3 Gestión


El proceso de direccionamiento en un sistema de memoria virtual combina el
mecanismo hardware de traducción de direcciones siguiendo el mecanismo habitual
de paginación pura o combinada, con la intervención del sistema operativo cuanto se
produce un fallo de página. En la referencia a memoria se comprueba el estado del
bit de validez. Si está activado, la página está cargada y el proceso de traducción
hardware acaba proporcionando la dirección física; en caso contrario, el trap de fallo
de página aborta la ejecución de la instrucción en curso9
 y provoca el salto a la rutina
de tratamiento del fallo de página, que ejecuta los siguientes pasos:
 (1) Si la dirección generada por el programa no es correcta10
, se aborta la ejecución
del programa. Si se trata de una dirección correcta, se busca un marco de
página libre en memoria donde cargar la página referenciada. Si no hay
marcos libres, se consigue uno expulsando una página de memoria. La
elección de ésta (página víctima) se realiza mediante un  algoritmo de
reemplazo. El reemplazo de una página, que se estudiará más  adelante,
implica escribir en disco la página víctima si ésta hubiera sido modificada.
(2) Se programa la lectura de la página referenciada en el dispositivo de
paginación. En los sistemas multiprogramados se produce un cambio de contexto: el proceso que ha provocado el fallo de página pasa a estado
bloqueado y se planifica otro proceso.
(3) Mientras el programa está bloqueado, se lee por DMA en el dispositivo de
paginación la página buscada y se carga en el marco libre seleccionado.
(4) Finalizada la carga, se actualiza la entrada de la tabla de páginas y el bit de
validez asociado. El proceso bloqueado por fallo de página pasa a preparado
para ejecución. Dependiendo de la política de planificación de procesos, el
proceso puede tener la oportunidad de entrar a ejecución.

6.4 Evaluación del rendimiento



Como podemos deducir del apartado anterior, el tratamiento de un fallo de página es
muy costoso en tiempo comparado con un acceso a memoria paginada. Hay que
tener en cuenta que en la actualidad un tiempo de acceso a memoria paginada típico
(tm) es del orden de 10-7
 segundos o menos, mientras que el tiempo de tratamiento de
un fallo de página (t
f
) es del orden de la decena de milisegundos (básicamente el
tiempo de acceso a disco), es decir cinco órdenes de magnitud superior.
Si la probabilidad de fallo de página es  pf
, el tiempo medio de acceso a memoria
virtual (tv) se calcula como:
tv = tm + pf
 t
f
Para hacernos una idea de en qué órdenes debe moverse la probabilidad de fallo de
página para que el rendimiento del sistema no se resienta demasiado, vamos a partir
de la relación de tiempos tv/tm. Obsérvese que tv/tm – 1 expresa una medida de la
pérdida de rendimiento relativa a tm resultante de introducir en un sistema paginado
memoria virtual, en tanto por 1. Despejando pf
 en la expresión de arriba, podemos
expresarla en función de esta relación:
pf
 = (tv/tm –1) (tm/t
f
)
Por ejemplo, si se pretende que la pérdida de rendimiento en el acceso a memoria
con memoria virtual no supere el 10% con respecto al tiempo de acceso en el mismo
sistema sin memoria virtual, la probabilidad de fallo de página debería ser:
pf
 < 0,1 (tm / t
f
)
que para la relación típica tm/t
f
 de 5 órdenes de magnitud razonada más arriba, da
una probabilidad del orden de 10
−6
.
Afortunadamente, hay algunos factores que permiten matizar estos resultados:

• Si el sistema no fuese de memoria virtual, debería cargar inicialmente todo el
programa, lo que supone un tiempo equivalente al de tratar tantos fallos de
página como páginas tiene el programa.
• La localidad espacial de los programas y el tamaño de las páginas (típicamente
de varios Kb en la actualidad) aseguran que, cargadas las primeras páginas,
habrá gran cantidad de referencias a ellas antes de producir un fallo.
• En sistemas multiprogramados, la CPU puede ejecutar otros procesos
mientras se atiende un fallo de página.
• Con relación a otros niveles de la jerarquía de memoria (por ejemplo la
memoria cache), en memoria virtual el espacio destinado en disco para área de
paginación ha de configurarse de forma que no sea mucho mayor que el
espacio la memoria física disponible
11
.
Una política de reemplazo de páginas adecuada explotará ventajosamente la
localidad temporal de los programas, haciendo posible un rendimiento razonable.

6.5 Reemplazo de páginas


Como hemos visto, cuando se produce un fallo de página y no hay marcos libres es
necesario liberar uno de los marcos de página ocupados para poder cargar la página
referenciada. Los pasos a seguir son los siguientes:
(1) Se selecciona la página víctima mediante un  algoritmo de reemplazo que
ejecute una política de reemplazo determinada.
(2) Si la página víctima había sido modificada durante su estancia en memoria,
hay que escribirla en el dispositivo de paginación  (page-out). Si no, esta
operación no es necesaria. Para la gestión de páginas modificadas se asocia un
bit de página modificada para cada marco de página, que se activa cada vez
que se accede a memoria para escritura.
(3) Se pone a cero el bit de validez correspondiente a la página víctima en su tabla
de páginas.
A continuación se sigue con el tratamiento del fallo de página como se describió
anteriormente, leyendo del dispositivo de paginación la página que provocó el fallo y
cargándola en el marco libre (page-in).

6.6 Políticas de reemplazo de páginas


Los criterios a seguir para implementar un algoritmo de reemplazo de páginas son
fundamentalmente dos:
• Minimizar el número de fallos de página, como se ha razonado en el apartado
anterior. Explotar la localidad temporal de los programas será fundamental.
• Sencillez de implementación. Un algoritmo complejo, como veremos, puede
requerir intervención adicional en los accesos a memoria, lo que implicará o
pérdida de rendimiento, o un hardware costoso, lo que a su vez redundará
probablemente en pérdida de rendimiento12
.
A continuación se describen las políticas de reemplazo de páginas. Para probar los
algoritmos de reemplazo y así poder evaluar su rendimiento comparativo se utiliza
una  secuencia de referencias a páginas (finita y determinista
13
), que permite
determinar la tasa de fallos de página para cada algoritmo. Para simplificar, se
considera que las referencias son producidas por un único programa. El Ejercicio 7
incluye una secuencia de referencias que permitirá probar el comportamiento de los
algoritmos. Como se verá más adelante, en multiprogramación es necesario
considerar que un conjunto de secuencias de referencias se intercalan en el tiempo.