Los procesos entienden de direcciones dentro del mapa de memoria del procesador. El gestor de memoria asigna un marco de página a un proceso, estableciendo un soporte físico más rápido a una zona de la memoria del proceso.
Requisitos de la Gestión de Memoria
El S.O. multiplexa los recursos entre los procesos:
- Cada proceso cree que tiene una máquina para él solo.
- Gestión de procesos: Reparto de procesador.
- Gestión de memoria: Reparto de memoria.
Funciones del Gestor de Memoria
- Crear la imagen de los procesos a partir de los ficheros ejecutables.
- Proporcionar protección entre procesos.
- Aislar los procesos.
- Controlar los recursos.
- Tratar los errores de acceso a memoria (detectados por el HW).
- Optimizar las prestaciones del sistema.
Tipos de Memoria
Memoria Real
No tiene memoria virtual; todas las regiones están en una zona contigua a la memoria principal (MP). Se deja un espacio de memoria principal para el crecimiento dinámico de las regiones.
Memoria Virtual
Las regiones están separadas, alineadas a página y están formadas por un número entero de páginas. Al crear o crecer, es cuando se requiere asignar soporte físico. Los espacios entre regiones no tienen soporte físico.
El Programa y la Memoria
Gestión de Memoria por el Programa
Crear una variable dinámica que quepa en la correspondiente región no implica al SO (lo resuelven las bibliotecas del lenguaje). Aumentar la región dinámica lo hacen las bibliotecas del lenguaje. Las bibliotecas del lenguaje gestionan el espacio disponible en la región de datos dinámicos (llaman al SO cuando tienen que variar el tamaño de la región o crear una nueva región).
Imagen de Memoria
Conjunto de regiones (o segmentos) de memoria asignados a un proceso.
Características de una Región
- Región: Zona de direcciones de memoria definidas por dirección de comienzo y tamaño.
- Fuente: Lugar donde se almacena el valor inicial.
- Puede ser compartida o privada.
- Niveles de protección típicos: RWX (Lectura, Escritura, Ejecución).
- Puede tener tamaño fijo o variable.
Operaciones sobre Regiones
- Creación de Región:
- Al crear el mapa inicial o por una solicitud posterior.
- En sistemas con memoria virtual no se asignan marcos de memoria principal; se asigna swap o se rellena con 0.
- Liberación de Región:
- Al terminar el proceso o por solicitud posterior.
- Se recuperan los recursos (swap y marcos).
- Cambio de Tamaño de Región:
- Del heap o de la pila.
- En sistemas con memoria virtual no se asigna memoria principal.
- Duplicado de Región:
- Operación requerida por el servicio FORK.
Características Detalladas de las Regiones de Memoria
Región de Código
- Compartida, RX (Lectura, Ejecución).
- Tamaño fijo.
- Fuente: el fichero ejecutable.
Región de Datos con Valor Inicial
- Privada, RW (Lectura, Escritura).
- Tamaño fijo.
- Fuente: el fichero ejecutable.
Región de Datos sin Valor Inicial
- Privada, RW (Lectura, Escritura).
- Tamaño fijo.
- Fuente: rellenar con 0.
Región de Pila
- Privada, RW (Lectura, Escritura).
- Tamaño variable.
- Fuente: rellenar con 0.
- Pila inicial (creada al arrancar el programa):
- Variables de entorno.
- Argumentos del programa.
Región de Heap
- Soporte de memoria dinámica gestionada por el lenguaje (p.ej.,
malloc
en C). - Persistencia controlada por el programador.
- Privada, RW (Lectura, Escritura).
- Tamaño variable.
- Fuente: rellenar con 0.
Memoria Compartida
- Región asociada a la zona de memoria compartida.
- Compartida, tamaño variable.
- Fuente: rellenar con 0.
- Protección especificada en proyección.
Fichero Proyectado
- Región asociada a cada fichero proyectado.
- Compartida o privada, tamaño variable.
- Fuente: el fichero proyectado.
- Protección especificada en proyección.
Pilas de Threads
- Cada pila de thread corresponde con una región.
- Mismas características que la pila del proceso.
Biblioteca Dinámica
- Regiones asociadas al código y datos de cada biblioteca dinámica.
Creación de Regiones
El gestor de memoria crea las regiones de memoria cuando:
- Se crea un proceso (
fork
). - Se cambia el programa del proceso (
exec
). - Se solicita una nueva región.
Estructura de un Fichero Ejecutable
- Cabecera: Número mágico, registros, tabla de secciones.
- Sección de Código (Texto): Contiene código del programa. Suele incluir también las constantes del programa y cadenas de caracteres.
- Sección de Datos con Valor Inicial: Variables globales inicializadas.
- Tabla de Símbolos: Para depuración y montaje dinámico.
- Lista de Bibliotecas Dinámicas Usadas.
Variables en Memoria
Variables Globales
- Estáticas.
- Se crean al iniciarse el programa.
- Existen durante toda la ejecución del mismo.
- Dirección fija en memoria y en ejecutable.
Variables Locales y Parámetros
- Creadas dentro del registro de activación de la rutina.
- Se crean al invocar una función.
- Se destruyen al retornar.
Crear Imagen desde Ejecutable
El gestor de memoria se encarga de crear la imagen del proceso a partir de un fichero ejecutable. En UNIX, esta operación la realiza exec
.
Obtención y Utilización de Memoria en Bruto
Obtención de Memoria en Bruto
- Mediante las bibliotecas del lenguaje (
malloc
,new
, etc.). - Mediante el SO (se detallan más adelante):
- Fichero proyectado en memoria.
- Región de memoria compartida.
- Nueva región de memoria.
Utilización de Memoria en Bruto
Se proyecta sobre la zona asignada uno o varios tipos de datos: estructura, vector, array, etc. Se utilizan los datos mediante la referencia o el puntero devuelto por el servicio o por la función del lenguaje. Para memoria compartida, hay que proyectar los mismos datos en todos los programas.
Detalle de malloc
Es una función del lenguaje. Si la memoria solicitada en malloc
no cabe en la región, es necesario solicitar al SO una ampliación de la región de datos. La memoria obtenida sobrevive al retorno de la función donde se ubicó. Ha de liberarse explícitamente. Al hacer un free
, no se reduce el tamaño del heap.
Parámetros
Primeros elementos de su bloque de activación (mete en la pila los valores).
Páginas y Marcos de Memoria
El espacio virtual se considera organizado en páginas de tamaño fijo. El espacio de disco dedicado a soportar la memoria virtual se divide en páginas. La memoria principal se divide en marcos de página. En estos marcos se ubican las páginas. El SO ha de conseguir que las páginas usadas en cada momento estén ubicadas en marcos de memoria principal.
Memory Management Unit (MMU)
La MMU traduce las direcciones virtuales en reales, basándose en una estructura de información denominada tabla de páginas. Cada proceso tiene su tabla de páginas.
- La MMU produce un fallo de página (excepción) cuando la página afectada no está en memoria principal, pero sí en la tabla de páginas.
- La MMU produce una excepción de violación de memoria cuando la página afectada no está en la tabla de páginas del proceso.
- El SO trata el fallo de página, haciendo un transvase entre la memoria principal y el swap (disco).
- El SO trata la violación de memoria abortando el proceso.
Fichero Proyectado en Memoria
Supone extender la zona de intercambio con una parte de un fichero.
- Tamaño entero de páginas, aunque se pida menos.
- Crear una región de memoria en el proceso del mismo tamaño que la parte de fichero añadida al intercambio.
Modos de Proyectar el Fichero
Proyección Compartida
Los cambios son visibles por otros procesos que tengan proyectado el fichero y se modifica el fichero en el disco. Las regiones de código se suelen construir proyectando la sección de código de los ficheros ejecutables en modo compartido (exec
).
Proyección Privada
Los cambios no son visibles por otros procesos que tengan proyectado el fichero, ni modifican el fichero en el disco. Se realiza una copia privada de la zona de disco proyectada.
Fallo de Página
La MMU genera una excepción que es tratada por el gestor de memoria, que:
- Selecciona un marco de página.
- En caso necesario, libera el marco de página, devolviendo su contenido a swap (algoritmo de reemplazo).
- Lee del disco la página requerida y la transfiere al marco seleccionado.
- Actualiza la tabla de páginas con la nueva metainformación.
Memoria Virtual: Buffering de Páginas
Si el número de marcos libres es menor que un umbral y/o el procesador está libre:
- Un “demonio de paginación” aplica repetidamente el algoritmo de reemplazo, seleccionando páginas a reemplazar:
- Se marcan como no disponibles en la tabla de páginas, pero:
- Las páginas no modificadas pasan a la lista de marcos libres.
- Las páginas modificadas pasan a la lista de marcos modificados.
- Si se referencia una página mientras está en estas listas:
- El fallo de página la recupera directamente de la lista (no hay E/S).
Multiprogramación
Al aumentar el grado de multiprogramación:
- Hay menos marcos de página para cada proceso.
- Aumentan los fallos de página.
Copy-On-Write (COW)
Se comparte una página mientras no se modifique. Si un proceso la modifica, se crea una copia para él. Es un “duplicado por demanda”. COW es útil para el fork
y para los datos con valor inicial.
Implementación de COW
- Se comparten páginas de regiones duplicadas, pero:
- Se marcan de solo lectura y con bit de COW.
- Primera escritura → Fallo de protección → copia privada.
- Puede haber varios procesos con la misma región duplicada:
- Existe un contador de uso por página.
- Cada vez que se crea una copia privada, se decrementa el contador.
- Si llega a 1, se desactiva COW, ya que no hay duplicados.
FORK con COW
- Se comparten todas las regiones.
- Las regiones privadas se marcan como COW en padre e hijo.
Resultado de la Optimización del FORK
En vez de duplicar espacio de memoria, solo se duplica la tabla de páginas.
Swap
- Preasignación de swap: Cada página virtual asignada tiene un espacio fijo en el swap.
- Sin preasignación de swap: Una página virtual asignada puede estar en:
- Swap.
- Un marco de memoria.
- Un fichero proyectado.
- A rellenar a 0.
- En reemplazo, hay que copiar la página a swap.
- Solamente se dedica swap a las regiones asignadas a los procesos.
- Tamaño típico de swap es del orden del doble de la memoria principal disponible.
- Swap reside normalmente en el disco (en una partición o un fichero).
- En algunos casos, el swap reside en una memoria RAM.
Rellenar con 0
Un posible problema de seguridad aparece cuando se le suministra a un proceso un soporte físico de memoria y este no tiene valor inicial. Si no se rellena a 0 por el SO, el proceso podrá leer el contenido que dejó en ese soporte físico el proceso que lo utilizó anteriormente, pudiendo recuperar información valiosa del mismo.
Errores de Acceso a Memoria
Errores y avisos detectados por el HW y tratados por el SO.
- Acceso a una dirección fuera de las regiones asignadas:
- Acción del SO: Enviar una señal al proceso, que suele matarlo.
- Acceso a una dirección correcta pero con un tipo de acceso no permitido (en algunos casos es un aviso):
- Acción del SO: Enviar una señal al proceso, que suele matarlo.
- Desbordamiento de pila:
- Se pone la última página como de lectura. Si se intenta escribir, es que queda poca pila.
- Acción del SO: Incrementar la región de pila. Si no es posible el incremento, enviar una señal al proceso para matarlo.
- Fallo de página:
- Acción del SO: Realizar la migración de la página fallida y actualizar la tabla de páginas afectada.
- COW (Copy-On-Write):
- Las páginas están como de lectura.
- Acción del SO: Desdoblar la página.
Bibliotecas Estáticas
- Montaje: Enlaza los módulos objeto con copias de módulos de las bibliotecas.
- Ejecutable autocontenido.
- Desventajas del montaje estático:
- Ejecutables grandes.
- Código de función de biblioteca repetido en muchos ejecutables.
- Múltiples copias en memoria del código de función de biblioteca.
- La actualización de la biblioteca implica volver a montar cada programa que las usa.
Bibliotecas Dinámicas
- Carga y montaje de la biblioteca en tiempo de ejecución.
- Región de código compartida.
- Región de datos privada.
Ventajas del Montaje Dinámico
- Menor tamaño de los ejecutables.
- Código de rutinas de biblioteca solo en el fichero de biblioteca.
- Los procesos pueden compartir el código de la biblioteca (región compartida en modo read only).
- Actualización automática de las bibliotecas: Uso de versiones.
Inconvenientes
- Bibliotecas del mismo nombre incompatibles (versiones incompatibles).
- Eliminación de bibliotecas obsoletas.
- Sobrecarga en tiempo de ejecución.
Alternativas de Montaje Dinámico
Montaje en Tiempo de Carga en Memoria
Al iniciar la ejecución del programa, el SO completa el ejecutable incluyendo todas las bibliotecas dinámicas y resolviendo los enlaces.
Montaje al Invocar el Procedimiento
Solamente cuando el proceso trata de ejecutar un procedimiento por primera vez se incluye la biblioteca correspondiente y se resuelve su enlace. Produce menos sobrecarga que la solución anterior.
El ejecutable contiene:
- Nombre de la biblioteca, así como los puntos de enlace de las rutinas de la biblioteca.
- Rutina encargada de cargar y montar la biblioteca en tiempo de ejecución al realizarse la primera referencia a un procedimiento de la misma.
Montaje Explícito
- Es más flexible que el anterior, puesto que se puede seleccionar la biblioteca en tiempo de ejecución.
- El ejecutable ha de preguntar a la biblioteca sobre los puntos de enlace de sus funciones.
- Es más frágil que los anteriores, puesto que el compilador no ayuda a verificar los prototipos de las llamadas.