Objetivos
- Establecer el manejo de varios procesos en la memoria de NachOS por medio de paginación
- Modificar el constructor de "AddrSpace" para permitir el uso de mapas de bits (bitmaps)
- Definir las estructuras de datos para que puedan ser actualizadas por hilos concurrentes
Procedimiento
- Trate de definir y utilizar constantes en sus programas
- Encabezado de los programas de usuario
- Cámbiese al directorio "userprog"
- Analice el código de la clase "AddrSpace", especialmente su constructor
- Identifique los siguientes puntos (si es necesario agregue mensajes de despliegue):
- ¿Cómo es leído el encabezado del programa ejecutable NachOS?
- ¿De qué tamaño es el encabezado?
- ¿Cuál es el número mágico?
- Puede verificar el número con hexdump
hexdump -n 128 -C ../test/halt
- Analice la estructura de los segmentos de NachOS y la estructura del encabezado (noff) de los programas ejecutables de MIPS
- ¿Cómo es establecido el tamaño del proceso?
- ¿Cuál es el tamaño del segmento de código (T)?
- ¿Cuál es el tamaño del segmento de datos (D)?
- ¿Cuál es el tamaño de la pila (S)?
- ¿Cuál es el tamaño de una página?
- ¿Alguno de estos tamaños puede ser cero?
- ¿Cómo el programa es cargado (del disco) a memoria?
- ¿Cómo se realiza la lectura del disco?
- Analice la clase encargada de realizar esta lectura del disco
- ¿Cómo se determina el archivo de donde se realiza la lectura ?
- ¿Cómo se indica la cantidad de bytes que se quiere leer?
- ¿Cómo hacer para leer del archivo solo una página (128 bytes)?
- ¿Cuál es la posición dentro del archivo de lectura?
- ¿Cómo es colocada en la memoria la información leída del disco?
- ¿Cuál es la posición en la memoria?
- ¿Cómo se puede cambiar esta dirección?
- Analice la estrategia que va a seguir para colocar las páginas de 128 bytes leidas del archivo ejecutables en las posiciones de memoria correspondientes (frames) también de 128 bytes
- Analice cómo va a manejar las páginas que se leen del archivo cuyo tamaño es menor que 128 bytes
- Analice una estrategia para manejar páginas que pueden tener información de segmentos distintos, por ejemplo de código (T) y datos (D)
- Estudiar el funcionamiento de la clase "TranslationEntry"
- Cada vez que el procesador (MIPS) realiza un acceso a memoria, se emplea un registro especial (pageTable) para realizar la traducción de las direcciones
- Como referencia estudiar el código en el archivo "machine/translate.cc" los métodos "Machine::Translate", "Machine::ReadMem" y "Machine::WriteMem"
- También puede revisar la estructura de la máquina MIPS que se construye en "machine/machine.h"
- También heche un vistazo por los métodos "AddrSpace::InitRegisters", "AddrSpace::RestoreState" y "AddrSpace::SaveState"
- Explique como esta estructura (pageTable) es construida y llenada en el constructor de "AddrSpace"
- Por ahora el mapeo se realiza asignando a cada página lógica de un proceso la misma página física, ( 0 -> 0, 1 -> 1, etc.). Para poder correr varios programas de usuario en la misma memoria física es necesario cambiar esta manera de asignación
- Estudie los métodos de la clase BitMap:
- Investigue cómo crear un mapa de bits que represente la memoria del procesador MIPS que estamos simulando. Debe conocer el tamaño (ver machine/machine.h) en páginas de esa memoria. Este mapa de bits indicará si la página está ocupada o libre
- Como esta es una estructura que puede ser compartida por varios hilos, determine la manera en que hará que su uso sea de acceso exclusivo
- Administración de la memoria de NachOS para programas de usuario
- Cree una estructura de datos (BitMap) para representar las páginas de la memoria. Puede colocarla como una variable global en los archivos "system.h" y "system.cc" en el directorio "threads", su declaración debe ser similar a la de la variable "currentThread"
- Para crear una variable global, debe agregarla en el archivo "system.h", por ejemplo "MiMapa" de esta manera
#ifdef USER_PROGRAM
#include "machine.h"
extern Machine* machine; // user program memory and registers
extern BitMap * MiMapa; // Declares a global variable defined elsewhere
...
#endif
- Note que la declaración puede colocarse dentro un #ifdef para hacerla condicional
- Además, esta nueva variable debe existir en el archivo "system.cc"
#ifdef USER_PROGRAM // requires either FILESYS or FILESYS_STUB
BitMap * MiMapa; // Variable definition, no extern prepended
- Inicialice la variable en el método "Initialize"
- Haga que NachOS utilice esta estructura para solicitar las páginas de memoria y actualizar la tabla de páginas del proceso. Por el momento, asegúrese de que el programa obtenga las mismas páginas que antes (0, 1, 2, etc.). No cambie la manera en que el programa es cargado en la memoria
- Recuerde asignar las páginas de los datos no inicializados y la pila
- Verifique que el programa de usuario "halt" funcione correctamente
- Carga del programa en la memoria
- Explique la manera en que el programa es cargado a la memoria
- Explique qué hace el método ReadAt de la clase OpenFile
- Explique la funcionalidad de los parámetros del método ReadAt
- Indique porqué hay dos llamados a este método
- Haga un diagrama que muestre la estructura de los programas de NachOS
- Estructura de los programas de usuario de NachOS en la arquitectura MIPS, formato NOFF, "in-disk image"
Encabezado (H) |
Texto (TX) |
Datos Inicializados (DI) |
- Estructura del encabezado de un programa de usuario de NachOS
- Analice la manera en que el programa puede ser leído por páginas (128 bytes)
- Haga que se lea el segmento de texto (código) página por página
- Haga lo mismo que en el paso anterior para el segmento de datos
- Considere el caso en que los segmentos no son múltiplos exactos de una página
- Asegúrese de reservar páginas para datos no inicializados y pila, aunque no debe ser leídos del disco
- Coloque las páginas de código y datos (128 bytes) leídas del archivos la posición de memoria correspondiente
- La posición es la indicada por nuestro pequeño administrador de memoria, descrito en el punto 4). Está dada por la tabla de páginas del proceso
- Verifique que el programa de usuario "halt" funcione correctamente
- ¿Cuáles cosas deben deshacerse cuando el programa finaliza (llama a Exit)?
- Pruebas
- Haga que algunas páginas (ejemplo 0,2,4,6,8,10) dentro de su administrador aparezcan como ocupadas antes de cargar cualquier programa en memoria, ésto se puede realizar dentro de constructor de "AddrSpace"
- Verifique el programa "halt" funcione
- Compruebe que el programa "addrspacetest" funcione bien
- Ejemplo de salida de "addrspacetest", requiere que "Exit" y "Write a la salida estándar estén implantados:
[farroyo@cloud userprog]$ ./nachos -x ../test/addrspacetest
abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{
abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{
abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{
abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{
abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{
abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{
abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{
abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{
abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxyz{
abcdefghijklmnopqrstuvwxyz{abcdefghijklmnopqrstuvwxy
No threads ready or runnable, and no pending interrupts.
Assuming the program completed.
Machine halting!
Ticks: total 31332, idle 0, system 560, user 30772
Disk I/O: reads 0, writes 0
Console I/O: reads 0, writes 1
Paging: faults 0
Network I/O: packets received 0, sent 0
Cleaning up...
- Libere las páginas del primer punto
- Corra de nuevo el programa "addrspacetest"
- Fin