Download El sistema operativo: gestión de memoria Licencia

Document related concepts

Segmentación de memoria wikipedia , lookup

Paginación de memoria wikipedia , lookup

Archivo proyectado en memoria wikipedia , lookup

Memoria virtual wikipedia , lookup

Tabla de paginación wikipedia , lookup

Transcript
El sistema operativo: gestión de memoria
El sistema operativo: gestión de memoria
Índice de contenido
El sistema operativo: gestión de memoria....................................................................................................1
Licencia......................................................................................................................................................1
Esquemas de carga de programas.............................................................................................................1
Enlazado.................................................................................................................................................1
Carga......................................................................................................................................................2
Estrategias de organización de la memoria...............................................................................................2
Partición fija...........................................................................................................................................3
Partición dinámica..................................................................................................................................3
Paginación..............................................................................................................................................4
Segmentación.........................................................................................................................................4
Segmentación y paginación....................................................................................................................5
Memoria virtual.........................................................................................................................................5
Concepto................................................................................................................................................5
TLBs.......................................................................................................................................................5
Políticas de lectura de páginas................................................................................................................6
Políticas de reemplazo............................................................................................................................6
Gestión del conjunto residente...............................................................................................................6
Hiperpaginación.....................................................................................................................................7
Licencia
Este obra de Jesús Jiménez Herranz está bajo una licencia Creative Commons AtribuciónLicenciarIgual 3.0 España.
Basada en una obra en oposcaib.wikispaces.com.
Esquemas de carga de programas
Generalmente, los programas se almacenan en forma de ficheros en algún medio de
almacenamiento. A la hora de ejecutar un programa, es necesario leer este fichero y cargarlo en
memoria para su ejecución. Este proceso implica una serie de transformaciones, y básicamente se
compone de dos etapas:
●
●
Enlazado: Consiste en determinar y reunir todos los módulos que componen un programa,
como el programa en sí, las librerías que utiliza, etc.
Carga: En el fichero, las direcciones de las diferentes variables, saltos, etc. se almacenan en
forma relativa. Antes de ejecutar el programa, es necesario transformar estas direcciones a las
direcciones reales que usará el programa una vez en ejecución.
Enlazado
Tipos de enlazado:
●
●
●
Estático: En el momento de la compilación, se determinan los módulos necesarios para el
programa, y se integran en el fichero ejecutable final.
Dinámico: Igual que el estático, pero el proceso se lleva a cabo en el momento de la ejecución.
Dinámico en tiempo de ejecución: En este caso, se carga la librería en memoria en la primera
ocasión que se accede a ella. Además, se mantiene una única instancia de la librería en
memoria, que usarán todos los programas que la necesiten.
Jesús Jiménez Herranz, http://oposcaib.wikispaces.com
1
El sistema operativo: gestión de memoria
El enlazado estático tiene la ventaja de que genera ejecutables independientes del entorno, en el
sentido de que no necesitan librerías externas. Ahora bien, el precio que se paga es un mayor
tamaño de los ejecutables, y una duplicación de recursos si dos programas utilizan la misma librería
(ambos la incluirían en su ejecutable). Por otra parte, si una vez compilado el programa aparece una
nueva versión de la librería, los programas no la utilizarían.
El enlazado dinámico sigue padeciendo el problema de la duplicación de datos en tiempo de
ejecución, pero en este caso los ejecutables son más pequeños, y es posible actualizar las librerías en
el sistema de manera que los cambios se propaguen a todos los programas que las usan.
El enlazado dinámico en tiempo de ejecución presenta las ventajas del enlazado dinámico, pero
además soluciona el problema de la duplicación de datos, al utilizar todos los programas una misma
instancia de la librería. La desventaja que tiene es que, al estar la librería en un espacio de
direcciones diferente al del resto del programa, se añade un nivel de indirección en cada acceso, lo
que puede ralentizar la ejecución.
En general, el esquema más utilizado es el dinámico en tiempo de ejecución, ya que el ahorro en
uso de recursos respecto al dinámico y al estático compensan la disminución del rendimiento. El
enlazado estático también tiene su uso en programas pequeños en los que se busque el máximo
rendimiento o en los que sea importante la independencia respecto al sistema operativo y las
librerías instaladas.
Carga
Como las direcciones almacenadas en un fichero ejecutable son relativas, en el momento de la
carga del programa es necesario convertirlas a las direcciones reales de memoria. Existen diferentes
esquemas:
●
●
●
Carga absoluta: Al cargar, se convierten las direcciones relativas a direcciones absolutas de la
zona de memoria en la que se va a cargar el programa. Impide reubicar el programa en otro
momento.
Carga reubicable: Establece las direcciones relativas respecto a 0, y dispone de un registro base
que indica la dirección en la que se carga el programa. Durante la ejecución, se suma a la
dirección relativa el contenido del registro base para determinar la dirección absoluta final.
Permite reubicar el programa simplemente moviéndolo y cambiando el valor del registro base.
Carga dinámica en ejecución: Dejar las direcciones en forma relativa, y en tiempo de ejecución
resolver cada dirección. Es el esquema más flexible, pero el gran overhead añadido requiere
hardware específico para que funcione bien.
Generalmente, y dado que todos los sistemas operativos modernos utilizan memoria virtual, el
esquema más utilizado es la carga dinámica en ejecución. En sistemas operativos empotrados
también es posible encontrar esquemas reubicables.
Estrategias de organización de la memoria
En un sistema operativo multiprogramado, en el que a lo largo del tiempo van a ejecutarse
diferentes programas, y donde por tanto entrarán y saldrán de memoria gran cantidad de procesos,
es importante planificar la estrategia de organización de memoria. A continuación se muestran los
principales esquemas.
Jesús Jiménez Herranz, http://oposcaib.wikispaces.com
2
El sistema operativo: gestión de memoria
Partición fija
En este caso, la memoria está dividida en bloques de tamaño fijo:
De esta forma, a cada proceso se le asigna un bloque de la
Tamaño fijo
Tamaño variable
memoria.
Los bloques pueden ser todos del mismo tamaño
128 K
128 K
512 K
(tamaño
fijo)
o tener diferentes tamaños (tamaño variable), si
256 K
bien el tamaño de los bloques nunca cambia en tiempo de
512 K
512 K
ejecución.
El direccionamiento en este esquema es sencillo, basta con
512 K
512 K
almacenar la dirección inicial del bloque en el que está el
proceso, y sumarla a sus direcciones relativas en cada acceso.
512 K
La reubicación también es sencilla, siempre y cuando existan
1024 K
bloques disponibles del tamaño apropiado.
512 K
Los problemas de este esquema son:
●
●
Gran fragmentación interna: Es decir, se desperdicia espacio dentro de cada bloque si el
proceso es de menor tamaño que el bloque. Este aspecto es aliviado en cierta manera por el
esquema de tamaño variable, pero aún así sigue existiendo.
Gran fragmentación externa: Se corresponde con el caso de que un proceso no se pueda cargar
porque, a pesar de que globalmente hay suficiente memoria libre, no existe ningún bloque libre
de su tamaño.
Partición dinámica
En este esquema, se utiliza una estrategia similar a la partición fija, pero los
bloques se van creando y asignando según se necesitan. Por tanto, para cada
proceso será necesario guardar dónde comienza su bloque y cuál es su longitud.
P2
Al asignarse los bloques de forma personalizada a cada proceso, este esquema
no padece de fragmentación interna. Ahora bien, sí que tiene fragmentación
P3
externa debido a los huecos que van quedando a medida que los procesos entran y
salen del sistema, lo que requiere compactar periódicamente el espacio de
memoria.
P4
Para intentar controlar esta fragmentación del espacio libre, es necesario
planear bien cómo se asignan los espacios de memoria a los nuevos procesos.
Básicamente existen tres esquemas:
P1
●
●
●
●
First-fit: Se asigna el primer espacio libre de suficiente tamaño.
Next-fit: Como first-fit, pero se empieza a buscar desde la última asignación, para no favorecer
(y por tanto fragmentar) el comienzo de la memoria.
Best-fit: Se asigna el espacio que mejor ajusta al tamaño del proceso.
Worst-fit: Se asigna el espacio que peor se ajusta, es decir, el más grande disponible.
Contrariamente a lo que pudiera parecer, el mejor algoritmo es worst-fit, seguido de first-fit,
next-fit y, finalmente, best-fit. La explicación de que best-fit funcione tan mal es que, al buscar
siempre el espacio que mejor ajusta, genera también huecos de espacio libre de pequeño tamaño,
que son difíciles de asignar y, por tanto, generan fragmentación externa. Por ese mismo motivo, y al
ser worst-fit el algoritmo que deja huecos de mayor tamaño, es el que genera menor fragmentación.
Jesús Jiménez Herranz, http://oposcaib.wikispaces.com
3
El sistema operativo: gestión de memoria
Paginación
Memoria
0
P1
0
1
1
2
2
7
1
P1.0
2
P1.1
3
4
P2.0
5
P2
6
0
4
7
1
9
8
9
P1.2
P2.1
Este esquema consiste en dividir, por una parte, la
memoria en particiones de muy pequeño tamaño
llamadas marcos, y, por otra, los programas en
particiones del mismo tamaño que los marcos llamadas
páginas. Para cada proceso, se guarda una tabla que
asigna a cada página su marco correspondiente en
memoria.
El acceso a memoria consistiría en averiguar, a partir
de la dirección de memoria, la página a la que se refiere
la dirección. De esta manera se podría consultar la tabla
de páginas para obtener el marco de memoria, y luego se
le sumaría el desplazamiento para obtener la dirección
final.
El número de página correspondiente a una dirección serían simplemente los N bits más
significativos de la misma, dependiendo N del tamaño de página. Por ejemplo, para un tamaño de
página de 32 KB, los 12 bits menos significativos serían el desplazamiento, y el resto de bits
indicarían la página.
En un esquema paginado no existe fragmentación externa, y la fragmentación interna se reduce a
la última página de un proceso, por lo que es despreciable. La principal desventaja es el overhead al
acceder a memoria, puesto que para cada acceso hay que consultar la tabla de páginas del proceso.
En cualquier caso, dadas las ventajas de este esquema, la mayoría de microprocesadores disponen
de métodos hardware para acelerar la gestión de la tabla de páginas y poder usar un esquema
paginado de forma eficiente.
Segmentación
Memoria
0
P1
0
Pos:0 Tam:1
1
Pos:1 Tam:2
2
Pos:7 Tam:1
P1.0
1
2
P1.1
3
4
5
P2
P2.0
6
0
Pos:4 Tam:3
7
1
Pos:8 Tam:2
8
P1.2
Es un esquema similar a la paginación, pero en el que
los programas se dividen en segmentos en lugar de en
páginas. La diferencia es que cada segmento puede tener
un tamaño diferente, si bien el resto del funcionamiento
es idéntico: una tabla de correspondencia entre
segmentos y bloques de memoria, y un direccionamiento
en el que parte de la dirección se usa para determinar el
segmento y el resto para el desplazamiento.
La segmentación no tiene fragmentación interna,
aunque sí tiene fragmentación externa al ser los
segmentos de diferente tamaño.
P2.1
9
A pesar de la fragmentación, la ventaja de este sistema respecto a la paginación es que facilita la
programación a alto nivel, favoreciendo la modularización del programa. De esta manera, es
posible utilizar un segmento para código, otro para datos, etc., con lo que además de facilitar la
escritura de programas se hace más fácil la protección de los mismos (p. ej. impidiendo escribir en
segmentos de código).
Jesús Jiménez Herranz, http://oposcaib.wikispaces.com
4
El sistema operativo: gestión de memoria
Segmentación y paginación
Para combinar las ventajas de la segmentación y la paginación, es posible utilizar
simultáneamente los dos esquemas. Así, la gestión de memoria sería paginada, es decir, dividiendo
el programa en páginas y la memoria en marcos, pero además el programa se dividiría a más alto
nivel en segmentos, cada uno de ellos con un tamaño en número de páginas.
De esta manera, se pueden conseguir los beneficios en cuanto a modularidad de la segmentación,
sin ninguno de sus inconvenientes, ya que al usar paginación no existiría fragmentación externa.
En cualquier caso, la popularización de lenguajes de alto nivel, que por una parte permiten
modularizar programas sin problemas, y que por otra alejan al programador de los detalles de
implementación del sistema operativo, hacen que la segmentación no se utilice en exceso, ya sea
por sí sola o combinada con paginación.
Memoria virtual
Concepto
El esquema de memoria virtual consiste en establecer, para cada proceso, un espacio de
direcciones virtual, e independiente del espacio de memoria real. En tiempo de ejecución, el sistema
operativo se encargaría de mapear este espacio virtual a la memoria real.
Una ventaja fundamental de este sistema es que permite tener cargada en memoria únicamente la
parte de un programa que se está ejecutando, cargando las páginas a medida que se necesitan y
descargándolas (por ejemplo a disco) cuando ya no se usan. Debido a los principios de localidad, en
un momento dado sólo se utiliza una parte muy pequeña de la memoria que utilizará el programa en
su ciclo de vida, por lo que el uso de memoria se reduce drásticamente, aumenta el grado de
multiprogramación del sistema y, en particular, es posible ejecutar programas que requieren más
memoria que la existente físicamente.
El conjunto de páginas de un proceso que están cargadas en memoria en un momento dado es lo
que se conoce como el conjunto residente del proceso. Este conjunto va variando con el tiempo a
medida que se cargan y descargan páginas de memoria. Cuando el proceso intenta acceder a una
página que no está en memoria, se produce un fallo de página, y el sistema operativo se encarga de
cargar la página solicitada en memoria.
Aunque generalmente la memoria virtual se utiliza en conjunción con la paginación, también es
posible hacerlo en un esquema segmentado.
TLBs
A pesar de sus ventajas, el esquema de memoria virtual ralentiza notablemente el funcionamiento
del sistema, ya que para cada acceso a memoria se requieren dos operaciones: una para traducir la
dirección virtual a una dirección real, y otra con el acceso en sí. Para aliviar este problema, los
microprocesadores modernos disponen de mecanismos hardware que facilitan el proceso.
Un de las facilidades que incluyen los microprocesadores es el TLB (Translation Lookaside
Buffer), que no es más que una pequeña caché muy rápida (generalmente asociativa) que contiene
parte de la tabla de páginas del proceso. De esta manera, para la mayoría de accesos (el hit ratio
suele ser superior al 99%) la CPU traduce las direcciones virtuales a direcciones físicas mediante el
TLB, sin necesidad de accesos a memoria adicionales a la tabla de páginas.
En caso de que la dirección virtual no esté en el TLB, la propia CPU se encarga de leerla de la
tabla de páginas en memoria y actualizar el TLB. Si la página tampoco estuviese en la tabla de
páginas, quiere decir que no está cargada en memoria, por lo que se generaría una interrupción, y el
sistema operativo se encargaría de cargar la página en memoria.
Jesús Jiménez Herranz, http://oposcaib.wikispaces.com
5
El sistema operativo: gestión de memoria
Políticas de lectura de páginas
Las diferentes políticas de carga en memoria de páginas pueden ser principalmente dos:
●
●
Por demanda: Cuando se produce un fallo de página, se lee la página de disco.
Previa: Ante un fallo de página, se cargan en memoria la página que ha producido el fallo, así
como las contiguas. Esto se basa en los principios de localidad y es especialmente eficiente en
el inicio de los programas. Además, aprovecha también las características de los discos duros.
Políticas de reemplazo
En muchas ocasiones, la carga de una página en memoria implica la descarga de otra que ya
estuviera allí. Escoger una buena política de reemplazo es fundamental para obtener un buen
rendimiento del sistema, ya que las cargas de páginas son costosas en tiempo de ejecución. La
opción ideal sería descargar de memoria la página a la que se va a tardar más tiempo en acceder,
pero como eso es un dato imposible de obtener, existen diferentes esquemas que intentan
aproximarse al ideal:
●
●
●
FIFO: Se extrae siempre la página que lleva más tiempo en memoria. Poco preciso.
LRU: Se mantiene un registro de accesos a cada página, y se descarga aquella que menos se ha
usado recientemente. Es más eficiente que FIFO, pero es costoso de implementar.
Política del reloj: Se basa en almacenar, para cada página, un bit que se activa al acceder a ella.
A la hora de descargar páginas, se recorre de forma circular la lista de páginas hasta encontrar
una página a 0. A medida que se recorre, se van poniendo los 1s a 0s, de modo que en el peor
caso (todas las páginas están a 1) se volvería a la primera página. La eficiencia de este esquema
es cercana a la de LRU, pero es mucho más sencillo de implementar.
En cualquiera de estas políticas, si se descarga una página y en poco tiempo se vuelve a acceder,
el sistema se resiente innecesariamente.
Una forma de aliviar este problema es, al descargar una página, no borrarla de memoria sino
simplemente quitarla de la tabla de páginas y guardar su referencia en una FIFO. Cuando realmente
sea necesario liberar memoria, ir descargando las páginas de la FIFO, pero si la política de
reemplazo se ha equivocado y se vuelve a acceder a una página supuestamente descargada,
restaurarla será casi instantáneo.
Para poder implementar este sistema, hay que iniciar las acciones de reemplazo antes de agotar
completamente la memoria, de modo que se disponga de algo de margen. En realidad, este esquema
es similar a una caché.
Gestión del conjunto residente
Para maximizar el número de procesos que pueden estar en memoria en un momento dado y, por
tanto, el grado de multiprogramación del sistema, se suele limitar el número de páginas que puede
tener simultáneamente en memoria un proceso, o lo que es lo mismo, su conjunto residente. Es
importante establecer con precisión este tamaño, ya que un conjunto residente demasiado grande
reduce el grado de multiprogramación del sistema, mientras que uno demasiado pequeño aumenta
innecesariamente el número de fallos de página en el sistema.
La gestión del conjunto residente también establece el alcance de la sustitución de páginas:
puede ser local (se descargan páginas del proceso que ha provocado el fallo) o global (se consideran
las páginas de todos los procesos).
Jesús Jiménez Herranz, http://oposcaib.wikispaces.com
6
El sistema operativo: gestión de memoria
La asignación de tamaño del conjunto residente puede ser de dos tipos:
●
●
Fija: Se asigna un número N fijo de páginas que puede tener en memoria un proceso, y este N
se mantiene constante a lo largo de la ejecución del proceso. Implica alcance local.
Variables: El valor de N va cambiando durante la vida del proceso según diferentes parámetros.
En un esquema variable de asignación del conjunto residente, el valor de N fluctúa a lo largo de
la ejecución del proceso. Idealmente, el valor de N debería ser aquel que produce un número de
fallos de página mínimo. Las siguientes estrategias intentan acercarse a este ideal:
●
●
●
Estrategia del conjunto de trabajo: Se monitoriza periódicamente a qué páginas accede el
proceso, y se establecen estas páginas como su conjunto residente. Es un esquema difícil de
implementar.
Estrategia de frecuencia de fallos: Se establecen umbrales para la frecuencia de fallos
provocados por el proceso en un intervalo concreto. Si se supera el umbral superior, se aumenta
el tamaño del conjunto residente, mientras que si no se llega al umbral inferior, se reduce. Es
fácil de implementar, pero tiene problemas en los transitorios (carga, reubicaciones del
proceso, etc.).
Estrategia de muestreo: Se funciona como en la estrategia de frecuencia de fallos, pero no se
hace el recuento continuamente sino que sólo se hace cada cierto tiempo. Esto hace que sea
menos sensible a los períodos transitorios.
Hiperpaginación
Cuando el tiempo dedicado por el sistema a los fallos de página supera al tiempo utilizado en la
ejecución de los procesos, se dice que el sistema ha entrado en hiperpaginación. La causa de la
hiperpaginación suele ser una excesiva multiprogramación, que provoca que el conjunto residente
de todos los procesos sea insuficiente, y se disparen los fallos de página.
Algunas soluciones a este fenómeno son:
●
●
●
Utilizar una estrategia de gestión del conjunto residente, ya que estas estrategias no permiten
lanzar un proceso hasta que no haya disponibles como mínimo tantas páginas de memoria
como el tamaño de su conjunto residente.
Ajustar el grado de multiprogramación del sistema según el tiempo entre fallos, aumentándolo
o disminuyéndolo según evolucione.
Suspender procesos hasta que la situación se estabilice. A la hora de escoger qué procesos
suspender, se pueden utilizar diferentes criterios: prioridad, tamaño en memoria, número de
fallos que ha provocado, etc.
Jesús Jiménez Herranz, http://oposcaib.wikispaces.com
7