Descripción: EUGENIO JACOBO HERNÁNDEZ VALDELAMAR. TESIS para obtener el grado de MAESTRÍA EN CIENCIAS DE LA COMPUTACIÓN....
ESTUDIOS CON RECONOCIMIENTO DE VALIDEZ OFICIAL NUMERO 00922681 DE FECHA 23 DE JUNIO DE 1992
DISEÑO Y SIMULACIÓN DE SISTEMAS OPERATIVOS
TESIS QUE PARA OBTENER EL GRADO DE MAESTRIA EN CIENCIAS DE LA COMPUTACIÓN PRESENTA: EUGENIO JACOBO HERNÁNDEZ VALDELAMAR
ASESOR: ENRIQUE CALDERÓN ALZATI
MÉXICO, D.F.
AGOSTO, 2003
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
DISEÑO Y SIMULACIÓN DE SISTEMAS OPERATIVOS EUGENIO JACOBO HERNÁNDEZ VALDELAMAR
http://creativecommons.org/licenses/by-nc-nd/2.5/mx/legalcode
Cualquier comentario o sugerencia es bien recibido en
[email protected]
2
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Contemplando una idea. Vladimir Islas Valdelamar
i
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Agradecimientos A mi familia, en especial a mi madre Guadalupe Valdelamar, a mi padre Jacobo Hernández y a mi tía Maria Luisa por su apoyo. A mi esposa y compañera Mar Sallago por su alegría y aliento (gracias por mostrarme otras perspectivasπ); y a toda la familia y amigos en Argentina, en especial a Pedro, Lis y Leo por su amistad. A mis profesores: Enrique Calderón, Carlos Calderón, Miguel Orozco, Alejandro Domínguez, Miguel Leal; Marcos Calderón y Edgar Herrador (después de todo, se superaron las dudas de ese mítico curso). A mis colegas: Jorge Vasconcelos por su ejemplo de perseverancia en la vida académica y sus comentarios a este trabajo; Miguel Armas por compartir muchos alucines académicos y a Roberto Murcio por sus comentarios a este trabajo en sus inicios. A los buenos amigos del Instituto de Química de la UNAM, en especial a Jaime Lagunez por abrirme la perspectiva de las consideraciones biológicas en cuestiones de sistemas cómputo. A los alumnos de licenciatura de la FAR del curso de sistemas operativos en el periodo 2002-3 (Gonzalo, Humberto, Gerardo, Josué, Héctor, Enrique, Luis) y 2003-1 (Lizethe, Rodrigo, Oscar, Christian, J. Ignacio, Josué), por la oportunidad de poner en práctica los resultados de este trabajo y el reto de transmitirles los conocimientos de un tema complejo y apasionante. A Paco Otero, Hugo Gutiérrez y a Rodrigo Herrera por su amistad. A Antonio Martinez por demostrarnos que es posible vivir la vida fuera del sistema. A la familia Morán; Alfonso Sr. y Jr., Manolo: gracias por su apoyo y amistad. Al profesor Rubén Lara por su gran labor en la enseñanza del kendo. To Rachael Dunne, Oisin & friends, (thanks for the opportunity of visiting Ireland, even when I preferred to stay in México; it was a great time) and Alan Armijo (thanks for offer me the opportunity of going to the US even when the odds were against the idea).
ii
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Resumen
Estamos en una época donde parece que el interés por cómo funcionan las cosas o cómo hacerlas, pasa a un segundo plano a raíz de estar más ocupados utilizándolas. El software no es la excepción. Toda aplicación que se use tiene un proceso de desarrollo, y más aún, cuenta con un sistema que soporta su ejecución. Estas piezas de ingeniería de software que nos hacen la vida más amable son los sistemas operativos, y vale mencionar que sin ellos, seguramente seguiríamos requiriendo de operadores de computadora súper especializados. Este trabajo es una investigación acerca de los sistemas operativos. El objetivo es proveer una visión integral de este tipo de sistemas; desde sus antecedentes y fundamentos, hasta un análisis de sus componentes y el establecimiento de criterios de diseño. He tratado de mantener un balance entre la teoría y la práctica, incluyendo algunos proyectos de desarrollo que han arrojado como producto no solo el código de los simuladores propuestos, sino la experiencia de las consideraciones involucradas en hacer un sistema operativo; experiencia que he tenido oportunidad de compartir con mis estudiantes. Además de los temas clásicos como administración de memoria, procesos y dispositivos, se incluye una sección dedicada al diseño de sistemas operativos, así como una completa referencia de las arquitecturas existentes en este tipo de sistemas, y las tendencias a futuro. Este trabajo será de utilidad para todos aquellos usuarios, administradores y desarrolladores de sistemas operativos, así como para cualquier profesional de las ciencias de la computación.
iii
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
iv
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Contenido
Introducción ___________________________________________________________ 1 Capitulo 1. 1.1
¿Qué es un sistema operativo? ___________________________________________ 7
1.1.1 1.1.2
1.2
Definiciones ______________________________________________________________ 8 Características principales__________________________________________________ 10
Principales conceptos de los Sistemas Operativos___________________________ 11
1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8
1.3
Fundamentos de los Sistemas Operativos _______________________ 7
Administración de procesos _________________________________________________ 12 Administración de memoria _________________________________________________ 13 La gestión de la integridad __________________________________________________ 13 Administración de dispositivos ______________________________________________ 14 Almacenamiento secundario ________________________________________________ 14 Transmisión de datos e información __________________________________________ 15 Núcleo del sistema (Kernel)_________________________________________________ 15 Comunicación con el usuario ________________________________________________ 16
Desarrollo histórico de los Sistemas Operativos ____________________________ 18
1.3.1 En el principio...__________________________________________________________ 20 1.3.2 Procesamiento por lotes y monitores __________________________________________ 21 1.3.3 Sistemas de operación simultanea de periféricos en línea __________________________ 23 1.3.4 Sistemas de Multiprogramación______________________________________________ 24 Sistemas de tiempo compartido (Timesharing) ____________________________________ 25 Sistemas de Tiempo Real _____________________________________________________ 27 1.3.5 Sistemas Multiprocesador, distribuidos y en red _________________________________ 28 1.3.6 Computadoras Personales __________________________________________________ 30
1.4
Comentarios _________________________________________________________ 32
1.5
Obras consultadas ____________________________________________________ 33
Capitulo 2. 2.1
Funcionamiento básico de un sistema operativo_________________ 35
El hardware y la ejecución de programas _________________________________ 35
2.1.1 La unidad central de procesamiento___________________________________________ 36 2.1.2 La memoria _____________________________________________________________ 38 2.1.3 Ejecución de programas ____________________________________________________ 39 2.1.4 Interacción entre los componentes de hardware__________________________________ 41 Tipos de interrupciones ______________________________________________________ 45
2.2
Software para el control del hardware____________________________________ 46
2.2.1 2.2.2 2.2.3 2.2.4
2.3
El papel del BIOS ________________________________________________________ 46 Rutinas del BIOS ___________________________________________________________ 47 Secuencia de arranque _______________________________________________________ 48 El BIOS y el sistema operativo ________________________________________________ 49 Cargador del sistema ______________________________________________________ 49 Carga desde un CD-ROM ____________________________________________________ 50 Carga por medio de conexión en red ____________________________________________ 51 Inicio de la ejecución del sistema operativo_____________________________________ 52 Protección del hardware____________________________________________________ 54 Funcionamiento del kernel____________________________________________________ 55
Comentarios _________________________________________________________ 55
v
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
2.4
Obras consultadas ____________________________________________________ 57
Capitulo 3.
Simulación de Hardware y Sistemas Operativos _________________ 59
3.1
La simulación en el diseño de sistemas operativos __________________________ 60
3.2
Emulación y Simulación de hardware ____________________________________ 63
3.2.1 Emulación de hardware ____________________________________________________ 63 ¿Cómo se instrumenta un emulador? ____________________________________________ 65 3.2.2 Simulación de hardware____________________________________________________ 65
3.3
Máquinas virtuales ____________________________________________________ 66
3.3.1
3.4
El sistema P _____________________________________________________________ 67
Plataformas de simulación de Sistemas Operativos _________________________ 68
3.4.1 Java Operating System Simulation ___________________________________________ 68 3.4.2 NachOS ________________________________________________________________ 71 La máquina Nachos _________________________________________________________ 72 3.4.3 RCOS __________________________________________________________________ 73
3.5
Simulación de un Sistema Operativo mínimo ______________________________ 75
3.5.1 3.5.2 3.5.3 3.5.4 3.5.5
El hardware: URM ________________________________________________________ 76 El software: SOM_________________________________________________________ 78 Consideraciones para el modelado de dispositivos de E/S__________________________ 81 Resultados ______________________________________________________________ 83 morfo-Hardware__________________________________________________________ 84
3.6
Comentarios _________________________________________________________ 86
3.7
Obras consultadas ____________________________________________________ 87
Capitulo 4. 4.1
Administración de la memoria _______________________________ 89
La memoria__________________________________________________________ 89
4.1.1 Asignación de direcciones __________________________________________________ 90 4.1.2 La unidad de administración de memoria (MMU)________________________________ 91 Memoria asociativa _________________________________________________________ 92 4.1.3 Manejo estático y dinámico de la memoria _____________________________________ 93 4.1.4 Carga de programas en memoria _____________________________________________ 93 Overlays __________________________________________________________________ 94 Relocalización _____________________________________________________________ 95
4.2
Administración de la memoria __________________________________________ 96
4.2.1 4.2.2 4.2.3 4.2.4 4.2.5
4.3
Administración manual ____________________________________________________ 97 Administración automática _________________________________________________ 98 Esquemas de Administración ________________________________________________ 98 Monoprogramación sin intercambio ____________________________________________ 99 Multiprogramación con particiones fijas ________________________________________ 100 Particiones de Longitud Variable______________________________________________ 101 Registro del Uso de la Memoria_______________________________________________ 102 Intercambio de procesos entre memoria y disco __________________________________ 103 Intercambio (Swapping)_____________________________________________________ 104 Memoria virtual ___________________________________________________________ 105 Problemas de la administración de memoria ___________________________________ 107 Caso de estudio: Sistema de administración de memoria de Linux __________________ 108
Asignación de la memoria _____________________________________________ 110
4.3.1 4.3.2 4.3.3
Alojamiento contiguo y no contiguo _________________________________________ 110 Estrategias de asignación __________________________________________________ 111 Fragmentación y compactación _____________________________________________ 111
vi
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Subalojadores_____________________________________________________________ 112 4.3.4 Paginación _____________________________________________________________ 112 Reemplazo de páginas ______________________________________________________ 115 4.3.5 Segmentación ___________________________________________________________ 116 4.3.6 Segmentación con paginación ______________________________________________ 117
4.4
Simulación del servicio de administración de memoria _____________________ 119
4.5
Comentarios ________________________________________________________ 122
4.5
Obras consultadas ___________________________________________________ 123
Capitulo 5. 5.1
Administración de procesos ________________________________ 125
Ejecución de programas y procesos _____________________________________ 125
5.1.1 Modelos de ejecución_____________________________________________________ 125 5.1.2 Procesos _______________________________________________________________ 127 5.1.3 Hilos__________________________________________________________________ 128 5.1.4 Representación de los procesos _____________________________________________ 129 5.1.5 Creación de procesos _____________________________________________________ 130 5.1.6 Estados de un proceso ____________________________________________________ 132 5.1.7 Colas de procesos________________________________________________________ 133 Llamadas de servicios ______________________________________________________ 134 5.1.8 Operaciones de manipulación de procesos_____________________________________ 134 5.1.9 ¿Por qué usar procesos? ___________________________________________________ 135
5.2
Planificación de procesos ______________________________________________ 136
5.2.1 5.2.2 • • •
Tipos de planificación ____________________________________________________ 137 Planificación del CPU ______________________________________________________ 138 Planificación de largo plazo __________________________________________________ 139 Planificación de mediano plazo _______________________________________________ 140 Caso de estudio: Sistema de planificación de procesos de Linux _____________________ 141 Algoritmos de planificación ________________________________________________ 142 Algoritmo de planificación FCFS (First Come - First Served) _______________________ 143 Algoritmo Round-robin _____________________________________________________ 145 Planificación por prioridad___________________________________________________ 146 Algoritmo del trabajo más corto primero (Shortest Job First) ________________________ 147 Múltiples colas de prioridad (MPQ)____________________________________________ 148 Planificación de dos niveles __________________________________________________ 150 Planificación por herencia (Inheritance scheduling) _______________________________ 151 Planificación evolutiva______________________________________________________ 151
5.3
Simulación del servicio de administración de procesos _____________________ 152
5.4
Procesos concurrentes ________________________________________________ 155
5.4.1 5.4.2 5.4.3 5.4.4
Sincronización de procesos ________________________________________________ 159 Semáforos _______________________________________________________________ 161 Candados (Locks) _________________________________________________________ 162 Monitores y variables de condición ____________________________________________ 163 Interbloqueos _____________________________________________________________ 167 Prevención y tratamiento ____________________________________________________ 168 Comunicación entre procesos ______________________________________________ 170 El esquema productor-consumidor_____________________________________________ 170 Mensajes ________________________________________________________________ 171 Tuberías (pipes) ___________________________________________________________ 173 Caso de estudio: Comunicación entre procesos en Linux ___________________________ 174 Comunicación entre procesos en Sistemas Distribuidos __________________________ 175 Modelo cliente-servidor ___________________________________________________ 177 Direccionamiento __________________________________________________________ 177
vii
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
5.4.5
Llamadas a Procedimientos Remotos (RPC) ___________________________________ 178
5.5
Comentarios ________________________________________________________ 180
5.6
Obras consultadas ___________________________________________________ 181
Capitulo 6. 6.1
Administración de dispositivos y periféricos ______________________________ 184
6.1.1 6.1.2 6.1.3 6.1.4 6.1.5
6.2
Dispositivos de Entrada - Salida ____________________________________________ 185 Controladores de Dispositivos ______________________________________________ 185 Manejadores de dispositivos (device drivers) __________________________________ 187 Acceso Directo a Memoria_________________________________________________ 190 Caso de estudio: Manejo de dispositivos en UNIX ______________________________ 191
Administración de archivos____________________________________________ 193
6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6
6.3
Administración de dispositivos, almacenamiento y comunicaciones. 183
Medios de almacenamiento ________________________________________________ 194 Manejador de discos______________________________________________________ 195 Archivos_______________________________________________________________ 196 El sistema de archivos ____________________________________________________ 197 Representación de archivos y estructura del sistema de archivos _____________________ 199 Operaciones soportadas por el sistema de archivos ________________________________ 202 Asignación del espacio de almacenamiento ______________________________________ 204 Métodos de acceso en los sistemas de archivos ___________________________________ 205 Algoritmos de planificación de lectura y escritura_________________________________ 205 Tolerancia a fallas _________________________________________________________ 206 El concepto de sistema virtual de archivos ______________________________________ 206 Nuevos enfoques en el manejo de archivos ____________________________________ 207 Caso de estudio: Sistema de archivos y control de dispositivos en Linux _____________ 208
Comunicaciones en red _______________________________________________ 210
6.3.1 6.3.2 6.3.3
Redes de computadoras ___________________________________________________ 211 Estructura y configuraciones de redes __________________________________________ 212 Interconexión de computadoras _______________________________________________ 214 Organización del software de red____________________________________________ 215 Protocolos _______________________________________________________________ 216 Caso de estudio: TCP/IP ____________________________________________________ 218 Sockets __________________________________________________________________ 219 Caso de estudio: Windows 9X en red ________________________________________ 221 Interfaces de dispositivos de red ______________________________________________ 221 Arquitectura para protocolos _________________________________________________ 222 Arquitectura para clientes de redes ____________________________________________ 222 Mecanismos de comunicación entre procesos (IPC) _______________________________ 223 Instalación y configuración de las tarjetas de red__________________________________ 223
6.4
Comentarios ________________________________________________________ 223
6.5
Obras consultadas ___________________________________________________ 225
Capitulo 7. 7.1
El software y sus características ________________________________________ 228
7.1.1 7.1.2
7.2
Diseño de sistemas operativos_______________________________ 227 ¿Por qué es necesario un sistema operativo? ___________________________________ 229 ¿Para qué escribir un sistema operativo? ______________________________________ 230
Desarrollo de sistemas de software ______________________________________ 230
7.2.1 Proceso de desarrollo de software ___________________________________________ 230 7.2.2 Ingeniería de software ____________________________________________________ 231 Concepto de ciclo de vida ___________________________________________________ 232 Fases genéricas de la ingeniería de software _____________________________________ 233
viii
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
7.3
El proceso de diseño _______________________________________________________ 235 Etapas del diseño de sistemas ________________________________________________ 235
Arquitectura de software______________________________________________ 237
7.3.1 7.3.2 7.3.3 • 7.3.4 7.3.5
7.4
Importancia de la arquitectura de software ____________________________________ 238 El diseño de la arquitectura ________________________________________________ 239 Elementos de una arquitectura de software ____________________________________ 241 Vistas (estructuras)_________________________________________________________ 242 El modelo de arquitectura 4+1 vistas ___________________________________________ 244 Vista de la arquitectura por capas _____________________________________________ 245 Estilos arquitectónicos ______________________________________________________ 246 Patrones arquitectónicos___________________________________________________ 248 El patrón Layers ___________________________________________________________ 249 El patrón Microkernel ______________________________________________________ 249 El patrón Broker___________________________________________________________ 251 Desarrollo basado en la arquitectura _________________________________________ 251
Diseño sistemas operativos: enfoque orientado a la arquitectura _____________ 252
7.4.1 7.4.2 7.4.3 7.4.4
7.5
Preguntas importantes: en busca de requerimientos______________________________ 252 Metas del diseño_________________________________________________________ 254 Estructura del sistema operativo ____________________________________________ 255 Mecanismos y políticas ___________________________________________________ 257
Diseño de sistemas operativos: el enfoque de los desarrolladores _____________ 257
7.5.1 El enfoque de diseño más simple ____________________________________________ 258 7.5.2 Consideraciones de diseño de sistemas operativos ______________________________ 260 7.5.3 Diseño de kernels ________________________________________________________ 262 Clasificación de los kernels __________________________________________________ 263 Criterios de planificación ____________________________________________________ 265 7.5.4 Consideraciones sobre la codificación del sistema ______________________________ 266 7.5.5 Uso de estándares y portabilidad ____________________________________________ 266
7.6
Diseño de sistemas operativos: la interacción con el usuario _________________ 267
7.6.1 Interacción humano-computadora_______________________________________________ 268 7.6.2 Interfaz basada en texto_______________________________________________________ 269 7.6.3 Interfaz gráfica de usuario ____________________________________________________ 270 7.6.4 Interfaces alternativas ________________________________________________________ 273 7.6.5 Diseño de interfaces de usuario_________________________________________________ 274
7.7
Diseño de sistemas operativos: la administración de sistemas ________________ 276
7.8
Comentarios ________________________________________________________ 277
7.9
Obras consultadas ___________________________________________________ 280
Capitulo 8.
Arquitecturas de Sistemas Operativos ________________________ 285
8.1
Representación de la arquitectura ______________________________________ 286
8.2
Arquitecturas de Sistemas Operativos ___________________________________ 287
8.3
Arquitectura de kernel monolítico ______________________________________ 288
8.4
Arquitectura de capas y anillos_________________________________________ 290
8.5
Arquitectura de máquina virtual _______________________________________ 293
8.6
Arquitectura de microkernel y multihilado _______________________________ 295
8.7
Arquitecturas Orientadas a Objetos_____________________________________ 298
8.7.1
Sistemas operativos basados en componentes __________________________________ 301
ix
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
8.8
Arquitectura cliente-servidor __________________________________________ 302
8.9
Implantación del modelo C/S para sistemas operativos distribuidos ___________________ 304
Arquitecturas en red y distribuidas _____________________________________ 305
8.9.1 8.9.2
Criterios de diseño de sistemas distribuidos____________________________________ 308 Mach _________________________________________________________________ 309
8.10
Arquitecturas adaptables____________________________________________ 312
8.11
Arquitectura de Exokernel __________________________________________ 314
8.12
Arquitecturas orientadas a agentes____________________________________ 317
8.13
Comentarios ______________________________________________________ 319
8.14
Obras consultadas__________________________________________________ 321
Resultados, conclusiones y perspectivas ___________________________________ 325 a.
Resultados __________________________________________________________ 325
b.
Aportaciones ________________________________________________________ 326
c.
Conclusiones __________________________________________________________ 328 c.1 c.2 c.3
¿Por qué seguir desarrollando nuevos sistemas operativos? _________________________ 329 Los sistemas operativos y el desarrollo de marcos conceptuales (frameworks)___________ 330 Tendencias en el desarrollo de sistemas operativos ________________________________ 330
d.
Perspectivas_________________________________________________________ 330
e.
Referencias ___________________________________________________________ 332
Bibliografía__________________________________________________________ 333 Glosario_____________________________________________________________ 335 Apéndices ___________________________________________________________ 341 Apéndice A. Programación de Cargadores (sectores de arranque) _________________ 341 Apéndice B. Simulación de un sistema mínimo de hardware y su sistema operativo___ 346 Apéndice C. Simulador del servicio de administración de la memoria ______________ 357 Apéndice D. Simulador del servicio de administración de procesos_________________ 372 Apendice E. Caso de estudio: Implementación de un microkernel _________________ 384
x
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Lista de figuras y tablas Organización del trabajo. ................................................................................................................................ 3 Figura 1.1 Vista de los programas de sistema y de aplicación........................................................................ 8 Figura 1.2 El SO administra los recursos de hardware y software de la computadora, y provee un medio estable y consistente donde las aplicaciones puedan usar el hardware. .................................................. 8 Figura 1.3 Soporte de software necesario para aprovechar los recursos del hardware. ................................ 11 Tabla 1. Recursos de la arquitectura, administración del sistema operativo y abstracciones del usuario. .... 12 Figura 1.4 Esquema de los diferentes tipos de memoria en un sistema de cómputo..................................... 13 Figura 1.5 Niveles de interacción de un shell ............................................................................................... 17 Figura 1.6 Ejemplos de interfaz gráfica de usuario: (a) el sistema NeXT; (b) Mac OS X............................ 18 Figura 1.7 Cronología del desarrollo de las computadoras y los sistemas operativos. ................................ 19 Figura 1.8 Esquema de operación de las primeras computadoras................................................................. 20 Figura 1.9 Esquema básico de la memoria de una computadora con procesamiento por lotes (monitor residente)............................................................................................................................................... 22 Figura 1.10 Esquemas básicos de procesamiento. Nótese como el tiempo desperdiciado ha ido disminuyendo........................................................................................................................................ 23 Figura 1.11 Esquema de sistema de multiprogramación (o multitarea), donde varias tareas son ejecutadas simultáneamente. .................................................................................................................................. 24 Figura 1.12 Esquema de ejecución de dos procesos con y sin multiprogramación....................................... 25 Figura 1.13 Esquema de un sistema de tiempo compartido. ......................................................................... 26 Figura 1.14 Esquema de un sistema de control, en donde deben ser aceptados y procesados gran cantidad de sucesos. ................................................................................................................................................. 27 Figura 1.15 Configuraciones de multiprocesamiento asimétrico(a) y simétrico(b). ..................................... 28 Figura 1.16 Esquema de un sistema operativo distribuido........................................................................... 30 Figura 1.17 Las primeras PCs: (a) MITS Altair (1974), (b) Radio Shack TRS-80 (1977), (c) Apple I (1976), (d) Apple Lisa (1983)............................................................................................................................ 31 Figura 2.1 Modelo de Von Neumann............................................................................................................ 36 Figura 2.2 El procesador y demás dispositivos se conectan por medio de enlaces físicos conocidos como buses. .................................................................................................................................................... 36 Figura 2.3 Modelo de un microprocesador simple....................................................................................... 37 Figura 2.4 El CPU accede diferentes tipos de memoria................................................................................ 39 Tabla 2. Comparación de un programa en lenguaje de alto nivel, ensamblador y código máquina............. 40 Figura 2.5 Esquema de la ejecución de un programa.................................................................................... 41 Figura 2.6 Los componentes de hardware pueden comunicarse con el CPU mediante controladores.......... 42 Figura 2.7 Software relacionado al control del hardware. ............................................................................ 46 Figura 2.8 Secuencia del inicio de ejecución del sistema operativo. ............................................................ 52 Figura 3.1a Esquema de la arquitectura del FLUX OSKit........................................................................... 61 Figura 3.1b Esquema de la arquitectura del Palm OS................................................................................... 62 Figura. 3.2 Emulación interpretativa............................................................................................................. 64 Figura 3.3 Emulación de compilación dinámica........................................................................................... 64 Figura 3.4 Clases y métodos del JOSS.......................................................................................................... 69 Figura 3.5 Forma en que los diferentes componentes de Nachos están ligados durante la ejecución........... 72 Figura 3.6 Arquitectura del RCOS................................................................................................................ 75 Figura 3.7 Modelo del simulador con un cargador de programas................................................................. 78 Figura 3.8 Modelo del simulador con un SOM para una URM modificada, basado en el concepto de un monitor residente. ................................................................................................................................. 80 Figura 3.9 Patrón de diseño Modelo-Vista-Controlador............................................................................... 84 Figura 3.10 Esquema del modelo morfo-Hardware ..................................................................................... 85 Figura 3.11 Modelo de clases de morfo-Hardware v.0.1 .............................................................................. 85 Figura 3.12 Modelo de clases de morfo-Hardware v.0.2 .............................................................................. 86 Figura 4.1 Vista simplificada del espacio de direcciones en la memoria...................................................... 90 Figura 4.2 La MMU se sitúa justo entre el CPU y la memoria.................................................................... 92 Figura 4.3 Cuando el CPU quiere acceder a la memoria, le manda la dirección que quiere a la MMU quien
xi
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
la traduce en otra dirección que le pasa a la unidad de memoria. ......................................................... 92 Figura 4.4 Carga de un programa en memoria virtual .................................................................................. 94 Figura 4.5 Esquema de un sistema que implementa recubrimientos............................................................ 95 Figura 4.6 Esquemas de organización de memoria con manejo de dos particiones...................................... 99 Figura 4.7 Administración con particiones fijas ......................................................................................... 100 Figura 4.8 Administración con particiones variables.................................................................................. 101 Figura 4.9 Administración con mapa de bits .............................................................................................. 102 Figura 4.10 Administración con listas ligadas ............................................................................................ 102 Figura 4.11 Intercambio.............................................................................................................................. 105 Figura 4.12 Administración con memoria virtual ....................................................................................... 106 Figura 4.13 Dependencias y flujos de control y datos en el administrador de memoria............................. 109 Figura 4.14 Estructura del administrador de memoria de Linux................................................................. 110 Figura 4.15 En la paginación el tamaño de la página debe ser una potencia de 2....................................... 113 Figura 4.16 Traducción de direcciones en un sistema de paginación ......................................................... 113 Figura 4.17 Direccionamiento en MS-DOS usando segmentación (8086-16 bits). Capacidad de direccionamiento 220=1'048,576=1MB............................................................................................... 114 Figura 4.18 Traducción de direcciones en la segmentación........................................................................ 116 Figura 4.19 Traducción de direcciones en un sistema con segmentación ................................................... 117 Figura 4.20 Método de segmentación y paginación.................................................................................... 118 Figura 4.21 Traducción de direcciones en un sistema con segmentación y paginación.............................. 118 Figura 4.22 Los esquemas de particiones fijas, variables y paginación manejan programas como bloques únicos. ................................................................................................................................................. 119 Figura 4.23 La segmentación y la segmentación con paginación son más aptos para manejar programas y módulos dinámicos. ............................................................................................................................ 120 Figura 4.24 Modelo de clases del simulador de administración de memoria.............................................. 121 Figura 4.25 Ejecución del simulador. ......................................................................................................... 122 Figura 5.1 Modelos de ejecuciónen sistemas de cómputo .......................................................................... 126 Figura 5.1a Esquema de un sistema monotarea .......................................................................................... 126 Figura 5.1b Esquema de un sistema multitarea........................................................................................... 127 Figura 5.2 Esquema del intercambio de procesos con el CPU en un sistema multitarea. .......................... 129 Figura 5.3 Esquemas de estados y transiciones de un proceso .................................................................. 132 Figura 5.4 Niveles de planificación ............................................................................................................ 137 Figura 5.5 Esquema de las dependencias y flujos de control y datos en el planificador de procesos ......... 141 Figura 5.6 Estructura del planificador de procesos de Linux...................................................................... 142 Figura 5.7 Para un quantum=1 se presenta la secuencia de ejecución de procesos .................................... 146 Figura 5.8 Ejemplo de los algoritmos SJF y SRTF..................................................................................... 148 Figura 5.9 Colas múltiples de prioridad...................................................................................................... 149 Figura 5.10 Planificación de 2 niveles ........................................................................................................ 151 Figura 5.11 Esquema del funcionamiento de la administración de procesos.............................................. 152 Figura 5.11a Modelo de clases del simulador de administración de procesos. ........................................... 154 Figura 5.12 Ejecución del simulador. ......................................................................................................... 155 Figura 5.12 Los procesos P1 y P2, así como P2 y P3 son concurrentes, en cambio P3 y P1 no lo son ...... 155 Figura 5.13 Interbloqueo............................................................................................................................. 167 Figura 5.14 Esquema donde los procesos que requieren acceder a un recurso compartido ........................ 170 Figura 5.15 Entrega de mensajes con múltiples colas................................................................................. 173 Figura 5.16 Estructura del subsistema IPC de Linux .................................................................................. 175 Figura 5.17 Esquema de procesos que se ejecutan en una computadora y en un sistema distribuido......... 176 Figura 5.18 Modelo cliente-servidor en un escenario distribuido.............................................................. 177 Figura 5.19 Esquema de invocación local y remota de procedimientos ..................................................... 179 Figura 6.1 Capas del sistema de entrada-salida........................................................................................... 184 Figura 6.2 Arquitecturas de entrada-salida y disposiciones de los dispositivos conectados al bus............. 186 Figura 6.3 Esquemas de E/S y su acceso mediante instrucciones en ensamblador..................................... 186 Figura 6.4 Capas del software de entrada-salida......................................................................................... 188 Figura 6.5 Flujo de operaciones en un manejador de dispositivo. .............................................................. 189 Figura 6.6 Flujos de E/S por el DMA ......................................................................................................... 190 Figura 6.7 Estructura de un manejador de discos........................................................................................ 195
xii
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 6.8 Objetos del sistema operativo y sus operaciones relacionadas con archivos. ............................ 197 Figura 6.9 Esquema del sistema de almacenamiento secundario............................................................... 197 Figura 6.10 Esquema del sistema de almacenamiento terciario.................................................................. 199 Figura 6.11 Formato de un archivo ejecutable............................................................................................ 200 Figura 6.12 Organización de archivos con directorios................................................................................ 200 Figura 6.13 Representaciones de archivos en UNIX, MS-DOS y Windows NT ........................................ 201 Figura 6.14 Ejemplos de estructuras en sistemas operativos como UNIX, MS-DOS y Windows. ............ 202 Figura 6.15 Esquema de la aplicación de operaciones de acceso y manipulación en un archivo .............. 204 Figura 6.16 Sistema virtual de archivos de Linux....................................................................................... 209 Figura 6.17 Estructura del administrador de archivos de Linux ................................................................. 210 Figura 6.18a Algunas ejemplos de las topologías que una red puede adoptar. .......................................... 213 Figura 6.18b Modelo OSI y los equivalentes en el modelo de protocolos TCP/IP..................................... 214 Figura 6.19 Arquitectura de Netware 2.2.................................................................................................... 214 Figura 6.20 Estructura del subsistema de red de Linux .............................................................................. 216 Figura 6.21 Conjunto de protocolos TCP/IP y su relación con el modelo OSI........................................... 218 Tabla 3. Relación de dispositivos de cómputo y sus sistemas operativos................................................... 229 Figura 7.1 Esquema del proceso unificado de desarrollo (RUP) ................................................................ 231 Figura 7.2 Ciclo de vida en cascada............................................................................................................ 232 Figura 7.3 Visiones de un sistema de software ........................................................................................... 237 Figura 7.4 La definición de la arquitectura está entre el análisis del sistema y su diseño........................... 240 Figura 7.5 Descomposición de elementos de diseño................................................................................... 241 Tabla 4. Estructuras de una arquitectura de software.................................................................................. 243 Figura 7.6 Vistas posibles de un elemento de diseño (lógica, concurrente o de instalación)...................... 244 Figura 7.7 Algunos tipos de estilos arquitectónicos.................................................................................... 247 Figura 7.8 Diagrama de clase del patrón microkernel ................................................................................ 250 Figura 7.9 Vista de capas de la arquitectura de un sistema operativo ......................................................... 256 Figura 7.10 Dispositivos de interfaz ........................................................................................................... 268 Figura 7.11 Interfaz de usuario del MS-DOS ............................................................................................. 269 Figura 7.12 Patrón de diseño Interpreter..................................................................................................... 270 Figura 7.13 Interfaz de la aplicación shell de MS-DOS.............................................................................. 270 Figura 7.14 Interfaz gráfica GNOME en Linux[7.87] ................................................................................ 271 Figura 7.15 Patrón MVC como base de una GUI ...................................................................................... 272 Figura 7.16 Elementos de la interfaz de usuario de Swing en Java ............................................................ 272 Figura 7.17 Arquitectura de la GUI del WCEfA ........................................................................................ 273 Figura 7.18 Arquitectura del Mac OS X y su interfaz de usuario Aqua ..................................................... 275 Figura 7.19 Consideraciones para el desarrollo de software....................................................................... 278 Figura 7.20 Diseño de sistemas operativos ................................................................................................. 279 Figura 8.1 Arquitectura de Windows NT representada en un esquema de módulos................................... 286 Figura 8.2 Especificación formal de alto nivel de la arquitectura de Windows NT usando UML (paquetes y relaciones)........................................................................................................................................... 287 Figura 8.3 Arquitectura de kernel monolítico ............................................................................................. 289 Figura 8.4 Arquitectura conceptual de Linux ............................................................................................. 290 Figura 8.5 Esquema de la organización en capas de un sistema operativo ................................................. 291 Figura 8.6 Organización del sistema operativo en anillos........................................................................... 291 Figura 8.7 La característica central de la arquitectura de Mac OS X es la división en capas del software del sistema ................................................................................................................................................ 292 Figura 8.8 Esquema de una arquitectura de máquina virtual ...................................................................... 293 Figura 8.9 Niveles de máquinas virtuales ................................................................................................... 294 Figura 8.10 Convivencia entre el sistema operativo nativo y ..................................................................... 295 el creado por la máquina virtual.................................................................................................................. 295 Figura 8.11 Esquema de la arquitectura de un microkernel. Pueden identificarse los modos de operación (modo kernel y modo usuario), así como los procesos del sistema y los procesos de usuario............ 296 Figura 8.12 Esquema de la arquitectura del Palm OS. El núcleo de este sistema es el microkernel AMX (Kadak) que implementa multiprocesamiento .................................................................................... 297 Figura 8.13 La arquitectura de paso de mensajes del QNX RTOS forma un bus de software que permite conectar o desconectar los módulos del SO que se necesiten, sin reiniciar el sistema........................ 298
xiii
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 8.14 En el corazón del JavaOS se encuentra la máquina virtual de Java (JVM). Los servicios del sistema, manejadores, applets y aplicaciones se ejecutan en la VM y un microkernel provee los servicios básicos de la plataforma....................................................................................................... 300 Figura 8.15 La red de módulos de software que forma una aplicación puede visualizarse en distintos niveles ............................................................................................................................................................ 301 Figura 8.16 Arquitectura del sistema operativo Go .................................................................................... 302 Figura 8.17 Arquitectura del sistema X Window, para el intercambio de mensajes de interfaz gráfica de usuario................................................................................................................................................. 304 Figura 8.18 Esquema de operación de un sistema operativo de red............................................................ 305 Figura 8.18a Arquitectura de Windows NT en referencia al modelo OSI .................................................. 306 Figura 8.19 Esquema de operación de un sistema operativo distribuido .................................................... 307 Figura 8.20 Esquema del middleware y entornos distribuidos .................................................................. 308 Figura 8.21 Esquema de la arquitectura de Mach ....................................................................................... 310 Figura 8.22 Arquitectura del microkernel Darwin del Mac OS X que integra el kernel Mach 3.0 y servicios del BSD UNIX.................................................................................................................................... 312 Figura 8.23 Estructura de un sistema exokernel. Las aplicaciones usan sus propias librerías de Sistema Operativo (Library Operating System (LibOS)) que a su vez usan el exokernel para cargar y descargar recursos de hardware........................................................................................................................... 314 Figura 8.24 Esquema de un servidor Web montado en un SO convencional ............................................. 315 Figura 8.25 El solicitar una página HTML desencadena una serie de procesos que el SO tiene que hacer para darle el soporte a la aplicación, lo cual no necesariamente puede ser óptimo. En el segundo diagrama pueden apreciarse las dependencias del sistema de administración de memoria de Linux. 315 Figura 8.26 El exokernel provee la protección del hardware y las librerías de aplicación, pero el control lo tiene la aplicación, lo que elimina procesos que el servidor Web no necesita .................................... 316 Figura 8.27 Un sistema de exokernel simplificado con dos aplicaciones, cada una ligada con su propia libOS y compartiendo páginas por medio de un registro .................................................................... 316 Figura 8.28 Arquitecturas de sistemas operativos y sus características ...................................................... 320 Figura 9.1 Simulador de administración de memoria con particiones fijas (Oscar Ceceña)....................... 328 Figura 9.2 Simulador de administración de procesos (Christian Islas) ....................................................... 328 Figura 9.3 Simulador de administración de procesos (Josué Huizar) ......................................................... 328
xiv
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Introducción Algunos ven las cosas como son y preguntan:¿Por qué? Yo sueño en lo que nunca existió y pregunto:¿Por qué no? Robert F. Kennedy
Las computadoras desde un principio han sido máquinas complejas (y un gran logro técnico iniciado por Babbage en el siglo XIX y desarrollado en el siglo XX), compuestas de diversas partes físicas (el hardware), las cuales realizan acciones cuando se les dan instrucciones (el llamado software). Los conjuntos ordenados de instrucciones son llamados programas, y son los que le dicen a la computadora como debe hacer diferentes cosas con objetivos específicos y particulares. Es un tipo especial de programas llamados sistemas operativos, los que permiten a la computadora brindar una plataforma para realizar una gran variedad de tareas complejas. La idea de realizar notas y hasta un libro de sistemas operativos nació en 1997 cuando daba un curso relacionado al tema en la Fundación Arturo Rosenblueth (el titulo de ese proyecto era "Sistemas operativos: Teoría y práctica"), sin embargo por motivos de trabajo la idea quedó en el baúl. Fue hasta 1999 (tal vez un poco antes) con el advenimiento de un movimiento importante en el país respaldando a Linux (por parte de entusiastas estudiantes de diversas universidades) que decidí retomar el tema de los sistemas operativos. Una motivación adicional apareció durante el tiempo que pasé colaborando en el Instituto de Química de la UNAM; hubo una pregunta que me intrigó cuando charlábamos sobre las analogías de los mecanismos celulares con las computadoras: "Si el núcleo celular era el hardware, ¿cuál era el software (y el sistema operativo) de la célula?" Aunque se comentó que el ADN podía considerarse como el software de control, me pareció que debía estudiar a fondo la teoría de los sistemas operativos para un análisis futuro del tema. Después de investigar caí en cuenta de algunos hechos importantes: •
•
•
El desarrollo de este tipo de sistemas está en manos de una élite de desarrolladores (ya sean los apoyados por universidades o compañías, o los que lo hacen como pasatiempo; esfuerzos sin duda, loables). Aunque hacer sistemas operativos no es una de las ofertas de trabajo que salgan a menudo en los periódicos, el conocimiento de este tema es obligado para cualquier profesional del área de cómputo. La bibliografía relacionada es escasa e importada (aunque hay traducciones) y en general más teórica que práctica. Esto último no ha tenido un balance (hay obras con mucha teoría y otras con la mitad de la publicación con listados de código fuente) y ante todo, no ha reportado la experiencia de las personas o equipos de trabajo, exponiendo cómo es que llegaron a sus soluciones (es decir, a sistemas que actualmente se usan en ambientes de producción). Un experto en sistemas operativos debe tener una perspectiva amplia sobre los diferentes sistemas operativos existentes. Alguien que trata o logra recompilar el kernel de Linux, o que
1
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
•
•
•
obtiene una certificación en el uso o administración de algún otro sistema, no necesariamente sabe cómo está funcionando dicho sistema, cómo está construido o cómo puede modificarse para mejorar su rendimiento. Deben tomarse en cuenta los avances en otras áreas de las ciencias de la computación, para aplicarlos a los problemas clásicos de los sistemas operativos, o para proveerlos de nuevas funcionalidades o incluso para proponer nuevos enfoques en su desarrollo (p.ej. técnicas de IA, agentes, etc.). Al no tener una referencia práctica sobre el desarrollo de este tipo de sistemas, se limita el avance e innovación potencial que pudiera lograrse, por falta de conocimiento. No solo hay pocos libros, sino que hay poco interés. Es necesario crear y difundir una cultura sobre los sistemas operativos para reducir la dependencia tecnológica del extranjero (cosa difícil a estas alturas, pero no imposible), y mejorar los criterios de consumo de los usuarios finales (¿por qué debo cambiar de sistema si el que uso funciona? ¿qué mejoras tiene la nueva versión? ¿qué otras opciones existen?).
Por todo lo anterior, decidí llevar a cabo una investigación que lograra, ante todo, aclarar muchas dudas que creo compartir con muchas personas (sin ir mas lejos, preguntas sobre qué son o cómo funcionan los sistemas operativos) con respuestas convincentes que vayan a la médula de la principal interrogante de todo estudiante de ciencias de la computación: ¿cómo se
diseña y construye un sistema operativo? Para ello, me he apoyado en toda la bibliografía a mi alcance y sobre todo en la información disponible en Internet (la cual de unos años para acá se ha incrementado, afortunadamente), así como en mi experiencia como desarrollador de software (que es donde hay que lidiar con los sistemas operativos, y donde surgen los retos). El objetivo es organizar y analizar la información existente sobre los sistemas operativos, en aspectos tales como: • • •
•
la conceptualización general de este tipo de sistemas, la integración de algoritmos y subsistemas que forman parte de ellos, la concepción y la implementación en código de todos sus elementos conceptuales, pues como desarrollador de sistemas sé apreciar la importancia de hacer las cosas para entenderlas, el aprendizaje de técnicas de un área de conocimiento, sirve para aplicarlas en la solución de problemas en otros contextos.
No he querido tomar un solo sistema como caso de estudio, pues esto sería limitado, dada la variedad que existe (además tratar de adivinar por qué se codificó de cierta manera un programa, o conjeturar sobre las decisiones de diseño del sistema puede ser poco objetivo). Por el contrario, he tratado de integrar las diversas visiones en torno a los sistemas operativos para ejemplificar (en lo posible), las ideas y técnicas más representativas aplicadas a estos sistemas (a nivel de sus componentes y su estructura general). Con base en lo anterior, la propuesta de elementos de los sistemas operativos implementación de estos sistemas, para concepción, su diseño y su construcción.
este trabajo es identificar los principales y analizar las técnicas de diseño e establecer lineamientos precisos para su Aunque hay varias obras que hablan de cómo
2
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
hacer un sistema operativo, ninguna de las exposiciones establece una metodología clara, por lo que es difícil abordar un proyecto de este tipo. La comprensión es básica si se desea analizar o construir uno de estos sistemas (hay muchos detalles entre líneas que pueden ser omitidos y que son importantes en la arquitectura del sistema); no sólo se trata de que cada quien haga su sistema operativo (pues esto no tendría mucho sentido), sino de tener los elementos necesarios para que con el advenimiento de nuevas tecnologías, se pueda colaborar en su desarrollo, o por lo menos entender cuál es el sentido y capacidades de las nuevas soluciones. Los objetivos concretos de este trabajo son: 1. Exponer los principales conceptos de la teoría de sistemas operativos con un enfoque práctico. 2. Analizar diversas arquitecturas de sistemas operativos y sus subsistemas, con el fin de establecer criterios para el diseño de nuevos sistemas operativos, así como para evaluar los existentes. 3. Proponer algunos modelos de simulación que integren a los elementos relacionados con el funcionamiento de un sistema operativo.
Organización del trabajo. Este trabajo está organizado en tres grandes partes: I. Conceptos fundamentales de los sistemas operativos y su funcionamiento general. Los primeros dos capítulos exponen los principales conceptos relacionados a los sistemas operativos, su evolución, sus principales componentes y su funcionamiento integral desde una perspectiva general. Esto permitirá comprender que elementos deberán ser estudiados a detalle, y a limitar el alcance del simulador propuesto. El capitulo 1 presenta los conceptos fundamentales sobre sistemas operativos:
3
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
- definición de conceptos de sistemas operativos - evolución histórica de los SOs y su clasificación - identificación de las principales partes que en general los conforman El capítulo 2 presenta el funcionamiento general de los sistemas operativos explorando a los elementos de hardware y software que trabajan en la computadora para que contemos con un sistema de este tipo. El capitulo 3 expone la justificación del uso de la simulación para el estudio de los SO, y se analizan algunas de las plataformas de simulación más usadas, con el fin de establecer los criterios y elementos de diseño para la simulación de los conceptos generales de funcionamiento expuestos en el capitulo 2. Para ello primero se presentan las consideraciones para la simulación de hardware y sistemas operativos, y un primer prototipo del simulador, el cual fue hecho sin tener un fundamento arquitectónico. II. Sistemas y servicios de administración de recursos. En la gran mayoría de los libros de sistemas operativos, se dedican 7 ó 10 capítulos al estudio de los sistemas de administración de memoria, procesos, almacenamiento, periféricos, etc. Para no volver a repetir lo que varios libros exponen, decidí que era mejor un enfoque donde se expongan estos sistemas como la definición de requerimientos que se necesitarán para el simulador. De esta manera, contaremos con un enfoque más práctico (pues inclusive se incluyen algunas pruebas de concepto) Los capítulos 4, 5 y 6 abordan el análisis de los principales componentes de los sistemas operativos, a nivel de sistemas de administración. En el capitulo 4 se analiza la administración de memoria. En el capitulo 5 se analiza la administración de procesos. En el capítulo 6 la administración de dispositivos del sistema. Todo esto brinda una perspectiva de los servicios que por lo general los sistemas operativos ofrecen (y que el usuario espera). III. Diseño de sistemas operativos. Una vez que contamos con el conocimiento de lo que es y cómo funciona un sistema operativo, y partes que lo integran, llega el momento de aplicarlo. En principio creí que el principal producto sería un simulador, pero de hecho hay un vacío más importante que llenar: la metodología de diseño de los sistemas operativos. Por ello, se presentan algunos casos de estudio de varios sistemas operativos para identificar los principales componentes de las diversas arquitecturas que existen, con el fin de establecer criterios metodológicos de diseño. El capitulo 7 plantea las consideraciones de diseño de sistemas operativos, y expone todo un marco de referencia para su diseño. El capitulo 8 revisa las principales arquitecturas de sistemas operativos y se presentan algunos casos de estudio, que relacionan a sus partes con la disposición que pueden adoptar en un sistema especifico. Esto será de utilidad como una paleta de elementos de diseño que el lector podrá aplicar al proceso de diseño.
4
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
La última sección contiene los resultados del trabajo, la experiencia del desarrollo, las conclusiones obtenidas, así como las perspectivas a futuro del proyecto. Adicionalmente los apéndices contienen varios ejemplos y referencias prácticas interesantes, relativas a diversos tópicos como: a. Simulación de sistemas operativos (modelado del hardware y software que se relaciona al SO). b. Implementación de servicios del sistema operativo (administración de la memoria y procesos). c. Casos de estudio de implementaciones (un microkernel).
Temas relacionados •
Sistemas operativos.
• • •
Sistemas distribuidos. Arquitectura de computadoras. Compiladores y lenguajes de programación.
• • •
Simulación y modelado. Simulación y emulación de hardware. Ingeniería de software.
•
Arquitectura de software.
5
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
6
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Capitulo 1. Fundamentos de los Sistemas Operativos Todo aquel que desee saber qué ocurrirá debe examinar qué ha ocurrido: todas las cosas de este mundo, en cualquier época, tienen su réplica en la antigüedad. Maquiavelo.
Para entrar en materia, este primer capítulo está dedicado a dar respuesta a las preguntas más comunes relacionadas a los sistemas operativos, tales como: • •
¿Qué son los sistemas operativos? ¿Cuáles son sus principales características?
• • •
¿Cuándo aparecen y para qué? ¿Cuál ha sido su desarrollo histórico? ¿Cuáles son los principales conceptos que intervienen en su estructura?
Se han tratado de incluir todos los aspectos que puedan requerirse para entender estas cuestiones, y para tener las bases para comprender la disertación de los siguientes capítulos. Además, puesto que uno de los principales objetivos de este trabajo es el diseño de este tipo de sistemas, es esencial que se comprenda cuales son sus antecedentes, los elementos conceptuales a manejar y la interacción entre ellos, para así pasar a cuestiones más específicas.
1.1
¿Qué es un sistema operativo?
Aunque en las últimas décadas se han hecho propuestas en cuanto a nuevos tipos de computadoras, el hecho es que sin el software (o programas, que son conjuntos de instrucciones que una máquina ejecuta) una computadora es solo un ingenio electrónico incapaz de realizar tareas útiles. Con el software, una computadora puede almacenar, procesar y recuperar información. El software para computadoras puede clasificarse en general como: • •
Programas de sistema, que controlan la operación de la computadora en sí. Programas de aplicación, los cuales definen la forma en que los recursos de la computadora se emplean para resolver los problemas de computación de los usuarios (compiladores, sistemas de bases de datos, juegos de video y programas para negocios).
7
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 1.1 Vista de los programas de sistema y de aplicación. El elemento fundamental de todos los programas de sistema es el Sistema Operativo (SO), que controla todos los recursos de la computadora y proporciona la base sobre la cual pueden escribirse y ejecutarse los programas de aplicación.
Figura 1.2 El SO administra los recursos de hardware y software de la computadora, y provee un medio estable y consistente donde las aplicaciones puedan usar el hardware. Puesto que hay una gran variedad de puntos de vista respecto a lo que es un sistema operativo, es prudente presentar algunas de las definiciones más representativas para empezar a comprender la amplitud de funciones de este tipo de sistemas.
1.1.1 Definiciones A continuación se presenta un conjunto de definiciones que contienen diferentes perspectivas de lo que es (o debería ser) un sistema operativo (SO).
8
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
I. Un SO es el programa que se ejecuta en todo instante en la computadora. II. Un SO es un programa que actúa como intermediario entre el usuario y el hardware de la computadora. Su propósito es proveer un ambiente en el cual el usuario pueda ejecutar programas. III. Un SO es un conjunto de programas de control del sistema de cómputo, cuyas funciones son: - Administración y control de los dispositivos del sistema de cómputo. - Solución a problemas tales como el tiempo de procesador, espacio en memoria, espacio para almacenamiento de archivos, dispositivos E/S, etc. - Ambiente de ejecución de los programas. Un programa que controla la ejecución de los programas del usuario previniendo errores y usos indebidos de la computadora. - Interfaz entre: - Programas y hardware (llamadas al SO). - Programador-usuario (lenguaje). - Proveer cómputo a bajo costo al compartir recursos e información. IV. Un SO es una colección integrada de rutinas que sirven para el secuenciamiento y procesamiento de programas por medio de una computadora. Un sistema operativo puede proveer varios servicios, como el alojamiento de recursos, planificación, control de la entrada/salida y administración de datos. Aunque los sistemas operativos son software predominantemente, implementaciones parciales o totales pueden ser hechas en forma de firmware (software escrito en ROM). V. Un sistema de cómputo puede ser definido en términos de varias funciones de supervisión y control que provee para los procesos (programas en ejecución) creados por el usuario, tales como: 1. Crear y quitar procesos. 2. Controlar el progreso de los procesos (p.ej. asegurando que no existan bloqueos entre los procesos activos). 3. Actuar en condiciones excepcionales que ocurran durante la ejecución de un proceso (errores aritméticos, de direccionamiento). 4. Asignar recursos de hardware a los procesos. 5. Dar acceso a los recursos de software (archivo, compiladores, etc.). 6. Proveer protección, control de acceso y seguridad a la información. 7. Proveer comunicación entre procesos y sincronización. Estas funciones deben ser provistas por el sistema ya que no siempre pueden ser manejadas adecuadamente por los mismos procesos. El software encargado de asistir al hardware en estas funciones es conocido como el sistema operativo. Todas estas definiciones son complementarias, y en resumen, se puede decir que los Sistemas Operativos son un conjunto de programas que crean la interfaz del hardware con el usuario, y que tienen como funciones primordiales:
9
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
•
Administrar el hardware. Se refiere al hecho de administrar de una forma más eficiente los recursos de la máquina.
• •
Facilitar el trabajo al usuario. Permite una comunicación con los dispositivos de la máquina. Controlar la ejecución de programas y proveer los servicios necesarios para hacerlo. A continuación veremos las características principales de los sistemas operativos.
1.1.2
Características principales
Algunas de las principales características generales de los sistemas operativos actuales son: a. Concurrencia. Es la existencia de varias actividades simultáneas (o paralelas). Algunos ejemplos son la coexistencia en memoria de varias aplicaciones del usuario y la ejecución simultanea de operaciones de E/S y procesos de cómputo. La concurrencia plantea problemas tales como el cambio de una actividad a otra (switching), la protección de una actividad contra los efectos de otra y la sincronización de actividades que son mutuamente dependientes. b. Compartir recursos o información entre las actividades concurrentes. Algunas de las razones son: i) ii) iii) iv)
Costos. A causa de que proveer con equipo suficiente a varios usuarios resulta muy caro. Reutilización. Utilización de de programas o rutinas ya existentes para desarrollar nuevas aplicaciones. Compartir datos de una misma base de datos para diferentes programas. Evitar la redundancia de utilizar copias individuales de un programa en vez de compartir una sola.
c. Almacenamiento a largo plazo de programas e información. d. Un sistema operativo debe ser determinista, en el sentido de que al correr un programa con los mismos datos en diferentes días, debe obtenerse el mismo resultado. Por otra parte debe responder a eventos que ocurren en orden impredecible. Tales eventos pueden ser requerimientos de recursos, errores de tiempo de ejecución en los programas e interrupciones de los dispositivos periféricos. Por lo tanto el SO debe ser escrito para manejar cualquier secuencia de eventos probable. e. Multiplexado. Una técnica en la que el tiempo es dividido en varios intervalos donde un recurso es asignado a un proceso durante cada intervalo. Algunas otras características deseables son las siguientes: 1. Eficiencia. Algunos de los criterios a tomar en cuenta son: a) Tiempo mínimo entre procesos.
10
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
2.
3.
4. 5. 6.
b) Tiempo de respuesta (en sistemas multiusuario) c) Utilización de recursos. d) Libre de errores. Fácil mantenimiento. Debe ser posible mantener un SO (mejorándolo o corrigiendo errores) sin emplear un ejercito de programadores, por lo que el sistema debe ser modular, con interfaces claras y bien definidas entre los módulos, y contar con una documentación completa. Tamaño. El espacio utilizado para cargar en memoria al sistema operativo, es desperdiciado en lo que respecta a procesos productivos. Si el sistema es grande, se tiene la desventaja de que sea más susceptible a errores, y tome más tiempo de codificación que uno pequeño. Interoperabilidad. Es la habilidad del sistema de facilitar intercambio de información entre los componentes heterogéneos en el sistema. Transparencia. Es la propiedad que permite a los usuarios ver al conjunto de máquinas en las que esta trabajando como una sola máquina. Autonomía. Es la independencia de los sistemas operativos con respecto al hardware, lo que permite que el sistema trabaje con unidades autónomas.
En la siguiente sección se revisan los principales conceptos relacionados a los sistemas operativos, los cuales serán explorados con más detalle en capítulos subsecuentes.
1.2
Principales conceptos de los Sistemas Operativos⊕
Básicamente el sistema operativo “enseña a la computadora como comportarse”, es decir, como controlar y coordinar su procesador, la memoria, los dispositivos periféricos y como comunicarse con los usuarios.
Figura 1.3 Soporte de software necesario para aprovechar los recursos del hardware.
⊕
Obras consultadas: [1.11] [1.12]
11
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
La idea de crear un sistema tan grande y complejo como un SO, solo puede manejarse partiéndolo en pequeños módulos, los cuales poseen una función bien definida en el sistema, con sus correspondientes entradas y salidas. Hardware
Ejemplos de servicios de SO
Abstracción del usuario
Procesador
Administración de Procesos, Planificación (scheduling), Excepciones, Protección, Sincronización
Proceso
Memoria
Administración, Protección, Memoria Virtual
Espacio de direcciones
Dispositivos de E/S
Concurrencia con el CPU, Manejo de Interrupciones
Terminal, Mouse, Impresora, (Llamadas al sistema)
Sistema de archivos
Administración, Persistencia
Archivos
Sistemas distribuidos
Seguridad en red Sistema de archivos distribuido
Llamadas al sistema, llamado remoto de procedimientos (RPC), Acceso transparente de archivos (Transparent file sharing)
Tabla 1. Recursos de la arquitectura, administración del sistema operativo y abstracciones del usuario. En las siguientes secciones se define el objetivo y actividades de cada uno de esos módulos (el criterio de selección de los módulos expuestos es que en su mayoría aparecen de forma constante en casi cualquier sistema operativo).
1.2.1 Administración de procesos Uno de los conceptos fundamentales en casi todo SO es el de proceso. Como se mencionó anteriormente, un proceso es un programa en ejecución, y el SO debe encargarse de proveer los medios para controlar dicha ejecución. De ahí nace el concepto de administración de procesos. El microprocesador no hace las cosas por si solo; el sistema operativo es el que determina que proceso se debe ejecutar y cuanto tiempo debe estar ejecutándose. A todo esto se le denomina administración de procesos. El SO es responsable de las siguientes actividades relacionadas con la administración de procesos: •
Creación y borrado de procesos del sistema y el usuario.
• • •
La suspensión y rehabilitación de procesos. Proveer mecanismos para la sincronización de procesos. Proveer mecanismos para la comunicación entre procesos (IPC).
•
Proveer mecanismos para el manejo de bloqueos (deadlocks).
12
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
1.2.2 Administración de memoria Para que los programas se ejecuten, deben ser almacenados en la memoria de la máquina, por lo que el SO debe ser capaz de interactuar con la memoria primaria de la computadora, así como con las abstracciones que el sistema realice con ella (p.ej. estructuras de datos) para gestionar los datos que van entrando y saliendo de la memoria de la computadora (fig. 1.4).
Figura 1.4 Esquema de los diferentes tipos de memoria en un sistema de cómputo. El SO es responsable de las siguientes actividades relacionadas con la administración de memoria: •
Mantener un seguimiento de que partes de la memoria están uso y por quién.
• •
Decidir que procesos serán cargados en memoria cuando exista espacio disponible. Asignar y quitar espacio en memoria como sea requerido.
Una de las abstracciones más importantes relacionadas con la administración de la memoria, es el concepto de memoria virtual. La administración de la memoria virtual se encarga de mantener el mapeo de la memoria virtual y física, decidir en el tamaño de la memoria asignada a los procesos y reforzar la política de reemplazo.
1.2.3 La gestión de la integridad Hay que tener en cuenta que cualquier programa puede, aunque no sea deseable, hacer mención a recursos, direcciones y otros accesos indebidos; si dichos accesos no son controlados, se produciría un error que daría como origen algo que no nos podríamos imaginar (reinicio de la máquina, bloqueo, etc.). Para evitar todos estos problemas, los sistemas operativos tienen distintos niveles de seguridad:
a. En la memoria: Hemos dicho que los programas se cargan en la memoria, pero imaginemos que un programa hace una escritura en una zona de memoria que es de otro programa, para evitar esto el sistema operativo realiza una gestión de la memoria entre los usuarios.
b. En el uso del CPU: Los programas se dividen en procesos que se ejecutan en el microprocesador (CPU), pero si varios procesos intentaran ejecutarse a la vez se produciría un
13
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
efecto imprevisible. Para ello el sistema operativo controla la ejecución de los procesos, la duración de cada uno de ellos y cuando deben entrar o salir de la ejecución. c. En el uso de las entradas y salidas (E/S): En realidad no es que el sistema operativo controle la E/S aunque si lo haga cuando es necesario, lo que ocurre es que si hay un proceso ejecutándose en la cpu y va a imprimir en la impresora algo, el sistema operativo, bloquea el uso de la impresora hasta que el proceso no termine con ella para que no haya otro proceso enviando información a la impresora por que si fuera así entonces provocaría un conflicto en la impresora, y al mismo tiempo saca del procesador el proceso que esta imprimiendo, por que sino los demás procesos tendrían que esperar a que el proceso terminara de imprimir para seguir con el CPU y entonces el CPU estaría bloqueado perdiendo tiempo inútilmente, por que el proceso consume el tiempo del procesador, cuando en realidad no hace nada con él pues está imprimiendo.
1.2.4 Administración de dispositivos Puesto que las configuraciones de hardware de las computadoras varían según las necesidades y desarrollo tecnológico, un área de constante desarrollo es la construcción de nuevos dispositivos periféricos que permitan a las computadoras expandir sus capacidades básicas. Para ello, es necesario que un SO cuente con subsistemas que permitan acceder a tales dispositivos. Dichos subsistemas son los siguientes: 1. Administración del sistema de E/S (I/O). Puesto que uno de los propósitos del SO es hacer transparente las peculiaridades del hardware al usuario, se tiene un sistema de E/S que consiste de: •
Una interfaz general dispositivo-controlador (device-driver).
•
Manejadores para dispositivos específicos de hardware.
2. Manejadores de dispositivos (device drivers): Los manejadores son piezas de código especiales que se encargan de la comunicación de todos los periféricos de la computadora (como terminales, impresoras, discos, etc.) Debe existir un manejador especial para cada diferente tipo de dispositivo conectado, y puesto que hay tantas posibilidades y cada día aparecen nuevos periféricos, no se pueden construir directamente en el kernel. Es necesario hacerlos una parte diferente que pueda ser sustituida o removida de la computadora.
1.2.5 Almacenamiento secundario Tal vez los dispositivos periféricos más usados, sean los de almacenamiento secundario (cintas, discos, etc.). Como la información se ha vuelto un bien vital para los usuarios, se requiere que los sistemas operativos provean servicios que hagan seguro, fácil y transparente el manejo y almacenamiento de información. Los servicios implementados por el SO son los siguientes: a. Administración de almacenamiento secundario. El SO es responsable de las siguientes actividades relacionadas con la administración de discos: •
Manejo del espacio libre.
14
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
• •
Distribución de almacenamiento. Organización del disco.
b. Administración de archivos. El SO es responsable de las siguientes actividades relacionadas con la administración y organización de archivos: • •
La creación y borrado, de archivos y directorios. Bloqueo y protección de archivos y directorios.
• • •
Soporte de operaciones primitivas para la manipulación de archivos y directorios. El mapeo de archivos en almacenamiento secundario. El respaldo de archivos en un medio estable de almacenamiento.
La principal abstracción que provee el SO para el manejo del almacenamiento secundario es el sistema de archivos, el cual permite ordenar los datos en una forma estructurada, fácil de recordar y manejar (p.ej. archivos de tamaño variable, directorios, etc.). El sistema de archivos trabaja sobre los manejadores de dispositivos para proveer una interfaz abstracta con los diferentes manejadores. Define la forma de almacenar información en dispositivos de almacenamiento, por lo que no es necesario aprender un nuevo método de almacenamiento para cada dispositivo posible.
1.2.6 Transmisión de datos e información Además de almacenar información, otra necesidad imperiosa es la de transmitirla. Cuando las computadoras cuentan con los dispositivos necesarios, pueden ser conectadas entre si, formando redes. Nuevamente el SO debe ofrecer la capacidad de conectarse a estas redes, y transmitir y recibir información de forma segura. Para ello se necesitan: a. Servicios de Comunicación en Red (networking). Se refiere a la conexión de múltiples procesadores por medio de una red, que puede ser configurada de diferentes maneras, y debe tomar en cuenta estrategias de conexión y ruteo, así como casos de contención y seguridad, además de dar soporte a varios protocolos y medios de comunicación. b. Protección del sistema. Se refiere a mecanismos para controlar el acceso de programas, procesos o usuarios a los recursos definidos por un sistema de cómputo. c. Programas Auxiliares. Estos programas se encargan de ayudar al SO a llevar a cabo sus tareas. Estos programas pueden encargarse de controlar comunicaciones, seguridad, etc. Algunos son visibles como el programa de autentificación de usuarios (login), pero muchos otros trabajan escondidos en el trasfondo (en algunos sistemas son llamados demonios).
1.2.7 Núcleo del sistema (Kernel) Una abstracción fundamental hecha con base en los conceptos anteriores, es la de organizar todos estos módulos de forma que pueda contarse con un mayor o menor número de servicios por parte del SO. Tal abstracción es llamada núcleo o kernel del sistema operativo.
15
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
El kernel (o núcleo) es la parte del sistema que en realidad se encarga de los aspectos más básicos de la funcionalidad, principalmente con la forma en que la computadora se comportará. Comúnmente, el kernel establecerá las políticas de trabajo (tarea simple o multi-tarea; métodos de planificación), como manejar a los componentes básicos (p.ej. políticas de manejo de memoria como el uso de la memoria virtual), las medidas de seguridad básica y como iniciar, comunicarse y apagar todos los demás componentes. Toda esta gestión la realiza para atender al funcionamiento y peticiones de los trabajos que se ejecutan en el sistema. El núcleo normalmente representa sólo una pequeña parte de lo que por lo general se piensa que es todo el sistema operativo, pero es el código que más se utiliza. Por esta razón el núcleo reside por lo regular en la memoria principal, mientras que otras partes del sistema operativo son cargadas en la memoria principal sólo cuando se necesitan.
1.2.8 Comunicación con el usuario⊕ Una vez establecidos los conceptos relativos al control de los recursos de hardware y software, podemos hablar de la forma en que una computadora con sistema operativo se comunica con el usuario. a. Interfaz de usuario. La Interfaz de usuario es la parte del sistema que provee una forma en que la computadora capte y reaccione a las acciones del usuario, y transmita la información que el usuario produce. Es el componente que se encarga de traducir los datos binarios en números y caracteres en la pantalla, o interpretar los códigos binarios del teclado, y si se trata de una interfaz grafica de usuario (GUI), se encarga de dibujar las ventanas y otros objetos en la pantalla. Nótese que una computadora puede tener varias interfaces de usuario para adaptarse a diferentes modelos de terminales o preferencias del usuario. b. Shells - Sistema interprete de comandos (Command Language Interpreter, CLI). El SO esta diseñado para trabajar en conjunto con otros programas, y no se pretende que sea accedido directamente por el usuario. Así que por lo menos se requiere un programa que sirva de interfaz entre el usuario y el sistema para permitir el uso de la computadora. La mayor parte de los sistemas operativos cuentan con uno o mas de estos programas (los cuales solo reciben comandos y los traducen en instrucciones del SO). Varias ordenes le son dadas al SO por medio de sentencias de control. Cuando un nuevo trabajo comienza en un sistema batch, o cuando un usuario accede en un sistema de tiempo compartido, un programa que lee e interpreta dichas ordenes es ejecutado inmediatamente. Se le llama también intérprete de tarjetas de control, intérprete de comandos en línea, el shell (en UNIX), etc. Su función es bastante simple: obtener el siguiente comando y ejecutarlo.
⊕
Obras consultadas: [1.29]
16
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 1.5 Niveles de interacción de un shell Los SOs se distinguen frecuentemente en el área de interpretación de comandos, por interpretes más amigables que hacen más agradable el sistema a los usuarios. Un ejemplo es el intérprete de Mac, que es un sistema basado en ventanas que es exclusivamente activado en ciertas regiones (iconos) por el ratón. c. Interfaz gráfica de usuario (GUIs -Graphical User Interfaces). Las GUIs despliegan objetos gráficos en la pantalla (imágenes, iconos, botones, etc.) y el usuario interactúa con ellos usando un dispositivo apuntador (por lo general un ratón (mouse)). Las interfaces gráficas modernas usan una "metáfora de escritorio" en las que áreas conocidas como ventanas, contienen actividades de trabajo, como hojas de papel sobre un escritorio real. Las GUIs hacen uso extensivo de los gráficos por computadora para organizar el área de trabajo del usuario, y presentan formas intuitivas para realizar diversas tareas. En 1968 Doug Engelbart del Stanford Research Center's Augmentation Research Center, patrocinado por la Agencia de Proyectos de Investigación Avanzados del Departamento de Defensa (ARPA), instrumentó el primer sistema de ventanas (windowing system). En 1970, investigadores del Centro de Investigación de Palo Alto (XEROX PARC) diseñaron la primera computadora con interfaz gráfica (Alto Computer).
17
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
(a)
(b)
Figura 1.6 Ejemplos de interfaz gráfica de usuario: (a) el sistema NeXT; (b) Mac OS X. Por lo anterior, se puede decir que aunque el SO es una parte muy importante del sistema de computo, este queda fuera de la vista de los usuarios, los cuales lo notan de forma indirecta por medio de las capacidades que el SO provee y las cosas que permite y no permite hacer, cuando lo acceden por medio de otros programas como los shells o las GUIs, que son los que comprenden e interpretan las acciones que el usuario quiere realizar. Para entender cómo es que aparecieron este tipo de sistemas, revisaremos la historia de la computación con la intención de entender las motivaciones que condujeron al desarrollo de los sistemas operativos.
1.3
Desarrollo histórico de los Sistemas Operativos⊕
Para tener una perspectiva completa de los sistemas operativos, es importante revisar su historia, la cual es paralela al desarrollo del hardware de las computadoras, pues los nuevos avances requerían de nuevas soluciones. Basado en algunas referencias relativas a la historia y evolución de las computadoras, se ha desarrollado la siguiente cronología (fig. 1.7) la cual integra a las generaciones de computadoras digitales y a los sistemas operativos. En ella se han tratado de incluir los principales paradigmas de ambas áreas. Por convención, la primera generación inicia con las primeras computadoras electrónicas, en lugar de las máquinas mecánicas y electromecánicas que les antecedieron. Cabe mencionar que de todas las referencias consultadas, no hay un consenso en cuanto a los periodos de tiempo que cada generación cubre, o incluso a los criterios que se usan para definirlas. Un criterio interesante se basa en los cambios en la tecnología de implementación dominante, que permiten crear nuevas computadoras. Sin embargo, es posible obtener nuevas configuraciones con la tecnología disponible, creando arreglos complejos de procesadores (que además implica desarrollar tecnologías de conectividad y sincronización).
⊕
Obras consultadas: [1.1] [1.2] [1.3] [1.4] [1.5] [1.6] [1.7] [1.8] [1.9] [1.10]
18
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 1.7 Cronología del desarrollo de las computadoras y los sistemas operativos. 19
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
En las siguientes secciones se explora el desarrollo histórico de los sistemas operativos, con el fin de tener una idea de como han ido evolucionando, y para apreciar un poco más "los lujos" que hoy disfrutamos en nuestras computadoras. Aunque los primeros sistemas ahora pueden ser (o parecer) obsoletos, no deja de ser interesante su análisis para comprender las tendencias actuales en su desarrollo.
1.3.1 En el principio... Las primeras computadoras de fines de los 1940s no tenían sistema operativo. En un principio solo existía el hardware de la computadora. Las primeras computadoras eran (físicamente) grandes máquinas que se operaban desde una consola. El programador escribía un programa y luego lo controlaba directamente. En primer lugar, el programa se cargaba manualmente en la memoria, desde los interruptores del tablero frontal, desde una cinta de papel o desde tarjetas perforadas. Luego se pulsaban los botones adecuados para establecer la dirección de inicio y comenzar la ejecución del programa. Mientras este se ejecutaba, el programador-operador lo podía supervisar observando las luces en la consola. Si se descubrían errores, el programador podía detener el programa, examinar el contenido de la memoria y los registros y depurar el programa directamente desde la consola. La salida del programa se imprimía, o se perforaba en cintas de papel o tarjetas para su impresión posterior. Un aspecto importante de ese entorno era su naturaleza interactiva directa. El programador también era el operador del sistema de cómputo (figura 1.8). Al mismo tiempo, el problema matemático a resolver, se mezclaba con los problemas físicos de la computadora. El trabajo de los operadores humanos, quienes planificaban los trabajos listos para ejecutar y supervisaban el uso de los recursos de la computadora, fue una de las primeras ocupaciones en ser automatizada.
Figura 1.8 Esquema de operación de las primeras computadoras. Estas computadoras eran tan caras, que el principal objetivo de un sistema operativo era hacer al hardware tan eficiente como fuera posible. Además, los programadores producían su propio
20
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
código objeto para los programas, incluyendo todas las instrucciones para entrada de datos de las tarjetas o cinta de papel y salida de resultados a impresoras o cinta magnética. Un programa (o trabajo) era cargado y ejecutado a la vez hasta su término o detenido a causa de un error; el sistema estaba ocioso hasta que el siguiente programa fuera cargado y ejecutado. Durante los 1950s, los cargadores, rutinas estándar de entrada/salida (E/S), ligadores, ensambladores y compiladores fueron introducidos, junto con el concepto de archivo, así que el código de programa o conjuntos de datos podían ser referidos por medio de nombres de archivos. Lotes de archivos de programas eran cargados de una sola vez (a través de lectoras de tarjetas), y compartían el CPU y la memoria primaria: cuando un programa esperaba por el término de la lenta E/S, era suspendido de forma que otro programa pudiera usar el CPU (multiprogramación). En los anales de la historia de la computación, 1956 es el año en que aparece el primer sistema operativo, diseñado para la IBM 704 (por Bob Patrick (General Motors) y Owen Mock (North American Aviation)), llamado GM-NAA I/O, y permitía el procesamiento por lotes (una forma simple de combinar comandos existentes en nuevos comandos). En la siguiente sección se explica a detalle la operación del procesamiento por lotes.
1.3.2 Procesamiento por lotes y monitores Los Sistemas Operativos por lotes, procesan una gran cantidad de trabajos con poca o ninguna interacción entre los usuarios y los programas en ejecución. Se reúnen todos los trabajos comunes para realizarlos al mismo tiempo, evitando la espera de dos o más trabajos como sucede en el procesamiento en serie. Estos sistemas son de los más tradicionales y antiguos, y fueron introducidos alrededor de 1956 para aumentar la capacidad de procesamiento de los programas. Un sistema de lotes es aquel cuyos trabajos (jobs) son reunidos con las instrucciones necesarias para permitirles ser procesados sin intervención de un operador. El monitor residente (o monitor), es el software del sistema que es responsable de interpretar y ejecutar las instrucciones en los trabajos por lotes. Cuando el monitor comenzaba un trabajo, cedía el control completo de la computadora al trabajo, el cual controlaba la computadora hasta su término (figura 1.9).
21
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 1.9 Esquema básico de la memoria de una computadora con procesamiento por lotes (monitor residente). Un ejemplo de varios trabajos en lote podría verse así: $JOB user_spec ; identificar al usuario $FORTRAN ; cargar el compilador de FORTRAN source program cards ; tarjetas con el programa fuente $LOAD ; cargar el programa compilado $RUN ; ejecutar el programa data cards ; tarjetas con los datos $EOJ ; fin del trabajo $JOB user_spec $LOAD application $RUN data $EOJ
; identificar un nuevo usuario ; cargar aplicación ; ejecutar la aplicación ; fin del trabajo
Por lo general se usaban cintas magnéticas o tambores para almacenar los datos intermedios y programas compilados. Las ventajas y desventajas de este tipo de sistemas son: 1. Ventajas mueve mucho del trabajo del operador a la computadora incrementa el desempeño, puesto que es posible para un trabajo comenzar tan pronto como el anterior termina 2. Desventajas depuración complicada de programas debido al esquema de protección, un trabajo del lote puede afectar a los demás trabajos pendientes (p.ej. a causa de la lectura de demasiadas tarjetas, etc.) un trabajo puede corromper al monitor, afectando también a los trabajos pendientes un trabajo puede entrar en un ciclo infinito Como se mencionó, una de las mayores carencias de los sistemas por lotes era que no existía un esquema de protección para prevenir que algún trabajo afecte adversamente a otros. La solución a esto era un simple esquema de protección, donde cierta memoria (p.ej. donde reside
22
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
el monitor) era restringida a los programas de usuario. Esto prevenía que los programas de usuario corrompieran al monitor. Para evitar que los programas de usuario leyeran demasiadas (o pocas) tarjetas, el hardware era cambiado para permitir a la computadora operar en uno de dos modos: uno para el monitor y uno para los programas de usuario. La entrada/salida (E/S) podría solo ser realizada en modo de monitor, así que las peticiones de E/S de los programas de usuario eran pasadas al monitor. De esta manera, el monitor podría evitar que un trabajo no leyera su tarjeta de fin de trabajo ($EOJ). Para prevenir un ciclo infinito, un temporizador (timer) fue agregado al sistema y la tarjeta $JOB fue modificada para que el tiempo máximo de ejecución de un trabajo fuera enviado al monitor. La computadora podría interrumpir el trabajo y regresar el control al monitor si se excedía este tiempo. Cuando estos sistemas son bien planeados, pueden tener un tiempo de ejecución muy alto, porque el procesador es mejor utilizado y los Sistemas Operativos pueden ser simples, debido a la naturaleza secuencial de la ejecución de los trabajos. Algunos ejemplos de Sistemas Operativos por lotes exitosos son el SCOPE, del DC6600, el cual está orientado a procesamiento científico pesado, y el EXEC II para el UNIVAC 1107, orientado a procesamiento académico.
1.3.3 Sistemas de operación simultanea de periféricos en línea Una dificultad con los sencillos sistemas de lotes es que la computadora aún necesitaba leer el bloque de tarjetas antes de comenzar a ejecutar un trabajo. Esto significa que el CPU estaría ocioso durante estas operaciones relativamente lentas.
Figura 1.10 Esquemas básicos de procesamiento. Nótese como el tiempo desperdiciado ha ido disminuyendo
23
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Puesto que es más rápida la lectura de una cinta magnética que un bloque de tarjetas, se volvió común para los centros de cómputo tener una o más computadoras menos potentes en complemento a su computadora principal. Las computadoras pequeñas eran usadas para leer y cargar las tarjetas a las cintas, por lo que la cinta podía contener varios trabajos en lote. Esta cinta era entonces cargada en la computadora principal y los trabajos de la cinta eran ejecutados. La salida de los trabajos podía ser escrita a otra cinta que era retirada y cargada en una computadora de menor capacidad para producir cualquier salida deseada (p.ej. impresiones). Una extensión lógica del temporizador en el sistema por lotes, fue tener un temporizador que pudiera permitir a los trabajos ejecutarse solo por un corto periodo de tiempo antes de interrumpirlos para que el monitor pudiera iniciar alguna operación de E/S. Puesto que la operación de E/S podría proceder mientras el CPU se ocupaba en un programa de usuario (realizar E/S y cálculos en paralelo), fue posible que la computadora leyera tarjetas a las cintas, tambores o discos y escribir la salida a una cinta mientras seguía procesando programas. Este proceso es llamado SPOOLing (Simultaneous Peripheral Operation OnLine). Los sistemas por lotes Spooling (Spooling Batch Systems) fueron los primeros (y más simples) sistemas de multiprogramación. Una ventaja de los sistemas de spooling era que la salida estaba disponible tan pronto como el trabajo se completara, en vez de tenerla cuando todos los trabajos del lote se completaran.
1.3.4 Sistemas de Multiprogramación Cuando máquinas con mayor cantidad de memoria estuvieron disponibles, fue posible extender la idea de multiprogramación como se hizo en los sistemas de spooling al crear sistemas capaces de cargar varios trabajos en memoria de una sola vez y ciclarlos en el mismo orden, trabajando en cada uno por un periodo específico de tiempo.
Figura 1.11 Esquema de sistema de multiprogramación (o multitarea), donde varias tareas son ejecutadas simultáneamente.
24
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
En este punto, el monitor crece hasta el punto de parecer un sistema operativo moderno, el cual es responsable de: •
iniciar trabajos de usuario
• • •
operaciones de spooling E/S para trabajos de usuario switcheo entre trabajos de usuario
•
asegurar la protección adecuada mientras realiza las tareas anteriores
Como un simple y común ejemplo, considérese una máquina que puede correr dos trabajos a la vez. Incluso, supongamos que un trabajo es de E/S intensiva y que el otro usa el CPU intensivamente. Una forma para el monitor de obtener tiempo de CPU entre estos trabajos podría ser dividir el tiempo equitativamente entre ellos. Sin embargo, el monitor podría estar ocioso gran parte del tiempo durante la ejecución del proceso de E/S. Una buena solución en este caso es permitir al trabajo del CPU (background job) ejecutarse hasta que el trabajo de E/S (foreground job) necesite tiempo de CPU, momento en el cual el monitor le permite ejecutarse, y cuando requiera de nuevo realizar sus operaciones de E/S, se devuelve el control al trabajo anterior. Los Sistemas Operativos de multiprogramación (o de multitarea) se distinguen por sus habilidades para poder soportar la ejecución de dos o más trabajos activos (que se están ejecutado) al mismo tiempo. Esto trae como resultado que el CPU siempre tenga alguna tarea que ejecutar, aprovechando al máximo su utilización.
Figura 1.12 Esquema de ejecución de dos procesos con y sin multiprogramación. Su objetivo es tener a varias tareas en la memoria principal, de manera que cada uno está usando el procesador, o un procesador distinto, es decir, involucra máquinas con más de una CPU. Sistemas Operativos como UNIX, Windows 95, Windows 98, Windows NT, MAC-OS, OS/2, soportan la multitarea.
Sistemas de tiempo compartido (Timesharing) En los tiempos en los que no se disponía de un sistema operativo, el programador tenía acceso completo a la máquina. Al desarrollarse hardware y software para crear monitores, sistemas de lotes y multiprogramación, la separación entre el usuario y la computadora de volvió más pronunciada.
25
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Uno de los problemas más comunes era que los usuarios y los programadores en particular, tardaban en tener acceso a la máquina (sobre todo en los esquemas de lotes). Tal cuestión trato de solucionarse por medio de un esquema llamado de tiempo compartido (timesharing/timeslicing). La idea de multiprogramación fue extendida para permitir que varias terminales fueran conectadas a la computadora, y que a cada terminal en uso se le asociaran uno o más trabajos en la computadora. El SO era entonces responsable de intercalar (switching) los trabajos (también llamados procesos) de manera que se favoreciera la interacción con el usuario. Si el cambio de contexto (context-switches) ocurría lo suficientemente rápido y con la suficiente frecuencia, el usuario tenía la impresión de tener acceso directo a la computadora. A los procesos interactivos se les da una mayor prioridad, así que cuando una E/S es requerida (p.ej. una tecla presionada), el control del CPU le es dado al proceso asociado, así que puede procesarlo. Esto es instrumentado mediante el uso de una interrupción que causa que la computadora se de cuenta que un evento de E/S ha ocurrido. Debe mencionarse que existen varios tipos de sistemas de tiempo compartido. Una clase es representada por computadoras como las VAX/VMS y las estaciones de trabajo UNIX. En estas computadoras, procesos enteros se encuentran en memoria, y la computadora intercala la ejecución entre ellos. En otros tipos de sistemas, como los de reservación de vuelos, una sola aplicación puede hacer la distribución de tiempo entre las terminales. De esta forma no se necesita ejecutar un programa diferente asociado a cada terminal. Los Sistemas Operativos de tiempo compartido permiten simular que el sistema y sus recursos son todos para cada usuario. El usuario hace una petición a la computadora, esta la procesa tan pronto como le es posible, y la respuesta aparecerá en la terminal del usuario en un tiempo muy corto, dando la impresión al usuario de tener al sistema bajo su control exclusivo.
Figura 1.13 Esquema de un sistema de tiempo compartido. Los principales recursos del sistema, el procesador, la memoria, dispositivos de E/S, son continuamente utilizados entre los diversos usuarios, dando a cada usuario la ilusión de que tiene el sistema dedicado para sí mismo. Esto trae como consecuencia una gran carga de trabajo al sistema operativo, principalmente en la administración de la memoria principal y secundaria.
26
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Ejemplos de sistemas operativos de tiempo compartido son Multics, OS/360 y DEC-10.
Sistemas de Tiempo Real⊕
Para empezar, un sistema de tiempo real es aquel sistema informático en el que el desempeño del sistema no sólo depende de los resultados lógicos de los algoritmos, sino que también depende del momento en el que estos se producen. Una computadora de tiempo real es aquella que ejecuta programas que están garantizados en poseer un desempeño superior en las tareas que desarrollan. Por ejemplo los sistemas de guía de misiles y equipo de monitoreo médico. Las computadoras dedicadas son computadoras de propósito especial que son usadas para realizar solo una o más tareas. Comúnmente estas son computadoras de tiempo real que incluyen aplicaciones de control (misiles, inyección electrónica de gasolina, control automático de trenes, etc.). Los sistemas operativos de este tipo de computadoras están severamente restringidos por requerimientos de tiempo.
Figura 1.14 Esquema de un sistema de control, en donde deben ser aceptados y procesados gran cantidad de sucesos. Los Sistemas Operativos de tiempo real son aquellos en los cuales no tiene importancia el usuario, sino los procesos. Por lo general, están subutilizados sus recursos con la finalidad de prestar atención a los procesos en el momento que lo requieran. Se utilizan en entornos donde son procesados un gran número de sucesos o eventos. Muchos sistemas operativos de tiempo real son construidos para aplicaciones muy específicas como control de tráfico aéreo, bolsas de valores, refinerías, etc. También en el ramo automovilístico y de la electrónica de consumo, las aplicaciones de tiempo real están creciendo muy rápidamente. Otros campos de aplicación de los Sistemas Operativos de tiempo real son los siguientes: - Control de trenes. - Control automático de procesos químicos. - Telecomunicaciones. ⊕
Obras consultadas: [1.18] [1.19]
27
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
-
Sistemas de fabricación integrada. Producción y distribución de energía eléctrica. Control de edificios. Sistemas multimedia.
Algunos ejemplos de Sistemas Operativos de tiempo real son: VxWorks, Solaris, Lyns OS y Spectra.
1.3.5 Sistemas Multiprocesador, distribuidos y en red⊕ Un sistema de cómputo multiprocesador es aquel con más de un CPU. Los dos grandes problemas que se tienen en este tipo de sistemas tienen que ver con: 1. El control de los procesadores. Dos o más procesadores similares están conectados por medio de conexiones de alta velocidad y son administrados por un sistema operativo, donde cada procesador tiene el mismo acceso a los dispositivos de entrada/salida. Los procesadores son tratados más o menos igual, permitiendo que los programas de aplicación se ejecuten en cualquiera o tal vez, hasta en todos los procesadores del sistema, bajo la dirección del sistema operativo. El multiprocesamiento simple usualmente consiste en asignar a cada procesador una tarea fija (como administrar el sistema de archivos), reservando el CPU principal para tareas generales (fig. 1.15).
Figura 1.15 Configuraciones de multiprocesamiento asimétrico(a) y simétrico(b). 2. La administración de la memoria. Esta categoría puede ser subdividida en: a. Multiprocesadores de memoria compartida que tienen varios CPUs, todos con acceso a la misma memoria. La comunicación entre los procesadores es fácil de implementar, pero el punto crítico es la sincronización del acceso a memoria. b. Multiprocesadores de memoria distribuida con varios CPUs, donde cada CPU tiene su propia memoria asociada. Aquí, la sincronización del acceso a memoria no es un problema, pero la comunicación entre los procesadores por lo general es lenta y complicada.
⊕
Obras consultadas: [1.20] [1.30] [1.31]
28
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
En los Sistemas Operativos Paralelos se pretende que cuando existan dos o más procesos que compitan por algún recurso, se puedan realizar o ejecutar al mismo tiempo. En una máquina paralela, el sistema operativo paralelo se construye encima de los sistemas operativos (o kernels) de cada procesador. Por ejemplo, en la IBM SP-2, el sistema operativo paralelo consiste de procesadores individuales ejecutando AIX y un componente unificador paralelo conocido como POE (Parallel Operating Environment). En UNIX existe también la posibilidad de ejecutar programas sin tener que atenderlos en forma interactiva, simulando paralelismo (es decir, atender de manera concurrente varios procesos de un mismo usuario). Así, en lugar de esperar a que el proceso termine de ejecutarse (como lo haría normalmente), regresa a atender al usuario inmediatamente después de haber creado el proceso. Ejemplos de Sistemas Operativos Paralelos son: Alpha, PVM, la serie AIX (que es utilizado en los sistemas RS/6000 de IBM), Tornado, Hurricane y Helios. También relacionado al multiprocesamiento se encuentran los siguientes tipos de sistemas: a. Sistemas en red, que consisten de varias computadoras que están conectadas entre si, usualmente con un sistema operativo común y recursos compartidos. Los usuarios sin embargo, están informados de las computadoras que conforman el sistema. Los sistemas operativos de red son aquellos sistemas que mantienen a dos o más computadoras unidas a través de algún medio de comunicación (físico o no), con el objetivo primordial de poder compartir los diferentes recursos y la información contenida en cada equipo. Los Sistemas Operativos de red más usados son: Novell Netware, Personal Netware, LAN Manager, Windows NT Server, UNIX y, LANtastic. b. Sistemas distribuidos, también consisten de varias computadoras pero difieren del enfoque de redes en que estas computadoras son transparentes al usuario. Por lo general hay recursos redundantes y se comparte la carga de trabajo entre las diferentes computadoras, pero esto es transparente al usuario (fig. 1.16). Los sistemas operativos distribuidos permiten distribuir trabajos, tareas o procesos, entre un conjunto de procesadores. Puede ser que este conjunto de procesadores esté en un equipo o en diferentes, en este caso es transparente para el usuario. Existen dos esquemas básicos: 1. Un sistema fuertemente acoplado es aquel que comparte la memoria y un reloj global, cuyos tiempos de acceso son similares para todos los procesadores. 2. En un sistema débilmente acoplado los procesadores no comparten ni memoria, ni reloj, ya que cada uno cuenta con su memoria local.
29
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 1.16 Esquema de un sistema operativo distribuido. Los sistemas distribuidos deben de ser muy confiables, ya que si un componente del sistema se descompone, otro componente debe de ser capaz de reemplazarlo. Entre los diferentes Sistemas Operativos distribuidos que existen tenemos los siguientes: Sprite, Solaris-MC, Mach, Chorus, Spring, Amoeba, Taos, etc. No hay que confundir un Sistema Operativo de Red con un Sistema Operativo Distribuido. En un Sistema Operativo de Red las computadoras están interconectadas por medios de comunicación: software y hardware. En este tipo de sistema los usuarios saben donde están ejecutando su trabajo y guardando su información. En cambio en los Sistemas Operativos Distribuidos existe un software que distribuye las tareas de los usuarios sobre una red de computadoras y para los usuarios es transparente donde realizan sus tareas y guardan su información. Existen dos esquemas básicos de éstos sistemas. Un sistema fuertemente acoplado es aquel que comparte la memoria y un reloj global, cuyos tiempos de acceso son similares para todos los procesadores. En un sistema débilmente acoplado los procesadores no comparten ni memoria ni reloj, ya que cada uno cuenta con su memoria local.
1.3.6 Computadoras Personales⊕ En los inicios, los sistemas operativos estaban individualizados. Puesto que las computadoras eran una rareza, la cuestión de la estandarización era ignorada, pues había pocas computadoras para ello, y por lo tanto los SOs estaban atados a las capacidades y propósitos de cada sistema. La segunda forma en la que los programadores y usuarios retomaron las computadoras fue el advenimiento de las computadoras personales cerca de 1980. Finalmente las computadoras fueron suficientemente pequeñas y baratas que un individuo podía tener una (fig. 1.17). Las primeras microcomputadoras fueron la Altair, la Commodore PET, la Tandy, y la Apple II (hay de hecho una Apple I, pero solo 200 fueron manufacturadas. Una de ellas cuelga en las oficinas de Apple con la leyenda "Nuestra Fundadora"). ⊕
Obras consultadas: [1.25] [1.26] [1.27] [1.28]
30
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
La primera computadora de Tandy fue la TRS-80. La TRS, cuando se presentó, fue un gran éxito de venta gracias a su poderoso sistema operativo y el creciente numero de aplicaciones desarrolladas para él. En lo que falló, fue en mantenerse al día en los campos de mejoras de video y facilidad de uso de su SO. Las series Apple II (hasta que oficialmente fueron descontinuadas), fue usada por todos los sistemas escolares y muchos hogares estadounidenses. La Apple tenía varios sistemas operativos, como el Integer BASIC, el DOS 3.3, y el sofisticado ProDOS.
(a)
(b)
(c)
(d)
Figura 1.17 Las primeras PCs: (a) MITS Altair (1974), (b) Radio Shack TRS-80 (1977), (c) Apple I (1976), (d) Apple Lisa (1983). Sin embargo la mayor contribución de Apple viene con la línea Macintosh. Steve Jobs estaba buscando una forma para mejorar la Apple II. En diciembre de 1979, fue invitado a participar en un paseo por el centro de desarrollo de Xerox (PARC), el cual estaba tecnológicamente avanzado para su tiempo y tenia dispositivos de los que no se había escuchado. Durante este paseo, le mostraron tres paradigmas revolucionarios: Ethernet, impresoras láser, y lo que más impresiono a Jobs, la interfaz gráfica de usuario (GUI). De inmediato Jobs vio esto como el futuro de los sistemas operativos (lo cual se plasmó en LISA). Cuando Commodore introdujo la PET, era bastante popular, pero no tanto como cuando introdujo su línea de 8-bits de color, con la VIC-20, la 64 y la 128. El contemporáneo sistema operativo de Commodore estaba basado en su versión de BASIC. Todos los comandos a periféricos, los cuales eran "inteligentes" (tenían su propia memoria, procesador y manejadores), eran hechos por medio de BASIC; la computadora arrancaba en BASIC; y BASIC estaba construido en ROM.
31
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
La Commodore 64 fue la caja maravilla para el mundo desde su llegada en 1982, con gráficos extraordinarios de 16 colores y sonido 3-voice, basada en la eficiente serie MOS 6500 (como nota, una variante del 6510 de 16 bits, el 65816, es el que soporta al Super Nintendo). Puesto que el BASIC no tenia los comandos nativos para manipular muchas de las avanzadas características de la 64, aparecieron una gran cantidad de accesorios: cargadores rápidos para mejorar la velocidad de las unidades de disco 1541; extensiones de BASIC de todo tipo, y mejoras de hardware, como extensiones de RAM, cajas de alta velocidad RS232 e interfaces a impresoras no-Commodore. Otra clave fue el sistema operativo GEOS, hecho por Berkeley Softworks (ahora GeoWorks). Aunque era lento y beligerante, desarrolló un fiel grupo de seguidores por a su poderosa GUI de 80 columnas (a la Mac) en la 64, y la gran cantidad de software existente para el (desde juegos hasta programas de negocio). La 64 podía incluso comportarse como una PC o estación Unix: programas como CS-DOS y los potentes sistemas operativos A64/OS y Lunix, que convertían a la 64 en pequeñas versiones de sus competidores más grandes. OS9 fue uno de los pocos SO, sino el único, multitarea, multihilado y, con un poco de suerte, multiusuario en los sistemas de 8 bits. Corriendo en sistemas basados en versiones del 6809, como CoCos, para sistemas 68000 como el Atari STs, e incluso para la Apple II. La gran piedra angular de los sistemas operativos de 8 bits fue CP/M (el cual casi reemplaza al MS-DOS como el SO para la PC, de no haber sido por una compañía de software de Redmond, Washington que hizo un mejor trabajo de relaciones públicas). Desarrollado por Gary Kildall (de Digital Research) a mediados de los 1970s, CP/M fue el primer SO estandarizado jamás creado para microcomputadoras. CP/M tenía un conjunto estándar de comandos, (eventualmente) un DOS estandarizado, e incluso utilerías del sistema. MS-DOS no fue el primero, ni el mejor de los sistemas operativos para microcomputadoras cuando fue licenciado por Microsoft para las PCs IBM (el sistema operativo de Tim Patterson, QDOS como lo llamaba, no era enteramente suyo. Él trabajo para Seattle Computer Products, así que ellos poseían los derechos de QDOS. Microsoft decidió comprar los derechos de QDOS por US$50,000 y cambio su nombre a PCDOS 1.0 (cerca de agosto de 1981)). Las primeras versiones presentadas eran similares al interprete de comandos de CP/M. MS-DOS fue escrito en lenguaje ensamblador de 16-bits (Intel) por lo que era difícil de portar a otras máquinas, a diferencia de CP/M, que en su mayor parte estaba escrito en un lenguaje de alto nivel. El DOS era un SO monousuario y monotarea, donde el usuario puede ejecutar un programa a la vez hasta su termino.
1.4
Comentarios
La principal contribución de todos estos desarrollos, fue enfrentar a un mercado creciente de usuarios con necesidades de usabilidad. En retrospectiva, los científicos que usaban las grandes computadoras estaban capacitados para operarlas, pero esto requería de un alto grado de especialización y es aquí donde las interfaces gráficas y los periféricos encontraron su lugar. En el siguiente capitulo se analizar el funcionamiento básico de un sistema operativo con el fin de integrar los conceptos expuestos hasta el momento.
32
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
1.5
Obras consultadas
[1.1] IIC 2332 -- Sistemas Operativos Apuntes 01 1er Semestre 1996
[1.12] Introduction to Operating Systems
http://www.cs.virginia.edu/~knabe/iic2332/
Kathryn S. McKinley. University of Massachusetts .Fall 1997
[1.2] CS322: A Brief History of Computer Operating Systems
http://www-aml.cs.umass.edu/~cs377/
Prof. R. Bjork, Gordon College
[1.13] DESDE QUE PULSAMOS EL BOTON DE NUESTRO PC HASTA...
http://www.cs.gordonc.edu/courses/cs322/lectures/hist ory.html [1.3] Operating Systems Lecture notes
José Manuel Tella Llop, extraído de microsoft.public.es.windows98 http://www.duiops.net/windows/articulos/
Lecture 1: Overview and History Martin C. Rinard
[1.14] How Operating Systems Work
http://williamstallings.com/Extras/OS-Notes/notes.html
Marshal Brain's HowStuffWorks http://www.howstuffworks.com/operating-system.htm
[1.4] A BRIEF HISTORY OF OPERATING SYSTEMS THROUGH TIME by Cameron Kaiser http://www.armory.com/~spectre/tech.html
[1.15] Sistemas operativos I: Interrupciones del procesador http://itver.edu.mx/so1/24.htm
[1.5] Brad A. Myers. "A Brief History of Human Computer Interaction Technology."
[1.16] CSC 277- Operating Systems (handouts)
ACM interactions. Vol. 5, no. 2, March, 1998. pp. 44-54.
Michael Lynch
[1.6] The computer museum history center. Timeline of computer history.
http://www.qvctc.commnet.edu/classes/csc277/handou ts.html
http://www.computerhistory.org
[1.17] Introduction to Operating Systems
[1.7] Curso de sistemas operativos
Kathryn S. McKinley. University of Massachusetts .Fall 1997
Enrique Sánchez Lara
http://www-aml.cs.umass.edu/~cs377/
http://lara.pue.udlap.mx/sist_oper/index.html [1.8] Un paseo por la historia Lidón García , Luis Peralta & Samuel Fernández http://spisa.act.uji.es/~peralta/os/ [1.9] An Overview Of Computational Science
[1.18] Real Time Linux (RT-Linux) Aitor Cuesta http://members.es.tripod.de/Arioch/ [1.19] Sistemas Operativos Curso 2000-2001 http://www.esi.uem.es/~gachet/s_oper.htm
Copyright (C) 1991, 1992, 1993, 1994, 1995 by the Computational Science Education Project
[1.20] Symmetric multiprocessing
http://csep1.phy.ornl.gov/ov/ov.html
The Free Online Dictionary of Computing http://burks.brighton.ac.uk/burks/foldoc/67/111.htm
[1.10] BITSYS: Operating Systems Lecture Notes http://ironbark.bendigo.latrobe.edu.au/subjects/bitsys/ oslect/lectlist.html [1.11] Curso de sistemas operativos Crysoft http://crysoft.com/cursos/endetalle.asp?pide=sisope
[1.21] Notas del Curso MATE 4096- Estructura de un Sistema Operativo http://cuhwww.upr.clu.edu/~jse/cursos/4096/notas/n4 096c04.html [1.22] Tornado operating system http://www.eecg.toronto.edu/parallel/tornado.html
33
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar [1.23] Operating System Basics/Architecture
[1.27] Apple history.com
Kurt Hudson & Andy Ruth. Published: July 1999
http://www.apple-history.com/frames/?
http://www.windowsitlibrary.com/Content/175/09/toc.h tml
[1.28] Old computers.com http://www.old-computers.com/
[1.24] X Window System Architecture Overview HOWTO Daniel Manrique. 2001 http://linuxselfhelp.com/HOWTO/XWindow-OverviewHOWTO/
[1.29] The real history of the GUI http://www.webmasterbase.com/article/511/62 [1.30] Clusters en México
[1.25] The machine that changed the world
http://clusters.unam.mx/Historia/
http://ei.cs.vt.edu/~history/TMTCTW.html [1.31] How to build a Beowulf: tutorial
[1.26] Smithsonian computer history
http://www.cacr.caltech.edu/beowulf/tutorial/tutorial.ht ml
http://americanhistory.si.edu/csr/comphist/comp_botto m.htm
34
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Capitulo 2. Funcionamiento básico de un sistema operativo La mayoría de las ideas fundamentales de la ciencia son esencialmente sencillas y por regla general pueden ser expresadas en un lenguaje comprensible para todos. Albert Einstein
Una de las preguntas más sencillas y comunes que podemos hacernos, es ¿cómo funciona un sistema operativo?, la cual no tiene una respuesta trivial si tomamos en cuenta todos los elementos relacionados en su funcionamiento. En esta sección se trata de dar una respuesta que contemple todos los aspectos involucrados, tanto del hardware (donde se ejecuta el SO), como del software (el propio SO) en la etapa específica en la que el SO toma control del hardware; el funcionamiento de los componentes específicos del sistema se expone en los capítulos 3, 4 y 5. Este escenario es básico, pues es lo mínimo indispensable que debe conocerse para construir un sistema operativo. Debe aclararse que mucho del material de este capítulo se basa en hardware de arquitectura secuencial y en específico de PCs (Intel), así como la interacción del software a bajo nivel, lo cual es un proceso bastante genérico para casi todos los sistemas existentes. No se tratan cuestiones del funcionamiento de servicios más sofisticados como conectividad con redes o almacenamiento secundario. La idea es mostrar como el SO toma control del hardware y establece las funciones básicas para ejecutar e implementar servicios más complejos. En las siguientes secciones se explica el funcionamiento de la unidad central de procesamiento (CPU) y la memoria, y los mecanismos de comunicación entre los componentes de hardware (la descripción está hecha en base al comportamiento y componentes de una computadora personal, que es lo más usado en estos días), para después explicar a detalle el funcionamiento del sistema operativo.
2.1
El hardware y la ejecución de programas⊕
La función principal de una computadora es ejecutar programas, por lo que primero debe entenderse el funcionamiento del hardware de la computadora. Citando a Von Neumann, "para que un sistema de computo sea eficiente y de propósito general, debe tener una unidad central aritmética, una unidad central de control que orqueste todas las operaciones, una memoria, una unidad de entrada y otra de salida".
⊕
Obras consultadas: [2.1] [2.2]
35
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 2.1 Modelo de Von Neumann. Un sistema mínimo de hardware está compuesto por un procesador(CPU) que ejecuta las instrucciones provenientes de una memoria de código (ROM), utilizando posiblemente una memoria de datos (RAM), e interactuando con dispositivos de entrada y salida (E/S), como teclado, monitor, discos, etc. Para comunicar a los distintos componentes, se utilizan un conjunto de cables por los que circulan los datos de un dispositivo a otro, o de un dispositivo a la memoria y/o CPU, llamados buses (fig.2.2). No hay que olvidar dos componentes esenciales: el reloj (que es un mecanismo de sincronización) y la alimentación (que es la que provee de energía a los componentes).
Figura 2.2 El procesador y demás dispositivos se conectan por medio de enlaces físicos conocidos como buses. En las siguientes secciones se detalla el funcionamiento del CPU (o microprocesador), la memoria y los mecanismos mediante los cuales se ejecutan los programas.
2.1.1 La unidad central de procesamiento⊕ El CPU (encarnado físicamente en un chip llamado microprocesador) ejecuta una colección de instrucciones de máquina que le dicen al procesador que hacer. Puede haber cosas muy sofisticadas que un microprocesador pueda realizar, pero en general 3 son sus actividades básicas:
⊕
Obras consultadas: [2.10]
36
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
•
Usar su Unidad Aritmético/Lógica (ALU). Un microprocesador puede realizar operaciones matemáticas como suma, resta, multiplicación y división. Los microprocesadores modernos contienen procesadores completos de punto flotante que pueden realizar operaciones muy sofisticadas en grandes números de punto flotante.
• •
Un microprocesador puede mover datos de una dirección de memoria a otra Un microprocesador puede hacer decisiones y saltar a un nuevo conjunto de instrucciones en base a dichas decisiones.
Figura 2.3 Modelo de un microprocesador simple1 El procesador de la Figura 2.3 tiene: • un bus de direcciones (que puede ser de 8, 16 ó 32 bits de ancho) que envía una dirección de memoria • un bus de datos (que puede ser de 8, 16 ó 32 bits de ancho) que puede enviar datos a la memoria o recibir datos de la memoria • una línea de lectura RD (Read) y una de escritura WR (Write) para decirle a la memoria agregar u obtener el contenido de una dirección de memoria • una línea de reloj que permite que un pulso de reloj mantenga la secuencia del procesador. • una línea de reinicio (reset) que inicializa el contador de programa a cero y reinicia la ejecución. y sus componentes son: • •
1
Los registros A, B y C son simplemente registros hechos con flip-flops. El registro de dirección es como los registros A, B y C.
Imagen reproducida de [2.10]
37
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
• • • •
El contador de programa es un registro con la habilidad de incrementarse en uno, y poner su estado en cero cuando se le indica. El ALU podría ser tan simple como un sumador de 8 bits, o podría ser capaz de sumar, restar, multiplicar y dividir valores de 8-bits. El registro de prueba (test register) es un registro especial que puede almacenar valores de comparaciones realizadas en la ALU. El registro de instrucción y el decodificador de instrucción son responsables de controlar a todos los demás componentes.
Todo procesador posee un conjunto de instrucciones que puede realizar. Esta colección de instrucciones es implementada como un patrón de bits, y cada uno tiene un significado diferente al ser cargado en el registro de instrucción; una forma de representar estos patrones de forma un poco más legible, es mediante palabras o mnemónicos conocidos como lenguaje ensamblador. Como ejemplo se presenta el conjunto de instrucciones en lenguaje ensamblador del procesador de la figura 2.3: •
LOADA mem - Carga el registro A de la dirección de memoria
• • •
LOADB mem - Carga el registro B de la dirección de memoria CONB con - Carga un valor constante en el registro B SAVEB mem - Salva el registro B a la dirección de memoria
• • •
SAVEC mem - Salva el registro C a la dirección de memoria ADD - Sumar A y B y almacenar el resultado en C SUB - Restar A y B y almacenar el resultado en C
• • •
MUL - Multiplicar A y B y almacenar el resultado en C DIV - Dividir A y B y almacenar el resultado en C COM - Comparar A y B y almacenar el resultado en test
• • •
JUMP addr - Saltar a una dirección JEQ addr - Saltar si igual, a la dirección JNEQ addr - Saltar si no es igual, a la dirección
• • •
JG addr - Saltar si es mayor, a la dirección JGE addr - Saltar si es mayor o igual, a la dirección JL addr - Saltar si es menor, a la dirección
• •
JLE addr - Saltar si es menor o igual, a la dirección STOP - Detiene la ejecución
A continuación se exponen detalles acerca de la memoria y como el CPU ejecuta los programas.
2.1.2 La memoria⊕ El término memoria es técnicamente cualquier forma de almacenamiento electrónico (fig. 2.4). Anteriormente se habló de los buses de datos y direcciones, así como de las líneas RD y WR. Estos buses y líneas conectan tanto a la RAM como a la ROM.
⊕
Obras consultadas: [2.11] [2.15] [2.16]
38
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
La memoria de solo lectura (ROM-Read-Only Memory) es un chip programado con una configuración permanente de bytes predefinidos. El bus de direcciones le dice a la ROM que byte obtener para colocarlo en el bus de datos. Cuando cambia el estado de la línea RD, la ROM coloca el byte seleccionado en el bus de datos. La memoria de acceso aleatorio (RAM - Random Access Memory) contiene bytes de información y el microprocesador puede leer o escribir esos bytes dependiendo de la línea que este señalada (RD o WR). Un problema de los actuales chips de RAM es que "olvidan" todo una vez que no hay energía; esa es la razón de que las computadoras necesiten una ROM. El ancho de los buses determina la capacidad de bytes de memoria que pueden ser direccionados, es decir, la cantidad de memoria del sistema. Por ejemplo en el microprocesador de la figura 2.3, si se tiene un bus de direcciones de 8 bits significa que el procesador puede acceder a 28 = 256 bytes de memoria, y puede leer o escribir 8 bits de la memoria a la vez.
Figura 2.4 El CPU accede diferentes tipos de memoria. Al leer de un medio de almacenamiento permanente (p.ej. un disco duro) o algún dispositivo de entrada (el teclado), la mayor parte de los datos llegan primero a la RAM. Ella almacena entonces piezas de datos que necesiten acceder continuamente en un caché y mantiene ciertas instrucciones especiales en el los registros. Cabe mencionar que es posible crear una computadora sencilla que no contenga RAM (muchos microcontroladores lo hacen incluyendo cierta de cantidad de RAM en el mismo chip), pero por lo general es imposible crear una computadora que no tenga ROM.
2.1.3 Ejecución de programas La ejecución de un programa consiste en el preciso seguimiento de una secuencia de instrucciones de máquina. Puede asumirse que todas las instrucciones necesarias para que un programa se ejecute están contenidas en la memoria de la computadora, en una secuencia ordenada. Cada instrucción está formada por uno o más bytes que contienen, codificada, la operación a realizar, así como también los datos involucrados en dicha operación. Un programa
39
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
conocido como ensamblador puede traducir estas palabras a lenguaje máquina, para después colocar el resultado en la memoria para su ejecución por medio de otro programa conocido como cargador. /* factorial lenguaje C */ a=1; f=1; while (a 5 the jump to 17 5 CONB 5 6 COM 7 JG 17 8 LOADA 129 // f=f*a; 9 LOADB 128 10 MUL 11 SAVEC 129 12 LOADA 128 // a=a+1; 13 CONB 1 14 ADD 15 SAVEC 128 16 JUMP 4 // loop back to if 17 STOP
//Lenguaje máquina // Asumir a esta en la dir. 128 // Asumir F esta en la dir. 129 Addr opcode/value 0 3 // CONB 1 1 1 2 4 // SAVEB 128 3 128 4 3 // CONB 1 5 1 6 4 // SAVEB 129 7 129 8 1 // LOADA 128 9 128 10 3 // CONB 5 11 5 12 10 // COM 13 14 // JG 17 14 31 15 1 // LOADA 129 16 129 17 2 // LOADB 128 18 128 19 8 // MUL 20 5 // SAVEC 129 21 129 22 1 // LOADA 128 23 128 24 3 // CONB 1 25 1 26 6 // ADD 27 4 // SAVEB 128 28 128 29 11 // JUMP 4 30 8 31 18 // STOP
Tabla 2. Comparación de un programa en lenguaje de alto nivel, ensamblador y código máquina La tabla 2 muestra un programa en lenguaje C, que es transformado por un compilador en lenguaje ensamblador y los códigos de operación correspondientes generados por el ensamblador, que son los que se cargan en memoria (la primera columna corresponde a la dirección de memoria y la segunda al código de la instrucción). Para poder ejecutar un programa (fig. 2.5) es necesario traer cada una de estas instrucciones desde la memoria, hasta un registro de instrucciones (IR) que es interno y no accesible por el programador, en un proceso denominado fetch. Una vez en este IR, la Unidad Lógico-Aritmética (ALU) podrá decodificar esta instrucción, y luego determinar cuales son los datos necesarios.
40
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Estos pasos se llaman decodificación de la instrucción, y decodificación de direcciones, ya que gran parte de los datos están en posiciones de memoria o registros que están representados por direcciones. Luego la instrucción es ejecutada, para finalmente escribirse los resultados en los registros de destino, que en general es el acumulador, y actualizarse las banderas (flags), en lo que se llama almacenamiento del resultado (Write-Back).
Figura 2.5 Esquema de la ejecución de un programa. En resumen, los pasos requeridos son los siguientes: 1. Fetch: Traer instrucción desde memoria hasta el IR (Instruction Register). 2. Decodificar Instrucción: determinar la operación requerida por la instrucción. 3. Decodificar Direcciones: De modo de poder acceder a los datos requeridos para la operación. 4. Ejecutar: Momento en el cual se realiza la operación, y se entrega un resultado. 5. Write-back: Proceso de escribir este resultado en algún registro de destino, como lo es el acumulador. Lo anterior es lo más representativo de la mayoría de los casos, pero existen CPUs que incorporan muchas más etapas, debido a la complejidad de las instrucciones que procesan. La operación se hace más compleja cuando el sistema mínimo integra dispositivos adicionales. En la siguiente sección se analiza la interacción entre los componentes de hardware, donde veremos que hay nuevas consideraciones para la ejecución de instrucciones.
2.1.4 Interacción entre los componentes de hardware⊕ Todos los dispositivos se conectan al BUS por medio de un controlador de entrada/salida. De esta manera dispositivos tales como el teclado, el ratón, o una tarjeta de red pueden producir entradas que deben ser procesadas por el CPU (fig. 2.6).
⊕
Obras consultadas: [2.3]
41
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 2.6 Los componentes de hardware pueden comunicarse con el CPU mediante controladores. El CPU a su vez, se comunica con los dispositivos por medio de instrucciones especiales o de direcciones de memoria concretas. Cada controlador tiene un buffer local, de donde el CPU recoge y envía datos. Pero, ¿cómo se puede enterar el CPU que los datos están ahí? Existen dos formas: •
El método de polling
•
El uso de señales de interrupción
La idea más simple, que no tiene porque ser la mejor, es que el CPU este comprobando una y otra vez si le han llegado datos. Cuando al fin los encuentre, los procesará. Este método es llamado polling, puesto que la CPU está comprobando el dispositivo continuamente para ver si tiene información de algún dato. Desgraciadamente, aunque el polling es muy simple, es también muy poco eficiente. El CPU está desaprovechando su tiempo en espera de que le llegue la entrada. Una opción más elaborada es el uso de una señal llamada interrupción, que es la forma en que el controlador notifica al CPU de la finalización de una operación o la llegada de nuevos datos. El CPU responde a la señal de interrupción dejando a un lado cualquier cosa que este haciendo para atender a la interrupción. Una vez que ha terminado de atender (handled) la interrupción, continua con lo que estaba haciendo antes de ser interrumpida. Por ejemplo, cuando se presiona una tecla de la computadora, el teclado envía una interrupción al CPU, el cual responde a esta señal interrumpiendo lo que estuviera haciendo, leyendo la tecla pulsada, procesándola, y continuando con la tarea que estaba realizando antes de que la tecla se presionara.
42
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Un evento es normalmente una interrupción de software (llamadas al sistema, división por cero (excepciones)) o hardware (p.ej. terminación de E/S, alarmas del reloj, etc.). Para provocar una interrupción de software existe una instrucción de interrupción específica para cada máquina (INT (Intel); TRAP (Motorola); SYSCALL (MIPS)). Cuando el SO recibe una interrupción, el CPU guarda su estado (incluyendo la dirección de la instrucción interrumpida) y transfiere el control a una posición fijada en la memoria, que es la dirección de la rutina de la interrupción. Después del procesamiento de la interrupción, el SO recupera el estado guardado y la ejecución continua donde fue interrumpida. En concreto, una interrupción es un evento que altera la secuencia en que el procesador ejecuta las instrucciones. Cuando ocurre una interrupción: • •
•
• • •
El sistema operativo toma el control (es decir, el hardware pasa el control al sistema operativo). El sistema operativo guarda el estado del proceso interrumpido. En muchos sistemas esta información se guarda en una estructura llamada bloque de control de proceso interrumpido. El sistema operativo analiza la interrupción y transfiere el control a la rutina apropiada para atenderla; en muchos sistemas actuales el hardware se encarga de esto automáticamente. La rutina del manejador de interrupciones procesa la interrupción. Se restablece el estado del proceso interrumpido (o del "siguiente proceso"). Se ejecuta el proceso interrumpido (o el "siguiente proceso").
Una interrupción puede ser iniciada específicamente por un proceso en ejecución, en cuyo caso se le suele denominar trampa (trap) y se dice que está sincronizada con la operación del proceso; o puede ser causada por algún evento que puede estar relacionado o no con el proceso en ejecución, en cuyo caso se dice que la interrupción es asíncrona con la operación del proceso. Esto implica un cambio en el enfoque de la ejecución de instrucciones, pues ahora debe atenderse a las interrupciones. Por lo tanto, basándonos en los pasos de ejecución de la sección anterior, tenemos la siguiente secuencia ampliada: 1. Fetch: Traer instrucción desde memoria hasta el registro de instrucción (IR) – Ocurre al inicio de cada ciclo de máquina. – Ocasiona que una instrucción de máquina sea traída de memoria principal. – Pasos del ciclo: Se asume que existe un reloj para sincronizar la ejecución. • Tiempo 1: Mover el contenido del PC al MAR. • Tiempo 2: Mover el contenido de la dirección de memoria apuntado por el MAR al MDR. Incrementar el contenido del PC en uno. • Tiempo 3: Mover el contenido del MDR al IR. 2. Decodificar Instrucción: determinar la operación requerida por la instrucción 3. Decodificar Direcciones: De modo de poder acceder a los datos requeridos para la operación – Obtiene los operandos indirectos de la instrucción de máquina. – Objetivo es transformar un direccionamiento indirecto en uno directo.
43
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
4. Interrupciones. – Pueden ocurrir al finalizar el ciclo de ejecución. – Se ejecuta si alguna señal de interrupción ha sido emitida. – Objetivo: • • •
Guardar la siguiente dirección a ejecutarse. Pasar el control a la rutina de interrupción. Retornar el control al proceso al terminar la interrupción
5. Ejecutar: Momento en el cual se realiza la operación, y se entrega un resultado. – El número de micro operaciones a ejecutarse no es fijo como en los ciclos de captación, indirecto e interrupción. – La cantidad de micro operaciones depende de la instrucción de máquina. 6. Write-back: Proceso de escribir este resultado en algún registro de destino, como lo es el acumulador. Cuando llega una señal de interrupción al CPU, este suspende su trabajo para ejecutar una rutina de servicio de interrupción (IRS o RSI). Antes de ejecutar dicha rutina, debe guardarse el estado del procesador, para que pueda continuar con sus actividades después de ejecutar la RSI. Debe recordarse que todo esto es un proceso puramente mecánico. La señal de interrupción del dispositivo, simplemente envía una señal por un cable. El CPU está construido para que cuando se reciba una señal por ese cable, guarde la información que está manejando en ese momento, y pueda volver a ese estado más tarde. Esa información consiste en el contenido de los registros internos importante como pueda ser el contador de instrucciones (PC). El CPU salta a una dirección de memoria predeterminada y ejecuta las instrucciones allí almacenadas. Estas instrucciones forman el manejador de interrupciones y definen el proceso necesario a realizar para responder a la interrupción. (El manejador de interrupciones, es parte del driver del dispositivo que ha activado la interrupción). Al final del manejador de interrupciones, hay una instrucción que hace que la CPU realice un salto hasta donde estaba antes, restaurando previamente los datos guardados. Una pregunta lógica de este proceso es: ¿cómo se identifica al dispositivo que lanzó la interrupción? Para ello se tienen dos opciones: preguntar a todos los dispositivos (polling) o que el dispositivo envíe un numero (su identificador) por el bus (interrupciones vectorizadas). En el segundo caso, el CPU usa una tabla en memoria con las direcciones de las distintas RSI que puede ejecutar (por lo tanto el numero enviado por el dispositivo es el índice en el vector de interrupciones). Las interrupciones permiten al CPU trabajar con eventos asíncronos. Durante el ciclo regular de leer-y-ejecutar, las cosas ocurren en un orden predeterminado, todo lo que pasa, esta sincronizado con todo lo demás. Las interrupciones hacen posible que el CPU pueda tratar eficientemente las cosas que pasan de manera asíncrona, esto es, en momentos impredecibles. Un ejemplo del uso de las interrupciones, es lo que pasa cuando el CPU necesita acceder a datos almacenados en el disco duro. El CPU solo puede acceder directamente a los datos si están
44
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
almacenados en la memoria principal. Los datos del disco, han de ser trasladados a memoria antes de que puedan ser accedidos. Desafortunadamente, en la escala de velocidades en las que opera el CPU, el disco es extremadamente lento. Cuando el CPU necesita datos almacenados en disco, envía una señal para indicarle al manejador del disco donde esta la información, y que esta preparada para recibirla. Esta señal es enviada en forma sincronizada, bajo el control de un programa normal. Entonces, en vez de quedarse esperando una importante e impredecible cantidad de tiempo a que el disco lo haga, el CPU se dedica a alguna otra tarea. Cuando el manejador del disco tenga los datos disponibles, enviara una señal de interrupción al CPU y el manejador de interrupciones, leerá los datos solicitados en forma asíncrona.
Tipos de interrupciones Existen tres tipos de interrupciones que pueden encontrarse en una computadora: a. Interrupciones internas de hardware. Las interrupciones internas son generadas por ciertos eventos que surgen durante la ejecución de un programa. Este tipo de interrupciones son manejadas en su totalidad por el hardware y no es posible modificarlas. Un ejemplo claro de este tipo de interrupciones es la que actualiza el contador del reloj interno de la computadora, el hardware hace el llamado a esta interrupción varias veces durante un segundo para mantener la hora actualizada. Aunque no podemos manejar directamente esta interrupción (no podemos controlar por software las actualizaciones del reloj), es posible utilizar sus efectos en la computadora para nuestro beneficio, por ejemplo para crear un "reloj virtual" actualizado continuamente gracias al contador del reloj interno. Únicamente debemos escribir un programa que lea el valor actual del contador y lo traduzca a un formato entendible para el usuario. b. Interrupciones externas de hardware. Las interrupciones externas las generan los dispositivos periféricos, como pueden ser: teclado, impresoras, tarjetas de comunicaciones, etc. También son generadas por los coprocesadores. No es posible desactivar a las interrupciones externas. Estas interrupciones no son enviadas directamente al CPU, sino que se mandan a un circuito integrado cuya función es exclusivamente manejar este tipo de interrupciones. c. Interrupciones de software. Las interrupciones de software pueden ser activadas directamente por el ensamblador invocando al número de interrupción deseada con la instrucción INT. El uso de las interrupciones nos ayuda en la creación de programas, utilizándolas nuestros programas son más cortos, es más fácil entenderlos y usualmente tienen un mejor desempeño debido en gran parte a su menor tamaño. Este tipo de interrupciones podemos separarlas en dos categorías: las interrupciones del sistema operativo y las interrupciones del firmware (p.ej. el BIOS (Basic I/O System)). Ya con la perspectiva de como opera el hardware de la computadora, ahora pasaremos a revisar lo que hace el sistema de software conocido como sistema operativo.
45
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
2.2
Software para el control del hardware⊕
Para que el software administre los elementos clave del hardware debe por lo menos desempeñar las siguientes cuatro funciones: • •
• •
Ejecución de programas. Asignación de recursos del sistema - La habilidad de organizar y asignar memoria, canales IRQ's (Interrupt Request Channels), canales DMA's (Direct Memory Access channels), etc. a los programas y al propio sistema operativo. Administración de archivos (I/O) - La habilidad de crear, almacenar y consultar archivos. Acceso a dispositivos - La habilidad para comunicarse con los diferentes dispositivos de entrada y salida conectados al procesador.
Figura 2.7 Software relacionado al control del hardware. En las siguientes secciones se analizarán los componentes de software que están relacionados al control del hardware y que conforman al sistema operativo (fig. 2.7).
2.2.1 El papel del BIOS En 1973, cuando afrontó la posibilidad de portar su recién elaborado sistema operativo CP/M, a un número cada vez mayor de diseños de computadoras personales que aparecía en esa época, Gary Kildall tuvo la gran idea de separar del Sistema Operativo la parte de código específica para la plataforma de hardware. De esta forma reducía drásticamente la cantidad de tiempo necesaria para crear una nueva versión de CP/M. ⊕
Obras consultadas: [2.4] [2.5]
46
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
La parte de código del SO para una máquina específica, hablaba directamente con el hardware de la computadora y ofrecía una serie de servicios genéricos, en forma de manejadores de interrupciones (interrupt handlers), al resto del sistema operativo. A partir de esto, el SO podía hacer una petición de un servicio (como el acceso a un archivo en un disco) sin preocuparse sobre los detalles de como el servicio se llevaba a cabo. La parte especifica de control y descripción de la máquina en el SO, llamada BIOS (Basic Input and Output System), podía manejar los accesos específicos de un disco duro de 20Mb ó un floppy de 720Kb. La decisión original de Gary Kildall de dividir (por conveniencia) su sistema operativo en dos partes, el BIOS específico del hardware y el SO independiente del hardware es un modelo que ha permanecido desde entonces. Cuando IBM tomó la decisión de desarrollar rápidamente una computadora personal, la premura de los tiempos de desarrollo requirió del uso de una arquitectura abierta, es decir, del uso de partes estándares de la industria para la PC (el microprocesador, los chips de memoria, las unidades de disco, etc.). Estas mismas partes estaban disponibles para otros fabricantes y su funcionamiento era bien comprendido. Donde IBM esperaba mantener su liderazgo sobre otros fabricantes, era en su habilidad de comprar grandes cantidades de estas partes, a precios más baratos y en su BIOS propietario. La forma en que estaba implementado el manejo de interrupciones del BIOS de IBM era ultra secreto. Para que el software escrito por otros fabricantes de PC fuera realmente compatible con la PC IBM, tendría que hacer las mismas peticiones de servicios exactamente igual que el software de IBM. El BIOS en una PCs está comprimido en una serie de chips, integrados en la tarjeta madre, con instrucciones (hardwired) para acceder los diversos dispositivos conectados a la PC y para cargar el resto del código del sistema operativo; este se complementa con un chip CMOS (Complementary Metal Oxide Semiconductor) reescribible capaz de almacenar la configuración del hardware definida por el usuario. En la siguiente sección se detalla el contenido de los servicios del BIOS.
Rutinas del BIOS Las rutinas de software contenidas en el BIOS pueden dividirse en cuatro categorías: 1. Rutinas de arranque (Start-Up Routines) 2. ROM BIOS 3. ROM Basic 4. ROM Extensions 1. Rutinas de arranque (Start-Up Routines) Las rutinas de arranque del BIOS son responsables del POST (Power-On Self Test) o auto-prueba de encendido; el proceso con el que la computadora prueba el estado de su hardware. De forma secundaria, estas rutinas inicializan la memoria y crean (en memoria) la tabla del vector de interrupciones (Interrupt Vector Table) inicial y una tabla con la lista del equipo. Ambas tablas son referidas (y en algunos casos alteradas) durante el proceso de BOOT subsecuente. Por último, las rutinas de arranque colocan en memoria la primera de varias rutinas de carga (bootstrap loader) en memoria. El propósito de este cargador es simplemente examinar el primer sector de la primera unidad de disco,
47
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
en busca de una firma que identifica a la unidad como de arranque (bootable drive) y además hasta una segunda (y posiblemente una tercera) rutina de carga que de hecho carga el primer archivo del sistema operativo. 2. ROM BIOS El ROM BIOS contiene las rutinas de software que permiten el acceso rudimentario a los dispositivos. Estas rutinas son por lo general, cargadas en memoria durante el proceso de boot, donde pueden ser accesadas más rápido. Algunas de estas rutinas permanecen en memoria como destinos de la tabla del vector de interrupciones, mientras otras son reemplazadas por rutinas más sofisticadas, al cargarse el sistema operativo. 3. ROM Basic Incluido en los primeros BIOS para dar soporte al lenguaje de programación BASIC. No se uso mucho durante versiones posteriores. 4. ROM Extensions Las rutinas en el BIOS fueron diseñadas para ser extendidas al aparecer nuevos dispositivos. Esto fue manejado con la implementación de las extensiones del ROM BIOS. Leídas en el arranque durante la fase de inicialización, estas rutinas proveen soporte de bajo nivel a nuevos dispositivos y comúnmente reemplazan algunos elementos de la tabla del vector de interrupciones. En la siguiente sección se analizan con más detalle los procesos de POST y BOOT.
Secuencia de arranque
Además de servir como un intermediario entre el hardware de la computadora y el sistema operativo, el BIOS también sirve para probar el hardware durante el arranque de la computadora. La secuencia que se sigue durante el arranque consiste de los siguientes pasos: 1. Encendido físico de la computadora. 2. Power-On Self Test (POST). Almacenado en memoria de solo lectura (ROM) en el chip BIOS se encuentra un pequeño conjunto de instrucciones de software que permiten a la computadora iniciar el proceso de auto-prueba y configuración. Estas instrucciones incluyen una serie de diagnósticos o pruebas de encendido: • Prueba de video: inicializa el adaptador del monitor, prueba la tarjeta de video y la memoria de video y despliega la información de configuración o cualquier error. • •
Identificación del BIOS: despliega la versión del BIOS, fecha y fabricante. Prueba de Memoria: Prueba los chips de memoria. La suma de la cantidad de memoria probada desplegará el total de memoria instalada (hasta puede generarse un sonido mientras la memoria es revisada). Un mensaje de error en esta parte puede indicar una falla en los chips de memoria que requerirán que sean reemplazados.
Los errores ocurridos durante el POST pueden clasificarse como "fatales" o "no-fatales". Un error no-fatal causará que el sistema despliegue el error en pantalla pero puede no impedir que el sistema continúe con el arranque. Un error fatal, detendrá el sistema y evitará que continúe con el proceso. Estos errores son desplegados generalmente por una serie de señales audibles (beep codes). 3. Inicialización del sistema, y revisión del CMOS y el BIOS. Después de un POST exitoso, las instrucciones almacenadas en el BIOS inicializarán el sistema con la configuración almacenada en el CMOS, el cual consiste de una pequeña área de memoria electrónica (64 bytes) donde se guarda información tal como la fecha y la hora, parámetros del disco duro,
48
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
etc. La corriente que alimenta al CMOS es enviada por una pequeña batería dentro de la computadora la cual, mantiene esta información. Las computadoras actuales usan una batería recargable con una vida media de cerca de diez años, mientras que computadoras más viejas usan baterías reemplazables con vida útil de aproximadamente dos años. Las configuraciones en el CMOS son accedidas por medio de un programa de configuración del sistema incluido en el chip BIOS (el cual puede activarse por medio de alguna combinación especial de teclas durante el proceso de arranque. Las direcciones de memoria son también inicializadas durante esta fase. Las direcciones de memoria baja son usadas para almacenar tanto la lista de equipo como la tabla del vector de interrupciones.
El BIOS y el sistema operativo Con la creación del chip BIOS independiente, el SO dejó de ser el principal responsable de acceder el hardware de la computadora. En su lugar, el SO organizó los dispositivos conectados a la computadora, manejando tareas como asignar la memoria y ofrecer un conjunto de de rutinas estándar de software con las cuales los programadores podrían comunicarse con el BIOS y el hardware de la computadora. Estas rutinas, conocidas como interfaces de programación (Application Programming Interface) o APIs del SO, reducen al mínimo que un desarrollador necesite saber sobre el hardware específico para escribir una aplicación de software. Sin embargo, el software se ha desviado de este modelo y se siguen desarrollando programas que hablen directamente con un dispositivo, a causa de la necesidad de velocidad en su acceso. Algunos ejemplos comunes incluyen a las aplicaciones que usan gráficos intensivos (juegos) que requieren acceso rápido a las capacidades del dispositivo de salida (monitor y tarjetas de gráficos). Recientemente, con la aparición de sistemas operativos de 32-bits como Windows 95/98/2000, el SO de nuevo está tomando la responsabilidad de comunicarse directamente con los dispositivos. El BIOS provee las líneas básicas de comunicación que permiten cargar el sistema, pero las rutinas de 32 bits incrementan la velocidad de acceso a la que el SO puede leer o escribir a los dispositivos. Un número creciente de funciones en las APIs ignoran al BIOS para acceder al hardware directamente. El BIOS mantiene su importancia primaria de proveer compatibilidad con software más antiguo.
2.2.2 Cargador del sistema Como se mencionó en la sección de "Funcionamiento del CPU", para que un programa se ejecute es necesario llevar sus instrucciones a la memoria, y un sistema operativo no es la excepción; el módulo de carga es esencial para que el sistema inicie su funcionamiento. En casi todos los casos, el SO es la primera pieza de software que comienza a ejecutarse después de que el hardware ha terminado el POST (Power On Self Test) o el BIST (Built In Self Test). Este software por lo general es colocado en una dirección predeterminada de memoria (que puede ser en RAM, ROM o disco) a la cual es transferido el control automáticamente.
49
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Este procedimiento es llamado BootStrapping (o booting). El área donde se encuentra el código de inicio es muy pequeña (típicamente un sector de disco). La responsabilidad primaria del código en esta área es activar los servicios esenciales del sistema operativo. Este código es llamado cargador (loader), y su responsabilidad principal es cargar el núcleo del sistema operativo en memoria (lo que también implica transferirle el control). Un ejemplo de este proceso es el sistema de arranque del JavaOS consiste de 128 KB de código (varia según la implementación), cuyo deber es cargar primero la imagen del núcleo del SO e informarle de la configuración de dispositivos de la plataforma. Los detalles para instrumentar programas de carga desde un disco, se pueden consultar en el Apéndice A.
Carga desde un CD-ROM⊕
Las unidades de CD-ROM IDE (compatibles con el estándar ATAPI) y las SCSI pueden opcionalmente proveer capacidades de arranque para los usuarios y fabricantes de computadoras personales. En el pasado las computadoras personales intentaban arrancar de una unidad de disco flexible o de un disco duro. La especificación El Torito explica como el procedimiento de arranque del BIOS puede ser mejorado para soportar un nuevo medio: el CDROM. Manteniendo la compatibilidad con el software actual requiere de usar las convenciones de llamada de la interrupción 13 (INT 13) pero dando una nueva interfaz del dispositivo. La INT 13 tiene ciertas restricciones en la información que el CD-ROM contiene y también tiene varias nuevas opciones para arrancar un sistema. La siguiente es una lista de capacidades y restricciones de este sistema: 1. 2. 3. 4. 5.
6. 7.
⊕
El CD-ROM puede arrancar como la unidad A o C. Si el CD-ROM arranca como A, la unidad debe contener imágenes de floppies de 1.2M, 1.4M o 2.88M. Si el CD-ROM arranca como la unidad A, la unidad del sistema A se convertirá en la unidad B. Si el sistema tiene una unidad B se volverá inaccesible. Si el CD-ROM arranca como la unidad C, entonces reemplaza a la unidad C. No se necesitan manejadores de dispositivos para aplicaciones que usen la interfaz INT 13. Esto significa que el software normal compatible con MS-DOS puede acceder al CDROM sin un manejador de dispositivo. Algunos sistemas como Windows, pueden ser configurados para usar la interrupción 13 dándole al usuario beneficios inmediatos de su CD. Dar formato a una parte del CD ROM como disco duro protegido contra escritura es un método sencillo de protección contra copias. Puede protegerse contra copia las porciones no formateadas del disco agregando algunos manejadores especiales de CD-ROM en el CD.
Obras consultadas: [2.6]
50
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Carga por medio de conexión en red⊕
Existen otro tipo de arrancadores, para máquinas sin disco (las alguna vez llamadas "terminales tontas"), que cargan los archivos necesarios por medio de una conexión en red. El arranque por red (network booting) es una idea vieja. La idea central es que la computadora tenga algún código de bootstrap en memoria no volátil (p.ej. un chip ROM), que le permita el contacto con un servidor y obtenga los archivos del sistema por medio de una conexión de red. Uno de los objetivos es evitar el uso del disco duro para inicializar. Hay varias razones para hacer esto. Una es reducir el costo de mantener software en diferentes máquinas. Con el arranque por red los archivos son administrados en un servidor central y pueden ser actualizados en un solo sitio. Otro objetivo es usar computadoras en sitios donde los discos duros no son lo suficientemente robustos. Por ejemplo, esto podría ser una computadora en el piso de una fábrica donde el disco duro puede ser frágil o estar expuesto a golpes. Finalmente, otro objetivo es tener un sistema que pueda cambiar de sistemas operativos, sin tener que instalar el software. Para poder arrancar sobre una red, la computadora necesita obtener: 1. una identidad 2. la imagen de un sistema operativo 3. un sistema de archivos activo. Consideremos una computadora sin disco (diskless computer -DC) que tiene una ROM de arranque en red, y que puede ser una de varias computadoras idénticas. ¿Cómo podemos distinguir esta computadora de las otras? Hay una pieza de información que es única para esta computadora que es su dirección Ethernet (contenida en su adaptador de red). Cada adaptador Ethernet en el mundo tiene una dirección Ethernet única de 48 bits por que cada a constructor de hardware Ethernet le ha sido asignado un bloque de direcciones. Por convención estas direcciones están escritas en dígitos hexadecimales donde cada dos dígitos se separan mediante dos puntos (p.ej. 00:60:08:C7:A3:D8). Los protocolos para obtener la dirección IP dada una dirección Ethernet, son llamados Boot Protocol (BOOTP) y Dynamic Host Configuration Protocol (DHCP). DHCP es la evolución del BOOTP (de hecho casi todo lo aplicable a BOOTP se aplica también en DHCP). Después de obtener una dirección IP, la computadora debe descargar la imagen de un sistema operativo y ejecutarlo. Para ello se usa otro protocolo de Internet llamado Trivial File Transfer Protocol (TFTP). TFTP es como una versión recortada de FTP; no hay autentificación, y se ejecuta sobre UDP (User Datagram Protocol) en lugar de TCP (Transmission Control Protocol). UDP fue escogido en lugar de TCP por simplicidad. La implementación de UDP en la computadora puede ser pequeña, por lo que el código cabe en una ROM. Cuando todos los bloques se han recibido, la ROM de arranque en red le cede el control al punto de inicio de la imagen del sistema operativo. Finalmente para ejecutar un SO, un sistema de archivos raíz debe proveerse. El protocolo usado por Linux y otros sistemas Unix es ⊕
Obras consultadas: [2.7] [2.8]
51
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
normalmente el Network File System (NFS), aunque otras opciones son posibles. En este caso el código no tiene que residir en la ROM pero puede ser parte del sistema operativo que se descargó. Sin embargo el SO debe ser capaz de ejecutarse con un sistema de archivos raíz que es un NFS, en lugar de un disco verdadero. Linux tiene las variables de configuración requeridas para construir una versión que pueda hacerlo.
2.2.3 Inicio de la ejecución del sistema operativo Para entender como funciona el SO, puede tomarse como punto de partida el análisis de su ejecución, la cual inicia al encender la computadora.
Figura 2.8 Secuencia del inicio de ejecución del sistema operativo. Cuando esto ocurre sucede lo siguiente: a. Primero se ejecuta el programa de arranque (bootstrap) que inicializa todos los aspectos del sistema, como los registros del CPU, controladores de dispositivos, la unidad de administración de memoria, etc. • El programa de arranque es el software alojado en memoria ROM (boot firmware) que controla la computadora desde el momento que se enciende, hasta que el sistema operativo primario toma control de la máquina. La función principal de este software es inicializar el hardware y luego, cargar y ejecutar (boot) el sistema operativo.
52
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
b. Se localiza el sistema operativo (puede ser por medio de una rutina en ROM). •
En el caso de las PCs, estas primeras tareas se hacen con un programa que reside en un chip de memoria llamado BIOS (Basic In-Out System) ROM y que al encender la computadora, ocupa una posición FIJA de memoria en cualquier PC. Suponiendo que el BIOS ya ha inicializado todos los dispositivos de la máquina (asignado las correspondientes IRQs y recursos a los dispositivos), ahora va a proceder a cargar el sistema operativo. Lo más normal es que intente su carga primero desde un disco. Si esta carga falla, lo intenta desde el primer disco duro.
c. Una vez localizado, se carga en memoria por medio de un programa llamado Cargador (Loader). • Generalmente las partes críticas del SO se mantienen en RAM mientras la computadora este encendida. Esto permite al CPU tener acceso inmediato al SO, lo que mejora el rendimiento y funcionalidad de todo el sistema. d. Durante el proceso de carga se instalan todas las RSI en el vector de interrupciones. e. Entonces el SO se ejecuta y espera un evento o bien cede el control a algún programa de
usuario. Un ejemplo de la ejecución inicial de un sistema operativo, es el proceso de carga del MS-DOS. Suponiendo que la carga es desde un disco flexible, el sector de arranque (boot) del disco (el cual es creado con una utilería de formateo), contiene un mini programa que lo único que sabe hacer es buscar un archivo oculto en esa unidad de disco, llamado IO.SYS, cargarlo en memoria y cederle control. •
•
• •
EL IO.SYS inicia la carga y ejecución. Lo primero que busca es otro archivo oculto en la misma unidad llamado MSDOS.SYS. Este archivo no es un archivo de ejecución, sino un archivo de parámetros del sistema que en cualquier momento podemos ver (no es aconsejable tocarlo), con un editor. Mas adelante veremos el posible contenido de este archivo. A continuación el IO.SYS, busca en el directorio raíz de esa unidad un archivo llamado CONFIG.SYS. Sí el archivo existe, lo lee y ejecuta las instrucciones que lleva dicho archivo. Básicamente el config.sys, contiene los parámetros del propio sistema y sobre todo, carga de manejadores de dispositivo. No es obligatorio que exista. Solo si lo encuentra lo ejecuta. A continuación, el IO.SYS, busca el COMMAND.COM, es decir al intérprete de comandos. El COMMAND, busca a su vez la existencia de un archivo llamado AUTOEXEC.BAT también en el directorio raíz de la unidad de arranque y lo lee para ejecutar los comandos que allí existan. Dichos comandos, serian básicamente programas (no pueden ser ya manejadores de dispositivos) y algún parámetro de configuración (como el PATH por ejemplo) propio del interprete de comandos.
53
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
2.2.4 Protección del hardware⊕ Para asegurar el correcto funcionamiento del SO, debe impedirse que los programas de usuario puedan realizar ciertas operaciones: •
Acceso a la memoria del SO y de otros programas
• •
Acceso directo al uso de dispositivos de E/S Uso libre del tiempo de CPU
Además, ciertas instrucciones de la máquina no pueden ser usadas por cualquiera. Por ejemplo, la instrucción de paro (Halt) podría ser peligrosa en manos de usuarios maliciosos o descuidados, por lo que ciertas instrucciones deberían ser usadas solo por usuarios privilegiados. Estas son llamadas Instrucciones Privilegiadas. Por esta razón la computadora ejecutará sus tareas en uno de (por lo menos) dos modos: •
Modo Usuario: Donde las instrucciones privilegiadas no pueden ser usadas; en caso de que se trate de usar una de estas instrucciones el sistema interrumpe la ejecución y genera una excepción.
•
Modo Supervisor (Kernel): Donde todas las instrucciones pueden ser ejecutadas.
Un ejemplo de procesador con modos es el MC6800 [2.19], que define sus modos de la siguiente manera: •
•
El MODO USUARIO conforma un entorno de programación para la ejecución de los programas de aplicación. En este modo no se pueden ejecutar ciertas instrucciones y no se puede acceder a parte del registro de Estado. El MODO SUPERVISOR permite utilizar el juego de instrucciones completo y acceder a todo el registro de Estado, tanto en lectura como en escritura. Se establecen así unos "privilegios" de utilidad en sistemas operativos y software de base de los sistemas.
La protección del uso sin control de las instrucciones de la máquina es consecuencia de la distinción de modo. Cuando se está en modo supervisor, el programa usará un nueva pila (stack), tendrá un vector de estado de programa diferente y acceso a un conjunto de direcciones diferente al de modo de usuario. Al iniciar el CPU se encuentra en modo supervisor. Cuando el SO cede el control a otro programa conmuta previamente a modo de usuario (no privilegiado), y solo se vuelve al modo supervisor cuando ocurre una interrupción, una llamada al sistema o una excepción. La transferencia del modo supervisor a modo usuario ocurre por una instrucción explicita de regreso llamada REI (REturn from Interrupt). Cada transferencia al modo de supervisor a causa de una llamada supervisora debe guardar el estado del emisor, y debería llevar los parámetros del modo en la petición, y debería dársele seguimiento checando la legalidad de dicha petición. El hardware debería ayudar a identificar la causa para la transferencia a modo de supervisor. La transición de modos usuario-supervisor y viceversa debe ser muy eficiente, lo cual no es fácil de hacer pues pueden haber muchos cambios en los espacios de memoria. ⊕
Obras consultadas: [2.17] [2.18] [2.19] [2.21]
54
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
El código ejecutado en modo supervisor es llamado ejecutivo, y una porción de este es el núcleo del sistema. La idea de modos separados e instrucciones privilegiadas ha sido tan exitosa que ya se han encontrado usos para más de dos modos.
Funcionamiento del kernel
El kernel de un SO (los que lo tienen) tiene la responsabilidad de la ejecución del sistema. Es usualmente el kernel el que realiza las tareas de controlar el hardware. En un escenario típico, el kernel realiza inicializaciones de hardware (además de algunas inicializaciones del software como estructuras de datos, etc.) como actualizar el estado del procesador, ajustes del reloj interno, inicialización de dispositivos, etc. Todas estas tareas son muy delicadas, por lo que deben realizarlas programas especializados. La protección (verificación de nivel de confianza del código) usualmente viene del hardware. El hardware reconoce el código por medio de un nivel de privilegio (más alto para el kernel). La regla del pulgar seguida por el procesador es que un código puede siempre disminuir sus privilegios pero no aumentarlos, excepto en algunas condiciones especiales que son determinadas por el código de alto nivel de privilegio (las cuales son llamadas trampas o llamadas al sistema). El kernel puede proveer ciertos puntos de entrada que permitan la ejecución de cierto código en el nivel más alto de privilegio en un punto posterior en el tiempo, y esta facilidad es extensamente usada por el enfoque de manejadores de dispositivos modulares. La forma de proceder es que dependiendo de la configuración del hardware, el kernel decide que código debe ser ejecutado. Este código es cargado de la memoria secundaria a la memoria primaria, y se le asigna un nivel de privilegio equivalente al del kernel (este código puede proceder de la misma forma). Al final de tales inicializaciones, el kernel cambia su nivel de privilegio a un valor menor y levanta el código que realiza el trabajo de interacción con el usuario.
2.3
Comentarios ⊕
Con respecto a la protección del hardware mediante el uso de modos, vale la pena comentar que el principal atributo que distingue a los kernels monolíticos y micro-kernels es lo que sus respectivas arquitecturas implementan en modo supervisor (kernel mode) de la CPU y lo que se implementa en el modo usuario (user mode) de la CPU.
⊕
Obras consultadas: [2.22]
55
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
La arquitectura monolítica implementa todos los servicios del sistema operativo (controladores de dispositivos, memoria virtual, sistema de archivos, comunicación en redes, etc.) en el espacio dominado por el modo supervisor de la CPU. En cambio, la arquitectura micro-kernel hace una división entre los servicios del sistema operativo dividiéndolos en "alto-nivel" implementados en el espacio dominado por el modo usuario y "bajo nivel" implementados en el espacio dominado por el modo supervisor. Ya contando con un panorama de las principales consideraciones relacionadas al funcionamiento de un sistema operativo, en el siguiente capítulo se exponen algunos conceptos sobre simulación de sistemas, en específico de sistemas operativos.
56
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
2.4
Obras consultadas
[2.1] DESDE QUE PULSAMOS EL BOTON DE NUESTRO PC HASTA...
[2.11] How computer memory works. Marshall Brain's HowStuffWorks
José Manuel Tella Llop, extraído de microsoft.public.es.windows98
http://www.howstuffworks.com/computer-memory.htm
http://www.duiops.net/windows/articulos/
[2.12] A Designer's Assistant Tool Home Page. Computer Systems Group University of Waterloo.
http://www.duiops.net/windows/tablacw.htm
http://csg.uwaterloo.ca/dptool/ [2.2] How Operating Systems Work. Marshall Brain's HowStuffWorks http://www.howstuffworks.com/operating-system.htm
[2.12] Bootsector authoring. Gareth Owen
[email protected]
[2.3] Sistemas operativos I: Interrupciones del procesador
[2.13] Daniels NASM bootstrap tutorial
http://itver.edu.mx/so1/24.htm
Daniel Marjamäki.
[email protected]
[2.4] CSC 277- Operating Systems (handouts). Michael Lynch http://www.qvctc.commnet.edu/classes/csc277/handou ts.html
http://www.nondot.org/sabre/os/files/Booting/nasmBoo t.txt [2.14] Operating system design & implementation – tutorial. Dr. Mohan Raj Dhanagopal. http://www.ansawide.com/josh/index.htm
[2.5] Introduction to Operating Systems. Kathryn S. McKinley. University of Massachusetts .Fall 1997 http://www-aml.cs.umass.edu/~cs377/ [2.6] "El Torito" : Bootable CD-ROM Format Specification Version 1.0. Curtis E. Stevens (Phoenix Technologies), Stan Merkin (IBM) January 25, 1995.
[2.15] La memoria http://fismat.umich.mx/~htejeda/introduccion/inf003.ht ml [2.16] Funcionamiento del bus de direcciones http://www.pchardware.org/buses/busfunci.php [2.17] Contexto de un proceso
[2.7] RFC Repository. Ross Finlayson. Bootstrap Loading using TFTP. RFC 906, NIC, June, 1984
http://labsopa.dis.ulpgc.es/psis/gesproc/Expo%20conte xto%20de%20un%20proceso.htm
RFC 951 (Croft & Gilmore, Septiembre 1985). BOOTSTRAP PROTOCOL (BOOTP)K. R. Sollins, Noel Chiappa. The TFTP Protocol. RFC 783, NIC, June, 1981. http://www.cis.ohiostate.edu/hypertext/information/rfc.html [2.8] An Introduction to Network Booting and Etherboot. Ken Yap. http://www.linuxfocus.org/English/index.html
[2.18] Memoria virtual http://www.multingles.net/docs/memoria_virtual.htm [2.19] EL µPROCESADOR 68000 http://www.ii.uam.es/~fjgomez/68000/tutorial/cap1.ht ml [2.20] Sistema operativo UNIX http://www.arrakis.es/~ofafian/unix-lec1.html
[2.9] JavaOS: Thin Client, Fat Service. Charles Mirho
and Tom Clements .Byte. July 1997.
[2.21] Estructura de los sistemas operativos
http://www.byte.com/art/9707/sec4/art4.htm
http://bari.ufps.edu.co/personal/150802A/estructura.ht m
[2.10] How Microprocessors Work. Marshall Brain's HowStuffWorks
[2.22] Linux FAQs
http://www.howstuffworks.com/microprocessor.htm
http://www.angelfire.com/ar/favaloro1/faqs3.html
57
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
58
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Capitulo 3. Simulación de Hardware y Sistemas Operativos Escucho y olvido, veo y recuerdo, hago y comprendo. Proverbio chino
Largo es el camino de la enseñanza por medio de teorías; breve y eficaz por medio de ejemplos. Séneca
El esfuerzo de utilizar las máquinas para emular el pensamiento humano siempre me ha parecido bastante estúpido. Preferiría usarlas para emular algo mejor. Edsger Dijkstra
Es muy interesante que algunos autores citen la posibilidad de simular un sistema operativo, así que en este capítulo se tratará de implementar uno propio para entender los conceptos e ideas que se han expuesto hasta el momento. Tal vez parecería que aun no se han tratado los temas suficientes como para emprender un esfuerzo de este tipo, pero cabe aclarar que no se quiere simular un Windows o un Linux, sino entender las funciones más primitivas del sistema, es decir: •
qué se requiere para ejecutar un programa
• • •
cómo se controla el hardware cómo funciona la secuencia de arranque cómo funciona un cargador del sistema
Para ello el principal elemento a simular es el hardware. Es un hecho que la complejidad de instrumentar un sistema operativo es considerable, pero al parecer del autor debe ser más fácil entender como funciona un SO, si se tiene la experiencia de modelar los componentes de más bajo nivel. Adicionalmente se trata el tema de la simulación de SOs por dos razones: 1. Ya existen programas que instrumentan modelos de sistemas operativos y que permiten que pueda entenderse su funcionamiento. 2. El enfoque de simulación de sistemas, es una herramienta con la que pueden modelarse algunos de los subsistemas expuestos en los capítulos anteriores, y que puede ser un enfoque alternativo a la construcción de un sistema operativo, con fines de entender y experimentar en la parte de diseño.
59
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
En los apéndices se ha incluido como caso de estudio el código del simulador propuesto en este capítulo (apéndice B).
3.1
La simulación en el diseño de sistemas operativos⊕
La simulación, es un método científico no obstructivo de estudio que involucra experimentos con un modelo en lugar de la porción de la realidad que el modelo representa. La simulación es no obstructiva por que no perturba el objeto de estudio (excepto tal vez cuando un actor aplica sus resultados). A pesar de que mucha de la información provista por la simulación esté ya contenida en el modelo, la simulación es útil cuando gran cantidad de partes interactúan con muchas rutas que necesitan ser rastreadas simultáneamente, lo que requiere realizar una gran cantidad de iteraciones para aproximarse a los resultados. El poder generar una historia sintética de procesos dinámicos y poder manipular los eventos y condiciones del modelo es lo que hacen de la simulación una técnica idónea para el diseño de sistemas operativos, como se verá más adelante. Aún cuando se considera que una implantación real es la única forma de comprobar la eficacia de un diseño, en el caso de los sistemas operativos, la simulación ha sido aplicada por varios grupos de trabajo. Aún cuando Silberschatz menciona en su tercera edición de Conceptos de sistemas operativos (pp. 126) que "las simulaciones pueden ser muy caras, al requerir horas de tiempo de computo, y más cuando se desea mucho detalle", es claro que con el poder de las actuales computadoras, y lo que está por venir, las consideraciones de recursos pueden quedar en un segundo plano. Entre los principales simuladores de SOs destacan: a. NachOS (Berkeley). Nachos es un sistema instruccional para la enseñanza de cursos de sistemas operativos. La distribución de Nachos contiene: - el código base para un SO operacional - un simulador de una computadora genérica Los temas ilustran y exploran todas las áreas de los sistemas operativos modernos, incluyendo hilos (threads) y concurrencia, multiprogramación, llamadas al sistema (system calls), memoria virtual, tablas de translación de direcciones virtuales a físicas (TLB), sistemas de archivos, protocolos de red, llamadas remotas a procedimientos (remote procedure call), y sistemas distribuidos. b. SimOS. Simula el hardware de una computadora con detalle suficiente para cargar y ejecutar sistemas operativos comerciales, además de proveer un ambiente completo de análisis de ejecución y carga de trabajo (workload). c. RCOS. Está diseñado para demostrar los principios generales de los sistemas operativos por medio de animación controlada. Básicamente es una herramienta diseñada para ayudar a la gente a comprender el funcionamiento interno de un sistema operativo. RCOS es un sistema operativo multitarea que se ejecuta en hardware simulado, el cual esta basado en la máquina P ⊕
Obras consultadas: [3.1] [3.2] [3.22] [3.23] [3.24]
60
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
(P-Machine), un sistema de computo hipotético simple. Incluye un compilador de C/C++ que genera P-Code que puede ejecutar la máquina P. d. SOS (Simple Operating System Simulator). El libro "Operating Systems: A Design-Oriented Approach" (Charles Crowley, Irwin, 1997) contiene el código (C++) para un sencillo sistema operativo llamado SOS, el cual se ejecuta en una plataforma de hardware llamada CRA-1, la cual es una máquina RISC simple. e. Flux OSKit (Utah). Es una plataforma con un conjunto de 34 librerías de componentes que facilita la creación de un nuevo sistema operativo portando un SO existente a otra plataforma (p.ej. x86), ampliar el soporte de dispositivos, formatos de sistemas de archivos, formatos ejecutables, o servicios de red; así como construir programas relacionados, como cargadores o servidores montados sobre un microkernel.
Figura 3.1a Esquema de la arquitectura del FLUX OSKit2 Las librerías contienen el código nativo del OSKit, código para integrar subsistemas y código legado (fig. 3.1a). La funcionalidad del OSKit se divide en tres categorías: interfaces, librerías de funciones y librerías de componentes. Las interfaces proveen el “pegamento” nuevos componentes a un SO. Las librería de funciones proveen servicios básicos de bajo nivel (manejo de memoria, carga de programas, manejo de interrupciones, etc.). Las librerías de componentes proveen funcionalidad de alto nivel (administración de memoria y procesos, soporte POSIX, sistemas de archivos, comunicaciones en red, multimedia, etc.). f. Palm OS Simulator. Es el simulador del Palm OS 5.0; no es una emulación del hardware como el PalmOS Emulator, sino el sistema operativo real ejecutándose sobre una DAL (capa de abstracción de dispositivos). Se usa más como herramienta para validar los posibles errores y 2
Imagen reproducida de [3.24]
61
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
compatibilidad de las aplicaciones en dispositivos PDA que tengan esta versión del sistema (que en el momento en el que lo descubrí, es una versión de prueba del sistema que esta compañía liberará, por lo que su estrategia para con los desarrolladores resulta sumamente útil). Se recomienda su uso en conjunto con el emulador para asegurar una buena compatibilidad de los desarrollos.
Figura 3.1b Esquema de la arquitectura del Palm OS3 Por lo anterior, puede decirse que los objetivos de la simulación de sistemas operativos son: • •
entender el funcionamiento interno de un SO determinación de cargas de trabajo del SO en un procesador especifico (SimOS)
•
diseño de nuevas arquitecturas de SOs
A estos puede agregarse Migración de sistemas operativos. Dado un sistema con una arquitectura modular, podría seleccionarse un subconjunto de módulos tales que puedan formar una nueva distribución del meta conjunto de módulos (algo similar a lo que ocurre con las distintas distribuciones de Linux actualmente), portarla a una arquitectura especifica, soportar un rango mas amplio de dispositivos y servicios. Desarrollo de SOs basado en componentes, de forma que puedan probarse nuevos kernels, servidores, manejadores, cargadores, etc. en diferentes condiciones y configuraciones (podría ser el inicio para una herramienta RAD) Un ejemplo de esto es la propuesta del OSKit con un enfoque basado en componentes, donde los diseñadores de SOs se beneficiarían de las técnicas de ingeniería de software como la orientación a objetos y excepciones, tal como los desarrolladores de aplicaciones lo hicieron en la década de los noventas. Algunos de los enfoques de los simuladores existentes se orientan a: • • •
3
Modelar componentes aislados de los SOs Modelos estáticos de SOs Simulación de hardware para ejecución de nuevos modelos de SOs
Imagen reproducida de [3.22]
62
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Este último enfoque es tal vez el más flexible y más complejo a la vez. En la siguiente sección se presentan los fundamentos de la simulación de hardware.
3.2
Emulación y Simulación de hardware⊕
Si en el proceso de diseño de un modelo de simulación de sistemas operativos, se opta por modelar el hardware en el que se ha de ejecutar, es necesario revisar los enfoques que pueden utilizarse para hacerlo. Para ello, podemos citar dos técnicas principales: La Emulación, que es un intento de imitar el diseño interno de un dispositivo. Por ejemplo, un programa que imite el hardware de las "maquinitas" (arcade) de Pacman, y ejecute una ROM de Pacman real en él, es un emulador. La Simulación, que es un intento de imitar las funciones de un dispositivo. Un juego de Pacman escrito para una PC que usa gráficos similares a la máquina del juego original, es un simulador. Ambos enfoques son presentados en las siguientes secciones.
3.2.1 Emulación de hardware Cuando una computadora trata de emular a otro procesador (tal como la PowerPC trata de emular un 80486), algunas traducciones de código deben suceder antes de que cualquier programa pueda ser ejecutado en el emulador. Referirse a la traducción de código, implica que el procesador huésped (p.ej. PowerPC) y el procesador invitado (p.ej. 80486) son diferentes, por lo que tienden a efectuar sus operaciones de maneras distintas. Estas "maneras" de ejecutar operaciones son conocidas como instrucciones, y puesto que ambos chips tienen diferentes conjuntos de instrucciones, el software de emulación debe encontrar una forma de resolver las diferencias entre ambos. Existen 3 esquemas básicos que pueden ser usados para un emulador (y pueden ser combinados para un mejor resultado): 1. Interpretación. Un emulador lee código emulado de la memoria byte a byte, lo decodifica, y realiza los comandos apropiados en registros emulados, memoria y entrada/salida. El algoritmo general para tal emulador es el siguiente pseudocódigo: mientras(CPUEnEjecucion) Fetch OpCode Interpretar OpCode }
⊕
{
Obras consultadas: [3.3] [3.4] [3.5]
63
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Las virtudes de este modelo incluyen la facilidad de depuración, portabilidad, y facilidad de sincronización (simplemente pueden contarse los ciclos de reloj pasados y ligar el resto de la emulación al ciclo actual). La única gran debilidad obvia es el bajo rendimiento. La interpretación toma demasiado tiempo del CPU y puede requerirse una computadora muy rápida para ejecutar el código a una velocidad razonable.
Figura. 3.2 Emulación interpretativa En la figura se muestra el proceso de emulación (interpretativa): A. Las instrucciones del procesador Intel son enviadas al software de emulación. B. El software de emulación traduce las instrucciones Intel a instrucciones Motorola. C. Estas instrucciones son enviadas al procesador Motorola para su ejecución. D. después de que las instrucciones son ejecutadas, son olvidadas. 2. Recompilación Estática. En esta técnica, se toma un programa escrito en el código a emular y se intenta traducir al código ensamblador de la computadora huésped. El resultado será un ejecutable común que puede ejecutarse sin herramientas especiales. Mientras que todo esto suena muy bien, no es siempre posible. Por ejemplo, no es posible recompilar estáticamente código auto-modificable, pues no hay forma de predecir en que se convertirá hasta ejecutarlo. Para evitar tales situaciones, se puede tratar de combinar el recompilador estático con un intérprete o un recompilador dinámico. 3. Recompilación Dinámica. La Recompilación Dinámica es esencialmente lo mismo que la estática, pero ocurre durante la ejecución del programa. En lugar de tratar de recompilar todo el código en un solo intento, se hace al vuelo cuando se encuentra una instrucción CALL o JUMP. Para incrementar la velocidad, esta técnica puede ser combinada con la recompilación estática.
Figura 3.3 Emulación de compilación dinámica En la figura se muestra el proceso de emulación dinámica: A. Las instrucciones del procesador Intel son enviadas al software de emulación.
64
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
B. El software de emulación traduce las instrucciones Intel a instrucciones Motorola, y envía estas instrucciones a un buffer especial donde pueden ser almacenadas y reusadas. C. Las Instrucciones del buffer pueden ser enviadas al procesador Motorola para su ejecución. D. Después de que las instrucciones han sido ejecutadas, pueden ser vueltas a llamar del RAM buffer, por lo que se elimina la necesidad de recompilarlas. Esta emulación es mucho más rápida.
¿Cómo se instrumenta un emulador?
Para escribir un emulador, debe contarse con un buen conocimiento de programación de computadoras (ensamblador y algún lenguaje de alto nivel) y electrónica digital. Los pasos principales son: 1. 2. 3. 4. 5.
Seleccionar el lenguaje de programación a usar. Encontrar toda la información disponible sobre el hardware a emular. Escribir la emulación del CPU u obtener algún código existente para la emulación del CPU. Escribir un prototipo del código para emular el resto del hardware, al menos parcialmente. En este punto, es útil escribir un depurador integrado que permita interrumpir la emulación y ver lo que el programa está haciendo. Puede también necesitarse un desensamblador del lenguaje ensamblador del sistema emulado (hay que escribir un propio si no existe alguno). 6. Tratar de ejecutar programas en el emulador. 7. Usar un desensamblador y un depurador para ver como los programas usan el hardware y ajustar el código del emulador
3.2.2 Simulación de hardware⊕ El problema de simular hardware se origina de tratar de reproducir el paralelismo inherente de los circuitos electrónicos, usando lenguajes de programación que son de naturaleza y diseño secuencial. El fundamento central de cualquier simulador, es el concepto de tiempo, y como los elementos que conforman un componente se comportan a través de él. El enfoque tradicional para simular dispositivos paralelos es tratar a todos los componentes como si estuvieran sincronizados con respecto a la llamada cola global de eventos (global event queue). Esta estructura consiste básicamente de una lista ligada de nodos de tiempo, donde cada nodo tiene un apuntador a una lista de componentes, o eventos, que tienen que ser procesados en el tiempo indicado. Todos los eventos ligados al mismo nodo de tiempo están esencialmente en paralelo entre sí. Cuando un componente produce una salida, todos los componentes que tienen una entrada que depende de la salida son colocados en la cola global de eventos en el nodo que representa el momento en que la señal de salida fue producida. Puesto que los nodos de tiempo son ⊕
Obras consultadas: [3.6]
65
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
secuenciales, los componentes conectados a cada uno de los nodos son simulados y más eventos son planificados para instantes posteriores, reflejando la salida de estos componentes. Esto continua hasta el fin de la cola de tiempos es alcanzado o el tiempo asignado para la simulación se acaba. Un segundo enfoque, las colas de eventos distribuidos, consiste en encapsular una o más colas dentro de lo mismos componentes, por lo que se elimina todos los problemas inherentes de mantener una estructura global. Las colas son distribuidas en el componente y pueden existir en casi cualquier nivel de descripción. Cada cola mantiene la historia de señales que han sido enviadas al componente durante el curso de la simulación y mantiene una lista de todos los componentes que están a la espera de la señal. Por lo tanto, la cola distribuida sirve como un conector entre 2 componentes y también sirve como el medio en que las señales pueden propagarse en paralelo usando un lenguaje secuencial de programación. Con respecto al hardware, las colas de eventos distribuidos representan cables; las señales viajan a través de cables, y los cables conectan a los componentes entre sí. Puesto que las colas y los cables realizan la misma función y están estrechamente relacionados, el concepto de colas distribuidas es mucho más atractivo e intuitivo que una cola global de eventos. Todos los componentes son simulados de la misma manera. En términos de pseudocódigo, el algoritmo podría resumirse como: función simular (componente) mientras (las entradas al componente están listas) hacer incrementar tiempo local del componente si (el componente no tiene subcomponentes) entonces llamar función de proceso virtual de otra forma para cada (puerto de entrada del componente) hacer para cada (elemento en el puerto de salida) hacer ejecutar función simular para el componente de salida fin mientras El simulador no es un reemplazo para un emulador. Un simulador es una herramienta totalmente diferente. Mientras que un emulador permite depurar el software ejecutándolo en un hardware especifico, un simulador permite depurar el software así como entender el microprocesador y el lenguaje de programación.
3.3
Máquinas virtuales⊕
El concepto de máquinas virtuales es usado a menudo en computación para solucionar problemas importantes, pero por lo general estos son transparentes al usuario (son usadas en programas y sistemas operativos). Algunos de estos problemas incluyen: • ⊕
compartir el mismo hardware entre varios programas dividiendo el hardware disponible, Obras consultadas: [3.7] [3.8]
66
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
• •
permitir al software ser "portable" entre varios sistemas operativos, ejecutar viejo software en una computadora más nueva.
El término "virtual" ha evolucionado para describir casi cualquier cosa que sea una simulación de un objeto real, con términos como memoria virtual, discos virtuales, y realidad virtual. En el caso de las máquinas virtuales se desea que estas se vean y comporten exactamente como una máquina real. Esto significa que la máquina virtual no es realmente de hecho una máquina, pero se comporta exactamente como una verdadera. Todas las máquinas tienen una cosa en común, ya sea un microondas, un refrigerador, una reproductora de video o una computadora; todas ellas están diseñadas para llevar a cabo ciertos tipos de conjuntos de instrucciones. Los conjuntos de instrucciones, pueden ser concebidos para cualquier máquina como piezas (como las de un rompecabezas o Lego) que al unirlas forman un objeto completo. Con las máquinas, estas piezas son instrucciones, las cuales son usadas para decirle a la máquina que hacer o que tareas realizar. En el caso de las máquinas virtuales, lo virtual se refiere a los conjuntos de instrucciones. Hay muchos tipos de máquinas virtuales, pero lo común entre ellas es la idea de simular un conjunto de instrucciones. Cada máquina virtual usa un conjunto virtual de instrucciones al que el usuario tiene acceso, y después la máquina virtual "mapea" estas instrucciones virtuales a instrucciones reales de la computadora. Hay cuatro corrientes principales en esta área: a. La primera es un mapeo (casi) uno a uno (representado por el modelo de máquina virtual de IBM). b. La segunda consiste de un mapeo de cada instrucción en la máquina con una instrucción virtual (representada por la máquina virtual de Java). c. Los modelos de máquinas virtuales de Unix y OSI representan los últimos dos modelos, los cuales mapean algunas de las instrucciones directamente, y otras son llamadas directas a las funciones del sistema operativo. Los modelos han sido utilizados para resolver problemas como: particionar una máquina (modelo IBM), crear una semi-plataforma independiente para lenguajes de programación (modelo Java), y crear sistemas operativos (modelo Unix y OSI). El poder y éxito del concepto de la máquina virtual viene de brindar a los usuarios la habilidad de acceder y utilizar funciones y dispositivos que son simples combinaciones de conjuntos de instrucciones. La habilidad de proveer una solución virtual a las limitaciones reales de los sistemas de cómputo modernos es una herramienta muy poderosa que continua extendiendo las habilidades de los sistemas modernos.
3.3.1 El sistema P⊕ Un caso interesante relacionado a las máquinas virtuales es el sistema P, el cual está relacionado a RCOS, una de las plataformas de simulación de sistemas operativos que se analiza en las siguientes secciones. ⊕
Obras consultadas: [3.9] [3.10]
67
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
El sistema P es un sistema operativo portable que fue popular en los primeros días de las computadoras personales, a fines de los 1970s y principios de los 1980s. El sistema-P, como Java actualmente, estaba basado en una máquina virtual con un conjunto estándar de instrucciones de "código-p" (p-code es un lenguaje de máquina de bajo nivel para una máquina de pila hipotética llamada máquina-P, que es una imitación del conjunto de instrucciones de la Burroughs Large System) que eran emuladas en hardware diferente, incluyendo el 6502, el 8080, el Z-80, y el PDP-11. En esta forma, un compilador de Pascal que emitía ejecutables de código-p, podía producir programas que podían ejecutarse en los sistemas P en las Apple II, Xerox 820, o una DEC PDP-11. El lenguaje más popular para el sistema P era el UCSD Pascal. De hecho, el sistema operativo del sistema P estaba escrito en UCSD Pascal, haciendo al SO relativamente fácil de portar entre plataformas. Al escribir un interprete de código P en el lenguaje ensamblador nativo de la plataforma y haciendo unos cuanto ajustes mínimos a las funciones del sistema operativo (sistemas de archivos e interacción con el usuario), era posible llevar ejecutables de un sistema y ejecutarlos en una nueva plataforma.
3.4
Plataformas de simulación de Sistemas Operativos
Al principio de este capitulo se mencionó que existen varios proyectos y enfoques en la simulación de sistemas operativos. Para comprender más a fondo como funcionan dichos modelos, se han incluido como casos de estudio: a. Java Operating System Simulator b. NachOS c. RCOS A continuación se exponen brevemente las características de cada uno de estos simuladores.
3.4.1 Java Operating System Simulation∇ Para tratar de responder a la pregunta "¿y cómo se implementa un servicio de planificación?" se presenta el Java Operating System Simulation (una aplicación hecha por Tony Teal que simula colas de planificación para procesos y dispositivos) para analizar cómo funciona la planificación de procesos. Los archivos que lo conforman son: OSProcess.java Representación de una tarea del sistema. OSQueue.java Representación de las colas ready y de E/S. OSDevice.java Representación de un CPU o un dispositivo de E/S. OSSystem.java Contiene 2 objetos Queue y 2 objetos Device.
∇
Para más detalles sobre la administración de procesos y conceptos relacionados consulte el capítulo 4
68
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Si se desean ver algunos detalles de bajo nivel como el intercambio de procesos, puede verse el apéndice "Caso de estudio: Implementación de un microkernel". Hasta el momento se ha establecido que las principales entidades que deben implementarse son: • •
Procesos Colas de procesos
Adicionalmente, puede incluirse a los dispositivos, pues como se mencionó hay procesos que pueden estar relacionados con el uso de los periféricos de la computadora. Sea entonces un sistema que puede contener uno ó más dispositivos (tomando en cuenta al CPU como dispositivo), los cuales tienen asociada una cola de procesos. Cada cola puede implementar un algoritmo de planificación para administrar los procesos creados en el sistema. Aunque una decisión posible es implementar estas colas con estructuras de datos FIFO, el asunto es que dichas estructuras consumen memoria y no son la opción de implementación si lo que se desea es rendimiento y velocidad (además de que lo que deseamos ver es como lo hacen a bajo nivel)
Figura 3.4 Clases y métodos del JOSS. Lo primero que hay que hacer es contar con un bloque de control de proceso, donde se puedan integrar los conceptos de identificador de proceso (ID), prioridad, tiempos de respuesta y un apuntador al proceso siguiente. public class OSProcess extends Object { int id;
69
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar int int int int int int int int public
priority; cpu_time_required; cpu_time_slice; cpu_time_total; io_time_required; io_time_total; response_time; time_in; int nextPos; /* next process array index--"pointer" */
...
Hecho esto podemos hablar de la estructura que contendrá y planificará a los procesos. Cada cola debe tener un máximo de procesos que puede atender (esto de forma dinámica tiene que ver con la memoria disponible del sistema) así como implementar un tipo de algoritmo de planificación (esto lo implementa la clase OSQueue). La principal operaciones de una cola de procesos es insertar un proceso en la estructura (insert). public class OSQueue extends Object { int queueType; /* 1 = FIFO, 2 = LIFO,
3 = SJF, 4 = LJF, 5 = RR */
int maxElements, curElements, qHead; public OSQueue(int q, int max) { queueType = q; maxElements = max; qHead = -1; }
Esta implementación en particular usa una estructura OSProcess[] ProcessArray que se encarga de almacenar todos los procesos del sistema. Debe resaltarse que esta estructura no pertenece a OSQueue, sino que aplica para cualquier cola de procesos existente en el sistema. Lo que sucede, es que al llamar al método insert de OSQueue, de actualizan los índices a los procesos siguientes de los PCBs. Esta implementación permite que cualquier cola de procesos pueda usar diferentes algoritmos de planificación. /*** put processes into the queue based on the queue type's ***/ /*** algorithm. The head must be the next in line to leave. ***/ public void insert(int P) { int ptr, optr=0; System.out.println("We are in Q insert"); if (curElements == maxElements) return; switch(queueType) { case 1: /* FIFO */ case 5: /* Round Robin */ /* traverse the Q to first */ System.out.println("IN OSQueueInsert, Qtype: "+queueType+ ",qHead: "+qHead+" P: "+P);
70
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar ptr = qHead; if(qHead == -1) { qHead = P; OSSystem.ProcessArray[qHead].nextPos = -1; } else { optr = ptr; while(ptr != -1) { System.out.println("We are in FIFO while ptr = "+ptr); optr = ptr; ptr = OSSystem.ProcessArray[ptr].nextPos; } OSSystem.ProcessArray[optr].nextPos = P; } curElements++; System.out.println("We are leaving FIFO; current elements: "+ curElements); break; } System.out.println("We are at the end of Q insert"); }
Tomemos como ejemplo la implementación para los algoritmos FIFO y Round robin (que en este caso es casi lo mismo). En realidad se esta implementando una estructura FIFO, pero lo interesante es que la inserción solo está operando sobre los índices del arreglo principal de procesos. Si el dispositivo en el que el proceso se ejecuta es el CPU se incrementan los valores de tiempo que el proceso ha pasado en el dispositivo; lo mismo pasa para la E/S. if (devName.equals("CPU")) { System.out.println("Qtype inside: "+devName); OSSystem.ProcessArray[curr_process].cpu_time_total++; if (devName.equals("IO")) { System.out.println("Qtype inside IO device: "+devName); OSSystem.ProcessArray[curr_process].io_time_total++;
3.4.2 NachOS⊕ Nachos es un software instruccional que permite a los estudiantes analizar y modificar un sistema operativo real operacional. Fue desarrollado en la Universidad de Berkeley y es usado por varias escuelas para la enseñanza de cursos de sistemas operativos. Como en cualquier sistema operativo, hay un planificador (Scheduler) que mantiene el control de los procesos en el sistema y los alterna periódicamente, y mantiene una lista de procesos (readyList) para este propósito. Todos los procesos en Nachos se ejecutan como hilos. Esto significa que todos los programas que se ejecutan en Nachos son implementados como hilos.
⊕
Obras consultadas: [3.11] [3.12] [3.13]
71
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 3.5 Forma en que los diferentes componentes de Nachos están ligados durante la ejecución4 El lapso de tiempo para la ejecución de cada proceso es determinado por el componente Temer, que causa una interrupción cuando el lapso de tiempo para un proceso en ejecución expira. El componente Interrupt maneja todas las interrupciones generadas por el componente Timer. La causa de las interrupciones pueden ser la E/S de algún dispositivo (p.ej. la escritura a un archivo por parte de un proceso, una señal del planificador para cambiar a otro proceso, etc.). Todos los sistemas operativos necesitan al hardware para ejecutar sus procesos. El componente Machine provee dicha funcionalidad, al simular la arquitectura MIPS. El componente FileSystem administra todas las operaciones de archivos. SynchDisk provee acceso sincronizado al disco. Para conectar una maquina con otras, se tiene el componente PostOffice que administra la recepción y envió de mensajes a través de una red. Stats es un componente que mantiene ciertas estadísticas sobre la ejecución y eficiencia del sistema. Por ejemplo, puede mantener el rastro de cuantos caracteres han sido escritos en la pantalla, cuantos errores de paginación han ocurrido, cuantos paquetes han sido recibidos por medio de la red, etc.
La máquina Nachos Nachos simula una máquina parecida a la arquitectura MIPS. La máquina tiene registros, memoria y CPU. Además, un reloj simulado manejado por eventos provee un mecanismo para planificar las interrupciones y ejecutarlas posteriormente. La simulación de la máquina MIPS puede ejecutar cualquier programa. Solo hay que cargar las instrucciones en la memoria de la
4
Imagen reproducida de [3.11]
72
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
máquina, inicializar los registros (incluyendo el contador de programa PCReg) y entonces decirle a la máquina que empiece a ejecutar las instrucciones. La máquina obtiene entonces la instrucción a la que apunta el PCReg, la decodifica y ejecuta. El proceso es repetido indefinidamente, hasta que una operación ilegal es realizada o una interrupción de hardware es generada. Cuando ocurre una trampa o interrupción, la ejecución de las instrucciones MIPS es suspendida, y una rutina de servicio de interrupción es invocada para atender la petición. Conceptualmente, Nachos tiene 2 modos de ejecución: Nachos ejecuta procesos a nivel de usuario cargándolos en la memoria del simulador, inicializando los registros del simulador y luego ejecutando el simulador. Los programas de usuario solo pueden accesar la memoria asociada con la máquina simulada. • El segundo modo corresponde al kernel de Nachos. El kernel se ejecuta cuando Nachos se inicia, o cuando un programa de usuario ejecuta una instrucción que causa una trampa de hardware (p.ej. una instrucción ilegal, falló de paginación, llamada al sistema, etc.). En modo de kernel, Nachos se ejecuta igual que un proceso normal de Unix. Es decir, las declaraciones correspondientes al código fuente de Nachos son ejecutadas, y la memoria accesada corresponde a la memoria asignada a las variables de Nachos.
•
3.4.3 RCOS⊕ RCOS esta implementado en Java (aunque la distribución original está en C++), y pertenece a la categoría de sistemas operativos basados en kernels. RCOS.java esta dividido en las siguientes secciones: 1. Hardware • • •
CPU. Hasta el momento está basado en el código de la máquina P. La intención es reutilizar el compilador RCOS PLL/2 y el intérprete de C++ existentes. Disco. Se usa una estructura pequeña para producir una representación gráfica de la asignación/desasignación de los bloques del disco por medio del sistema de archivos. Terminal y Memoria (RAM). La Terminal provee la interfaz física con el usuario, incluyendo el teclado y monitor. La Memoria consiste de 2 secciones. La primera es el cache del CPU, la cual es ajustada dinámicamente para almacenar programas en ella. Esto incrementa la velocidad y reduce la complejidad principalmente. La memoria RAM secundaria contiene todos los programas cargados y los almacena en dos secciones: código de proceso y pila (stack).
2. Sistema operativo - Kernel. RCOS usa un micro-kernel basado en una estructura de paso de mensajes. El kernel es responsable de varias funciones específicas de la plataforma incluyendo: a. manejo de interrupciones b. salvado/restauración del contexto (saving/retrieving context)
⊕
Obras consultadas: [3.16] [3.17] [3.18] [3.19] [3.20]
73
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
c. generación de mensajes al componente apropiado del SO como resultado de una llamada al sistema - Paso de mensajes (Message passing). Las funciones estándar del sistema operativo están divididas en diversos componentes. Toda la comunicación entre ellos debe ser en forma de mensajes. Todos los mensajes pasan por el componente Post Office que es responsable de entregar los mensajes a los destinos correctos. La intención es que componentes diferentes puedan ser localizados en computadoras diferentes. - Funciones del SO. Las responsabilidades restantes de SO están divididas en los siguientes componentes: a. Planificador de disco. Responsable de administrar las peticiones de planificación al disco, traducir los números de bloque lógico a sectores específicos del disco, cilindro y superficie. Hay un planificador de disco para cada disco. b. Sistema de archivos. Responsable de implementar un sistema de archivos particular (MS-DOS, CP/M, UNIX, NTFS, etc.). Maneja mensajes estándar como abrir archivo, cerrar, leer, escribir, abrir directorio, obtener atributos del archivo, etc. Es posible para una instancia del RCOStener varios objetos FileSystem, dando la habilidad para soportar más de un sistema de archivos a la vez. c. Planificador de procesos. Responsable de administrar la creación de procesos, terminación y planificación. Maneja mensajes como dividir un proceso (fork), ejecutar proceso, matar un proceso, planificar un nuevo proceso, bloquear proceso, etc. Mantiene todas las colas de discos e incluye métodos como runningToReady, runningToBlocked, getNextRunningProcess. d. Administrador de memoria. Responsable de administrar la memoria, asignar y desasignar memoria para los procesos, lectura y escritura de memoria para otros componentes. e. Terminales. Proveen el mecanismo para escribir/leer a/de una terminal. 3. Animación El sistema de Animación esta oculto del resto del sistema por la clase Post Office Animator. Sus responsabilidades incluyen: - dibujar la pantalla de perspectiva principal - manejar eventos de entrada e inicializar nuevos hilos para manipular la animación de varios componentes del SO. - decidir que mensajes son interesantes para el sistema de animación y distribuirlos en los hilos apropiados (si existen).
74
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 3.6 Arquitectura del RCOS5
3.5
Simulación de un Sistema Operativo mínimo
Aunque sería en extremo interesante poder simular cada una de las configuraciones históricas de los diversos sistemas operativos (una idea extremista pero interesante si se quiere hacer una exploración desde los inicios), esto sería en extremo un esfuerzo de mucho tiempo y escapa al objetivo de este trabajo. Para capitalizar las ideas expuestas anteriormente, con respecto al funcionamiento de un sistema operativo (capítulo 2) y la simulación de este tipo de sistemas, en esta sección he documentado una primera experiencia en este sentido. En cuanto todos los conceptos y sus interacciones cobraron sentido, se decidió hacer el intento de codificar un simulador que hiciera las cosas más sencillas que un SO se supone que realiza. La primera pregunta que surgió fue: ¿modelar solo el SO, o se requiere modelar también el hardware donde se ejecuta? Este primer problema no es tan sencillo como podría suponerse. Modelar una computadora es un ejercicio bastante complejo; y por lo visto hasta el momento un SO también es un sistema bastante complejo, como para aumentar la complejidad de la implementación. Sin embargo, hay algunos hechos que no pueden dejarse de lado:
5
Imagen reproducida de [3.17]
75
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
- el sistema operativo se crea para administrar los recursos de una computadora; - el SO en la mayoría de los casos es muy dependiente del hardware, pues aunque se creen abstracciones de alto nivel para modelar sus servicios, los niveles de base siguen encargados de el acceso al hardware y su control; - el SO por más portable que sea, necesita realizar funciones básicas para su inicialización y configuración, las cuales son dependientes de los recursos y arquitectura de la computadora. Esto deja claro que es necesario modelar el hardware para tener una simulación completa. Basta con ver los casos de estudio expuestos (NachOS y RCOS) para ver que es necesario (consulte los detalles de la implementación en el Apéndice. Simulación de un sistema mínimo de hardware y su sistema operativo).
3.5.1 El hardware: URM Así, se decidió retomar un modelo de computadora llamado URM (Unlimited Register Machine) implementado en el curso "Computabilidad y Funciones recursivas" de la licenciatura en ingeniería en Computación (FAR). Puesto que este modelo es un procesador abstracto, y tiene muy pocas instrucciones, es un ejemplo de dimensiones controlables (haber elegido un microprocesador como un Pentium o un PowerPC, seria tema de otro trabajo). La URM tiene un numero infinito de registros (R1,R2,R3...) cada uno de los cuales contiene en todo momento un numero natural. El contenido de los registros puede ser alterado por la URM en respuesta a ciertas instrucciones que puede reconocer. Estas instrucciones corresponden a operaciones simples usadas para realizar cálculos con números. Una lista finita de instrucciones constituye un programa. Las instrucciones son las siguientes: -
Z(n). Instrucción cero. Cambia el contenido del registro Rn a cero, dejando sin alteración a los demás registros. S(n). Instrucción sucesora. Incrementa el valor del número contenido en Rn en 1, dejando a los otros registros sin alteración. T(m,n). Instrucción de transferencia. Reemplaza el contenido del registro Rn por el valor contenido en Rm. J(m,n,q). Instrucción de salto. El contenido de los registros Rm y Rn son comparados; si rm=rn la URM procede a la instrucción q-ésima del programa en ejecución; si rmrn la URM procede a la siguiente instrucción.
En la implementación original del simulador de la máquina URM, la idea era darle a la máquina un programa escrito con las instrucciones del modelo, y que este las ejecutara. Retomar este simulador con el fin de simular un sistema operativo mínimo (SOM) requiere de nuevas consideraciones y varios cambios. La consideración principal debe ser el separar los componentes de hardware y software del modelo. Además en la implementación original: - la carga de los programas, la hacia el simulador, y no había explícitamente en el modelo un cargador de programas. - la URM no constaba con hardware adicional (periféricos); solo la unidad de procesamiento, sus registros y la memoria de programa.
76
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Si consideramos que la URM es un procesador, es posible usarla bajo el modelo de Von Neumann, y con ello modelar el hardware de una computadora que lo use. Por lo tanto, el sistema mínimo requeriría de: 1. Un procesador y sus registros. 2. Memoria principal Las instrucciones del modelo y su implementación conformarían el conjunto de instrucciones del procesador (y nos podemos dar el lujo de implementar una pequeña ALU para las cuestiones de operaciones aritméticas). Además puede incluirse parte del funcionamiento del modelo Von Neuman, agregando un ciclo de fetch y uno de ejecución al ciclo de instrucción de la máquina. Estas inclusiones requieren de agregar al modelo original dos registros especiales para estos fines. El registro de instrucción (IR) y el contador de programa (PC). A continuación se muestran los métodos encargados de dichos ciclos. interface Processor { /** ciclo de "fetch" donde la instrucción a ejecutarse se trae de memoria primaria y se coloca en el IR. El ciclo de Fetch -Va al PC -Va a la dirección que apunta el PC -Hace IR = MEM[PC] -Incrementa PC */ public void fetchInstruction(Memory m); /** el ciclo de ejecución, donde la instrucción se decodifica El ciclo de Ejecución -Si tiene que ir a Memoria -va a Memoria -ejecuta instrucción -almacena resultados. */ public void execInstruction();
y se ejecuta .
La idea de mostrar las interfases y no su implementación, es que si se hubiera modelado otro tipo de máquina, muy probablemente el funcionamiento de estos ciclos cambiaría (por ejemplo una arquitectura RISC que usa pipelining); sin embargo la implementación se puede ver en el apéndice correspondiente. La URM incorpora a su funcionamiento un número ilimitado de registros, pero en procesadores reales, estos registros son limitados (acumuladores, registros de segmento, de pila, de código, etc.) por lo que debe respetarse esta funcionalidad, aunque ajustándola a un numero de registros variable y finito (lo cual permitirá variar la configuración del modelo). De hecho en el simulador de URM original también se limitó el número de registros por cuestiones prácticas, pues los programas que se diseñaron en ese entonces eran muy sencillos. En cuanto a la memoria, esta puede modelarse como un arreglo, donde cada celda de memoria puede contener una instrucción y sus parámetros. Por tanto, el acceso a la memoria es de forma
77
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
lineal, donde el índice del arreglo es equivalente a una dirección (celda) de memoria. Este acceso, implica la lectura y escritura de datos en memoria. Aunque no forman parte explícitamente del modelo, se requerirá implementar un par de instrucciones para estos fines (p.ej. READ/WRITE, GET/SET, IN/out, LOAD ax,dir/LOAD dir,ax, etc.) interface public public public }
Memory { void setMemLoc(int adr, Object value); Object getMemLoc(int adr); void showMem();
En el simulador se cuenta con un genérico de estas funciones, y una implementación específica para la memoria de la URM.
3.5.2 El software: SOM En lo que respecta al software, en específico al sistema operativo de esta máquina, hay dos alternativas: 1. Codificar el sistema operativo en código del modelo simulado. 2. Crear un módulo que se encargue de las funciones propias del sistema operativo. Como se mencionó al principio, lo que se quiere es un sistema operativo mínimo, pero... ¿qué es eso? En concreto, es una pieza de software que permita cargar un programa a la memoria del modelo y que el procesador lo ejecute.
Figura 3.7 Modelo del simulador con un cargador de programas. 78
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Si tomáramos la primera opción, lo primero que salta a la vista es que como el modelo solo consta de 4 instrucciones, el conjunto de instrucciones tendría que ser ampliado para permitir el acceso al disco, controlar dispositivos, mostrar resultados en un dispositivo de salida, etc. Aunque puede hacerse, el modelo se convertiría en un nuevo procesador, y en ese caso sería mejor emular un procesador con las instrucciones suficientes como para implementar un SO completo. El segundo enfoque es igualmente válido, pues si el mismo simulador implementa el modelado de las funciones de nuestro SO mínimo, el resultado de la simulación es el mismo. Esta opción es la que se ha implementado. Tomar esta decisión implica algunas consideraciones extra, como: - Que la dirección de carga de programas, será el inicio del arreglo que se use. Esto se interpretaría como que el SO ya está cargado en memoria, y esa área está protegida contra el acceso de otros programas. - Que el SO implemente funciones de acceso a dispositivos, aunque estos no formen parte explicita del modelo. La entrada/salida estándar es equivalente a que el simulador cuente con un monitor, y el acceso a los archivos es equivalente a contar con dispositivos y sus respectivos manejadores. De esta forma el SOM tendría todas las características de un monitor residente, uno de los primeros SOs, las cuales pueden extenderse para implementar el procesamiento por lotes (batch), para lo que se debe incluir un JCL (Job Control Language). El JCL propuesto es el siguiente: • • •
LOAD - carga un programa RUN - ejecuta un programa EOJ - Fin del trabajo (End Of Job)
• •
LDBATCH - Carga un archivo con comandos para procesarlos en lote SHUTDOWN - Apaga el SO
El modelo solo ejecutará un programa a la vez, por lo que la administración de procesos no fue implementada. Además con la simplificación del acceso a memoria tampoco se necesita un administrador de memoria, aunque pudiera ser útil si se quisiera expandir la memoria base del modelo. El SOM está compuesto de las clases: Loader, se encarga de cargar los programas desde su archivos a la memoria para su ejecución. JCLInterpreter, se encarga de interpretar los comandos JCL. Monitor, esta compuesta por Loader y JCLInterpreter y se encarga de cargar un programa o un conjunto de programas en memoria para luego ejecutarlos, en base a una secuencia de comandos JCL.
79
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 3.8 Modelo del simulador con un SOM para una URM modificada, basado en el concepto de un monitor residente.
Figura 3.8a Ejecución del simulador
80
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Aunque sin incorporar el manejo de interrupciones, dispositivos, etc., este primer diseño es lo bastante ilustrativo como para entender lo que hace un sistema operativo, y como codificarlo (a un nivel muy básico). En la siguiente sección se comentan algunos de los elementos que no han sido considerados en el simulador, pero podrían ser modelados para incluir los aspectos del manejo de dispositivos, pero por el momento eso no está incluido en la implementación del apéndice B.
3.5.3 Consideraciones para el modelado de dispositivos de E/S⊕ Uno de los elementos básicos de cualquier computadora, son sus dispositivos de entrada y salida (E/S). Aunque en la sección anterior la E/S de datos no era explicita en el modelo, estaba implícita en las funcionalidades del lenguaje. En el caso de la entrada de datos, el método runProgram() de la clase TestSimulator, captaba las instrucciones del Lenguaje de Control de Trabajos, a nivel de instrucciones en Java (hardcoded). public void runProgram () { Processor p=new URMProcessor(); //creando un nuevo procesador //creando la memoria donde se almacenarán los programas Memory m=new URMMemory(20); Monitor os=new Monitor(p,m); //creando una nueva instancia del SO System.out.println("Iniciando ejecución de instrucciones JCL..."); os.startMonitor(); //inicializando SO os.userInput("LOAD c:\\sw\\oses\\OS\\prog.urm"); //comandos JCL para que los ejecute el SO os.userInput("RUN"); os.userInput("SHUTDOWN"); }
En el caso de la salida, la instrucción System.out.println() hacia las veces de un dispositivo de despliegue (monitor), permitiéndonos ver el resultado de la ejecución del programa. Incluso el sistema de archivos también se vio encapsulado, y tampoco forma parte del modelo explícitamente. Aunque la abstracción es válida, y no impidió que el modelo se desarrollara hasta obtener un prototipo funcional, la verdad es que se supone que parte del trabajo del sistema operativo es controlar los dispositivos de E/S de la computadora, por lo que si no los tomamos en cuenta, el modelo del SO quedará incompleto, y no podrán apreciarse los detalles relacionados a este servicio. Para mejorar el modelo propuesto, será entonces necesario incluir el sistema de E/S en el simulador. Puede resumirse de lo expuesto en la sección 1.4.2, que los elementos a tomar en cuenta son: • ⊕
El dispositivo Obras consultadas: [3.14]
81
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
• •
El controlador del dispositivo El sistema de interrupciones
Esto implica las siguientes consideraciones: a. Modelar un dispositivo abstracto, con un protocolo de mensajes que sea aceptado por cualquier implementación de un dispositivo específico. El dispositivo genérico deberá proveer como mínimo la lectura y escritura de sus datos, así como su configuración e identificación. Esto será ampliado después por las implementaciones específicas, pero debe tomarse en cuanta que el protocolo de mensajes puede verse ampliado, según el tipo de dispositivo (un monitor es mucho más complejo que un teclado en su funcionamiento e interfaz). b. Modelar el concepto de controlador de dispositivo. Todo dispositivo se conecta al bus por medio de un controlador. Además, cada controlador tiene un buffer local, de donde el CPU recoge y envía datos. c. Modelar un sistema de interrupciones genérico que pueda ser aprovechado por implementaciones de arquitecturas específicas. Los principales elementos del sistema de interrupciones son: - Las interrupciones, que notifican al CPU de una operación o llegada de nuevos datos. - Las rutinas de servicio de interrupción (ISR), que son los procesos que se ejecutan cuando llega una señal de interrupción y el CPU debe atenderla. - El vector de interrupciones, que es una tabla en memoria con las direcciones de las ISRs con que se cuenta. Debe tomarse en cuenta que: - las ISRs son instaladas en el vector por el sistema operativo; - el dispositivo que interrumpe envía un numero por el bus de datos, el cual sirve de índice en el vector de interrupciones para que el CPU pueda ejecutar la ISR adecuada; - existen diferentes tipos de eventos: Interrupciones de hardware, por señales de los dispositivos. Interrupciones de software (llamadas al sistema; excepciones) por medio de instrucciones especificas del procesador. y cada evento activa una ISR diferente; - el control de interrupciones puede ser síncrono (el SO espera a que la E/S termine) o asíncrono (el SO continua su ejecución mientras la E/S se lleva a cabo). • •
d. Puede tenerse en cuenta el mecanismo de acceso directo a memoria (DMA), por medio del cual los dispositivos tienen acceso a la memoria principal sin necesidad de que el CPU intervenga. Ahora hay que revisar si el modelo actual permite la comunicación entre los dispositivos y el CPU. Puesto que todo lo anterior no fue considerado desde un principio, es casi seguro que se tenga que modificar una buena parte de la estructura del modelo.
82
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Lo que se mantendrá en el modelo es la protección del SO y los programas de usuario como una abstracción, puesto que el SO forma parte de la implementación del simulador no habrá que implementar ese detalle.
3.5.4 Resultados La estrategia para la construcción del modelo de simulación consistió en modelar los principales servicios de administración de los sistemas operativos (procesos, memoria y dispositivos), para después integrarlos en diferentes configuraciones, esperando que la tarea de integración arroje problemas y consideraciones que aporten soluciones y experiencias interesantes para la comprensión del diseño e implementación del simulador. Aunque al principio se había planteado solo codificar los algoritmos y módulos que son importantes para los sistemas basados en núcleos modulares (los más difundidos actualmente), la simulación de cada una de estas partes, y del hardware relacionado a su funcionamiento, ha dado como resultados algunas configuraciones similares a los primeros sistemas (sencillos pero muy ilustrativos). Lo positivo de esto, es que se brinda al lector una perspectiva real, no sólo de como funciona un sistema operativo y como hacerlo, sino de todas las reflexiones y decisiones que involucra su diseño. Los principales resultados de este primer experimento son: •
•
•
•
•
• • •
El escoger el modelo de URM para la simulación, no permite experimentar con programas que tengan un control total sobre los recursos. Para este fin, el conjunto de instrucciones debería ser lo más real posible, aunque para los fines de este trabajo, conviene que tenga el menor numero de elementos posibles. El conjunto de instrucciones de la URM es suficiente para crear programas útiles, sin embargo, habría que agregar instrucciones adicionales para el control de registros, accesos a memoria y recursos, etc.; por eso es que los conjuntos de instrucciones de los procesadores reales tienen tantas instrucciones. Implementar la abstracción de dispositivos de E/S reduce la complejidad, pues modelar dispositivos específicos, como tarjetas de red, etc. hace necesario contar con más elementos teórico-prácticos. No existió una fase previa de diseño. El "tener claro" que componentes era necesario modelar, hizo que la improvisación reinara, y al final aunque se cuenta con un modelo que funciona, hay muchas mejoras que pueden hacerse. En este momento se hizo patente la necesidad de una metodología clara para proceder. Podría haber usado una metodología de ingeniería de software como RUP, o la que fuera, pero sin perder el foco de este trabajo de este trabajo que son los SOs, usar una metodología tan grande para un SO como el SOM hubiera sido excesivo (aunque en general para al simulador le hubiera caído bien) La cohesión entre las clases del simulador es muy fuerte, por lo que hacer cambios en su configuración es algo difícil. Las capacidades del BlueJay y su depurador permitieron contar con una visualización del proceso de simulación (primitiva pero efectiva) Para reforzar el modelo de simulación, es recomendable (sino indispensable) permitir que el usuario de la herramienta pueda visualizar el comportamiento del modelo, e incluso modificar su comportamiento, en cualquier momento. Para ello debe considerarse agregar a los elementos más significativos del modelo, la funcionalidad para que puedan desplegar su
83
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
comportamiento a través de una interfaz gráfica. Preferentemente debe permitir visualizar el modelo a nivel general, y además permitir el seguimiento de cada módulo que implique un servicio relevante a todo el sistema. En el paradigma MVC (Modelo-Vista-Controlador) las entradas producidas por el usuario, el modelado del mundo exterior, y la retroalimentación visual al usuario están explícitamente separadas y manejadas por tres tipos de objetos, cada uno especializado en su tarea. La Vista administra la salida gráfica y/o textual a la porción del área de despliegue asignada a la aplicación. El Controlador interpreta las entradas del usuario provenientes del teclado o ratón, ordenándole al Modelo y/o a la Vista cambiar como sea apropiado. Finalmente, el Modelo maneja el comportamiento y datos del dominio de la aplicación, responde a requerimientos de información sobre su estado (usualmente de la Vista), y responde a las instrucciones al cambio de estado (usualmente del Controlador). Este modelo deberá ser considerado más adelante.
Figura 3.9 Patrón de diseño Modelo-Vista-Controlador. En los siguientes capítulos se presentarán a detalle los diversos sistemas de administración de servicios que comúnmente forman parte de un sistema operativo. La idea es que una vez que se ha mostrado que la simulación es una herramienta útil, se continuará usando para demostrar el funcionamiento de estos sistemas. Debo hacer notar que el enfoque de simular el hardware y el SO, es el más completo. Sin embargo, en los siguientes tres capítulos es probable que se simulen solo los elementos relacionados a cada sistema de administración, o probablemente solo se modelen puramente los elementos de administración, sin el hardware. Ambos enfoques considero que siguen siendo válidos, sobre todo para aclarar que hace cada parte y tomar a sus simulaciones como pruebas de concepto.
3.5.5 morfo-Hardware Uno de los resultados adicionales de este primer modelo de simulación fue la idea de crear un sistema de hardware que pudiera modificarse para probar diferentes conjuntos de instrucciones. A este modelo se le llamó morfo-Hardware.
84
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 3.10 Esquema del modelo morfo-Hardware La idea es contar con una abstracción genérica de un dispositivo de hardware (HWDevice), del cual se puedan derivar procesadores, memoria, y dispositivos periféricos, quienes se comunican por medio de señales administradas por medio de un controlador.
Figura 3.11 Modelo de clases de morfo-Hardware v.0.1 Se incluyen algunos de los diagramas de clases preliminares de este modelo (figuras 3.11 y 3.12), pues a consideración del autor esto sería de mucha utilidad si se quieren comprobar cuestiones de portabilidad de una plataforma de hardware a otra.
85
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 3.12 Modelo de clases de morfo-Hardware v.0.2 Lo interesante del modelo es que una vez que el framework quede establecido solo hay que codificar el conjunto de instrucciones del nuevo procesador; todo lo demás quedaría intacto. En fin, esta es una idea que sigue en desarrollo.
3.6
Comentarios
Como ya se comentó, simular el hardware puede ser una tarea exhaustiva, y dependerá mucho del nivel de detalle y realismo que se desee en el simulador. Para muchos fines bastará con incluir en los modelos elementos que efectúen las operaciones básicas de los dispositivos de hardware; sobre todo si en lo que se quiere hacer énfasis, es en los componentes del sistema operativo. En tal caso debe tenerse en cuenta que muchos algoritmos relacionados a la administración de recursos ya están disponibles, por lo que es deseable hacer énfasis en el análisis y visualización de resultados. Ya que se han planteado los principales elementos para la simulación de sistemas operativos, en los siguientes dos capítulos se planteará el desarrollo de simuladores para los subsistemas de administración de memoria y de procesos, respectivamente.
86
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
3.7
Obras consultadas
[3.1] Guide to the Java Version of the Simple Operating System (SOS) Simulator. Charles Crowley. August 1997. [3.2] The Flux OS Toolkit: Reusable Components for OS Implementation.
Research Center,Duke University.
[email protected] February 3, 1997 http://www.cs.duke.edu/~narten/110/nachos/main/mai n.html
The Flux OS Kit: A Substrate for OS and Language Research
[3.14] A Designer's Assistant Tool Home Page.
ftp://mancos.cs.utah.edu/papers/oskit-hotos6-abs.html
http://csg.uwaterloo.ca/dptool/
[3.3] How To Write a Computer Emulator
[3.15] The OS Emulation HomePage
Marat Fayzullin. 1997-2000.
http://www.kearney.net/~mhoffman/
Computer Systems Group . University of Waterloo
http://www.komkon.org/fms/EMUL8/ [3.16] RCOSjava [3.4] The SNES Developers Corner http://emureview.ztnet.com/developerscorner/index.ht m [3.5] Emulation programmers resource
http://rcosjava.sourceforge.net/ [3.17] RCOS.java http://webfuse.cqu.edu.au/Information/Resources/Rea dings/RCOS.java/
http://www.classicgaming.com/EPR/ [3.18] RCOS: Yet Another Teaching Operating System [3.6] Trends in Hardware/Software Codesign
Ron Chernich, Bruce Jamieson, David Jones
Larry Mittag
Proceedings of the First Australasian Conference on Computer Science Education.
http://www.embedded.com [3.7] Truth, Beauty, and the Virtual Machine David Gelernter http://rum.cs.yale.edu/jvmsem/lecture/0922/gelernter. html [3.8] Visible Virtual Machine (VVM) Page
http://webfuse.cqu.edu.au/Information/Resources/Rea dings/RCOS.java/yato/ [3.19] The Design and Construction of a Simulated Operating System. Ron Chernich, David Jones. Asia Pacific Information Technology in Education Conference, Brisbane, July 1994.
http://www.cba.uri.edu/faculty/vvm/
http://webfuse.cqu.edu.au/Information/Resources/Rea dings/RCOS.java/Design/
[3.9] THE UCSD P-SYSTEM MUSEUM IN THE WEST WING OF THE JEFFERSON COMPUTER MUSEUM
[3.20] Not just another teaching operating system
http://www.threedee.com/jcm/psystem/index.html
http://webfuse.cqu.edu.au/Information/Resources/Rea dings/RCOS.java/njato/ http://cq-pan.cqu.edu.au/david-jones/Projects/rcos/
[3.10] The Free Online Dictionary of Computing Edited Denis Howe http://foldoc.doc.ic.ac.uk/ [3.11] NACHOS http://http.cs.berkeley.edu/~tea/nachos/
[3.21] Modern Operating Systems Simulators http://www.ontko.com/moss/ [3.22] Palm OS Simulator http://www.palmos.com/dev/tools/simulator/
[3.12] Salsa - An Operating Systems Tutorial. University of Massachusetts, Amherst
[3.23] SimOS
http://ali-www.cs.umass.edu/salsa/about.html
http://simos.stanford.edu/
[3.13] A Road Map Through Nachos. Thomas Narten. Department of Computer Sciences, Levine Science
[3.24] The OS Kit Project http://www.cs.utah.edu/flux/oskit/
87
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
88
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Capitulo 4. Administración de la memoria Para hacer una tarta de manzana, primero tienes que crear un universo. Carl Sagan, Cosmos
La memoria es fundamental para la operación de cualquier computadora moderna. Curiosamente nuestras aplicaciones cada vez necesitan más y más de este recurso, pero ¿por qué? Una respuesta es el tamaño de las aplicaciones, pero recordemos que los sistemas operativos son los encargados de proveer un ambiente donde estas aplicaciones se ejecuten; por lo tanto, para que la idea de administración de procesos sea factible, tenemos que contar con la memoria para cargar nuestros programas, y también serán necesarios mecanismos que optimicen el uso de este recurso esencial. Los sistemas operativos ofrecen un mecanismo para que el software acceda a la memoria. En el enfoque más sencillo, la memoria entera de la computadora se dedica a los programas. Este enfoque es el más común en sistemas de una sola tarea (solo un programa se ejecuta a la vez). Incluso en este caso, existirán porciones de la memoria designados para ciertos propósitos (variables, áreas para las rutinas del SO, mapeo del hardware, memoria de video, etc.). Con el hardware de soporte para memoria virtual, los sistemas operativos pueden darle a los programas la ilusión de tener la memoria entera para ellos (o incluso dar la ilusión de que hay más memoria de la que en realidad exista, usando el espacio en disco), cuando en realidad el SO está moviendo continuamente programas en la memoria y asignando dinámicamente la memoria cuando se necesita. Para comprender la ejecución de programas, es necesario estudiar el funcionamiento del servicio que hace posible que las instrucciones y datos puedan ser manipulados. En este capítulo se presentan los principales conceptos relacionados a la administración de memoria, tomando en cuenta que los chips proveen el almacenamiento físico, pero es el sistema operativo quien dicta como se usa y aprovecha; por ello también se aborda el tema de la carga de programas en memoria y algunas cuestiones de compilación de código, que también influyen en el servicio de administración de la memoria.
4.1
La memoria⊕
La memoria es una colección de elementos (bytes o words), cada uno con su propia dirección. La interacción con la memoria se lleva a cabo por medio de una secuencia de lecturas o escrituras a direcciones específicas. ⊕
Obras consultadas: [4.14]
89
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
El CPU intercambia datos de forma intensiva con la memoria. En un ciclo típico de instrucción, por ejemplo, primero se obtiene una instrucción de la memoria; la instrucción es entonces decodificada y puede causar que los operandos sean traídos de la memoria. Después de ejecutar la instrucción sobre los operandos, los resultados pueden ser almacenados en la memoria. Es importante notar que la unidad de memoria lo único que ve es un conjunto de direcciones de memoria; no sabe como son generadas (el apuntador a instrucción, indexado, etc.) o para que se van a usar (instrucciones o datos). De acuerdo a esto, podemos ignorar como un programa genera una dirección de memoria, y solo interesarnos por las secuencias de direcciones de memoria generadas por el programa en ejecución.
4.1.1 Asignación de direcciones Para referenciar una parte especifica de la memoria, se necesita la ubicación de dicha parte de memoria. Esto es lo que se conoce como direcciones físicas. En los programas, las ubicaciones de memoria a las que se hace referencia son llamadas direcciones lógicas, porque una dirección especificada por un programa puede o no ser la dirección física correcta.
Figura 4.1 Vista simplificada del espacio de direcciones en la memoria. Básicamente hay tres formas diferentes de que las direcciones lógicas sean mapeadas a direcciones físicas, lo cual es llamado ligado de direcciones (address binding). Estás técnicas de ligado dependen de los métodos de administración de memoria que el SO de la computadora use y el hardware disponible: 1. Ligado de direcciones a tiempo de compilación. Cuando al compilar se conoce la dirección absoluta, el compilador escribe la imagen exacta del código que se cargará en la memoria. Esta técnica genera código absoluto, es decir, que las direcciones están previamente en su lugar, y cuando el programa es ejecutado, las ubicaciones lógicas 000 - 999 de hecho
90
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
corresponden a las direcciones físicas 000 - 999. Por ejemplo, consideremos un sistema simple donde el SO reside en las direcciones físicas 000 - 500, por lo que cualquier programa tendría que comenzar en la dirección 501. Un programa que tiene el espacio de direcciones lógicas 000 999 podría ser modificado para que sus direcciones lógicas correspondan con las direcciones físicas 501 - 1500. Si el programa se compiló para una dirección específica, pero tiene que ser cargado en una dirección diferente de arranque, entonces el programa tendrá que ser recompilado. Los sistemas modernos no usan este método por no ser flexible. 2. Ligado de direcciones a tiempo de carga. Si la dirección de inicio del programa no se conoce a tiempo de compilación, entonces el compilador generará código relocalizable. A tiempo de carga, cuando el sistema conoce el lugar donde se colocará el programa, el ligado de tiempo de carga podrá mapear las direcciones lógicas del programa (p.ej. 000-999) a las direcciones físicas correspondientes (p.ej. 501-1500 o 1000-1999), dependiendo de la situación de la carga (DOS trabaja de esta forma). 3. Ligado de direcciones a tiempo de ejecución. Si la dirección de inicio de un programa va a ser alterada durante su ejecución, entonces el ligado deberá ser postergado hasta el momento en que se ejecute. Las direcciones físicas son generadas durante la ejecución agregando el valor de las direcciones lógicas a un registro de desplazamiento (offset register). De nuevo, suponiendo que las direcciones lógicas del programa son 000-999, puede asignarse el valor de 501 al registro de desplazamiento para hacer referencia a las direcciones físicas 501-1500. Así, cuando la dirección base del programa se cambia de 501 a 2001, el valor del desplazamiento se cambia de 501 a 2001. Este técnica se usa si el sistema operativo usa swapping (pasar procesos a disco para hacer espacio en la memoria), lo que ocasiona que un proceso sea cambiado de posición durante su ejecución. En este caso se usa hardware especial para mejorar el rendimiento. El programa de usuario sólo ve direcciones lógicas; es la unidad de administración de memoria (MMU) quien se encarga de traducirlas transparentemente a direcciones físicas. La gracia es que el compilador puede generar código absoluto, pensando que el programa se va a cargar siempre en la posición 0, y en realidad el ligado de direcciones se hace a tiempo de ejecución.
4.1.2 La unidad de administración de memoria (MMU)⊕ La unidad de administración de memoria (MMU) es un dispositivo de hardware que traduce direcciones virtuales en direcciones físicas. Típicamente la MMU es parte del CPU, aunque en algunos sistemas es una parte independiente (fig. 4.2).
⊕
Obras consultadas: [4.6] [4.7] [4.8] [4.9]
91
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 4.2 La MMU se sitúa justo entre el CPU y la memoria. Las direcciones generadas por el CPU, después de cualquier indexación u operación realizada por los modos de direccionamiento, es llamada dirección virtual, y la dirección transformada por la MMU es llamada dirección física (fig. 4.3).
Figura 4.3 Cuando el CPU quiere acceder a la memoria, le manda la dirección que quiere a la MMU quien la traduce en otra dirección que le pasa a la unidad de memoria. La MMU incluye una pequeña cantidad de memoria que contiene una tabla que relaciona las direcciones virtuales y las direcciones físicas; esta tabla es llamada TLB (Translation Lookaside Buffer). Todas las peticiones de datos son enviadas a la MMU, la cual determina si los datos están en la RAM o es necesario extraerlos de un medio de almacenamiento secundario. Si los datos no están en memoria, la MMU genera una interrupción de falló de página (page fault interrupt). La MMU soporta el manejo de esquemas de memoria virtual como alojamiento continuo, paginación, segmentación y segmentación con paginación (estos serán tratados en la siguiente sección).
Memoria asociativa La memoria asociativa se basa en el principio de localidad que establece que la mayoría de programas tiende a referenciar un porcentaje reducido de sus páginas durante períodos relativamente largos de tiempo. Con base en este principio se equipa a los computadores de un dispositivo de hardware para asociar las direcciones virtuales con las direcciones reales (físicas)
92
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
sin tener que recurrir a la tabla de páginas. Este se encuentra en la MMU y consta de un número pequeño de entradas (8, 16, 32 son cantidades típicas), cada una de las cuales tiene la estructura similar a una entrada en una tabla de páginas convencional. La memoria asociativa funciona de la siguiente forma: cuando se presenta una dirección virtual a la MMU para su traducción, se verifica primero si su número de página virtual se encuentra en la memoria asociativa, al comparar todos los registros que la componen en paralelo. Si se encuentra allí, la dirección del marco de página se selecciona de allí directamente sin ir a la tabla de páginas y se continúa con el proceso de traducción normal. Cuando el número de página no está en la memoria asociativa, se recurre a la tabla de páginas. Una vez localizada la entrada correspondiente, se extrae una entrada de la memoria asociativa y se reemplaza con el dato determinado en la tabla de páginas. Así, si esta página vuelve a ser referenciada, la segunda vez será encontrada con rapidez. Con esto la proporción de encuentros, es decir, la proporción de referencias a la memoria que pueden ser satisfechas a partir de la memoria asociativa, se incrementa considerablemente, permitiendo una mayor eficiencia en el proceso de traducción de direcciones.
4.1.3 Manejo estático y dinámico de la memoria⊕ Existen dos esquemas en que la memoria puede manejarse: estático y dinámico. El concepto de memoria estática asume que las direcciones no cambian. Esto puede ser una ilusión de memoria virtual, o puede ser la disposición física disponible. La asignación estática de memoria puede ser por medio de direcciones absolutas o por medio de direcciones relativas del apuntador de programa (PC) (para permitir la relocalización o la recursividad), pero en cualquier caso, el compilador o el ensamblador generan un conjunto de direcciones que no pueden cambiar durante la vida del programa o el proceso. • El concepto de memoria dinámica asume que las direcciones pueden cambiar (aunque el cambio por lo general se limita a condiciones posibles predefinidas). Los dos enfoques dinámicos más comunes son el uso de pilas de cuadros (stack frames) y el uso de apuntadores o manijas (handlers). Las pilas de cuadros se usan principalmente en los datos temporales (como variable de funciones o subrutinas o contadores de iteraciones). Las manijas o apuntadores se usan para tener una referencia de bloques de memoria dinámicamente asignados.
•
4.1.4 Carga de programas en memoria El proceso de carga consiste en colocar un programa en memoria para que pueda ser ejecutado. Existen diferentes tipos de cargadores: - Compile and go: (compile y ejecute). Son los utilizados por los compiladores tipo Turbo (Pascal, C, Prolog, etc.), cuando la compilación se realiza directamente a la memoria. La idea central consiste en que a medida que se va compilando se va escribiendo directamente sobre la memoria el código ejecutable y una vez se termine el proceso, se le da el control al programa compilado para su ejecución. - Cargadores Absolutos: Existen en sistemas en los que los compiladores generan código absoluto (no relocalizable). De esta forma se obliga a que el programa siempre se deba carga en
⊕
Obras consultadas: [4.14]
93
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
las mismas posiciones de memoria. Son relativamente simples pero no permiten tener multiprogramación. - Cargadores Relocalizadores: permiten cargar el programa en cualquier sitio de la memoria. Para que esto sea posible, es necesario contar con algún mecanismo de relocalización. - Cargadores Dinámicos: Cargan los procedimientos del programa dinámicamente durante su ejecución. Son necesarios en el caso de presentarse recubrimientos. - Cargadores en memoria virtual: Para cargar un programa en memoria virtual este primero se mueve a una zona de módulos cargables en el espacio auxiliar y creando las correspondientes entradas en la tabla de páginas, las cuales deben quedar con el bit presente/ausente apagado, lo que implica que las páginas aún no están en la memoria real, a pesar de que el programa ya está cargado en la memoria virtual. Este mecanismo recibe el nombre de acoplamientos y también se utiliza para realizar operaciones de E/S (fig. 4.4).
Figura 4.4 Carga de un programa en memoria virtual Overlays⊕
¿Cómo implementar múltiples programas en un sistema operativo usando direcciones absolutas? o en las primeras computadoras, ¿Cómo se implementaba un programa que era más grande que la memoria RAM disponible (especialmente en una época donde los procesadores apenas tenían más de 1k, 2k, o 4k de RAM? La respuesta más fácil eran los sistemas de recubrimientos. La idea básica es que el programa es divido en partes llamadas recubrimientos (overlays). Todos los recubrimientos se mantienen en disco y son intercambiados a la memoria conforme se van necesitando. Un recubrimiento puede comenzar a ejecutarse y al terminar, llamar a otro recubrimiento. El problema con este enfoque era que el programador tendría que dividir manualmente el programa en recubrimientos. La memoria virtual, desarrollada posteriormente, hizo que la computadora hiciera todo el trabajo. Así, aunque el tamaño combinado del programa, los datos y la pila excediera el tamaño de la memoria física disponible, el SO podría ejecutar el programa. Aquellas partes del programa que estén en uso son almacenadas en memoria principal; el resto en el disco. Por ejemplo, un programa de 16Mb puede ejecutarse en una máquina con 4Mb escogiendo que partes deberían mantenerse en memoria, y cuales en disco. Las piezas del programa eran intercambiadas entre la memoria y el disco como se fuera requiriendo (fig. 4.5).
⊕
Obras consultadas: [4.14]
94
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 4.5 Esquema de un sistema que implementa recubrimientos6 Con un sistema de recubrimientos, cada programa o segmento de programa es cargado exactamente en el mismo espacio de memoria. Un manejador de recubrimientos existe en otra área de la memoria y es responsable de intercambiar páginas de recubrimiento (o segmentos de recubrimiento). Cuando un segmento de recubrimiento termina su trabajo o necesita acceder una rutina en otro segmento de recubrimiento, envía una señal al manejador de recubrimiento, la cual intercambia el viejo segmento de programa e intercambia en el próximo segmento de programa.
Relocalización La relocalización consiste en ajustar las direcciones de un programa al sitio donde fue cargado, para que este pueda ser ejecutado. Este proceso es indispensable para poder tener multiprogramación, puesto que un programa no siempre va a ocupar las mismas posiciones de memoria. Suponga que se tiene el siguiente trozo de programa en lenguaje ensamblador:
Para su ejecución el programa debe ser traducido a lenguaje de máquina. Sin embargo el ensamblador no conoce el sitio en donde va a ser cargado el programa y por lo tanto no puede traducir adecuadamente las referencias a la memoria. Si el programa fuese cargado en la posición 0, por ejemplo, y suponiendo que las variables f y g están en las posiciones 50 y 54 respectivamente, con respecto al inicio del programa, el programa generado sería:
6
Imagen reproducida de [G12]
95
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Sin embargo, si el programa fuese cargado a partir de la posición 100, el código debe relocalizarse y sería:
4.2
Administración de la memoria⊕
Por lo general la administración de memoria está dividida en tres áreas:
Hardware. Este nivel se ocupa de los dispositivos electrónicos relacionados al almacenamiento de información (RAM y caches de memoria). Sistema Operativo. En el sistema operativo debe reservarse la memoria para los programas de usuario, y reciclarse cuando ya no está en uso. El SO puede dar la ilusión de que existe más memoria de la que el sistema tiene, y también que un programa puede apoderarse de toda la memoria (sistemas de memoria virtual). Aplicaciones. Se trata de proveer la memoria necesaria a los objetos y estructuras de datos de un programa, de los recursos limitados disponibles, y reciclar dicha memoria para reusarla cuando es liberada. Puesto que los programas de aplicación no pueden predecir cuanta memoria requerirán, necesitan código adicional para manejar sus requerimientos variantes de memoria.
Una de las primeras tareas del sistema operativo es organizar una estructura heterogénea de memoria (resultado de las constantes presiones de los fabricantes de sistemas y dispositivos periféricos por mantener la compatibilidad con sus esquemas de memoria originales), asignando direcciones lógicas a direcciones de memoria física (en conjunto con el bus de memoria) y asignando varias áreas reservadas a la tabla del vector de interrupciones, memoria de video y código del BIOS. En la administración de procesos, el CPU puede ser compartido por un conjunto de procesos. Como resultado de la planificación de procesos, es posible mejorar la utilización del CPU y la velocidad de respuesta de la computadora con los usuarios. Sin embargo, para realizar este
⊕
Obras consultadas: [4.1] [4.2] [4.3] [4.4] [4.5]
96
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
incremento en el desempeño deben mantenerse varios procesos en la memoria, por lo que esta debe poder compartirse. De hecho la administración de memoria en un sistema operativo puede definirse como: •
la tarea desempeñada por el SO y el hardware para acomodar varios procesos en la memoria principal.
Su labor consiste en llevar un registro de qué partes de la memoria se están utilizando y qué partes no (donde están almacenados los procesos y datos), con el fin de asignar espacio a los procesos cuando estos hagan requerimientos, liberarlo cuando terminen, así como administrar el intercambio entre la memoria principal y el disco, en el caso en que esta no pueda albergar a todos los procesos. También facilita los mecanismos de protección para que un proceso no invada el espacio de otros procesos.
4.2.1 Administración manual La administración manual de la memoria es donde el programador tiene control directo de cuando la memoria debe ser reciclada. Usualmente esto se hace por medio de llamadas explicitas a funciones de administración de la memoria dinámica (heap), por ejemplo, malloc/free en lenguaje C; o por construcciones del lenguaje que afecten el stack (como las variables locales). La principal característica de la administración manual de memoria es que provee al programa de una forma de expresar "aquí está este trozo de memoria; ya termine de usarlo". El administrador de memoria no recicla ninguna parte de la memoria sin tal instrucción. Las ventajas de la administración manual de memoria son: • •
Puede ser más fácil para el programador entender exactamente lo que está pasando; Algunos administradores manuales tienen mejor desempeño cuando hay poca memoria.
Las desventajas de la administración manual son: • El programador debe escribir mucho código para hacer mantenimientos repetitivos de la memoria; • La administración de memoria debe formar una parte significativa de cualquier módulo de interfaz; • La administración manual por lo general requiere más sobrecarga de memoria por objeto; •
Los errores (bugs) en la administración son comunes.
Es muy común para los programadores que se encuentran con un administrador manual ineficiente o inadecuado, escribir código para duplicar el comportamiento de un administrador de memoria, ya sea alojando grandes bloques o partiéndolos para usarlos, o reciclando los bloques internamente. Tal código se conoce como subalojador (suballocator). Los subalojadores pueden tomar ventaja del conocimiento especial del comportamiento del programa, pero son menos eficientes que arreglar el alojador. Los subalojadores pueden ser ineficientes o ineficaces a menos que un experto en administración de memoria lo implemente.
97
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Los siguientes lenguajes usan principalmente administradores de memoria manuales en varias de sus implementaciones, aunque algunos tienen extensiones para recolección de basura: Pascal; Cobol; Fortran; Algol; C; C++.
4.2.2 Administración automática La administración automática de la memoria es un servicio que puede ser parte de un lenguaje o una extensión, que automáticamente recicla la memoria que un programa no usará más. Los administradores automáticos de memoria (conocidos comúnmente como recolectores de basura, o recolectores) usualmente hacen su trabajo reciclando bloques que son inalcanzables desde las variables de un programa (es decir, bloques que no pueden alcanzarse siguiendo los apuntadores). Las ventajas de la administración automática son: • •
El programador es liberado para trabajar en el problema que está resolviendo; Las interfases de módulos son más limpias;
• •
Hay menos bugs de administración de memoria; La administración es más eficiente.
Las desventajas son: • •
La memoria puede ser retenida porque es alcanzable, pero no será usada de nuevo; Los administradores automáticos tienen (actualmente) una disponibilidad limitada.
La mayoría de los lenguajes modernos usan administración de memoria automática: Dylan, Erlang, Haskell, Java, Lisp, Perl, Prolog, Python, Scheme, Smalltalk, etc.
4.2.3 Esquemas de Administración⊕ Por mucho, el esquema más sencillo de administración de memoria es: NINGUNO. El usuario tiene a su disposición el hardware y tiene control completo sobre el espacio de direcciones de la máquina. Esto tiene sus ventajas: •
provee máxima flexibilidad al usuario, pues se puede controlar el uso de la memoria como se desee;
• • •
máxima simplicidad; no se necesita soporte de hardware adicional para la administración de la memoria; se tiene la capacidad de ejecutar un solo proceso;
•
NO se necesita de un sistema operativo.
Este esquema es usado solamente en sistemas dedicados donde los usuarios requieren flexibilidad y se requiere de rutinas de soporte propietaria.
⊕
Obras consultadas: [4.10]
98
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Pero además esto tiene sus limitaciones: NO PROVEE NINGUN SERVICIO; es decir que aunque el usuario tiene control total sobre la computadora, el SO no tiene: • • •
control sobre las interrupciones, ni mecanismos para llamadas a procesos o errores, y ningún espacio para proveer capacidades de multiprogramación.
Por lo anterior será necesario explorar esquemas que permitan proveer servicios a las aplicaciones y al sistema operativo.
Monoprogramación sin intercambio⊕
La forma más simple de administrar la memoria es ejecutando sólo un programa a la vez, que comparta la memoria con el sistema operativo (el cual está residente en la memoria alta o baja, dependiendo de donde se coloque el vector de interrupciones).
Figura 4.6 Esquemas de organización de memoria con manejo de dos particiones. En el esquema de monoprogramación por lo general, el SO está en la parte baja, los programas de usuario se cargan arriba, y un área en la parte superior se reserva para manejadores de dispositivos, etc. (fig. 4.6). Un caso de esto es MS-DOS. Cuando un usuario ejecuta un comando, el sistema operativo carga el programa correspondiente en la memoria, y lo ejecuta. Cuando el programa termina, el sistema operativo solicita un nuevo comando y carga el nuevo programa en la memoria, sobrescribiendo el anterior. La organización física bajo este esquema es muy simple: El sistema operativo se ubica en las localidades superiores o inferiores de la memoria, seguido por algunos manejadores de dispositivos (drivers). Esto deja un espacio contiguo de memoria disponible que es tomado por los programas del usuario, dejando generalmente la ubicación de la pila (stack) al último, con el objetivo de que ésta pueda crecer hasta el máximo posible. Bajo este esquema no se requieren algoritmos sofisticados para asignar la memoria a los diferentes procesos, ya que éstos son ejecutados secuencialmente conforme van terminando.
⊕
Obras consultadas: [4.11]
99
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
De esta forma solo se puede ejecutar un programa a la vez y entonces se hace un mal uso del procesador y de la memoria, pues usualmente los usuarios no ocupan todo el espacio disponible. Otro inconveniente es que no se puede correr un programa más grande que la memoria disponible sin recurrir a recubrimientos (overlays). Además se requiere de mecanismos de protección para proteger al sistema operativo contra los programas del usuario.
Multiprogramación con particiones fijas La forma más simple de obtener multiprogramación es dividiendo la memoria en n particiones fijas, de tamaños no necesariamente iguales (fig. 4.7). Puede haber una cola de trabajos por partición, o bien una sola cola general. En el primer caso, cuando llega un trabajo, se pone en la cola de la partición más pequeña en la que todavía quepa el trabajo. Si llegan muchos trabajos pequeños podría pasar que, mientras las colas para las particiones chicas están llenas, las particiones grandes quedan sin uso. En el caso de una sola cola, cada vez que un programa termina y se libera una partición, se escoge un trabajo de la cola general. ¿Cómo escoger?
Figura 4.7 Administración con particiones fijas Dentro de sus ventajas se pueden mencionar las siguientes: - Su administración es relativamente simple, pues para guardar información del estado del recurso se debe tener un registro de cada zona (libre u ocupada). - La protección entre usuarios se puede realizar mediante el mecanismo de llaves de memoria o utilizando el registro base y la longitud de la zona. Algunos de los inconvenientes que presenta este modelo, son los siguientes: - Se hace una mala utilización de la memoria debido a la poca flexibilidad del método. - Es complicado correr programas más grandes que el tamaño de la zona. - Se presenta fragmentación interna. Este fenómeno ocurre cuando un proceso no ocupa toda la memoria asignada y sin embargo el espacio libre no puede ser utilizado por ningún otro proceso.
100
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Particiones de Longitud Variable
El método de particiones de longitud variable consiste en que la memoria se divide en bloques de diferente tamaño de acuerdo a las necesidades del usuario (fig. 4.8). Una gran ventaja es su flexibilidad, pues permite definir bloques del tamaño requerido, terminando así con la fragmentación interna y permitiendo hacer un mejor uso de la memoria y por ende del procesador.
Figura 4.8 Administración con particiones variables Sin embargo, presenta algunos inconvenientes. Al partirse la memoria en bloques de tamaño diferente, puede ocurrir que el bloque más grande no pueda contener un programa dado, a pesar que la suma de los espacios libres sea mayor que el tamaño del programa. A esto se le denomina fragmentación externa. Por ejemplo, si llegase un nuevo proceso solicitando un espacio de 6 unidades de tamaño, no podría asignársele, pues no hay un espacio contiguo en la memoria de ese tamaño, a pesar de que la suma de los tamaños de los espacios libres es mayor que 6 unidades . Para solucionar este problema, se puede recurrir a realizar una compactación de la memoria, siempre y cuando se cuente con relocalización dinámica. Este procedimiento puede ser muy costoso en tiempo. • A pesar de que para ejecutar un programa solo se necesita tener cargado una parte de él, en este modelo se hace necesario tener todo el código en memoria. •
La administración de la memoria no es tan sencilla como en el caso de particiones fijas.
La protección de la memoria entre los diferentes usuarios se realiza mediante el mecanismo de registro base-registro límite. El registro base guarda la dirección donde inicia el bloque de memoria asignado al usuario y el registro límite, la dirección donde termina. Todas las direcciones del programa serán entonces un desplazamiento con respecto al registro base. Si por alguna razón, se encuentra una dirección que sobrepase al registro límite, se produce un error en el direccionamiento, (puesto que se estaría referenciando una dirección que puede pertenecer al espacio de otro usuario), se produce una interrupción y el sistema toma el control. La representación de las zonas libres y ocupadas y su administración representan un problema mayor.
101
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Registro del Uso de la Memoria El registro del uso de la memoria es un problema mayor en la asignación por particiones de longitud variable, ya que las estructuras que deben mantenerse cambian dinámicamente. Hay 2 formas básicas para llevar un registro del uso de la memoria: a) Administración de la memoria con mapas de bits. Con un mapa de bits la memoria se divide en unidades de asignación. A cada unidad de asignación le corresponde un bit en el mapa de bits, el cual toma el valor de cero (0) si la unidad está libre y de uno (1) si está ocupada (fig. 4.9).
Figura 4.9 Administración con mapa de bits7 El tamaño de la unidad de asignación define qué tan grande será el mapa de bits. Si la unidad de asignación es pequeña, el mapa de bits será mayor, caso contrario ocurre si la unidad de asignación es grande. Sin embargo, si se define demasiado grande puede generar problemas de fragmentación interna. Cuando un proceso, solicita un espacio de tamaño k unidades, el sistema debe buscar una cadena de k bits de ceros consecutivos. b) Administración de la memoria con listas ligadas. Otra forma de mantener un registro de la memoria es mediante una lista ligada de los segmentos de memoria asignados o libres, en donde un segmento puede ser un proceso o un hueco entre dos procesos (fig. 4.10).
Figura 4.10 Administración con listas ligadas8
7 8
Imagen reproducida de [4.5] Imagen reproducida de [4.5]
102
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Esta lista puede estar ordenada por direcciones en cuyo caso la actualización de la misma al terminar un proceso es casi que inmediata. Un proceso que termina tiene por lo general dos vecinos (uno por arriba y uno por abajo), a menos que se encuentre en algún extremo de la memoria. Cuando los procesos y los huecos se mantienen en una lista ordenada por direcciones, se pueden utilizar diversos algoritmos para asignar la memoria para un proceso de reciente creación. Se supone que el administrador de memoria conoce la cantidad de memoria a asignar. Entre ellos están: •
•
•
•
First Fit o el Primero en Ajustarse: El administrador de memoria revisa toda la lista de segmentos hasta encontrar un espacio lo suficientemente grande. El espacio se divide entonces en dos partes, una para el proceso y otro para la memoria no utilizada. Este algoritmo es rápido, puesto que busca lo menos posible. Siguiente en Ajustarse: Funciona de la misma forma que el anterior, con la diferencia que mantiene un registro del lugar dónde se encuentra un hueco adecuado. La siguiente vez que se le llama, comienza a buscar desde el punto donde se detuvo, en lugar de comenzar a buscar siempre desde el inicio. Best-Fit o el Mejor en Ajustarse: Busca en toda la lista y toma el mínimo hueco adecuado. En lugar de asignar un hueco grande, intenta encontrar un hueco más cercano al tamaño necesario. El peor ajuste: Toma siempre el hueco más grande disponible, de forma que el hueco resultante sea lo suficientemente grande para ser útil.
Estos cuatro algoritmos pueden agilizarse si se tienen dos listas independientes, una para los procesos y otra para los huecos. De esta forma todos ellos, pueden limitarse a inspeccionar la lista de huecos y no la de los procesos. Sin embargo, el aumentar la velocidad implica que la complejidad se aumenta y la velocidad al liberar la memoria se aumenta, ya que un segmento liberado, debe ser liberado de la lista de procesos y adicionado a la lista de huecos. Otro algoritmo de asignación es el de ajuste rápido, que consiste en tener listas independientes para algunos de los tamaños que se solicitan con mayor frecuencia. Si se solicita un espacio de tamaño típico (de los más frecuentes) se busca primero en tales listas. Igual sucede si se libera, se adiciona a una de ellas. Esto facilita la administración de la memoria puesto que se van a tener espacios libres de tamaños comunes en una lista, lo que facilita su búsqueda. Sin embargo el mantenimiento de las listas también es costoso en tiempo.
Intercambio de procesos entre memoria y disco La memoria es un recurso limitado en el sistema el cual va ha hacer posible que nuestros programas funcionen. Cualquier programa que se quiera ejecutar debe ser previamente cargado en memoria y esto hace que los SOs deban diseñar buenos algoritmos para aprovechar al máximo este recurso. Para la gestión de memoria existe dos sistemas que se pueden diferenciar claramente: los que durante la ejecución intercambian procesos entre la memoria principal y el disco, y los que no. Los segundos como es de suponer son los más sencillos.
103
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
a. Sistemas sin intercambio ni paginación. En estos sistemas la memoria que tenemos disponible para ejecutar nuestros programas, incluyendo el SO, es la memoria física que poseemos. Este método de gestión reduce mucho las posibilidades en cuanto a tamaño de los programas a ejecutar. Dentro de esta forma de gestión de memoria existen también diferentes estrategias. La más sencilla es la de tener un solo programa en memoria ejecutándose que la ocupe toda, pero este método es nefasto porque el aprovechamiento de la memoria es mínimo. La otra forma es tener particiones de la memoria de tamaño fijo de forma que puedan coexistir varios programas en la memoria principal. Así se da soporte para la multiprogramación pero se generan 2 problemas: la reubicación y la protección. Estos dos problemas están íntimamente ligados y consisten en que los programas pueden saltar a direcciones de memoria que no pertenecen a su área de direcciones. Estos problemas se soluciona dotando a la máquina registros especiales llamados registro base y registro límite, de forma que el programa genera direcciones virtuales y para acceder a la dirección real se utilizan estos registros. La dirección de memoria se calcula sumando al a dirección virtual la dirección contenida en el registro base y sólo puede llegar a la posición indicada en el registro límite. b. Sistemas con intercambio y paginación Estos sistemas a diferencia que los anteriores van a permitir que programas que posean un tamaño mayor al de la memoria puedan ejecutarse ya que el tamaño de la memoria del que disponemos es mayor que el tamaño real. El concepto de intercambio ya se ha explicado anteriormente y consiste en intercambiar procesos entre la memoria central y el disco. Los sistemas que utilizan este método no suelen dividir la memoria en particiones fijas sino que las particiones de la memoria se van creando según vayan apareciendo y desapareciendo procesos nuevos. De esta forma el aprovechamiento de la memoria es mejor, pero complica la inserción y desocupación en la memoria.
Intercambio (Swapping) El esquema de intercambio es útil en los sistemas de tiempo compartido. En estos sistemas cuando se ha finalizado una transacción con el usuario, se entra en un período de espera relativamente largo en términos del tiempo del procesador, mientras el usuario responde. Durante este tiempo, se puede cargar un nuevo programa en la zona asignada al usuario. Para ello, se requiere transferir el primer programa a la memoria auxiliar (disco) y cargar un nuevo programa en la zona. Cuando este finalice su transacción, se puede volver a cargar el primer programa (fig. 4.11). Si en un sistema interactivo no es posible mantener a todos los procesos en memoria, se puede usar el disco como apoyo para extender la capacidad de la memoria: pasar procesos temporalmente a disco.
104
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 4.11 Intercambio El sistema operativo mantiene una tabla que indica qué partes de la memoria están desocupadas, y cuáles en uso. Las partes desocupadas son hoyos en la memoria; inicialmente, toda la memoria es un solo gran hoyo. Cuando se crea un proceso o se trae uno del disco, se busca un hueco capaz de contenerlo, y se pone el proceso allí. Las particiones ya no son fijas, sino que van cambiando dinámicamente, tanto en cantidad como en ubicación y tamaño. Además, cuando un proceso es pasado a disco, no hay ninguna garantía de que vuelva a quedar en la misma posición de memoria al traerlo de vuelta, de manera que es imprescindible el apoyo del hardware para hacer ligadura en tiempo de ejecución. Si los procesos pueden crecer, conviene reservar un poco más de memoria que la que estrictamente necesita al momento de ponerlo en memoria. Al hacer swapping, no es necesario guardar todo el espacio que tiene reservado, sino sólo el que está usando. Otro punto que hay que tener en cuenta al usar swappping, es la E/S que pudiera estar pendiente. Cuando se hace, por ejemplo, input, se especifica una dirección de memoria donde se va a poner lo que se lea desde el dispositivo. Supongamos que proceso A trata de leer del disco hacia la dirección d, pero el dispositivo está ocupado: su solicitud, por lo tanto, es encolada. Entretanto, el proceso A es intercambiado a disco, y la operación se completa cuando A no está en memoria. En esas circunstancias, lo leído se escribe en la dirección d, que ahora corresponde a otro proceso.
Memoria virtual⊕
En tiempos pasados cuando un programa era más grande que el tamaño de la memoria, este debía dividirse en módulos o partes e irse cargando a medida que se iban necesitando (recubrimientos). Este trabajo correspondía al programador y esto además de ser un trabajo engorroso implicaba pérdida de tiempo. Posteriormente se creó un mecanismo para encargarle este trabajo en su totalidad al sistema operativo. La necesidad cada vez más imperiosa de ejecutar programas grandes y el crecimiento en poder de las unidades centrales de procesamiento empujaron a los diseñadores de sistemas operativos a implantar un mecanismo para ejecutar automáticamente programas más grandes que la memoria real disponible, esto es, de ofrecer memoria virtual.
⊕
Obras consultadas: [4.12] [4.13]
105
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
El método diseñado se conoce como memoria virtual. La idea fundamental detrás de la memoria virtual es que el tamaño combinado del programa, los datos y la pila de ejecución puede exceder la cantidad de memoria real disponible para él. El sistema operativo mantiene aquellas partes del programa que se están utilizando en cada momento en la memoria principal y el resto permanece en el disco. En la medida en que se vayan necesitando nuevas partes estas se intercambian con las residentes en la memoria principal. La memoria virtual se llama así porque el programador ve una cantidad de memoria mucho mayor que la real, y en realidad se trata de la suma de la memoria de almacenamiento primario y una cantidad determinada de almacenamiento secundario. El sistema operativo, en su módulo de manejo de memoria, se encarga de intercambiar programas enteros, segmentos o páginas entre la memoria real y el medio de almacenamiento secundario. Si lo que se intercambia son procesos enteros, se habla entonces de multiprogramación en memoria real, pero si lo que se intercambian son segmentos o páginas, se puede hablar de multiprogramación con memoria virtual. En los sistemas que utilizan memoria virtual, todas las direcciones son virtuales y el conjunto de todas ellas conforman el espacio de direcciones virtuales. En los computadores donde no hay memoria virtual, la dirección se coloca directamente sobre el bus de la memoria, lo que permite que se pueda acceder a la palabra de la memoria física que tenga tal dirección. Al utilizar memoria virtual, las direcciones no pasan directamente al bus de memoria, sino que van a una unidad de administración de la memoria (MMU), un conjunto de chips que asocian las direcciones virtuales con las direcciones de memoria física.
Figura 4.12 Administración con memoria virtual9 La idea central de la memoria virtual es que como la dirección es diferente de localización física, se hace necesario tomar las direcciones virtuales y convertirlas a reales para poder tener acceso a la posición de memoria correspondiente (fig. 4.12). Todas las referencias a memoria dentro de un proceso son direcciones lógicas que se traducen dinámicamente a direcciones físicas durante la ejecución. Esto quiere decir que un proceso puede cargarse y descargarse de memoria principal de forma que ocupe regiones diferentes en instantes diferentes a lo largo de su ejecución.
9
Imagen reproducida de [4.5]
106
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Un proceso puede dividirse en varias partes (páginas o segmentos) y no es necesario que estas partes se encuentren contiguas en memoria principal durante la ejecución. Esto es posible por la combinación de la traducción dinámica de direcciones en tiempo de ejecución y el uso de una tabla de páginas o de segmentos. La memoria virtual se apoya en varias técnicas interesantes para lograr su objetivo. Una de las teorías más fuertes es la del conjunto de trabajo, la cual se refiere a que un programa o proceso no está usando todo su espacio de direcciones en todo momento, sino que existen un conjunto de localidades activas que conforman el conjunto de trabajo. Si se logra que las páginas o segmentos que contienen al conjunto de trabajo estén siempre en RAM, entonces el programa se desempeñará muy bien. Otro factor importante es si los programas exhiben un fenómeno llamado localidad, lo cual quiere decir que algunos programas tienden a usar mucho las instrucciones que están cercanas a la localidad de la instrucción que se está ejecutando actualmente.
4.2.4 Problemas de la administración de memoria El problema básico de administración de la memoria es saber cuando mantener los datos que esta contiene, y cuando eliminarlos para que la memoria pueda ser reusada. Esto suena fácil, pero de hecho es un problema tan difícil que se ha convertido en un campo de estudio por sí mismo. Idealmente, los programadores no deberían de preocuparse por las cuestiones de administración de la memoria. Por desgracia, hay muchas maneras en las que una forma ineficiente de administración de la memoria (manual o automática) puede afectar la robustez y velocidad de los programas. Los problemas típicos incluyen: Liberación prematura. Muchos programas ceden memoria, pero intentan accederla después y fallan o se comportan erráticamente. Esta condición se conoce como liberación prematura, y la referencia sobreviviente a la memoria se conoce como dangling pointer. Esto usualmente se presenta en la administración manual de memoria. • Memory leak. Algunos programas ocupan continuamente memoria sin liberarla y eventualmente se quedan sin memoria. Esta condición se conoce como memory leak. • Fragmentación externa. Un alojador puede hacer su trabajo de dar y recibir bloques de memoria tan mal, que ya no pueda dar bloques lo suficientemente grandes a pesar de tener suficiente espacio en memoria. Esto es porque la memoria libre puede dividirse en bloques muy pequeños, separados por bloques que aun están en uso. Esta condición se conoce como fragmentación externa. • Mala localización de referencias (Poor locality of reference). Otro problema con la distribución de los bloques asignados viene de la forma en que el hardware moderno y los administradores de memoria de los sistemas operativos manejan la memoria: accesos sucesivos a la memoria son más rápidos si se hacen a direcciones cercanas. Si el administrador de memoria coloca muy lejos los bloques de un programa que se usan juntos, esto causará problemas en el desempeño. Esta condición se conoce como mala localización de referencias. • Diseño inflexible. Los administradores de memoria pueden causar severos problemas de desempeño si han sido diseñados con un solo uso en mente, pero son usados de forma diferente. Estos problemas ocurren porque cualquier solución de administración de memoria
•
107
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
•
tiende a hacer suposiciones sobre la forma en que los programas van a usar la memoria, como tamaños típicos de bloques, patrones de referencia, o tiempos de vida de los objetos. Si tales suposiciones están equivocadas, entonces el administrador de memoria puede gastar mucho tiempo tratando de lidiar con lo que en realidad este sucediendo. Complejidad de la interfaz. Si los objetos son pasados entre módulos, entonces el diseño de la interfaz debe considerar la administración de su memoria.
Un administrador de memoria bien diseñado puede hacer más fácil crear herramientas de depuración, porque mucho del código puede ser compartido. Tales herramientas podrían desplegar objetos, ligas de navegación, validar objetos o detectar acumulaciones anormales de cierto tipo de objetos o tamaños de los bloques de memoria.
4.2.5 Caso de estudio: Sistema de administración de memoria de Linux El administrador de memoria de Linux (fig. 4.13) provee dos interfaces para sus recursos: •
una interfaz de llamadas al sistema, usada por los procesos de usuario, y
•
una interfaz usada por otros subsistemas del kernel para realizar sus tareas.
a. Interfaz de llamadas al sistema • •
malloc() / free() – aloja o libera una región de memoria para que el proceso lo use mmap() / munmap() / msync() / mremap() – mapea archivos en la memoria virtual
• •
mprotect – cambia la protección en una región de la memoria virtual mlock() / mlockall() / munlock() / munlockall() – rutinas de súper usuario para prevenir que la memoria sea intercambiada swapon() / swapoff() - rutinas de súper usuario para agregar y quitar archivos swap del sistema
•
b. Interfaz Intra-Kernel • kmalloc() / kfree() - aloja y libera memoria para el uso de las estructuras de datos del kernel • verify_area() - verifica que una región de memoria de usuario sea relacionada con los permisos correspondientes •
get_free_page() / free_page() - aloja y libera página de memoria física
Además de las interfaces, el administrador construye todas sus estructuras de datos y la mayor parte de sus rutinas están disponibles en el kernel. Varios de los módulos del kernel se comunican con el administrador por medio del acceso a las estructuras de datos y detalles de implementación del subsistema.
108
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 4.13 Dependencias y flujos de control y datos en el administrador de memoria10 El administrador de memoria del SO usa al administrador de memoria de hardware para relacionar direcciones virtuales (usadas por los procesos de usuario) a direcciones de la memoria física. Cuando un proceso de usuario acceda una dirección de memoria, el administrador de memoria de hardware traduce la dirección virtual a una dirección física, y luego usa la dirección física para realizar el acceso (los procesos de usuario no se dan cuenta de esto, lo que permite mover procesos a cualquier parte de la memoria física, y que incluso dos procesos compartan la misma área de memoria física). Además, el administrador intercambia (swaps) memoria de procesos a un archivo de paginación cuando no está en uso. Esto permite al sistema ejecutar procesos que usan más memoria física que la disponible en el sistema (esto lo hace un demonio (o hilo del kernel que puede acceder directamente a las estructuras de datos) llamado (kswapd)).
10
Imagen reproducida de [4.15]
109
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 4.14 Estructura del administrador de memoria de Linux11
Asignación de la memoria⊕
4.3
La asignación de memoria es el proceso de alojar bloques de memoria por petición. Un método de asignación de memoria es la manera mediante la cual el sistema operativo lleva el control de la memoria tratando de que sea lo más eficiente posible. Los métodos de asignación más comunes son: • Alojamiento contiguo • • •
Paginación Segmentación Segmentación con paginación
4.3.1 Alojamiento contiguo y no contiguo El alojamiento contiguo es uno de los esquemas más sencillos de alojamiento de memoria. En este esquema, las instrucciones para el proceso son almacenadas de forma contigua (en un bloque). La memoria es dividida en particiones, y cada una contiene exactamente un proceso. Inicialmente, toda la memoria está disponible para los procesos del usuario, y se considera como un gran bloque único de memoria disponible. El sistema operativo mantiene una tabla que indica que partes de la memoria están disponibles y cuales están ocupadas.
11 ⊕
Imagen reproducida de [4.16] Obras consultadas:[4.3] [4.11]
110
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Cuando un proceso llega y necesita memoria, el sistema operativo busca en la tabla un espacio suficientemente grande para el proceso. Si tal espacio está disponible, la memoria es asignada al proceso. Cuando un proceso termina su ejecución, libera su memoria, la cual puede ser asignada por el sistema operativo a otro proceso. La asignación no contigua significa que la memoria se asigna de tal modo que partes de un objeto lógico pueden ser colocadas en áreas no contiguas de memoria física. La traducción de direcciones efectuada durante la ejecución de las instrucciones, establece la correspondencia necesaria entre un espacio de direcciones virtuales contiguo y las posiciones físicas no contiguas de las posiciones en donde se encuentran los objetos en memoria física en tiempo de ejecución.
4.3.2 Estrategias de asignación Sin embargo, en cualquier momento, hay un conjunto de espacios, de varios tamaños, distribuidos en la memoria. Cuando llega un proceso, el SO debe elegir en que espacio debe alojar el proceso. Por lo general, el alojador recibe memoria del sistema operativo en un pequeño numero de grandes bloques que deben ser divididos para satisfacer las peticiones por bloques más pequeños. También hace que los bloques regresados estén disponibles para su reutilización. Las siguientes estrategias son usadas para este propósito: • • •
First-fit. Asignar el primer espacio que sea suficientemente grande. La búsqueda de un espacio termina tan pronto como se encuentra uno del tamaño del proceso. Best-fit. Asignar el espacio más pequeño que es suficientemente grande. El conjunto entero de espacios se necesita examinar. Esta estrategia produce el hueco más pequeño disponible. Worst-fit. Asignar el espacio más grande. De nuevo, el conjunto entero de espacios se necesita examinar. Esta estrategia produce el espacio más grande que queda que puede ser más útil que el espacio más pequeño.
Las simulaciones han mostrado que los las técnicas first-fit y best-fit son mejores que el worstfit en términos de disminuir el tiempo e incrementar el uso del almacenamiento.
4.3.3 Fragmentación y compactación Todas las estrategias descritas antes sufren de fragmentación externa. Esto se da cuando hay suficiente memoria disponible para alojar un proceso, pero esta dispersa en espacios no contiguos (el almacenamiento se fragmenta en varios pequeños espacios, suficientes para cargar un proceso pero esparcidos en la memoria). Una solución a este problema es la compactación. Esto se encarga de reacomodar la memoria para que todos los bloques libres se combinen en un solo bloque.
111
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Otro problema que puede ocurrir con el alojamiento contiguo es la fragmentación interna. Si a un proceso le es asignada más memoria de la que necesita por que no había un espacio disponible en el que ajustara exactamente, habrá memoria que el proceso tiene pero no ocupa. La fragmentación interna es entonces interna al proceso.
Subalojadores
Hay muchos ejemplos de programas de aplicación que incluyen adicionalmente código de administración de memoria, llamado un subalojador. Un subalojador obtiene grandes bloques de memoria del sistema de administración de memoria, y asigna la memoria a la aplicación en piezas más pequeñas. Los subalojadores por lo general se escriben por alguna de las siguientes razones: • • •
Para evitar ineficiencia general en el sistema de administración de memoria; Para tomar ventaja de conocimiento especial de los requerimientos de memoria de la aplicación que no pueden ser expresados al sistema de administración de memoria; Para proveer servicios de administración de memoria que el sistema de administración no ofrece.
En general, los subalojadores son menos eficientes que tener un solo administrador de memoria que esté bien escrito y tenga una interfaz flexible. Es también más difícil evitar errores de administración de memoria, si el administrador de memoria se compone de varias capas, y si cada aplicación tiene su propia versión del subalojador. Muchas aplicaciones tienen uno o dos tamaños de bloques que forman la mayoría de sus asignaciones. Uno de los usos comunes del subalojador es suplir a la aplicación con objetos de un tamaño uniforme, lo que reduce el problema de fragmentación externa. Hay peligros involucrados en el uso de conocimiento especial de los requerimientos de memoria de una aplicación. Si tales requerimientos cambian, entonces el rendimiento del subalojador tiende a ser peor que el del alojador general. A veces es mejor tener un administrador de memoria que pueda responder dinámicamente a los requerimientos variables.
4.3.4 Paginación La paginación consiste en considerar el espacio de direcciones lógicas de cada proceso como un conjunto de bloques de tamaño consistente llamados páginas. Cada dirección lógica manejada para un proceso estará conformada por un par de valores [página: desplazamiento] (fig. 4.15). La memoria física se administra implementando bloques de tamaño consistente denominados
marcos. Obviamente el tamaño de un marco debe ser igual al tamaño de una página. Por lo general el tamaño designado para los marcos y páginas es pequeño.
112
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 4.15 En la paginación el tamaño de la página debe ser una potencia de 212 Las páginas de un proceso son mapeadas en la memoria principal usando una tabla de páginas, que define que parte de la memoria física contiene a la página en particular. La implementación de la tabla de páginas puede ser: 1. Implementada completamente en hardware. a. VENTAJA: Se obtiene una alta velocidad de acceso a memoria. b. DESVENTAJA: Resulta problemática cuando la tabla de páginas debe ser grande. 2. Implementada en la memoria principal. a. VENTAJA: La tabla de páginas puede crecer según se requiera. b. DESVENTAJA: La velocidad de acceder a memoria es relativamente baja, dado que cada referencia a memoria involucra 2 accesos.
Figura 4.16 Traducción de direcciones en un sistema de paginación13 12 13
Imagen reproducida de [4.3] Imagen reproducida de [4.3]
113
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
La paginación pura en el manejo de memoria consiste en que el sistema operativo divida dinámicamente los programas en unidades de tamaño fijo (generalmente múltiplos de 1 kilobyte) los cuales va a manipular de RAM a disco y viceversa. Al proceso de intercambiar páginas, segmentos o programas completos entre RAM y disco se le conoce como intercambio o swapping. En la paginación, se debe cuidar el tamaño de las páginas, ya que si éstas son muy pequeñas el control por parte del sistema operativo para saber cuáles están en RAM y cuales en disco, sus direcciones reales, etc., crece y provoca mucha sobrecarga (overhead). Por otro lado, si las páginas son muy grandes, la sobrecarga disminuye pero entonces puede ocurrir que se desperdicie memoria en procesos pequeños. Debe haber un equilibrio.
Figura 4.17 Direccionamiento en MS-DOS usando segmentación (8086-16 bits). Capacidad de direccionamiento 220=1'048,576=1MB.14 Cuando se está buscando una página cualquiera y ésta no está cargada, surge lo que se llama un fallo de página (page fault). Esto es caro para el manejador de memoria, ya que tiene que realizar una serie de pasos extra para poder resolver la dirección deseada y darle su contenido a quien lo pide. Primero, se detecta que la página no está presente y entonces se busca en la tabla la dirección de esta página en disco. Una vez localizada en disco se intenta cargar en alguna página libre de RAM. Si no hay páginas libres se tiene que escoger alguna para enviarla hacia el disco. Una vez escogida y enviada a disco, se marca su valor de control en la tabla de direcciones virtuales para indicar que ya no está en RAM, mientras que la página deseada se carga en RAM y se marca su valor para indicar que ahora ya está en RAM. Todo este procedimiento es caro, ya que se sabe que los accesos a disco duro son del orden de decenas de veces más lentos que en RAM. En el ejemplo anterior se mencionó que cuando se necesita descargar una página de RAM hacia disco se debe de hacer una elección. Para realizar esta elección existen varios algoritmos, los cuales se describen a continuación. •La primera en entrar, primera en salir. Se escoge la página que haya entrado primero y esté cargada en RAM. Se necesita que en los valores de control se guarde un dato de tiempo. No es eficiente porque no aprovecha ninguna característica de ningún sistema. Es justa e imparcial.
14
Imagen reproducida de [4.3]
114
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
•La no usada recientemente. Se escoge la página que no haya sido usada (referenciada) en el ciclo anterior. Pretende aprovechar el hecho de la localidad en el conjunto de trabajo. •La usada menos recientemente. Es parecida a la anterior, pero escoge la página que se usó hace más tiempo, pretendiendo que como ya tiene mucho sin usarse es muy probable que siga sin usarse en los próximos ciclos. Necesita de una búsqueda exhaustiva. •La no usada frecuentemente. Este algoritmo toma en cuenta no tanto el tiempo, sino el número de referencias. En este caso cualquier página que se use muy poco, menos veces que alguna otra. •La menos frecuentemente usada. Es parecida a la anterior, pero aquí se busca en forma exhaustiva aquella página que se ha usado menos que todas las demás. •En forma aleatoria. Elige cualquier página sin aprovechar nada. Es justa e imparcial, pero ineficiente. Otro dato interesante de la paginación es que ya no se requiere que los programas estén ubicados en zonas de memoria adyacente, ya que las páginas pueden estar ubicadas en cualquier lugar de la memoria RAM.
Reemplazo de páginas
Cuando ocurre un defecto de página (interrupción que se lanza cuando se hace referencia a una dirección virtual que no se encuentra en la memoria real), el sistema operativo debe seleccionar una página para retirarla de la memoria real y así dejar un marco vacío que contendrá a la página referenciada. Si el marco seleccionado contiene una página que haya sido modificada, esta deberá ser escrita de nuevo al disco. Por el contrario, si no se ha modificado, la página a cargar reemplazará a la existente en memoria real sin necesidad de rescribirla, pues su imagen en disco es idéntica a la existente en memoria principal. A pesar de que se puede elegir una página al azar, es mejor seleccionar una de poco uso para favorecer el Principio de Optimalidad dice que el mejor algoritmo de reemplazo será aquel que seleccione la página que será referenciada más tarde en el tiempo. A pesar de ser muy fácil de enunciar, este principio es imposible de implementar pues para ello se requeriría saber de antemano, el orden en el que van a ser referenciadas las páginas. Dentro de los algoritmos realizables, los más conocidos son los siguientes: • •
Aleatorio: No respeta el principio de localidad. FIFO (First Input First Output): reemplaza las páginas en el orden de llegada. No respeta el principio de localidad.
• •
LFU (Least Frequently Used): Elige la página menos frecuentemente usada. MRU (Most Rencently Used): Selecciona la página más recientemente referenciada. A pesar de no respetar el principio de localidad, puede comportarse bien en sistemas interactivos, en donde existen períodos largos de tiempo mientras el usuario responde al sistema. LRU (Least Recently Used): Elige la página menos recientemente usada. Se basa en el principio de localidad.
•
Este último es uno de los más utilizados a pesar de que para su implementación se requieren mecanismos sofisticados, ya que para poder llevarlo a cabo, se requeriría guardar para cada
115
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
página la hora exacta en la cual ocurrió la última referencia, lo cual implicaría ampliar el tamaño de la entrada en la tabla de páginas, lo que resulta muy costoso. Por esta razón, se recurre a una aproximación que consiste en que cada vez que la página es referenciada, el bit de referencia se prende en la entrada correspondiente en la tabla de páginas. Periódicamente, un proceso demonio (un proceso background del sistema operativo), se encarga de apagar tal bit en aquellas páginas que lo tengan prendido. Cuando se necesita un marco, se selecciona una de aquellos que contengan páginas que tengan el bit apagado.
4.3.5 Segmentación Este método consiste en la asignación de bloques de memoria de tamaño variable, llamados
segmentos. El tamaño de cada segmento será el requerido según la petición, por ejemplo el tamaño del proceso a cargar. El tamaño máximo para un segmento estará determinado por la capacidad de direccionamiento del hardware de la computadora, esto es, de cuantos bits se dispone para almacenar una dirección. El acceso a cada elemento individual (byte) en la memoria se hace mediante una dirección de memoria que se integra por dos elementos: una dirección de segmento y una de desplazamiento. La combinación (suma) de la dirección de segmento y la de desplazamiento generan la dirección de memoria absoluta a acceder.
Figura 4.18 Traducción de direcciones en la segmentación15 Prácticamente la traducción es igual que la llevada a cabo en la paginación pura, tomando en consideración que el tamaño de los bloques a controlar por la tabla de traducción son variables, por lo cual, cada entrada en dicha tabla debe contener la longitud de cada segmento a controlar. Otra vez se cuenta con un registro base que contiene la dirección del comienzo de la tabla de segmentos. La dirección virtual se compone de un número de segmento (s) y un desplazamiento (d) para ubicar un byte (o palabra) dentro de dicho segmento. Es importante que el desplazamiento no sea mayor que el tamaño del segmento, lo cual se controla simplemente checando que ese valor sea mayor que la dirección del inicio del segmento y menor que el inicio sumado al tamaño. La segmentación se aprovecha del hecho de que los programas se dividen en partes lógicas, como son las partes de datos, de código y de pila (stack). La segmentación asigna particiones de memoria a cada segmento de un programa y busca como objetivos el hacer fácil el compartir 15
Imagen reproducida de [4.3]
116
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
segmentos (por ejemplo librerías compartidas) y el intercambio entre memoria y los medios de almacenamiento secundario.
Figura 4.19 Traducción de direcciones en un sistema con segmentación16 Por ejemplo, en la versión de UNIX SunOS 3.5, no existían librerías compartidas para algunas herramientas, por ejemplo, para los editores de texto orientados al ratón y menús. Cada vez que un usuario invocaba a un editor, se tenía que reservar 1 megabyte de memoria. Como los editores son una herramienta muy solicitada y frecuentemente usada, se dividió en segmentos para la versión 4.x ( que a su vez se dividen en páginas ), pero lo importante es que la mayor parte del editor es común para todos los usuarios, de manera que la primera vez que cualquier usuario lo invocaba, se reservaba un megabyte de memoria como antes, pero para el segundo, tercero y resto de usuarios, cada editor extra sólo consumía 20 kilobytes de memoria. El ahorro es impresionante. Obsérvese que en la segmentación pura las particiones de memoria son de tamaño variable, en contraste con páginas de tamaño fijo en la paginación pura. También se puede decir que la segmentación pura tiene una granularidad menor que la paginación por el tamaño de segmentos versus tamaño de páginas.
4.3.6 Segmentación con paginación Tanto la segmentación como la paginación ofrecen significativas ventajas, algunos sistemas (Multics y la Serie 370 de IBM) combinan ambas técnicas en donde los segmentos tienen un tamaño múltiplo de página. Este método utiliza Segmentación y Paginación tal y como su nombre lo indica, el proceso es el siguiente: • Se hace la solicitud de acceso por medio de una dirección V la cual contiene los campos Segmento, Página y Desplazamiento. Con el campo Segmento, lo que se trata es de accesar a una Tabla de segmentos, cada campo de dicha tabla apunta directamente a la tabla de páginas asignada para ese segmento conteniendo una dirección que será sumada a una 16
Imagen reproducida de [4.3]
117
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
dirección en la Tabla Asociativa para por fin formar una dirección real con el desplazamiento de V (fig. 4.20).
Figura 4.20 Método de segmentación y paginación17 En un sistema con un número muy grande de procesos, segmentos o paginas, ésta estructura puede consumir una parte muy importante de la memoria real. La cuestión es que la traducción de direcciones puede realizarse con rapidez pero si se tienen demasiadas tablas, el sistema puede soportar menos procesos y bajar su rendimiento
Figura 4.21 Traducción de direcciones en un sistema con segmentación y paginación18
17 18
Imagen reproducida de [4.3] Imagen reproducida de [4.3]
118
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
4.4
Simulación del servicio de administración de memoria
Con el fin de integrar los conceptos y técnicas descritos en las secciones anteriores de este capítulo, se implemento un pequeño simulador para ejemplificar la administración de la memoria. Después de analizar la información presentada en este capítulo, pueden distinguirse 2 escenarios de administración en relación a los programas: • •
Los esquemas que manejan programas como bloques monolíticos (todo el código del programa está en un bloque) Los esquemas que manejan programas en forma de módulos (p.ej. en el caso de usar overlays, librerías dinámicas, etc.)
Programa = un solo bloque de código Particiones fijas PP
Particiones variables
PP
Paginación
PP
Figura 4.22 Los esquemas de particiones fijas, variables y paginación manejan programas como bloques únicos. Para mostrar el funcionamiento de la administración de memoria, se eligió implementar la simulación usando el esquema de multiprogramación en sus dos variantes: particiones fijas y particiones dinámicas. Esto permite mostrar los mecanismos que se requieren para la administración de forma sencilla (si alguien se interesa en los otros esquemas es un buen ejercicio pero está fuera del alcance del trabajo; sin embargo hay simuladores específicos que abordan el tema).
119
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Programa = Programa principal + módulos
PP
Segmentación
PP
Segmentación con Paginación por demanda
Figura 4.23 La segmentación y la segmentación con paginación son más aptos para manejar programas y módulos dinámicos. Los objetivos del simulador son: •
aplicar los conceptos relacionados a la administración de la memoria
• •
entender cómo se implementan los componentes de un administrador de memoria contar con una herramienta que permita visualizar el comportamiento de la memoria durante la ejecución de programas
•
tener la capacidad de observar fenómenos como la fragmentación
En principio, lo único que se modelará será la memoria y el administrador de la memoria. Elementos como el almacenamiento secundario, el procesador, etc., no son modelados de forma explicita. Para acotar el modelo hay que tomar en cuenta que: • •
el único hardware a modelar es la memoria principal (RAM) el esquema de alojamiento de memoria es contiguo
• • •
la administración se hará de forma automática solo se tomará en cuenta el tamaño y tiempo de ejecución de los programas no se implementan métodos sofisticados de optimización (pero se implementa un sencillo mecanismo de compactación en el caso de las particiones variables) Así, los principales componentes del simulador son:
•
•
Programa. El programa que se cargará en la memoria, convirtiéndose en proceso. En el simulador se representará mediante un objeto con atributos de tiempo y tamaño (del código y memoria reservada), así como un identificador. Generador de Programas. Se encarga de generar de forma aleatoria, programas que serán procesados por el administrador de memoria.
120
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
•
• •
•
Memoria principal. El almacenamiento primario donde se almacenan las instrucciones del programa; en este caso, no son instrucciones lo que se almacena, sino que solo se marca la memoria usada por un proceso con el valor del identificador del proceso correspondiente. Administrador de memoria. Encargado de la carga, asignación y desasignación de la memoria para los procesos. Tablas de asignación. Son las estructuras encargadas de registrar la relación entre la memoria disponible, y los recursos asignados. Su implementación varía dependiendo del tipo de particiones a manejar. Controlador del simulador. Encargado de implementar el control de los componentes del modelo. Cabe mencionar que parte de su implementación funciona de forma indirecta como el procesador del sistema modelado, pues es el encargado de determinar que procesos han cumplido con su tiempo de latencia en el sistema.
Figura 4.24 Modelo de clases del simulador de administración de memoria. Lo más interesante es observar el comportamiento de cada enfoque de manejo de memoria, y como al transcurrir el tiempo, los recursos deben de ser reasignados.
121
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 4.25 Ejecución del simulador. El código del simulador puede ser consultado en el apéndice "Simulador del servicio de administración de memoria".
4.5
Comentarios
El sistema de administración de memoria está dedicado a manipular el código y los datos que integran una aplicación, y por lo tanto está muy relacionado al sistema de administración de procesos. Por ello fue necesario en el primer capítulo introducir toda la terminología relacionada a todos los subsistemas de los sistemas operativos, pues es difícil hablar de ambos en forma aislada. Cabe mencionar que todos los esquemas de administración de memoria presentados se aplican por lo general a una sola máquina, aunque es posible ampliar estos conceptos a esquemas distribuidos donde se trate de unificar las capacidades de memoria de varios equipos en un solo recurso. En el siguiente capítulo se exponen los principales aspectos de la administración de procesos, y con ello se tendrá una visión más amplia de las funciones de base de un sistema operativo.
122
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
4.5
Obras consultadas
[4.1] Estudio Sistemas Operativos Moisés Domènech Lloca. 1998.
[4.10] Operating Systems concepts. A. Silberschatz, J. Peterson, P. Galvin. Addison Wesley. 1991. ISBN 0-201-54873-9
[4.2] Fundamentals of operating systems http://www.cs.wayne.edu/~tom/guide/os.html [4.3] Tutorial de sistemas operativos II. ITLP http://www.itlp.edu.mx/publica/tutoriales/sistemasoper ativos2/index.htm [4.4] Sistemas Operativos. UDLA http://lara.pue.udlap.mx/sist_oper/ [4.5] 150802 SISTEMAS OPERATIVOS I. UFPS. Facultad de Ingeniería. http://bari.ufps.edu.co/personal/150802A/memoria.htm
[4.11] IIC2332- Apuntes de clase http://www2.ing.puc.cl/~jnavarro/iic2332/apuntes/apu ntes_6.html [4.12] Introduction to Operating Systems Kathryn S. McKinley. University of Massachusetts .Fall 1997 http://www-aml.cs.umass.edu/~cs377/ [4.13] Memoria Virtual. Alberto Pacheco http://www.socrates.itch.edu.mx/~apacheco/os/memvi rt.htm http://200.34.100.10/~apacheco/os/memvirt.htm http://www.mycgiserver.com/~apacheco/os.html
[4.6] The Free Online Dictionary of Computing. Denis Howe
[4.14] Basics of computer memory. OSData.com
http://foldoc.doc.ic.ac.uk
http://www.osdata.com/system/physical/memory.htm
[4.7] Webopedia
[4.15] Conceptual Architecture of the Linux Kernel. Ivan Bowman (
[email protected]) January 1998
http://www.pcwebopedia.com/TERM/m/MMU.html
http://plg.uwaterloo.ca/~itbowman/CS746G/a1/ [4.8] The Memory Management Reference. Xanalys, Harlequin. http://www.xanalys.com/software_tools/mm/ [4.9] CS 537 Lecture Notes Paging http://www.cs.wisc.edu/~solomon/cs537old/f96/paging.html
[4.16] Concrete Architecture of the Linux Kernel. Ivan Bowman (
[email protected]), Saheem Siddiqi (s4siddiqi@neumann), Meyer C. Tanuan (
[email protected]). Department of Computer Science, University of Waterloo. Winter 1998 http://plg.uwaterloo.ca/~itbowman/CS746G/a2
123
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
124
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Capitulo 5. Administración de procesos Lo que conduce y arrastra al mundo no son las máquinas sino las ideas. Víctor Hugo
Un sistema operativo puede ejecutar una gran variedad de programas, y para ello, debe brindar un ambiente y soporte adecuado para su ejecución. El cómo iniciar la ejecución de un programa, cómo permitir que varios programas se ejecuten a la vez, se comuniquen entre ellos, etc., es responsabilidad del subsistema del sistema operativo encargado de la administración de procesos. En este capítulo se trata de dar respuesta a las siguientes interrogantes: • •
¿qué son los procesos y para qué sirven? ¿cuál es el papel del sistema operativo en la administración de procesos?
• •
¿qué es la planificación de procesos y cómo se hace? ¿qué son los procesos concurrentes y sus implicaciones de implementación?
5.1
Ejecución de programas y procesos
5.1.1 Modelos de ejecución⊕ Los modelos de ejecución pueden representar una perspective abstracta de la ejecución de un programa o pueden representar de hecho la dinámica de ejecución de un programa en un sistema de cómputo. Dependiendo de la arquitectura de la computadora y el soporte que se requiera para la ejecución de programas, se plantean los siguientes modelos de ejecución (fig. 5.1):
⊕
Modelo secuencial (Von Neumann), en donde se ejecuta una instrucción a la vez. El problema es que si existe un error en una instrucción todo el programa se bloquea. Modelo de flujo de datos, en donde cada instrucción del programa se ejecuta cuando todos sus operandos están disponibles, lo que permite la ejecución asíncrona de instrucciones; si una instrucción tiene un error no bloquea al resto del programa. Modelo de multihilado, es la intersección de los modelos anteriores, en donde se ejecutan bloques de instrucciones pertenecientes a subprogramas (hilos); las instrucciones de cada hilo se jecuta de forma secuencial, mientras los hilos se ejecutan
Obras consultadas: [5.40]
125
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
independientemente; si una instrucción provoca un error, el hilo correspondiente se bloquea, pero los otros hilos continuan su ejecución.
Figura 5.1 Modelos de ejecuciónen sistemas de cómputo19 En los viejos sistemas de cómputo, los sistemas operativos permitían solo la ejecución secuencial de programas (fig. 5.1a), aunque durante su evolución la ejecución de varias tareas como operaciones de impresión y luego otros programas, fue haciéndose posible.
Figura 5.1a Esquema de un sistema monotarea En los sistemas de lotes se ejecutaban trabajos, y en los sistemas de tiempo compartido las ejecuciones eran llamadas programas de usuario o tareas. La multiprogramación implica que existan varios programas que se ejecutan a la vez (fig. 5.1b). La abstracción para un programa en ejecución es un proceso, el cual es un concepto reciente pues las primeras máquinas y las PCs no tenían procesos. 19
Imagen reproducida de [5.40]
126
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Figura 5.1b Esquema de un sistema multitarea
5.1.2 Procesos⊕ Podemos iniciar por preguntarnos, ¿qué es un proceso? Para ello tenemos las siguientes respuestas: •
Un proceso no es el código de un programa.
• •
Cada invocación de un programa es un proceso distinto. Un proceso es una actividad que se apoya en datos, recursos, un estado en cada momento y un programa.
Un proceso es más que el código de un programa y la actividad que este desarrolla. Cada proceso tiene su propio contador de programa, que es el registro que le dice en que parte del programa está. También necesita un lugar para almacenar las direcciones de retorno cuando llama a una subrutina, para que en el caso de que dos procesos ejecuten la misma subrutina desde diferentes lugares, pueda regresar a los puntos de inicio adecuados. Puesto que las subrutinas pueden llamar otras subrutinas, cada proceso necesita su propia pila de direcciones de retorno, así como espacio para variables locales y globales. Cuando el sistema operativo ofrece la capacidad de ejecutar múltiples procesos, los procesadores son virtuales y el núcleo multiplexa el procesador real disponible en lapsos de tiempo que otorga por turnos a los distintos procesos.
⊕
Obras consultadas: [5.26] [5.27]
127
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Cuando la computadora es multiprocesador y el sistema operativo está diseñado para explotar todos los procesadores disponibles, entonces los procesos se pueden ejecutar efectivamente en paralelo.
5.1.3 Hilos⊕ Un problema con el uso de procesos múltiples es que los cambios de contexto son muy costosos. Un segundo problema es que el poder compartir los recursos como datos, archivos abiertos, I/O con el usuario, etc., puede ser difícil. Los hilos (threads) son entidades separadas de ejecución dentro de un espacio existente de direcciones, que poseen su propio contador de programa, registros y pila. Al hacer referencia al término espacio de direcciones, esto quiere decir que el hilo comparte sus secciones de código y datos con otros hilos. Un proceso normal (o proceso pesado) puede contener muchos hilos. Un proceso secuencial tiene un solo flujo de control (una secuencia de instrucciones ejecutadas por el proceso). En un proceso multihilado, hay diversos flujos de control planificables llamados hilos. Los hilos están asociados con una secuencia de instrucciones, y comúnmente se les refiere como hilos de ejecución. Tradicionalmente, las aplicaciones eran partidas en múltiples procesos, y alguna forma de comunicación entre procesos era usada para comunicar a los procesos. Un proceso multihilado tiene mas de un hilo de control que comparte tanto el espacio de direcciones como los recursos. El uso de hilos elimina la necesidad de cualquier forma de comunicación entre procesos y reduce la sobrecarga en los cambios de contexto. Los hilos también son conocidos como procesos ligeros (lightweight processes -LWPs), pues el contexto que se mantiene para los hilos es mucho más ligero que el de los procesos. Aún cuando los hilos son entidades ejecutables, esto no significa que se ejecuten en paralelo. Los hilos pueden ser planificados concurrentemente en varios procesadores, mientras que en máquinas con un solo procesador el tiempo de ejecución se reparte. Con Solaris 2.2, Sun introdujo una librería de hilos para desarrollo de aplicaciones que aprovechara las características de multiprocesamiento y multihilado de su nuevo kernel. A partir del modelo de Solaris (el cual usa un modelo de dos capas de hilos) se tienen los siguientes esquemas de implementación: • los hilos de usuario, los cuales son manejados por la librería de hilos, y administrados en el espacio de usuario. El SO no se percata de su existencia, pues la alternancia entre hilos no requiere de llamadas al sistema o interrumpir al kernel, por lo que es muy rápida. Una desventaja de este esquema es que si uno de estos hilos se bloquea al ejecutar una llamada al sistema, el kernel bloquea a todo el proceso, pues no se da cuenta de que existan otros hilos. ⊕
Obras consultadas: [5.1]
128
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
•
los hilos del kernel (LWPs), que usan los recursos del kernel y son las entidades planificables del sistema. En este caso el kernel esta al tanto de la existencia de varios hilos por proceso, por lo que si un hilo se bloquea, el SO escoge otro para continuar la ejecución, ya sea del mismo espacio o de otro diferente.
El objetivo de los hilos es facilitar la escritura de aplicaciones concurrentes (ver sección 5.4). Ya que los hilos comparten los recursos, un proceso pesado puede contener varios hilos sin un costo adicional (solo los bloques de control de sus hilos). Además la comunicación entre los hilos del proceso es más sencilla pues comparten la memoria. Sin embargo, su uso implica la necesidad de controlar el acceso a los datos compartidos.
5.1.4 Representación de los procesos Un proceso se representa, desde el punto de vista del sistema operativo, por un conjunto de datos donde se incluyen su estado en cada momento, recursos utilizados, registros, etc., denominado Bloque de Control de Procesos (PCB).
Figura 5.2 Esquema del intercambio de procesos con el CPU en un sistema multitarea. Los objetivos del bloque de control de procesos son los siguientes: • •
Localización de la información sobre el proceso por parte del sistema operativo. Mantener registrados los datos del proceso en caso de tener que suspender temporalmente su ejecución o reanudarla. La información contenida en el bloque de control es la siguiente:
•
Estado del proceso. Información relativa al contenido del contador del programa (Program Counter, PC), estado de procesador en cuanto a prioridad del proceso, modo de ejecución, etc., y por último el estado de los registros internos de la computadora.
129
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
•
Estadísticas de tiempo y ocupación de recursos para la gestión de la planificación del procesador.
• •
Ocupación de memoria interna y externa para el intercambio (swapping). Recursos en uso (normalmente unidades de entrada/salida).
• •
Archivos en uso. Privilegios.
Esta información relativa al estado del proceso, se encuentra siempre en memoria principal y se accede a ella en los momentos en que se hace necesaria su actualización o consulta. Todos los bloques de control son almacenados en una estructura llamada tabla de procesos. Existe un Bloque de Control de Sistema (SCB) con objetivos similares al anterior y entre los que se encuentra el enlazado de los bloques de control de procesos existentes en el sistema. La operación de guardar el estado de un proceso (en su PCB) y recuperar el estado de otro es un cambio de contexto. El cambio de contexto se producirá en caso de ejecutar una instrucción privilegiada, una llamada al sistema operativo o una interrupción, es decir, siempre que se requiera la atención de algún servicio del sistema operativo (fig. 5.2). El SO es responsable de las siguientes actividades relacionadas con la administración de procesos: • • •
creación y borrado de los procesos del sistema y el usuario; planificación de los procesos; proveer mecanismos para la sincronización, comunicación, y manejo de bloqueos (deadlock handling) para los procesos.
En las siguientes secciones se revisa cada una de estas actividades.
5.1.5 Creación de procesos Los procesos por lo general son creados, ya sea: • •
por el SO para ejecutar programas, o bajo el control del usuario (si está contemplado y permitido por el sistema, como en UNIX con la instrucción fork()).
La creación de un proceso involucra en el lado del SO: • La creación de la imagen de un proceso en un cierto espacio de direcciones, lo cual involucra la carga del código ejecutable para la tarea de un medio de almacenamiento secundario; • La creación e inicialización de un PCB para el proceso, y su inserción en una de las estructuras de control de procesos. Los procesos pueden crear procesos nuevos, donde se llama padre al proceso creador e hijo al proceso creado. Los hijos pueden obtener sus recursos (tiempo de la CPU, archivos, memoria, etc.) del SO o de un subconjunto de los recursos del padre. El hijo puede ser un programa nuevo o un duplicado del espacio de direcciones del padre.
130
Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Cabe mencionar que los procesos son creados por medio de una llamada al sistema (en Windows se hace por medio de la función CreateProcess, y en Unix por medio de la operación fork). Un proceso termina cuando realiza una llamada especifica al sistema (p.ej. exit), o si se genera una excepción (error) y el SO decide abortarlo. Cuando un nuevo proceso es creado, necesita saber donde empezar a ejecutarse. En Java, cuando un objeto es creado se le da a un hilo. Cuando es iniciado, comienza su ejecución al principio del método run() del objeto. En Unix, un nuevo proceso se inicia con el comando fork(), el cual comienza un nuevo proceso ejecutándose en el mismo programa, comenzando en la declaración siguiente inmediata a la llamada del fork(). Después de la llamada, tanto el proceso padre como el hijo se ejecutan en el mismo punto en el programa. Al hijo se le da su propio espacio en memoria, que es inicializado con una copia exacta de del espacio de memoria (objetos globales, stack, heap) del padre. Aunque el hijo se ve como un clon exacto del padre, es difícil distinguirlos; la única diferencia es que el fork() regresa cero en el hijo, y un valor diferente a cero en el padre. #include #include char *str; int f() { int k; k = fork(); if (k == 0) { str = "el hijo tiene el valor de: "; return 1; } else { str = "el padre tiene el valor de:"; return 9; } } main() { int j; str = "programa principal"; j = f(); cout