P. 1
Diseño y simulación de sistemas operativos

Diseño y simulación de sistemas operativos

4.71

|Views: 16.623|Likes:
Publicado porJacobo Hernández V
EUGENIO JACOBO HERNÁNDEZ VALDELAMAR. TESIS para obtener el grado de
MAESTRÍA EN CIENCIAS DE LA COMPUTACIÓN.

Fundación Arturo Rosenblueth. México, 2003.
EUGENIO JACOBO HERNÁNDEZ VALDELAMAR. TESIS para obtener el grado de
MAESTRÍA EN CIENCIAS DE LA COMPUTACIÓN.

Fundación Arturo Rosenblueth. México, 2003.

More info:

Published by: Jacobo Hernández V on Jun 23, 2008
Copyright:Attribution Non-commercial No-derivs

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

07/21/2013

pdf

text

original

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 jack_hv@yahoo.com

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
1.1.1 1.1.2

Fundamentos de los Sistemas Operativos _______________________ 7
Definiciones ______________________________________________________________ 8 Características principales__________________________________________________ 10 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

¿Qué es un sistema operativo? ___________________________________________ 7

1.2

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

Desarrollo histórico de los Sistemas Operativos ____________________________ 18

1.3.1 1.3.2 1.3.3 1.3.4

En el principio...__________________________________________________________ 20 Procesamiento por lotes y monitores __________________________________________ 21 Sistemas de operación simultanea de periféricos en línea __________________________ 23 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 1.5

Comentarios _________________________________________________________ 32 Obras consultadas ____________________________________________________ 33

Capitulo 2.
2.1
2.1.1 2.1.2 2.1.3 2.1.4

Funcionamiento básico de un sistema operativo_________________ 35

El hardware y la ejecución de programas _________________________________ 35
La unidad central de procesamiento___________________________________________ 36 La memoria _____________________________________________________________ 38 Ejecución de programas ____________________________________________________ 39 Interacción entre los componentes de hardware__________________________________ 41 Tipos de interrupciones ______________________________________________________ 45

2.2

Software para el control del hardware____________________________________ 46

2.2.1

El papel del BIOS ________________________________________________________ 46 Rutinas del BIOS ___________________________________________________________ 47 Secuencia de arranque _______________________________________________________ 48 El BIOS y el sistema operativo ________________________________________________ 49 2.2.2 Cargador del sistema ______________________________________________________ 49 Carga desde un CD-ROM ____________________________________________________ 50 Carga por medio de conexión en red ____________________________________________ 51 2.2.3 Inicio de la ejecución del sistema operativo_____________________________________ 52 2.2.4 Protección del hardware____________________________________________________ 54 Funcionamiento del kernel____________________________________________________ 55

2.3

Comentarios _________________________________________________________ 55

v

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

2.4

Obras consultadas ____________________________________________________ 57

Capitulo 3.
3.1 3.2

Simulación de Hardware y Sistemas Operativos _________________ 59

La simulación en el diseño de sistemas operativos __________________________ 60 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 3.4

Máquinas virtuales ____________________________________________________ 66
El sistema P _____________________________________________________________ 67

3.3.1 3.4.1 3.4.2

Plataformas de simulación de Sistemas Operativos _________________________ 68

Java Operating System Simulation ___________________________________________ 68 NachOS ________________________________________________________________ 71 La máquina Nachos _________________________________________________________ 72 3.4.3 RCOS __________________________________________________________________ 73

3.5

Simulación de un Sistema Operativo mínimo ______________________________ 75
El hardware: URM ________________________________________________________ 76 El software: SOM_________________________________________________________ 78 Consideraciones para el modelado de dispositivos de E/S__________________________ 81 Resultados ______________________________________________________________ 83 morfo-Hardware__________________________________________________________ 84

3.5.1 3.5.2 3.5.3 3.5.4 3.5.5

3.6 3.7

Comentarios _________________________________________________________ 86 Obras consultadas ____________________________________________________ 87

Capitulo 4.
4.1
4.1.1 4.1.2

Administración de la memoria _______________________________ 89

La memoria__________________________________________________________ 89

Asignación de direcciones __________________________________________________ 90 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

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 4.2.4 Problemas de la administración de memoria ___________________________________ 107 4.2.5 Caso de estudio: Sistema de administración de memoria de Linux __________________ 108

4.3

Asignación de la memoria _____________________________________________ 110
Alojamiento contiguo y no contiguo _________________________________________ 110 Estrategias de asignación __________________________________________________ 111 Fragmentación y compactación _____________________________________________ 111

4.3.1 4.3.2 4.3.3

vi

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Subalojadores_____________________________________________________________ 112 Paginación _____________________________________________________________ 112 Reemplazo de páginas ______________________________________________________ 115 4.3.5 Segmentación ___________________________________________________________ 116 4.3.6 Segmentación con paginación ______________________________________________ 117 4.3.4

4.4 4.5 4.5

Simulación del servicio de administración de memoria _____________________ 119 Comentarios ________________________________________________________ 122 Obras consultadas ___________________________________________________ 123

Capitulo 5.
5.1
5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7

Administración de procesos ________________________________ 125

Ejecución de programas y procesos _____________________________________ 125

Modelos de ejecución_____________________________________________________ 125 Procesos _______________________________________________________________ 127 Hilos__________________________________________________________________ 128 Representación de los procesos _____________________________________________ 129 Creación de procesos _____________________________________________________ 130 Estados de un proceso ____________________________________________________ 132 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

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 5.2.2 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 5.4

Simulación del servicio de administración de procesos _____________________ 152 Procesos concurrentes ________________________________________________ 155

5.4.1

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 5.4.2 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 5.4.3 Comunicación entre procesos en Sistemas Distribuidos __________________________ 175 5.4.4 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 5.6

Comentarios ________________________________________________________ 180 Obras consultadas ___________________________________________________ 181

Capitulo 6.
6.1
6.1.1 6.1.2 6.1.3 6.1.4 6.1.5

Administración de dispositivos, almacenamiento y comunicaciones. 183
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 dispositivos y periféricos ______________________________ 184

6.2

Administración de archivos____________________________________________ 193

6.2.1 6.2.2 6.2.3 6.2.4

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 6.2.5 Nuevos enfoques en el manejo de archivos ____________________________________ 207 6.2.6 Caso de estudio: Sistema de archivos y control de dispositivos en Linux _____________ 208

6.3

Comunicaciones en red _______________________________________________ 210

6.3.1

Redes de computadoras ___________________________________________________ 211 Estructura y configuraciones de redes __________________________________________ 212 Interconexión de computadoras _______________________________________________ 214 6.3.2 Organización del software de red____________________________________________ 215 Protocolos _______________________________________________________________ 216 Caso de estudio: TCP/IP ____________________________________________________ 218 Sockets __________________________________________________________________ 219 6.3.3 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 6.5

Comentarios ________________________________________________________ 223 Obras consultadas ___________________________________________________ 225

Capitulo 7.
7.1
7.1.1 7.1.2

Diseño de sistemas operativos_______________________________ 227
¿Por qué es necesario un sistema operativo? ___________________________________ 229 ¿Para qué escribir un sistema operativo? ______________________________________ 230

El software y sus características ________________________________________ 228

7.2

Desarrollo de sistemas de software ______________________________________ 230
Proceso de desarrollo de software ___________________________________________ 230 Ingeniería de software ____________________________________________________ 231 Concepto de ciclo de vida ___________________________________________________ 232 Fases genéricas de la ingeniería de software _____________________________________ 233

7.2.1 7.2.2

viii

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

El proceso de diseño _______________________________________________________ 235 Etapas del diseño de sistemas ________________________________________________ 235

7.3

Arquitectura de software______________________________________________ 237

7.3.1 Importancia de la arquitectura de software ____________________________________ 238 7.3.2 El diseño de la arquitectura ________________________________________________ 239 7.3.3 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 7.3.4 Patrones arquitectónicos___________________________________________________ 248 El patrón Layers ___________________________________________________________ 249 El patrón Microkernel ______________________________________________________ 249 El patrón Broker___________________________________________________________ 251 7.3.5 Desarrollo basado en la arquitectura _________________________________________ 251

7.4

Diseño sistemas operativos: enfoque orientado a la arquitectura _____________ 252
Preguntas importantes: en busca de requerimientos______________________________ 252 Metas del diseño_________________________________________________________ 254 Estructura del sistema operativo ____________________________________________ 255 Mecanismos y políticas ___________________________________________________ 257

7.4.1 7.4.2 7.4.3 7.4.4

7.5

Diseño de sistemas operativos: el enfoque de los desarrolladores _____________ 257

7.5.1 7.5.2 7.5.3

El enfoque de diseño más simple ____________________________________________ 258 Consideraciones de diseño de sistemas operativos ______________________________ 260 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 7.8 7.9

Diseño de sistemas operativos: la administración de sistemas ________________ 276 Comentarios ________________________________________________________ 277 Obras consultadas ___________________________________________________ 280

Capitulo 8.
8.1 8.2 8.3 8.4 8.5 8.6 8.7

Arquitecturas de Sistemas Operativos ________________________ 285

Representación de la arquitectura ______________________________________ 286 Arquitecturas de Sistemas Operativos ___________________________________ 287 Arquitectura de kernel monolítico ______________________________________ 288 Arquitectura de capas y anillos_________________________________________ 290 Arquitectura de máquina virtual _______________________________________ 293 Arquitectura de microkernel y multihilado _______________________________ 295 Arquitecturas Orientadas a Objetos_____________________________________ 298
Sistemas operativos basados en componentes __________________________________ 301

8.7.1

ix

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

8.8 8.9

Arquitectura cliente-servidor __________________________________________ 302
Implantación del modelo C/S para sistemas operativos distribuidos ___________________ 304

Arquitecturas en red y distribuidas _____________________________________ 305
Criterios de diseño de sistemas distribuidos____________________________________ 308 Mach _________________________________________________________________ 309

8.9.1 8.9.2

8.10 8.11 8.12 8.13 8.14

Arquitecturas adaptables____________________________________________ 312 Arquitectura de Exokernel __________________________________________ 314 Arquitecturas orientadas a agentes____________________________________ 317 Comentarios ______________________________________________________ 319 Obras consultadas__________________________________________________ 321

Resultados, conclusiones y perspectivas ___________________________________ 325
a. b. c.
c.1 c.2 c.3

Resultados __________________________________________________________ 325 Aportaciones ________________________________________________________ 326 Conclusiones __________________________________________________________ 328
¿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. e.

Perspectivas_________________________________________________________ 330 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 Procesador Ejemplos de servicios de SO Administración de Procesos, Planificación (scheduling), Excepciones, Protección, Sincronización Administración, Protección, Memoria Virtual Concurrencia con el CPU, Manejo de Interrupciones Administración, Persistencia Seguridad en red Sistema de archivos distribuido Abstracción del usuario Proceso

Memoria Dispositivos de E/S Sistema de archivos

Espacio de direcciones Terminal, Mouse, Impresora, (Llamadas al sistema) Archivos Llamadas al sistema, llamado remoto de procedimientos (RPC), Acceso transparente de archivos (Transparent file sharing)

Sistemas distribuidos

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.12] Introduction to Operating Systems Kathryn S. McKinley. University of Massachusetts .Fall 1997 http://www-aml.cs.umass.edu/~cs377/ [1.13] DESDE QUE PULSAMOS EL BOTON DE NUESTRO PC HASTA... José Manuel Tella Llop, extraído de microsoft.public.es.windows98 http://www.duiops.net/windows/articulos/ [1.14] How Operating Systems Work Marshal Brain's HowStuffWorks http://www.howstuffworks.com/operating-system.htm

[1.1] IIC 2332 -- Sistemas Operativos Apuntes 01 1er Semestre 1996 http://www.cs.virginia.edu/~knabe/iic2332/ [1.2] CS322: A Brief History of Computer Operating Systems Prof. R. Bjork, Gordon College http://www.cs.gordonc.edu/courses/cs322/lectures/hist ory.html [1.3] Operating Systems Lecture notes Lecture 1: Overview and History Martin C. Rinard http://williamstallings.com/Extras/OS-Notes/notes.html [1.4] A BRIEF HISTORY OF OPERATING SYSTEMS THROUGH TIME by Cameron Kaiser http://www.armory.com/~spectre/tech.html [1.5] Brad A. Myers. "A Brief History of Human Computer Interaction Technology." ACM interactions. Vol. 5, no. 2, March, 1998. pp. 44-54. [1.6] The computer museum history center. Timeline of computer history. http://www.computerhistory.org [1.7] Curso de sistemas operativos Enrique Sánchez Lara 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 Copyright (C) 1991, 1992, 1993, 1994, 1995 by the Computational Science Education Project http://csep1.phy.ornl.gov/ov/ov.html [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 [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 [1.20] Symmetric multiprocessing

[1.15] Sistemas operativos I: Interrupciones del procesador http://itver.edu.mx/so1/24.htm [1.16] CSC 277- Operating Systems (handouts) Michael Lynch http://www.qvctc.commnet.edu/classes/csc277/handou ts.html [1.17] Introduction to Operating Systems Kathryn S. McKinley. University of Massachusetts .Fall 1997 http://www-aml.cs.umass.edu/~cs377/

The Free Online Dictionary of Computing
http://burks.brighton.ac.uk/burks/foldoc/67/111.htm

33

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
[1.23] Operating System Basics/Architecture Kurt Hudson & Andy Ruth. Published: July 1999 http://www.windowsitlibrary.com/Content/175/09/toc.h tml [1.24] X Window System Architecture Overview HOWTO Daniel Manrique. 2001 http://linuxselfhelp.com/HOWTO/XWindow-OverviewHOWTO/ [1.25] The machine that changed the world http://ei.cs.vt.edu/~history/TMTCTW.html [1.31] How to build a Beowulf: tutorial http://www.cacr.caltech.edu/beowulf/tutorial/tutorial.ht ml [1.27] Apple history.com http://www.apple-history.com/frames/? [1.28] Old computers.com http://www.old-computers.com/ [1.29] The real history of the GUI http://www.webmasterbase.com/article/511/62 [1.30] Clusters en México http://clusters.unam.mx/Historia/

[1.26] Smithsonian computer history 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: • • 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.

1

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) { f = f * a; a = a + 1; } //ASM // Asumir a esta en la dir. 128 // Asumir F esta en la dir. 129 0 CONB 1 // a=1; 1 SAVEB 128 2 CONB 1 // f=1; 3 SAVEB 129 4 LOADA 128 // if 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. 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.

6. 7.

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.11] How computer memory works. Marshall Brain's HowStuffWorks http://www.howstuffworks.com/computer-memory.htm [2.12] A Designer's Assistant Tool Home Page. Computer Systems Group University of Waterloo. http://csg.uwaterloo.ca/dptool/

[2.1] DESDE QUE PULSAMOS EL BOTON DE NUESTRO PC HASTA... José Manuel Tella Llop, extraído de microsoft.public.es.windows98 http://www.duiops.net/windows/articulos/ http://www.duiops.net/windows/tablacw.htm [2.2] How Operating Systems Work. Marshall Brain's HowStuffWorks http://www.howstuffworks.com/operating-system.htm [2.3] Sistemas operativos I: Interrupciones del procesador http://itver.edu.mx/so1/24.htm [2.4] CSC 277- Operating Systems (handouts). Michael Lynch http://www.qvctc.commnet.edu/classes/csc277/handou ts.html [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.7] RFC Repository. Ross Finlayson. Bootstrap Loading using TFTP. RFC 906, NIC, June, 1984 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.9] JavaOS: Thin Client, Fat Service. Charles Mirho

[2.12] Bootsector authoring. Gareth Owen gaz@athene.co.uk [2.13] Daniels NASM bootstrap tutorial Daniel Marjamäki. daniel.marjamaki@home.se 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.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 http://labsopa.dis.ulpgc.es/psis/gesproc/Expo%20conte xto%20de%20un%20proceso.htm [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

and Tom Clements .Byte. July 1997.
http://www.byte.com/art/9707/sec4/art4.htm [2.10] How Microprocessors Work. Marshall Brain's HowStuffWorks http://www.howstuffworks.com/microprocessor.htm

[2.21] Estructura de los sistemas operativos http://bari.ufps.edu.co/personal/150802A/estructura.ht m [2.22] Linux FAQs 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: • • • Modelar componentes aislados de los SOs Modelos estáticos de SOs Simulación de hardware para ejecución de nuevos modelos de SOs

3

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, int maxElements, curElements, qHead; public OSQueue(int q, int max) { queueType = q; maxElements = max; qHead = -1; }

3 = SJF, 4 = LJF, 5 = RR */

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 rm<>rn 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
Research Center,Duke University. narten@cs.duke.edu February 3, 1997 http://www.cs.duke.edu/~narten/110/nachos/main/mai n.html [3.14] A Designer's Assistant Tool Home Page. Computer Systems Group . University of Waterloo http://csg.uwaterloo.ca/dptool/ [3.15] The OS Emulation HomePage http://www.kearney.net/~mhoffman/ [3.16] RCOSjava

[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. The Flux OS Kit: A Substrate for OS and Language Research ftp://mancos.cs.utah.edu/papers/oskit-hotos6-abs.html [3.3] How To Write a Computer Emulator Marat Fayzullin. 1997-2000. http://www.komkon.org/fms/EMUL8/ [3.4] The SNES Developers Corner http://emureview.ztnet.com/developerscorner/index.ht m [3.5] Emulation programmers resource http://www.classicgaming.com/EPR/

http://rcosjava.sourceforge.net/ [3.17] RCOS.java http://webfuse.cqu.edu.au/Information/Resources/Rea dings/RCOS.java/ [3.18] RCOS: Yet Another Teaching Operating System

[3.6] Trends in Hardware/Software Codesign Larry Mittag 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://www.cba.uri.edu/faculty/vvm/ [3.9] THE UCSD P-SYSTEM MUSEUM IN THE WEST WING OF THE JEFFERSON COMPUTER MUSEUM http://www.threedee.com/jcm/psystem/index.html [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.12] Salsa - An Operating Systems Tutorial. University of Massachusetts, Amherst http://ali-www.cs.umass.edu/salsa/about.html [3.13] A Road Map Through Nachos. Thomas Narten. Department of Computer Sciences, Levine Science

Ron Chernich, Bruce Jamieson, David Jones Proceedings of the First Australasian Conference on Computer Science Education. 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://webfuse.cqu.edu.au/Information/Resources/Rea dings/RCOS.java/Design/ [3.20] Not just another teaching operating system http://webfuse.cqu.edu.au/Information/Resources/Rea dings/RCOS.java/njato/ http://cq-pan.cqu.edu.au/david-jones/Projects/rcos/ [3.21] Modern Operating Systems Simulators http://www.ontko.com/moss/ [3.22] Palm OS Simulator http://www.palmos.com/dev/tools/simulator/ [3.23] SimOS http://simos.stanford.edu/ [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

4.3

Asignación de la memoria⊕

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

PP

Particiones variables

PP

Paginación

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.10] Operating Systems concepts. A. Silberschatz, J. Peterson, P. Galvin. Addison Wesley. 1991. ISBN 0-201-54873-9

[4.1] Estudio Sistemas Operativos Moisés Domènech Lloca. 1998. [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.6] The Free Online Dictionary of Computing. Denis Howe http://foldoc.doc.ic.ac.uk [4.7] Webopedia http://www.pcwebopedia.com/TERM/m/MMU.html [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.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.14] Basics of computer memory. OSData.com http://www.osdata.com/system/physical/memory.htm [4.15] Conceptual Architecture of the Linux Kernel. Ivan Bowman (ibowman@sybase.com) January 1998 http://plg.uwaterloo.ca/~itbowman/CS746G/a1/ [4.16] Concrete Architecture of the Linux Kernel. Ivan Bowman (ibowman@sybase.com), Saheem Siddiqi (s4siddiqi@neumann), Meyer C. Tanuan (mtanuan@descartes.com). 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 <iostream.h> #include <unistd.h> 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 << str << j << endl; }

el padre tiene el valor de: 9 el hijo tiene el valor de: 1

131

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

En el programa, se inicia con un proceso que se ejecuta en main(). Este proceso llama a f(), y adentro de f() se llama al fork(). Entonces aparecen 2 procesos como consecuencia de la llamada. Cada uno tiene su propia copia de la variable str y su propia copia del stack, que contiene un área para main() con la variable j y un área para f() con la variable k. Después de regresar del fork() el padre asigna a su copia de k un valor diferente de cero, mientras el hijo asigna a su copia de k el valor de cero. Cada proceso entonces asigna su propio valor de la cadena a su copia de str y regresa valores diferentes.

5.1.6 Estados de un proceso
Cuando un proceso es ejecutado, su estado cambia. Los estados que un proceso puede adoptar son: • • • • • Nuevo, cuando ha sido recién creado por el SO. Preparado (o listo), cuando se encuentra en espera de asignación del procesador. En ejecución, cuando se encuentra en el CPU ejecutando sus operaciones. En espera (o bloqueado), cuando espera que ocurra algún evento (p.ej. una operación de E/S). Finalizado, cuando no ejecutará más instrucciones y los recursos asignados le son retirados por el SO.

Estos estados no son los únicos que un proceso puede adoptar, pues muchas veces depende de las especificaciones y objetivos del sistema operativo el esquema de estados que se usa para la administración de los procesos. Por ejemplo, QNX que es un sistema de tiempo real, define 8 estados posibles para sus procesos [5.29], mientras Linux define 5 estados [5.30].

Figura 5.3 Esquemas de estados y transiciones de un proceso
La primera tarea importante del manejo de procesos es poder rastrearlos, es decir, mantener

un registro que nos diga que es lo que existe y en que estado se encuentra.
Todo proceso a lo largo de su existencia puede cambiar de estado varias veces. Cada uno de estos cambios se denomina transacción de estado. Estas transacciones son las siguientes:

132

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Comienzo de la ejecución. Todo proceso comienza al ser dada la orden de ejecución del programa insertándose en la cola de preparados. El encolamiento dependerá de la política de gestión de dicha cola. Paso de estado de ejecución. Cuando el procesador se encuentra inactivo y en la cola de preparados exista algún proceso en espera de ser ejecutado, se pondrá en ejecución el primero de ellos. Paso a estado bloqueado. Un proceso que se encuentre en ejecución y que solicite una operación a un dispositivo externo, teniendo que esperar a que dicha operación finalice, será pasado de estado de ejecución a estado bloqueado insertándose su PCB en la cola correspondientes de bloqueado. A partir de este momento el procesador pone en ejecución el siguiente proceso, que será el primero de la cola de preparados. Paso a estado preparado. Este paso puede ser producido por alguna de las siguientes causas. Orden de ejecución de un programa, con la cual, ya se ha mencionado, el proceso pasa a la cola de preparados. Si un proceso está en estado bloqueado por causa de una operación de entrada/salida y está finaliza, pasará de la cola de bloqueados a la de preparados. Si un proceso está en ejecución y aparece una interrupción que fuerza al sistema operativo a ejecutar otro proceso, el primero pasará al estado de preparado y su PCB a la cola de preparados. Activación. Un proceso suspendido previamente sin estar bloqueado pasará al estado preparado al ser activado nuevamente. Paso a estado suspendido bloqueado. Si un proceso está bloqueado y el sistema operativo recibe la orden de suspenderlo, su PCB entrará en la cola de procesos suspendidos bloqueados. Paso a estado suspendido preparado. Este paso se puede producir bajo tres circunstancias: • Suspensión de un proceso preparado pasando éste de la cola de procesos preparados a la de suspendidos preparados. • Suspensión de un proceso en ejecución, con lo cual el proceso pasa a la cola de suspendidos preparados. • Desbloqueo de un proceso suspendido bloqueado por desaparecer la causa que impedía el ser activado de nuevo.

5.1.7 Colas de procesos
Los bloques de contexto de los procesos son almacenados en listas llamadas colas de procesos. Cada lista está dedicada a una clase particular de procesos. Estas listas pueden ser organizadas de la siguiente manera: • Ejecución. El proceso que se este ejecutando. En la mayoría de las computadoras, solo un proceso se ejecuta a la vez, pero, en maquinas con múltiples procesadores, varios procesos pueden ejecutarse a la vez. • Preparado. Aquellos procesos que están dispuestos para ser ejecutados, pero no están en ejecución por alguna causa (una interrupción, haber entrado en cola estando otro proceso en ejecución, etc.). • Espera. Procesos que no pueden ejecutarse en el momento porque han hecho peticiones no han sido completadas. Preferentemente, el kernel debe mantener una lista diferente para cada tipo de servicio que pueda ser requerido.

133

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Por ejemplo, la administración de espacio a veces causa que los procesos esperen en una lista principal de espera (main-store wait), hasta que haya suficiente espacio para ejecutarlos. Un proceso que lee datos de un archivo puede esperar en una lista de espera de acceso a archivos (file transput wait) hasta que los datos sean leídos. Cada dispositivo que un proceso pueda usar para operaciones de entrada/salida deberá tener su propia lista de espera. Mientras un proceso este en una lista de espera, se dirá que esta bloqueado. Estas listas son llamadas también colas (queues) pero no necesitan ser construidas como colas, con su entrada en un extremo y su salida por el otro. Estas listas pueden ser representadas incluyendo en cada bloque de contexto un campo que indique en que lista se encuentra. Dichos bloques pueden ser almacenados en una estructura de datos de pila (heap) de acuerdo a cierta prioridad, de modo que aquel con mayor urgencia pueda ser accesado rápidamente.

Llamadas de servicios
Varios eventos pueden provocar que un proceso sea enviado de una lista a otra. Un proceso hace una petición al kernel enviando una llamada de servicio (Service call), la cual puede pedir recursos, retornar recursos o realizar una operación de E/S (transput). Como resultado de dicha llamada, el planificador debe decidir si coloca el proceso de regreso en la lista de de preparados y comenzar a ejecutar otro proceso de dicha lista. Esta operación, llamada intercambio de proceso (process switch), usualmente toma más tiempo que un simple cambio de contexto (context switch). Después de un intercambio de proceso, un cambio de contexto inicia la ejecución de un nuevo proceso. La mayoría de los sistemas operativos construyen las llamadas de servicio a partir de instrucciones que causan interrupciones en el procesador (processor traps). Una interrupción (trap) causa que el hardware copie ciertos registros del hardware, como el contador de programa y el estado del procesador, a un lugar seguro (por lo general en un stack). El hardware carga entonces los registros apropiados con el nuevo contexto (que incluye el contador de programa para establecer el sitio en el kernel donde el programa manejador de interrupciones es almacenado). Entonces se cambia el procesador al estado privilegiado. El SO debe colocar la información de contexto salvada por el hardware en el bloque de contexto del proceso que estaba ejecutándose en el momento de la interrupción. Las llamadas de servicio son como llamadas a subrutinas desde el punto de vista de llamar a un proceso.

5.1.8 Operaciones de manipulación de procesos
En los cimientos de un sistema operativo, hay un programa de control que reacciona ante cualquier interrupción de eventos externos y que da servicio a los procesos, creándolos, terminándolos y respondiendo a cualquier petición de servicio por parte de los mismos.

134

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Los sistemas operativos actuales poseen una serie de funciones orientadas a la manipulación de los procesos. Las operaciones que se pueden hacer sobre un proceso son las siguientes: • Crear el proceso. Se produce con la orden de ejecución del programa y suele necesitar varios argumentos, como el nombre y la prioridad del proceso. Aparece en este momento el PCB, que será insertado en la cola de procesos preparados. La creación de un proceso puede ser de dos tipos: a. Jerárquica. En ella, cada proceso que se crea es hijo del proceso creador y hereda el entorno de ejecución de su padre. El primer proceso que ejecuta un usuario será hijo del intérprete de comandos con el que interactúa. b. No jerárquica. Cada proceso creado por otro proceso se ejecuta independientemente de su creador con un entorno diferente. Es un tipo de creación que no suele darse en los sistemas operativos actuales. Destruir un proceso. Se trata de la orden de eliminación del proceso con la cual el sistema operativo destruye su PCB. Suspender un proceso. Es un proceso de alta prioridad que paraliza un proceso que puede ser reanudado posteriormente. Suele utilizarse en ocasiones de mal funcionamiento o sobrecarga del sistema. Reanudar un proceso. Trata de activar un proceso que a sido previamente suspendido. Cambiar la prioridad de un proceso. Todo proceso por sus características e importancia lleva aparejadas unas determinadas necesidades de ejecución en cuanto a urgencia y asignación de recursos. Las prioridades según los sistemas operativos se pueden clasificar del

• •

• •

siguiente modo:
• Asignadas por el sistema operativo. Se trata de prioridades que son asignadas a un proceso en el momento de comenzar su ejecución y dependen fundamentalmente de los privilegios de su propietario y del modo de ejecución. Asignadas por el propietario. Estáticas.

• • •

• Dinámicas. Temporizar la ejecución de un proceso. Hace que un determinado proceso se ejecute cada cierto tiempo (segundos, minutos, horas) por etapas de una sola vez, pero transcurrido un periodo de tiempo fijo. Despertar un proceso. Es una forma de desbloquear un proceso que habrá sido bloqueado previamente por temporización o cualquier otra causa.

5.1.9 ¿Por qué usar procesos?
Los procesos son básicamente solo una conveniencia para programar, pero en ciertas configuraciones son muy útiles, pues si no sería casi imposible escribir un programa sin ellos. Un proceso permite escribir un bloque o hilo de código para llevar a cabo una tarea, sin preocuparnos de la posibilidad de que algo suceda durante la ejecución. Algunos ejemplos de esto son: • • • Un servidor que provee servicios a otros. Un hilo para cada cliente. Un sistema de tiempo compartido. Un hilo por cada usuario autentificado. Una computadora de control a tiempo real que controla una fábrica. Un hilo por cada dispositivo que necesite monitorearse.

135

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Un servidor de red. Un hilo para cada conexión. En este capítulo se expondrán los 3 principales problemas de la administración de procesos: • • • La planificación de procesos La sincronización entre procesos La comunicación entre procesos

5.2

Planificación de procesos⊕

La planificación es una tarea fundamental de los sistemas operativos. La mayor parte de los recursos se planifican antes de usarse. Desde luego, el CPU es uno de los principales recursos de la computadora, por lo que su planificación es importante para el diseño de los sistemas operativos. Los recursos pueden dividirse en dos categorías: 1. Con derecho preferente o expropiable (preemptible): el procesador o un canal de E/S puede tomarse el recurso, usarlo para alguna otra cosa, y regresarlo más tarde. 2. Sin derecho preferente o no expropiable (non-preemptible): una vez otorgado, no puede ser reutilizado hasta que el proceso lo devuelve. Algunos ejemplos son el espacio de archivos, terminales, e incluso la memoria. La planificación se refiere a un conjunto de políticas y mecanismos que poseen los actuales sistemas operativos y por los que se rige el orden en que se completa el trabajo que los procesos deben realizar. Al igual que los recursos, las políticas de planificación pueden ser: Con derecho preferente o expropiable (apropiable). Cuando se permite la suspensión de la ejecución de un proceso. El planificador puede remover al proceso que está en el CPU (lo cual es necesario si se desea implementar un sistema de tiempo real o de tiempo compartido). Sin derecho preferente o no expropiable (no apropiable). Cuando no se permite la suspensión de la ejecución de un proceso. El proceso que está en el CPU, lo abandona cuando quiere. Esto puede causar un acaparamiento de tiempo del procesador. Los sistemas operativos realizan dos tipos de decisiones relacionadas a los recursos: a. Alojamiento (Allocation): quién obtiene qué. Dado un conjunto de peticiones por recursos, a que procesos deben dárseles que recursos, para hacer mas eficiente el uso de recursos. b. Planificación (Scheduling): cuanto tiempo pueden mantenerse. Cuando se requieren más recursos que pueden ser ofrecidos de inmediato, cual es el orden en que deberían

Obras consultadas: [5.2]

136

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

ser atendidos. Se tienen por ejemplo, la planificación del procesador (un procesador, muchos procesos), la planificación de la memoria en sistemas de memoria virtual. El planificador es un componente del SO que se encarga de elegir la tarea siguiente que hay que admitir en el sistema y el proceso siguiente que hay que ejecutar. La finalidad del planificador es asignar procesos para que sean ejecutados por el procesador o procesadores con el fin de obtener mejores tiempos de respuesta, mayor productividad o rendimiento y eficiencia del procesador.

5.2.1 Tipos de planificación
En la mayoría de los sistemas, la actividad de planificación se realiza en tres tipos de planificadores (fig. 5.4):

Figura 5.4 Niveles de planificación
1. Planificador a largo plazo (Planificador de trabajos). Cada vez que un usuario inicia la ejecución de un programa, el planificador a largo plazo recibe la orden de ejecución, crea el proceso correspondiente y lo pasa al planificador a corto plazo, colocándose en la cola de procesos listos. Este planificador es, por tanto, el encargado de crear los procesos. Cada vez que termina un trabajo, el planificador tomara la decisión de añadir uno o más trabajos nuevos. 2. Planificador a mediano plazo (planificador de intercambio). Este planificador decide si un proceso que está en estado bloqueado o suspendido debe ser retirado de la memoria temporalmente (y por ejemplo, trasladarlo al almacenamiento secundario). Posteriormente, cuando el sistema se encuentra mas descargado, devolverá dicho proceso a la memoria y al estado de ejecución. Esta técnica se conoce con el nombre de intercambio (swapping). Este nivel, por tanto, gestiona los procesos suspendidos en espera de algún recurso no disponible en el momento de la suspensión.

137

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

3. Planificador a corto plazo (planificador del procesador). El planificador a corto plazo, es el encargado de decidir como y cuando tendrá acceso al procesador un proceso que esta listo para utilizarlo. Solo considera a los procesos que están en memoria. Ha de ser rápido y eficiente ya que se ejecuta muy a menudo. En este nivel, es donde se debe dar un buen servicio a los procesos para que el usuario no perciba que esta compitiendo por el procesador junto con otros usuarios. En las siguientes secciones se detalla cada uno de ellos.

Planificación del CPU
Existen dos partes principales en la planificación del procesador: I. El despachador (dispatcher) provee el mecanismo básico para la ejecución de procesos (cambios de contexto). II. El planificador de corto plazo, es una pieza del código del SO que decide que proceso se ejecutará en el CPU por medio de un algoritmo de planificación (ya sea por criterios de prioridades de los procesos o su tiempo de ejecución) y le cede el control por medio del despachador. El despachador es el módulo que cede el control del CPU al proceso seleccionado por el planificador a corto plazo. Esta función implica: Cambiar de contexto Cambiar a modo de usuario Saltar al punto apropiado del programa del usuario para reiniciar ese programa El despachador debe ser lo más rápido posible, porque se invoca en cada conmutación de proceso. El tiempo que el despachador tarda en detener un proceso y poner otro en ejecución se denomina latencia del despachador. Su funcionamiento puede describirse como: a. Ejecutar un proceso por un lapso de tiempo b. Salvar su estado c. Cargar el estado de otro proceso d. Ejecutarlo... Una pregunta lógica es: ¿cómo decide el despachador cuál es el proceso siguiente que debe ejecutar? Para ello el planificador de corto plazo utiliza las siguientes estrategias: • • Plan 0: buscar desde el principio de la tabla de procesos, algún proceso que este listo para ejecutarse (este método es muy lento por ser una búsqueda lineal). Plan 1: reunir a los procesos listos para ejecutarse en una cola. El Despachador toma el primer proceso de la cola. Cuando los procesos se tornan listos para ejecutarse, se insertan al final de la cola. Plan 2: dar a cada proceso una prioridad, y organizar la cola de acuerdo a la prioridad, o tal vez tener varias colas (una para cada tipo de prioridad).

138

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Puesto que el CPU solo puede hacer una cosa a la vez, si un proceso de usuario se está ejecutando, el despachador pierde el control del CPU. Para recuperarlo puede emplearse un "despertador" que puede ser: a. Un evento Interno (trampas), que ocurra dentro del proceso de usuario que devuelva el control al SO, por ejemplo: - Llamadas al sistema. - Errores (instrucciones ilegales, violación de direccionamiento, etc.). - Error de página (page fault). b. Un evento Externo (interrupciones), que ocurra fuera del control del proceso de usuario que devuelva el control al SO, por ejemplo: - Caracteres tecleados en una terminal. - Termino de una operación en disco (el controlador esta listo para más trabajo). - Temporizador (Timer), que asegura que eventualmente el SO recupere el control. El diseño del planificador de corto plazo es una de las áreas criticas en el diseño del sistema en general, y una de las más "truculentas" puesto que como cada arquitectura de procesadores posee sus propias facilidades para intercambio de tareas, la implementación del mecanismo de software de intercambio de procesos por lo general debe ser independiente de la máquina, pero el software de intercambio se codifica por lo general en lenguaje ensamblador especifico de la máquina (debe ser el único módulo dependiente de la arquitectura). Independientemente de la política de planificación adoptada, tres criterios básicos del planificador de corto plazo deben ser individualizados: 1. El intercambio de procesos debe ser hecho eficientemente. Puesto que la mayor parte del tiempo que toma llevar a cabo el cambio de procesos es sacrificado en salvar y restaurar el contexto del proceso, es importante que la cantidad de información que representa al proceso y su estado, se reduzca a un mínimo indispensable. 2. Puesto que muchas estructuras de datos son compartidas entre los procesos (p.ej. tablas de dispositivos, información de tiempo, prioridades relativas, etc.), debe haber un método consistente para permitir el acceso a los datos entre ellas. La única respuesta obvia es almacenar estas estructuras en la memoria principal. 3. Puesto que el sistema administra varios procesos, cada uno de los cuales asume que es el único proceso ejecutándose, el sistema debe escoger un esquema en el que los procesos tengan una justa repartición del tiempo del procesador.

Planificación de largo plazo⊕
El planificador de largo plazo (long term scheduler - LTS) es la parte del SO que manipula la inclusión o exclusión de nuevos procesos en el pool de trabajos (job pool) del sistema. Cuando un nuevo proceso es iniciado o terminado, el trabajo es hecho por el planificador de largo plazo.

Obras consultadas: [5.3]

139

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Generalmente es el intérprete de comandos el encargado de llamar al planificador de largo plazo, cuando el usuario hace una petición para arrancar un proceso; y el proceso mismo cuando realiza una llamada para terminar su operación y liberar los recursos que el sistema le había asignado. Las llamadas al sistema deben ser hechas también por el planificador de largo plazo, pues llama al administrador de memoria para alojar memoria para el nuevo proceso, o desalojar la memoria para un proceso muerto.

La principal función del LTS, después de verificar que la memoria ha sido correctamente asignada al proceso por el administrador de memoria, es crear el bloque de control de proceso (PCB) para el nuevo proceso. Esto puede hacerse examinando el PCB del proceso padre, y
copiando gran parte de su información en el nuevo PCB. Los campos del PCB tales como valores de registro del usuario, permisos del proceso, y recursos pueden ser copiados directamente. Los registros base y limite, y el contador de programa (PC) son ejemplos de campos que el LTS tendrá que crear con la ayuda del administrador de memoria. El nuevo PCB es entonces agregado a la cola apropiada con su estado inicializado en ejecutable (runnable). En cambio desasignar es más sencillo, pues el planificador solo cierra los recursos y borra el PCB de las colas de planificación. Sin embargo, si el sistema está muy cargado con procesos, el planificador de largo plazo puede elegir mantener el trabajo en disco hasta que los recursos del sistema sean suficientes para agregar un nuevo trabajo. Una vez que el estado de un proceso es cambiado de "nuevo" a "listo" por el planificador de largo plazo, entonces el planificador de corto plazo pasa a determinar cual es el proceso que será despachado.

Planificación de mediano plazo
Como su nombre lo indica el planificador de mediano plazo (medium-term scheduler MTS) no es invocado tan frecuentemente como el de corto plazo, pero es llamado más a menudo que el de largo plazo. El código del programa ejecutado por el CPU y los datos que el programa maneja deben ser almacenados en la memoria principal (RAM). El intercambio con el disco (disk swapping) permite al SO usar el disco duro (memoria secundaria) para simular la memoria primaria, intercambiando trozos de la memoria principal al disco, y de vuelta como vaya siendo necesario. Con esta memoria virtual, un SO con, digamos, 64 Mbytes de RAM puede simular cientos de megabytes o hasta gigabytes de memoria principal. Los sistemas operativos implementan este intercambio tomando el código y datos de un proceso en memoria principal, y lo escriben temporalmente al disco duro (swapped out). Un proceso en este estado se llama suspendido. Cuando dicha memoria es requerida nuevamente por su proceso asociado, es leída del disco y devuelta a la memoria principal (swapped in). El proceso no sabe que su código y datos están

140

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

siendo intercambiados, puesto que esto ocurre cuando el proceso esta en estado de bloqueo o listo para ejecutarse. Esto significa que si se desea considerar un diagrama de procesos para un sistema que provee intercambio de procesos, deben agregarse los estados: • • Suspendido-bloqueado (suspended-blocked) Suspendido-preparado (suspended-ready)

El MTS es usado por el SO para decidir que procesos serán intercambiados, y cuando; además debe asegurarse que antes de que un proceso sea despachado al CPU, su código y datos hayan sido devueltos a la memoria principal. Por lo tanto es claro que este planificador requerirá su propio algoritmo de planificación.

Caso de estudio: Sistema de planificación de procesos de Linux
Como ejemplo concreto se presenta el esquema usado por el SO Linux. El planificador de procesos es el corazón de Linux, y tiene las siguientes responsabilidades: • • • • • • permitir a los procesos crear nuevas copias de si mismos determinar que procesos tendrán acceso al CPU y efectuar la transferencia entre procesos en ejecución recibir interrupciones y direccionarlas a los subsistemas apropiados del kernel enviar señales a los procesos de usuario administrar el hardware de temporizador liberar los recursos usados cuando los procesos finalicen su ejecución

Figura 5.5 Esquema de las dependencias y flujos de control y datos en el planificador de procesos20
20

Imagen reproducida de [5.31]

141

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

El planificador también provee soporte para la carga dinámica de módulos; estos módulos representan funcionalidades del kernel que pueden cargarse después de que el kernel ha comenzado a ejecutarse. Esta capacidad es usada por los subsistemas de administración de archivos (vfs) y de red (net).

Figura 5.6 Estructura del planificador de procesos de Linux21 5.2.2 Algoritmos de planificación⊕
Cuando más de un proceso es ejecutable, el sistema operativo debe decidir cuál de ellos debe ejecutarse primero. La parte del sistema operativo que debe de llevar a cabo esa decisión se llama planificador y el algoritmo que utiliza se llama algoritmo de planificación. El planificador intenta conseguir con su administración de procesos lo siguiente: • • • Equidad: Garantizar que cada proceso obtenga su proporción justa de la CPU. Es decir, que ningún proceso llegue a apoderarse por completo de la CPU. Eficiencia: Mantener ocupada la CPU al 100%, esto con el fin de evitar los tiempos ociosos que pueda tener el CPU. Rendimiento: Maximizar el número de tareas procesadas por hora, es decir, que el CPU pueda atender todos y cada una de las peticiones que le fueron hechas.

Para garantizar que ningún proceso se ejecute un tiempo excesivo, casi todas las computadoras tienen un cronómetro electrónico o un reloj incluido, que provoca una interrupción en forma periódica. En cada interrupción del reloj, el sistema operativo logra ejecutarse y decidir si el proceso que se ejecuta en ese momento tiene permiso de continuar o si tiene el tiempo suficiente en la CPU por el momento, para después suspenderlo para que otro proceso utilice la CPU.

21 ⊕

Imagen reproducida de [5.32] Obras consultadas: [5.5] [5.6] [5.12] [5.13] [5.14] [5.15]

142

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

La mayor parte de los sistemas operativos usan algoritmos de planificación de tiempo de CPU muy similares, todos basados en las mismas ideas básicas, pero con adaptaciones y extensiones especificas a cada SO. La toma de decisión del próximo proceso a ser ejecutado puede llevarse a cabo cuando sucede alguna de las siguientes transiciones: • • • • Cuando Cuando Cuando Cuando un un un un proceso proceso proceso proceso pasa de estado Running a Waiting. pasa de estado Running a Ready pasa de estado Waiting a Ready finaliza y pasa del estado Running a Terminated.

Para la primera y última transición, el planificador seleccionará un proceso (si hay alguno en la cola de listos). Si las decisiones del planificador se llevan a cabo solamente cuando ocurren estas transiciones, decimos que el esquema de planificación es no expropiativa. Bajo este esquema, una vez que el CPU ha sido asignado a un proceso, el proceso mantendrá el CPU hasta que él lo libere ya sea porque finalizó la ejecución del proceso o porque necesite esperar por la ocurrencia de algún evento. Este esquema no requiere hardware especial (timer). Cuando se permite la suspensión de la ejecución de un proceso estamos hablando de un esquema expropiativo. Los esquemas de planificación expropiativos incurren en ciertos costos y afectan el diseño del kernel del sistema de operación. Por ejemplo, considérese el caso en que dos procesos comparten cierta data. Si uno de ellos está en ejecución y se encuentra alterando dichos datos, puede suceder que dicho proceso sea suspendido temporalmente y se le pase el control del CPU al otro proceso. El nuevo proceso puede encontrarse con los datos en un estado de inconsistencia. Por lo tanto, nuevos mecanismos son necesarios para coordinar el acceso a datos compartidos. Los algoritmos de planificación no expropiativos son sencillos y fáciles de implementar, por lo general no son apropiados para sistemas de aplicación general con varios usuarios que compiten entre si. Cabe preguntarnos ¿qué hace el CPU si no hay procesos para ejecutar en la cola de listos? Aquí el sistema operativo crea un proceso estático (iddle process), que es un proceso limitado por el CPU construido en el sistema (podríamos pensar en un pequeño ciclo), al que se le da la menor prioridad posible, por lo que no es ejecutado si hay procesos preparados en el sistema. A continuación se presentan los algoritmos más importantes.

Algoritmo de planificación FCFS (First Come - First Served)⊕
La política más simple de planificación es la FCFS (First Come - First Served (el primero en llegar es el primero que es atendido)). A medida que un proceso pasa al estado listo, este es agregado a la cola de listos. Cuando el proceso que actualmente se está ejecutando cesa su ejecución, entonces el proceso más viejo en la cola es seleccionado para ejecutarse. La implementación de esta política es a través de colas FIFO (First-In, First-Out). Cuando el CPU está libre, éste es asignado al proceso que está en la cabeza de la cola.

Obras consultadas: [5.16] [5.17] [5.18]

143

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Cuando un proceso tiene el CPU, se ejecuta hasta terminar. Es justo en el sentido formal, pero algo injusta en cuanto a que los trabajos largos hacen esperar a los cortos y los trabajos sin importancia hacen esperar a los importantes. El tiempo de espera promedio en este tipo de algoritmo es muy variable, pues el tiempo de espera de cada uno de los procesos que están en la cola de listos depende del orden de dichos procesos en la cola. Consideremos el siguiente ejemplo: Proceso P1 P2 P3 Tiempo ejecución 20 5 7

Según la tabla presentada, el tiempo de espera por proceso es el siguiente: Tiempo espera P1 = 0 Tiempo espera P2 = 20 Tiempo espera P3 = 25 Tiempo espera promedio = 15 Si cambiamos el orden de llegada de los procesos, produciéndose la siguiente secuencia de llegada P2, P3, P1 el tiempo de espera promedio, de la siguiente manera: Tiempo espera P1 = 12 Tiempo espera P2 = 0 Tiempo espera P3 = 5 Tiempo espera Promedio = 5.66 Luego, se puede concluir el tiempo de espera promedio no es mínimo y puede variar mucho debido, por una parte a las diferencias por requerimiento de tiempo de CPU y por el orden de llegada de los procesos a la cola de procesos listos.

FCFS es un algoritmo no expropiativo, pues una vez de que el CPU sea asignado a un proceso, este lo mantiene hasta que espontáneamente lo suelta, ya sea porque el proceso finalizó o por algún requerimiento de E/S.
El tiempo de espera bajo esta política tiende a ser alto. Además, tiende a favorecer aquellos procesos que requieren más tiempo de CPU (CPU-bound). No es útil en la planificación para los usuarios interactivos porque no puede garantizar buenos tiempos de respuesta. El esquema FIFO rara vez se usa como esquema principal en los sistemas actuales, pero a menudo está incorporado en otros sistemas. Por ejemplo, muchos esquemas de planificación despachan los procesos de acuerdo con la prioridad, pero los procesos con la misma prioridad se despachan de acuerdo con el esquema FIFO. Las características principales de este algoritmo son las siguientes:

144

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• • • •

No es expropiativo Es justo, aunque los procesos largos hacen esperar mucho a los cortos. Es una política predecible El tiempo promedio de servicio es muy variable ya que está en función del número de procesos y la duración promedio que tenga

El tiempo promedio de espera que tengan los procesos depende por completo del orden en que llegan los procesos a ejecutarse.

Algoritmo Round-robin⊕
Una manera rápida de reducir la penalización que los procesos cortos sufren con FCFS es usar expropiación basada en un reloj. Una interrupción de reloj es generada a intervalos periódicos. El algoritmo consiste en tener una cola tipo FIFO de procesos listos. El planificador de procesos toma el primer proceso de la cola, programa un cronómetro para que interrumpa después de un lapso o quantum de tiempo y despacha el proceso en la CPU. Posteriormente puede suceder una de dos alternativas. • Si el proceso ocupa en ejecución menos tiempo que el quantum, entonces el proceso libera voluntariamente la CPU y el planificador continúa con la planificación del siguiente proceso listo. • Si el proceso requiere para su ejecución más tiempo que el otorgado a través de un quantum, se produce la interrupción del cronómetro cuando su tiempo expira. En ese momento el planificador detiene la ejecución del proceso, lo pone al final de la cola de procesos listos, y realiza la conmutación de contexto para la ejecución, por un quantum, del siguiente proceso de la cola FIFO. La principal decisión de diseño que surge con Round Robin es el tamaño del trozo o quantum. Si el quantum es muy corto, entonces los procesos se moverán a través del sistema rápidamente. Por otro lado, hay un cierto overhead o desperdicio de tiempo envuelto con el manejo de la interrupción de reloj y las funciones de planificación y despacho. Por lo tanto trozos muy pequeños deberían evitarse. Una alternativa es usar un quantum de tiempo que sea un poco más grande que el tiempo promedio requerido para una interacción típica.

Round Robin es particularmente efectivo para sistemas generales de tiempo compartido. Se implementa con una cola FIFO de procesos. Nuevos procesos son agregados al final de la cola, y toma el proceso que se encuentra en la cabeza de la cola. Actualiza el timer para que interrumpa después del quantum de tiempo.
El desempeño de este algoritmo dependerá del tamaño del quantum. Si el quantum es infinito entonces degenera en FCFS. Si el quantum es muy pequeño entonces Round Robin es llamado compartición de CPU y en teoría pareciera que cada proceso tiene su propio procesador corriendo a 1/n la velocidad del procesador real.

Obras consultadas: [5.19] [5.20]

145

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 5.7 Para un quantum=1 se presenta la secuencia de ejecución de procesos22
Bajo este esquema es importante considerar el efecto del cambio de contexto. Este algoritmo no es el lo mejor para SOs de propósito general, pero es muy útil para SOs de procesamiento por lotes, en donde todos los trabajos tienen la misma prioridad, y en donde el tiempo de respuesta es de menor o nula importancia.

Planificación por prioridad⊕

En muchos sistemas, los procesos tienen prioridades asignadas, y el planificador escogerá aquel proceso con mayor prioridad. Cuando un proceso debe ser seleccionado, el planificador por prioridades seleccionará aquel proceso que tenga mayor prioridad. Si hay más de un proceso entonces se deberá seguir alguna política de selección.

22

Imagen reproducida de [G12] Obras consultadas: [5.21]

146

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

En este algoritmo, a cada proceso le es asignada una prioridad, y el proceso con la prioridad más alta obtiene siempre el tiempo de CPU. Es posible asignar una prioridad alta a los procesos interactivos, para obtener un mejor tiempo de respuesta. Los procesos de cómputo intensivo reciben una prioridad más baja, pues no necesitan un tiempo de respuesta. Las prioridades pueden ser definidas interna o externamente. En el primer caso, el sistema operativo se basa en una serie de informaciones medibles para el cálculo y asignación de dichas prioridades (tiempo necesitado del procesador, necesidad de memoria, etc.). En las externas la asignación de prioridades se basa en la categoría que tenga el usuario. Un problema que presenta un esquema de planificación por prioridades puro es que los procesos con la prioridad más baja pueden sufrir de inanición o bloqueo indefinido. Un proceso que está listo para correr pero espera porque siempre hay procesos con prioridad más alta. Un mecanismo que se utiliza para evitar el aplazamiento indefinido de los procesos de baja prioridad es el envejecimiento, el cual consiste en aumentar gradualmente en el tiempo la prioridad de los procesos que esperan durante mucho tiempo en el sistema. Un ejemplo de como funciona este algoritmo, es el siguiente: Proceso P1 P2 P3 P4 Tiempo ejecución 10 5 7 8 Prioridad 3 2 1 2

Caso NO apropiativo: Tiempo espera P1 = tP3 + tP2 + tP4= 20 Tiempo espera P2 = tP3 = 7 Tiempo espera P3 = 0 Tiempo espera P4 = tP3 + tP2 = 12 Tiempo espera promedio = 9.75 SJF es un caso especial de planificación por prioridad, donde la prioridad es el inverso del valor estimado del próximo ciclo de CPU (a menor ciclo, mayor prioridad). Este algoritmo puede ser expropiativo y no expropiativo. En el caso de expropiación, cuando un proceso llega a la cola de procesos listos, su prioridad es comparada con la prioridad del proceso que está corriendo. Si la prioridad del nuevo proceso es mayor, entonces se atiende al nuevo proceso.

Algoritmo del trabajo más corto primero (Shortest Job First)⊕

El algoritmo del trabajo más corto (SJF) selecciona al proceso con el próximo tiempo de ejecución más corto. Un proceso corto saltará a la cabeza de la cola. La ejecución de un proceso consiste en ciclos de ejecución de CPU y ciclos de espera por E/S. El algoritmo selecciona aquel proceso cuyo próximo ciclo de ejecución de CPU sea menor. El problema está

Obras consultadas: [5.22]

147

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

en conocer dichos valores, pero podemos predecirlos usando la información de los ciclos anteriores ejecutados. El SJF es probablemente óptimo pues da el mínimo tiempo promedio de espera. El problema está en conocer la duración del próximo requerimiento de CPU para cada proceso. Esta duración puede predecirse suponiendo que el próximo ciclo puede ser similar a los anteriores. Este algoritmo puede ser expropiativo o no. Cuando un nuevo proceso llega a la cola de procesos listos mientras otro se está ejecutando, el nuevo proceso puede tener el ciclo de duración de CPU más corto que lo que falta por ejecutar del proceso actual. En el caso de un esquema expropiativo, el CPU será asignado al proceso que acaba de llegar a la cola. Este algoritmo se conoce como Shortest Remaining Time First (SRTF).

Figura 5.8 Ejemplo de los algoritmos SJF y SRTF23

Múltiples colas de prioridad (MPQ)⊕

El algoritmo MPQ (Multiple Priority Queues) es el algoritmo más utilizado por la mayoría de los sistemas operativos actualmente. El planificador mantiene una lista de colas de procesos, donde cada cola tiene una prioridad asignada. Los procesos comienzan en una cola de prioridad determinada por el usuario o el SO.

23

Imagen reproducida de [5.11] Obras consultadas: [5.23] [5.24]

148

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 5.9 Colas múltiples de prioridad
Este algoritmo surge para tratar de dar un mejor servicio a los usuarios interactivos y está basado en una mezcla entre algoritmos ya vistos y el algoritmo por prioridades, lo usual es que se mezcle el algoritmo Round-robin y el de prioridades. Este algoritmo contempla distintas colas de procesos en donde a cada una de ellas se le asigna una determinada prioridad y se utiliza el algoritmo RR para la planificación de procesos pertenecientes a una misma cola. La operación del algoritmo es como sigue: la CPU es asignada a los procesos pertenecientes a las colas de mayor prioridad, cuando la cola queda vacía se pasa a la cola de procesos asociada a la siguiente prioridad. Por el estilo, existe también el algoritmo de colas de múltiples niveles con retroalimentación. Este algoritmo básicamente es igual al anterior sólo que los procesos pueden moverse de una cola de menor prioridad a una de mayor prioridad y viceversa. La idea en este algoritmo es diferenciar los tipos de procesos de acuerdo a sus requerimientos en tiempos de ejecución. Si un proceso utiliza demasiado tiempo de CPU, se pasa a una cola de menor prioridad. De la misma manera, si un proceso espera demasiado tiempo en una cola de menor prioridad se puede mover a una cola de mayor prioridad, esta es una manera de evitar el bloqueo indefinido producto del envejecimiento. Este esquema permite dejar los procesos interactivos en las colas de mayor prioridad, ya que los procesos interactivos requieren tiempos de respuesta pequeños y necesitan ser atendidos con mayor frecuencia. Los procesos por lotes, en cambio, no requieren interactuar con el sistema y básicamente lo que les interesa es ejecutar su tarea completamente en un tiempo de retorno razonable. De esta manera, lo que sucede en este algoritmo es que cada una de las colas posee una prioridad asociada y la planificación de los procesos que le pertenecen se realiza mediante RR. Sin embargo, el quantum no es el mismo en ambas colas, siendo más pequeño para los procesos de mayor prioridad que corresponde a los procesos interactivos, y mayores para las prioridades más bajas.

149

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Planificación de dos niveles
Los algoritmos de planificación vistos hasta ahora, consideran que la cantidad de memoria disponible es ilimitada. Sin embargo, en los sistemas reales, el recurso de la memoria es limitado y por lo tanto debe ser utilizado de la mejor manera posible. Como ya sabemos, para que un proceso se pueda ejecutar, las instrucciones que definen su acción deben estar almacenadas en memoria, luego, si no se dispone de suficiente memoria, es necesario que algunos de los procesos o porciones de ellos se encuentren en memoria secundaria. Desde el punto de vista de planificación de procesos esta es una situación que debe ser considerada, ya que el tiempo involucrado para ejecutar un proceso que está en disco es mucho mayor que el tiempo requerido para ejecutar un proceso que está en memoria; puesto que, necesariamente, hay que traspasar el proceso de disco a memoria antes de ejecutarlo. La planificación de dos niveles se realiza mediante, un planificador de largo plazo (Longterm Scheduler o planificador de nivel alto), que es el que selecciona los procesos de disco para cargarlos en memoria y viceversa; y el planificador de corto plazo (Short-term Scheduler o planificador de nivel bajo), que es el selecciona un proceso listo para asignarle CPU. La principal diferencia entre estos dos planificadores es la frecuencia de su ejecución. El planificador de corto plazo debe seleccionar con mucha frecuencia un nuevo proceso para asignación de CPU. Como este planificador debe asegurar una rápida alternancia entre procesos, la selección de cada proceso y la asignación de la CPU propiamente tal deben realizarla muy rápidamente. Por otro lado, el planificador de largo plazo se ejecuta con mucha menos frecuencia que el de corto plazo. Este planificador es el encargado de controlar el grado de multiprogramación (el número de procesos en memoria). Si el grado de programación se mantiene más o menos estable, entonces el planificador debe velar porque la cantidad de procesos que entran a memoria sea más o menos igual a la cantidad de procesos que salen de memoria. El algoritmo funciona de la siguiente manera: • Se cargan en memoria un conjunto de procesos, el planificador de bajo nivel se encarga entonces, por un período de tiempo de planificar dichos procesos en la CPU. • Periódicamente se llama al planificador de alto nivel para que saque de memoria el conjunto de procesos de memoria e intercambie de disco a memoria un muevo conjunto de procesos. • Se repite ciclo anterior.

El siguiente esquema refleja como funciona este algoritmo.

150

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 5.10 Planificación de 2 niveles
Algunos de los parámetros que se analizan para decidir qué procesos se intercambian de disco a memoria y viceversa son: • • • • Tiempo que proceso ha permanecido en memoria o disco. Tiempo que proceso ha utilizado CPU. Prioridad del proceso Tamaño del proceso

Planificación por herencia (Inheritance scheduling)
Los procesos pueden ceder su tiempo de CPU a los procesos hijos, de igual manera que un planificador lo hace. De esta forma, múltiples tipos de planificación pueden ser implementados: un planificador para procesos de tiempo real, un planificador para procesos interactivos, una para procesamiento por lotes, etc. El planificador principal (root) es el planificador básico implementado por el SO en si, que planifica los procesos, y los procesos de planificación. Mientras que cada proceso de planificación puede proveer planificación a los demás, el planificador principal utiliza una forma de MPQ para sus funciones.

Planificación evolutiva⊕
La planificación evolutiva se propone para resolver el problema de optimización de: • • • • la planificación de colas de procesos listos la planificación de colas de procesos bloqueados la planificación de colas de control por prioridad la planificación de colas cliente-servidor.

La planificación evolutiva comienza con la manipulación de la aptitud (fitness) de las colas y termina con el proceso óptimo. Además es necesario definir el concepto de proceso evolutivo:

Obras consultadas: [5.25]

151

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Si un proceso confronta la competencia en la planificación evolutiva llamará al proceso evolutivo.

Los procesos evolutivos pueden adaptarse a su ambiente cambiando sus funciones de aptitud. Este tipo de reacción puede hacer a un proceso siempre adecuado en casos en el que el uso del CPU fluctúa y se tiene una mucha carga en la E/S. Nótese que los procesos cambiarán automáticamente sus valores de aptitud de acuerdo al procesamiento de las ordenes ganadoras en las optimizaciones de la planificación, pero no podrán cambiar sus funciones de aptitud originales (las cuales solo pueden cambiarlas usuarios autorizados como el administrador del sistema). La planificación evolutiva se divide en dos partes: • Selección de colas. En la primera fase de la se emplea programación evolutiva para escoger una cola óptima, la cual será usada después para el proceso ganador. • Selección de procesos. En la segunda fase se aplican algoritmos genéticos para la selección del proceso a ejecutar en el siguiente quantum de tiempo del CPU. La planificación evolutiva puede implementarse para reemplazar cualquier control de planificación. Los usuarios pueden aplicar funciones de aptitud apropiadas para simular cualquier control de planificación, por lo que la política de la planificación evolutiva siempre queda en manos del los usuarios.

5.3

Simulación del servicio de administración de procesos

De nuevo para demostrar la integración de las ideas relacionadas a la planificación y administración de procesos hasta este punto, se ha implementado un nuevo simulador.

Figura 5.11 Esquema del funcionamiento de la administración de procesos.

152

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Es importante que el modelo refleje los principales componentes de este subsistema, por lo que deseablemente deben integrarse en el modelo (fig. 5.11): 1. La carga de programas a partir de un evento determinado (generado por el usuario u otro programa) 2. La transferencia del código del almacenamiento secundario a la memoria. 3. La creación de un nuevo proceso para el programa requerido. 4. La inclusión del proceso en una estructura que permite administrar un conjunto de varios procesos (modelo de multiprogramación). 5. Los modulos encargados de la planificación de mediano y corto plazo. 6. El intercambio en el control del uso del CPU. Particularmente en el punto 4 podría pensarse que ya que algunos planificadores usan un mecanismo FIFO, por qué no implementar la estructura de datos correspondiente (una cola) y a partir de ahí manipular los elementos relacionados al administrador de procesos. Sin embargo, después de analizar el código que se presenta en el apéndice "Caso de estudio: Implementación de un microkernel" y la implementación de JOSS (presentada en el capítulo 3), fue claro que de poco serviría modelar la estructura de datos tal como se presenta en un curso de programación, pues por cuestiones de optimización, aunque el comportamiento es el de una cola, la implementación dista mucho de lo convencional. Después de hacer tales reflexiones se comenzó a implementar un simulador que toma en cuenta el hardware y software relacionados a la administración de procesos, el cual cuenta con los siguientes elementos (fig. 5.11a): • El temporizador (Timer). Esta clase modela a un temporizador, un elemento de hardware que puede ser programado para que cada determinado tiempo envíe señales que permitan retomar el control al sistema operativo. El Timer deberá coordinarse con el procesador para que después de determinados ciclos de ejecución las señales sean enviadas. La unidad central de procesamiento (CPU), que es el principal recurso que será repartido. El contexto del proceso está formado por la información que los registros del procesador contienen al ejecutar un programa. Esta clase creará objetos equivalentes a los Bloques de Control de proceso (PCBs). Una lista de bloques de contexto (ProcessList), que sirve como contenedor a los contextos de los procesos simulados. El despachador es el encargado de intercambiar el contexto del proceso en ejecución, por un nuevo proceso a ejecutarse. Para llevar a cabo esta función, debe asociarse una lista de procesos al despachador para que pueda obtener el siguiente proceso. Las estrategias de planificación que se aplicarán a los procesos. En este caso se uso un patrón de diseño llamado Estrategia (Strategy) para implementar las políticas a usar (FIFO y prioridades). Un administrador de procesos (ProcessManager), que es el encargado del control de todos los elementos del modelo.

• •

• •

153

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 5.11a Modelo de clases del simulador de administración de procesos.
La idea es poder crear procesos que puedan ser ejecutados de forma simultánea, aplicando una política de planificación para repartir el tiempo del procesador al proceso. Es posible también destruir un proceso existente. El modelo implementa la etapa de planificación del CPU, por lo que se implementa un despachador y un planificador de corto plazo. Para tomar en cuenta la planificación a medio y largo plazo habría que modelar medios de almacenamiento secundario y algunos otros componentes (lo cuál queda fuera del alcance del modelo presentado).

154

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 5.12 Ejecución del simulador.
El código del simulador puede ser consultado en el apéndice "Simulador del servicio de administración de procesos".

5.4

Procesos concurrentes⊕

Se dice que dos o más procesos son concurrentes si están activos simultáneamente. Los procesos concurrentes pueden ser independientes si no hay interacción directa entre ellos o dependientes si la hay (fig. 5.12).

Figura 5.12 Los procesos P1 y P2, así como P2 y P3 son concurrentes, en cambio P3 y P1 no lo son24
⊕ 24

Obras consultadas: [5.7] [5.8] [5.9] [G19] Imagen reproducida de [5.10]

155

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Si no se cuenta con el soporte de un SO, debe conocerse bien la arquitectura de la computadora donde se pretende que el programa funcione, para implementar de forma manual esta funcionalidad. A continuación se presenta el listado de un programa escrito en C++ (basado en las experiencias expuestas en [G19]) que instrumenta la concurrencia entre dos funciones del mismo programa. Para ello la estrategia a seguir es crear bloques de memoria donde puedan direccionarse las funciones que se quiere hacer concurrir, para que al intercalar la dirección de estos bloques en el registro SP (snack pointer) el control se transfiera de uno a otro. #include<stdio.h> #include<iostream.h> #include<dos.h> #define mb_size 256 /* tamaño del bloque de memoria */ typedef unsigned int WORD; typedef WORD* WPointer; /* prototipos de funciones */ void corrutina1(); void corrutina2(); void transfer_1(); void transfer_2(); void salto_ac1(); void restablecer(); WPointer allocCorrutinaSP(WPointer, WORD); /* variables globales*/ WPointer mem_bloque1, mem_bloque2, Almacen1, Almacen2, AlmacenTmp; /*programa principal*/ main () { mem_bloque1=new WORD[mb_size]; mem_bloque2=new WORD[mb_size]; Almacen1 = allocCorrutinaSP(mem_bloque1,(WORD)corrutina1); Almacen2 = allocCorrutinaSP(mem_bloque2,(WORD)corrutina2); salto_ac1(); return(0); } En este caso, las funciones (corrutinas) solo imprimen un mensaje distintivo, y transfieren de inmediato el control entre sí. void corrutina1() { cout<<"\n Corrutina 1, Acceso 1"; transfer_2(); cout<<"\n Corrutina 1, Acceso 2";

156

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

transfer_2(); cout<<"\n Corrutina 1, Acceso 3"; transfer_2(); restablecer(); } void corrutina2() { cout<<"\n Corrutina 2, Acceso 1"; transfer_1(); cout<<"\n Corrutina 2, Acceso 2"; transfer_1(); cout<<"\n Corrutina 2, Acceso 3"; transfer_1(); } La transferencia del control entre las corrutinas se realiza intercambiando los bloques de memoria en el SP. /* se transfiere el control a la corrutina 1 */ void transfer_1() { Almacen2=(WPointer)_SP; _SP=(WORD)Almacen1; } /* se transfiere el control a la corrutina 2 */ void transfer_2() { Almacen1=(WPointer)_SP; _SP=(WORD)Almacen2; } Es de llamar la atención, que la primera transferencia del programa principal a la corrutina 1 implica salvar el estado del SP del programa, para asegurar que al terminar pueda reestablecerse el estado de ejecución original. /* salva el estado del stack corrutina */ void salto_ac1() { AlmacenTmp=(WPointer)_SP; _SP=(WORD)Almacen1; } pointer (SP) y salta a la primera

/* restablece el estado del stack pointer (SP) */ void restablecer() { Almacen2=(WPointer)_SP; _SP=(WORD)AlmacenTmp; }

157

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

/* aloja la corrutina en el bloque de memoria designado */ WPointer allocCorrutinaSP(WPointer mem_bloque, WORD corrut) { WPointer Almacen; Almacen=(WPointer)mem_bloque+mb_size-1; *(--Almacen)=(WORD)corrut; *(--Almacen)=0; return Almacen; } Como puede apreciarse, la alternativa manual limita de manera importante la implantación de un sistema de concurrencia flexible, que permita a diversos programas aprovechar los recursos del CPU. En este punto radica la importancia de que un sistema operativo pueda proveer esta funcionalidad. Es importante para el diseño de un SO considerar si los procesos dependen o no de otros procesos, para determinar la forma en que se administrarán. Un proceso independiente tiene como características: Que su estado no es compartido de ninguna forma por otros procesos. Que su comportamiento es determinístico (su estado de entrada por si solo determina el resultado) y reproducible. Que puede detenerse o reiniciarse sin efectos adversos (solo varia el tiempo); por ejemplo, un programa que realiza una suma de 1 a i (entrada).

En este caso, hay varias formas de ejecutar un conjunto de procesos independientes en un procesador. Entre ellas están: a. Monoprocesamiento. Un solo proceso es ejecutado hasta su término antes de que cualquier otra cosa se ejecute en el procesador. b. Multiprogramación. Se comparte un procesador entre varios procesos. Si no se comparte el estado, el orden en que se ejecutan es irrelevante. c. Multiprocesamiento. Si el enfoque de multiprogramación funciona, debe funcionar también la ejecución de procesos en procesadores separados. En este caso: . Un proceso dado se ejecuta en solo un procesador a la vez. . Un proceso puede ejecutarse en distintos procesadores, en diferentes instantes de tiempo (se asume que los procesadores son idénticos). Por otro lado la cooperación implica poder compartir el estado de los procesos (procesos cooperativos). En este caso: El comportamiento es no deterministico, pues depende de una secuencia relativa de ejecución, que no puede predecirse. El comportamiento es irreproducible.

158

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Los objetivos de la cooperación entre procesos son: 1. 2. 3. Compartir recursos (una computadora, varios usuarios). Acelerar la ejecución (dividir un trabajo en subtrabajos que se ejecuten en paralelo). Construir sistemas de forma modular.

Los procesos no concurrentes no presentan problemas de coordinación, pues se ejecutan en períodos diferentes de tiempo y por lo general no hay comunicación entre ellos. Para los procesos concurrentes dependientes deben crearse mecanismos de coordinación y comunicación entre ellos. Tales cuestiones se discuten en lo que resta de este capítulo.

5.4.1 Sincronización de procesos⊕
La sincronización entre procesos puede definirse como la necesidad que tienen algunos procesos de bloquearse en determinadas circunstancias y ser despertados cuando ocurren ciertos eventos. Un caso típico en el cual se requiere sincronización ocurre cuando un proceso inicia una lectura y va a utilizar en la siguiente instrucción la información leída. En este caso se debe esperar a que la operación de E/S termine para poder continuar la ejecución. Existen dos puntos que se necesitan considerar en relación a la sincronización entre procesos:

Cómo hacer seguro que dos procesos no se estorben el uno al otro cuando accedan un recurso común. En muchas aplicaciones, un proceso necesita el acceso exclusivo no sólo
a un recurso, sino a varios. Un proceso que copie un archivo mayor que un disco desde una cinta magnética hacia la impresora necesita el acceso exclusivo a la unidad de cinta y a la impresora al mismo tiempo. En un sistema con un único proceso, éste puede tener el acceso a todos los recursos que necesite y realizar su trabajo. Sin embargo, en un sistema con multiprogramación, pueden surgir serios problemas. Supongamos, por ejemplo, que 2 procesos desean imprimir cada uno un archivo enorme. El proceso A solicita el permiso para utilizar la impresora, el cual se le concede. Es entonces cuando el proceso B solicita permiso para utilizar la unidad cinta y se le otorga. El proceso A solicita entonces la unidad de cinta, pero la solicitud es denegada hasta que B la libere. Por desgracia, en este momento, en vez de liberar unidad de cinta, B solicita la impresora. Los procesos se bloquean en ese momento y permanecen así por siempre. Esta situación se llama bloqueo (deadlock). Por lo general, una computadora tiene distintos recursos que pueden ser otorgados. Algunos recursos podrán tener varias instancias idénticas, como es el caso de tres unidad es de cinta. Si se tienen disponibles varias copias de un recurso, cualquiera de ellas se puede utilizar para satisfacer cualquier solicitud del recurso. En resumen, un recurso es cualquier cosa que sólo puede ser utilizada por un único proceso en un instante dado. Los recursos son de dos tipos: apropiables y no apropiables. Un recurso apropiable es aquel que se puede tomar del proceso que lo posee sin efectos dañinos. La memoria es un ejemplo de

Obras consultadas: [5.10]

159

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

recurso apropiable. Por el contrario, un recurso no apropiable, es aquel que no se puede tomar de su poseedor activo sin provocar un fallo de cálculo. Si un proceso comienza a imprimir una salida, se toma la impresora y se le da a otro proceso, el resultado será una salida incomprensible. Las impresoras no son apropiables. Los interbloqueos se relacionan con los recursos no apropiables. Lo usual es que los bloqueos asociados a recursos apropiables se pueden resolver, mediante la reasignación de recursos de un proceso a otro. La secuencia de eventos necesarios para utilizar un recurso es: • • • Solicitar el recurso. Utilizar el recuso. Liberar el recurso.

Si el recurso no esta disponible cuando se le solicita, el proceso solicitante debe esperar. En algunos sistemas operativos, el proceso se bloquea de manera automática al fallar una solicitud de un recurso y se despierta cuando dicho recurso está disponible.

Cómo secuenciar los procesos cuando hay dependencias entre ellos (p.ej. que el
proceso B espere la salida del proceso A). Sean dos procesos A y B, que necesitan leer e incrementar el valor de la variable x cuyo valor inicial es 7; después de que A y B incrementan a x su valor debe ser 9. Supongamos que el proceso A lee el valor de 7 y antes de incrementarlo es retirado (preempted) por el planificador del CPU que empieza a ejecutar a B. B lee el valor de 7 también, lo incrementa y lo almacena en x. Ahora A retoma el CPU, incrementa el valor que leyó a 8 y lo guarda. Aunque el valor de x fue leído e incrementado por A y B, es incorrecto. Situaciones como esta, donde 2 o más procesos están leyendo o escribiendo algún dato compartido y el valor depende en que los procesos ejecutados sean ejecutados en el instante preciso, son llamadas condiciones de competencia (race conditions). La clave para evitar este tipo de condiciones es proveer exclusión mutua, es decir, alguna forma de asegurar que si un proceso está accediendo una variable compartida, otros procesos serán excluidos de hacer lo mismo. La parte de un programa donde las variables compartidas son accedidas es llamada sección crítica (o región crítica). Si la ejecución de procesos es arreglada de manera que ningún par de procesos estuvieran en su sección crítica al mismo tiempo, se evitarían las condiciones de competencia. La solución más sencilla de hardware es tener deshabilitadas las interrupciones de cada proceso cuando entra a su región crítica y habilitarlas cuando sale. Esta solución no es viable pues no es lo más correcto dar el control de deshabilitación de interrupciones a un proceso, y por que en sistemas multiprocesador, esta deshabilitación afecta solo al CPU donde se ejecutan las instrucciones, mientras los otros continúan ejecutándose y accediendo al recurso o variable compartido. Por ello, muchas máquinas proveen instrucciones especiales de hardware que permiten a los procesos probar y modificar el contenido de una palabra o intercambiar el contenido de dos palabras, atómicamente como las instrucciones Test-and-Set y Swap.

160

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Test-and-Set
function Test-and-Set (var target: boolean): boolean; begin Test-and-Set := target; target := true end;

Swap
procedure Swap (var a,b: boolean); var temp: boolean; begin temp := a; a := b; b := temp; end;

Exclusión mutua
(*lock iniciado a falso*) while Test-and-Set(lock) do no-op; <SC> lock := false;

Estas instrucciones pueden usarse para resolver el problema de sección crítica (SC). Cualquiera de estas soluciones puede usarse como base para resolver problemas de sincronización más complejos. Las soluciones de software construidas en las soluciones de hardware, proveen un soporte de alto nivel para el soporte de sincronización. Existen tres mecanismos de software para ello: • • • Semáforos Candados (locks) Monitores

los cuales se explican a continuación.

Semáforos
Un semáforo (S) es una variable entera que puede ser accedida solo por medio de 2 operaciones atómicas: P y V (alemán para Espera y Señal), las cuales se definen como: P(S): while S <= 0 do no-op; S = S-1; V(S): S = S + 1; La prueba y modificación del valor del semáforo en ambas operaciones debe hacerse atómicamente (p.ej. cuando un proceso esta probando o modificando el valor del semáforo, ningún otro proceso puede modificar el valor). Para ver como se usan estas operaciones para sincronizar procesos, sean dos procesos A y B, ejecutando las sentencias S1 y S2 respectivamente. La condición es que S2 puede ser excluido solo después de S1. Esto se logra con un semáforo (synch) inicializado en cero. A y B ejecutarán el siguiente código: A: S1; V(synch); B: P(synch); S2;

161

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Puesto que synch está inicializada a cero, B ejecutará S2 sólo después de que A lo haya señalado por la invocación de V(synch) que está después de S1. La desventaja de esta implementación de semáforos es que involucra tiempo de espera, pues se prueba continuamente una variable hasta que aparece algún valor. Esto debe evitarse pues desperdicia tiempo del CPU. Solo cuando hay una expectativa de que la espera será corta el esquema funciona. Tomando esto en cuenta, puede redefinirse P() y V() de la siguiente manera. Cuando un proceso ejecuta P() y encuentra que el semáforo no es positivo, debe esperar. Sin embargo, en vez de esperar, el proceso puede bloquearse a si mismo. La operación de bloque coloca al proceso en una cola de espera asociada con el semáforo. El control es entonces transferido al planificador del CPU, el cual selecciona otro proceso para ejecutar. Un proceso que es bloqueado, esperando a un semáforo, debe reestablecerse cuando otro proceso ejecute la operación V(). La cuestión importante es percatarse de que los semáforos trabajan solo cuando sus operaciones son atómicas. En un ambiente de un solo procesador, esto se logra deshabilitando las interrupciones por el tiempo que duren estas operaciones.

Candados (Locks)
Un candado es una primitiva de sincronización parecida a los semáforos, que provee exclusión mutua. Las operaciones atómicas provistas son Acquire y Release. Un candado puede estar libre u ocupado (al inicio esa libre). Antes de acceder a una variable compartida, un proceso adquiere un candado, y lo libera al terminar su acceso a la variable. Dos procesos A y B que acceden a una variable compartida podrían ejecutar el siguiente código para sincronizar su acceso a sus secciones críticas: Lock->Acquire(); //obtiene control del candado // Sección critica Lock->Release(); //libera el candado Por convención, un candado es liberado por el proceso que lo adquiere (lo cual es diferente a los semáforos). Un ejemplo simple es una lista con sincronización: Lock candado; InsertaEnCola() { candado.Acquire(); añade un elemento en la cola; candado.Release(); } ExtraeDeCola() { candado.Acquire();

162

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

if (algo en la cola) extrae(elemento); candado.Release(); return elemento; } El ejemplo anterior nos muestra un problema que los candados no son capaces de resolver. La rutina ExtraeDeCola debería esperar a que hubiera algún elemento en la cola. Si lo que hacemos es dormir al hilo hasta que alguien deposite un elemento en la cola, resulta que el programa se bloquea, ya que al estar retenido el cerrojo, ningún otro hilo puede manipular la cola. Por tanto hay que liberar el candado antes de esperar. Una posible solución sería: ExtraeDeCola() { candado.Acquire(); while (cola vacía) { candado.Release(); candado.Acquire(); } extrae(elemento); candado.Release(); return elemento; } Esta solución funciona, pero utiliza espera activa, es decir que el hilo está continuamente entrando y saliendo de la sección crítica para revisar si la cola está vacía.

Monitores y variables de condición
Los monitores fueron diseñados para facilitar la codificación de programas que implementaban sincronización. Los semáforos y candados tienen que usarse cuidadosamente, pues un pequeño error como una operación atómica en el lugar equivocado puede causar un bloqueo (deadlock) u otras formas de comportamiento impredecibles. Un monitor es una primitiva de alto nivel, provista como construcción de un lenguaje de programación, lo que significa que el compilador está al tanto de la construcción y puede manejar llamadas a ella de forma diferente a otras construcciones. Un monitor es una colección de procedimiento, variables, y estructuras de datos agrupadas en un módulo o paquete especial. He aquí un ejemplo: Un proceso puede hacer llamadas a procedimientos por medio de un monitor, pero no puede acceder directamente a las estructuras de datos del monitor. La propiedad más importante de un monitor es que un solo proceso puede estar activo en el monitor en cualquier instante. Cuando un proceso llama al procedimiento monitor, el procedimiento primero checa si otro proceso esta activo en el monitor. Si es así, el proceso que hace la llamada es suspendido hasta que el otro proceso haya dejado el monitor. Si ningún otro proceso esta usando el monitor, el proceso que llamó puede entrar.

163

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Lo bueno de esto, es que el compilador es el que implementa la exclusión mutua que necesitan los procesos, no los procesos por si mismos. Es suficiente saber que transformando todas las regiones criticas en procedimientos de monitor, ninguno de los proceso ejecutarán sus regiones criticas al mismo tiempo. Los monitores necesitan proveer una forma para que los procesos se bloqueen entre si cuando no puedan proceder. La idea de las variables de condición es tener un mecanismo que permita a un proceso abandonar una sección crítica y a la misma vez quedarse bloqueado en espera de una condición que alguien le debe notificar. Como en los casos de los candados y los semáforos, se provee un conjunto de operaciones atómicas, que son: • Wait(condición). Libera el candado, suspende el hilo y espera a que alguien ejecute un Signal (libera el semáforo binario del monitor y pone al proceso a dormir. Cuando el proceso despierta de nuevo, trata de readquirir el semáforo binario inmediatamente). Signal(condición). Despierta un proceso que estaba esperando por la variable de condición. Si no hay ninguno, no hace nada. Broadcast(condición). Despierta todos los procesos que esperan por la variable de condición. Si no hay ninguno, no hace nada. Un ejemplo práctico de esto, son las variables de condición de Java: • • • wait(): libera el candado del monitor del objeto; pone el hilo a dormir. notify(): levanta a un proceso que espera en la condición; este proceso tratara de readquirir el candado del monitor. notifyall(): despierta a todos los procesos en condición de espera; cada proceso tratara de retomar el candado del monitor.

• •

Cuando un procedimiento de monitor se da cuenta que no pude continuar, realiza un Wait en alguna variable de condición. Esto causa que la llamada al proceso A sea bloqueada. También permite que otro proceso B que se le haya prohibido anteriormente la entrada al monitor, pueda entrar. B ahora puede despertar a otro proceso haciendo un Signal en la variable de condición que A estaba esperando. Sea por ejemplo un proceso productor que genera numeros, y uno o varios procesos consumidores que harán uso de ellos. Para asegurar que el producto estará disponible para todos los consumidores, este se ofrecerá como recurso compartido a todos aquellos que lo requieran. En lenguajes de alto nivel como Java se cuenta con construcciones del lenguaje que permiten codificar este tipo de programas de manera sencilla. La sección de código en donde se declaran las estructuras de sincronización es en el recurso compartido. En el ejemplo puede apreciarse como los métodos get() y put() encargados de aceptar o ceder un valor almacenado tienen la declaración synchronized, y dentro de los métodos es donde se hace referencia a las operaciones del monitor.

164

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

class Recurso { //Recurso compartido entre productor y consumidor private int contenido; private boolean disponible = false; public synchronized int get() { //si esta vacio el contenido o alguien lo esta accesando, bloquea while (disponible == false) { try { wait(); } catch (InterruptedException e) { } } disponible = false; notify(); return contenido; } public synchronized void put(int valor) { while (disponible == true) { try { wait(); } catch (InterruptedException e) { } } contenido = valor; disponible = true; notify(); } }

El productor entonces deberá contar con una instancia del recurso compartido, la cual será enviada como parámetro durante su inicialización, para después hacer uso de él depositando los objetos que genere.
class Productor extends Thread { private Recurso recurso; private int numero; public Producer(Recurso r, int numero) { recurso = r; this.numero = numero; } public void run() { //el productor genera 10 numeros; //cada uno lo va enviando al recurso compartido for (int i = 0; i < 10; i++) { recurso.put(i); System.out.println("Productor #" + this.numero + " pone: " + i); try {

165

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar sleep((int)(Math.random() * 100)); } catch (InterruptedException e) { } } } }

Por su parte el consumidor tambien debe contar con una instancia del recurso compartido, la cual será enviada como parámetro durante su inicialización; de esta manera tendrá acceso a los objetos generados por el productor.
class Consumidor extends Thread { private Recurso recurso; private int numero; public Consumidor(Recurso r, int numero) { recurso = r; this.numero = numero; } public void run() { int value = 0; for (int i = 0; i < 10; i++) { value = recurso.get(); System.out.println("Consumidor #" + this.numero + " obtiene: " + value); } } }

Lo único que resta es instanciar al productor, a los consumidores y al recurso compartido en una aplicación para observar los resultados.
public class MonitorApp { public static void main (String[] args) { Recurso rn= new Recurso(); //el recurso compartido new Productor(rn,1).start(); //1 productor new Consumidor(rn,1).start(); //3 consumidores new Consumidor(rn,2).start(); new Consumidor(rn,3).start(); } }

Para evitar que dos procesos se activen dentro de un monitor al mismo tiempo, se necesita una regla que especifique que es lo que pasa después de una llamada Signal. Debería B esperar hasta que A deje el monitor o debería A esperar hasta que B deje el monitor. Los investigadores han defendido las dos alternativas: prioridad al que ya está dentro, o al que estaba esperando. Las dos propuestas clásicas son las de Tony Hoare (investigador británico) y la de Mesa (lenguaje de programación desarrollado por Xerox en los 1970s):

166

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Estilo Mesa: Quien hace Signal continúa reteniendo el candado. El proceso que había hecho Wait se pone en la cola de preparados sin ninguna prioridad especial y esperará a adquirir de nuevo el candado (en pugna con los restantes procesos). Estilo Hoare: Quien hace Signal cede el cerrojo al del Wait y abandona la CPU. El proceso que había hecho Wait entra en ejecución sobre la marcha. El que hizo Signal tiene que esperar a adquirir de nuevo el candado.

Muchos sistemas operativos modernos utilizan el estilo Mesa por la sencillez de la implementación. Una diferencia fundamental entre semáforos y variables de condición es que éstas no tienen memoria. Si alguien ejecuta una operación Signal sin que haya nadie esperando, esa operación se pierde para siempre, mientras que un semáforo "recuerda" para posteriores Waits.

Interbloqueos⊕
Un sistema está interbloqueado cuando dos o más procesos esperan por un evento que no va a ocurrir. Por ejemplo, supóngase que existen dos procesos P1 y P2 que comparten dos recursos R1 y R2. P1 solicita el recurso R2 mientras tiene asignado R1 y simultáneamente P2 solicita R1 mientras tiene asignado R2. En este caso se presenta un interbloqueo.

Figura 5.13 Interbloqueo25
Cuando los recursos son compartidos entre varios usuarios, donde cada uno mantiene un control exclusivo sobre determinados recursos asignados a ese usuario, pueden producirse interbloqueos, en los cuales los procesos de algunos usuarios no podrán llegar a su término. En cualquier sistema que mantenga procesos en espera mientras realiza la asignación de recursos y procesa la planeación de decisiones, es posible que un proceso sea aplazado indefinidamente mientras otros reciben la atención del sistema. Esta situación llamada postergación indefinida puede ser en ocasiones de consecuencias equivalentes a un interbloqueo.

⊕ 25

Obras consultadas: [5.10] [5.33] [5.34] Imagen reproducida de [5.10]

167

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Cuando los recursos son planeados en función de prioridades, es posible que un proceso dado espere indefinidamente en tanto continúen llegando procesos de prioridades más importantes. Hay cuatro condiciones necesarias que deben darse para que se produzca un interbloqueo [5.34]: 1. Los procesos reclaman control exclusivo de los recursos que piden (condición de exclusión mutua). 2. Los procesos mantienen los recursos que ya les han sido asignados, mientras esperan recursos adicionales (condición de espera por). 3. Los recursos no pueden ser extraídos de los procesos que los tienen hasta su completa utilización (condición de no apropiatividad). 4. Existe una cadena circular de procesos en la cual cada uno de ellos mantiene a uno o más recursos que son requeridos por el siguiente proceso de la cadena (condición de espera circular). Existen algunas estrategias para evitar varias de las condiciones de interbloqueo [5.34]: 1. Cada proceso deberá pedir todos sus recursos requeridos de una sola vez y no podrá proceder hasta que le hayan sido asignados. 2. Si a un proceso que mantiene ciertos recursos se le niega una nueva petición, éste deberá liberar sus recursos originales y en caso necesario pedirlos de nuevo junto con los recursos adicionales. 3. Se impondrá la ordenación lineal de los tipos de recursos en todos los procesos, es decir, si a un proceso le han sido asignados recursos de un tipo dado, en lo sucesivo sólo podrá pedir aquellos recursos de los tipos que siguen en el ordenamiento. En general existen dos tipos de soluciones al interbloqueo: 1. Prevención (evitar que ocurra) 2. Tratamiento (permitir que ocurra, detectarlo y corregirlo)

Prevención y tratamiento
Existen dos tipos de prevenciones: una estática, cuya solución se basa en un conjunto de reglas y otra dinámica, en la cual se evita que ocurra, no asignando recursos cuando ello puede conducir a interbloqueos. La prevención estática se basa en el hecho que para que ocurra un interbloqueo se deben dar las siguientes cuatro condiciones en forma simultánea: (c1) Los recursos se utilizan en exclusión mutua (c2) Los recursos, una vez asignados, no pueden ser retirados a los procesos (c3) Los procesos esperan por la asignación de recursos mientras tienen asignados otros (c4) Existe una cadena circular de procesos en la cual cada uno tiene asignado uno o más recursos que son solicitados por otros procesos.

168

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Si se desea evitar los interbloqueos, se debe impedir que se cumpla al menos una de las cuatro condiciones. La condición (c1) no se puede evitar, ya que como se mencionó previamente, los recursos se deben utilizar en exclusión mutua. Para evitar la condición (c2) se puede actuar de la siguiente forma: Si un proceso tiene asignado un recurso R1 y le es negado otro recurso R2, entonces se le retira el recurso R1. Sin embargo, esta solución puede llevar a que la ejecución de un proceso se prolongue indefinidamente, debido a que nadie puede garantizar que termine en un tiempo determinado. Para evitar la condición (c3), se pueden asignar todos los recursos necesitados por el proceso en el momento de su creación, sin embargo, esto conlleva a un manejo poco eficiente de los mismos. Para eludir la condición (c4) se puede hacer una asignación recursos por niveles. En este caso se le asigna a cada tipo de recurso un nivel y se establece que los recursos deben ser asignados en orden ascendente de nivel. La prevención dinámica consiste en analizar cada vez que se va a asignar un recurso, si tal asignación puede conducir a un interbloqueo (situación no-segura), en cuyo caso no se asigna. En caso contrario (situación segura) el recurso se asigna. Por ejemplo suponga que en el sistema existen múltiples recursos de un solo tipo y que existen cuatro procesos que quieren usarlos.
MÁXIMO RECURSOS NECESARIOS 8 7 5 5

PROCESO P1 P2 P3 P4

RECURSOS ASIGNADOS 4 3 3 0

Suponga además que la cantidad de recursos disponibles es 2. Si el proceso P3 solicita estos recursos se le pueden asignar, ya que tal asignación conduce a una situación segura, puesto que P3 puede terminar y liberar los 5 recursos asignados y con ellos se garantiza que todos los demás procesos pueden terminar. Sin embargo, si estos 2 recursos son solicitados por P2, la situación no es segura si se le asignan, ya que no se puede garantizar que los procesos terminen satisfactoriamente. El hecho de que la situación no se segura no implica necesariamente que se vaya a presentar interbloqueo, sino que puede ocurrir. El tratamiento se basa en el hecho de detectar el interbloqueo y corregirlo. La corrección se limita en la mayoría de los casos a seleccionar uno o más procesos de baja prioridad y destruirlos. En el peor de los casos, se debe reiniciar el sistema. Como se puede suponer, este tipo de solución puede conducir a inconsistencias en el sistema, además de ser una solución demasiado costosa.

169

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

5.4.2 Comunicación entre procesos
Los procesos frecuentemente necesitan comunicarse con otros procesos. Por ejemplo, la entrada de un proceso puede depender de la salida de otro o los procesos pueden necesitar acceder al mismo tiempo el mismo recurso y necesitar hacerlo de una manera ordenada.

Figura 5.14 Esquema donde los procesos que requieren acceder a un recurso compartido
Tanto los semáforos como los monitores, están limitados por el alcance que tienen, es decir son primitivas y abstracciones que operan sobre una computadora aislada. Cuando se desea trabajar sobre un sistema distribuido en un ambiente de red, estos mecanismos ya no sirven, pues no permiten comunicar procesos residentes en computadoras distintas. Por esta razón existen otros tipos de comunicación entre procesos, en donde no es necesario que los procesos se encuentren en la misma máquina. Dentro de estos mecanismos se encuentran: 1. Paso de mensajes 2. Tuberías (Pipes) 3. RPC (esta se trata en la sección 5.4.3) El problema del Productor-Consumidor, resume el paradigma de los procesos cooperativos; el proceso productor produce información que es consumida por el proceso consumidor.

El esquema productor-consumidor
En el esquema productor-consumidor se definen dos tipos de procesos, productores y consumidores, que escriben y leen información de una zona común denominada buzón. Dado que la zona es compartida, se debe garantizar exclusión mutua para su manejo. Cuando la zona se llene, se debe bloquear a los productores. Cuando la zona esté vacía, se debe bloquear a los consumidores.

170

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

La solución incluye el uso de las siguientes variables: • • • • • • Buzón: arreglo de 0...n posiciones donde se guardan los mensajes. prox_prod: indica la posición donde se debe colocar el próximo mensaje. (0) prox_cons: indica la posición desde donde se debe leer el siguiente mensaje (0) em: semáforo de exclusión mutua para el uso del buzón (1) lleno: semáforo que controla la cantidad de posiciones ocupadas en el buzón. (0) vacío: semáforo que controla la cantidad de posiciones vacías en el buzón (n)

Las funciones de producir y consumir se definen de la siguiente manera: Producir(q,m) /* q es un proceso, m un mensaje */ p(vacío,q); p(em,q); buzón[prox_prod]=m; prox_prod=(prox_prod+1)%n; v(em); V(lleno); Fin_Producir Consumir(q) p(lleno,q); p(em,q); m<==buzon[prox_cons]; prox_cons=(prox_cons+1)%n; v(em); v(vacío); Fin_consumir Vale la pena notar que la exclusión mutua solo afecta a las variables comunes (buzón, prox_prod, prox_cons).

Mensajes
Consideraremos que un mensaje es una pieza de información que es enviada de un proceso a otro. Además diremos que un buzón (Mailbox) es un lugar donde se almacenan los mensajes a medida que estos se envían y reciben. Por otro lado, existen 2 posibles operaciones sobre los mensajes, que son las siguientes. • • send(destino,&mensaje): copia un mensaje en un mailbox, si el mailbox está lleno, espera a que exista un espacio en el y lo envía a destino. receive(origen, &mensaje): recibe mensaje del origen lo saca del mailbox, si el mailbox esta vacío espera a que llegue un mensaje. A continuación se presenta el problema productor/consumidor resuelto mediante mensajes.

171

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

#define N 100 #define MAILBOX 4; typedef int message[MAILBOX]; void productor(void) { int item; message m; while(1){ produce_item(item); receive(consumidor,&m); construir_mensaje; send(consumidor,&m); } } void consumidor(void) { int item, i; message m; for (i=0;i<N;i++) send(productor,&m); while(1){ receive(productor,&m); extrae_mensaje; send(productor,&m); consume_item(item); } } Existen dos tipos de pasos de mensajes: • • a través de tuberías (pipes), mensajes en una sola dirección y a través de RPC, mensajes en ambas direcciones.

172

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 5.15 Entrega de mensajes con múltiples colas Tuberías (pipes)⊕
Las tuberías (pipes) son mecanismos de comunicación entre procesos que permiten que dos o más procesos se envíen información entre ellos. Un usuario puede ejecutar varios procesos e interconectarlos a través de tuberías, simbolizados por el carácter ¦ (ASCII 124). Son usados comúnmente por el shell para conectar la salida estándar de un comando a la entrada estándar de otro. Aquí se muestra un ejemplo de un comando en UNIX que determina cuantos archivos, con extensión .c hay en el directorio actual. $ ls *.c | wc -l El comando ls lista los archivos con extensión .c , y su salida va hacia el comando wc que cuando se invoca con la opción -l muestra el total de líneas en la entrada. Así, el comando completo con el pipe calcula el total de archivos con extensión .c que hay en el directorio actual. El pipe tiene un extremo para lectura y otro para escritura. Asociados a cada extremo puede haber uno o más lectores o escritores. Si el pipe esta full, el escritor de turno automáticamente

Obras consultadas: [5.35] [5.36]

173

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

se suspende. Del mismo modo, si el pipe esta vacío, el lector de turno se suspende. Hay dos tipos de pipes: a. Nominales (named pipes). Los pipes nominales tienen menos restricciones que los pipes no nominales, y entre sus ventajas se encuentran: • • • Tienen un nombre que existe en el sistema de archivos. Pueden ser usados por procesos que no tienen ninguna relación. Existen hasta que son borrados explícitamente.

Todas las reglas mencionadas para los pipes no nominales aplican para los pipes nominales. Excepto que los pipes nominales tienen mayor capacidad. Los pipes nominales son archivos especiales del sistema de archivos y pueden crearse de las siguientes formas (en sistemas UNIX): • • Usando el comando mknod desde el shell. Usando la llamada al sistema mknod().

b. No nominales (unnamed pipes). Un pipe no nominal es un enlace de comunicación unidireccional que puede crearse usando la llamada al sistema pipe. Cada extremo del pipe tiene un descriptor de archivo asociado. Se puede escribir al pipe y leer de él usando las llamadas al sistema write() y read(), respectivamente. Cuando un proceso termina de usar el pipe, debe cerrarlo usando la llamada al sistema close().

Caso de estudio: Comunicación entre procesos en Linux
El mecanismo de comunicación entre procesos (IPC) es provisto para que procesos ejecutándose concurrentemente tengan forma de compartir recursos, sincronizarse e intercambiar datos entre si. Linux implementa esto por medio de recursos compartidos, estructuras de datos del kernel y colas de espera. Linux provee las siguientes formas de IPC: • Señales (signals). Tal vez la mas antigua forma de Unix IPC, las señales son mensajes de notificación asíncronos enviados por el kernel u otro proceso, a un proceso de destino. • Colas de espera (wait queues). Proveen un mecanismo para poner procesos en espera (sleep) mientras esperan a que una operación se complete. Este mecanismo es usado por el planificador de procesos para implementar bottom-half handling • Candados de archivos (File locks). Proveen un mecanismo (soportado por el sistema de archivos) que permite a los procesos declarar secciones de archivos o archivos completos como de solo lectura para todos los procesos, excepto para el que tiene el candado. • Canales (Pipes y Named Pipes). Permite la transferencia de datos bidireccional entre dos procesos ya sea por la creación explicita (con la llamada de sistema pipe()) de una conexión de canal (o tubería, como se prefiera), o comunicándose por medio de un canal residente en el sistema de archivos (usando las llamadas del sistema de archivos read() y write()). • System V IPC. Consiste en la llamada al sistema ipc(). Las diversas operaciones IPC son especificadas por medio de parámetros en la llamada.

174

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• •

• •

Semáforos. Una implementación del clásico modelo de semáforos (el cual se trata con mas detalle en el siguiente capitulo), que además permite la creación de arreglos de semáforos. Colas de mensajes (Message queues). Son un modelo de transferencia de datos. Un mensaje es una secuencia de bytes, con un tipo asociado. Los mensajes son escritos a las colas de mensajes, y los mensajes pueden obtenerse leyendo las mismas estructuras, restringiendo la lectura por medio del tipo de mensaje. Memoria compartida. Es un mecanismo por el cual varios procesos tienen acceso a la misma región de memoria física. Sockets de dominio (Unix Domain sockets). Otro mecanismo de transferencia de datos orientado a conexión que provee el mismo modelo de comunicación que los sockets INET.

El subsistema IPC expone llamadas de espera a otros subsistemas del kernel. Puesto que las colas de espera no son usadas por los procesos de usuario, no tienen una interfaz de llamadas al sistema.

Figura 5.16 Estructura del subsistema IPC de Linux26

5.4.3 Comunicación entre procesos en Sistemas Distribuidos⊕
Un sistema distribuido es aquel en el que dos o más máquinas colaboran para la obtención de un resultado. Sus principales entidades son: • •
26 ⊕

Computadoras con dispositivos, procesadores, etc. Procesos que reciben, manipulan, transforman y emiten datos

Imagen reproducida de [5.32] Obras consultadas: [5.11]

175

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

El medio sobre el cual circulan los datos y que forman una red local dotada de propiedades estructurales y dinámicas

Las principales características de un sistema distribuido son: • • • • • Uso de un sistema de comunicación Ausencia de memoria común Sincronización del trabajo Ausencia de un estado global perceptible por un observador Comunicación a través de mensajes

La diferencia más importante entre un sistema distribuido y un sistema de un solo procesador es la comunicación entre procesos. En un sistema de un solo procesador la comunicación supone implícitamente la existencia de la memoria compartida. Un ejemplo es el problema de los productores y los consumidores, donde un proceso escribe en un buffer compartido y otro proceso lee de él.

Figura 5.17 Esquema de procesos que se ejecutan en una computadora y en un sistema distribuido
En un sistema distribuido no existe la memoria compartida y por ello toda la naturaleza de la comunicación entre procesos debe replantearse. Los procesos para comunicarse, deben apegarse a reglas conocidas como protocolos. Para los sistemas distribuidos en un área amplia, estos protocolos toman frecuentemente la forma de varias capas y cada capa tiene sus propias metas y reglas. Los mensajes se intercambian de diversas formas, existiendo muchas opciones de diseño al respecto; una importante opción son las llamadas remotas a procedimientos. También es importante considerar las posibilidades de comunicación entre grupos de procesos, no solo entre dos procesos.

176

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

5.4.4 Modelo cliente-servidor
Debido a la ausencia de memoria compartida, toda la comunicación en los sistemas distribuidos se basa en la transferencia de mensajes. Cuando el proceso A quiere comunicarse con el proceso B: • • • Construye un mensaje en su propio espacio de direcciones. Ejecuta una llamada al sistema para que el SO busque el mensaje y lo envíe a través de la red hacia B. Para evitar el caos, A y B deben coincidir en el significado de los bits que se envíen.

El modelo cliente - servidor tiene como idea fundamental la estructuración del SO como: • Un grupo de procesos en cooperación, llamados servidores, que ofrecen servicios a los usuarios. • Un grupo de procesos usuarios llamados clientes.

Figura 5.18 Modelo cliente-servidor en un escenario distribuido
Los procesos clientes y servidores han de seguir un protocolo de comunicaciones que defina cómo se codifican las peticiones y cómo se sincronizan entre sí los procesos. El modelo cliente - servidor se basa en un protocolo solicitud / respuesta donde: • • • El cliente envía un mensaje de solicitud al servidor pidiendo cierto servicio. El servidor ejecuta el requerimiento y regresa los datos solicitados o un código de error si no pudo ejecutarlo correctamente. No se tiene que establecer una conexión sino hasta que ésta se utilice.

Direccionamiento
Para que un cliente pueda enviar un mensaje a un servidor, debe conocer la dirección de éste. Un esquema de direccionamiento se basa en la dirección de la máquina destinataria del

177

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

mensaje, aunque es limitativo si en la máquina destinataria se ejecutan varios procesos, pues no se sabría para cuál de ellos es el mensaje. Otro esquema de direccionamiento se basa en identificar los procesos destinatarios en vez de a las máquinas, lo cual elimina la ambigüedad acerca de quién es el receptor, pero presenta el problema de cómo identificar los procesos (una solución es una nomenclatura que incluya la

identificación de la máquina y del proceso)
Otro método de direccionamiento consiste en asignarle a cada proceso una única dirección que no contenga un número de máquina. Una forma es mediante un asignador centralizado de direcciones a los procesos que mantenga un contador. Al recibir una solicitud de dirección regresa el valor actual del contador y lo incrementa en uno. La desventaja es el elemento centralizado. También existe el método de dejar que cada proceso elija su propio identificador en un espacio de direcciones grande y disperso, por ejemplo: enteros binarios de 64 bits. La probabilidad de que dos procesos elijan el mismo número es muy pequeña. Existe el problema, para el núcleo emisor, de saber a qué máquina enviar el mensaje

Otro método utiliza hardware especial:
Los procesos eligen su dirección en forma aleatoria. Los chips de interfaz de la red se diseñan de modo que permitan a los procesos almacenar direcciones de procesos en ellos. Los paquetes transmitidos utilizan direcciones de procesos en vez de direcciones de máquinas. Al recibir cada paquete el chip de interfaz de la red debe examinarlo para determinar si el proceso destino se encuentra en esa máquina: o Lo acepta en caso afirmativo. o No lo acepta en caso negativo.

5.4.5 Llamadas a Procedimientos Remotos (RPC)⊕
El modelo cliente - servidor es una forma conveniente de estructurar un SO distribuido, pero posee desventajas: • El paradigma esencial en torno al que se construye la comunicación es la entrada / •

salida. Los procedimientos enviar / recibir están reservados para la realización de E/S.

Una opción distinta fue planteada por Birrel y Nelson, quienes propusieron permitir a los programas que llamasen a procedimientos localizados en otras máquinas. La información se puede transportar de un lado al otro mediante los parámetros y puede regresar en el resultado del procedimiento. El programador no se preocupa de una transferencia

Obras consultadas: [5.11] [5.37]

178

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

de mensajes o de la E/S. A este método se lo denomina llamadas a procedimientos remotos (RPC - Remote Procedure Calls).

Figura 5.19 Esquema de invocación local y remota de procedimientos
El RPC es un mecanismo para el desarrollo de aplicaciones cliente-servidor, basado en la invocación de procedimientos remotos. El objetivo es que un programador pueda desarrollar su aplicación de manera convencional, y decidir después cómo distribuir las funciones entre los clientes y el servidor. Cuando el programa en el cliente invoca una función remota, su ejecución se suspende, se invoca la función en el servidor, y cuando ésta termine se reactiva el programa en el cliente. En cuanto a la ejecución, el ideal sería que no hubiera distinción entre una ejecución remota o local de una función. Sin embargo, existen dos problemas que atentan contra esta transparencia: 1. La latencia de la red. El invocar una función remota puede tardar más que una invocación local. 2. La confiabilidad de la red. La invocación remota implica enviar al servidor la identificación de la función a ejecutar, al igual que los parámetros, y recibir del servidor el resultado de la ejecución. Cualquiera de estos mensajes (solicitud o respuesta) puede ser extraviado o duplicado por la red, por lo que deberá considerarse el manejo de estos errores en las aplicaciones. El mecanismo de RPC incluye los siguientes aspectos: • Unos "intermediarios" (stubs) entre la aplicación en el cliente y la(s) función(es) en el servidor. El intermediario en el cliente se encarga de empaquetar los parámetros y la solicitud, enviarlos al intermediario en el servidor, y luego esperar la respuesta, desempaquetarla y entregarla a la aplicación. El intermediario en el servidor se encarga de recibir peticiones, desempaquetar los parámetros, invocar la función solicitada, pasarle los parámetros, luego obtener el resultado, empaquetarlo y enviarlo al cliente. El empaquetamiento (marshalling) debe tomar en cuenta que las máquinas cliente y servidor puedan ser de arquitectura diferente (y no compatible). Localización del servicio. Cuando un cliente invoca una llamada remota, debe ubicarse el servidor, el intermediario que sirve esa función, y finalmente la función. Semántica del RPC (confiabilidad). Cuando una función remota es invocada, y no retorna, ¿qué se puede interpretar en el cliente?. Y si retorna, ¿puede estar seguro el cliente que la función se realizó una sola vez?

• • •

179

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Algunos de los estándares más usados para la implementación de RPC son: • • • SUN RPC (es el más extendido). DCE RPC. ANSA RPC (es el más reciente).

5.5

Comentarios

En este capítulo se han expuesto los fundamentos en relación a la administración de procesos. Cabe mencionar que con el desarrollo de sistemas distribuidos, las técnicas convencionales de planificación de procesos, ejecución, etc., han tenido que ser ampliadas para satisfacer las exigencias de ambientes heterogéneos e interconectados. A este respecto hay que seguir muy de cerca el desarrollo de nuevos productos de software (middleware) que proveen funcionalidad adicional para el procesamiento distribuido, y que aunque no forma parte del SO como tal, expanden sus funciones. En el capítulo siguiente se hablará de los recursos que los procesos pueden consumir, y como se requieren otros subsistemas para la administración de periféricos, almacenamiento y comunicaciones en red.

180

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

5.6

Obras consultadas
[5.13] CPU SCHEDULING http://www.cs.njit.edu/~web332/F98/CPU_scheduling/ cpuschd_obj.html [5.14] Operating systems concepts. A. Q. Davis 1999 2000 http://www.personal.comp.brad.ac.uk/~aqdavis/fullInd ex!.htm [5.15] Esquemas de Planificación. Angela Di Serio USB - Sistemas Paralelos y Distribuidos. 1998 http://ci.ldc.usb.ve/~spd/Docencia/ci3821/Tema4/node6.html [5.16] FCFS Scheduling

[5.1] Weaving a Thread. Shashi Prasad. October, 1995. http://www.byte.com/art/9510/sec12/sec12.htm [5.2] An Operating Systems Vade Mecum. Raphael A.

Finkel.University of Wisconsin at Madison
Prentice Hall [5.3] Student Operating System. R. Lambert, J. Homack, B. Kennedy, T. Nassif & A. Biver COP 4610. Dr. Coulter 12-3-97 [5.4] Curso de sistemas operativos. Capitulo 10. Procesos. http://crysoft.com/cursos/endetalle.asp?pide=sisope&c apitulo=10 [5.5] The 'standard' cpu scheduling algorithm - A short description of the basic cpu scheduling algorithm used by most OSs today. Pieter Dumon. 1998. http://unios.dhs.org/std-sched.html [5.6] Sistemas operativos I. Instituto tecnologico de Veracruz http://itver.edu.mx/so1/sistemas_operativos.htm [5.19] Round Robin Scheduling [5.7] CS 537 Notes, Section #4: Independent and Cooperating Processes. Barton P. Miller. 1997. http://www.cs.wisc.edu/~bart/537/lecturenotes/ [5.8] Monitores, variables condición y los lectores/escritores Adaptado del original de Tom Anderson (Universidad de Berkeley) [5.9] CS 537 Notes, Section #8: Monitors. Barton P. Miller. 1997. http://www.cs.wisc.edu/~bart/537/lecturenotes/ [5.10] UFPS Sistemas Operativos I http://bari.ufps.edu.co/personal/150802A/procesos.htm [5.11] Sistemas operativos. Master David Luis la Red Martínez http://exa.unne.edu.ar/depar/areas/informatica/Sistem asOperativos/SOF.htm [5.12] Scheduling Simulations. Charles Baldridge and Karl Papadantonakis. CS414 project http://www.people.cornell.edu/pages/csb11/CS414/sim .html http://megahertz.njit.edu/~wxl3226/rr.html [5.20] Round Robin CPU Scheduling http://www.cs.njit.edu/~web332/F98/CPU_scheduling/ cpuschd_rr.html [5.21] Priority scheduling http://megahertz.njit.edu/~wxl3226/pr.html [5.22] Shortest-Job-First algorithm http://megahertz.njit.edu/~pxl8936/sjf.html [5.23] Multilevel Queue Scheduling http://megahertz.njit.edu/~pxl8936/mqs.html [5.24] Multilevel Feedback Queue Scheduling http://megahertz.njit.edu/~yxy8776/node200.html [5.25] Evolutionary Computation for Scheduling Controls in Concurrent Object-Oriented Systems. Tzilla Elrad, Jinlong Lin & Douglas J. Cork IJCA, PP.11-20, Vol.5, No.3, Sept, 1998, Published by ISCA.

http://www-ec.njit.edu/~yxy8776/node100.html [5.17] First-Come First-Served Scheduling http://www.personal.comp.brad.ac.uk/~aqdavis/cpu/sc heduling/FIFO.htm [5.18] Sistemas operativos. Gabriela Herrera B. http://www.inf.udec.cl/~sistcomp/SistOpe/

181

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
http://www.rice.iit.edu/~linjin/ijca98.zip [5.34] Interbloqueo [5.26] CS 537 Lecture Notes Part 3 - Processes and Synchronization http://www.cs.wisc.edu/~solomon/cs537/notes.html [5.27] Apuntes de Sistemas Operativos. Luis Mateu DCC - U. de Chile http://www.dcc.uchile.cl/~jpiquer/Docencia/SO/aps/ap s.html [5.28] The Linux architecture http://se.uwaterloo.ca/~mnarmstr/report1/node7.html [5.29] QNX Process manager http://mazsola.iit.unimiskolc.hu/tempus/parallel/doc/drotos/rtos/procman/ [5.30] The Linux OS process management http://home.att.net/~ejuke/papers/tlos1.0/procmgt.ht m [5.31] Conceptual Architecture of the Linux Kernel. Ivan Bowman (ibowman@sybase.com) January 1998 http://plg.uwaterloo.ca/~itbowman/CS746G/a1/ [5.32] Concrete Architecture of the Linux Kernel. Ivan Bowman (ibowman@sybase.com), Saheem Siddiqi (s4siddiqi@neumann), Meyer C. Tanuan (mtanuan@descartes.com). Department of Computer Science, University of Waterloo. Winter 1998 http://plg.uwaterloo.ca/~itbowman/CS746G/a2 [5.33] Mecanismos para evitar el interbloqueo http://www.itver.edu.mx/so1/44.htm [5.39] An introduction to parallel computing http://www.pcc.qub.ac.uk/tec/courses/intro/ohp/introohp.html [5.40] What is multithreading? http://www.ece.gatech.edu/research/pica/compiler/mth read.htm [5.41] Introduction to Multithreading, Superthreading and Hyperthreading. Jon "Hannibal" Stokes http://www.arstechnica.com/paedia/h/hyperthreading/ hyperthreading-1.html [5.37] Remote procedure call http://www.ai.ldc.usb.ve/~figueira/Cursos/redes/resour ces/claseRPC.html [5.38] Message Passing Interface standard http://www-unix.mcs.anl.gov/mpi/ http://vysec.galeon.com/INTERB.HTML [5.35] Comunicación entre procesos http://www.ldc.usb.ve/~adiserio/ci3825/CLASEPS21.ht ml [5.36] Redirecciones y pipes http://highland.dit.upm.es:8000/UNIX/movs2/3redir.ht ml

182

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Capitulo 6. Administración de dispositivos, almacenamiento y comunicaciones.
Se debe hacer todo tan sencillo como sea posible, pero no más sencillo.
Albert Einstein

Las computadoras no servirían de mucho sin: a. Dispositivos Periféricos - Proporcionan interfaz al usuario. • Entrada: ratón, teclado, micrófono, cámara, scanner, etc. • Salida: impresoras, pantalla, altavoces, etc. b. Dispositivos de almacenamiento - Proporcionan almacenamiento no volátil de datos y memoria. • Secundario: discos y disquetes. • Terciario: cintas y sistemas de archivo. c. Dispositivos de comunicaciones - Permiten conectar con otras computadoras. • Los módems o tarjetas de interfaz de red. Los dispositivos que se conectan a una computadora varían en muchas formas: • • • • • transfieren un carácter o un bloque de caracteres a la vez; se puede acceder a ellos sólo secuencialmente, o de forma aleatoria; transfieren datos síncrona o asíncronamente; son dedicados o compartidos; pueden ser sólo de lectura o de lectura y escritura.

Además, los dispositivos varían mucho en cuanto a su velocidad. En muchos sentidos, estos dispositivos también son los más lentos de los componentes principales de la computadora. La misión y objetivos de los sistemas operativos en este contexto son: • Ofrecer una visión lógica simplificada de dispositivos de E/S: – Para otros componentes del SO: Ej. el sistema de archivos. – Para el usuario. • Objetivos: – Optimizar la E/S, implementando mecanismos para mejorar prestaciones. – Facilitar el manejo de los dispositivos periféricos. – Permitir conectar cualquier tipo de dispositivo físico sin remodelar el sistema operativo. – Permitir conectar dispositivos solventando automáticamente su instalación (plug & play).

183

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 6.1 Capas del sistema de entrada-salida
En este capítulo veremos cómo es que el sistema operativo puede soportar la integración de dispositivos adicionales en una computadora, y en específico se analizan los casos del almacenamiento secundario y la comunicación en redes.

6.1

Administración de dispositivos y periféricos⊕

En lugar de colocar código en cada aplicación que se desarrolla para controlar cada dispositivo, se comparte este código entre las aplicaciones. Para asegurarse de que el código no es comprometido, se protege de los usuarios y programas normales que lo usan. Si se hace de forma correcta, se tendrá la capacidad de agregar y quitar dispositivos al sistema sin cambiar las aplicaciones. Uno de los objetivos clave del subsistema de entrada/salida (E/S) de un sistema operativo es proporcionar la interfaz más sencilla posible al resto del sistema, y puesto que los dispositivos son un cuello de botella para el desempeño, es necesario optimizar la E/S de modo que la concurrencia sea máxima. El papel del sistema operativo en la E/S de una computadora es administrar y controlar las operaciones de E/S y los dispositivos de E/S.

Obras consultadas: [6.5] [6.6]

184

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

6.1.1 Dispositivos de Entrada - Salida
El control de los dispositivos conectados a la computadora es una preocupación importante de los diseñadores de sistemas operativos. Dada la amplia variación en la función y velocidad de los dispositivos de E/S (consideremos un ratón, un joystick, una cámara de video, una impresora, un disco duro y un jukebox de CD-ROM), se requieren diversos métodos para controlarlos. Estos métodos constituyen el subsistema de E/S del núcleo, que aísla el resto del núcleo de la complejidad de administrar los dispositivos de E/S. La tecnología de dispositivos de E/S exhibe dos tendencias que están en conflicto. Por un lado vemos una creciente estandarización de las interfases de software y hardware. Esta tendencia nos ayuda a incorporar generaciones de dispositivos mejorados a computadores y sistemas operativos existentes. Por otro lado, vemos una variedad cada vez más amplia de dispositivos de E/S. Algunos dispositivos nuevos son tan distintos de los anteriores que es un reto incorporarlos en nuestros computadores y sistemas operativos. Este reto se enfrenta con una combinación de técnicas de hardware y software. Los dispositivos de entrada-salida se dividen, en general, en dos tipos: • Los dispositivos orientados a bloques tienen la propiedad de que se pueden direccionar, esto es, el programador puede escribir o leer cualquier bloque del dispositivo realizando primero una operación de posicionamiento sobre el dispositivo. Los dispositivos más comunes orientados a bloques son los discos duros, la memoria, discos compactos y, posiblemente, unidades de cinta. • Los dispositivos orientados a caracteres son aquellos que trabajan con secuencias de bytes sin importar su longitud ni ninguna agrupación en especial. No son dispositivos direccionables. Ejemplos de estos dispositivos son el teclado, la pantalla o display y las impresoras. La clasificación anterior no es perfecta, porque existen varios dispositivos que generan entrada o salida que no pueden englobarse en esas categorías. Por ejemplo, un reloj que genera pulsos. Sin embargo, aunque existan algunos periféricos que no se puedan categorizar, todos están administrados por el sistema operativo por medio de una parte electrónica-mecánica y una parte de software.

6.1.2 Controladores de Dispositivos
Los controladores de dispositivos (también llamados adaptadores de dispositivos) son la parte electrónica de los periféricos, los cuales pueden tener la forma de una tarjeta o un circuito impreso integrado a la tarjeta maestra de la computadora. Por ejemplo, existen controladores de discos que se venden por separado y que se insertan en una ranura de la computadora, o existen fabricantes de computadoras que integran esa funcionalidad en la misma tarjeta en que viene el CPU (tarjeta madre). Los controladores de dispositivos generalmente trabajan con voltajes de 5 y 12 volts con el dispositivo propiamente, y con la computadora a través de interrupciones. Estas interrupciones viajan por el bus de la computadora y son recibidos por el CPU el cual a su vez pondrá en ejecución algún programa que sabrá qué hacer con esa señal. A ese programa se le llama manejador de dispositivo (device driver).

185

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Algunas veces el mismo controlador contiene un pequeño programa en una memoria de solo lectura o en memoria de acceso aleatorio no volátil y re-escribible que interactúa con el correspondiente manejador en la computadora. En la figura 6.1 se muestra un esquema simple de dispositivos orientados a bloques y otros a caracteres.

Figura 6.2 Arquitecturas de entrada-salida y disposiciones de los dispositivos conectados al bus27
Por ejemplo, la terminal (CRT) tiene un chip que se encarga de enviar cadenas de bits por medio de un cable serial que a su vez son recibidos por un controlador de puerto serial en la computadora. Este chip también se encarga de leer secuencias de bits que agrupa para su despliegue en la pantalla o para ejecutar algunas funciones de control. Lo importante en todos estos dispositivos es que se debe ejercer un mecanismo para sincronizar el envío y llegada de datos de manera concurrente.

Figura 6.3 Esquemas de E/S y su acceso mediante instrucciones en ensamblador28

27 28

Imagen reproducida de [6.26] Imagen reproducida de [6.26]

186

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Para intercambiar datos o señales entre la computadora y los controladores, muchas veces se usan registros o secciones predefinidas de la memoria de la computadora. A este esquema se le llama manejo de entrada-salida mapeado por memoria (memory mapped I/O). Por ejemplo, para una IBM PC se muestran los vectores de interrupción y las direcciones para la entrada-salida:
Controlador Reloj Teclado Disco Duro Impresora Monitor Mono Monitor Color Disco Flexible Dirección (Hex) 040 060 320 378 380 3D0 3F0 043 063 32F 37F 3BF 3DF 3F7 Vector de Interrupción 8 9 13 15 14

6.1.3 Manejadores de dispositivos (device drivers)⊕
Para realizar la administración de dispositivos, el sistema operativo debe ofrecer: • Manejadores de interrupciones El primer objetivo referente a los manejadores de interrupciones consiste en que el programador o el usuario no debe darse cuenta de los manejos de bajo nivel para los casos en que el dispositivo está ocupado y se debe suspender el proceso o sincronizar algunas tareas. Desde el punto de vista del proceso o usuario, el sistema simplemente se tardó más o menos en responder a su petición. Manejadores de dispositivos El sistema debe proveer los manejadores de dispositivos necesarios para los periféricos, así como ocultar las peculiaridades del manejo interno de cada uno de ellos, tales como el formato de la información, los medios mecánicos, los niveles de voltaje y otros. Por ejemplo, si el sistema tiene varios tipos diferentes de discos duros, para el usuario o programador las diferencias técnicas entre ellos no le deben importar, y los manejadores le deben ofrecer el mismo conjunto de rutinas para leer y escribir datos. Software independiente del dispositivo Este es un nivel superior de independencia que el ofrecido por los manejadores de dispositivos. Aquí el sistema operativo debe ser capaz, en lo más posible, de ofrecer un conjunto de utilerías para acceder periféricos o programarlos de una manera consistente. Por ejemplo, que para todos los dispositivos orientados a bloques se tenga una llamada para decidir si se desea usar buffers o no, o para posicionarse en ellos. Software para usuarios La mayoría de las rutinas de entrada-salida trabajan en modo privilegiado, o son llamadas al sistema que se ligan a los programas del usuario formando parte de sus aplicaciones y que no le dejan ninguna flexibilidad al usuario en cuanto a la apariencia de los datos. Existen otras librerías en donde el usuario si tiene poder de decisión (por ejemplo la llamada a printf() en el lenguaje C). Otra facilidad ofrecida son las áreas de trabajos en cola (spooling areas), tales como las de impresión y correo electrónico.

Obras consultadas: [6.7]

187

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Proceso de usuario

Aplicación S ubsistema o DLL

Modo usuario Modo núcleo

Copia en memoria del usuario

Servicios
SW de E/S independiente de dispositivo

Gestor de archivos Gestor de bloques Gestor de cache Manejador de dispositivo Manejador de interrupción
Copia en el controlador Copia en el sistema operativo

SW de E/S independiente de dispositivo SW de E/S dependiente de dispositivo

Software Hardware

Controlador

Dispositivo (disco)

Bloque del dispositivo

Figura 6.4 Capas del software de entrada-salida
Los elementos básicos de hardware de E/S, como puertos, buses y controladores de dispositivos, dan cabida a una amplia variedad de dispositivos de E/S. Para encapsular los detalles y peculiaridades de los diferentes dispositivos, el núcleo de un sistema operativo se estructura a modo de usar módulos manejadores de dispositivos en software (device drivers). Los manejadores presentan al subsistema de E/S una interfaz de acceso a dispositivos uniforme, así como las llamadas al sistema proporcionan una interfaz estándar entre la aplicación y el sistema operativo. Los manejadores de dispositivo son programas añadidos al núcleo del sistema operativo, concebidos inicialmente para gestionar periféricos y dispositivos especiales. Los controladores de dispositivo pueden ser de dos tipos: • • orientados a caracteres (tales como los dispositivos NUL, AUX, PRN, etc. del sistema) o bien orientados a bloques, constituyendo las conocidas unidades de disco.

La diferencia fundamental entre ambos tipos de controladores es que los primeros reciben o envían la información carácter a carácter; en cambio, los controladores de dispositivo de bloques procesan, como su propio nombre indica, bloques de cierta longitud en bytes (sectores).

188

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
Peticiones de E/S del dispositivo

Extraer petición E/S de la lista

Contestación a la petición

Traducir a formato del controlador

Preparar respuesta de error Si

Operaciones sobre datos No Error

Enviar mandatos al controlador Programación del controlador Bloqueo Si Esperar interrupción Interrupción No

Leer registros estado del controlador

Figura 6.5 Flujo de operaciones en un manejador de dispositivo.
Muchos sistemas operativos modernos tienen un método para instalar archivos especiales para hacer que el hardware funcione; aquí algunos casos: • En la Mac, por ejemplo, los manejadores para los dispositivos de hardware son archivos que se encuentran en la carpeta System Extensions. • • Linux también tiene archivos especiales que usa para controlar el hardware. En el JavaOS una colección de clases llamada JDI (Java Driver Interface) provee soporte para manejadores de dispositivo. Los manejadores acceden a los dispositivos indirectamente por medio de las clases de la plataforma que abstraen las interrupciones, direccionamiento y administración de memoria del dispositivo de hardware. Puesto que los manejadores están protegidos del contacto directo con el hardware, la integridad del sistema operativo y errores de procesamiento se minimiza.

Para implementar manejadores de dispositivos hace falta: – Manipular registros de hardware y direcciones » un registro se puede representar como una variable o como un canal de comunicación – Enlazar interrupciones con código. Algunas posibilidades son: » Llamada a procedimiento » Activación de proceso esporádico » Suceso asíncrono » Sincronización con variable de condición » Mensaje

189

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

En el caso de usar C hay que programar en un nivel de abstracción bajo: – el manejador es un procedimiento sin parámetros – su dirección se copia al vector de interrupciones – hay que programar directamente la comunicación y sincronización con el resto del programa cuando termina el manejador de interrupción

6.1.4 Acceso Directo a Memoria
El acceso directo a memoria (Direct Memory Access - DMA) se creó con el propósito de liberar al CPU de la carga de atender a algunos controladores de dispositivos. Para comprender su funcionamiento vale la pena revisar cómo trabaja un controlador sin DMA. En el caso de un dispositivo orientado a bloques, cuando un proceso requiere algunos bloques de un dispositivo, se envía una señal al controlador con la dirección del bloque deseado. El controlador lo recibe a través del bus y el proceso puede estar esperando la respuesta (trabajo síncrono) o puede estar haciendo otra cosa (trabajo asíncrono). El controlador recibe la señal y lee la dirección del bus. Envía a su vez una o varias señales al dispositivo mecánico (si es que lo hay) y espera los datos. Cuando los recibe los escribe en un buffer local y envía una señal al CPU indicándole que los datos están listos. El CPU recibe esta interrupción y comienza a leer byte por byte o palabra por palabra los datos del buffer del controlador (a través del manejador de dispositivo) hasta terminar la operación.

Figura 6.6 Flujos de E/S por el DMA
Como se ve, el CPU gasta varios ciclos en leer los datos deseados. El DMA soluciona ese problema de la siguiente forma. Cuando un proceso requiere uno o varios bloques de datos, el

190

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

CPU envía al controlador la petición junto con el número de bytes deseados y la dirección de en dónde quiere que se almacenen de regreso. El DMA actuará como un "CPU secundario" en cuanto a que tiene el poder de tomar el control del bus e indicarle al verdadero CPU que espere. Cuando el controlador tiene listos los datos, el DMA "escucha" si el bus está libre aprovechando esos ciclos para ir leyendo los datos del buffer del controlador e ir escribiéndolos en el área de memoria que el CPU le indicó. Cuando todos los datos fueron escritos, se le envía una interrupción al CPU para que use los datos. El ahorro con el DMA es que el CPU ya no es interrumpido (aunque sí puede ser retardado por el DMA) salvando así el cambio de contexto y además el DMA aprovechará aquellos ciclos en que el bus no fue usado por el CPU. El hecho de que los controladores necesiten buffers internos se debe a que conforme ellos reciben datos de los dispositivos que controlan, los deben poder almacenar temporalmente, ya que el CPU no está listo en todo momento para leerlos.

6.1.5 Caso de estudio: Manejo de dispositivos en UNIX⊕
La abstracción que ofrece UNIX de los dispositivos físicos conectados a la computadora es la de un archivo especial de dispositivo. Los archivos especiales de dispositivo suelen localizarse en el directorio /dev, aunque esto no es obligatorio. En los dispositivos simples, como los puertos serie, terminales, teclados, etc., la interacción se limita a menudo a abrir el archivo con la llamada open(), para lectura o escritura y volcar o leer los datos que queremos transmitir o recibir, mediante las llamadas read() y write(). En muchos dispositivos, sobre todo en los más sofisticados, como tarjetas de sonido, escáners, tarjetas de video, etc., es necesario interactuar de forma más específica con el hardware. Para ello se recurre a la llamada ioctl(), que permite modificar los parámetros del dispositivo (como velocidad, paridad, bits de stop, etc. del puerto serie; bits por muestra o frecuencia de muestreo en una tarjeta de sonido, etc.), así como instruir al periférico para que realice accesos directos a memoria u otras operaciones específicas. Los archivos especiales (en UNIX hay tres tipos de archivo: archivos normales o "regulares", archivos especiales y directorios) ocultan una funcionalidad especial bajo la apariencia de archivos convencionales, con su ruta de acceso, sus atributos, etc. Distinguimos dos tipos de archivos especiales de dispositivo: • Dispositivos de bloques: Son aquéllos que pueden direccionarse por bloques, es decir que proporcionan acceso aleatorio a sectores, típicamente los discos de todo tipo. • Dispositivos de caracteres: Son los que admiten operaciones secuenciales carácter a carácter y/o pueden direccionarse a nivel de bytes. De hecho, estos archivos no contienen información ni ocupan espacio si los duplicamos. Los únicos datos útiles que contienen son el major number y el minor number, que identifican unívocamente el dispositivo que representan. • El major number indica el tipo de dispositivo (p.ej. 3 es un disco del primer IDE, 22 uno del segundo IDE, 2 es un disco flexible, etc.)

Obras consultadas: [6.11]

191

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

El minor number indica un número de orden dentro de los dispositivos de cada tipo (p.ej., entre los discos de un IDE, el 0 es el primer disco, el 64 el segundo, el 1 es la primera partición del primer disco, el 2 la segunda, etc.).

Para crear un archivo especial de dispositivo se usa la orden mknod(), que recibe un nombre de archivo, un tipo (bloques o caracteres), un major y un minor number. • • • • • • • • • • /dev/fd0: Primer floppy. /dev/hda: Disco master del primer IDE. /dev/hdd3: Tercera partición del disco slave del segundo IDE. (Las particiones primarias van de la 1 a la 4 y las lógicas de la 5 a la 20.) /dev/sda2: Segunda partición del primer disco SCSI. /dev/scd0: Primer CD-ROM SCSI. (Los CD-ROM IDE se ven como discos magnéticos.) /dev/st0: Primera unidad de cinta SCSI. /dev/tty2: Tercera consola. /dev/ttyS0: Primer puerto serie. /dev/ptyp5: Sexta pseudoterminal maestra. /dev/ttyp5: Sexta pseudoterminal esclava (el proceso que crea la terminal abre la maestra y el que la va a usar abre la esclava).

Otros dispositivos físicos: • • • • • • • • • • • /dev/lp0: Primer puerto paralelo. /dev/parport0: Primer puerto paralelo a nivel binario. /dev/psaux: Puerto de ratón PS/2. /dev/sg2: Tercer dispositivo genérico SCSI (escáner, p.ej.). /dev/dsp0: Primera entrada y salida de audio digital. /dev/mixer1: Segundo mezclador de audio (tarjeta de sonido). /dev/midi3: Cuarto puerto MIDI (instrumentos musicales). /dev/video0: Primera tarjeta de captura de vídeo. /dev/radio1: Segunda tarjeta de radio. /dev/md1: Segundo "metadisco" (RAID). /dev/ppp: Dispositivo virtual para ppp.

Dispositivos virtuales: • /dev/loop0: Primer archivo "loopback". Se asocia un archivo normal para poder montarlo como un dispositivo de bloques. • • • • • • • • • /dev/mem: Permite acceder a la memoria física. /dev/kmem: Permite acceder a la memoria virtual del núcleo. /dev/null: Como un agujero negro que se lo "traga" todo. /dev/port: Permite acceder a los puertos de E/S. /dev/zero: Suministra incansablemente caracteres "\0". /dev/full: Devuelve error de dispositivo lleno. /dev/random: Da auténticos números aleatorios de un pozo de entropía. /dev/urandom: Devuelve siempre números (pseudo)aleatorios. /dev/stdin: Entrada estándar del proceso en curso.

192

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• •

/dev/stdout: Salida estándar del proceso en curso. /dev/stderr: Salida estándar de error del proceso en curso.

Las rutinas para acceder a los puertos de E/S residen en include/asm-i386/io.h y son macros, de modo que basta con incluir el archivo para poder usarlas, sin necesidad de enlazar con librería alguna. Debido a una peculiaridad del compilador gcc, la optimización debe estar activada cuando se usan estas funciones. Para acceder a los puertos desde un programa C fuera del núcleo, hay que ser súper usuario y, además, requerir del sistema operativo el permiso para hacerlo. Para ello se dispone de la función ioperm() o iopl(). Desde dentro del núcleo (o de un módulo, que es lo mismo), no hace falta llamar a estas funciones. La E/S se realiza a través de la función inb(port), que devuelve el valor (de 8 bits) al que se encuentra el puerto correspondiente, y de la función outb(valor,puerto), que envía un valor de 8 bits sobre un puerto. Debe ponerse atención al orden de los parámetros, pues es distinto al adoptado por algunos compiladores comunes en el mundo de DOS y Windows. Desde el núcleo, el acceso a los puertos de E/S está regulado mediante un mecanismo de reserva de rangos de direcciones. Esto permite que los manejadores sepan si un rango de puertos está siendo utilizado por otros manejadores. Para ello se dispone de tres funciones que debemos emplear para no colisionar con otros manejadores. • int check_region (unsigned int port, unsigned int range) : Comprueba si un rango de range puertos a partir de port están siendo utilizadas por otro módulo, devolviendo un valor negativo si es así. void request_region (unsigned int port, unsigned int range, const char *name) : Reserva un rango de range puertos a partir de port, identificándolo con name. void release_region (unsigned int port, unsigned int range) : Libera un rango de range puertos a partir de port, reservados anteriormente.

• •

Se puede saber en un momento dado cuáles son los rangos de puertos reservados por los diferentes manejadores que se han instalados en el sistema visualizando el archivo /proc/ioports.

6.2

Administración de archivos
Superando las limitaciones del almacenamiento real. Trascendiendo a la duración de los procesos que las utilizan o generan. Independizando a la información de los procesos permitiendo el acceso a la misma a través de varios procesos.

Todas las aplicaciones computarizadas necesitan almacenar y recuperar la información: • • •

En un sistema de cómputo es evidente que existe la necesidad por parte de los usuarios y aplicaciones de almacenar datos en algún medio, a veces por periodos largos y a veces por instantes. Cada aplicación y cada usuario debe tener ciertos derechos con sus datos, como son el poder crearlos y borrarlos, o cambiarlos de lugar; así como tener privacidad contra otros usuarios

193

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

o aplicaciones. El subsistema de archivos del sistema operativo se debe encargar de estos detalles, además de establecer el formato físico en el cual almacenará los datos en discos duros, cintas o discos flexibles.

6.2.1 Medios de almacenamiento
A diferencia de la RAM, que olvida todo en cuanto se apaga la puede aprender nada nuevo, los dispositivos de almacenamiento computadora registre información en forma semi-permanente, para por el mismo u otro computador. El almacenamiento secundario capacidad que el almacenamiento primario. máquina, y la ROM, que no secundario permiten que la que pueda ser leída después es más barato y de mayor

El almacenamiento secundario es un medio de almacenamiento definitivo (no volátil como el de la memoria RAM). El proceso de transferencia de datos a un equipo de cómputo se le llama procedimiento de lectura. El proceso de transferencia de datos desde la computadora hacia el almacenamiento se denomina procedimiento de escritura. En la actualidad se pueden usar principalmente dos tecnologías para almacenar información: • El almacenamiento Magnético. 1. Discos Flexibles 2. Discos Duros 3. Cintas Magnéticas o Cartuchos. 2. El almacenamiento Óptico. La necesidad de mayores capacidades de almacenamiento han llevado a los fabricantes de hardware a una búsqueda continua de medios de almacenamiento alternativos y cuando no hay opciones, a mejorar tecnologías disponibles y desarrollar nuevas. Las técnicas de almacenamiento óptico hacen posible el uso de la localización precisa mediante rayos láser. Leer información de un medio óptico es una tarea relativamente fácil, escribirla es otro asunto. El problema es la dificultad para modificar la superficie de un medio óptico, ya que los medios ópticos perforan físicamente la superficie para reflejar o dispersar la luz del láser. Los principales dispositivos de almacenamiento óptico son: 1. CD ROM.- CD Read Only Memory 2. WORM.- Write Once, Read Many

Algunos dispositivos combinan ambas tecnologías. • Medios Magnético - Ópticos. Estos medios combinan algunas de las mejores características de las tecnologías de grabación magnética y óptica. Un disco MO tiene la capacidad de un disco óptico, pero puede ser re-grabable con la facilidad de un disco magnético. Actualmente están disponibles en varios tamaños y capacidades.

Debe ser conocido por todos que tradicionalmente la información en los sistemas modernos se almacena en discos duros, flexibles y unidades de disco óptico, y en todos ellos se comparten algunos esquemas básicos para darles formato físico: • Las superficies de almacenamiento son divididas en círculos concéntricos llamados "pistas" y cada pista se divide en "sectores".

194

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

A la unión lógica de varias pistas a través de varias superficies "paralelas" de almacenamiento se les llama "cilindros", los cuales son inspeccionados al momento de lectura o escritura de datos por las respectivas unidades físicas llamadas "cabezas". Las superficies de almacenamiento reciben el nombre de "platos" y generalmente están en movimiento rotatorio para que las cabezas accedan a las pistas que los componen. Los datos se escriben a través de los sectores en las pistas y cilindros modificando las superficies por medio de las cabezas. Para poder acceder a estos dispositivos es necesario contar con manejadores específicos.

6.2.2 Manejador de discos
Un disco o partición puede accederse por medio de dos interfaces: • • Manejador de dispositivo de bloques. Todos los accesos pasan por la caché de bloques. Manejador de dispositivo de caracteres. Acceso directo a bloques, sin pasar por caché. Las peticiones deben ser múltiplo del tamaño de bloque.

Planificador

Manejador de CD_ROM

Manejador de disco Manejador Manejador IDE SCSI

Manejador de floppy

Figura 6.7 Estructura de un manejador de discos.
Las funciones principales de un manejador de disco son: • • • • • • • • Proceso de cada petición de E/S en bloques. Traducción del formato lógico a mandatos del controlador. Insertar la petición en la cola del dispositivo, llevando a cabo la política de planificación de disco pertinente (FIFO, SJF, SCAN, CSCAN, EDF, etc.). Enviar los mandatos al controlador, programando la DMA. Bloqueo en espera de la interrupción de E/S. Comprobación del estado de la operación cuando llega la interrupción. Gestionar los errores, si existen, y resolverlos si es posible. Indicación del estado de terminación al nivel superior del sistema de E/S.

195

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

6.2.3 Archivos
La unidad lógica de almacenamiento para la información son los archivos. Estos son mapeados por el SO en los dispositivos físicos. En general son tratados como una secuencia de bits, bytes o registros (el significado lo da el creador del archivo).
Un archivo es un repositorio persistente de información, que puede ser leído o escrito por los procesos de usuario. Los archivos son identificados por nombres. En sistemas antiguos, el nombre del archivo estaba estructurado con un nombre (8 caracteres por lo regular) y una extensión (que identifica el formato del archivo). Los sistemas actuales permiten que el nombre contenga (casi) cualquier número de caracteres. La información de todos los archivos se guarda en una estructura de directorios que reside en el dispositivo de almacenamiento secundario junto con los archivos. Los directorios permiten al usuario administrar grupos de archivos de una forma jerárquica. Todos los archivos poseen un nombre, su localización y datos. Además pueden tener algunos o todos los siguientes atributos asociados: • • • • • • • • • identificador del dueño identificador del grupo bits de protección tiempo de creación tiempo de la última modificación tiempo de último acceso tiempo del último respaldo tamaño actual Banderas: • ASCII/Binario • escondido • • sistema solo lectura

La interfaz que el SO provee para el sistema de archivos contiene, entre otras cosas, las operaciones para manipular archivos (creación, apertura, escritura o truncamiento de archivos). Muchas de estas operaciones con archivos implican la búsqueda de algún atributo asociado con los archivos en la estructura de directorios. Puesto que buscar la referencia de un archivo para cada operación realizada en él puede ser costoso, el SO mantiene una pequeña tabla que contiene información sobre los archivos abiertos (la tabla de archivos abiertos). Cuando se requiere una operación, un índice en esta tabla de archivos se usa para obtener el resultado adecuado. Cuando el archivo ya no se está usando, se cierra por el proceso y el SO quita sus datos de la tabla de archivos abiertos.

196

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.
Cada proceso también mantiene una tabla de todos los archivos que ha abierto. Esta almacena la información sobre como el (los) archivo(s) están siendo usados, p.ej., la localización actual del apuntador al archivo. Cada elemento de esta tabla apunta al elemento correspondiente de la tabla de archivos abiertos.

6.2.4 El sistema de archivos⊕
El Sistema de Archivos es la parte del sistema de administración del almacenamiento responsable, principalmente, de la administración de los archivos del almacenamiento secundario.
Interfaz de llamadas al sistema Sistema de ficheros virtual Sistema de ficheros Caché de páginas de memoria Controlador del dispositivo [alto nivel] Caché de bloques

Gestor de peticiones a los discos Planificador de los discos Controlador de dispositivos [bajo nivel]

S istem a de Almac enamiento S undario ec

Figura 6.9 Esquema del sistema de almacenamiento secundario

Obras consultadas: [6.3]

197

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Un sistema de archivos provee el mecanismo para almacenamiento en línea y acceso a la información perteneciente al SO y sus usuarios. Algunas de las principales funciones de este sistema son: • • • Los usuarios deben poder crear, modificar y borrar archivos. Se deben poder compartir los archivos de una manera cuidadosamente controlada. El mecanismo encargado de compartir los archivos debe proporcionar varios tipos de acceso controlado: • Ej.: “Acceso de Lectura”, “Acceso de Escritura”, “Acceso de Ejecución”, varias combinaciones de estos, etc. Se debe poder estructurar los archivos de la manera más apropiada a cada aplicación. Los usuarios deben poder ordenar la transferencia de información entre archivos. Se deben proporcionar posibilidades de “respaldo” y “recuperación” para prevenirse contra: • La pérdida accidental de información. • La destrucción maliciosa de información. Se debe poder referenciar a los archivos mediante “Nombres Simbólicos”, brindando Independencia de Dispositivos. En ambientes sensibles, el sistema de archivos debe proporcionar posibilidades de Cifrado y

• • •

• • •

Descifrado.
El sistema de archivos debe brindar una interfaz favorable al usuario: • Debe suministrar una visión lógica de los datos y de las funciones que serán ejecutadas, en vez de una visión física. • El usuario no debe tener que preocuparse por: • • • • Los dispositivos particulares. Dónde serán almacenados los datos. El formato de los datos en los dispositivos. Los medios físicos de la transferencia de datos hacia y desde los dispositivos

198

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 6.10 Esquema del sistema de almacenamiento terciario

Representación de archivos y estructura del sistema de archivos
Los archivos se pueden estructurar de varias maneras, las más comunes son: •

Secuencia de bytes:
• • El archivo es una serie no estructurada de bytes. Posee máxima flexibilidad. El archivo es una secuencia de registros de longitud fija, cada uno con su propia estructura interna. El archivo consta de un árbol de registros, no necesariamente de la misma longitud. Cada registro tiene un campo llave o clave en una posición fija del registro. El árbol se ordena mediante el campo de clave para permitir una rápida búsqueda de una clave particular.

Secuencia de registros:

Árbol :
• • •

Muchos sistemas operativos soportan varios tipos de archivos, por ejemplo: • Archivos regulares. Son aquellos que contiene información del usuario •- Archivos en ASCII: constan de líneas de texto

199

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

•- Binarios: ejecutables, imágenes, etc.., los ejecutables tienen cinco secciones: encabezado, texto, datos, bits de reasignación y tabla símbolos

Figura 6.11 Formato de un archivo ejecutable
• Directorios. Son archivos del sistema para el mantenimiento de una estructura del sistema de archivos

Figura 6.12 Organización de archivos con directorios29

29

Imagen reproducida de [6.25]

200

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• •

Archivos especiales de caracteres. Están relacionados con entrada salida y se utilizan para modelar dispositivos seriales de E/S tales como terminales, impresoras y redes. Archivos especiales de bloques. Se utilizan para modelar discos.

La información relacionada con el archivo se mantiene en el descriptor del archivo, al que se apunta desde los directorios. La representación es distinta en cada sistema operativo: nodoi, registro Windows, etc.

Nombre Atrib. Size KB Agrup. FAT

cabecera Atributos Tamaño Nombre Seguridad

Datos

Vclusters

Figura 6.13 Representaciones de archivos en UNIX, MS-DOS y Windows NT
Adicionalmente deben definirse las unidades que maneja el sistema de archivos para operar: • Bloque: agrupación lógica de sectores de disco y es la unidad de transferencia mínima que usa el sistema de archivos. Optimizar la eficiencia de la entrada/salida de los dispositivos secundarios de almacenamiento. Todos los sistemas operativos proporcionan un tamaño de bloque por defecto. Por ejemplo en UNIX, los usuarios pueden definir el tamaño de bloque a usar dentro de un sistema de archivos mediante el mandato mkfs. Agrupación: conjunto de bloques que se gestionan como una unidad lógica de gestión del almacenamiento. El problema que introducen las agrupaciones, y los bloques grandes, es la existencia de fragmentación interna.

El sistema de archivos es un conjunto coherente de meta-información y datos. Permite organizar la información dentro de los dispositivos de almacenamiento secundario en un formato inteligible para el sistema operativo. Previamente a la instalación del sistema de archivos es necesario dividir físicamente, o lógicamente, los discos en particiones o volúmenes. Una partición es una porción de un disco a la que se la dota de una identidad propia y que puede ser manipulada por el sistema operativo como una entidad lógica independiente. Una

201

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

vez creadas las particiones, el sistema operativo debe crear las estructuras de los sistemas de archivos dentro de esas particiones.

Figura 6.14 Ejemplos de estructuras en sistemas operativos como UNIX, MS-DOS y Windows.

Operaciones soportadas por el sistema de archivos
El Sistema de Archivos es un componente importante de un SO y suele contener: • • • •

Métodos de acceso relacionados con la manera de acceder a los datos almacenados en
archivos.

Administración de archivos referida a la provisión de mecanismos para que los archivos
sean almacenados, referenciados, compartidos y asegurados.

Administración del almacenamiento auxiliar para la asignación de espacio a los archivos
en los dispositivos de almacenamiento secundario.

Integridad del archivo para garantizar la integridad de la información del archivo.

El sistema de archivos está relacionado especialmente con la administración del espacio de almacenamiento secundario, fundamentalmente con el almacenamiento de disco. Independientemente de los algoritmos de asignación de espacio, de los métodos de acceso y de la forma de resolver las peticiones de lectura y escritura, el sistema de archivos debe proveer un conjunto de llamadas al sistema para operar con los datos y de proveer mecanismos de protección y seguridad. Las operaciones básicas que la mayoría de los sistemas de archivos soportan son: a. Operaciones para la manipulación de archivos:

202

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• • • •

Crear ( create ) : Permite crear un archivo sin datos, con el propósito de indicar que ese nombre ya está usado y se deben crear las estructuras básicas para soportarlo. Borrar ( delete ): Eliminar el archivo y liberar los bloques para su uso posterior. Abrir ( open ): Antes de usar un archivo se debe abrir para que el sistema conozca sus atributos, tales como el dueño, la fecha de modificación, etc. Cerrar ( close ): Después de realizar todas las operaciones deseadas, el archivo debe cerrarse para asegurar su integridad y para liberar recursos de su control en la memoria.

b. Operaciones para manipular el contenido de los archivos: • Leer o Escribir ( read, write ): Añadir información al archivo o leer el caracter o una cadena de caracteres a partir de la posición actual. • Agregar ( append ): Es una forma restringida de la llamada `write', en la cual sólo se permite añadir información al final del archivo. • Localizar (seek): Para los archivos de acceso directo se permite posicionar el apuntador de lectura o escritura en un registro aleatorio, a veces a partir del inicio o final del archivo. • Leer atributos: Permite obtener una estructura con todos los atributos del archivo especificado, tales como permisos de escritura, de borrado, ejecución, etc. • Poner atributos: Permite cambiar los atributos de un archivo, por ejemplo en UNIX, donde todos los dispositivos se manejan como si fueran archivos, es posible cambiar el comportamiento de una terminal con una de estas llamadas. • Renombrar (rename): Permite cambiarle el nombre e incluso a veces la posición en la organización de directorios del archivo especificado. Los subsistemas de archivos también proveen un conjunto de llamadas para operar sobre directorios, las más comunes son crear, borrar, abrir, cerrar, renombrar y leer. Sus funcionalidades son obvias, pero existen también otras dos operaciones no tan comunes que son la de “crear una liga” y la de “destruir la liga”. La operación de crear una liga sirve para que desde diferentes puntos de la organización de directorios se pueda acceder un mismo directorio sin necesidad de copiarlo o duplicarlo. La llamada a "destruir la liga" lo que hace es eliminar esas referencias, siendo su efecto la de eliminar las ligas y no el directorio real. El directorio real es eliminado hasta que la llamada a "destruir liga" se realiza sobre él.

203

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 6.15 Esquema de la aplicación de operaciones de acceso y manipulación en un archivo Asignación del espacio de almacenamiento
El sistema de archivos se debe encargar de localizar espacio libre en los medios de almacenamiento para guardar archivos y para después borrarlos, renombrarlos o agrandarlos. Para ello se vale de localidades especiales que contienen la lista de archivos creados y por cada archivo una serie de direcciones que contienen los datos de los mismos. Esas localidades especiales se llaman directorios. Para asignarle espacio a los archivos existen tres criterios generales que se describen enseguida. • Asignación contigua: Cada directorio contiene la los nombres de archivos y la dirección del bloque inicial de cada archivo, así como el tamaño total de los mismos. Por ejemplo, si un archivo comienza en el sector 17 y mide 10 bloques, cuando el archivo sea accedido, el brazo se moverá inicialmente al bloque 17 y de ahí hasta el 27. Si el archivo es borrado y luego creado otro más pequeño, quedarán huecos inútiles entre archivos útiles, lo cual se llama fragmentación externa. Asignación encadenada: Con este criterio los directorios contienen los nombres de archivos y por cada uno de ellos la dirección del bloque inicial que compone al archivo. Cuando un archivo es leído, el brazo va a esa dirección inicial y encuentra los datos iniciales junto con la dirección del siguiente bloque y así sucesivamente. Con este criterio no es necesario que los bloques estén contiguos y no existe la fragmentación externa, pero en cada "eslabón" de la cadena se desperdicia espacio con las direcciones mismas. En otras palabras, lo que se crea en el disco es una lista ligada. Asignación con índices (indexada): En este esquema se guarda en el directorio un bloque de índices para cada archivo, con apuntadores hacia todos sus bloques constituyentes, de manera que el acceso directo se agiliza notablemente, a cambio de sacrificar varios bloques para almacenar dichos apuntadores. Cuando se quiere leer un archivo o cualquiera de sus partes, se hacen dos accesos: uno al bloque de índices y

204

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

otro a la dirección deseada. Este es un esquema excelente para archivos grandes pero no para pequeños, porque la relación entre bloques destinados para índices respecto a los asignados para datos es incosteable..

Métodos de acceso en los sistemas de archivos
Los métodos de acceso se refieren a las capacidades que el subsistema de archivos provee para acceder datos dentro de los directorios y medios de almacenamiento en general. Se ubican tres formas generales: acceso secuencial, acceso directo y acceso directo indexado. • Acceso secuencial: Es el método más lento y consiste en recorrer los componentes de un archivo uno en uno hasta llegar al registro deseado. Se necesita que el orden lógico de los registros sea igual al orden físico en el medio de almacenamiento. Este tipo de acceso se usa comúnmente en cintas y cartuchos. Acceso directo: Permite acceder cualquier sector o registro inmediatamente, por medio de llamadas al sistema como la de seek. Este tipo de acceso es rápido y se usa comúnmente en discos duros y discos o archivos manejados en memoria de acceso aleatorio. Acceso directo indexado: Este tipo de acceso es útil para grandes volúmenes de información o datos. Consiste en que cada archivo tiene una tabla de apuntadores, donde cada apuntador va a la dirección de un bloque de índices, lo cual permite que el archivo se expanda a través de un espacio enorme. Consume una cantidad importante de recursos en las tablas de índices pero es muy rápido.

Algoritmos de planificación de lectura y escritura
Los algoritmos de planificación de peticiones de lectura y escritura a discos se encargan de registrar dichas peticiones y de responderlas en un tiempo razonable. Los algoritmos más comunes para esta tarea son: • Primero en llegar, primero en ser servido (FIFO): Las peticiones son encoladas de acuerdo al orden en que llegaron y de esa misma forma se van leyendo o escribiendo las mismas. La ventaja de este algoritmo es su simplicidad y no causa sobrecarga, su desventaja principal es que no aprovecha para nada ninguna característica de las peticiones, de manera que es muy factible que el brazo del disco se mueva muy ineficientemente, ya que las peticiones pueden tener direcciones en el disco unas muy alejadas de otras. Por ejemplo, si se están haciendo peticiones a los sectores 6,10,8,21 y 4, las mismas serán resueltas en el mismo orden. _ Primero el más cercano a la posición actual: En este algoritmo las peticiones se ordenan de acuerdo a la posición actual de la cabeza lectora, sirviendo primero a aquellas peticiones más cercanas y reduciendo, así, el movimiento del brazo, lo cual constituye la ventaja principal de este algoritmo. Su desventaja consiste en que puede haber solicitudes que se queden esperando para siempre, en el infortunado caso de que existan peticiones muy alejadas y en todo momento estén entrando peticiones que estén más cercanas. Para las peticiones 6,10,8,21 y 4, las mismas serán resueltas en el orden 4,6,8,10 y 21.

205

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Por exploración (algoritmo del elevador): En este algoritmo el brazo se estará moviendo en todo momento desde el perímetro del disco hacia su centro y viceversa, resolviendo las peticiones que existan en la dirección que tenga en turno. En este caso las peticiones 6,10,8,21 y 4 serán resueltas en el orden 6,10,21,8 y 4; es decir, la posición actual es 6 y como va hacia los sectores de mayor numeración (hacia el centro, por ejemplo), en el camino sigue el sector 10, luego el 21 y ese fue el más central, así que ahora el brazo resolverá las peticiones en su camino hacia afuera y la primera que se encuentra es la del sector 8 y luego la 4. La ventaja de este algoritmo es que el brazo se moverá mucho menos que en FIFO y evita la espera indefinida; su desventaja es que no es justo, ya que no sirve las peticiones en el orden en que llegaron, además de que las peticiones en los extremos interior y exterior tendrán un tiempo de respuesta un poco mayor. Por exploración circular: Es una variación del algoritmo anterior, con la única diferencia que al llegar a la parte central, el brazo regresa al exterior sin resolver ninguna petición, lo cual proveerá un tiempo de respuesta más cercana al promedio para todas las peticiones, sin importar si están cercas del centro o del exterior.

Tolerancia a fallas
Al sistema de E/S se le exige máxima fiabilidad, ya a que no se desea perder los datos y programas que almacena. Algunas técnicas para proporcionar fiabilidad son: Códigos correctores de error (Ej. en los sectores de disco). Operaciones fiables: cuya corrección se puede verificar. Se implementan con técnicas de almacenamiento estable. • Redundancia de datos: sólo los críticos o de todos. Se implementan técnicas de (o se usan) dispositivos RAID (Redundant Array of Inexpensive Disks). • Redundancia hardware: Ej. Windows NT permite conectar un disco a dos controladores a la vez. • •

El concepto de sistema virtual de archivos
El Sistema Virtual de Archivos (VFS - virtual file system) es una capa que maneja las llamadas del sistema orientadas a los archivos y llama a las funciones necesarias en el código del sistema de archivos físico para realizar la E/S. Este mecanismo de es usado frecuentemente en sistemas operativos del tipo UNIX para hacer más fácil la integración y uso de varios tipos de sistemas de archivos. Cuando un proceso realiza una llamada al sistema orientada a los archivos, el kernel llama una función contenida en el VFS. Esta función se encarga de las manipulaciones de la estructura independiente y redirecciona la llamada a una función del sistema físico indicado, que es responsable de manejar las operaciones del sistema dependiente. El código del sistema de archivos usa las funciones de caché para las peticiones de E/S de los dispositivos.

206

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

El VFS define un conjunto de funciones que cada sistema de archivos debe implementar. Esta interfaz esta formada por un conjunto de operaciones asociadas a tres tipos de objetos: filesystems, inodes, y open files. El VFS tiene conocimiento de los sistemas de archivos soportados por el kernel, para lo que usa una tabla definida durante la configuración del kernel. Cada elemento de la tabla describe un tipo de sistema de archivos: contiene el nombre del tipo de sistema de archivos y un apuntador a la función llamada durante la operación de montaje (del dispositivo de almacenamiento). Cuando un sistema de archivos va a ser montado, la función apropiada de montaje es llamada. Esta función es responsable de leer el superbloque del disco, inicializar sus variables internas, y regresar un descriptor del sistema de archivos montado al VFS. Después de que el sistema de archivos es montado, las funciones del el VFS pueden usar este descriptor para acceder a las rutinas del sistema de archivos físico. El descriptor del sistema de archivos montado contiene varios tipos de datos: información que es común a todos los sistemas de archivos, apuntadores a las funciones provistas por el código del sistema de archivos físico, y datos privados mantenidos por el sistema de archivos físico. Los apuntadores a funciones están contenidos en los descriptores del sistema de archivos, permitiendo que el VFS accese a las rutinas internas del sistema de archivos. Adicionalmente el VFS usa otros 2 tipos de descriptores: descriptor de inode y un descriptor de archivo abierto. Cada descriptor contiene información relacionada a los archivos en uso y a un conjunto de operaciones provistas por el sistema de archivos físico. Mientras el descriptor de inode contiene apuntadores a funciones que pueden usarse para actuar en cualquier archivo (p.ej. create, unlink), los descriptores de archivo contienen apuntadores a funciones que solo pueden actuar en archivos abiertos (p.ej. read, write).

6.2.5 Nuevos enfoques en el manejo de archivos⊕
Lo hasta aquí expuesto referente al sistema de archivos esta evolucionando y nuevos sistemas operativos proponen nuevos enfoques en este sentido. El sistema operativo de los laboratorios AT&T Bell, Plan 9, establece varios principios interesantes en relación al manejo de archivos. El primero es que todos los objetos del sistema son archivos o sistemas de archivos. Todo con lo que un programa puede comunicarse, se ajusta a esta abstracción. En Plan 9, toda la comunicación con archivos está expresada por un protocolo que puede ser transmitido, por lo que todo puede convertirse en un sistema remoto de archivos (por lo que no importaría saber el lugar donde reside un archivo particular). Plan 9 también implementa algunas ideas de manejo de espacios de nombres (conjuntos de objetos visibles a un programa), haciéndolo dinámico e individualmente ajustable. Esta idea tiene varios efectos interesantes, sobre todo por significar que el conjunto de archivos que puede ver el SO puede ser ajustado para cada proceso, por lo que los programas de aplicación no necesitan saber donde se están ejecutando, lo cual es una decisión que no afecta la construcción de la aplicación en sí.

Obras consultadas: [6.4] [6.21]

207

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

En el caso de Off++ se propone una abstracción llamada caja (box), que se define como un recipiente siempre abierto que contiene datos. Los recursos del sistema que pueden ir desde aplicaciones enteras hasta variables definidas por el usuario pueden representarse mediante cajas. Las operaciones que aplican a estas estructuras son: copy(otherBox,aBox) , la cual copia una caja en otra (suponiendo que ambas cajas sean de tipos compatibles) share(otherBox,aBox) , la cual hace a una caja convertirse lógicamente en otra (en el caso de que sean de tipos compatibles) select(aBox,aSelector)->innerBox, la cual regresa una referencia de una caja dentro de otra. El objetivo de las cajas es proveer una abstracción y mecanismos para expresar relaciones y dependencias en un ambiente distribuido.

6.2.6 Caso de estudio: Sistema de archivos y control de dispositivos en Linux
Linux está diseñado para soportar una gran variedad de dispositivos físicos. Además Linux soporta varios sistemas lógicos de archivos, por lo que puede interoperar fácilmente con otros sistemas operativos. El sistema de archivos tiene los siguientes objetivos: • • • • • • • Proveer acceso a diversos tipos de dispositivos de hardware Soportar diversos sistemas lógicos de archivos Soportar diversos formatos de archivos ejecutables (como a.out, ELF, java) Presentar una interfaz común para todos los sistemas de archivos y dispositivos de hardware Proveer acceso de alta velocidad a los archivos Seguridad (al no perder o corromper datos) Restringir el acceso de usuarios a los archivos, así como restringir las cuotas de espacio de cada usuario

El sistema de archivos provee dos niveles de interfaz: una interfaz de llamadas al sistema disponible a los procesos de usuario (operaciones con archivos (open/close/read/write/seek/tell) y directorios (readdir/creat/unlink/chmod/stat) que cumplen con la especificación de sistemas POSIX), y una interfaz interna, usada por los subsistemas del kernel (inodes y archivos). La capa de controladores de dispositivos es responsable de presentar una interfaz común a todos los dispositivos físicos. El kernel de Linux tiene tres tipos de controladores: caracter (character), de bloque (block) y de red. Los dos tipos de controladores relevantes para el sistema de archivos son los dispositivos caracter y de bloque. Los dispositivos de caracteres deben ser accedidos secuencialmente; ejemplos típicos son cintas, módems, y el ratón. Los dispositivos de bloque pueden ser accedidos en cualquier orden, pero solo pueden ser leídos o escritos en múltiplos del tamaño de bloque.

208

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Todos los manejadores de dispositivos soportan la interfaz de operaciones de archivos ya descrita, por lo que cada dispositivo puede ser accedido como si fuera un archivo en el sistema de archivos (este archivo es referenciado como un archivo especial de dispositivo). Puesto que la mayor parte del kernel está relacionado con dispositivos por medio de esta interfaz de archivos, es relativamente sencillo agregar un nuevo controlador de dispositivo implementando el código específico de hardware que soporte la nueva interfaz abstracta.

Figura 6.16 Sistema virtual de archivos de Linux30
Aunque es posible acceder dispositivos físicos por medio de sus archivos especiales dispositivo, es más común acceder dispositivos de bloque por medio de un sistema lógico archivos. Un sistema de archivos lógico puede ser montado en algún punto del sistema virtual archivos, lo que significa que el dispositivo de bloque asociado contiene archivos y estructuras información que permiten al sistema lógico de archivos acceder al dispositivo. de de de de

30

Imagen reproducida de [6.24]

209

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 6.17 Estructura del administrador de archivos de Linux31

6.3

Comunicaciones en red⊕

En el inicio de la era de la informática las computadoras eran grandes y caras. Debido a su escasez y costo, éstas funcionaban de forma independiente. A partir de los años 70, surgen las primeras minicomputadoras, que competirían con las grandes computadoras (mainframes) tanto por las prestaciones, como por su precio, con lo que se extendió su uso. Los grandes sistemas centralizados fueron dejando paso lentamente a sistemas mucho más descentralizados, y formados por varias computadoras o sistemas multiprocesador. Pronto surgieron nuevas necesidades de interconexión de los equipos, y se desarrollaron las redes de área local (LAN), como Ethernet o Token Ring. En la actualidad, Internet es la red de mayor tamaño y la más usada, y mantiene un impresionante ritmo de crecimiento. Además, Internet es la base de muchos nuevos proyectos de sistemas distribuidos.

31 ⊕

Imagen reproducida de [6.24] Obras consultadas: [6.14][6.15]

210

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Dada su creciente importancia, el soporte de red de los sistemas operativos se ha convertido en un servicio básico para que las computadoras puedan interconectarse y compartir recursos. En esta sección se exponen los principales elementos que un sistema operativo debe implementar para que una computadora pueda integrarse a una red.

6.3.1 Redes de computadoras
Durante el siglo XX, la tecnología clave ha sido la recolección, procesamiento y distribución de información. Entre otros desarrollos, se tienen la instalación de redes telefónicas en todo el mundo, a la invención de la radio y la televisión, el nacimiento y crecimiento sin precedente de la industria de las computadoras, así como a la puesta en orbita de los satélites de comunicación. Una vez resuelto el problema de extender el poder de cálculo en las primeras generaciones de computadoras, se comenzó a atacar el problema de compartir los datos y la información que ese poder de cálculo produjo, lo cual llevó a inventar formas de compartir recursos (impresoras, graficadores, archivos, etc.) a través de algún medio de transmisión usando una serie de reglas (protocolos) para acceder y manipular dichos recursos. En un principio se creó un modelo centralizado de computadoras grandes (mainframes) para satisfacer todas las necesidades de cálculo de una organización; estas constaban de una computadora central (llamada anfitrión o host) y terminales ("tontas") que funcionaban como entrada y salida de datos pero eran incapaces de procesar información o de funcionar por cuenta propia. Este modelo fue reemplazado por otro que considera un gran número de computadoras separadas, pero interconectadas, que efectúan el mismo trabajo. Estos sistemas, se conocen con el nombre de redes de computadoras. Una red de computadoras es un sistema de comunicación de datos que enlaza dos o más computadoras y dispositivos o periféricos. En 1969 la Advanced Research Projects Agency (ARPA) del Pentagono creó la primera red llamada ARPAnet, la cual constaba sólo de cuatro computadoras conectadas. ARPAnet (la antecesora de la actual Internet) era una red experimental de investigación militar, en particular la investigación sobre cómo construir redes que pudieran soportar fallas parciales (como las producidas por bombardeos) y aún así funcionar. En el modelo ARPAnet, la comunicación siempre ocurre entre una computadora fuente y una destino. La red asume por si misma que es falible; cualquier parte de la red puede desaparecer en cualquier momento. La red fue diseñada para requerir un mínimo de información de las computadoras que forman parte de ella. Las primeras redes de cómputo comenzaron a operar a mediados de los años 70’s y la forma de comunicación entre dos computadoras era manual, se empleaba una cinta magnética o una pila de tarjetas perforadas, las cuales necesitaban ser insertadas a la otra computadora mediante la intervención humana, es decir, no funcionaban automáticamente como hoy se hace. Más tarde, este proceso se perfecciono y se logró transmitir información mediante cables conectando 3 o más computadoras, surgiendo así las redes, esta comunicación se establecía a muy baja velocidad y además había un gran inconveniente, las computadoras que formaban la red tenían que funcionar a la perfección porque a la menor falla de cualquiera de ellas la red dejaba de operar y era necesario desconectarla para dejar funcionando a las demás.

211

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Las redes en general, se avocan a compartir recursos, y uno de sus objetivos es hacer que todos los programas, datos y equipo estén disponibles para cualquiera en la red que así lo solicite, sin importar la localización física del recurso y del usuario. Una red de computadoras consta de: • • Componentes de hardware. Tarjetas de red y el medio de conexión (cable que las une). Componentes de software. Incluyen sistemas operativos, protocolos de comunicación y controladores (drivers) para las tarjetas de red.

Estructura y configuraciones de redes⊕
Existen 2 tipos de estructuras de una red: Redes Punto a punto.- Cada máquina tiene los mismos derechos de acceso como todas las demás; no existe un local central para las aplicaciones. Una red punto a punto es una colección de computadoras que comparten información igualmente, donde no existe una máquina central en la red. Los sistemas punto a punto son menos costosos que los sistemas basados en servidores, pero poseen más restricciones, especialmente en el aspecto del desempeño y del número total de usuarios. Los sistemas punto a punto están formados por pequeños grupos de trabajo que conectan un número pequeño de computadoras (de 2 a 20); los sistemas basados en servidores normalmente conectan más de 100 computadoras. Redes Cliente - Servidor.- Una red tipo Cliente-Servidor es una colección de computadoras (servidores) que agrupan recursos compatibles y computadoras (clientes) que acceden a dichos recursos desde los servidores. A su vez existen varias configuraciones o topologías de redes como: • Malla.- Son las más caras, pero a su vez son las más flexibles. Vienen caracterizadas por encontrar caminos entre estaciones muy rápidamente, pero hay que tener en cuenta que para N nodos, necesitamos N-1 enlaces, teniendo pues en total (N(N-1))/2 enlaces. Bus.- Tenemos un enlace por cada nodo, y estos se conectan a un enlace que une todas las estaciones. Típica. Anillo.- Cada nodo tiene dos enlaces, puesto que la información siempre le vendrá de un lado y la enviará hacia el otro. Un ejemplo de esta configuración la encontramos en un Token Ring. Estrella.- Esta configuración está siendo eliminada poco a poco, puesto que todo el sistema se basa en la estación central y si por algún motivo cayese, todo el sistema se vería afectado. El nodo central, para N estaciones, tiene N-1 enlaces, mientras que las otras estaciones tan sólo tendrían uno que es el que les vendría de la estación central. Árbol.- Todas las estaciones cuelgan de una computadora central y se conectan entre ellas a través de los hubs que haya instalados.

• •

Obras consultadas: [6.16][6.17]

212

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 6.18a Algunas ejemplos de las topologías que una red puede adoptar.
Las redes también se pueden clasificar en base a su ámbito de influencia. Según este criterio se pueden clasificar en tres grandes grupos: • LAN (Local Area Network): Redes de área local. La longitud entre los nodos más distantes no debe exceder los 5 Km. • • MAN (Metropolitan Area Network): Redes de área metropolitana. WAN (Wide Area Network): redes de área extensa o amplia.

El diseño (e implementación) de una red es especificado por ISO (International Standards Organization). En el modelo OSI, la red esta organizada en 7 capas. Cada capa se comunica con la capa equivalente en un sitio remoto. 1. Capa física. Transmite bits de una computadora a otra, y regula la transmisión de cadenas de bits sobre el medio físico. En esta capa se define cómo se une el cable al adaptador de red, y qué técnica de transmisión se emplea para enviar datos por el cable. 2. Capa de enlace. Aquí se empaquetan en bruto los bits de la capa física en tramas (paquetes de datos estructurados y lógicos) Es la responsable de transferir tramas de una computadora a otra sin errores. Después de enviar una trama se espera una expresión de reconocimiento de la computadora receptor. 3. Capa de red: Dirige mensajes y traduce traducciones lógicas, y nombres de direcciones físicas. También determina la ruta desde el origen al destino, y gestiona problemas de tráfico como conmutar, encaminar y controlar la congestión de paquetes de datos. 4. Capa de transporte: Maneja los errores de reconocimiento y la recuperación. También empaqueta grandes mensajes cuando es necesario transmitirlos en pequeños paquetes o reconstruye los originales en el lado de la recepción. También envía reconocimiento de la recepción. 5. Capa de sesión: permite a dos aplicaciones de diferentes computadoras establecer, usar y terminar una comunicación. A este nivel se establece el diálogo de control entre dos computadoras regulando cuál transmite, cuándo y cuánto. 6. Capa de presentación: en este nivel el sistema operativo traduce la información que el usuario generó en el nivel anterior. Se encripta la información (si fuese necesario) o se comprime, con el objetivo de disminuir el tráfico de la red y de la forma más fiable. 7. Capa de aplicación: representa el nivel en el que se encuentran las aplicaciones que acceden a los servicios de red. El usuario maneja estas aplicaciones en esta capa cuando trabaja con programas clientes de correo electrónico, acceso a datos de otros equipos, etc.

213

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 6.18b Modelo OSI y los equivalentes en el modelo de protocolos TCP/IP

Figura 6.19 Arquitectura de Netware 2.2 Interconexión de computadoras
Hay varias maneras de conectar computadoras físicamente: los puertos seriales, puertos paralelos, o adaptadores a los medios de comunicación especiales. Los ejemplos de medios de comunicación especiales incluyen Ethernet, Token Ring, ISDN, y otros.

214

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Hecha la elección del medio físico, todavía se tiene que escoger un protocolo. El protocolo es un juego de reglas que describen cosas como el formato de mensajes de la red. El software especializado para redes de computadoras es implementado casi siempre como varias capas de software separadas. Hay dos buenas razones para hacerlo esta manera: • Si se quiere crear un software fiable y libre de errores, entonces necesita complicarse un poco, dividiendo el trabajo en módulos independientes. La persona o equipo responsable de los detalles de bajo nivel deben preocuparse por la parte de alto nivel, y viceversa. La estratificación (layering) es una buena manera de clasificación de un trabajo complejo en módulos más manejables. Todo el manejo de los dispositivos se concentra en las capas más bajas, y las capas más altas pueden hacerse "universales", en el sentido que son independientes de qué clase de red está operando. Para agregar apoyo a un nuevo medio de transporte, o un nuevo protocolo, sólo se tiene que modificar una parte pequeña del software, y dejar el resto inalterado.

6.3.2 Organización del software de red
El software de red está organizado en tres niveles: Nivel de interfaz a las aplicaciones • Por lo general sockets (p.ej. Winsock en Windows) • Puede considerarse como nivel de sesión OSI Nivel de protocolos • Capa(s) que implementa(n) transporte y red OSI (o TCP/IP) • Incluye funciones de encaminamiento Nivel de dispositivo de red • Manejadores de dispositivos de red (nivel de enlace OSI)

215

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 6.20 Estructura del subsistema de red de Linux32
Puesto que ya se ha visto en las secciones anteriores la parte de manejadores de dispositivos, a continuación se presentan algunos detalles sobre los primeros 2 niveles del software de red.

Protocolos⊕
Un protocolo de comunicaciones es un conjunto de normas que están obligadas a cumplir todas las máquinas y programas que intervienen en una comunicación de datos entre computadoras sin las cuales la comunicación resultaría caótica y por tanto imposible Los protocolos establecen una descripción formal de los formatos que deberán presentar los mensajes para poder ser intercambiados por equipos de cómputo; además definen las reglas que ellos deben seguir para lograrlo.

32

Imagen reproducida de [6.24] Obras consultadas: [6.18] [6.19]

216

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Los protocolos están presentes en todas las etapas necesarias para establecer una comunicación entre equipos de cómputo, desde aquellas de más bajo nivel (p.ej. la transmisión de flujos de bits a un medio físico) hasta aquellas de más alto nivel (p.ej. el compartir o transferir información desde una computadora a otra en la red). Tomando al modelo OSI (Open Systems Interconection) como referencia podemos afirmar que para cada capa o nivel que él define existen uno o más protocolos interactuando. Los protocolos son entre pares (peer-to-peer), es decir, un protocolo de algún nivel dialoga con el protocolo del mismo nivel en la computadora remota. Conforme los esquemas de comunicación entre computadoras han evolucionado, se distinguen dos enfoques: Protocolos punto a punto. Son los protocolos más antiguos y elementales utilizados para la comunicación mediante una línea de datos entre dos únicas computadoras. Algunas de sus normas básicas establecen los criterios siguientes: • Papel que asume cada una de las dos partes durante una sesión de comunicaciones, identificándose y definiendo el papel correspondiente a la computadora que ha iniciado la sesión y al que responde. Al primero se le llama "comando" y al segundo, "respuesta". • Manera de controlar la correcta recepción de los datos. Por ejemplo, añadiendo un carácter al final de cada mensaje que sea la suma total de bit utilizados. • Tiempo máximo que debe pasar entre el envío de un mensaje y la recepción del acuse de recibo desde la estación receptora. • Número veces que se debe repetir un mensaje en caso de que, pasados los tiempos correspondientes, no se reciba el mensaje de acuse de recibo. Comunicación entre redes. Además de las normas del apartado anterior, han de especificar la forma de identificar al terminal concreto de la red con el que se debe establecer la comunicación en el caso de que las máquinas que se están comunicando directamente sean servidores de una red local (LAN). Por ejemplo asignando un numero a cada uno de los terminales. • Sistemas de polling: Estos sistemas controlan las comunicaciones en una red dirigida por una computadora central, y se organizan de manera que es éste el que les pregunta secuencialmente a todas las computadoras de la red si tienen algo que comunicar, y les insta a que lo hagan en caso afirmativo, ningún otro componentes de la red toma, en ningún momento, la iniciativa de la comunicación. • Protocolos de transmisión de paquetes: En los protocolos de transmisión de paquetes la transmisión se apoya en la propia información contenida en los datos que transitan por las redes de comunicaciones, mientras que en los protocolos anteriores, la responsabilidad del buen funcionamiento de las comunicaciones recae sobre los equipos y las líneas de datos. Para ello los datos se fragmentan y organizan en paquetes, como cartas de correo ordinario, con sus datos de origen y destino y van de equipo en equipo como las cartas van de estafeta en estafeta, de tren correo a camión de reparto y de otra estafeta al bolso del cartero quien finalmente la hace llegar a su destinatario. Los equipos que conforman las redes se limitan a leer las direcciones contenidas en los paquetes de datos y a entregar a la siguiente máquina el paquete, quien a su vez la entregará a otra y así sucesivamente hasta que finalmente llegue al destino.

217

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Caso de estudio: TCP/IP
TCP/IP es un conjunto de protocolos construidos para permitir la cooperación entre computadores con el fin de compartir recursos a través de la red. Este fue desarrollado por un conjunto de investigadores de ARPanet. Ciertamente ARPAnet es la red TCP/IP mejor conocida. Sin embargo en junio de 1987 más de 130 vendedores ya tenían productos que soportaban TCP/IP y cientos de redes de toda clase utilizaban este protocolo. Internet es un conjunto de redes, incluyendo a ARPanet, NSFnet, redes locales y un número de instituciones universitarias de investigaciones y un conjunto de redes militares. El término "Internet" aplica a todo el conjunto de redes anteriores. Un subconjunto de este que es administrado por el Departamento de Defensa es referenciado como el DDN (Defensa Data Network). TCP/IP es una familia de protocolos que provee funciones de "bajo nivel" necesarias para muchas aplicaciones. Este incluye los protocolos IP, TCP, y UDP.

Figura 6.21 Conjunto de protocolos TCP/IP y su relación con el modelo OSI
Los protocolos son para realizar tareas específicas, como por ejemplo transferencia de archivos entre computadoras, enviar correo, etc. Inicialmente TCP/IP fue utilizado comúnmente entre minicomputadoras y mainframes. Los servicios tradicionales más importantes de TCP/IP son: •

Transferencia de archivos: El protocolo de transferencia de archivos FTP (File Transfer Protocol) permite a un usuario desde cualquier computadora descargar
archivos desde otra computadora, o para enviar archivos entre computadoras. La seguridad está dada por un nombre de usuario y una contraseña válidos. Acceso remoto: El protocolo de terminal de redes (TELNET) permite a un usuario conectarse con cualquier otra computadora sobre la red. Usted puede iniciar una conexión especificando el nombre de la computadora con el que se desea conectar. Cualquier carácter que se teclee es enviado directamente al otro sistema. Generalmente, la conexión hacia el otro computador se realiza a través de una conexión telefónica. Para poder conectarse de forma remota se necesita conocer un nombre de usuario y una contraseña validos. Correo electrónico: Este permite que usted envíe mensajes a usuarios sobre otros computadores. A través de una aplicación que descarga los correos desde el servidor hasta su computadora (p.ej. Pine, Outlook).

218

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Estos servicios pueden estar presentes en cualquier implementación de TCP/IP. Este sistema se apoya en un modelo de servicio de redes Cliente/Servidor. Un servidor es un sistema que provee un servicio específico para el resto de la red. Un cliente es otro sistema que utiliza los servicios del servidor. A continuación mostramos los servicios típicos en un servidor. Estos servicios también pueden ser provistos sin la estructura de TCP/IP. • Sistema de Archivo de Red. Este permite a un sistema acceder archivos sobre otra computadora (algo más integrada que FTP). El sistema de archivo de red crea la ilusión que el disco u otro recurso compartido desde un sistema está directamente conectado a otro sistema. No se necesita usar una utilería especial de red para acceder un archivo sobre otro sistema. La computadora simplemente piensa que existe un disco extra. Este disco "virtual" extra hace referencia al disco del otro sistema. Impresión remota. Este permite que acceder impresoras en otras computadoras como si estas estuvieran colocadas en su máquina directamente. Ejecución remota. Este permite que haga una solicitud para correr un programa sobre una computadora diferente. Existe un número de diferente de clases de ejecución remota. Algunas operan sobre comandos básicos. Existen sistemas de "llamadas a procedimientos remotos" (remote procedure call - RPC) que permite a un programa llamar a una subrutina para que corra sobre otro computadora. Servidor de Nombres. En redes grandes, existe diferente número de nombres que tienen que ser administrado. Es tedioso mantener actualizado esta información en todas las computadoras, por lo que se creó este servicio que utiliza una base de datos para resolver los nombre de las computadoras a su dirección. Servidor de terminal. Un servidor de terminal es simplemente una pequeña computadora que solo permite correr Telnet. Si la terminal está conectada a uno de estos servidores, simplemente hay que escribir el nombre de una computadora y se estará conectado a esta. Por lo general es posible mantener conexiones activas con más de una computadora al mismo tiempo.

• •

Los anteriores son un simple ejemplo de algunos de los servicios que puede implementarse a través de TCP/IP.

Sockets⊕
Los sockets no son más que puntos o mecanismos de comunicación entre procesos que permiten que un proceso hable (emita o reciba información) con otro proceso incluso estando estos procesos en distintas máquinas (2 programas que se ejecutan a través de una red). Un escenario típico, es donde una aplicación servidor normalmente escucha a un puerto específico esperando una petición de conexión de un cliente. Cuando llega una petición de conexión, el cliente y el servidor establecen una conexión dedicada sobre la que poder comunicarse. Durante el proceso de conexión, el cliente es asignado a un número de puerto, y asigna un socket a ella. El cliente habla al servidor escribiendo sobre el socket y obtiene información del servidor cuando lee de él. Similarmente, el servidor obtiene un nuevo número de puerto local (necesita un nuevo puerto para poder continuar escuchando para petición de

Obras consultadas: [6.20] [6.22]

219

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

conexión del puerto original.) El servidor también asigna un socket a este puerto local y comunica con él mediante la lectura y escritura sobre él. El cliente y el servidor deben ponerse de acuerdo sobre el protocolo -- esto es, debe ponerse de acuerdo en el lenguaje para transferir la información de vuelta a través del socket. En el interior de un proceso, un socket se identifica por un descriptor de la misma naturaleza que los que identifican los archivos, al igual que todos los procesos del sistema UNIX de Berkeley. La comunicación mediante sockets es una interfaz (o servicio) con la capa de transporte (nivel 4) de la jerarquía OSI. La filosofía de la división por capas de un sistema es encapsular, dentro de cada una de ellas, detalles que conciernen sólo a cada capa, y presentársela al usuario de tal forma que este pueda trabajar con ella sin necesidad de conocer sus detalles de implementación. La interfaz de acceso a la capa de transporte del sistema UNIX de Berkeley no está totalmente aislada de las capas inferiores, por lo que a la hora de trabajar con sockets, es necesario conocer algunos detalles sobre esas capas. En concreto, a la hora de establecer una conexión mediante sockets, es necesario conocer la familia o dominio de la conexión, y el tipo de conexión. La creación de un socket se realizará por la primitiva socket(), cuyo valor de vuelta es un descriptor sobre el cual es posible realizar operaciones de escritura y lectura. Un socket permite la comunicación en los dos sentidos (conexión full-dúplex). Cada tipo de socket va a definir una serie de propiedades en función de las comunicaciones en las cuales está implicado: a. La fiabilidad de la transmisión. Ningún dato transmitido se pierde. b. La conservación del orden de los datos. Los datos llegan en el orden en el que han sido emitidos. c. La no duplicación de datos. Sólo llega a destino un ejemplar de cada dato emitido. d. La comunicación en modo conectado. Se establece una conexión entre dos puntos antes del principio de la comunicación (es decir, se establece un circuito virtual). A partir de entonces, una emisión desde un extremo está implícitamente destinada al otro extremo conectado. e. La conservación de los límites de los mensajes. Los límites de los mensajes emitidos se pueden encontrar en el destino. f. El envío de mensajes (urgentes). Corresponde a la posibilidad de enviar datos fuera del flujo normal, y por consecuencia accesibles inmediatamente (datos fuera de flujo). Cabe resaltar que un cauce de comunicación normal tiene las cuatro primeras propiedades, pero no las dos últimas. En cuanto a los tipos de sockets disponibles, se pueden considerar: • SOCK_STREAM: Los sockets de este tipo permiten comunicaciones fiables en modo conectado (propiedades a, b, c y d) y eventualmente autorizan, según el protocolo aplicado los mensajes fuera de flujo (propiedad f). El protocolo subyacente en el dominio Internet es TCP. Se establece un circuito virtual realizando una búsqueda de enlaces libres que unan las dos computadoras a conectar (parecido a lo que hace la

220

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• •

red telefónica conmutada para establecer una conexión entre dos teléfonos). Una vez establecida la conexión, se puede proceder al envío secuencial de los datos, ya que la conexión es permanente. Son streams de bytes full-dúplex (similar a pipes). Un socket stream debe estar en estado conectado antes de que se envíe o reciba en él. SOCK_DGRAM: Corresponde a los sockets destinados a la comunicación en modo no conectado para el envío de datagramas de tamaño limitado. Las comunicaciones correspondientes tienen la propiedad e. En el dominio Internet, el protocolo subyacente es el UDP. Los datagramas no trabajan con conexiones permanentes. La transmisión por los datagramas es a nivel de paquetes, donde cada paquete puede seguir una ruta distinta, no garantizándose una recepción secuencial de la información. SOCK_RAW: Permite el acceso a los protocolos de más bajo nivel (por ejemplo, el protocolo IP en el dominio Internet). Su uso está reservado al superusuario. SOCK_SEQPACKET: Corresponde a las comunicaciones que poseen las propiedades a, b, c, d y e. Estas comunicaciones se encuentran en el dominio XNS.

Los tipos de sockets más utilizados son los dos primeros.

6.3.3 Caso de estudio: Windows 9X en red
La arquitectura modular de red en Windows 95 está basada en dos modelos estándares de la industria: el modelo de la Organización Internacional de Estandarización (ISO) denominado modelo de Referencia de Sistemas Abiertos Interconectados (OSI: Open System Inerconect), y el 802 del IEEE. Ambos modelos definen las características que debe poseer un sistema de red, distribuyendo todos los componentes de la misma en capas interrelacionadas y perfectamente definidas. Se contemplan desde los programas que maneja el usuario, hasta el cableado que une los adaptadores y elementos de la red. La red Windows 9x funciona a los siguientes niveles: 7. 6. 5. 4. 3. 2. 1. Aplicación Proveedores de red Administradores IFS Redirector red Microsoft/compatible NetWare Protocolo de transporte NDIS.YXD Controlador de la tarjeta de red. NIC (tarjeta de red)

Interfaces de dispositivos de red
Hasta hace poco, sobre un adaptador de red sólo se podía montar un único protocolo. Se denominaban arquitecturas de tipo monolítico. Esto quiere decir que para conectar un equipo simultáneamente a una red Novell y a una red de Microsoft, era necesario dotarle de dos tarjetas, una por cada tipo de red.

221

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Con el fin de permitir que sobre una tarjeta se pudiese montar más de un protocolo surgieron dos especificaciones: • • ODI: Open Device Interface de Novell. NEDIS: Network Device Interface Specification de Microsoft.

En Windows 9x, tanto la tarjeta de red como cada uno de los protocolos que se montan sobre ella deben de admitir la especificación NEDIS. Así, entre los controladores que acompañan a las tarjetas en los discos, se incluyen los que soportan tanto NEDIS como ODI. Los adaptadores NEDIS 3.1, se gestionan a través de un controlador que se divide en dos partes. La primera es un mini-controlador que realiza detalles como el establecimiento de comunicaciones con el adaptador, el apagado o encendido del aislamiento eléctrico para dispositivo P&P y la activación de cualquier propiedad añadida que tenga el adaptador. La segunda es una envoltura que implementa las funciones NDIS.

Arquitectura para protocolos
Windows 9x incluye soporte para protocolos IPX/SPX, NetBeui y TCP/IP. NetBIOS no es un protocolo, es como una capa entre los protocolos y las aplicaciones. Permite conectarse a la red utilizando nombres sencillos, sin importar el protocolo que se esté utilizando. • Protocolo para IPX/SPX. El driver encargado de dar soporte IPX/SPX es el NWNBLINK.VXD, el cual permite NetBIOS sobre IPX, además de permitir la interfaz de programación NetBIOS. El protocolo compatible IPX/SPX es compatible NEDIS 3.1. De esta forma, permite comunicarse con servidores Novell-Netware configurados como encaminadores para transferir paquetes sobre una LAN y acceder incluso a otros equipos como Windows 9x.Este es el protocolo más adecuado para una red pequeña que no se conecte a Internet. Por supuesto, debe tener NetBIOS por encima de él. Como desventaja, en este protocolo no pueden redireccionar subredes. Protocolo NetBeui. El módulo NETBEUI.VXD implementa el protocolo de tramas NetBIOS. Es un protocolo de Microsoft. Puede ser utilizado por cuestiones de compatibilidad con sistemas antiguos, aunque en general es conflictivo, por lo que no es aconsejable en una red con más de diez equipos. Protocolo TCP/IP. El protocolo TCP/IP se encuentra en el módulo VTCP.VXD, que es accesible a través de la interfaz de conexiones lógicas de red de Windows, o a través de la interfaz NetBIOS. El problema es que la información no está codificada, por lo que la seguridad no es la mejor. Para ello se ha desarrollado el protocolo PPTP. También es más difícil de configurar.

Arquitectura para clientes de redes
Para poder utilizar todos los productos de red de Microsoft que empleen el protocolo de compartición de archivos NetBIOS, Windows 9x proporciona un controlador en modo protegido de 32 bits. Esto incluye LAN Manager, IBM LAN Server y 3Com 3+Open. El cliente de redes Microsoft permite la conexión sobre cualquier protocolo NEDIS que admita la interfaz NetBIOS.

222

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Mecanismos de comunicación entre procesos (IPC)
El procesamiento distribuido permite que una tarea se desarrolle en dos partes: Una ejecutándose en la computadora cliente, consumiendo pocos recursos, y otra en el servidor consumiendo gran cantidad. También permite que determinados dispositivos residan en el servidor permitiendo que los clientes hagan uso de él. Otro tipo de procesamiento distribuido permite que la carga de determinadas operaciones se distribuya entre varias computadoras. De esta forma una tarea que exija de grandes cálculos y que llevaría varios días en una computadora se puede repartir entre varios equipos de forma que estos tarden menos tiempo en realizarla. El procesamiento distribuido permite la conexión a nivel proceso-proceso, estableciéndose un flujo de datos en ambas direcciones. Windows 9x incluye los siguientes mecanismos de comunicación y de procesos para permitir la computación distribuida: • Conexiones lógicas de red; Las conexiones lógicas de red, también llamadas WinSockets, están diseñadas basadas en las API (Aplication Program Interface) de conexión lógica de red U.C.Berkeley, el estándar de facto para acceder a servicios de datagrama y sesión sobre TCP/IP. Llamadas a procedimientos remotos (RPC: Remote Procedure Call). El componente RPC de Microsoft es compatible con la especificación de intercambio de comunicación de datos DCE de Open Software Foundation (OSF) para llamadas a procedimientos remotos, y por tanto funciona con sistemas compatibles DCE, como sistemas HP y AIX. RPC emplea mecanismos tales como canales identificativos NetBIOS o conexiones lógicas de red para establecer comunicaciones entre el cliente y el servidor. Con el componente RPC la lógica de programación básica y el código relacionado pueden funcionar en diferentes computadoras, lo que es muy importante para aplicaciones distribuidas. NetBIOS. El sistema básico de entrada y salida de red (NetBIOS) es el conjunto de funciones de bajo nivel que dan soporte a todos los servicios de la red Windows. NetBIOS puede ser usado para comunicación entre protocolos y el software de alto nivel como el reexpedidor y el servicio de servidor. Proporciona compatibilidad hacia abajo para aplicaciones desarrolladas para versiones anteriores de Windows. Canales identificativos Buzones.

• •

Instalación y configuración de las tarjetas de red
La tarjeta de red puede ser instalada mientras se instala Windows 9x. Para ello nos pregunta si tenemos tarjeta de red. También es posible instalarla posteriormente. Las tarjetas de red suelen venir con los conectores RJ-45, BNC, AUI o alguna combinación de ellos. La interfaz mediante el cual se conecta la tarjeta a la computadora puede ser ISA o PCI (en modelos antiguos Vesa y EISA). Las más modernas o actuales suelen ser de tipo PnP.

6.4

Comentarios

En este capítulo se concluye la exposición de los principales subsistemas de administración de los sistemas operativos.

223

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Con estos elementos, en los siguientes capítulos se discute el diseño de sistemas operativos para después hacer una categorización y descripción de las principales arquitecturas existentes. Por ello, es importante el referente de los capítulos 4, 5 y 6 para que el lector sepa con que bloques funcionales puede contar.

224

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

6.5

Obras consultadas
[6.13] Linux Device Drivers Demystified. James Andrews http://www.linuxplanet.com/linuxplanet/tutorials/ [6.14] SISTEMAS OPERATIVOS http://server2.southlink.com.ar/vap/sistemas_operativo s.htm [6.15] Sistemas Operativos de Red http://www.itmorelia.edu.mx/matsdsc/sor/indice~1.html [6.16] Sistemas operativos para redes punto a punto http://www.geocities.com/SiliconValley/8195/nospp.ht ml [6.17] Sistemas Operativos de Red y Distribuidos http://www.lafacu.com/apuntes/informatica/Sistemas_ Operativos_en_Red_y_Distribuidos/default.htm [6.18] FAMILIA DE PROTOCOLOS TCP/IP http://www.uca.edu.sv/investigacion/tutoriales/tcpip.html http://members.tripod.com/~MoisesRBB/tcpip.html [6.19] PUNTONET TUTORIAL REDES http://epuntonet.com/tu/estu_reti.htm

[6.1] Sistemas operativos: una visión aplicada. Félix García Carballeira, et. al. 1999 http://laurel.datsi.fi.upm.es/~ssoo/DSO/ [6.2] HOW TO WRITE DEVICE DRIVERS. Stephen Williams steve@icarus.com http://icarus.com/linux_driver/device-driver-1.html [6.3] http://ironbark.bendigo.latrobe.edu.au/subjects/bitsys/ oslect/lectlist.html [6.4] Plan 9: Feature Film to Feature-Rich OS. Paul Fillinich. March, 1996. http://www.byte.com/art/9603/sec14/sec14.htm [6.5] EL UNIVERSO DIGITAL DEL IBM PC, AT Y PS/2 Ciriaco García de Celis. Edición 4.0 http://udigital.homepage.com/libro/index.html [6.6] Curso de sistemas operativos http://lara.pue.udlap.mx/sist_oper/index.html [6.7] JavaOS: Thin Client, Fat Service. Charles Mirho and Tom Clements. July, 1997. http://www.byte.com/art/9707/sec4/sec4.htm [6.8] Tecnología de Redes y Sistema de cableado Estructurado Conceptos generales http://www.solnet.com.pe/cursos/redes_conceptos_gen erales/index.htm [6.9] Historia de Sistemas Operativos para Red y Porque es más fácil y económico configurar Unix que Windows en Red ? http://www.osmosislatina.com/diversos/mas_facil.htm [6.10] Introducción a los Sistemas de Información-SCI 210 http://www.ucb.edu.pr/SCI210/LESSONS/L5.HTM [6.11] ESO-SOL Práctica 3: Manejadores de dispositivo Ismael Ripoll, Juan Carlos Pérez, y Sergio Sáez [6.12] Device Drivers. The HyperNews Linux KHG Discussion Pages http://khg.redhat.com/HyperNews/get/khg.html

[6.20] La interfaz Socket http://www.lcc.uma.es/~eat/services/i_socket/i_socket. html [6.21] The Box: A Replacement for Files Francisco J. Ballesteros http://plan9.escet.urjc.es/who/nemo/export/2kblocks/in dex.html [6.22] Pequeña introducción a los sockets http://members.easyspace.com/hackuma/socketz.htm [6.23] Conceptual Architecture of the Linux Kernel. Ivan Bowman (ibowman@sybase.com) January 1998 http://plg.uwaterloo.ca/~itbowman/CS746G/a1/ [6.24] Concrete Architecture of the Linux Kernel. Ivan Bowman, Saheem Siddiqi , Meyer C. Tanuan. Department of Computer Science, University of Waterloo. Winter 1998 http://plg.uwaterloo.ca/~itbowman/CS746G/a2

225

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

[6.25] Sistemas operativos. David Luis la Red Martínez. http://exa.unne.edu.ar/depar/areas/informatica/Sistem asOperativos/SOF.htm

[6.26] Programación de bajo nivel. Juan Antonio de la Puente. DIT/UPM. 2001 http://polaris.dit.upm.es/~jpuente/strl/transparenc ias/Bajo_Nivel.pdf

226

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Capitulo 7. Diseño de sistemas operativos
-¿Cual es su código de entrada en computadora doctora Rash?- pregunto Calvin-. O márcalo tú misma, si esto te tranquiliza. Quiero inspeccionar el diseño del cerebro positrónico.(...) Linda se asombró. Era imposible analizar un diseño sin la ayuda, por lo menos de una computadora de mano. No obstante, la vieja simplemente observaba.¿Tendría acaso una computadora implantada en su cráneo? ¿o era que su cerebro durante décadas no había hecho otra cosa que inventar, estudiar y analizar los diseños de cerebros positrónicos? ¿Captaba los diseños como Mozart captaba la notación de una sinfonía? -¿Qué es lo que has hecho Rash?- dijo Calvin por fin. Linda, algo avergonzada contestó: -He utilizado la geometría fractal. -Ya me he dado cuenta, pero, ¿por qué? -Nunca se había hecho. Pensé que a lo mejor produciría un diseño cerebral con complejidad añadida, posiblemente más cercano al cerebro humano. -¿Consultaste a alguien? ¿Lo hiciste todo por tu cuenta? -No consulte a nadie. Lo hice sola. Los ojos ya apagados de la doctora miraron fijamente a la joven. -No tenías derecho a hacerlo. Tu nombre es Rash; tu naturaleza hace juego con tu nombre.¿Quién eres tu para obrar sin consultar? Yo misma, yo, Susan Calvin, lo hubiera discutido antes. -Temí que se me impidiera. -Por supuesto que se te habría impedido.

Sueños de robot, Isaac Asimov

Después de haber expuesto todos los fundamentos teóricos, analizar los principales servicios y componentes de los sistemas operativos, y contar con el antecedente del uso de la simulación para el diseño de este tipo de sistemas, llegó la hora de integrar todo este conocimiento. Todo aquel que ha tomado un curso de sistemas operativos o ha comprado un libro sobre el tema, siempre ha deseado saber cómo se construye uno (lo cual por lo general no es un tema trivial). En un principio, las metas de este trabajo llegaron a ser: • • implementar un sistema operativo o plantear una metodología que lidiara con la complejidad del desarrollo de un sistema operativo

En el primer caso, no se ha tenido una buena razón para codificar un sistema operativo (en lo laboral, lo más que el autor ha aplicado y desarrollado son compiladores). En el segundo caso, siendo realistas, es una tarea que implicaría otro trabajo por sí mismo. Además, después de reflexionar, se llegó a la conclusión de que inventar el hilo negro no tiene mucho sentido, por lo que se prefirió investigar si existía alguna forma de abordar el desarrollo de SOs sin que implicará replantear algo que grupos de trabajo fuertes en ingeniería de software ya han hecho.

227

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Hablar de un proyecto para el desarrollo de un sistema operativo puede ser muy basto. Hablar de todo el proceso de desarrollo y los detalles que un sistema, o varios deben tomar en cuenta, es complejo y hay poca documentación al respecto. Sin embargo la etapa crítica es la elaboración del sistema, cuyo propósito es analizar el dominio del problema, establecer una arquitectura, desarrollar un plan para el proyecto y eliminar los mayores elementos de riesgo del proyecto. En específico, se decidió acotar la exposición de este capítulo a ¿cómo definir la arquitectura de un sistema operativo? Después de investigar algunas referencias, se encontró un enfoque que está cobrando fuerza en el proceso de desarrollo de sistemas, llamado arquitectura de software, el cual está orientado al planteamiento de arquitecturas conceptuales. Este parece un enfoque realista de alto nivel que no entra al detalle de resultados de aplicar completamente una metodología para desarrollo de sistemas. La idea no es crear la mini-especificación de un sistema, pues esto solo serviría como un caso de estudio particular. Por el contrario, la idea es establecer los lineamiento generales para poder enfocar los esfuerzos de desarrollo de manera óptima, y aprovechando el conocimiento expuesto hasta el momento, por lo que se expondrán consideraciones de diseño de alto nivel, relacionadas con la definición de una arquitectura de software. En este capítulo se ubica el enfoque de la arquitectura de software en el contexto del desarrollo y la ingeniería de software, y se aplicarán en este sentido varias de las consideraciones de diseño que otros proyectos han tomado en cuenta al desarrollar sistemas operativos, esperando con esto establecer un contexto especifico a los sistemas operativos que permita una mejor toma de decisiones de diseño, de forma metódica. Además este enfoque permitirá incluir algunos consejos y lineamientos de los doctos en la cuestión de diseñar este tipo de sistemas (aficionados y académicos), lo que resulta más ilustrativo al dejar constancia de todo lo que a alguien se le puede ocurrir o pensar para llegar a concretar un prototipo de este tipo de sistemas.

7.1

El software y sus características

Todo sistema de cómputo, es una combinación de hardware y software, y este último es vital para su funcionamiento. El software de computadoras actúa como la base de control de la computadora, la comunicación de información y la creación y control de otros programas. El software es la parte lógica con que trabaja una computadora: programas de sistemas, aplicaciones y utilerías. Algunas características del software son: • El software se desarrolla, no se fabrica en el sentido clásico: Desarrollar software y construir hardware son actividades que requieren la construcción de un producto, pero los métodos son diferentes. Los proyectos de software no se pueden gestionar como si fueran un proyecto de fabricación. • El software no se estropea: Durante su vida el software sufre cambios que producen el deterioro del mismo. Se debe tener presente que no hay pieza de repuesto para el

228

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

software, los fallos en el software indican un error en el diseño o en el proceso mediante se trabaja el diseño a código de máquina ejecutable. La mayoría del software se construye a la medida, en vez de ensamblaje componentes existentes: Se puede comprar software ya desarrollado, pero sólo como una unidad completa, no como componentes que pueden reensamblarse en nuevos programas.

7.1.1 ¿Por qué es necesario un sistema operativo?⊕
Antes de aventurarse en la empresa de hacer sistemas operativos, debe cuestionarse si el dispositivo electrónico que se tiene necesita un sistema operativo. Es un hecho que no todas las computadoras tienen SOs. La computadora que controla un horno microondas, o una lavadora, no necesita un SO. Este tipo de dispositivos tienen un conjunto relativamente simple de tareas a realizar, como métodos simples de entrada y salida (un teclado y una pantalla LCD) y el hardware a controlar (que nunca cambia). Para una computadora como estas, un SO no es necesario (puede ser implementado por una máquina de estados sencilla) y sería hasta exagerado (aunque hay que aclarar que ya hay proyectos donde los refrigeradores se conectán al Internet y hacen las compras, y el concepto de casas inteligentes y cómputo ubicuo si pueden llegar a necesitar SOs en diferentes dispositivos). En su lugar, la computadora del microondas ejecuta un solo programa todo el tiempo. Para computadoras que sobrepasan la complejidad de la lavadora, un SO es la clave para una operación eficiente y facilidad al desarrollar aplicaciones. Las más comunes para nosotros son las computadoras personales, asistentes personales (PDAs), etc. Hay cientos de SOs disponibles para aplicaciones especificas como supercomputadoras, robótica, manufactura, sistemas de control, etc. Una relación de dispositivos y algunos de los sistemas operativos usados en ellos se presenta en la tabla 3. Dispositivo
Tarjeta inteligente Dispositivos incrustados Teléfonos celulares y dispositivos móviles Auto PC Consolas de juegos Handheld/PC (PDA) Computadora personal Estación de trabajo Servidor Cluster Supercomputadora OSSCA, MULTOS QNX, Linux, eCos, Inferno, MS Windows CE, EYRX EPOC, Symbian OS, Linux MS Windows CE Linux, MS, Windows, Roundtable, Sony Palm OS, MS Windows CE, Linux DOS, MS Windows (3.x, 9x, Me, XP), Mac OS, Linux, Be OS, IBM OS/2 BSD, SCO UNIX, IRIX, Linux, MS Windows (NT, 2000), Mac OS Sun Solaris, MS Windows (NT, 2000), Mac OS, Linux, SCO UNIX, IBM VM/CMS, IBM z/VM, Open VMS, Sun OS, Linux, MS Windows (2000, .Net) UNIX, Cray UNICOS, IBM AIX, SGI IRIX, OSF/1, PUMA OS

Sistema Operativo

Tabla 3. Relación de dispositivos de cómputo y sus sistemas operativos

Obras consultadas: [7.9] [7.10]

229

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Así que primero hay que establecer la complejidad del sistema para el cual se quiere desarrollar el SO, para determinar el esfuerzo y los costos del desarrollo. Debe tomarse en cuenta que en los últimos años se ha planteado el paradigma de los sistemas ubicuos, es decir muchas computadoras trabajando en conjunto, pero sin que el usuario lo note. Esto hace que no solo nos preguntemos si el dispositivo requiere de un SO, sino si el dispositivo formará parte (ahora o en un futuro) de este tipo de sistemas de cómputo.

7.1.2 ¿Para qué escribir un sistema operativo?
Algunas razones que pueden motivar el desarrollo de un sistema operativo son: • Investigación: alta disponibilidad, alto desempeño, tiempo real, computo distribuido, orientación a objetos, portabilidad, reemplazo o competencia de un sistema operativo comercial, nuevas arquitecturas (p.ej. exokernel, SASOS), etc. • Aprendizaje sobre: multitarea, protección de la memoria, codificar una librería estándar (p.ej. libc en lenguaje C), manejadores de dispositivos, sistemas de archivos, aplicaciones, etc. • Los SOs disponibles pueden no ser satisfactorios (no cubren necesidades especificas, o su visión y alcance es limitado en su contexto de aplicación). • • Crear un SO orientado a la enseñanza del diseño de sistemas operativos. Buscar fama y la fortuna (¿por qué no?)

7.2

Desarrollo de sistemas de software

El desarrollo de sistemas de software complejos no es una actividad trivial que pueda abordarse sin una preparación previa. El considerar que un proyecto de desarrollo de software podía abordarse como cualquier otro, ha llevado a una serie de problemas que limitan nuestra capacidad de aprovechar los recursos que el hardware pone a nuestra disposición. En esta sección se exponen algunos conceptos sobre el proceso de desarrollo y la ingeniería de software, con el fin de ubicar y entender la actividad del diseño de sistemas y orientar la discusión a las principales decisiones de diseño que se presentan en un proyecto de sistemas operativos.

7.2.1 Proceso de desarrollo de software
El proceso de desarrollo de software (PDS) puede definirse como un conjunto de herramientas, métodos y prácticas que se emplean para producir software. Como cualquier otra organización, las dedicadas al desarrollo de software mantienen entre sus principales fines, la producción de software de acuerdo con la planificación inicial realizada, además de una constante mejora con el fin de lograr los tres objetivos últimos de cualquier proceso de producción: alta calidad y bajo costo, en el mínimo tiempo. Un proceso software debe especificar:

230

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

– – – – –

la secuencia de actividades a realizar por el equipo de desarrollo: flujo de actividades productos que deben crearse: qué y cuándo asignación de tareas a cada miembro del equipo y al equipo como un todo proporcionar heurísticas criterios para controlar el proceso

Figura 7.1 Esquema del proceso unificado de desarrollo (RUP)
La gestión de un proceso engloba, por tanto, todas las funciones que mantengan a un proyecto dentro de unos objetivos de coste, calidad y duración previamente estimados. La mayoría de estas funciones y técnicas de gestión y control empleadas, se han importado de otras industrias de producción que desarrollaron estos métodos a principios de siglo. No existe una fórmula mágica para solucionar estos problemas, pero combinando métodos aplicables a cada una de las fases del desarrollo de software, construyendo herramientas para automatizar estos métodos, utilizando técnicas para garantizar la calidad de los productos desarrollados y coordinando todas las personas involucradas en el desarrollo de un proyecto, podremos avanzar mucho en la solución de estos problemas. De ello se encarga la disciplina llamada Ingeniería del Software.

7.2.2 Ingeniería de software
Una de las primeras definiciones que se dio de la ingeniería del software es la siguiente:

El establecimiento y uso de principios de ingeniería robustos, orientados a obtener software económico, que sea fiable y funcione de manera eficiente sobre máquinas reales.
La ingeniería del software abarca un conjunto de tres elementos clave: métodos, herramientas y procedimientos, que faciliten al gestor el control el proceso de desarrollo y suministren a los desarrolladores bases para construir de forma productiva software de alta calidad.

231

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Los métodos indican cómo construir técnicamente el software, y abarcan una amplia serie de tareas que incluyen la planificación y estimación de proyectos, el análisis de requisitos, el diseño de estructuras de datos, programas y procedimientos, la codificación, las pruebas y el mantenimiento. Los métodos introducen frecuentemente una notación específica para la tarea en cuestión y una serie de criterios de calidad. Las herramientas proporcionan un soporte automático o semiautomático para utilizar los métodos. Existen herramientas automatizadas para cada una de las fases vistas anteriormente, y sistemas que integran las herramientas de cada fase de forma que sirven para todo el proceso de desarrollo. Estas herramientas se denominan CASE (Computer Assisted Software Engineering). Los procedimientos definen la secuencia en que se aplican los métodos, los documentos que se requieren, los controles que permiten asegurar la calidad y las directrices que permiten a los gestores evaluar los progresos.

La ingeniería de software se define como la disciplina tecnológica preocupada de la producción sistemática y del mantenimiento de los productos de software que son desarrollados y modificados en tiempo y dentro de un presupuesto definido. La ingeniería de software difiere de la programación tradicional en que se utilizan técnicas de ingeniería para especificar, diseñar, instrumentar, validar y mantener los productos dentro del tiempo y el presupuesto establecidos.

Concepto de ciclo de vida
Por ciclo de vida, se entiende la sucesión de etapas por las que pasa el software desde que un nuevo proyecto es concebido hasta que se deja de usar. Cada una de estas etapas lleva asociada una serie de tareas que deben realizarse, y una serie de entregables que serán la salida de cada una de estas fases y servirán de entrada en la fase siguiente.

Figura 7.2 Ciclo de vida en cascada

232

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Fases genéricas de la ingeniería de software
Independientemente del paradigma que se utilice, del área de aplicación, y del tamaño y la complejidad del proyecto, el proceso de desarrollo de software contiene siempre una serie de fases genéricas, existentes en todos los paradigmas. Estas fases son la definición, el desarrollo y el mantenimiento. a. Definición. La fase de definición se centra en el qué. Durante esta fase, se intenta identificar: 1. 2. 3. 4. 5. 6. Qué información es la que tiene que ser procesada. Qué función y rendimiento son los que se esperan. Qué restricciones de diseño existen. Qué interfaces deben utilizarse. Qué lenguaje de programación, sistema operativo y soporte hardware van a ser utilizados. Qué criterios de validación se necesitan para conseguir que el sistema final sea correcto.

Aunque los pasos concretos dependen del modelo de ciclo de vida utilizado, en general se realizarán tres tareas específicas: 1. Análisis del sistema. Como ya hemos visto, el análisis del sistema define el papel de cada elemento de un sistema informático, estableciendo cuál es el papel del software dentro de ese sistema. 2. Análisis de requisitos del software. El análisis del sistema proporciona el ámbito del software, su relación con el resto de componentes del sistema, pero antes de empezar a desarrollar es necesario hacer una definición más detallada de la función del software. Existen dos formas de realizar el análisis y refinamiento de los requisitos del software. Por una parte, se puede hacer un análisis formal del ámbito de la información para establecer modelos del flujo y la estructura de la información. Luego se amplían unos modelos para convertirlos en una especificación del software. La otra alternativa consiste en construir un prototipo del software, que será evaluado por el cliente para intentar consolidar los requisitos. Los requisitos de rendimiento y las limitaciones de recursos se traducen en directivas para la fase de diseño. El análisis y definición de los requisitos es una tarea que debe llevarse a cabo conjuntamente por el desarrollador de software y por el cliente. La especificación de requisitos del software es el documento que se produce como resultado de esta etapa.

233

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

3. Planificación del proyecto software. Durante esta etapa se lleva a cabo el análisis de riesgos, se definen los recursos necesarios para desarrollar el software y se establecen las estimaciones de tiempo y costes. El propósito de esta etapa de planificación es proporcionar una indicación preliminar de la viabilidad del proyecto de acuerdo con el coste y con la agenda que se hayan establecido. Posteriormente, la gestión del proyecto durante el desarrollo del mismo realiza y revisa el plan de proyecto de software. b. Desarrollo. La fase de definición se centra en el cómo. • • • • • • Cómo ha de ser la arquitectura de la aplicación. Cómo han de ser las estructuras de datos. Cómo han de implementarse los detalles procedurales de los módulos. Cómo van a ser las interfaces. Cómo ha de traducirse el diseño a un lenguaje de programación. Cómo van a realizarse las pruebas.

Aunque, al igual que antes, los pasos concretos dependen del modelo de ciclo de vida utilizado, en general se realizarán cuatro tareas específicas: 1. Diseño. El diseño del software traduce los requisitos a un conjunto de representaciones (gráficas, en forma de tabla o basadas en algún lenguaje apropiado) que describen cómo van a estructurarse los datos, cuál va a ser la arquitectura de la aplicación, cuál va a ser la estructura de cada programa y cómo van a ser las interfaces. Es necesario seguir criterios de diseño que nos permitan asegurar la calidad del producto. Una vez finalizado el diseño es necesario revisarlo para asegurar la completitud y el cumplimiento de los requisitos del software. 2. Codificación. En esta fase, el diseño se traduce a un lenguaje de programación, dando como resultado un programa ejecutable. La buena calidad de los programas desarrollados depende en gran medida de la calidad del diseño. Una vez codificados los programas debe revisarse su estilo y claridad, y se comprueba que haya una correspondencia con la estructura de los mismos definida en la fase de diseño. El listado fuente de cada módulo (o el programa fuente en soporte magnético) pasa a formar parte de la configuración del sistema. 3. Pruebas. Una vez que tenemos implementado el software es preciso probarlo, para detectar errores de codificación, de diseño o de especificación. Las pruebas son necesarias para encontrar el mayor número posible de errores antes de entregar el programa al cliente. Es necesario probar cada uno de los componentes por separado (cada uno de los módulos o programas) para comprobar el rendimiento funcional de cada una de estas unidades. A continuación se procede a integrar los componentes para probar toda la arquitectura del software, y probar su funcionamiento y las interfaces. En este punto hay que comprobar si se cumplen todos los requisitos de la especificación. Se puede desarrollar un plan y procedimiento de pruebas y guardar información sobre los casos de pruebas y los resultados de las mismas.

234

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

3.1 Garantía de calidad. Una vez terminada la fase de pruebas, el software está casi preparado para ser entregado al cliente. 4. Mantenimiento. La fase de mantenimiento se centra en los cambios que va a sufrir el software a lo largo de su vida útil. Como ya hemos dicho, estos cambio pueden deberse a la corrección de errores, a cambios en el entorno inmediato del software o a cambios en los requisitos del cliente, dirigidos normalmente a ampliar el sistema. La fase de mantenimiento vuelve a aplicar los pasos de las fases de definición y de desarrollo, pero en el contexto de un software ya existente y en funcionamiento.

El proceso de diseño
El diseño es el proceso de aplicar varias técnicas y principios con el propósito de definir un dispositivo, un proceso o un sistema con suficiente detalle como para permitir su realización física. Los conceptos del diseño proporcionan criterios básicos para su calidad, es decir proporcionan la estructura básica necesaria para hacerlo bien. • Abstracción: Durante el análisis de los requisitos del software, la solución software se establece en términos que sean familiares en el entorno del problema. A medida que nos movemos a través del proceso de diseño, se reduce el nivel de abstracción, finalmente se alcanza el nivel inferior de abstracción cuando se construye el código. Refinamiento: Proporciona un mecanismo para representar capas sucesivas de detalles funcionales. Ayuda al diseñador a revelar detalles de bajo nivel a medida que progresa el diseño. Modularidad: Permite al diseñador a simplificar y reutilizar componentes del software. La arquitectura del software conlleva modularidad, es decir, se divide el software en componentes identificables y tratables por separado, denominados módulos, que están integrados para satisfacer los requerimientos del programa.

Etapas del diseño de sistemas
El diseño de sistemas consta de cuatro etapas: 1. El diseño de los datos. Trasforma el modelo de dominio de la información, creado durante el análisis, en las estructuras de datos necesarios para implementar el Software. 2. El diseño arquitectónico. Define la relación entre cada uno de los elementos estructurales del programa. 3. El diseño de la interfaz. Describe como se comunica el software consigo mismo, con los sistemas que operan junto con el y con los operadores y usuarios que lo emplean. 4. El diseño de procedimientos. Transforma elementos estructurales de la arquitectura del programa. La importancia del diseño del software se puede definir en una sola palabra: Calidad. Dentro del diseño es donde se fomenta la calidad del Proyecto. El diseño es la única manera de materializar con precisión los requerimientos del cliente.

235

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

El proceso de diseño es un conjunto de pasos repetitivos que permiten al diseñador describir todos los aspectos del sistema a construir. A lo largo del diseño se evalúa la calidad del desarrollo del proyecto con un conjunto de revisiones técnicas: • El diseño debe implementar todos los requisitos explícitos contenidos en el modelo de análisis y debe acumular todos los requisitos implícitos que desea el cliente. Debe ser una guía que puedan leer y entender los que construyan el código y los que prueban y mantienen el software. • El diseño debe proporcionar una completa idea de lo que es el software, enfocando los dominios de datos, funcional y comportamiento desde el punto de vista de la Implementación. Para evaluar la calidad de una presentación del diseño, se deben establecer criterios técnicos para un buen diseño como son: • Un diseño debe presentar una organización jerárquica que haga un uso inteligente del control entre los componentes del software. • El diseño debe ser modular, es decir, se debe hacer una partición lógica del software en elementos que realicen funciones y subfunciones especificas. • • • • Un diseño debe contener abstracciones de datos y procedimientos. Debe producir módulos que presenten características de funcionamiento independiente. Debe conducir a interfaces que reduzcan la complejidad de las conexiones entre los módulos y el entorno exterior. Debe producir un diseño usando un método que pudiera repetirse según la información obtenida durante el análisis de requisitos de Software.

Estos criterios no se consiguen por casualidad. El proceso de diseño del software exige buena calidad a través de la aplicación de principios fundamentales de diseño, metodología sistemática y una revisión exhaustiva. Cuando se va a diseñar un sistema de cómputo se debe tener presente que el proceso de un diseño incluye, concebir y planear algo en la mente, así como hacer un dibujo o modelo o croquis.

236

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

7.3

Arquitectura de software

La arquitectura de un programa o sistema de cómputo es la estructura o estructuras del sistema, y se conforma de sus componentes de software, las propiedades externamente visibles de los componentes y las relaciones entre ellos. La arquitectura de software es un nivel de diseño que va más allá de los algoritmos y las estructuras de datos: el diseño y la especificación de la estructura del sistema como un todo emerge como un nuevo problema. Los elementos estructurales incluyen la organización y el control global, los protocolos de comunicación, la distribución física, la composición de elementos de diseño, la escalabilidad y el rendimiento, y la elección entre distintas alternativas de diseño.

Figura 7.3 Visiones de un sistema de software

La arquitectura de software es: • • • • • Un diseño de alto nivel. La estructura del sistema. Las componentes de un programa o sistema, sus relaciones, y principios que gobiernan su diseño y su evolución en el tiempo. Componentes y conectores. Componentes, conectores, configuración y restricciones.

Su importancia radica en ofrecer: • • • • • • • • • • comunicación entre las personas involucradas, documentación temprana de las decisiones de diseño, restricción de la implementación, la arquitectura dicta la estructura organizacional, facilita o inhibe propiedades del sistema, permitir predecir cualidades del sistema, facilitar la administración de la evolución, dar una abstracción transferible del sistema, las líneas de productos comparten arquitectura, servir como base para el entrenamiento de nuevo personal.

237

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

La arquitectura de software es un conjunto de conceptos y decisiones de diseño relativas a la estructura y textura del software, que deben hacerse antes de la ingeniería, para asegurar la satisfacción efectiva de los requerimientos de calidad y de funcionalidad significativos, así como los requerimientos implícitos de la familia, el problema y los dominios de la solución (figura 7.4). Al crear arquitecturas de software, nos referimos a:

meta-arquitecturas: la visión arquitectónica, estilo, principios, mecanismo clave de comunicación y control , y conceptos que guían al equipo de arquitectos en la creación de la arquitectura. vistas arquitectónicas: tal como las arquitecturas de edificaciones son mejor visualizadas en términos de algunas vistas o modelos complementarios, para igual en las arquitecturas de software. En particular, las vistas estructurales ayudan a documentar y comunicar la arquitectura en términos de los componentes y sus relaciones. Las vistas de comportamiento son útiles al pensar cómo interactuaran los componentes para desempeñar sus responsabilidades y evaluar el impacto de escenarios "que tal si.." (what-if) en la arquitectura. Los modelos de comportamiento son especialmente útiles al revisar características de tiempo de ejecución, como el desempeño y la seguridad. Las vistas de ejecución ayudan al evaluar opciones físicas de distribución y documentar y comunicar decisiones. patrones arquitectónicos: patrones estructurales tales como capas y cliente/servidor, y mecanismos como brokers y puentes.
principios de diseño arquitectónico claves, como la abstracción, separación de responsabilidades, posponer decisiones, y simplicidad, y técnicas relacionadas como el ocultamiento de interfases y encapsulamiento. principios de descomposición de sistemas y un buen diseño de interfaces.

• •

La arquitectura de software debe distinguirse del diseño de bajo nivel (p.ej. el diseño de los algoritmos y partes internas de los componentes) y la implementación.

7.3.1 Importancia de la arquitectura de software
Puede decirse que la importancia de la arquitectura de software radica en tres razones: 1. Comunicación mutua. La arquitectura de software representa una abstracción común de alto nivel del sistema, para que la mayoría de los involucrados tengan un mutuo entendimiento y puedan comunicarse entre sí. 2. Decisiones tempranas de diseño. La arquitectura de software es la representación de las primeras decisiones de diseño del sistema, que pueden repercutir en su desarrollo, implantación y mantenimiento. Estas decisiones tempranas son las más difíciles de tomar atinadamente, son las más difíciles de cambiar, y tienen los efectos más duraderos, algunos de los cuales son: a. La arquitectura provee a los constructores las restricciones de la implementación b. La arquitectura dicta la estructura organizacional para los proyectos de desarrollo y mantenimiento c. Una arquitectura permite alcanzar los atributos de calidad esperados del sistema d. Es posible predecir ciertas cualidades del sistema al estudiar su arquitectura (por medio de métodos de análisis como el Software Architecture Analysis Method (SAAM))

238

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

e. La arquitectura puede ser la base para el entrenamiento y capacitación f. Una arquitectura ayuda a razonar sobre la administración del cambio 3. Abstracción transferible del sistema. La arquitectura de software integra un modelo relativamente pequeño, de como está estructurado el sistema y como trabajan sus componentes entre sí; esto permite transferir el modelo a otros sistemas con comportamientos o requerimientos similares, y con esto se promueve el reuso a gran escala. La arquitectura sirve para los siguientes propósitos: a. Técnicos: • encontrar requerimientos del sistema y objetivos: Los requerimientos funcionales y no funcionales pueden priorizarse como "debe estar" vs. "muy deseable" vs. deseable • permitir una distribución flexible del sistema: Una buena arquitectura permite al sistema y sus partes ser distribuidas en otros procesadores en varias formas sin tener que rediseñar las partes distribuibles. • reducir el costo del mantenimiento y la evolución: La arquitectura puede ayudar a minimizar los costos al anticipar los principales cambios que puede sufrir el sistema, asegurando que el diseño facilite dichos cambios y localizando los efectos en los documentos de diseño, código y otros productos del sistema. • incrementa el reuso e integración con software de terceros y de legado: Una arquitectura puede ser diseñada para permitir y facilitar el reuso de ciertos componentes existentes, frameworks, librerías de clase, y otras aplicaciones. b. Organizacionales: • comunicar el diseño de alto nivel: esto incluye a gerentes, equipos de trabajo de otras áreas (ventas, calidad, capacitación) y clientes. • proveer el contexto del sistema: Los desarrolladores (y encargados del mantenimiento) necesitan entender el sistema de manera global. • asignación del trabajo: Al contar con una separación clara de los subsistemas y una especificación de las interfaces, es posible distribuir el trabajo de manera efectiva, lo que permite que el trabajo de desarrollo se realice en paralelo, que puede ser integrado independientemente en puntos y momentos bien definidos. Una arquitectura ayuda a los usuarios a razonar y administrar el cambio (cerca del 80% del esfuerzo en sistemas ocurre después de implantarlos). La arquitectura divide el cambio en tres clases: • • • local: modificar un solo componente no-local: modificar varios componentes arquitectónico: modificar el grueso de la topología, comunicaciones y mecanismos de coordinación del sistema.

7.3.2 El diseño de la arquitectura⊕
Las descripciones de la arquitectura han sido reconocidas como un ingrediente esencial de un sistema bien diseñado. Estas descripciones tienden a ser informales e idiosincrásicas, consistentes de diagramas de cajas y líneas que pueden describir la estructura básica del sistema, junto con textos descriptivos que explican el significado de los símbolos. Sin embargo,

Obras consultadas: [7.58]

239

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

sirven como un componente clave en el desarrollo de la mayoría de los sistemas estableciendo un punto de partida crítico para determinar si un sistema puede cumplir sus requerimientos básicos y guiando a los desarrolladores en la construcción del sistema.

Figura 7.4 La definición de la arquitectura está entre el análisis del sistema y su diseño.
El diseño de la arquitectura de un sistema de software tiene que ver con su estructura general y las formas en que la estructura lleva a la satisfacción de las propiedades clave del sistema. En la práctica, el diseño de la arquitectura satisface 2 roles primarios: • El diseño de la arquitectura provee un nivel de abstracción del diseño en el que los diseñadores de sistemas de software pueden razonar sobre el comportamiento global del sistema: funcionamiento, rendimiento, etc. Así, sin entrar en detalles de implementación, una buena descripción de la arquitectura hace al sistema "intelectualmente rastreable", exponiendo las propiedades que son cruciales para su éxito. De esta manera, un diseño de arquitectura es un documento técnico clave para determinar si un nuevo sistema propuesto cumplirá sus requerimientos. El diseño de la arquitectura sirve como la “conciencia” para el sistema mientras evoluciona en el tiempo. Al caracterizar las hipótesis cruciales del diseño del sistema, un buen diseño sirve de guía para el proceso de mejora del sistema, indicando que aspectos del sistema pueden ser fácilmente modificados sin comprometer la integridad del sistema.

Además una arquitectura bien documentada ayuda no solo al diseñar, sino durante todo el ciclo de vida del sistema. Para satisfacer sus objetivos, una descripción de la arquitectura debe ser lo suficientemente simple para permitir el razonamiento y predicción a nivel del sistema. En la práctica, esto limita las descripciones de la arquitectura a un nivel de detalle que puede abarcar una o dos páginas. Por lo tanto, para representar diseños de arquitecturas, las descripciones son por lo general jerárquicas: los elementos atómicos de la arquitectura en un nivel de abstracción son descritos con una arquitectura más detallada a bajo nivel. Las descripciones arquitectónicas tratan los siguientes aspectos: • Estructura del sistema. Las descripciones de la arquitectura caracterizan la estructura de un sistema en términos de elementos computacionales de alto nivel y sus interacciones. Es decir que la arquitectura tiene que ver con la naturaleza de la solución de un problema, como la configuración de componentes que interactúan. No es

240

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

específicamente una representación de requerimientos (p.ej. relaciones abstractas entre elementos de un problema), ni detalles de la implementación (p.ej. algoritmos y estructuras de datos). Abstracciones para la interacción. Las interacciones entre los componentes arquitectónicos – por lo general expresadas como líneas conectoras – reflejan un rico vocabulario para los diseñadores de sistemas. Aunque las interacciones puedan ser tan simples como llamados a procedimientos o variables compartidas, por lo general representan formas más complejas de comunicación y coordinación (p.ej. interacciones cliente-servidor (con reglas sobre la inicialización, finalización y manejo de excepciones), conexiones de transmisión de eventos (con múltiples receptores), y protocolos de acceso a bases de datos (con protocolos para la invocación de transacciones)). Propiedades globales. Puesto que el uso principal de un diseño arquitectónico es razonar sobre el comportamiento global del sistema, los diseños arquitectónicos se relacionan típicamente con todo el sistema. Los problemas que surgen de una arquitectura son aquellos a nivel del sistema, como latencia y lapsos de los datos de un punto a otro, consecuencias de la falla de una parte del sistema y su impacto en otras partes, o la propagación de cambios en el sistema cuando una parte de este es modificada (p.ej. cambiar la plataforma en la que se ejecuta el sistema).

7.3.3 Elementos de una arquitectura de software
Los principales elementos de una Arquitectura de Software son: • componentes - lugar de almacenamiento o cómputo: • procesos, programas, objetos, funciones, librerías, unidades de compilación, filtros, bases de datos • conectores - mediadores entre componentes: • llamadas a procedimientos, invocaciones, llamadas, flujos de datos, pipes, broadcast. • propiedades - información para construcción y análisis: • pre/post condiciones, invariantes.

Figura 7.5 Descomposición de elementos de diseño

241

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Las propiedades de los componentes son asunciones que un componente puede hacer de otro. Estas propiedades incluyen: • Servicios provistos (funcionalidad) • • • • Servicios requeridos Características de desempeño Manejo de errores Uso de recursos compartidos

Las relaciones son más genéricas que los conectores. Las relaciones pueden ser: • • Dinámicas o a tiempo de ejecución (conectores) • enviar dato(s) a; invocar; señales Estáticas • es un submódulo de; encapsula información; hereda de

Vistas (estructuras)

Una arquitectura de software debe ser descrita por diversas vistas (relacionadas), también llamadas estructuras.

242

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Tipo de estructura Estructura de módulos

Descomposición •Componentes: módulos, asignaciones de trabajo •Relaciones: “es un submódulo de” , “comparte un secreto con” •Uso: como base de la estructura de equipo y alojamiento de recursos •Atributos: mantenimiento, comprensión •Componentes: tareas, procesos •Relaciones: “se sincroniza con”, “excluye”, “preempts” •Uso: afinar el desempeño del sistema a tiempo de ejecución, explotar el hardware de multiprocesamiento •Atributos: desempeño

Representación gráfica

Estructura de procesos

Estructura de uso

•Componentes: procedimientos •Relaciones: “asume la presencia correcta de” •Uso: para especificar subconjuntos y superconjuntos •Atributos: Reusabilidad, pruebas, desarrollo incremental •Componentes: procedimientos •Relaciones: “invoca” •Uso: para establecer el flujo de control, para depuración •Atributos: construcción, pruebas, mantenimiento, comprensión •Componentes: programas, módulos •Relaciones: “puede enviar datos a” •Uso: para seguimiento de la funcionalidad •Atributos: desempeño, exactitud •Componentes: objetos •Relaciones: “hereda de”, “es instancia de” •Uso: para explotar las similaridades entre objetos •Atributos: tiempo de desarrollo, mantenimiento
NewClass NewClass2
o b je c t 1 o b je c t 2 o b je c tk

Estructura de llamadas

Estructura de flujo de datos

Estructura de clases

NewClass5

NewClass4

NewClass3

Estructura física

•Componentes: tareas, procesos, procesadores •Relaciones: “reside en el mismo procesador” •Uso: administrar la asignación proceso-procesador •Atributos: rendimiento, disponibilidad

Tabla 4. Estructuras de una arquitectura de software

243

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Lo más importante de las estructuras es elegir cuales pueden ser útiles para describir mejor los detalles del sistema.

Figura 7.6 Vistas posibles de un elemento de diseño (lógica, concurrente o de instalación)
Los componentes, sus relaciones y estructuras, conforman una vista que se usa para especificar el sistema, resaltar diversas cualidades del sistema y puede ser usada por varias personas.

El modelo de arquitectura 4+1 vistas⊕
El modelo de 4+1 vistas organiza una descripción de una arquitectura de software usando 5 vistas concurrentes, cada una de las cuales se orienta a describir un conjunto especifico de características. Los arquitectos capturan sus decisiones de diseño en 4 vistas y usan la quinta para ilustrarlas y validarlas. Las vistas del modelo son las siguientes: 1. Vista lógica. Soporta principalmente los requerimientos funcionales; los servicios que el sistema debe proveer a sus usuarios finales. Los diseñadores descomponen el sistema en un conjunto de abstracciones clave, tomadas principalmente del dominio del problema. Estas abstracciones son objetos o clases de objetos que explotan los principios de abstracción, encapsulamiento y herencia. Además de auxiliar al análisis funcional, la descomposición identifica mecanismos y elementos de diseño que son comunes en el sistema. 2. Vista de proceso. Toma en cuenta los requerimientos no funcionales, tales como el rendimiento y disponibilidad del sistema. Se enfoca a la concurrencia y distribución, integridad del sistema y tolerancia a fallas. Esta vista también especifica que hilo de control ejecuta cada operación de cada clase identificada en la vista lógica. 3. Vista física. Toma en cuenta los requerimientos no funcionales del sistema como la disponibilidad del sistema, tolerancia a fallas, desempeño y escalabilidad. El software se ejecuta en una red de computadoras (nodos de procesamiento). Los diversos elementos identificados en las vistas lógicas, de procesos y desarrollo, como redes, procesos, tareas y

Obras consultadas: [7.57]

244

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

objetos, deben mapearse en los diversos nodos. Muchas configuraciones físicas serán usadas en el desarrollo, prueba e implantación. 4. Vista de desarrollo. Se enfoca a la organización de los módulos de software en el ambiente de desarrollo. El software es empacado en librerías o subsistemas que pueden ser desarrollados por uno o más desarrolladores. Los subsistemas son organizados en capas jerárquicas, y cada una provee una interfaz bien definida con las capas superiores. 5. Vista de escenarios. Consiste de un subconjunto de escenarios importantes de casos de uso, para mostrar que los elementos de las 4 vistas trabajan conjuntamente. Para cada escenario se describe el correspondiente guión (secuencias de interacciones entre objetos y entre procesos). Esta vista es redundante, pero tiene dos roles importantes: • actúa como manejador para ayudar a los diseñadores a descubrir elementos arquitectónicos durante el diseño de la arquitectura; • valida e ilustra el diseño de la arquitectura, y es el punto de inicio para las pruebas de un prototipo arquitectónico.

Vista de la arquitectura por capas
La vista por capas de una arquitectura, que se muestra mediante un diagrama de capas, es una de las vistas comúnmente usadas en la arquitectura de software. Las capas, como todas las estructuras arquitectónicas, reflejan una división del software en unidades. En este caso, las unidades son capas; cada capa representa una máquina virtual. Una máquina virtual es una colección de software que en conjunto provee un servicio que otro software puede utilizar sin conocimiento de como esos servicios están implementados. Las capas tienen una propiedad fundamental: las máquinas virtuales son creadas para interactuar entre si de acuerdo a una relación estricta de orden. Si (A,B) está en esta relación, se dice que la capa B está bajo la capa A, lo que puede significar: 1. La capa de implementación A está autorizada para usar cualquier facilidad pública de la máquina virtual provista por la capa B. 2. Las facilidades públicas en la capa B pueden ser usadas por el software de la capa A. Una relación entre capas se representa como:

Lo que puede interpretarse como que la capa A está autorizada para usar la capa B:

245

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Un diagrama de capas debe estar acompañado de la siguiente documentación: • Referencia (key). Una explicación de como las relaciones se llevan a cabo en la figura. En particular se debe responder a las siguientes preguntas: • ¿Se permite a una capa usar solo la capa inferior, cualquier capa inferior, o alguna otra? • • • ¿Al software se le permite usar otro software en la misma capa? ¿Los tamaños relativos de las capas son significativos? El color se usa por lo general para dar significado a ciertas capas. Si es así, una clave debe ser incluida para explicar el significado del color. • Debe aclararse que ningún mensaje ascendente es asumido a menos que sea explícitamente descrito. Interfaces de capas. Un documento que muestre que elementos constituyen la interfaz pública de cada capa. Puesto que las capas consisten de software publico y privado, la implementación en las capas superiores debe saber que facilidades están disponibles en la capa inferior. La interfaz de capa consiste de todas las interfaces públicas para las unidades de software que contiene. Catálogo de capas. Un documento que asigna cada unidad de software a exactamente una capa. Los diagramas de capas etiquetan a las capas con nombres descriptivos (pero vagos) como "capa de comunicación en redes" o "capa de reglas de negocio", pero un catálogo es necesario para listar el contenido completo de cada capa. Guía de portabilidad de la capa. Es un documento que describe los cambios que pueden ser hechos a cada capa, sin afectar a otras capas. Excepciones. Es un documento que explica las excepciones, si las hay, de las reglas de uso implicadas en la distribución. Estas pueden ser ascendentes o descendentes.

• •

Estilos arquitectónicos
Como en cualquier actividad de diseño, una pregunta central es cómo aprovechar la experiencia del pasado para producir mejores diseños. En la práctica actual, la codificación y reuso de diseños arquitectónicos ha ocurrido principalmente por medio de la transmisión informal de idiomas arquitectónicos. Por ejemplo, un sistema puede ser definido arquitectónicamente como un "sistema cliente-servidor", un "sistema de pizarrón", una "tubería" (pipeline), un "interprete" o un "sistema de capas". Mientras estas caracterizaciones no siempre cuentan con definiciones formales, si nos dan mucha idea sobre la estructura y el modelo computacional del sistema. Una clase importante de idiomas arquitectónicos son los llamados estilos arquitectónicos. Un estilo arquitectónico caracteriza a una familia de sistemas que se relacionan por compartir propiedades estructurales y semánticas. Específicamente, los estilos proveen 4 cosas: 1. Un vocabulario de elementos de diseño – componentes y tipos de conectores como tuberías (pipes), filtros, clientes, servidores, parsers, bases de datos, etc. 2. Reglas de diseño – o restricciones – que determinan la composición permitida de los elementos. Por ejemplo, las reglas deben prohibir ciclos en un estilo particular de filtrotubería, especificando que una organización cliente-servidor debe ser una relación de N a 1, o definir un patrón de composición específico. 3. Interpretación semántica, donde composiciones de elementos de diseño, se restringen por reglas de diseño con significados bien definidos.

246

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

4. Análisis que pueden realizarse en sistemas construidos con dicho estilo. Algunos ejemplos incluyen el análisis de planificación para estilos orientados al procesamiento en tiempo real y detección de bloqueos para el paso de mensajes cliente-servidor. Un caso especial de análisis es la generación de sistemas: muchos estilos soportan generadores de aplicaciones (p.ej. generadores de parsers), o llevan al reuso de ciertas implementaciones de base compartidas (p.ej. frameworks de interfaces de usuario o soporte para comunicaciones entre procesos distribuidos). Un estilo arquitectónico es una descripción de tipos de componentes y un patrón de su control y/o transferencia de datos a tiempo de ejecución. Un estilo se describe a partir de: • • • • Un conjunto de tipos de componentes (p.ej. repositorio de datos, proceso, objeto). Un marco de la topología de estos componentes. Un conjunto de restricciones semánticas (p.ej., a un repositorio de datos no se le permite cambiar los valores almacenados). Un conjunto de mecanismos de interacción (p.ej., llamada a subrutinas, eventos, tuberías (pipes)).

Figura 7.7 Algunos tipos de estilos arquitectónicos
El uso de estilos arquitectónicos tiene varios beneficios: • Promueve el reuso en el diseño: soluciones rutinarias con propiedades bien entendidas pueden ser reaplicadas a nuevos problemas con toda confianza. • Lleva al reuso significativo de código: comúnmente los aspectos invariantes de un estilo arquitectónico llevan a implementaciones compartidas. Por ejemplo, los sistemas descritos en un estilo tubería-filtro (pipe-filter) deben reusar primitivas del sistema operativo UNIX para encargarse de la planificación de tareas, sincronización y comunicación por medio de tuberías. De forma similar un estilo cliente-servidor puede tomar ventaja de los mecanismos RPC existentes y capacidades de generación de stubs. • Es más fácil que otros comprendan la organización del sistema si se usan estructuras basadas en convenciones. Por ejemplo, incluso sin dar muchos detalles, la caracterización de un sistema como un a organización "cliente-servidor" de inmediato establece una imagen de los tipos de piezas a usar y sus relaciones.

247

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Usar estilos estandarizados apoya la interoperabilidad. Ejemplos de esto son las arquitecturas orientadas a objetos de CORBA, los protocolos OSI, y la integración de herramientas basadas en eventos. Al delimitar el espacio de diseño, un estilo arquitectónico permite análisis especializados específicos para el estilo. Por ejemplo, es posible analizar sistemas construidos con un estilo de tuberías-filtro con respecto a su rendimiento, latencia y libertad de bloqueos. Tales análisis pueden no ser significativos para otras arquitecturas. En particular, algunos estilos hacen posible generar código directamente de una descripción arquitectónica. Usualmente es posible (y deseable) proveer descripciones gráficas de los elementos de diseño de un estilo específico. Esto permite a los ingenieros de dominio específico visualizar sus diseños.

7.3.4 Patrones arquitectónicos⊕
Un patrón es una solución existente a un problema recurrente en contexto.
Sin embargo no hay una definición universalmente aceptada, aunque los patrones tienen 4 elementos fundamentales: 1. Un nombre. Nombrar un patrón incrementa nuestro vocabulario de diseño y facilita el diseño a niveles altos de abstracción. También hace más fácil comunicar diseños a otros. 2. Un problema. Una explicación del problema y su contexto. Para que la solución de un problema de nacimiento a un patrón, el problema (y su contexto) deben plasmarse en más de un esfuerzo de diseño. 3. Una solución. El patrón provee una descripción abstracta de un problema de diseño y cómo un arreglo general de elementos (clases y objetos) lo solucionan. 4. Consecuencias. Una discusión de los resultados y por menores de aplicar el patrón. Fundamentalmente existen tres tipos de patrones: • Un patrón arquitectónico expresa una organización estructural fundamental o esquema para sistemas de software. Provee un conjunto de sistemas predefinidos, especifica sus responsabilidades, e incluye reglas y guías para organizar las relaciones entre ellos. • Un patrón de diseño provee un esquema para refinar los subsistemas o componentes de un sistema de software, o las relaciones entre ellos. Describe la estructura de comunicación de los componentes que solucionan un problema de diseño general en un contexto particular. • Un idioma es un patrón de bajo nivel específico a un lenguaje de programación. Un idioma describe como implementar los aspectos particulares de componentes o relaciones entre ellos usando las capacidades ofrecidas por un lenguaje dado. Los patrones arquitectónicos pueden subdividirse en 4 categorías de acuerdo a sus propiedades: • Estructurales • Capas (layers), tuberías y filtros (pipes & filtres), pizarrón (blackboard)

Obras consultadas: [7.59] [7.60] [7.61]

248

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• •

Sistemas distribuidos • Broker, tuberías y filtros, microkernel Sistemas interactivos • Modelo-Vista-Controlador (Model-View-Controller), Presentación-AbstracciónControl (Presentation-Abstraction-Control) Sistemas adaptables • Reflexión, Microkernel

A continuación se presentan algunos patrones relevantes para el diseño de la arquitectura de un sistema operativo.

El patrón Layers⊕
El patrón Layers (capas) estructura el sistema en grupos de subtareas que trabajan en un nivel particular de abstracción. Beneficios: • • • • Ejemplos: • • Reuso de capas Soporta la estandarización Las dependencias se mantienen locales Intercambio OSI Conjunto de protocolos de Internet

En el mundo real por lo general se usa una mezcla de criterios de abstracción para agrupar tareas en capas. Por ejemplo, la distancia del hardware puede darle forma a los niveles más bajos, y complejidad conceptual a los más altos. Un ejemplo de capas es el siguiente: • • • • • • Elementos visibles al usuario Módulos específicos de aplicación Nivel de servicios común Nivel de interfaz del sistema operativo Sistema operativo (siendo un sistema en capas en sí mismo, o estructurado de acuerdo al patrón microkernel) Hardware

El patrón Microkernel
El patrón Microkernel aplica a los sistemas de software que deben ser capaces de adaptarse a requerimientos del sistema variables. Separa un núcleo mínimo de funcionalidad de la funcionalidad extendida y partes específicas del consumidor. El microkernel también sirve como un enchufe para conectar estas extensiones y coordinar su colaboración.

Obras consultadas: [7.62]

249

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Exte rnal Server +calls rece ive R equ es t() dis p atchR e que s t() 1..* execute Se rvic e()

Mi cr o ke r n el Internal Serve r in itC om m u nicatio n() fin dR ec eiver() 1 e xe cuteMe chan is m () ca llInternalServe r() +a ctiva tes

1

1..*

r eceiveR eq u e s t() execu teService()

1

+initia lize s com m unica tion Adap tor C l ie nt or App li cation +s e nds requ es t callService() crea teR eq ues t() +calls s ervice

Figura 7.8 Diagrama de clase del patrón microkernel33
Las responsabilidades de un Microkernel son: • • • • Proveer mecanismos de base (core mechanisms). Ofrecer facilidades de comunicación Encapsular dependencias del sistema Administrar y controlar recursos

Dentro del patrón se encuentran los siguientes Colaboradores: - Servidor interno (Internal server). Sus responsabilidades son: • Implementar servicios adicionales • Encapsular algunas características especificas del sistema Colaboradores: Microkernel. - Servidor externo (External server). Sus responsabilidades son: • Proveer interfases de programación a sus clientes Colaboradores: Microkernel. - Adaptador (Adaptor). Sus responsabilidades son: • Esconde las dependencias del sistema tales como facilidades de comunicación desde el cliente • Invoca métodos de los servidores externos en beneficio de los clientes Colaboradores: External server, Microkernel. - Cliente o Aplicación (Client or Application). Sus responsabilidades son:

33

Imagen reproducida de [7.59]

250

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• Representa una aplicación Colaboradores: Adaptador.

El patrón Broker
El patrón Broker puede usarse para estructurar sistemas de software distribuidos con componentes desacoplados que interactúan mediante invocaciones a servicios remotos. Un componente del broker es responsable de coordinar la comunicación, así como de transmitir resultados y excepciones. Un broker coordina la comunicación entre los sistemas de software distribuido para permitir el uso remoto de servicios. Beneficios: • • • • • Ejemplos: • • • • Transparencia en la localización Independencia del sistema Interoperabilidad y portabilidad Modificabilidad y reusabilidad Configuración a tiempo de ejecución CORBA (Common Object Request Broker Architecture) [OMG] OLE / ActiveX [Microsoft] SOM/DSOM [IBM] WWW

7.3.5 Desarrollo basado en la arquitectura
¿Cuáles son las actividades involucradas en el desarrollo de software al tomar un enfoque basado en la arquitectura? Desde una visión de alto nivel, se incluyen las siguientes además de las actividades convencionales de diseño, programación y pruebas en proyectos de desarrollo a pequeña escala: • • • • • • comprensión de los requerimientos de dominio desarrollo o selección de la arquitectura representación y comunicación de la arquitectura análisis o evaluación de la arquitectura implementación del sistema basado en la arquitectura aseguramiento de que la implementación conforma la arquitectura

Las siguientes actividades han sido reconocidas como parte del proceso de diseño basado en la arquitectura: • • • crear los casos de negocio para el sistema comprender los requerimientos crear o seleccionar la arquitectura

251

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• • • •

representar y comunicar la arquitectura analizar o evaluar la arquitectura implementar el sistema basado en la arquitectura asegurarse de que la aplicación cumple con los lineamientos de la arquitectura

7.4 Diseño sistemas operativos: enfoque orientado a la arquitectura
Curiosamente la inmensa mayoría de los documentos relacionados al diseño de sistemas operativos, se refieren a las consideraciones de bajo nivel (implementación). Ciertamente hay quién estará encantado de contar con esta miríada de detalles sobre el hardware, las herramientas de desarrollo, las especificaciones del funcionamiento de periféricos, etc., pero en realidad se habla muy poco de como llegar a este punto. Necesariamente como se ha comentado en este capítulo, debe hacerse un trabajo previo a la codificación del sistema. En esta sección, el objetivo es plantear algunas consideraciones de diseño desde el enfoque de la arquitectura de software.

7.4.1 Preguntas importantes: en busca de requerimientos
Hay algunas preguntas que responder antes de empezar a codificar un SO. No es un secreto que todo programa debe ser diseñado antes de ser implementado; y tampoco es un secreto que pocos programas son desarrollados de esta manera. La mayoría están escritos bajo presión y difícilmente cumplen con una lista de requerimientos completa antes de comenzar a codificar. Este escenario es difícil y poco productivo. El diseño se termina en los descansos durante la codificación y está delimitado por cosas ya implementadas y que funcionan. Los programadores tienden a pensar "lo cambio después", y esto casi nunca pasa. Nadie quiere modificar el código de la aplicación para ajustarlo al diseño. Implementar un SO es difícil, porque un diseño incompleto puede consumir más recursos; sin embargo, sin un diseño es difícil orientar un proyecto de esta naturaleza, y su control de vuelve extremadamente complejo. A continuación se plantean algunas preguntas que, aunque no conforman una especificación completa de diseño, delimitan la codificación del sistema. La idea es contestar todas las preguntas antes de iniciar a codificar (aunque algunas pueden ignorarse si son irrelevantes): 1. • • ¿Cuál es el objetivo primario del sistema operativo? ¿Es un sistema estándar de escritorio de bajo perfil? El usuario es principiante; la prioridad más alta es la compatibilidad de hardware/software. ¿Es un sistema estándar de escritorio de alto perfil? El usuario es un ingeniero en CAD/CAM; la prioridad más alta es en el desempeño y cierta compatibilidad hardware/software.

252

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

2. • • • • •

¿Es un sistema orientado a tiempo real? El usuario es un programador profesional; la prioridad más alta es el rendimiento, tiempo de respuesta definido, soporte de hardware fácilmente extendible y control programable. ¿Qué plataformas va a soportar el sistema operativo? ¿Cuál es la plataforma objetivo? (Hand-held, PC, sistema incrustado) ¿El sistema va a ser multiplataforma? ¿Se montará el sistema sobre otro sistema operativo? ¿Va a soportar multiprocesamiento? ¿Qué tipo de plataforma de mutiprocesamiento ¿Simétrica? (todos los procesadores son exactamente el mismo). ¿Asimétrica? (los CPUs pueden estar en diferentes arquitecturas y tener diferente potencia de cómputo). ¿Ambos? ¿Soportará solo multiprocesamiento local? (todos los CPUs están conectados por medio de un bus local). ¿Multiprocesamiento distribuido? (los CPUs están conectados mediante una red) ¿Ambos? ¿Cuál es el sistema de hardware objetivo? ¿PC? ¿hay hardware estándar disponible en el mercado? ¿Será un sistema operativo multitarea? ¿Qué tipo de multitarea proveerá a las aplicaciones? ¿cooperativa? ¿apropiativa? ¿Es necesario proteger a las tareas entre sí? ¿Cuál es la relación entre las tareas en términos del espacio donde conviven? ¿comparten el mismo espacio de direcciones, es separado, o ambos? ¿Cómo se comunican las tareas entre sí? ¿Es necesario proteger al sistema de las tareas de las aplicaciones? ¿Qué sistema de archivos usará el SO? ¿Debe favorecerse el tiempo de acceso (rendimiento) o un espacio de almacenamiento reducido (espacio)? ¿Es posible usar alguno de los sistemas de archivos ya creados y documentados? ¿Es posible usar una versión reducida de un sistema de archivos ya existente? ¿Cuál será el formato de archivo ejecutable? ¿Qué herramientas de construcción se requerirán? ¿Dónde se codificará el sistema operativo? ¿en qué máquina? ¿con qué SO instalado? ¿Pueden usarse compiladores y ligadores existentes? ¿Se puede obtener el código fuente de compiladores y ligadores? ¿Deben desarrollarse herramientas propias? ¿Las herramientas son gratuitas o hay que pagar por ellas? ¿Cuánto? ¿Que garantía/soporte existe? ¿Cómo puede soportarse fácilmente software de terceros? ¿Es posible soportar software existente (y popular)? ¿Cómo se puede soportar la creación sencilla de aplicaciones de terceros en el nuevo sistema operativo? ¿Cómo soportar la creación de manejadores de dispositivos de terceros? ¿Cómo puede usarse código e información preexistente? ¿Es posible usar código escrito por otros y que funcione (inclusive parcialmente)? ¿Existen proyectos similares? ¿Dónde puede conseguirse documentación, ayuda o asesoría?

• 3. • • • • • 4. • • • • 5. • • • • • 6. • • • 7. • • •

253

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

¿Cómo se organizará la documentación del proyecto?

7.4.2 Metas del diseño
Siempre es importante establecer lo que se supone que el sistema operativo va a hacer. Esto puede descomponerse en tres tareas: 1. Abstracción del hardware. Es el proceso de simplificación y ocultamiento de información. La cuestión aquí es tomar la complejidad del hardware y ajustarla en un conjunto de interfaces simples y bien definidas. Por ejemplo, un disco puede verse como una colección de bloques, donde los datos pueden ser escritos en estos bloques. En la realidad el disco debe ser accesado mediante el complejo protocolo SCSI, mediante un adaptador de bus SCSI, mediante el bus PCI. Pero si una aplicación escribe en el disco, todo esto será transparente. Hay 2 razones por las que la abstracción del hardware es importante: simplicidad y compatibilidad. La idea es que el sistema operativo provea una interfaz simple a la aplicación y haga el trabajo rudo. Con respecto a la compatibilidad, muchos SOs de propósito general permiten el uso de una gran variedad de hardware, y aunque sería deseable que los dispositivos similares hablaran en un mismo idioma, esto no siempre es cierto. Alguna parte del sistema necesita saber que tipo de dispositivo se tiene y como hablar con dicho dispositivo. Es parte del proceso de abstracción tratar de encontrar una abstracción que sea relativamente simple, y aun así expresar un monto razonable de flexibilidad en el hardware que pueda abstraerse y el uso del hardware. La abstracción necesita formas de lidiar con las fallas si el dispositivo debe ser tolerante a fallas. Todas estas metas pueden hacer de la abstracción una tarea muy difícil que puede realizarse de muchas maneras. 2. Administración de recursos. Los sistemas operativos administran los recursos del sistema de cómputo. Esta es una gran preocupación con la multitarea y en algunos casos sistemas multiusuario. Un "recurso" es un término genérico para referirse a cualquier componente del sistema capaz de hacer un trabajo. Por ejemplo, el procesador, la RAM, los discos, las tarjetas de sonido o de red, son recursos. No todos los recursos son hardware. La administración de recursos es el proceso de asignar recursos a las aplicaciones para su uso. Esto se hace de diversas formas, pero las principales son: • Multiplexado. Consiste en compartir un recurso mediante accesos concurrentes. Esta es una preocupación central en los SO multitarea. Muchos recursos pueden ser multiplexados por diferentes aplicaciones. • Bloqueo. Algunos dispositivos pueden no ser multiplexados (por ejemplo una cinta de respaldo), pero ello implica asegurar que para evitar errores solo una aplicación a la vez pueda acceder al dispositivo en cierto momento. • Control de acceso. A veces la administración de recursos no se involucra en solucionar el problema de que varios procesos accedan al hardware; en cambio si le incumbe proteger a los procesos entre sí. La seguridad se implementa de alguna forma como parte de la administración de recursos. • Máquinas virtuales: Combinando la administración de recursos con la abstracción. Administrar el acceso a los recursos demanda que alguna interfaz sea provista para el recurso, así que en lugar de accesar al hardware directamente una aplicación debe pedirle al SO que acceda al hardware. El resultado de esto es un concepto llamado máquina virtual. A

254

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

cada aplicación en el SO le es dado un ambiente para ejecutarse, y dicho ambiente incluye vistas abstractas del hardware. El ambiente es una máquina virtual, y desde ella el proceso parece tener su propio conjunto de hardware, aunque el hardware este multiplexado sin saberlo. 3. Interfaz de usuario. Una meta importante de un sistema operativo es proveer algún tipo de interfaz a los usuarios para controlar el sistema y ejecutar aplicaciones. Esto lleva al SO lejos de las discusiones puramente técnicas, a cuestiones relacionadas con la interacción del sistema con el usuario. 4. Metas especializadas de diseño. Algo que hay que señalar es que un sistema operativo no lo puede hacer todo. Muchos SO son construidos para propósitos específicos. Algunos casos son: • Sistemas incrustados (embedded). Los SO incrustados son escritos para ambientes donde los recursos son muy limitados, para realizar una tarea específica para un dispositivo específico. Por ejemplo, el SO que ejecuta el software de un teléfono celular es uno de estos sistemas, los cuales deben ser muy pequeños por que sus ambientes pueden tener solo unos cuantos kilobytes de memoria disponible. • Sistemas de tiempo real. Diseñados para ejecutar tareas criticas de tiempo real, donde se garantice que cada tarea cumplirá su labor en un tiempo límite. • Sistemas distribuidos. Estos sistemas se ejecutan en varias máquinas a la vez, y distribuyen tareas entre los nodos. Esta es la forma en que una red se comporta como un solo SO. • Sistemas tolerantes a fallas. La respuesta típica a una falla del procesadores un SO que se estropea y arrastra al usuario con él. Sin embargo, hay sistemas que necesitan estar trabajando sin importar lo que pase. Estos sistemas están diseñados para recuperarse de un problema de hardware y seguir ejecutándose. Estos SOs se escriben con el fin de ocultar a las aplicaciones las fallas de hardware.

7.4.3 Estructura del sistema operativo⊕
Tal vez la primera decisión de diseño importante es ¿qué estructura debe adoptar el sistema? Un diseño monolítico sin estructura no es una buena opción, excepto para un SO muy pequeño (e incluso eso es discutible). Algunas estructuras que pueden ser útiles al diseñar un sistema operativo Estructura de capas. Este es un enfoque usado en sistemas como el THE, UNIX y Windows 2000. Sin embargo este es más una forma de describir el sistema. Para un sistema nuevo, los diseñadores que tomen este camino deben ser cuidadosos al elegir las capas y definir la funcionalidad de cada una. La capa del fondo siempre debe tratar de ocultar los detalles más rudos del hardware (como el HAL-Hardware Abstraction Layer). Tal vez la siguiente capa deba encargarse de las interrupciones, cambios de contexto, y la MMU, para que en los niveles superiores el código sea lo más independiente de la máquina. En los niveles superiores, los diseñadores tienen diferentes tendencias. Una posibilidad es que la capa 3 administre los hilos, incluyendo la planificación y sincronización.

Obras consultadas: [7.23]

255

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 7.9 Vista de capas de la arquitectura de un sistema operativo34
En la capa 4 pueden encontrarse manejadores de dispositivos ejecutándose por separado, con su propio estado, contador de programa, registros, etc., posiblemente en el mismo espacio de direcciones del kernel. Tal diseño puede simplificar la estructura de entrada/salida, lo cual es uno de los principales puntos de complejidad de cualquier SO. Arriba de la capa 4, se puede esperar encontrar la memoria virtual, uno o más sistemas de archivos y los manejadores de llamadas del sistema. Sistemas cliente/servidor. En un diseño de microkernel, la mayor cantidad de código relacionado con la abstracción y la administración de recursos se coloca fuera del kernel para promover la modularidad. La interfaz entre los componentes del sistema se convierte en un esquema de paso de mensajes de la aplicación a los componentes requeridos para dar el servicio. Estos componentes se ejecutan como programas separados en el mismo SO. Estos programas del sistema en el microkernel son llamados servidores, y las aplicaciones son los clientes. Los servidores se ejecutan en el sistema operativo como lo hacen las aplicaciones. El microkernel mismo necesita implementar un control de procesos y el paso de mensajes. Exokernels. Los exokernels toman un enfoque interesante, al tomar gran parte del código fuera del kernel, pero en lugar de colocar el código en programas externos como lo hace el microkernel, lo colocan en librerías compartidas ligadas al código de la aplicación. La aplicación entonces hace peticiones a recursos protegidos solo llamando a las funciones en la librería. Esencialmente el exokernel dejará cualquier código crítico para la seguridad en el kernel, pero las abstracciones se colocan en las librerías. Sistemas extensibles. Este enfoque consiste en poner más módulos en el kernel, de una forma protegida. Un sistema extensible por sí mismo no es una forma de estructurar un SO. Sin embargo, al comenzar con un sistema mínimo consistente de un poco más que un mecanismo de protección y después agregar módulos protegidos al kernel, uno a la vez, hasta alcanzar la funcionalidad deseada, un sistema mínimo puede construirse para la aplicación deseada. Con este enfoque un nuevo sistema operativo puede ajustarse a cada aplicación al incluir solo las partes que se requieran (Paramecium es un ejemplo de este tipo de sistemas).

34

Imagen reproducida de [7.23]

256

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

En el siguiente capítulo se hace una investigación más detallada de las estructuras que los SOs adoptan.

7.4.4 Mecanismos y políticas
Otro principio que apoya la coherencia arquitectónica, además de mantener las cosas pequeñas y bien estructuradas, es el separar los mecanismos de las políticas. Deben tenerse en cuenta los conceptos de política y mecanismo. Un mecanismo determina como hacer algo, mientras que una política decide que se tiene que hacer. Las decisiones políticas son importantes para la asignación de recursos. Al colocar mecanismos en el sistema operativo y dejar la política a los procesos de usuario, el sistema puede dejarse sin modificación, incluso si se necesita cambiar la política. Incluso si el módulo de la política debe ponerse en el kernel, debe aislarse del mecanismo, de ser posible, para que los cambios en el módulo de políticas no afecten al módulo del mecanismo. Algunos ejemplos de esto son los siguientes: • Planificación de hilos. El kernel puede contar con un planificador por prioridad, con n niveles de prioridad. El mecanismo es un arreglo, indexado por nivel de prioridad. Cada elemento es la cabeza de una lista de hilos listos en ese nivel de prioridad. El planificador solo busca en el arreglo de la prioridad más alta a la más baja, seleccionando los primeros hilos que encuentre. La política es establecer las prioridades. El sistema puede tener varios tipos de usuarios, cada uno con diferente prioridad. • Paginación. El mecanismo involucra la administración de la MMU, manteniendo listas de páginas ocupadas y páginas libres, y código para intercambiar páginas con el disco. La política es decidir que hacer cuando ocurre un fallo de página. Este puede ser local o global, basado en LRU o FIFO, pero este algoritmo puede estar completamente separado del mecanismo que de hecho administra las páginas. • Carga de módulos en el kernel. El mecanismo se ocupa de como son insertados, como se ligan, que llamadas pueden hacer, y que llamadas pueden ser hechas en ellos. La política es determinar quién está autorizado para cargar un módulo en el kernel, y qué módulos. Puede que solo un superusuario pueda cargar módulos, pero puede ser que cualquier usuario pueda cargar un módulo que ha sido aprobado apropiadamente. • Protección del CPU. Un mecanismo para asegurar la protección del CPU es el temporizador (timer). La decisión de cuanto tiempo del timer es asignado a un usuario, es una política.

7.5 Diseño de sistemas operativos: el enfoque de los desarrolladores⊕
Cuando se diseña un sistema, siempre buscamos resolver un problema en particular. Los sistemas operativos resuelven una gran variedad de problemas en relación al uso y aprovechamiento de los recursos de hardware de una computadora, y en el camino permite crear

Obras consultadas: [7.1] [7.2] [7.3] [7.4]

257

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

nuevas aplicaciones que aprovechen esta infraestructura. Así que ¿cómo hacer que el SO de a los usuarios la ilusión de contar con recursos infinitos: memoria, CPUs, cómputo distribuido, etc.? La meta de diseñar un SO es hacer a la máquina conveniente de usar (un problema de ingeniería de software) y eficiente (un problema de sistemas e ingeniería). Algunos de los principios más importantes a implementar son: • • • • • • proveer la ilusión de una máquina dedicada con memoria y capacidad de cómputo infinita. proteger a los usuarios de ellos mismos alojar recursos eficiente y justamente proveer comunicaciones seguras y confiables mantener el diseño y la implementación del SO tan simple como sea posible ( esto es la llave para que el SO funcione) tener conciencia del pasado, pues problemas en modelos propuestos con anterioridad pudieran ser resueltos con la tecnología actual

En el camino habrá que tomar decisiones importantes, pues es un hecho que no puede tenerse todo (no hay sistema que implemente lo mejor de toda la teoría). Por ello el diseño deberá sacrificar en su momento: • • • el rendimiento y la conveniencia de las abstracciones del SO el rendimiento y la sencillez del diseño del SO añadir funcionalidad en el hardware o el software

A continuación se presenta una aproximación de diseño común en los desarrolladores (consideraciones y decisiones de bajo nivel).

7.5.1 El enfoque de diseño más simple⊕
Si se desea hacer un sistema operativo que inicialice una computadora, tal vez el enfoque más simple es centrar los esfuerzos de diseño e implementación en 2 módulos principales: El cargador del sistema. Un kernel mono-tarea y mono-usuario, sin servicios. El requisito indispensable para un proyecto de este tipo (y para cualquier proyecto de SO) es conocer bien el hardware, por lo que contar con documentación sobre los diferentes componentes (procesador, memoria, controlador de dispositivos, dispositivos periféricos, timer, BIOS, etc.) y sus características es vital. También es importante establecer el alcance de cada uno de los módulos. En el caso de cargador deberá establecerse la estrategia de arranque y carga, lo cual debe estar relacionado con el hardware con el que contemos. Lo más sencillo es hacer un cargador de disco flexible, aunque está la posibilidad de hacerlo desde el disco duro (cuidado con esto! hay que hacerlo en

Obras consultadas: [7.47] [7.48] [7.49]

258

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

una máquina dedicada para pruebas) o por medio de red (se necesitaría una tarjeta , una red montada y el sitio de donde se descargaría el SO). Para el kernel, lo más simple es desplegar un mensaje o implementar algún programa sencillo, asegurándonos de implementar una manera de salir (bien podríamos generar un ciclo infinito y reiniciar apagando la computadora, pero hacer que termine por medio de un teclazo, u otro evento es más interesante). Algunos de los principales requerimientos técnicos que deben estar documentados son: • • • • el conjunto de instrucciones del procesador el modelo de organización de la memoria los tamaños de los bloques de memoria y su distribución el manejo de interrupciones del sistema

así como contar con un ensamblador para generar ejecutables con características muy particulares, por ejemplo: • • • que el código del cargador se guarde en determinado sector del disco y que de ahi cargue el SO a una dirección determinada de memoria) que el tamaño del archivo sea de un tamaño determinado que el código generado tenga un determinado modelo de memoria

Para más información, consulte la sección "Cargador del Sistema" y las referencias del capítulo 2, así como el apéndice de "Sectores de arranque". Debe tomarse en cuenta que el cargador no es necesario implementarlo, pues ya hay varios cargadores que pueden manipular diversos tipos de ejecutables y sistemas operativos (multiboot) como el GRUB (GRand Unified Bootloader), OSL, XOSL, Etherboot, NILO, etc., que se encargan de esta tarea; pero lo cierto es que hacerlo resulta más ilustrativo. Sin embargo, usar un programa de este tipo tiene sus ventajas; en el caso del GNU GRUB, este sigue los siguientes requerimientos: • • • • Cumple con la especificación Multiboot. Las funciones básicas son sencillas de usar para el usuario final. Funcionalidad para diseñadores/expertos en sistemas operativos. Compatibilidad para arrancar FreeBSD, NetBSD, OpenBSD, y GNU/Linux. SOs propietarios como Win 98, NT y OS/2 se soportan mediante chain-loading function.

y adicionalmente proporciona: • • • • • • • Soporta múltiples formatos ejecutables. Soporta sistemas no-Multiboot. Carga múltiples módulos. Interfaz de usuario. Interfaz de comandos flexible. Soporta múltiples tipos de sistemas de archivos. Soporta descompresión automática.

259

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• • • •

Accesa datos de cualquier dispositivo instalado. Detecta toda la RAM instalada. Descarga imágenes de SOs desde una red. Soporta sistemas sin disco y terminales remotas.

Por lo anterior debe quedar claro que SI vale la pena usar este tipo de herramientas (hacer algo así parece bastante complejo). Aunque todo esto no suene tan difícil, es bastante complejo y es un buen reto técnico. Como ejemplos de este tipo de desarrollos tenemos el SO JOSH y un proyecto del SIGOPS para enseñar como construir un sistema operativo sencillo, pero que a fin de cuentas permita aprender varios principios básicos de su implementación.

7.5.2 Consideraciones de diseño de sistemas operativos⊕
Puesto que el diseño de un SO es dependiente del diseño del hardware de la computadora, no sorprende que una arquitectura similar de funciones exista en cada SO. Además de las funciones que un SO debe proveer para poder operar (core functions), hay un conjunto de servicios siempre en expansión que extienden las capacidades del sistema. Algunas consideraciones básicas durante el diseño son: 1. Tipo de sistema a implantar. Sistemas de control, robots, PCs. Propósito específico o general. Usuarios finales. 2. Especificaciones técnicas y herramientas de hardware y software. Dependencia por la arquitectura del microprocesador (CISC, RISC, microcontroladores) o su disposición (serial, paralelo). Memoria y periféricos disponibles. 3. Metodología de desarrollo. Metodologías Estructuradas u orientadas a objetos. 4. Distribución de módulos en base al modelo OSI. 5. Protocolos de comunicación. 6. Modelo cliente/servidor. 7. Control de periféricos. Estándares de fabricación. 8. Aprovechamiento de instrucciones nativas del procesador. 9. Portabilidad. 10. Dimensionamiento (rigth sizing). Kernels compactos para cualquier tipo de sistema (escalabilidad). Versiones para servidores y terminales o dedicados. Un proyecto de sistemas operativos necesita considerar tres componentes básicos para comenzar a tomar decisiones: • • • Cargador Kernel Utilerías mínimas (programas de aplicación)

Obras consultadas: [7.21]

260

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Tales decisiones requieren de diversas consideraciones tales como el acceso que proveerá el kernel, el tipo de dispositivos (hardware) con los que se va trabajar, etc. Estas decisiones son influenciadas por la naturaleza de las funciones que se quieran proporcionar. Pero una muy clara es la interdependencia. No se debe optar por un diseño complejo que exija un alto nivel de complejidad en el kernel. La idea básica es comenzar con una plataforma modesta de funciones y construir un kernel prototipo funcional, para después ir incrementando lentamente la complejidad de las funciones para optimizar el kernel. A esto puede llamársele el modelo de desarrollo de escalera ('Ladder' model of development) donde dos metas interdependientes proceden paralelamente complementando los requerimientos mutuos. La escalera requerirá de varios escalones para ser una escalera funcional. En un proyecto de sistemas operativos estos escalones son típicamente herramientas de depuración (depuradores del kernel) y herramientas de verificación (programas de prueba). Algunas decisiones típicas son: • Un SO portable o explotar las características de una arquitectura de hardware particular (p.ej. si se usan las características de una x86: traducción de direcciones de memoria basadas en segmentos y protección de la memoria (vs. paginación), switcheo de tareas usando TSSs (vs. intercambio de stack)). • • • Arquitectura del Kernel: kernel monolítico, microkernel, exokernel, SASOS, etc. Multitarea: ninguna, cooperativa, preemptiva. Hilos (Threads): no usar, planificación expropiativa del kernel o cooperativa por aplicación, mismo espacio de memoria que la tarea padre, espacio separado de direcciones con memoria compartida, o espacios de direcciones totalmente separados. Multiprocesamiento: monoprocesador, multiprocesamiento altamente acoplado (p.ej. multiprocesamiento simétrico, SMP), multiprocesamiento poco acoplado (cómputo distribuido, como Amoeba) Multiusuario (multitarea + seguridad) SO Huésped para desarrollo: DOS, MS-Windows, Linux, Be, etc. Lenguaje usado para implementar el SO: C, C++, ensamblador, Ada, propietario, etc. Formato de archivos ejecutables. Una decisión relacionada: soportar o no ligado dinámico (Los formatos ELF y PE simplifican el ligado dinámico) Librerías para lenguajes de alto nivel: GNU glibc, Cygnus Newlib, propietarias, etc. Compatibilidad hacia atrás: ¿mismas llamadas al sistema que en otros SOs? ¿mismas funciones en librerías? ¿capa de compatibilidad? ¿Microkernel con "múltiples personalidades"? ¿Codificar o reusar? ¿escribir código propio o usar código fuente de otros proyectos? ¿el código es entendible? ¿hace lo que se requiere?

• • • • • •

Algunas de las opciones para implementar un sistema operativo, y en específico un kernel son las siguientes: - Interfaz directa con el hardware.

261

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

- Montar un kernel sobre un sistema operativo ya instalado. - Crear un kernel cuyas operaciones estén basadas en un emulador de un procesador diferente al del hardware (máquina virtual).

7.5.3 Diseño de kernels
El propósito fundamental de un SO es permitir a los programas compartir una computadora eficiente (servicios para proteger a los usuarios de afectarse mutuamente; mediar el acceso a dispositivos físicos) y productivamente (coordinar el acceso de periféricos, protección de la memoria, planificación apropiativa de tiempo compartido, etc.), y permitir a varios usuarios compartir una computadora. Actualmente los programadores implementan estos objetivos por medio de un gran programa llamado kernel. Puesto que este programa debe ser accesible a todos los demás programas de usuario, es el lugar natural para agregar toda la funcionalidad del sistema. Puesto que el único modelo para la interacción de procesos es el de servicios individuales provistos por el kernel, nadie crea otros lugares para agregar funcionalidad; así al pasar del tiempo, más y más cosas se le agregan al kernel (esta práctica es común en los sistemas de kernel monolítico). Un sistema tradicional permite a los usuarios agregar componentes a un kernel solo si comprenden su funcionamiento y si tiene un cierto nivel de privilegios en el sistema. Probar nuevos componentes requiere un ciclo muy rudo de edición-compilación-depuración, mayor a cualquier otro programa, pues no se puede hacer si otros están usando el sistema (esto hablando de un ambiente "de producción"). Los errores causan caídas del sistema fatales, y la complejidad del kernel hace difícil incluso agregar extensiones simples. A causa de estas restricciones, la funcionalidad que por lo general permanece escondida en el kernel es dejada fuera del sistema a menos de que sea absolutamente necesaria. Muchas buenas ideas, que pueden hacerse con una interfaz open/read/write no pueden ser implementadas a causa de los problemas inherentes a la naturaleza monolítica de los sistemas tradicionales. Incluso aquellos con la determinación de implementar nuevas ideas, solo aquellos que son usuarios privilegiados de sus computadoras pueden hacerlo. El sistema de copyright de software además ha obscurecido este campo previniendo a personas sin "licencia" de incluso leer el código fuente del kernel. Algunos sistemas han tratado de solucionar estas dificultades. Smalltalk-80 y la máquina Lisp, representan una forma de darle vuelta al problema. El código del sistema no es distinguible del código del usuario; todo el sistema es accesible al usuario y puede cambiarse según las necesidades. Ambos sistemas fueron construidos alrededor de lenguajes que facilitaran el fácil reemplazo y extensión, y fueron moderadamente exitosos. Pero ambos fueron bastante deficientes, distanciando a los usuarios y a los programas uno del otro, fallando con uno de los principales objetivos del diseño de sistemas operativos. Muchos de los proyectos que usan el kernel Mach 3.0 siguen aplicando el tan difícil de cambiar diseño de SOs tradicional: la estructura interna es diferente, pero la misma barrera entre el usuario y el sistema permanece. Sus servidores individuales (single-servers) aunque fáciles de construir, heredan todas las deficiencias de los kernels monolíticos.

262

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Clasificación de los kernels
Cabe hacer algunas preguntas sobre el kernel del sistema operativo (si este es el estilo elegido): • Si el kernel hace multitarea, ¿cómo se resolverán los conflictos de direccionamiento entre tareas? • • ¿cómo obtendrán las tareas servicios del kernel? ¿el CPU provee protección? ¿tiene niveles de privilegios y una MMU? ¿El SO usará protección?

En este sentido se puede clasificar a los kernels en los siguientes niveles: Tipo 0. Tareas estáticas ligadas al kernel cuando este se construye, usando la instrucción CALL para accesar los servicios del kernel (sin protección) Ejemplos: Pequeños SOs de tiempo real (p.ej. u-COS) Ventajas: Muy simple Llamadas al sistema rápidas y simples (instrucción near CALL) por que las tareas se ejecutan en el mismo espacio de direcciones y en el mismo nivel de privilegios del CPU que el kernel • Alternancia de tareas rápida y simple por que las tareas se ejecutan en el mismo espacio de direcciones y en el mismo nivel de privilegios del CPU que el kernel Desventajas: • • • • • La protección no es posible por que las tareas están ligadas al kernel No es posible crear nuevas tareas después de que el kernel comienza a ejecutarse Todo debe ser vuelto a ligar cuando el kernel o alguna tarea se reconstruye

Tipo 1. Tareas dinámicas son ligadas al kernel cuando la tarea se carga, usando la instrucción CALL para accesar los servicios del kernel (sin protección) • • • Tipo 1a: tareas relocalizables Tipo 1b: las tareas usan código independiente de la posición (PIC) Tipo 1c: las tareas están en direcciones fijas, y el kernel usa el MMU solo para traducción de direcciones Ventajas: Pueden crearse nuevas tareas después de que el kernel comienza a ejecutarse Llamadas al sistema (syscalls) rápidas y simples por que las tareas se ejecutan en el mismo espacio de direcciones y en el mismo nivel de privilegios del CPU que el kernel • Alternancia de tareas rápida y simple por que las tareas se ejecutan en el mismo espacio de direcciones y en el mismo nivel de privilegios del CPU que el kernel Desventajas: • • • • • La protección no es posible porque las tareas están ligadas al kernel El kernel es más grande y complejo por que debe tener una tabla de símbolos y código para relocalizar/ligar las tareas (tareas relocalizables) Las tareas son más grandes por que deben tener relocalizaciones externas e internas

263

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

(tareas PIC) Las tareas son más grandes por que deben tener relocalizaciones externas, y por que PIC consume uno de los registros de propósito general

Tipo 2. Tareas dinámicas NO ligadas al kernel (usan la instrucción INT para accesar los servicios del kernel); sin protección • • • Tipo 2a: tareas relocalizables Tipo 2b: las tareas usan PIC Tipo 2c: las tareas están en direcciones fijas; el kernel usa la MMU solo para traducción de direcciones Ejemplos • (tipo 2a) DOS. Usa la INT 21h para llamadas al sistema. El formato de archivo relocalizable es .EXE • (tipo 2b) OS/9 para el CPU 6809 (Radio Shack Color Computer). Usa SWI para llamadas al sistema. El 6809 no requiere un registro de propósito general para PIC. • (tipo 2b) Macintosh basada en el 68000 original. Usas TRAP nn para llamadas al sistema. El registro A5 es usado para PIC. Ventajas: • Pueden crearse nuevas tareas después de que el kernel comienza a ejecutarse • Alternancia de tareas rápida y simple por que las tareas se ejecutan en el mismo espacio de direcciones y en el mismo nivel de privilegios del CPU que el kernel Desventajas: • • • • No hay protección Las llamadas al sistema que usan INT son un poco más lentas que near CALL, y el código de llamada al sistema agrega complejidad al kernel y las tareas (tareas relocalizables) Las tareas son más grandes por que deben tener relocalizaciones internas (tareas PIC) Las tareas son más grandes por que PIC consume uno de los registros de propósito general

Tipo 3. Tareas dinámicas NO ligadas al kernel (usan la instrucción INT para accesar los servicios del kernel); con protección Tipo 3a: tareas relocalizables, usando la MMU solo para protección Tipo 3b: las tareas usan PIC, usando la MMU solo para protección Tipo 3c: las tareas están en una dirección fija, usando la MMU para protección y traducción de direcciones Ejemplos: • (tipo 3a) pk/Roadrunner. Usa la INT 30h para llamadas al sistema. El formato de archivo relocalizable es ELF. La protección de memoria usa paginación. • (tipo 3c) Linux. Usa la INT 80h para llamadas al sistema. la dirección fija de carga para ejecutables ELF Linux ELF es 8048000h. La traducción y protección de direcciones usa paginación. Ventajas: • • • • • Pueden crearse nuevas tareas después de que el kernel comienza a ejecutarse Código defectuoso o malicioso de una tarea no puede dañar al kernel u otras tareas

264

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Desventajas: • Las llamadas al sistema que usan INT son un poco más lentas que near CALL, y el código de llamada al sistema agrega complejidad al kernel y las tareas • (tareas relocalizables) Las tareas son más grandes por que deben tener relocalizaciones internas • (tareas PIC) Las tareas son más grandes por que PIC consume uno de los registros de propósito general • La protección impone sobrecarga, haciendo las llamadas al sistema y el intercambio de tareas más lento, y el código de protección agrega complejidad al kernel • Se requiere soporte de hardware en forma de niveles de privilegio en el CPU y una MMU

Criterios de planificación⊕
Los algoritmos de planificación deben tener en cuenta una serie de casos: • Utilización del CPU., queremos que el CPU se mantenga tan ocupado como sea posible. • Productividad, una medida del trabajo es el número de procesos que se completa por unidad de tiempo. • Tiempo de Retorno, sería la suma de los periodos transcurridos esperando entrar en la memoria, esperando en la cola de procesos listos, ejecutándose en el CPU y efectuando operaciones de E/S. • • La cantidad de tiempo, que el proceso espera en la cola de procesos listos. El tiempo de respuesta, el tiempo transcurrido desde la presentación de una solicitud hasta que se produce la primera respuesta.

Siempre vamos a intentar maximizar la productividad (el tiempo de CPU) y se intenta minimizar el tiempo de retorno, de respuesta y el de espera. Existen dos criterios en la planificación de los procesos: Utilización de Prioridades. Utilización de QUANTUM de tiempo.

• •

Las prioridades consisten en asignarle a cada proceso un calificador que determine la atención que va a recibir del sistema, las prioridades pueden ser asignadas directamente por el Sistema Operativo (serían las internas) o por el usuario o Administrador (serían las externas). A su vez dentro de estas prioridades pueden ser: - Estáticas. Las que no cambian durante la ejecución del proceso. Siempre el proceso va a tener la misma prioridad. Son fáciles de implementar y sobrecarga menos el sistema (el procesador no tiene que dedicar tiempo a administrar prioridades). - Dinámicas. Son las que responden a cambios, al proceso se le da una prioridad inicial que en principio será de duración corta para después pasar a ajustarse a un mejor valor.

Referencias: [7.4]

265

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

7.5.4 Consideraciones sobre la codificación del sistema
Tradicionalmente los sistemas operativos eran implementados en lenguaje ensamblador, aunque ahora pueden codificarse por medio de lenguajes de programación de alto nivel. Las ventajas son que el código se escribe rápidamente, es más compacto, es más fácil de entender y revisar, y es fácilmente portable (trasladarse a otro tipo de hardware). Las desventajas son una menor velocidad y mayor capacidad de almacenamiento. Aunque los SOs son sistemas grandes, solo parte de su código es crítico para su desempeño (administración de la memoria, planificador del CPU). Después de que el sistema esté operando, las rutinas que forman cuellos de botella pueden ser identificadas, y como posible solución, reemplazadas por código en ensamblador. Para identificar esos cuellos de botella debe monitorearse el desempeño del sistema, por lo que debe agregarse código que calcule y despliegue medidas del comportamiento del sistema (algunas veces se guardan en archivos log para su análisis posterior o puede optarse por el despliegue a tiempo real). Aunque es posible diseñar, codificar e implementar un SO para una máquina en un solo sitio, la práctica más común es que los SOs sean diseñados para funcionar en cualquier clase de máquina, en una gran variedad de sitios y con una gran variedad de configuraciones de periféricos. El sistema debe ser entonces configurado o generado para cada computadora. Este proceso es conocido como SYSGEN (system generation). Al ser distribuido en disco, se utiliza un programa especial para leer de un archivo o preguntar al operador la información relacionada a la configuración del sistema de hardware, tal como: • El tipo de CPU a utilizar, sus opciones, o la descripción de cada CPU en sistemas multiprocesador. • La cantidad de memoria. • • Disponibilidad de dispositivos. Opciones deseadas del SO (buffers, número de procesos, tipo de scheduling, etc.)

Una vez con esta información, puede procederse de varias formas: • Modificar una copia del código fuente para que sea compilado, obteniendo una versión ajustada al sistema descrito. • • Creación de tablas de selección de módulos precompilados, para ser ligados y generar el SO. Selección de componentes a copiar, de una versión completamente operacional para cada plataforma.

7.5.5 Uso de estándares y portabilidad⊕
Un estándar de sistema abierto es una especificación de interfaz que describe los servicios provistos por un producto de software sobre la cual, cualquiera puede construir nuevos productos. Tales especificaciones están disponibles para cualquier productor y evolucionan por medio de un proceso de consenso que está abierto a toda la industria, y además definen solo

Referencias: [7.28] [7.29] [7.30] [7.31] [7.32] [7.33] [7.34]

266

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

una interfaz, así que otros pueden proveer la interfaz estándar en sus propios sistemas operativos. Los estándares de sistemas abiertos harán posible el desarrollo de componentes estándar de software que puedan ser implementados en una gran variedad de hardware, haciendo a la industria de componentes de software económicamente viable. POSIX (Portable Operating System Interface for Computer Environments) es un estándar de la IEEE diseñado para facilitar la portabilidad de aplicaciones. POSIX es un intento para crear una sola versión estándar de UNIX por parte de varios fabricantes, lo que busca portar fácilmente aplicaciones entre plataformas de hardware (p.ej. Hewlett-Packard está incorporando POSIX en la versión 5.0 de su sistema operativo propietario MPE/iX y en la versión 10.0 del HP/UX). Hay más de diez partes del estándar POSIX, pero dos están disponibles: • POSIX.1 define interfases de programación en C (una librería de llamadas al sistema) para archivos, procesos, y entrada/salida de terminales. Para soportar la librería, un sistema POSIX debe implementar un sistema de archivos jerárquico (Hierarchical File System (HFS)). • POSIX.2 define un intérprete de comandos (shell) y utilerías (p.ej. ls para listar archivos). Ciertos estándares importantes no son cubiertos por POSIX (p.ej. spooling, procesamiento por lotes, y soporte de lenguaje nativo (NLS, Native Language Support, que esta definido por el estándar X/Open)). La interfaz de programación de aplicaciones (API) de los sistemas UNIX ha sido estandarizada por un gran número de documentos de la IEEE. Para la mayoría de los programadores el más importante es el POSIX 1003.1 que cubre primitivas de procesos y ambientes, directorios y archivos, primitivas de entrada/salida y funciones específicas de dispositivos. Estándares posteriores cubren otros rubros como los interpretes de comandos y utilerías (POSIX 1003.2) y administración (POSIX 1387.2). La mayoría de las APIs de sistemas operativos comparten funcionalidades comunes. Por ejemplo, tanto Unix como Windows tienden a organizar y listar archivos en directorios.

7.6 Diseño de sistemas operativos: la interacción con el usuario⊕
Aunque el uso de los recursos del hardware de la computadora sea el objetivo principal del diseño de un sistema operativo, no se puede dejar de pensar en como los usuarios interactuarán con la computadora, pues hay que recordar que por lo menos en la arena de las computadoras personales, esto ha sido el factor principal para el éxito de cualquier producto, ya sea una computadora o alguno de sus periféricos. En un principio los operadores expertos tenían que recurrir a teclados especiales para perforar tarjetas que alimentaban a la máquina, y debían consultar sus resultados en manojos de hojas

Obras consultadas: [7.64] [7.65] [7.66] [7.67] [7.69]

267

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

que salían de las impresoras. Poco a poco, la mejora en interfaces con el usuario ha permitido que pueda disminuirse la complejidad de interacción entre las computadoras y usuarios. Tareas como reconocer información del teclado o el ratón, desplegar información en un monitor, o controlar la impresión de un documento, son faenas básicas que un sistema operativo debe realizar actualmente. Además de esto, el SO debe ofrecer una serie de servicios y recursos que puedan ser aprovechados por el software de aplicación. En esta sección se profundiza en los conceptos de interfaz de usuario presentados en la sección 1.2.8 y se exponen algunas consideraciones de diseño útiles para su implantación.

7.6.1 Interacción humano-computadora⊕
La interacción humano-computadora (HCI) es la disciplina relacionada con el estudio, diseño, construcción e implementación de sistemas de cómputo interactivos centrados en el usuario. HCI va más allá de diseñar pantallas o menús que sean más fáciles de usar (usabilidad), pues estudia el razonamiento que implica construir determinada funcionalidad en las computadoras y sus efectos a largo plazo que estos sistemas tienen en los humanos. Una de las principales actividades en esta área es el desarrollo de nuevos sistemas de interfaz para el usuario, lo que implica desarrollar nuevos dispositivos de interfaz (fig. 7.10), nuevas técnicas de graficación por computadora y técnicas de diálogo [7.89]. Una interfaz de usuario es un medio para que el usuario interactúe con la computadora. Este medio se constituye tanto de software como de hardware. Aunque las interfaces de usuario pueden adoptar diversas formas, sus objetivos fundamentales son: comunicar información de la máquina al usuario y comunicar información del usuario a la máquina.

Figura 7.10 Dispositivos de interfaz
Douglas Engelbart fue el pionero en esta área, pues planteó una visión en la que “las computadoras fueran extensiones de las capacidades de comunicación del ser humano y fueran un recurso para aumentar el intelecto humano” [7.75]. Él, junto con un grupo de jóvenes

Obras consultadas: [7.81] [7.82] [7.83] [7.89]

268

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

investigadores en el Instituto de Investigación de Stanford (SRI) desarrollaron el ratón, el concepto de hipermedia, la interfaz de ventanas y la teleconferencia. La importancia de las interfaces de usuario es muy trascendente no solo para el usuario convencional, sino para los usuarios con discapacidades, pues para hacer la tecnología accesible para ellos, deben contemplarse nuevos dispositivos y aplicaciones que les permitan usar la computadora.

7.6.2 Interfaz basada en texto⊕
Los programas orientados a caracteres solo eran capaces de desplegar códigos ASCII en pantalla. Estos programas trataban al área de despliegue como un arreglo de bloques, donde cada uno solo puede contener un caracter. En contraste los programas gráficos tratan al monitor como un arreglo de puntos (pixeles). Las primeras interfaces de usuario con la computadora estaban orientadas al uso de texto proveniente de un teclado, y usualmente consistían de un conjunto de comando que el usuario debía memorizar y a los que la computadora respondía (fig. 7.11).

Figura 7.11 Interfaz de usuario del MS-DOS
Así que por una parte está el manejo del modo gráfico correspondiente a la interfaz para desplegar sus resultados en el monitor, y por otro esta el programa encargado de captar y ejecutar los comandos correspondientes. Dichos comandos corresponden a un lenguaje que debe ser especificado por una gramática. Este programa por lo general es un interprete que puede basar su codificación en el patrón Interpreter (fig. 7.12).

Obras consultadas: [7.79] [7.80]

269

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 7.12 Patrón de diseño Interpreter
Un paso intermedio entre la interfaz de línea de comando y las interfaces gráficas, fue el uso interfaces basadas en menús en modo texto (fig. 7.13), donde se podía interactuar por medio un ratón en lugar de escribir el comando correspondiente en el teclado. Esto demandaba esfuerzo considerable de programación, y por lo general no había una manera estandarizada programar este tipo de interfaces. de de un de

Figura 7.13 Interfaz de la aplicación shell de MS-DOS
En este punto, muchas librerías para interfaces de usuario aparecieron prometiendo disminuir los tiempos de desarrollo, pero con el advenimiento de las interfaces gráficas integradas en el sistema operativo, mucho de este trabajo fue efímero.

7.6.3 Interfaz gráfica de usuario ⊕
Una interfaz gráfica de usuario (GUI) es un programa de interfaz que aprovecha las capacidades de despliegue gráfico de la computadora que permite hacer más sencillo el uso de

Obras consultadas: [7.70] [7.71] [7.72] [7.73] [7.74] [7.75] [7.76] [7.77] [7.78]

270

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

los programas [7.78]. Este cambio de paradigma en las interfaces de usuario se dio en el centro de investigación de Xerox, cuando se construyó la computadora Alto (1973).

Figura 7.14 Interfaz gráfica GNOME en Linux[7.87]
La metáfora más usada actualmente es la de un espacio de trabajo bidimensional, donde como en un escritorio se tienen los implementos que el usuario usa en su trabajo diario. Este tipo de interfaz gráfica de usuario usa iconos y menús para realizar comandos tales como abrir archivos o ejecutar aplicaciones (fig. 7.14). Algunos de los componentes gráficos comunes en este tipo de interfaces son: Apuntador. Es un símbolo que aparece en la pantalla y que se desplaza para seleccionar objetos y comandos. Dispositivo apuntador. Un dispositivo como el ratón que permite seleccionar objetos de la pantalla. Iconos. Pequeñas imágenes que representan comandos, archivos o ventanas. Menús. Opciones o comandos agrupados en forma de listas. Ventanas. Son áreas que dividen la pantalla, y en cada una de ellas puede ejecutarse un programa o abrir un archivo diferente. Escritorio. Es el área de la pantalla donde los iconos son agrupados. Además de sus componentes gráficos, la interfaz debe permitir mover datos de una aplicación a otra. Una buena GUI debe incluir formatos estándar para representar texto y gráficos, lo que permite que las aplicaciones puedan compartir sus contenidos (p.ej. llevar un gráfico de una hoja de cálculo a un procesador de palabras). Una arquitectura que es comúnmente usada para el desarrollo de la GUI es el patrón modelovista-controlador (MVC), que permite separar los componentes gráficos, el control de los dispositivos periféricos y eventos, y sus efectos en el modelo (fig. 7.15).

271

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 7.15 Patrón MVC como base de una GUI
En este esquema las aplicaciones usan los elementos del GUI que proporciona el sistema operativo, y es posible agregar elementos gráficos adicionales. Tómese como ejemplo el caso de Java donde se tiene un marco de trabajo llamado Swing que permite la programación de interfaces de usuario (fig. 7.16).

Figura 7.16 Elementos de la interfaz de usuario de Swing en Java35
Cada sistema operativo tiene su propia arquitectura de GUI, pues sistemas como BeOs o el Mac OS X, orientados a diseñadores y artistas gráficos, hacen un uso intensivo de las capacidades gráficas de la computadora, por lo que debe optimizar el uso de estos recursos.
35

Imagen reproducida de [7.70]

272

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Una tendencia adicional es la personalización del diseño gráfico de los elementos de la interfaz gráfica. Para ello se ha introducido el concepto de tema, donde existe una separación en el trabajo de los diseñadores gráficos y los programadores. De esta manera, pueden cambiarse el diseño y distribución de los controles sin tener que recompilar el código encargado del GUI (fig. 7.17)

Figura 7.17 Arquitectura de la GUI del WCEfA36 7.6.4 Interfaces alternativas⊕
En un futuro la forma de interacción de los humanos con las computadoras cambiará de forma radical. Al aumentar el poder de cómputo, formas de interacción planteadas como futuristas se están haciendo realidad. Algunos ejemplos de esto son: 1. Las interfaces basadas en el reconocimiento del habla 2. Las interfaces basadas en el reconocimiento de la escritura 3. Las interfaces neuronales A continuación se exponen algunos detalles de los casos 1 y 3. Una interfaz de usuario basada en el habla (speech user interface - SUI) es aquella que soporta un diálogo interactivo entre el usuario y una aplicación de software, ofreciendo una forma de interacción más natural para el usuario. Un escenario propicio para este tipo de interfaces es el de dispositivos móviles, en especifico plataformas como el Auto-PC. En donde se requiere que el usuario tenga desocupadas las manos para manejar. Los dispositivos de interfaz neuronal (Neural Interface Devices) permiten a los usuarios aprovechar las señales eléctricas generadas por sus cuerpos para controlar una computadora o dispositivos eléctricos conectados a ella.

36 ⊕

Imagen adaptada de [7.67] Obras consultadas: [7.68] [7.83] [7.84]

273

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Las señales pueden adquirirse de forma directa o indirecta. Los métodos directos implican implantes quirúrgicos en el cuerpo del usuario. El implante puede localizarse en el cerebro o en algún miembro amputado, dependiendo de la aplicación. Este tipo de tecnología aún está en desarrollo. Los métodos indirectos de obtención de señales no requieren cirugía. Estas señales neuronales indirectas pueden obtenerse de los músculos (EMG), movimiento de los ojos (EOG) o de las ondas cerebrales (EEG). Después de que las señales eléctricas se obtienen del cuerpo se amplifican, y se traducen en su equivalente digital para que el software pueda interpretar las señales. Dicho software permite a los usuarios controlar un cursor, jugar videojuegos especialmente diseñados o controlar otros dispositivos conectados a la computadora.

7.6.5 Diseño de interfaces de usuario⊕
El principal objetivo del desarrollo de interfaces de usuario es el diseñar e implementar interfaces que sean eficientes efectivas al ser utilizadas por el usuario [7.86]. Este proceso debe estar contemplado en el proceso de desarrollo de software, y por lo general empieza en la fase de diseño, donde se plantean prototipos de interfaces donde se determinan que eventos ocurrirán y los procesos lógicos soportarán a dichos eventos; en otras palabras, se visualiza la funcionalidad del sistema y las interacciones con el usuario. Dichos prototipos servirán como referencia para codificar las interfaces de usuario con una tecnología específica, dependiendo de los requerimientos del sistema. Después de codificar la aplicación, se procede a la etapa de pruebas. Existe una técnica específica llamada pruebas de usabilidad que puede validar el diseño de la interfaz y revelar áreas que requieran refinamiento. La idea básica es observar a los usuarios mientras operan la interfaz. Previamente se les debe capacitar para que puedan verbalizar sus pensamientos y acciones mientras los realizan. Por ejemplo, un usuario podría narrar algo como lo siguiente: "Quiero encontrar un archive de texto con mis notas. Veo un botón que dice “Archivos”, pero no se si es para crear o para buscar archivos". Comprendiendo que es lo que están pensando los sujetos de prueba es posible detectar problemas de comprensión o uso de la interfaz de usuario. En el contexto de los sistemas operativos, sobre todo de los de uso general, dichas interfaces deben implementar una metáfora del espacio de trabajo y sus correspondientes elementos de diseño, así como contemplar los dispositivos con que la computadora podrá contar, lo que lleva al desarrollo de: Controladores para dispositivos de interfaz o Ratón, visores, tarjetas gráficas, cámaras, etc. APIs de interfaz de usuario o GUI, SUI, etc. APIs de graficación (2D, 3D, etc.) Ambientes de trabajo (modo texto o gráficos) Herramientas para diseño de aplicaciones con interfaz de usuario

Obras consultadas: [7.86] [7.87] [7.88]

274

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Un ejemplo palpable de este enfoque es la arquitectura del Mac OS X (fig. 7.18). Como soporte se tiene un microkernel muy potente (Darwin), sobre el que se monta la capa del sistema de gráficos que integra 3 tecnologías [7.88]: Quartz, que es un servidor de ventanas y un motor de despliegue gráfico bidimensional que define las formas en términos de sus componentes vectoriales, y que usa como lenguaje gráfico de representación interna el estándar PDF (Portable Document Format). OpenGL, que es el estándar para gráficos tridimensionales. QuickTime, que es una tecnología multimedia que permite la manipulación de imágenes, sonidos, texto, música, animación y hasta realidad virtual.

Figura 7.18 Arquitectura del Mac OS X y su interfaz de usuario Aqua37
Aqua es la interfaz gráfica de usuario de este sistema operativo, que integra la apariencia y comportamiento de la interfaz, que basa mucha de su funcionalidad gráfica en las capacidades de Quartz. Estas tecnologías de manipulación gráfica, en combinación con las interfaces de programación Carbon, Cocoa (Java/Objective C), Java y el soporte de UNIX, permiten el desarrollo de aplicaciones con interfaz gráfica de usuario en diversas plataformas. Todo esto queda plasmado en el término definido por Apple como experiencia del usuario (User Experience) el cuál abarca la apariencia visual, comportamiento interactivo, y capacidades asistivas del software. Todo este soporte debe ser considerado por quien desarrolle un sistema operativo, pues esta infraestructura representa una ventaja competitiva si se quiere que el SO sea adoptado por el mayor numero de usuarios posible, y sobre todo si se quiere que las comunidades de desarrolladores produzcan aplicaciones en la nueva plataforma. Incluso aunque la parte de interfaz de usuario este contemplada en el diseño del SO, puede que su implementación no sea del gusto de los desarrolladores, o que por estar implementada en un lenguaje estructurado, si se requiere desarrollar con orientación a objetos existan problemas de

37

Imagen reproducida de [7.88]

275

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

compatibilidad. Estos escenarios pueden provocar de nuevo que algunos desarrolladores prefieran programar sus propias APIs.

7.7 Diseño de sistemas operativos: la administración de sistemas⊕
Existe un tipo de usuarios especializados de los sistemas operativos para los cuales la simple funcionalidad de ejecutar sus programas no es suficiente. Estos usuarios, llamados administradores de sistemas, requieren el control completo del sistema para cumplir con 3 objetivos fundamentales: • • • Asegurar que el sistema hace su trabajo efectiva y eficientemente Asegurar que la información almacenada en el sistema está a salvo de daños intencionales o accidentales Administrar las reglas para el uso del sistema.

Para realizar estos objetivos el administrador del sistema debe entender más que solo la estructura e interacción del hardware y el software; debe comprender el ambiente de interconexión en el que actualmente los sistemas existen y los efectos que el ambiente tiene en el funcionamiento y rendimiento del sistema local. Un sistema de cómputo contemporaneo incluye un conjunto de elementos de hardware, software, e información que deben trabajar cooperativamente para que el sistema satisfaga las necesidades de los usuarios. Los principales elementos y sus funciones administrativas son: • Unidades de disco o Control de la agrupación y subdivisión del espacio en disco. o Control de la localización de datos y programas para un desempeño óptimo. o Control de la cantidad de espacio asignado para diversos propósitos. Programas de aplicación o Control del uso de programas costosos o “sensibles” (uso restringido) o Instalación y ajuste del desempeño de aplicaciones críticas. Datos de aplicación o Control del acceso a datos sensibles. o Asegurar las medidas de respaldo apropiado. Memoria y procesadores de computadoras individuales o Control de acceso al sistema por individuos y grupos. o Ajustar el sistema operative para el uso óptimo de los recursos disponibles. Redes de area local o Ajustar la red para un óptimo desempeño. o Control de los mecanismos de direccionamiento de la red.

Obras consultadas: [7.90][7.91][7.92][7.93]

276

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Terminales locales o Control de la conección de las terminals a los procesadores. o Asegurar que las terminales y procesadores esten ajustados para un óptimo desempeño. Acceso a sistemas remotos o Control de los permisos de acceso en ambas direcciones. o Monitoreo y ajuste del desempeño de la carga impuesta por la conexiones remota. Acceso a datos remotos o Control de los método y disponibilidad de acceso.

Por la amplia variedad de funciones que se requieren para que un sistema opere debidamente, el sistema operativo debe considerar en su diseño el soporte de las actividades propias de administración de sistemas. Esto puede incluir: • archivos que permitan parametrizar la operación del SO (p.ej. el archivo AUTOEXEC.BAT en DOS que permitía definir que manejadores de dispositivos adicionales debían cargarse, o el tamaño o modo de la memoria) • estructuras de datos y archivos que permitan controlar la configuración del sistema operativo (p.ej. el Registry de Windows) • • • • • • APIs que permitan el acceso a la información de administración y monitoreo. herramientas de administración por línea de comandos (p.ej. el comando kill para destruir procesos en UNIX) herramientas de interfaz gráfica de administración y monitoreo (p.ej. el Task Manager de Windows) herramientas web de administración y monitoreo (p.ej. el Web-based System Manager de AIX) servicios de administración remota del SO (p.ej. herramientas que usan protocolos como el Simple Network Management Protocol) ayuda en linea (p.ej. el comando man de UNIX)

Aunque muchas de estas herramientas son usados por administradores experimentados, una tendencia de los nuevos sistemas operativos es brindar al usuario convencional algunas de estas funcionalidades, pues el usuario casero no optará por un sistema complejo o costoso de administrar. Inclusive compañías como Symantec han optado por desarrollar herramientas muy sofisticadas que simplifican la labor de la administración de sistemas, y que cubren las posibles carencias que un sistema operativo tenga en este rubro. Este es un nicho de mercado paralelo al desarrollo de sistemas operativos, y que seguramente implica la formación de alianzas entre los productores de software para que estos productos tengan el impacto deseado.

7.8

Comentarios

Esta parte del trabajo se ha dedicado a ubicar la actividad de diseño de sistemas operativos en el marco del proceso de desarrollo e ingeniería de software (fig. 7.19), con el fin de recalcar una

277

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

vez más a los desarrolladores la importancia de contar con un modelo de referencia para la producción de sistemas operativos (fig. 7.20). Dicho modelo dista mucho del enfoque orientado exclusivamente a la programación, y expone todos los requerimientos, consideraciones y criterios que deberán tomarse en cuenta al enfrentar un desarrollo de estas dimensiones. De igual forma puede notarse que aunque el presente es extenso y trata de cubrir la mayoría de los aspectos, hay muchos otros que quedan sin explorar. Como se puede apreciar en la última parte de este capítulo, los desafíos técnicos a solucionar son muchos y variados, por lo que los desarrolladores tienden a ocuparse más en domar al hardware, hasta alcanzar un nivel de complejidad suficiente en la codificación como para pensar en las cuestiones de alto nivel. Esto de ninguna manera es censurable; sin embargo, se reafirma la necesidad de aplicar los métodos de ingeniería de software para que el producto pueda alcanzar sus objetivos. En el siguiente capítulo se expondrán más a detalle los detalles relacionados a la estructura arquitectónica de los sistemas operativos.

Figura 7.19 Consideraciones para el desarrollo de software

278

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 7.20 Diseño de sistemas operativos

279

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

7.9

Obras consultadas
http://www.nondot.org/sabre/os/articles [7.13] OS Design for Ametures (my FAQ). Brian Klock

[7.1] Argante virtual operating system http://agt.buka.org/concept.html [7.2] Introduction to Operating Systems Kathryn S. McKinley. University of Massachusetts .Fall 1997 http://www-aml.cs.umass.edu/~cs377/ [7.3] Write Your Own Operating System [FAQ]. Stuart 'Dark Fiber' George <dfiber@mega-tokyo.com> http://www.nondot.org/sabre/os/S9Misc/osfaq/index.html [7.4] OS Design for Amatures (my FAQ). Brian Klock http://www.overwhelmed.org/shawn/faq.html [7.5] Applications Programming in Smalltalk80(TM):How to use Model-View-Controller (MVC) Steve Burbeck, Ph.D. http://st-www.cs.uiuc.edu/users/smarch/stdocs/mvc.html [7.6] Model View Controller http://www.objectarts.com/EducationCentre/Overviews/MVC.htm [7.7] Towards a New Strategy of OS Design Thomas Bushnell, BSG http://www.gnu.org/software/hurd/hurd-paper.html [7.8] The Hurd presentation by Marcus Brinkmann http://www.gnu.org/software/hurd/hurd-talk.html

http://www.overwhelmed.org/shawn/faq.html [7.14] Questions For an OS Designer. http://phantom.urbis.net.il/bphantom/OS_Design_Qs.ht ml [7.15] Code your own OS http://www.openbg.net/sto/os/ [7.16] Write Your Own Operating System [FAQ] Stuart 'Dark Fiber' George 2001 http://www.mega-tokyo.com/os/os-faq.html [7.17] OSFAQ.com http://www.osfaq.com/ [7.18] Operating System Development For Dummies (OSD) A project of the alt.os.development Usenet discussion group http://www.execpc.com/~geezer/osd/index.htm [7.19] Answers to frequently asked questions for comp.os.research. Bryan O'Sullivan http://www.serpentine.com/~bos/os-faq/welcome.html http://www.serpentine.com/~bos/os-faq/FAQ-1.html http://www.serpentine.com/~bos/os-faq/FAQ-2.html http://www.serpentine.com/~bos/os-faq/FAQ-3.html [7.20] The Triple Fault Club

[7.9] How operating systems work. How stuff works. Lycos. http://howstuffworks.lycos.com/operating-system.htm [7.10] What Operating System? Who Cares! Chuck Jazdzewski The Future of software. Winter 2000. http://www.futureofsoftware.net/cj0010/cj0010.asp [7.11] Techniques for the Design of Java Operating Systems. Back et al (Univ. of Utah) http://www.cs.wpi.edu/~cs535/f00/back:usenix00/ [7.12] The Operating System resource center. Chris Lattner

http://www.execpc.com/~geezer/os/ [7.21] Operating System Directions for the Next Millennium. William J. Bolosky, Richard P. Draves, Robert P. Fitzgerald, Christopher W. Fraser, Michael B. Jones, Todd B. Knoblock, Rick Rashid Microsoft Research One Microsoft Way Redmond WA 98052 http://research.microsoft.com/research/sn/Millennium/ mgoals.html [7.22] Strategies for the Future of System Integration By James B. Bassich Jim.Bassich@cpu.com http://www.cpu.com [7.23] Implementing an operating system. Andrew Tanenbaum. InformIT

280

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
[7.24] Análisis y diseño de sistemas http://www.monografias.com/trabajos/anaydisesis/ana ydisesis.shtml [7.25] Operating system design & implementation tutorial. http://www.ansawide.com/josh/index.htm [7.26] How to Write an Operating System. SigOPS http://www.acm.uiuc.edu/sigops/roll_your_own/ [7.27] The Special Interest Group for Operating Systems. ACM http://www.acm.uiuc.edu/sigops/ [7.28] What is POSIX? The Portable Application Standards Committee (PASC) http://www.pasc.org/#POSIX [7.29] The POSIX/2 Project http://posix2.sourceforge.net/ [7.30] The Serial Programming Guide for POSIX Operating Systems http://www.easysw.com/~mike/serial/serial.html [7.31] PW32 the Posix-over-Win32 layer http://pw32.sourceforge.net/main.html [7.32] The Posix Basic Regular Expression language http://www.delorie.com/gnu/docs/rx/rx_3.html [7.33] Programming Posix threads http://www.humanfactor.com/pthreads/ [7.34] POSIX Threads Tutorial http://www.math.arizona.edu/swig/pthreads/threads.ht ml [7.35] Legion The Grid operating system http://legion.virginia.edu/presentations/UMBC-Apr2001/ [7.50] 2K Motivation [7.36] Tutorial Interactivo Programación II http://sistemas.ing.ula.ve/sistemas/pd20/ [7.51] Quality assurance tips [7.37] Los Modelos Dinámicos y la Ingeniería del Software Isabel Ramos Román, isabel.ramos@lsi.us.es http://www.sc.ehu.es/jiwdocoj/remis/docs/modelos.ht ml [7.38] Introducción a la Ingeniería de Software Lic. Yadira Esparza Rodríguez http://www.uag.mx/66/portada.htm http://developer.apple.com/testing/docs/TNqatips.html [7.52] JX operating system http://www4.informatik.uni-erlangen.de/Projects/JX/ [7.53] A Brief History of PC Operating Systems http://www.viewz.com/shoppingguide/os2.shtml http://choices.cs.uiuc.edu/2k/Motivation.html [7.48] The Multiboot Specification OKUJI Yoshinori, Bryan Ford, Erich Stefan Boleyn, Kunihiro Ishiguro http://www.mcc.ac.uk/grub/multiboot_toc.html [7.49] Multiboot Standard - Version 0.6 http://www.uruk.org/orig-grub/boot-proposal.html [7.47] GNU GRUB http://www.gnu.org/software/grub/ [7.46] Patrones o Estilos de Arquitectura de Software http://www.dcc.uchile.cl/~cc61h/patrones/index.htm [7.39] Sitio www de apoyo al texto de R. Pressman. http://www.rspa.com/ [7.40] Software Architecture and Related Concerns http://www.bredemeyer.com/whatis.htm [7.41] Software Architecture: An Executive Overview http://www.sei.cmu.edu/publications/documents/96.rep orts/96.tr.003.html [7.42] Model Problems http://www-2.cs.cmu.edu/People/ModProb/ [7.43] Software Architecture Documentation in Practice: Documenting Architectural Layers http://www.sei.cmu.edu/publications/documents/00.rep orts/00sr004.html [7.44] Introduction to the Architecture-Based Design Method" tutorial http://www.sei.cmu.edu/plp/symposium00/ABD/current _activities.html [7.45] Seminario de Arquitectura de Software http://www.dcc.uchile.cl/~cc61h/intro/index.htm

281

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
[7.54] Operating System 2010 by Steven J. VaughanNichols Byte. November 5, 2001 http://www.byte.com/documents/s=1778/byt20011031 s0004/ [7.55] The Design and Implementation of the 4.4BSD Operating System Marshall Kirk McKusick, Keith Bostic, Michael J. Karels, John S. Quarterman Addison-Wesley Longman, Inc, 1996 http://www.freebsd.org/doc/en_US.ISO88591/books/design-44bsd/ [7.56] DROS http://www.dros.com/ [7.57] Software Architecture in Practice http://www.cs.vu.nl/~hansdb/state/node6.html [7.58] Architectural Styles, Design Patterns and Objects. Robert T. Monroe, Andrew Kompanek, Ralph Melton, and David Garlan [7.70] Fundamentals of Swing: Part I Short Course By MageLang Institute http://developer.java.sun.com/developer/onlineTraining /GUI/Swing1/shortcourse.html [7.71] MVC meets Swing Todd Sundsted http://www.javaworld.com/javaworld/jw-04-1998/jw04-howto_p.html [7.72] Bambookit GUI - XML GUI Software Architecture http://www.bambookit.com/_architecture.html [7.59] Architectural patterns http://www.rational.com/products/whitepapers/390.jsp [7.60] Architectural Patterns, Design Patterns, Idioms http://www.tml.hut.fi/Opinnot/Tik-109.450/1998/niska/ [7.61] Architectural patterns http://www.opengroup.org/togaf/p4/patterns/patterns. htm [7.62] Layers http://home.earthlink.net/~huston2/dp/layers.html [7.63] Sistemas operativos- prácticas y apuntes http://www.dc.uba.ar/people/materias/so/html/practica s.html [7.64] Operating Systems Widely Used on Personal Computers http://www.abilityhub.com/information/os.htm [7.78] GUI – Webopedia [7.65] The X Window system http://www.viewtouch.com/xwindows.html [7.66] OPERATING SYSTEMS http://www.computerhope.com/os.htm http://www.webopedia.com/TERM/G/Graphical_User_I nterface_GUI.html [7.79] Interpreter pattern http://home.earthlink.net/~huston2/dp/interpreter.html [7.73] Java Look and Feel Design Guidelines, second edition. Copyright 2001. Sun Microsystems http://java.sun.com/products/jlf/ed2/book/HIGTitle.htm l [7.74] Microsoft, Apple and Xerox. The History of the Graphical User Interface . David K. Every http://www.mackido.com/Interface/ui_history.html [7.75] Mouse Site http://sloan.stanford.edu/MouseSite/ [7.76] IBM Ease of use http://www3.ibm.com/ibm/easy/eou_ext.nsf/publish/558 [7.77] User interface Markup Language http://www.uiml.org/index.php [7.67] WCEfA. Using Automotive Graphical User Interface http://msdn.microsoft.com/library/default.asp?url=/libr ary/en-us/apcguide/htm/acc_guide_1.asp [7.68] WCEfA. Using Automotive Speech Architecture http://msdn.microsoft.com/library/default.asp?url=/libr ary/en-us/apcguide/htm/spc_overview_1.asp [7.69] A Graphical User Interface Toolkit Approach to Thin-Client Computing Simon Lok, Steven K. Feiner, William M. Chiong and Yoav J. Hirsch http://www2002.org/CDROM/refereed/577/

IEEE Software, January 1997, pp. 43-52.
http://pecan.srv.cs.cmu.edu/afs/cs/project/able/www/p aper_abstracts/ObjPatternsArch-ieee.html

282

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
[7.80] Interpreter - AGCS http://www.agcs.com/supportv2/techpapers/patterns/p apers/tutnotes/sld021.htm [7.81] HCI- Webopedia http://www.webopedia.com/TERM/H/HCI.html [7.82] Human Interface Devices http://www.nondot.org/sabre/os/articles/HumanInterfa ceDevices/ [7.83] VR Interface devices http://archive.ncsa.uiuc.edu/Cyberia/VETopLevels/VR.I nterface.html [7.84] ATRC – Neural interface devices http://www.utoronto.ca/atrc/reference/tech/neuralinter face.html [7.85] Architecture of the Runtime Engine http://developer.apple.com/techpubs/macosx/Carbon/g raphics/OpenGL/OpenGL/chap2/chapter_2_section_4.ht ml [7.86] User Interface Design Common Front Group http://cfg.cit.cornell.edu/cfg/design/contents.html [7.87] GUI Gallery http://toastytech.com/guis/ [7.93] BolinOS http://www.med-ia.ch/med-ia/bolinos/ [7.89] ACM SIGCHI Curricula for Human-Computer Interaction http://sigchi.org/cdg/index.html [7.90] System Management Concepts: Operating System and Devices. IBM. http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_ lib/aixbman/admnconc/admnconctfrm.htm [7.91] Windows 95 System Management Architecture Windows Development Management Technical Articles July 26, 1994 http://msdn.microsoft.com/archive/default.asp?url=/arc hive/en-us/dnarmgmt/html/msdn_chic_mgt.asp [7.92] Web-based System Manager Administration Guide. IBM. http://publib16.boulder.ibm.com/pseries/en_US/aixbma n/wsmadmn/mastertoc.htm [7.88] Mac OS X Update: Quartz & Aqua John Siracusa http://www.arstechnica.com/reviews/1q00/macos-xgui/macos-x-gui-1.html

283

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

284

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Capitulo 8. Arquitecturas de Sistemas Operativos
La imaginación es más importante que el conocimiento.
Albert Einstein

Recurrimos a la televisión para apagar el cerebro, y a la computadora para encenderlo.
Steve Jobs

Después de explicar qué es un sistema operativo, cuáles son sus partes y cómo funciona, quedan por responder las incógnitas referentes a su estructura, tales como: • • • • ¿por qué algunos sistemas tienen más (o menos) elementos que otros? ¿por qué algunos son portables entre distintas computadoras? ¿cómo están construidos? ¿de qué (o de quién) depende que un SO tenga más (o menos) servicios?

Para poder responder lo anterior, debemos hablar de la etapa de concepción del software, donde se decide qué se quiere hacer y hasta dónde llegar. Es en esta fase del desarrollo de cualquier sistema donde se plantea una arquitectura, que es la descripción de la estructura de un sistema y la información que lo hace funcionar. La arquitectura de un sistema representa el siguiente paso en su desarrollo, después de la definición de requerimientos del usuario durante la etapa de análisis. Durante la definición de una arquitectura, la estructura del sistema y el software serán definidos con todos los subsistemas y la estructura de los datos a procesar. Aunque ya sabemos que hay servicios básicos de administración de memoria, procesos y recursos, la forma en que interactúan, se configuran y se complementan es parte de las decisiones y especificaciones que se hacen al definir la arquitectura del sistema. Así que si se quiere aspirar a diseñar un sistema operativo, lo más prudente será hablar un poco sobre arquitectura de software, para luego abordar los paradigmas en arquitectura de sistemas operativos que se han desarrollado desde la aparición de estos sistemas, para luego analizar algunos casos particulares. La idea es contar con una referencia de elementos concretos de diseño para poder establecer lineamientos y criterios para el diseño de este tipo de sistemas.

285

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

8.1

Representación de la arquitectura

Por lo general, en casi todos los documentos consultados relacionados a describir la arquitectura de los sistemas operativos, aparecen diagramas como el de la figura 8.1 Aunque esto pueda parecer informal, es un enfoque muy gráfico de lo que se quiere lograr.

Figura 8.1 Arquitectura de Windows NT representada en un esquema de módulos.
Si se desea un poco más de rigor en la especificación, pueden utilizarse diagramas de paquetes UML (parte de la vista lógica), utilizando el patrón de capas (layers). Este patrón ayuda a estructurar aplicaciones que pueden ser descompuestas en grupos de subtareas, en donde cada grupo de subtareas se encuentra en un nivel particular de abstracción (fig. 8.2).

286

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Sys tem Service s N T Kerne l archite cture

R es ource Mana ger

Ker nel

H AL

H ar dw are

Figura 8.2 Especificación formal de alto nivel de la arquitectura de Windows NT usando UML (paquetes y relaciones).
Obviamente puede continuarse con la especificación de los detalles usando UML, pero los esquemas de módulos son útiles (y hasta más amigables) para representar el contexto general de una arquitectura, razón por la cual se incluyen en las siguientes secciones donde se discuten las arquitecturas de los sistemas operativos.

8.2

Arquitecturas de Sistemas Operativos⊕

Un sistema operativo abstrae y protege los recursos de hardware; por ejemplo abstrae la memoria física en términos de memoria virtual, los bloques de un disco en archivos, y las excepciones y CPU en procesos. Esta organización tiene 3 beneficios principales: • • se provee una interfaz portable al hardware de la máquina, por lo que las aplicaciones no necesitan preocuparse de los detalles del hardware. provee una plataforma funcional, eliminando la necesidad de que los desarrolladores escriban manejadores de dispositivos, u otro código de bajo nivel. Obras consultadas: [8.1] [8.12]

287

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

provee protección, pues al controlar el uso de recursos de las aplicaciones, el SO previene que se comprometa la integridad del sistema entero.

Por ello, su estructura tiene un gran impacto en el desempeño y alcance de las aplicaciones que pueden construirse sobre él. Así como hay principios que definen las arquitecturas de hardware (ver capítulo 2) y puesto que el diseño de los sistemas operativos es dependiente de este, es de esperarse que exista una estructura similar de funciones para los SOs. Además de las funciones que un SO debe proveer para operar por completo (funciones centrales o core functions), hay un amplio conjunto de servicios que el usuario espera de un SO. Algunas veces estos servicios son hechos por otros desarrolladores que quieren expandir las capacidades de un SO, definiendo nuevas habilidades que eventualmente serán agregadas al SO (a veces por optimización, a veces solo para eliminar a la competencia) El objetivo principal de las propuestas de nuevas arquitecturas en los sistemas operativos, es mejorar los conceptos estructurales tales como la planificación, interacción y administración de recursos. Existen muchos tipos de modelos de sistemas operativos. Algunos son usados en sistemas comerciales o de distribución gratuita, mientras que otros están siendo inventados en las universidades como parte de proyectos de investigación. Todos los tipos de sistemas operativos tienen sus ventajas y desventajas, al ser hechos para diferentes tipos de hardware o con diferentes propósitos. Hablar de ventajas y desventajas es difícil, pues la mayoría de los sistemas operativos están enfocados a un grupo de usuarios o aplicaciones específico, o son usados en configuraciones específicas de sistemas de cómputo. En las siguientes secciones, se exponen diferentes arquitecturas de sistemas operativos con el fin de analizar la evolución en su estructura, principalmente en la forma en que los servicios del sistema están organizados y construidos, y además se presentan algunos casos de estudio concretos para aplicar los conceptos expuestos.

8.3

Arquitectura de kernel monolítico⊕

En esta arquitectura el sistema operativo se escribe como una colección de procedimientos, cada uno de los cuales puede invocar a cualquiera de los otros cuando necesita hacerlo. Cuando se usa esta técnica, cada procedimiento del sistema tiene una interfaz bien definida en términos de parámetros y resultados, y cada uno está en libertad de invocar a cualquier otro, si este último realiza algún cálculo útil para el primero que lo necesita.

Obras consultadas: [8.31] [8.32] [8.33] [8.34] [8.35] [8.36]

288

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 8.3 Arquitectura de kernel monolítico
Para construir el programa objeto de un SO bajo este enfoque, lo primero es compilar todos los procedimientos individuales, o archivos que los contienen, y luego se vinculan en un solo archivo objeto. Los servicios (llamadas al sistema) proporcionados por el SO se solicitan colocando parámetros en lugares bien definidos, como en registros o en pilas, y ejecutando después una instrucción de trampa especial conocida como llamada al kernel o llamada al supervisor, la cual conmuta la máquina del modo de usuario, al modo de kernel y transfiere el control al SO. Esta organización sugiere una estructura básica que consiste en: 1. Un programa principal que invoca el procedimiento de servicios solicitado. 2. Un conjunto de procedimientos de servicio que llevan a cabo las llamadas al sistema. 3. Un conjunto de procedimientos de utilería que ayudan a los procedimientos de servicio. La arquitectura más antigua usada para los sistemas operativos es la de kernel monolítico. Un kernel monolítico puede ser fácilmente implementado si se está preparado para aceptar una alta latencia (p.ej. dar servicio a peticiones sin importar la urgencia de otras peticiones). Los kernels monolíticos más nuevos (p.ej. UNIX) tienen un diseño modular, que ofrece la adición o remoción de servicios a tiempo de ejecución. El kernel entero se ejecuta en modo supervisor, un modo de procesador en el que el software tiene control absoluto de la máquina. Los procesos que se ejecutan sobre el kernel se ejecutan en modo de usuario, en el que los programas solo tienen acceso a los servicios del kernel. Un ejemplo de la vigencia de este enfoque lo encontramos en Linux (Linus B. Torvalds, 1991). Linux fue desarrollado originalmente para ejecutarse en microprocesadores Intel 386. La versión original no era portable a otras plataformas a causa del uso de rutinas específicas para el manejo de interrupciones de Intel.

289

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Como otros sistemas operativos, Linux mantiene seguimiento de archivos en disco, ejecuta programas, y multiplexa el procesador y otro hardware para proveer multitarea, asigna memoria y otros recursos a varios procesos, recibe y envía paquetes por medio de una red. Este sistema operativo tiene dos partes principales: 1. El Shell, el cual lee las ordenes del usuario y los traduce para enviarlas al kernel. 2. El Kernel, el cual interactúa directamente con el hardware del sistema. El kernel mantiene mucha de la información sobre el estado del sistema (la mayor parte en memoria física). Hay varias estructuras de datos en el kernel cuyo propósito es apoyar las funciones de los subsistemas (o componentes) del kernel. En realidad, los módulos de Linux "pueden compartir datos" con cualquier otro módulo. Esto es por que el kernel tiene una estructura monolítica (el sistema operativo está escrito como una colección de procedimientos, cada uno de los cuales puede llamar a cualquier otro cuando lo necesite).

Figura 8.4 Arquitectura conceptual de Linux38

8.4

Arquitectura de capas y anillos

Dijkstra introdujo la arquitectura de capas cuando desarrollo el sistema THE (1968), un sencillo sistema de procesamiento por lotes (figura 8.6). El sistema tenia seis capas: • La capa 0 se ocupaba del reparto del microprocesador (multiprogramación básica del CPU).

38

Imagen reproducida de [8.35]

290

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• • • •

La capa 1 administraba la memoria, repartiendo espacio para los procesos. Arriba de esta capa, los procesos no tenían que preocuparse por si estaban en la memoria o en un tambor. La capa 2 manejaba la comunicación entre cada proceso y la consola del operador. La capa 3 administraba los dispositivos de entrada/salida. En la capa 4 se encontraban los programas de usuario y El proceso del operador del sistema estaba en la capa 5.

Figura 8.5 Esquema de la organización en capas de un sistema operativo
Una forma más generalizada del concepto de capas estuvo presente en el sistema MULTICS, el cual estaba organizado como una serie de anillos concéntricos, siendo los interiores más privilegiados que los exteriores. Cuando un procedimiento exterior quería invocar alguno de un anillo interior, tenía que emitir el equivalente a una llamada al sistema, cuyos parámetros se analizaban cuidadosamente para comprobar su validez antes de permitir que la llamada procediera. Aunque todo el sistema formaba parte del espacio de direcciones de cada proceso de usuario, el hardware permitía designar procedimientos individuales como protegidos contra lectura, escritura o ejecución.

Figura 8.6 Organización del sistema operativo en anillos 291

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

En tanto que el esquema por capas del sistema THE era en realidad solo una ayuda para el diseño, ya que todas las partes del programa en última instancia se vinculaban en un solo programa objeto, en MULTICS el mecanismo de anillo estaba muy presente en el momento de la ejecución y el hardware obligaba a ajustarse a él. La ventaja del mecanismo de anillo es que se puede extender fácilmente para estructurar los subsistemas de usuario. No siempre es fácil tener una verdadera arquitectura de capas puesto que algunas funcionalidades pueden describirse como mutuamente dependientes, además de que esta arquitectura es comúnmente ineficiente al requerir un gran número de interfases transversales. Un caso donde este enfoque ha sido refinado es el del Mac OS X, el cuál tiene 4 capas distintas de software del sistema: • Ambientes de aplicación. Existen 5 ambientes de aplicación (ejecución): Carbon, Cocoa, Java, Classic, y comandos BSD. Para los desarrolladores los primeros 3 ambientes son los más importantes. Mac OS X incluye herramientas de desarrollo y a tiempo de ejecución para estos ambientes. Servicios de aplicación. Incorpora los servicios del sistema disponibles para todos los ambientes de aplicación que tienen algún impacto en la interfaz gráfica de usuario. Incluye Quartz, QuickDraw, y OpenGL así como los administradores esenciales del sistema. Servicios del núcleo. Incorpora aquellos servicios que no tienen efecto en la interfaz gráfica. Incluye Core Foundation, Open Transport, y ciertas porciones del núcleo de Carbon. Ambiente del Kernel. Provee la capa fundamental del Mac OS X. Sus componentes primarios son Mach y BSD, pero también incluye servicios y pilas de protocolos de red, sistemas de archivos y manejadores de dispositivos. El ambiente del kernel ofrece facilidades para desarrollar manejadores de dispositivos (I/O Kit) y extensiones del kernel cargables, incluyendo NKEs (Network Kernel Extensions).

Figura 8.7 La característica central de la arquitectura de Mac OS X es la división en capas del software del sistema39

39

Imagen reproducida de [8.46]

292

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

8.5

Arquitectura de máquina virtual⊕

La idea principal de este enfoque es que por medio del software se proporcione a los programas la emulación de un hardware que "de facto" no existe. El software emulador convierte las peticiones hechas a la máquina virtual en operaciones sobre la máquina real (los recursos reales se reparten entre las distintas máquinas virtuales). Esta arquitectura crea una máquina virtual (p.ej. una IBM 370) para cada "usuario" y el usuario puede elegir que SO ejecutar en esa máquina virtual. Algunos ejemplos de máquinas virtuales son: A. IBM VM. Ofrecía a cada usuario su propia máquina mono-tarea, y las máquinas virtuales se planificaban por medio de tiempo compartido (los SOs más recientes de este tipo son VM/ESA y z/VM de IBM). B. Java VM. Permite ejecutar los códigos binarios (bytecode) en distintas plataformas sin necesidad de recompilar. C. VM Ware. Puede ejecutar al mismo tiempo varias sesiones de Windows, OS/2, Linux, etc. D. NachOS. Es un sistema operativo que se ejecuta en una máquina virtual MIPS, cuyo emulador corre sobre UNIX o Windows. El corazón del sistema, conocido como monitor de máquina virtual, se ejecuta en el hardware y realiza la multiprogramación, proporcionando no una, sino varias máquinas virtuales a la siguiente capa superior. Sin embargo, a diferencia de otros sistemas operativos, estas máquinas virtuales no son máquinas extendidas, con archivos y otras características "accesibles", sino que son copias exactas del hardware, incluido el modo de kernel/usuario, E/S, interrupciones y todo lo que una máquina real tiene. La ventaja es que estos monitores son más pequeños y simples pues no proveen ningún servicio de usuario; son simples simuladores de hardware, y pueden ejecutar diferentes sistemas operativos en una misma máquina.

Figura 8.8 Esquema de una arquitectura de máquina virtual
Puesto que cada máquina virtual es idéntica al verdadero hardware, cada una puede ejecutar cualquier sistema operativo que se ejecutaría directamente en el hardware. Diferentes máquinas virtuales pueden ejecutar diferentes sistemas (p.ej. algún descendiente del OS/360, CMS, etc.).

Obras consultadas: [8.2]

293

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 8.9 Niveles de máquinas virtuales
En el caso de VM/370, cuando un usuario ejecuta una llamada al sistema, la llamada se atrapa y se envía al sistema operativo de su propia máquina virtual. Al emitir señales de E/S (por ejemplo para leer un disco virtual), tales instrucciones son atrapadas por el VM el cual las ejecuta como parte de la simulación del hardware. Al separar por completo las funciones de multiprogramación y de suministro de una máquina extendida, cada uno de los componentes puede ser mucho más sencillo, flexible y fácil de mantener (fig. 8.10). Esta arquitectura es elegante, pero no trata con cuestiones de administración de recursos o responsabilidades.

294

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 8.10 Convivencia entre el sistema operativo nativo y el creado por la máquina virtual40

8.6

Arquitectura de microkernel y multihilado⊕

La arquitectura de microkernel es muy moderna (Mach, OSF, QNX y Windows NT). Esta radica en: • • • sacar la mayor parte de funcionalidad del kernel, limitarlo a ejecutarlo en modo privilegiado, y permitir fáciles modificaciones y extensiones.

La arquitectura de microkernel permite construir una gran variedad de sistemas operativos usando el mismo microkernel. Cada SO hará uso de diferentes procesos del sistema. Las interacciones entre procesos involucran la intervención del kernel, por lo que la eficiencia en la transferencia entre modo de usuario y de kernel debe ser muy alta. Los diseños de microkernels colocan la mayoría de los servicios del SO en procesos separados, que pueden ser iniciados o detenidos a tiempo de ejecución, lo que hace al kernel mucho más pequeño y se ofrece una gran flexibilidad. Los sistemas de archivos, controladores de dispositivos, administración de procesos e incluso parte del manejo de memoria pueden ser colocados en procesos que se ejecuten sobre el kernel (fig. 8.11).

40 ⊕

Imagen reproducida de [8.2] Obras consultadas: [8.6] [8.7] [8.8] [8.13] [8.14]

295

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

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.
Esta arquitectura es de hecho un modelo cliente-servidor, donde los procesos (clientes) pueden llamar procesos del SO enviando peticiones por medio del IPC a los procesos servidores (p.ej. un proceso que quiera leer un cierto archivo envía una petición al proceso del sistema de archivos). Los procesos centrales que proveen la administración de procesos, sistemas de archivos, etc., son llamados servidores. Algunos microkernels han adoptado un esquema de multihilado, colocando a cada servicio en un hilo diferente, ofreciendo gran velocidad y estabilidad. Este cambio se basa en mejorar la eficiencia. Todos los cambios de contexto que se requieren en la arquitectura de micro-kernel para ir del kernel a las tareas del sistema y de regreso, son reemplazados por llamadas a subrutinas dentro del mismo kernel, con un gran ahorro de tiempo. Por supuesto la escritura del kernel se vuelve más compleja, pues dentro de un solo espacio de direcciones y un solo modo puede tenerse más de una acción concurrente (p.ej. Solaris, usa esta arquitectura). Con el multihilado, no solo los programas de usuario pueden crear múltiples tareas a voluntad, sino que controladores de dispositivos y otros servicios del kernel pueden crear sus propias tareas, llamadas hilos del kernel. Los hilos del kernel permiten una mejor planificación del manejo de interrupciones, pues cierto código (de E/S de discos o red) que era parte del manejador de interrupciones puede colocarse en un hilo de manera que no interfiere con el procesamiento. Por lo tanto, es posible planificar tareas de usuario críticas a que se ejecuten con una prioridad más alta, que el hilo del kernel encargado del manejador de dispositivo, por lo que las tareas de usuario responden más rápido a los eventos.

296

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Por lo general, un microkernel implementa funciones específicas de la plataforma tales como multihilado, multiprocesamiento, administración de la memoria, manejo de interrupciones, y aceleración nativa para operaciones criticas del sistema (p.ej. salida de video).

Figura 8.12 Esquema de la arquitectura del Palm OS. El núcleo de este sistema es el microkernel AMX (Kadak) que implementa multiprocesamiento41
La mayor dificultad del modelo de microkernel es hacer que el servicio de comunicación entre procesos sea tan rápido como sea posible. Este fue un problema de diseño en los primeros microkernels, pues a veces se causaban cuellos de botella en lugar de optimizaciones, aunque actualmente se ha superado dicho problema. Cuando se habla de microkernels, debe diferenciarse entre dos generaciones. La primera generación, como Mach, son pesados y proveen muchos servicios, o varias maneras de hacer las mismas tareas. La segunda generación, como L4 y QNX, implementan kernels solo con las abstracciones necesarias, con una sencilla y clara interfaz (API).

41

Imagenes reproducidas de [8.13] y [8.14]

297

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

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 sistema42

8.7

Arquitecturas Orientadas a Objetos⊕

Aunque no existe una definición exacta, los Sistemas Operativos Orientados a Objetos (SOOO) son sistemas que proveen recursos por medio de objetos. Imaginemos un sistema de cómputo como una colección de procesos y objetos. Un sistema consiste de objetos de hardware: CPU, segmentos de memoria, impresoras, unidades de almacenamiento (discos, cintas); y objetos de software: archivos, programas y semáforos. Puede considerarse a los objetos como tipos de datos abstractos. Cada objeto es un tipo abstracto de datos único que se diferencia de todos los demás objetos y puede ser accedido por medio de operaciones bien definidas. Tales operaciones son diferentes para cada objeto (por ejemplo, la memoria puede accederse solo por medio de operaciones de lectura y escritura). A la hora de diseñar un modelo de cómputo, existen dos alternativas diferentes que definen dos modelos diferentes y dos conjuntos de características diferentes para los objetos. a. Modelo de Objetos Pasivo. Este modelo divide los objetos, desde el punto de vista de la computación, en pasivos y activos. Los primeros sólo son meros contenedores de datos y métodos; no tienen ninguna capacidad para la ejecución y, por tanto, dependen de otros objetos para la ejecución de sus métodos. Los segundos, proporcionan la capacidad computacional y son capaces de ejecutar sus métodos. Representan el flujo de ejecución y pueden involucrar métodos

42 ⊕

Imagen reproducida de [8.7] Obras consultadas: [8.3] [8.4] [8.5] [8.30]

298

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

ofrecidos por más de un objeto. De esta forma su vida es independiente de aquellos objetos que atraviesa en su ejecución. b. Modelo de Objetos Activo. Este modelo define un objeto con más contenido semántico. Los objetos se definen de forma homogénea como entidades con un ciclo de vida propio que no se limitan a encapsular datos y métodos sino que disponen de sus propios recursos de computación. En este modelo, el objeto es una entidad autónoma que interacciona con otros objetos en el sistema. El mecanismo usado para la comunicación es el paso de mensajes. Generalmente un sistema se dice que es orientado a objetos si por lo menos una de sus partes está hecha con orientación a objetos. Los primeros SOOO eran relativamente simples (p.ej., Genera, el primer SOOO comercial; ambiente de desarrollo en máquinas LISP). A diferencia de la mayoría de los sistemas operativos (como UNIX), Genera tenia una estructura abierta, lo que significa que no tenia una estructura supervisor/usuario. Tampoco tenía un núcleo, a excepción de un programa de arranque. No hay diferencia entre programas de sistema o de usuario. El usuario puede accesar fácilmente cualquier archivo que necesite, por lo que no se requiere emplear recursos para separar y controlar los archivos del sistema y el usuario, lo que ahorra espacio en memoria y acelera la ejecución de procesos. Cada parte del sistema tiene su propia implementación. Un típico SOOO en general consiste de un administrador de archivos, administrador de dispositivos, administrador de memoria y una estructura de manejo de excepciones. Un legado importante de este tipo de sistemas es el uso de administradores de memoria automáticos. Es muy difícil mantener la pista de todos los objetos creados y destruirlos cuando no se necesitan más. Escribir código para manejar la memoria de esta forma es muy difícil y por lo general sujeto a errores. Los SOOO permiten la creación de tantos objetos como se quiera (limitado por supuesto a las características del sistema) pero sin la necesidad de destruirlos. El ambiente de ejecución elimina objetos cuando determina que ya no están siendo usados. Este proceso se conoce como recolección de basura (garbage collection). El algoritmo del recolector es bastante simple. Se revisan dinámicamente las áreas de memoria en busca de objetos, y marca aquellos que están referenciados. Después de investigar todas las posibles rutas a los objetos, aquellos que no se marcaron se recolectan. En otras palabras, el sistema solo asume que todo lo que no está marcado es espacio libre. El recolector de basura por lo general se ejecuta de forma síncrona cuando el sistema se queda sin memoria, o en respuesta a una petición de un programa. De otra forma, se ejecuta asíncronamente cuando el sistema esta ocioso. Desafortunadamente la recolección de basura requiere mucho tiempo para completar su tarea, lo que la hace una técnica inadecuada para sistemas de tiempo real, aunque puede ser útil si se implementa de forma que se ejecute en partes, teniendo en cuenta que nunca debe interferir con los procesos de prioridad alta, y que debe ejecutarse durante el procesamiento de procesos de prioridad baja y tiempo de ocio del procesador (por lo que su prioridad debe ser media).

299

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 plataforma43
Uno de los SOOO más recientes es el 3-D Visual OS (VOS) que es un nuevo sistema operativo basado en los conceptos de la programación orientada a objetos (en términos de adaptación y el uso de componentes disponibles) y la programación visual (en términos del despliegue de módulos de software). Esto implica que los usuarios pueden usar un editor gráfico para crear y programar su ambiente y aplicaciones, relacionando los módulos de software apropiados. En comparación a las herramientas de programación visual convencionales, el sistema propuesto tiene las ventajas de la visualización tridimensional, permitiendo una representación estructurada clara de los módulos de programa interconectados. Este SO se ejecuta en una computadora Silicon Graphics Onyx y usa el software de realidad virtual dVS de Division Ltd. como base de los gráficos 3-D y para implementar las interacciones con el usuario. El SO subdivide todos los módulos de software accesibles al usuario en 3 niveles de complejidad: • •
43

primitivas como las unidades más pequeñas (funciones aritméticas o gráficas básicas), componentes, y Imagen reproducida de [8.5]

300

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

aplicaciones de gran escala (agregaciones de los módulos de bajo nivel).

Figura 8.15 La red de módulos de software que forma una aplicación puede visualizarse en distintos niveles44

8.7.1 Sistemas operativos basados en componentes⊕
Los sistemas operativos basados en componentes traen los beneficios de la orientación a objetos de la cual disfrutan las aplicaciones, a los sistemas operativos. Si se logra, los desarrolladores de sistemas, los desarrolladores de aplicaciones y los usuarios se verán beneficiados. Los diseñadores de sistemas operativos se beneficiarán de las técnicas de ingeniería de software tales como la orientación a objetos y manejo de excepciones (tal como lo han disfrutado los desarrolladores de aplicaciones en los 1990s). Los desarrolladores de aplicaciones se beneficiarán de servicios y abstracciones del SO, más apropiados para la ingeniería de software moderna.

44 ⊕

Imagen reproducida de [8.30] Obras consultadas: [8.29]

301

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 8.16 Arquitectura del sistema operativo Go45

8.8

Arquitectura cliente-servidor⊕

La arquitectura cliente/servidor es un modelo para el desarrollo de sistemas de información, en el que las transacciones se dividen en procesos independientes que cooperan entre sí para intercambiar información, servicios o recursos. Se denomina cliente al proceso que inicia el diálogo o solicita los recursos, y servidor al proceso que responde a las solicitudes. Es el modelo de interacción más común entre aplicaciones en una red. No forma parte de los conceptos de la Internet como los protocolos IP, TCP o UDP, sin embargo todos los servicios estándares de alto nivel propuestos en Internet funcionan según este modelo. Los principales componentes del esquema cliente/servidor son entonces los Clientes, los Servidores y la infraestructura de comunicaciones. En este modelo, las aplicaciones se dividen de forma que el servidor contiene la parte que debe ser compartida por varios usuarios, y en el cliente permanece sólo lo particular de cada usuario.

45 ⊕

Imagen reproducida de [8.29] Obras consultadas: [8.42]

302

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Los Clientes interactúan con el usuario, usualmente en forma gráfica. Frecuentemente se comunican con procesos auxiliares que se encargan de establecer conexión con el servidor, enviar el pedido, recibir la respuesta, manejar las fallas y realizar actividades de sincronización y de seguridad. Los clientes realizan generalmente funciones como: • • • Manejo de la interfaz de usuario. Captura y validación de los datos de entrada. Generación de consultas e informes sobre las bases de datos.

Los Servidores proporcionan un servicio al cliente y devuelven los resultados. En algunos casos existen procesos auxiliares que se encargan de recibir las solicitudes del cliente, verificar la protección, activar un proceso servidor para satisfacer el pedido, recibir su respuesta y enviarla al cliente. Además, deben manejar los interbloqueos, la recuperación ante fallas, y otros aspectos afines. Por las razones anteriores, la plataforma computacional asociada con los servidores es más poderosa que la de los clientes. Por esta razón se utilizan PCs poderosas, estaciones de trabajo, minicomputadoras o sistemas grandes. Además deben manejar servicios como administración de la red, mensajes, control y administración de la entrada al sistema (login), auditoria y recuperación y contabilidad. Usualmente en los servidores existe algún tipo de servicio de bases de datos. En ciertas circunstancias, este término designará a una máquina. Este será el caso si dicha máquina está dedicada a un servicio particular, por ejemplo: servidores de impresión, servidor de archivos, servidor de correo electrónico, etc. Por su parte los servidores realizan, entre otras, las siguientes funciones: • • • • Gestión de periféricos compartidos. Control de accesos concurrentes a bases de datos compartidas. Enlaces de comunicaciones con otras redes de área local o extensa. Siempre que un cliente requiere un servicio lo solicita al servidor correspondiente y éste, le responde proporcionándolo. Normalmente, pero no necesariamente, el cliente y el servidor están ubicados en distintos procesadores. Los clientes se suelen situar en computadoras personales y/o estaciones de trabajo y los servidores en procesadores departamentales o de grupo.

Para que los clientes y los servidores puedan comunicarse se requiere una infraestructura de comunicaciones, la cual proporciona los mecanismos básicos de direccionamiento y transporte. La mayoría de los sistemas Cliente/Servidor actuales, se basan en redes locales y por lo tanto utilizan protocolos no orientados a conexión, lo cual implica que las aplicaciones deben hacer las verificaciones. La red debe tener características adecuadas de desempeño, confiabilidad, transparencia y administración. Entre las principales características de la arquitectura cliente/servidor, se pueden destacar las siguientes: • El servidor presenta a todos sus clientes una interfaz única y bien definida. • • • El cliente no necesita conocer la lógica del servidor, sólo su interfaz externa. El cliente no depende de la ubicación física del servidor, ni del tipo de equipo físico en el que se encuentra, ni de su sistema operativo. Los cambios en el servidor implican pocos o ningún cambio en el cliente.

303

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Como ejemplos de clientes pueden citarse interfaces de usuario para enviar comandos a un servidor, APIs para el desarrollo de aplicaciones distribuidas, herramientas en el cliente para hacer acceso a servidores remotos (por ejemplo, servidores de SQL) o aplicaciones que solicitan acceso a servidores para algunos servicios. Como ejemplos de servidores en el software del sistema, pueden citarse servidores de ventanas como X-Window, servidores de archivos como NFS; en el software de aplicación tenemos servidores para el manejo de bases de datos (como los servidores de SQL), servidores de diseño y manufactura asistidos por computadora, etc.

Figura 8.17 Arquitectura del sistema X Window, para el intercambio de mensajes de interfaz gráfica de usuario46
En el modelo Cliente/Servidor la idea es dividir el SO en varios procesos, cada uno de los cuales implementa un conjunto simple de servicios (asignación de memoria, creación de procesos, asignación del procesador). NT usa el modelo cliente/servidor principalmente para proveer APIs, los servidores se comunican con las aplicaciones por paso de mensajes. Los principales beneficios del modelo cliente/servidor son: • • • • Simplifica la base del sistema operacional. Teniendo cada API en un servidor separado, se evitan conflictos y permite que nuevos APIs sean adicionados fácilmente. Aumenta la disponibilidad, porque cada servidor corre en un proceso separado. Como los servidores corren en modo usuario, no pueden acceder directamente el hardware o modificar la memoria en la cual el núcleo del sistema está almacenado

Implantación del modelo C/S para sistemas operativos distribuidos
Las principales opciones de diseño analizadas se resumen en: •
46

Protocolo de comunicaciones cliente - servidor.

Imagen reproducida de [8.57]

304

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Direccionamiento:
o Número de máquina. o Direcciones de procesos. o Búsqueda de nombres en ASCII por medio del servidor.

Bloqueo:
o Primitivas con bloqueo. o Sin bloqueo, con copia al núcleo. o Sin bloqueo, con interrupciones.

Almacenamiento en buffers:
o No usar el almacenamiento en buffers, descartar los mensajes inesperados. o Sin almacenamiento en buffers, mantenimiento temporal de los mensajes inesperados. o Buzones.

Confiabilidad:
o No confiable. o Solicitud - reconocimiento - respuesta - reconocimiento. o Solicitud - respuesta - reconocimiento

8.9

Arquitecturas en red y distribuidas⊕

Existen dos tipos básicos de redes: las Redes Locales (LAN) y las Redes de Área Amplia (WAN). La principal diferencia entre ambas es su distribución geográfica. Las redes locales están compuestas por procesadores distribuidos en un área geográfica pequeña, como un edificio o varios edificios adyacentes; en cambio las redes de área ancha, están formadas por varios procesadores autónomos distribuidos en un área geográfica extensa (como todo un país). Estas diferencias radican en la velocidad y confiabilidad de la red de comunicaciones y se ven reflejadas en el diseño del sistema operativo. Los sistemas operativos de red se definen como aquellos que tiene la capacidad de interactuar con sistemas operativos en otras computadoras a través de un medio de transmisión con el objeto de intercambiar información, transferir archivos, ejecutar comandos remotos y un sin fin de otras actividades. El punto crucial de estos sistemas es que el usuario debe saber la sintaxis de un conjunto de comandos o llamadas al sistema para ejecutar estas operaciones, además de la ubicación de los recursos que desee acceder.

Figura 8.18 Esquema de operación de un sistema operativo de red

Obras consultadas: [8.15] [8.16] [8.17] [8.40] [8.41] [8.43]

305

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Aunque los actuales sistemas de red solucionan parte de las necesidades actuales de comunicación entre computadoras, tienen importantes limitaciones, y no son aplicables a una gran cantidad de problemas. Por ello surge la necesidad de crear sistemas distribuidos que sustituyan a los actuales sistemas de red o a los sistemas multiprocesadores.

Figura 8.18a Arquitectura de Windows NT en referencia al modelo OSI47
Un sistema distribuido es un caso especial de una red de computadoras. Interconecta los lugares que tienen recursos computacionales, para capturar y almacenar datos, procesarlos y enviar datos e información a otros sistemas, tales como un sistema central. El rango de recursos computacionales varía. Algunos lugares utilizan terminales, otros microcomputadoras, otros incluso, grandes sistemas de cómputo. No existe el requisito de que todo el equipo sea del mismo fabricante. De hecho se espera que estén implicadas varias marcas de hardware. Esto permite al usuario tener el tipo más adecuado a sus necesidades. La diferencia de una red de computadoras y un sistema distribuido es que en una red de computadoras el usuario se conecta explícitamente con otra máquina. Explícitamente lanza tareas remotas, mueve archivos, etc. La diferencia radica en quién invoca las funciones del sistema. Todos los lugares (reciben el nombre de nodos en el procesamiento distribuido) tienen la capacidad de capturar y procesar datos en donde ocurran los eventos. En otras palabras, si un lugar específico usa una microcomputadora, los usuarios capturan y procesan datos en su
47

Imagen reproducida de [8.56]

306

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

minicomputadora. Reciben respuestas rápidas a sus consultas, almacenan datos en el sistema y preparan reportes cuando se necesitan. Sin embargo, también pueden transmitir datos o reportes desde su sistema a otro enlazado en la red, compuesta por todos los sistemas interconectados. Un sistema de procesamiento distribuido incluye: • Múltiples componentes de procesamiento de propósito general. Pueden asignarse tareas específicas a los sistemas de procesamiento sobre una base dinámica. Los sistemas no necesitan ser de una misma marca o tamaño. • Sistema operativo de alto nivel. Los nodos de procesamiento individual tienen su propio sistema operativo, el cual está diseñado para la computadora específica. Pero también hay un sistema operativo que los enlaza e integra al control de los componentes distribuidos. • Distribución física de los componentes. Las computadoras y otras unidades de procesamiento están separadas físicamente. Interactúan entre sí por medio de una red de comunicaciones. • Transparencia del sistema. Los usuarios no conocen la ubicación de un componente en el sistema distribuido o nada de su fabricante, modelo, sistema operativo local, velocidad o tamaño. Todos los servicios se piden por su nombre. El sistema operativo distribuido lleva a cabo todas las actividades que implican la ubicación física y atributos de procesamiento para satisfacer la demanda del usuario. • Papel dual de los componentes.- Los componentes individuales de procesamiento pueden operar independientemente del marco de trabajo del sistema distribuido

Figura 8.19 Esquema de operación de un sistema operativo distribuido
Están fuera de la clasificación como sistemas distribuidos, los siguientes: • Una computadora multifuncional grande, que distribuye el procesamiento entre varios procesadores de entrada/salida y periféricos. • • • • Un procesador primario, que controla las comunicaciones del sistema al cual fue añadido. Un conjunto de terminales remotas, que recogen y transmiten datos a un sistema anfitrión. La interconexión de varias computadoras anfitrionas, que transmiten mensajes y llevan a cabo funciones y tareas exclusivas. Una computadora que puede ser particionada, es decir capaz de operar diversas sesiones de procesamiento en forma simultánea, utilizando un sistema operativo especial.

307

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 8.20 Esquema del middleware y entornos distribuidos
Podemos citar como casos de sistemas operativos distribuidos a los siguientes: LynxOS, QNX, OS-9, JavaOS, Amoeba, Mach, Chorus e Inferno.

8.9.1 Criterios de diseño de sistemas distribuidos
El diseño más sencillo de este tipo de sistemas es el modelo cliente/servidor, donde el SO es estructurado como un grupo de procesos cooperativos llamados servidores que ofrecen servicios a los usuarios, llamados clientes. Síntomas de Distribución: • Multiproceso (concurrencia): El hardware permite el progreso simultáneo de varias actividades (varias CPUs, con memoria local, etc.). • • • Interconexión: Permite la comunicación entre las actividades. Relación: Uso compartido de recursos, información, etc. Fallo independiente: Permite buscar soluciones resistentes en caso de fallo (las comunicaciones también pueden fallar). Propiedades • • • Nombrado global: el mismo nombre es válido en todo el sistema. Acceso global: los mismos métodos actúan en objetos, en cualquier parte del sistema. Seguridad global: autenticación y acceso uniformes en todo el sistema.

• Disponibilidad global: funcionamiento correcto en presencia de fallos parciales. • Gestión global: posibilidad de gestión centralizada del sistema. Características funcionales • Cada usuario trabaja con su terminal local inteligente, con lo que obtiene mejores tiempos de respuesta. • Los recursos necesarios que no estén disponibles sobre el terminal local (computadora personal o estación de trabajo), pueden tomarse de la computadora central a través de la red de telecomunicaciones. Características físicas • Sistemas informáticos distribuidos en los que las computadoras, a través de la organización, están conectados por medio de una red de telecomunicaciones. • Cada computadora sobre la red tiene capacidad de tratamiento autónomo que permite servir a las necesidades de los usuarios locales. • • También proporciona acceso a otros elementos de la red o a servidores centrales. Toma importancia la red de comunicación de datos.

308

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Características lógicas • Cada tarea individual puede ser analizada para determinar si puede distribuirse o no. En general, las tareas más complejas o de carácter estratégico para la organización se mantienen en la computadora central. Las tareas de complejidad media o específica para un determinado grupo de usuarios, se distribuyen entre las máquinas locales de ese grupo. • La plataforma física seleccionada puede ajustarse a las necesidades del grupo de usuarios, con lo que surgen las computadoras especializadas para determinados tipos de tareas. Ventajas • Funcionamiento autónomo de los sistemas locales, lo que origina un buen tiempo de respuesta. • Los sistemas de información llegan a todos los departamentos de la empresa. • Abre posibilidades de trabajo mucho más flexibles y potentes. Inconvenientes • Requiere un intenso flujo de informaciones (muchas veces no útiles, como pantallas y datos incorrectos) dentro de la red, lo que puede elevar los costos de comunicaciones. • • Supone una mayor complejidad. Si los sistemas no están integrados, pueden producirse problemas de inconsistencia de datos.

8.9.2 Mach⊕
Como caso de estudio de un sistema operativo distribuido se tiene a Mach, que fue diseñado e implementado en la universidad de Carnegie-Melon (CMU) como una alternativa más estructurada y pequeña que el BSD UNIX (de hecho está basado en el sistema operativo Accent, también desarrollado en CMU). Su desarrollo empezó en 1985 y la primera versión de Mach estuvo disponible para la familia de computadoras DEC VAX (1986), y las versiones siguientes aparecieron con soporte pleno de multiprocesamiento (las máquinas que lo usaban eran sistemas multiprocesador con acceso uniforme a la memoria del sistema). La versión 2 fue portada a sistemas donde los procesadores compartían la memoria, pero cada procesador tenia acceso limitado a parte de la memoria del sistema. Actualmente se encuentra disponible para una gran variedad de sistemas, incluyendo maquinas con un procesador (SUN, IBM, Intel y DEC). Su objetivo principal es ser un sistema operativo distribuido capaz de funcionar con hardware heterogéneo y hasta ejecutar varios ambientes de sistemas operativos (después de ser recodificados para usar las capacidades de Mach) ejecutándose como aplicaciones. El sistema operativo Mach fue diseñado para proveer algunos mecanismos básicos que casi todos los sistemas operativos ofrecen, y ser compatible con BSD. Además:

Obras consultadas: [8.37]

309

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• •

• • •

Soportar diversas arquitecturas de hardware, incluyendo multiprocesadores UMA (Uniform Memory Access), NUMA (Non-Uniform Memory Access) y NORMA (No Remote Memory Access). Habilidad para funcionar con velocidades variables de transmisión en red (LAN y WAN). Estructura simplificada del kernel, con un pequeño número de abstracciones (se supone que las abstracciones deben ser suficientemente generales para ser utilizadas en la implementación de otros sistemas operativos basados en Mach). Operación distribuida, ofreciendo transferencia a los clientes en red y una organización orientada a objetos interna y externamente. Administración integrada de memoria y comunicación entre procesos, para proveer una basa clara y eficiente de comunicación y mecanismos de memoria con una sola estructura. Soporte de sistemas heterogéneos, para hacer que Mach este disponible en varios sistemas de cómputo.

Figura 8.21 Esquema de la arquitectura de Mach48
Los diseñadores de Mach se influenciaron por BSD (y en general UNIX), lo que dio como beneficios: • • • Una interfaz de programación simple, con un buen conjunto de servicios básicos (primitivas) y un conjunto consistente de interfases con el sistema. Sencilla portabilidad a una gran gama de sistemas con un procesador. Una amplia librería de utilerías y aplicaciones, así como la habilidad de combinar utilerías por medio de canales (pipes).

Aportaciones
Para alcanzar sus metas, el SO debía reducir su funcionalidad a un conjunto de abstracciones básicas, por medio del cual, todo servicio del sistema pueda derivarse. La filosofía de diseño de Mach es tener un kernel sencillo y extensible, centrado en servicios de comunicación. Por ejemplo, todas las peticiones al kernel, y todo el intercambio de datos entre los procesos, son manejados por medio de un mecanismo de comunicación. Limitar las operaciones de datos de esta forma, hace que Mach pueda ofrecer protección a sus usuarios,
48

Imagen reproducida de [8.38]

310

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

protegiendo el mecanismo de comunicación. Además el kernel puede extenderse, puesto que muchas de las funciones tradicionales del kernel pueden implementarse como servidores de nivel de usuario. Mach esta basado en el paradigma de la orientación a objetos, para facilitar su diseño y modificación (mientras en los sistemas tradicionales se tienen datos y operaciones que los manipulan, los sistemas orientados a objetos unifican estos dos componentes en un objeto abstracto, donde solo las operaciones del objeto pueden afectar las entidades definidas en el). Además esto permite a los objetos de Mach residir en cualquier lugar de una red de sistemas Mach, de forma transparente para el usuario (lo cual es un antecedente interesante de los sistemas de objetos distribuidos). Las abstracciones básicas soportadas por Mach son las siguientes: • Tarea (task). Es la unidad básica de alojamiento de recursos, y tiene una dirección de espacio virtual, y acceso protegido a los recursos del sistema. Una tarea posee procesadores, puertos y memoria virtual asociada a ella. • Hilo (thread). Es la unidad básica de ejecución. Es el objeto de trabajo más pequeño, y se ejecuta en el contexto de una tarea. Comparte los recursos de una tarea con otros hilos de la tarea (en Mach no existe la noción de proceso, aunque puede implementarse como una tarea con un solo hilo de control). • Puerto. Es el mecanismo básico de referencia de objetos en Mach. Toda la comunicación se hace por medio de puertos, los cuales son canales de comunicación unidireccionales que son administrados y protegidos por el kernel (son equivalentes a las colas de mensajes). Se invoca una operación sobre un objeto enviando un mensaje al puerto asociado con el objeto. El objeto representado por el puerto, recibe los mensajes. El emisor y el receptor deben tener derechos sobre los puertos para accesar el puerto. • Conjunto de puertos. Es un grupo de puertos que comparten una cola de mensajes común. Un hilo puede recibir mensajes de un conjunto de puertos, y por lo tanto dar servicio a varios puertos. Tal hilo, debe usar el identificador del puerto de destino para diferencias la función que se requiera. • Mensaje. Es el método básico de comunicación entre hilos en Mach. Es una colección de objetos de datos, que puede contener a los mismos datos, apuntadores a los datos o capacidades de puertos (para transferir capacidades de puerto a otro hilo). • Objeto de memoria. Es un elemento de memoria secundaria que es relacionado en el espacio de direcciones de una tarea. Por ejemplo, un archivo es administrado por un servidor de archivos, pero un objeto de memoria puede ser cualquier objeto para el que las peticiones de lectura y escritura puedan ser manejadas, como un pipe de UNIX Partes de Mach han sido incorporadas en varios sistemas operativos comerciales como: • • • • • • • Encore's Multimax NeXT OS MachTen para Macintosh Omron's Luna DEC's OSF/1 para el DEC Alpha IBM's OS/2 para máquinas basadas en el RS6000. Mac OS X

311

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 8.22 Arquitectura del microkernel Darwin del Mac OS X que integra el kernel Mach 3.0 y servicios del BSD UNIX49

8.10 Arquitecturas adaptables⊕
El proyecto Synthetix está investigando la aplicación de una técnica llamada especialización incremental, una combinación de modularidad de grano fino y generación dinámica de código, para crear sistemas operativos que sean muy modulares y de alto desempeño. La especialización incremental toma ventaja de circunstancias particulares, no solo a tiempo de compilación, sino también a tiempo de carga y de ejecución, para hacer optimizaciones especializadas. Por ejemplo, los protocolos de corrección de errores y compresión de datos en una conexión inalámbrica de bajo ancho de banda y baja calidad, son innecesarios en una conexión a una red de fibra óptica de alta calidad y gran ancho de banda. Al especializar los protocolos de comunicación, se puede alcanzar un alto desempeño en diversos ambientes de cómputo. Un ejemplo más específico de la especialización incremental es una técnica llamada retroalimentación de software (software feedback). Esta técnica toma ventaja de las condiciones de carga variables en una red y la carga del CPU, así como las distintas demandas de una aplicación en particular, para balancear los componentes productores y consumidores de una aplicación. Al ajustar al productor de datos a que envíe datos al mismo ritmo que el consumidor es capaz de captarlos, se alcanza un ancho de banda óptimo. Este balanceo de carga de datos se realiza retroalimentando dinámicamente el consumo entre ambos componentes. La retroalimentación permite un balance entre el productor y el consumidor. La noción de una especialización incremental es solo una de las formas en que los sistemas operativos pueden adaptarse a circunstancias en continuo cambio. Los sistemas operativos adaptables se clasifican en 3 formas: Quién hace la adaptación: Usuario vs. Adaptación del sistema. El programa de usuario (aplicación) tiene que solicitar explícitamente la adaptación, o el sistema automáticamente se

49 ⊕

Imagen reproducida de [8.48] Obras consultadas: [8.18] [8.19] [8.20] [8.21] [8.22] [8.44]

312

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

adapta en función de una necesidad percibida. La adaptación es transparente a las aplicaciones del programador. Qué es adaptado: Como se agrega la funcionalidad. El desempeño es solo uno de los beneficios de la adaptación. Otras formas de funcionalidad mejorada pueden resultar de la adaptación. Esta nueva funcionalidad puede tomar una de varias formas: • Una nueva implementación de un sistema de interfaz existente. • Una capa de software que presenta una nueva interfaz sobre la interfaz existente. • Una nueva interfaz del sistema modificada o completamente nueva. Cuando adaptarse: Compilación, carga o tiempo de ejecución. Las adaptaciones pueden ser hechas en varios momentos: • • A tiempo de compilación. A tiempo de ligado.

• A tiempo de carga. • A tiempo de ejecución. Las decisiones postergadas de adaptación tienen más información sobre la cual basar la decisión. Sin embargo las decisiones postergadas son potencialmente más costosas por que tienen menos oportunidad de amortizar el costo de la adaptación sobre múltiples invocaciones sobre el servicio del sistema que se este especializando. En el área de sistemas distribuidos y proyectos como Off++ (microkernel diseñado en 1997 por Francisco Ballesteros, Roy Campbell, y Fabio Kon), se sabe que la adaptabilidad puede lograrse usando un microkernel mínimo como base para el sistema operativo. Si el microkernel está centralizado, la adaptación de los servicios del sistema para requerimientos particulares puede dañar la distribución de dichos servicios por que están distribuidos sobre el microkernel y esta distribución no es soportada por el microkernel mismo. La razón es que las extensiones de usuario pueden fallar en preservar las propiedades encontradas en el hardware distribuido y no habrá una capa de bajo nivel para soportarlo. Si el microkernel está distribuido, extensiones simples del sistema pueden beneficiarse de la distribución del sistema, pues la capa de bajo nivel está distribuida. Este problema puede notarse por el hecho de que es necesario modificar o reimplementar servicios existentes del sistema para agregar nuevos servicios distribuidos a un sistema distribuido basado en un microkernel típico. Algunos de los proyectos relacionados a este paradigma son: • • • • • • • • • • Fluke: Flux -kernel Environment Aegis (MIT) AIX Extensions (Notre Dame) Apertos (Sony CSL) Cache Kernel (Stanford) Fast and Flexible Mach-based Systems (Utah) Open Implementation Using Meta-Object Protocols (PARC) x-kernel (Arizona) SPIN (Washington) Universal Transport System (University of Technology, Sydney)

313

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

8.11 Arquitectura de Exokernel⊕
Uno de los objetivos de arquitecturas como la de capas, máquinas virtuales o microkernel, es proveer la habilidad de mantener a varias aplicaciones y usuarios compartiendo una misma máquina. Sin embargo existe un problema: solo los servicios privilegiados y el kernel pueden administrar los recursos del sistema. Las aplicaciones son restringidas a las interfaces e implementaciones de este software privilegiado. Por lo tanto, este esquema de organización puede no ser óptimo para las demandas de una aplicación. Una interfaz diseñada para el soporte de aplicaciones, debe anticipar todas las posibles necesidades. La implementación de tal interfaz requeriría resolver todos los contratiempos y anticipar todas las formas en que la interfaz pueda usarse. La experiencia sugiere que tal anticipación no es factible y que el costo de los errores es alto. La arquitectura de exokernel (desarrollada en el MIT) ataca este problema dándole al código de una aplicación no privilegiada un control seguro sobre los recursos (tanto como sea posible), y permitiendo que los desarrolladores innoven sin comprometer la integridad del sistema. Esto se hace dividiendo las responsabilidades de forma diferente a lo que se hace tradicionalmente. Los exokernels separan la protección de la administración: ellos protegen los recursos y las aplicaciones los administran. Un exokernel trata de aislar la funcionalidad no requerida para protección de los kernels y servicios privilegiados, y trasladarla a las aplicaciones no privilegiadas. Por ejemplo, en el contexto de la memoria virtual, un exokernel protege las páginas físicas y los bloques de disco, pero delega el resto de la administración a la aplicación (p.ej. paginación, asignación, manejo de errores, mantenimiento de tablas de paginación, etc.). Desde su creación, el campo de los SOs ha intentado identificar la estructura más apropiada para abstraer y proteger el hardware; entre los intentos más comunes están los kernels monolíticos y microkernels, así como otros sistemas basados en máquinas virtuales o lenguajes. Un exokernel elimina la noción de que un sistema operativo debe proveer abstracciones sobre las cuales las aplicaciones son construidas. Por el contrario, esta arquitectura solo se concentra en el multiplexado seguro del hardware (raw hardware); así, a partir de las primitivas básicas de hardware, librerías a nivel de aplicación y servidores, pueden implementarse directamente abstracciones tradicionales de los sistemas operativos para mejorar la velocidad y desempeño.

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 hardware50
⊕ 50

Obras consultadas: [8.25] [8.26] [8.58][8.59] Imagen reproducida de [8.26]

314

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Para comprender mejor esto, tomemos el ejemplo de un servidor Web. Un servicio de este tipo se encuentra montado en un SO, el cual se encarga de brindar la conectividad a la red, administrar la memoria y proveer un sistema de archivos para el almacenamiento secundario; nada nuevo.

Figura 8.24 Esquema de un servidor Web montado en un SO convencional51
El problema es que el SO hace más trabajo del necesario: maneja desde el protocolo TCP y todas sus abstracciones superiores hasta el protocolo HTTP, puede estar compartiendo recursos, etc., lo cual disminuye el rendimiento de nuestra aplicación.

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 óptimo52. En el segundo diagrama pueden apreciarse las dependencias del sistema de administración de memoria de Linux.
51 52

Imagen reproducida de [8.58] Imagen reproducida de [8.58]

315

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

La alternativa del exokernel es solo proveer lo necesario: conectividad y el sistema de archivos, por lo que el rendimiento se vería incrementado dramáticamente.

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 necesita53
Así, en esta arquitectura los servicios de administración de memoria, sistemas de archivos, etc. se encuentran en librerías de aplicación (libOS) El escenario ideal de este enfoque es que las librerías sean tan poderosas y tengan los mismos privilegios de un SO, además de permitir innovar más rápidamente al no ser un esquema restrictivo (en los aspectos de los privilegios necesarios para modificar un SO o de causar daños, lo que reduce costos).

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 registro54
La arquitectura de exokernel ofrece de forma segura, control eficiente al software de aplicación del hardware y recursos de software separando la administración de la protección.

53 54

Imagen reproducida de [8.58] Imagen reproducida de [8.25]

316

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

La meta de un exokernel es brindar control eficiente de los recursos para aplicaciones no confiables en un sistema multiusuario seguro. Para ello se siguen los siguientes principios: • Separar protección y administración. Los Exokernels proveen primitivas al más bajo nivel posible requeridas para protección a nivel del hardware (bloques de disco, identificadores de contexto, TLB, etc.). La administración de recursos está restringida a funciones necesarias para la protección: asignación, revocación, compartir y el seguimiento de propiedad. • Exponer asignaciones. Las aplicaciones asignan recursos explícitamente. El kernel permite que recursos específicos sean solicitados durante la asignación. • Exponer nombres. Los exokernels usan nombres físicos siempre que sea posible. Los nombres físicos capturan información útil y no requieren de traducción a nombres virtuales (que puede ser potencialmente costosa). • Exponer revocaciones. Los exokernels exponen las políticas de revocación a las aplicaciones. Ellos permiten a las aplicaciones escoger que instancia de un recurso pueden ceder. Cada aplicación tiene control sobre su conjunto de recursos físicos. • Exponer información. Los exokernels exponen toda la información del sistema y juntan datos que las aplicaciones que no puedan derivar localmente de forma sencilla. Por ejemplo, las aplicaciones pueden determinar cuantos buffers de red en hardware hay. Un exokernel podría también registrar un aproximado de todas las páginas físicas menos usadas recientemente, algo que las aplicaciones individuales no pueden hacer sin información global. Estos principios aplican no solo al kernel, sino a cualquier componente de un sistema de exokernel.

8.12 Arquitecturas orientadas a agentes⊕
Los paradigmas de comunicación basados en agentes han mostrado un enorme potencial para operar en ambientes impredecibles y metamórficos, como las redes de cómputo móviles. Un ejemplo de tareas distribuidas de alto nivel que pueden ser realizadas por agentes es el procesamiento de transacciones electrónicas. Varias autoridades pude que necesiten ser contactadas antes de que la transacción sea completada. Por ejemplo, para comprar un producto de software de forma electrónica, se necesita obtener la verificación del número de tarjeta de crédito del usuario, el número de la cuenta del usuario y del proveedor, y entregar el producto al usuario. Tales tareas requieren una serie de operaciones de lectura y escritura en varios nodos. Los agentes muestran características que son adecuadas para ambientes de red móviles en áreas amplias: 1. Movilidad: el cómputo móvil muestra una naturaleza transitoria (p.ej. la localización de los hosts cambia constantemente, y las transacciones pasan por varios nodos y tienen una vida corta). La habilidad de los agentes para transportar código y datos a través de los nodos de una red se ajusta muy bien a un ambiente transitorio. 2. Flexibilidad: los algoritmos de los agentes pueden ser modificados dinámicamente de acuerdo a condiciones ambientales pertinentes (p.ej. congestión en la red, fallo de un nodo y movilidad del usuario).

Obras consultadas: [8.28]

317

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

3. Solución de problemas concurrentes: los agentes proveen un paradigma natural para realizar tareas que tienen varios aspectos de concurrencia. 4. Modelo de seguridad autónomo: a cada agente le es asignado un nivel de privilegio y los agentes se ejecutan en una "caja de arena", gobernada por el principio del menos privilegiado (p.ej. otorgar al agente solo el privilegio necesario). Los agentes pueden también delegar o transferir privilegios del usuario o el sistema. 5. Manejo de proxies: los agentes pueden comportarse simultáneamente como proxies servidores o clientes en cualquier nodo. Los proxies servidores emulan la funcionalidad o presencia de un servidor, mientras los proxies cliente emulan la funcionalidad o presencia de un cliente (típicamente un cliente nómada o móvil). Con un sistema lleno de agentes, incluyendo agentes del sistema (las funciones del sistema, como la administración de recursos, pueden realizarse con agentes), aplicación y usuario, es necesario un ambiente operativo para administrar dichos agentes; por ello es necesario un sistema operativo para agentes. Cuando un agente de usuario, aplicación o sistema necesita realizar una tarea, genera y envía agentes móviles para contactar otros agentes; así que los protocolos de base son parcialmente generados por agentes. En el caso específico del proyecto AgentOS las metas de investigación son: • Mostrar que un SO eficiente para aplicaciones móviles puede ser construido usado agentes. • Demostrar que los agentes móviles concurrentes representan el paradigma adecuado para desarrollar e implantar aplicaciones de cómputo móvil. • Mostrar que los protocolos basados en agentes son ideales para la administración de la consistencia, detección de fallas en redes y ruteo inteligente/adaptable. • Mostrar que los sistemas basados en agentes son aplicables a problemas reales, como los monitores de equipos en fábrica o transacciones electrónicas. Algunos proyectos relacionados caen en las siguientes categorías: • • • sistemas operativos para Internet, sistema de soporte para cómputo móvil y sistemas de agentes móviles.

El uso de sistemas operativos para Internet es un concepto relativamente nuevo. Inspirado en la proliferación de máquinas virtuales de Java (Java VMs) en navegadores Web, el "Internet OS'' intenta definir un conjunto de servicios básicos esenciales para una aplicación de Internet migratoria y multiplataforma. El JavaOS (Sun Microsystems), se planea que opere en computadoras de red (NetPCs), lo que acepta el concepto de la red como un sistema operativo. Sin embargo, las NetPCs adoptan un modelo cliente/servidor. El AgentOS en cambio, propone un modelo de agentes móviles. Apple ha descrito recientemente el concepto de un sistema operativo para el Web, que en su opinión, es solo la agregación de Java VMs incrustadas en los navegadores, vistas como un sistema operativo virtual. AgentOS extiende el concepto de máquina virtual más allá del navegador, a nodos intermedios en la red y nodos móviles, como computadoras portátiles y dispositivos inalámbricos.

318

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

8.13 Comentarios
Tras exponer las principales arquitecturas de sistemas operativos, puede contarse con un panorama más amplio de su desarrollo y una serie de ideas que pueden incorporarse a nuevos desarrollos, no solo de sistemas operativos sino de sistemas de cómputo en general. Además cada componente arquitectónico de los sistemas mostrados forma parte de una guía de diseño de alto nivel (fig. 8.28) que puede aplicarse en los casos como el análisis de un sistema existente o la propuesta de uno nuevo, en conjunción con los criterios de diseño expuestos en el capítulo anterior. Por ejemplo, si se quiere desarrollar un servicio que atienda peticiones de información o ejecución de programas, puede tomarse como referencia la arquitectura cliente-servidor, pero tambien debe tomarse en cuenta una organización en capas que asegure los privilegios de acceso y ejecución de los usuarios. Así mismo, debe tomarse en cuenta la arquitectura de microkernel, pues una pieza de software será la que provea el soporte de ejecución de todo el servicio (p.ej. un motor de servlets si se usa tecnología Java), para que su desarrollo sea modular. Y por último, puesto que las tecnologías de orientación a objetos tienen actualmente un papel preponderante en el desarrollo de software no puede dejarse de lado el tomar en cuenta esa arquitectura para comprender y aprovechar la plataforma de desarrollo de la aplicación. En el caso de analizar un sistema existente, puede decirse que Linux es un sistema con arquitectura monolítica, pero que a su vez tiene una organización en capas, que comparado con el MS-DOS lo hace muy seguro.

319

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 8.28 Arquitecturas de sistemas operativos y sus características 320

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

8.14 Obras consultadas
[8.1] 01051 - INGENIERIA DE SOFTWARE. Luis Cobo http://www.sanmartinbaq.edu.co/cursos/sistemas/0105 1/guia05.html [8.2] Virtual Virtual Machines. Bertil Folliot, Ian Piumarta, Fabio Riccard. Projet SOR, INRIA Rocquencourt, B.P. 105, 78153 Le Chesnay Cedex, France. http://www-sor.inria.fr/publi/HTML/VVM_radical97/ http://www-sor.inria.fr/publi/VVM_radical97.html [8.3] Object Orientation in Operating Systems Michael Lazebnik. May 1997, Rutgers University Email:mxl5294@megahertz.njit.edu [8.4] Sistema de Computación para un Sistema Operativo Orientado a Objetos basado en una Máquina Abstracta Orientada a Objetos Reflectiva http://www3.uniovi.es/~oviedo3/so4/concurrencia.html [8.5] JavaOS: Thin Client, Fat Service. Charles Mirho and Tom Clements .Byte. July 1997. http://www.byte.com/art/9707/sec4/art4.htm [8.6] QNX Forges Ahead. Peter D. Varhol. October, 1994. http://www.byte.com/art/9410/sec14/sec14.htm [8.7] An Architectural Overview of QNX. Dan Hildebrand, Senior Architect (danh@qnx.com) QNX Software Systems Ltd. [8.8] QNX Neutrino OS. http://qdn.qnx.com/support/docs/qnx_neutrino/index.h tml [8.9] Inside Mac OS X - System overview http://developer.apple.com/techpubs/macosx/SystemO verview/SystemOverview/SystemOverview.pdf [8.10] MIT Exokernel Operating System March 5, 1998 http://www.pdos.lcs.mit.edu/exo.html [8.11] IBM Research work on Operating Systems http://www.research.ibm.com/compsci/os/index.html [8.12] Operating System Architecture. Michael Lynch. 1999 [8.20] Synthetix project http://www.cse.ogi.edu/DISC/projects/synthetix/ [8.21] Incremental specialization: the key to high performance, modularity and portability in operating systems. C. Consel, C. Pu, and J. Walpole In ACM Symposium on Partial Evaluation and Semantics-Based Program Manipulation (PEPM '93), pages 44-46, 1993. Invited paper. http://www.irisa.fr/lande/consel/papers/inc-spec.ps.gz [8.22] Adaptive Distributed Computing. Ray Ozzie The future of software. Winter 2000. http://www.futureofsoftware.net/ro0010/ro0010.asp [8.17] An Overview of Projects on Distributed Operating Systems Alfred J. Lupper Computer Science Department, Distributed Systems Laboratory University of Ulm http://www-vs.informatik.uniulm.de/DOSinWWW/DistribSys.html [8.18] Related Work in Adaptive Operating Systems. Crispin Cowan http://www.cse.ogi.edu/DISC/projects/synthetix/related .html [8.19] A Detailed Description of Off++, a Distributed Adaptable kernel Francisco J. Ballesteros Fabio Kon Roy H. Campbell. [8.16] CS134c Computing Systems Laboratory, 2001. Instructor: Jason Hickey Caltech Computer Science Department http://www.cs.caltech.edu/cs134/cs134c/index.html [8.15] ISE2 Literature Review : Article1. Distributed Real-time Applications and their Operating Systems. Sarfraz Bacchus http://www.iis.ee.ic.ac.uk/~frank/surp98/article1/sb19/ http://www.qvctc.commnet.edu/classes/csc277/os_arc h.html [8.13] Palm OS platform http://www.palmos.com/platform/architecture.html [8.14] Kadak AMX RTOS http://www.kadak.com/html/kdkp2500.htm

Department of Computer Science, University of Illinois at Urbana-Champaign August, 1997
http://gsyc.escet.urjc.es/off/dd.html

321

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

[8.23] Operating System Services For Wide Area Applications,'' Amin Vahdat. November 1998. PhD Dissertation, Department of Computer Science, University of California, Berkeley http://www.cs.duke.edu/~vahdat/ps/thesis.pdf [8.24] WebOS: Operating System Services for Wide Area Applications http://www.cs.duke.edu/ari/issg/webos/ [8.25] Exokernels (or, making the operating system just another application library) http://amsterdam.lcs.mit.edu/exo/exo-slides/index.htm [8.26] The exokernel operating system architecture Dawson R. Engler PhD CSE Thesis MIT 1998 [8.27] Architectural Styles, Design Patterns and Objects. Robert T. Monroe, Andrew Kompanek, Ralph Melton, and David Garlan

[8.35] Conceptual Architecture of the Linux Kernel. Ivan Bowman (ibowman@sybase.com) January 1998 http://plg.uwaterloo.ca/~itbowman/CS746G/a1/ [8.36] Concrete Architecture of the Linux Kernel. Ivan Bowman (ibowman@sybase.com), Saheem Siddiqi (s4siddiqi@neumann), Meyer C. Tanuan (mtanuan@descartes.com). Department of Computer Science, University of Waterloo. Winter 1998 http://plg.uwaterloo.ca/~itbowman/CS746G/a2 [8.37] Real-Time Mach OS. Real-Time and Multimedia Laboratory in the Department of Computer Science at Carnegie Mellon University http://www-2.cs.cmu.edu/afs/cs/project/art-6/www/ [8.38] MACH - An example of a Distributed Operating System . Ken Kellow http://www.rit.edu/~kjk2135/MACH.html [8.39] Resource Kernel and Services. Raj Rajkumar http://www-2.cs.cmu.edu/afs/cs/project/art6/www/Overview97/index.htm [8.40] ChorusOS http://www.sun.com/chorusos/ [8.41] Sun™ Embedded Telecom Platform - Combining the Power of Solaris Computing with the Real-Time Performance of the ChorusOS™ Operating System White Paper http://www.sun.com/software/chorusos/wpemb.telecom.platform/index.html [8.42] Metodologias informáticas- Arquitectura clienteservidor http://www.inei.gob.pe/cpimapa/bancopub/libfree/lib616/INDEX.HTM [8.43] Distributed Operating Systems http://www.cs.arizona.edu/people/bridges/os/distribute d.html [8.44] Fluke: Flux -kernel Environment http://www.cs.utah.edu/flux/fluke/html/ [8.45] The Globe project http://www.cs.vu.nl/~steen/globe/ [8.46] Mac OS X System architecture http://developer.apple.com/macosx/architecture/# [8.47] Mac OS X Development http://developer.apple.com/macosx/

IEEE Software, January 1997, pp. 43-52.
http://pecan.srv.cs.cmu.edu/afs/cs/project/able/www/p aper_abstracts/ObjPatternsArch-ieee.html [8.28] AgentOS: The Agent-based Distributed Operating System for Mobile Networks. Larry T. Chen

http://www.acm.org/crossroads/espanol/xrds52/agentos.html
[8.29] Go! - Genuine Componentisation of the Operating System http://www.soi.city.ac.uk/~gel/go/overview.html [8.30] 3-D Visual Operating System http://atwww.hhi.de/blick/3-D_Visual_OS/3d_visual_os.html [8.31] Lo básico de UNIX

Vicente González Ruiz . 1998
http://www.ace.ual.es/~vruiz/docencia/cursos/linux/ht ml/node1.html [8.32] An Overview of the UNIX* Operating System Bell Labs innovations history http://www.bell-labs.com/history/unix/tutorial.html [8.33] Unix history http://perso.wanadoo.fr/levenez//unix/ [8.34] An Introduction to the Linux Operating System Architecture Meyer C. Tanuan, (mtanuan@descartes.com). Department of Computer Science, University of Waterloo. CS 746G, Winter 1998, 27-Jan-98

322

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

[8.48] Darwin Documentation http://www.opensource.apple.com//projects/document ation/howto/ [8.49] Apple Open Source Projects - Darwin http://www.opensource.apple.com//projects/darwin/

[8.56] The Foundations of Microsoft Windows NT System Architecture Microsoft Corporation, September 1997 http://msdn.microsoft.com/archive/default.asp?url=/arc hive/en-us/dnarwbgen/html/msdn_ntfound.asp [8.57] The X window system

[8.50] Mac OS X - An overview for developers http://developer.apple.com/macosx/pdf/macosx_overvi ew.pdf [8.51] A Big Day for Mac Fans. Cade Metz. PC Magazine, March 23, 2001 12:46 PM PT http://www5.zdnet.com/zdnn/stories/news/0,4586,270 0598,00.html [8.52] HISTORY OF APPLE™ MACINTOSH™ OPERATING SYSTEM http://perso.club-internet.fr/jctrotot/Perso/History.html [8.53] SciNet - ISTP Perceptual OS http://www.scinetcorp.com/associates/index.htm?rsi.htm~index2

http://www.northants.lug.org.uk/meetings/notes/xtalk/arch.html [8.58] Exokernels (or, making the operating system just another application library). F. Kaashoek, G. Ganger, H. Briceño, R. Hunt, D. Mazières, T. Pinckney, J. Jannotti MIT Lab for Computer Science. 1998. http://amsterdam.lcs.mit.edu/exo/exo-slides/index.htm [8.59] Exokernel: an operating system architecture for application-level resource management. Dawson R. Engler, M. Frans Kaashoek and James O’Toole Jr. M.I.T. Laboratory for Computer Science. 1995. http://citeseer.nj.nec.com/engler95exokernel.html

323

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

324

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Resultados, conclusiones y perspectivas
El Alma del Mundo se alimenta con la felicidad de las personas. O con la infelicidad, la envidia, los celos. Cumplir su Leyenda Personal es la única obligación de los hombres. Todo es una sola cosa. Y cuando quieres algo, todo el Universo conspira para que realices tu deseo.
El alquimista, Paulo Coelho

a.

Resultados

Haber integrado las referencias teóricas relativas a los sistemas operativos, ha conformado una interesante lista de requerimientos para la comprensión y el desarrollo de un sistema operativo. Los modelos de simulación presentados en el trabajo están basados en el contenido de cada sección, aunque en algunos casos la especialización de los temas se ha preferido dejar solo como una referencia para los lectores. Esto permite contar con un seguimiento del proceso de desarrollo, y una referencia a la teoría de forma unificada. En relación a los simuladores, se han obtenido 3 productos interesantes: • • • El simulador de un SO mínimo, el cual a pesar de ser el primer intento intempestivo por aterrizar toda la teoría, capturó el espíritu de los primeros sistemas (capítulo 3). El simulador del servicio de administración de memoria, el cual presenta 2 esquemas de administración de la memoria (capítulo 4). El simulador del servicio de administración de procesos, donde se se instrumento la principal abstracción en la que se basan todos los sistemas operativos (capítulo 5).

Así se cuenta con modelos que permiten analizar un sistema operativo a diferentes niveles de codificación: • en lenguaje ensamblador o lenguaje de máquina (todo dependerá de la implementación del modelo de instrucciones y su representación e interpretación en la memoria) • en un lenguaje de alto nivel orientado a objetos como lo es Java , tomando en cuenta la consideración presentada en el modelo del simulador, donde parte de la implementación de alto nivel del simulador pareciera estar ya cargada en memoria, y puede interactuar con los elementos de hardware simulado. Para la implementación de las diversas simulaciones presentadas en este trabajo, se usan técnicas y herramientas orientadas a objetos. En particular, se eligió usar una herramienta que

325

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

permitiera hacer de manera visual el modelado de clases y a su vez permitiera su codificación y compilación en un ambiente integrado. El lenguaje de programación usado es Java, por sus capacidades multiplataforma y su completo soporte de clases. De esta manera, cualquier persona interesada en evaluar o ampliar los modelos propuestos, podrá hacerlo en cualquier plataforma. Como IDE se uso la herramienta llamada BlueJ (hecha en Java), la cual en efecto provee un ambiente integrado de edición de diagramas de clases (UML) y el desarrollo en Java. BlueJ no solo se convirtió en una herramienta de desarrollo, sino en una excelente plataforma de pruebas para los diversos prototipos y modelos desarrollados en este trabajo, por lo que de alguna manera BlueJ forma parte integral de los simuladores implementados. Elegir BlueJ como herramienta de trabajo, resultó ser un gran auxiliar en el diseño, pruebas y depuración de todo el modelo de simulación. Incluso, ejecutando los simuladores sobre esta herramienta, las capacidades del simulador se incrementan notablemente (es posible explorar valores de instancias del simulador, a tiempo de ejecución del mismo). Al diseñar un sistema, muchos elementos pequeños tienden a ser incrustados en clases que aunque extienden su alcance, encapsulan detalles importantes del modelo. Por ejemplo, en el caso del despachador del SO, en cualquier implementación puede encontrarse simplemente como una función más en el kernel, cuando es en sí un objeto con una tarea específica dentro del sistema. Por ello, el detalle de las referencias teóricas permitió modelar partes que por lo general hay que buscar entre líneas, y que incluso a veces forman parte de componentes más complejos. Esto permitió además disminuir la cohesión entre objetos del sistema, pues en casos donde las llamadas a métodos implicaba una alta dependencia de los objetos e impedía que los modelos pudieran modificarse con facilidad, esto permitió adoptar estrategias como modelado orientado a eventos o protocolos y manejadores de mensajes que mejoraron la funcionalidad del sistema. El uso de patrones permitió un diseño más claro, potente y con una mínima cohesión entre los objetos que lo componen. Aunque los modelos no son interactivos (no cuentan con una GUI, la implementación de los modelos es lo que cuenta) es posible aprender de la implementación en sí. Un punto a resaltar es la estrecha relación entre el hardware y software modelado. Puede no ser muy claro hacer un sistema operativo si no se tiene hardware. Tal vez podrá implementarse un intérprete de comandos, un shell o un complejo GUI, pero ese sería otro terreno. Ya sea para su implementación de facto o para su simulación, debe contarse con un conocimiento sólido en cuestiones de hardware.

b.

Aportaciones

Entre las principales aportaciones de esta obra se encuentran: • Investigación y desarrollo del tema de simulación de los sistemas operativos. Este es un tema poco tratado, pero del cuál existen muchos trabajos que permiten el acercamiento al área de los sistemas operativos, en formas como: • • la mejor comprensión del funcionamiento interno del sistema, la integración de los diversos componentes del SO,

326

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• la experimentación de nuevas configuraciones y prototipos de sistemas. Investigación y desarrollo de los principales servicios de los sistemas operativos. En diversas obras impera la teoría absoluta, o la relación práctica basada en un ejemplo puntual. En este trabajo se aprovecho el enfoque de simulación para que cada parte tuviera una implementación que permitiera contemplar los elementos de hardware y software relacionados en un servicio, los algoritmos y políticas que aplican al servicio, e incluso pudieron verse algunos de los problemas comunes en cada uno de los contextos. Investigación y desarrollo del tema de arquitecturas de los sistemas operativos. Varias obras tienen secciones dedicadas al estudio de casos de sistemas operativos, pero poco se habla de su arquitectura, sus características y las aportaciones que se han hecho alrededor de cada desarrollo. Esto es estratégico si se quiere contar con un panorama amplio de los sistemas con que se cuenta actualmente y cuales son las tendencias a futuro en el área. Investigación y desarrollo del tema de diseño de los sistemas operativos. Hay muy poco materias sobre el tema y en su mayoría se refiere a recomendaciones técnicas y reglas del pulgar, pero la principal conclusión es que las metodologías para el desarrollo de software deben ser aplicadas, considerando la complejidad de los sistemas operativos.

Complementar toda la teoría acerca de los sistemas operativos, con modelos de programación, proveen a este trabajo de un enfoque práctico que bien podrá ser aprovechado por estudiantes de licenciaturas y postgrados en computación, para poder involucrarse en el desarrollo de estos sistemas. También puede mencionarse que el cúmulo de referencias reunidas durante el desarrollo de este trabajo, permitirán a los interesados consultar fuentes muy variadas y especializadas en el tema. Adicionalmente durante 2002 se presentó la oportunidad de impartir el curso de Sistemas Operativos en la Fundación Arturo Rosenblueth con excelentes resultados, pues la transferencia de conocimientos a los estudiantes abarco la totalidad del material de esta obra (y en algunos momentos hasta más), lo que motivo que ellos contaran con los elementos para hacer sus propios simuladores. Esto se vio enriquecido por: El desarrollo de notas compactas para consulta por parte de los estudiantes. El uso de los simuladores de sistemas operativos mencionados en el capitulo 3, en especifico el RCOS. La diversidad de lenguajes de programación usados en las implementaciones de los simuladores (C, Java, Pascal, Sanscript) y la inclusión de interfaces gráficas para visualizar el comportamiento de los modelos. Incluso durante el XV CONGRESO NACIONAL Y I CONGRESO INTERNACIONAL DE INFORMÁTICA Y COMPUTACIÓN organizado por la ANIEI, se presentó una ponencia en colaboración con Humberto Uribe llamada El paradigma de la programación visual55, donde se citaron como casos de éxito en el desarrollo de software usando lenguajes visuales, los simuladores de una neurona artificial y de administración de memoria y de procesos (estos últimos desarrollados por Gerardo Sierra y Héctor Hernández, alumnos del curso antes citado). En relación al desarrollo simuladores con interfaces gráficas, los alumnos del periodo 2003-1 hicieron algunos avances, presentando alternativas interesantes en relación a la visualización del comportamiento de los modelos de simulación.

55

El paradigma de la programación visual. E.J. Hernández Valdelamar y H. Uribe. Consulte [G20]

327

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Figura 9.1 Simulador de administración de memoria con particiones fijas (Oscar Ceceña)

Figura 9.2 Simulador de administración de procesos (Christian Islas)

Figura 9.3 Simulador de administración de procesos (Josué Huizar)
Será deseable el uso de estas herramientas en cursos futuros para reafirmar los conceptos teóricos de la materia (y que mejor que se haga con productos hechos en la FAR).

c.

Conclusiones

Desde los primeros días de las computadoras modernas, la tecnología del hardware ha progresado más rápido que el software que la acompaña. Por ejemplo, existen computadoras que poseen un hardware con un funcionamiento veloz e increíble, pero el software (en específico el sistema operativo) que estas máquinas poseen es tan pobre que son extremadamente difíciles

328

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

de programar. Debido al estado inmaduro de estos sistemas operativos, estas computadoras funcionan solamente en una fracción pequeña de su velocidad máxima mientras que trabajan bajo cargas de trabajo típicas. Es por lo anterior que la industria del software debe ahora dedicar más tiempo y recursos para el desarrollo. Una vez que la tecnología del software alcance el nivel de la tecnología del hardware, los sistemas serán no sólo más prácticos, sino que utilizarán sus recursos de hardware mucho más eficientemente. Comprender a los sistemas operativos permite usar a la computadora de manera más efectiva, además de ser un excelente ejemplo de consideraciones en el diseño de sistemas cuyos resultados e ideas se aplican en otros campos. Un desarrollador que no ha estado en contacto con proyectos grandes y complejos, tratará de solucionar el problema que se le presente de una forma simple. Sin embargo, la misma aplicación puede tener implicaciones en el corto, mediano y largo plazo; digamos al integrarse con otros sistemas o tratar de que la solución sea más amplia. Ideas como aislar la configuración del software, modularizar los componentes de software, usar protocolos estándares, etc., de alguna manera son herencia del desarrollo de sistemas operativos. Por eso considero que un conocimiento integral del hardware y el software de base permiten un mejor diseño e implementación de sistemas de alto nivel.

c.1

¿Por qué seguir desarrollando nuevos sistemas operativos?

Una constante es la necesidad de sistemas más eficientes. Además si en un futuro cercano el modelo de cómputo de Von Neumann es reemplazado, será necesario diseñar nuevos SOs que permitan aprovechar las ventajas de esas nuevas arquitecturas. Una cuestión adicional es la estructura de las implementaciones de los sistemas operativos. Un detalle que apareció durante la investigación, es que incluso los más nuevos SOs tienen un porcentaje de su código dedicado a cuestiones de bajo nivel (generalmente escrito en ensamblador). Tomando el mismo enfoque del BIOS, en el sentido de simplificar la migración de un sistema en varias arquitecturas de hardware, debe considerarse una interfaz de más alto nivel que permita a los sistemas operativos operar en ambientes Con la llegada de los nuevos sistemas operativos el hardware se aprovechará al máximo y se reducirá esa brecha tan grande de rapidez que existe entre el hardware y el software que lo controla. Con estos sistemas operativos se llegará a concretar lo que se llamó la quinta generación de computadoras, la cual pretende multiplicar la velocidad, disponer procesamientos paralelos, diseñar una arquitectura de hardware-software muy superior y utilizar el lenguaje natural. Una tendencia adicional esta vinculada a los sistemas distribuidos. En este escenario ya no solo se requiere de software de base para un hardware específico, una interfaz de usuario amigable y software de aplicación, sino que se requiere una infraestructura compleja de servicios en línea que permitan explotar los recursos de todas las computadoras en red. Esto implica crear abstracciones de alto nivel que aprovechen los recursos de los sistemas operativos locales. Hay muchos proyectos de este tipo en desarrollo, por lo que hay que estar atentos de sus resultados.

329

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Cabe mencionar que para los desarrolladors de estos sistemas será necesario contar con una amplia gama de conocimientos de técnicas de programación como el manejo de dispositivos a bajo nivel, concurrencia, hilos, comunicación en redes, etc. , asi como de análisis y diseño de software.

c.2

Los sistemas operativos y el desarrollo de marcos conceptuales

(frameworks)
Si los sistemas operativos nos dan la posibilidad de acceder a todos los recursos y capacidades de la computadora, ¿por qué la tendencia de las compañías desarrolladoras es crear frameworks? Por mucho que el SO pueda abstraer y administrar los recursos de la computadora, las APIs generadas a este nivel siguen siendo “crípticas”. Si se requiere elevar la productividad del desarrollo de software, no se le puede pedir a los programadores ser expertos en detalles que muchos desconocen. Además está demostrado que las abstracciones provistas por el enfoque orientado a objetos permiten un mejor modelado de los sistemas de aplicación. En este sentido es muy probable que las arquitecturas de SO orientadas a objetos o componentes, permitan prescindir de instalaciones adicionales.

c.3

Tendencias en el desarrollo de sistemas operativos

En el capitulo 8 se presentaron diversas arquitecturas de sistemas operativos, y los más nuevos tienen como objetivo aprovechar los recursos de las redes, y en específico del internet. En este punto no hay que perder de vista todo el desarrollo de middleware hecho por diversas compañías. Esto hace prever que habrán dos niveles en el diseño y desarrollo de los nuevos sistemas operativos: Desarrollo orientado a la habilitación de nuevas plataformas de hardware. Cualquier nuevo desarrollo de hardware requerirá de un sistema operativo que permita disponer de sus recursos y los optimice. Por el momento parece que la arquitectura de microkernel seguirá manteniendo su hegemonía, pero si el paradigma Desarrollo orientado a la integración de recursos en redes. Será software que aprovechará los sistemas operativos de base, para crear entornos donde servicios más complejos puedan integrar la capacidad de procesamiento y almacenamiento, asi como soportar abstracciones de procesos más complejos (por ejemplo, los agentes). Desarrollo orientado a la integración de hardware dedicado. Tal vez no será un SO completo, pero si modulos que permitan el intercambio de información con hardware dedicado (por ejemplo neurocomputadoras [9.4]).

d.

Perspectivas⊕

Por último solo queda establecer qué hay por hacer en el futuro. Hay algunos temas que vale la pena desarrollar en relación a los sistemas operativos, entre ellos:

Referencias: [9.1] [9.3]

330

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

• • • • • •

Interfaces gráficas de usuario Administración de la configuración Administración de la seguridad Ingeniería de pruebas Seguridad informática Interoperabilidad entre plataformas

Tratar estos temas daría una perspectiva mucho más amplia de todo lo que debe tomarse en cuenta para el desarrollo de futuros sistemas operativos. Tambien me gustaría saber que es lo que hay detrás de la siguiente afirmación: "Alan Turing proved that any OS can be ported to any computer architecture" [9.1]. Sería muy interesante saber de donde salió esto, pues busque en algunos sitios dedicados a Turing, y no encontré referencia alguna. De esto podría derivarse una metodología para portar sistemas ya existentes, o unificar capacidades de diversos sistemas. En fin, es de las pocas dudas inducidas que dejare pendientes. Un punto para reflexionar es la automatización de las tares relacionadas con las computadoras. Como se mencionó desde el primer capítulo, el operador experto encargado de alimentar a la computadora on programas y datos, fue el primero en ser reemplazado. Durante la historia de la computación, este mismo fenómeno se ha repetido en pro de la eficiencia de las organizaciones; sistemas financieros, de manufactura y administrativos, han ido poco a poco desplazando a los grupos de trabajo que realizaban las tareas ahora automatizadas, reduciendo su tamaño o desapareciendolos definitivamente. Pero tambien aquellos que hacen los sistemas pagan un precio: los nuevos sistemas configurables, multiplataforma y con estándares que permiten integrarlos fácilmente con otros sistemas, requieren de menos programadores para su mantenimiento o expansión, asi que ¿el futuro qué nos depara? Por lo demás, me parece que hay muchas líneas de investigación que pueden desarrollarse y actividades académicas que hacer. Sobre las líneas del trabajo que pueden ser exploradas, las siguientes son interesantes: • el modelo de procesador que puede ejecutar varios modelos de conjuntos de instrucciones, puede ser ampliado con más conjuntos y probar si es posible ejecutar programas escritos en diferentes ensambladores en un mismo ambiente, o incluso si es posible que un programa contenga instrucciones de diversos conjuntos. • implementar nuevos servicios de administración de los servicios expuestos (procesos, memoria, dispositivos, etc.) • implementar configuraciones distribuidas o puramente orientadas a objetos del sistema operativo. • • • generar distribuciones funcionales de las configuraciones implementadas en el simulador incurrir en el estudio de TSIAs, un nuevo soporte de ejecución que sirve como optimización del sistema operativo y los compiladores. aplicar los conocimientos relacionados a los sistemas operativos en otras áreas. Por ejemplo, el tipo de trabajo que realizarán el hardware y software de la quinta generación no solo en el tratamiento de datos, sino en la adquisición de información y, a partir de los materiales y estructuras de que dispone, en la elaboración de conocimientos, es decir, en la elaboración inteligente del saber. Es decir se anuncia el aprovechamiento de la computadora para adquirir conocimientos artificialmente, a través de las máquinas. A partir de esto, estas ya no

331

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

solo aportarán fuerza o habilidad, sino que también proveerán al hombre de un conocimiento del mundo. ¿cómo será el sistema operativo de una de estas máquinas? Sobre las actividades académicas: • Introducir en México el uso de simuladores de sistemas operativos (citados en el capítulo 3) para la enseñanza de esta materia. • Aprovechar esfuerzos como el del SygOps para involucrar a los estudiantes en proyectos que permiten a otros estudiantes aprender de su experiencia. Esta práctica debe ser una nueva actitud que los profesores deben inculcar en cualquier curso. • Investigar sobre las nuevas tendencias en sistemas distribuidos (p.ej. Web OS), pues estas tecnologías son el próximo parte aguas en la industria. En lo personal, creo que el próximo paso será involucrarme más en la biocomputación y bioinformática, donde todo este trabajo podrá ser aprovechado y ampliado. Después de todo hay propuestas interesantes, como la de computadoras basadas en ADN que suenan lo suficientemente interesantes y prometedoras como para invertir tiempo y esfuerzo en investigar al respecto.

e.

Referencias

[9.1] Computer Architecture http://www.rdrop.com/~cary/html/computer_architecture.html [9.2] OS Agents: Using AI Techniques in the Operating System Environment Oren Etzioni, Henry M. Levy, Richard B. Segal, and Chandramohan A. Thekkath Department of Computer Science and Engineering, University of Washington August 3, 1994 [9.3] Burkhard D. Burow. DRAFT : Task System and Item Architecture (TSIA), March 1999. http://www.tsia.org [9.4] Neural Networks in Hardware: Architectures, Products and Applications Clark S. Lindsey. August, 2002 http://www.particle.kth.se/~lindsey/HardwareNNWCourse/home.html

332

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Bibliografía
[G1] Operating Systems concepts. A. Silberschatz, J. Peterson, P. Galvin. Addison Wesley. 1991. ISBN 0-201-54873-9 [G2] Computer systems J. Stanley Warfold Jones & Bartlett. 1999. ISBN 0-7637-0794-5 [G3] Sistemas operativos. Diseño e implementación. Andrew S. Tanenbaum. Prentice-Hall. 1988. ISBN 968-880-153-4 [G4] Sistemas operativos. Conceptos y diseño. Milan Milenkovic. McGraw-Hill. 1987. ISBN 0-07-041920-5 [G5] Trends in operating system design. Peter D. Varhol. Dr. Dobb's Journal, May 1994. [G6] RTMK: A real-time microkernel. J.F. Bortolotti, P. Bernard and E. Bouchet. Dr. Dobb's Journal, May 1994. [G7] MMURTL: Your own 32-bit operating system. Richard Burgess. Dr. Dobb's Journal, May 1994. [G8] Fundamentals of operating systems. A. M. Lister. MacMillan Publishers. 1984. ISBN 0-333-37097-X [G9] Operating systems theory. Edward G. Coffman Jr., Peter J. Denning. Prentice-Hall. 1973. ISBN 0-13-637868-4 [G10] Distributed operating systems: The logical design. A. Goscinski. Addison-Wesley. 1991. ISBN 0-201-41704-9 [G11] Construya una microcomputadora basado en el Z80. [G19] Diseño de un sistema de multiprogramación CPU. Héctor Bolívar Olmos Ramirez, Héctor Ruiz Barradas. Universidad Autónoma Metropolitana – Azcapotzalco. 2000. ISBN 970-654-677-4 [G20] Avances en informática y computación Editores: Juan Humberto Sossa Azuela, María de Lourdes Sánchez Guerrero. XV CONGRESO NACIONAL Y I CONGRESO INTERNACIONAL DE INFORMÁTICA Y COMPUTACIÓN pp. 371-380. Octubre, 2002. [G18] Introducción a la computación. Jorge Vasconcelos Santillán. Publicaciones Patria Cultural. 1999. ISBN 9684398735 [G17] Computer organization & design. The hardware/software interface. David A. Patterson & John L. Hennessy Morgan Kaufmann Publishers. 1998. ISBN 1-55860-428-6 [G16] Operating systems. A systematic view. William S. Davis Addison-Wesley publishing Co. 1987. ISBN 0-201-11185-3 [G15] Inside Microsoft Windows CE John Murray Microsoft press. 1998. ISBN 1-57231-854-6 [G14] El proceso unificado de desarrollo de software Ivar Jacobson, Graidy Booch & James Rumbaugh Addison Wesley, 2000 ISBN 84-7829-036-2 [G13] Conceptos de sistemas operativos. José Torres Jiménez. Trillas. ISBN 968-24-5959-1 [G12] An Operating Systems Vade Mecum Raphael A. Finkel.University of Wisconsin at Madison Prentice Hall Steve Ciarcia. Byte books/ McGraw-Hill. 1981.

333

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
[G22] Serious play. How the world’s best companies simulates to innovate. Michael Schrage. Hardvard business school press. 2000. ISBN 0-87584-814-1

[G21] Sistemas distribuidos. Conceptos y diseño. George Couloris, Jean Dollimore, Tim Kindberg. Addison Wesley. 2001 ISBN 84-7829-049-4

334

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Glosario
Algoritmo . El término algoritmo es un procedimiento palabra se deriva del nombre del matemático árabe ordenador puede considerarse como un algoritmo informática, un algoritmo generalmente es un pequeño recurrente. o fórmula para resolver un problema. La Al-Juarismi (825 DC). Un programa de elaborado. En matemáticas o ciencia procedimiento que resuelve un problema

ANSI . ANSI (American National Standards Institute, Instituto nacional estadounidense de estándares) es la principal organización que promueve el desarrollo de estándares tecnológicos en los Estados Unidos. ANSI trabaja con grupos de la industria y es el miembro estadounidense de la Organización Internacional para la Estandarización (International Organization for Standardization, ISO) y la Comisión Electrotécnica Internacional (International Electrotechnical Commission, IEC). Entre los estándares ANSI más conocidos se encuentra el código ASCII para el intercambio de información (American Standard Code for Information Interchange) y la interfaz SCSI (Small Computer System Interface). API . Una interfaz de programa de aplicación o de programación de aplicaciones, API (application program interface o application programming interface) es el método específico prescrito por un sistema operativo o por cualquier otra aplicación mediante el cual un programador que escribe una aplicación puede hacer solicitudes al sistema operativo o a otra aplicación. Una API puede contrastarse con una interfaz gráfica de usuario (GUI) o una interfaz de comando (ya que ambas son interfaces directas del usuario) como formas de interactuar con un sistema operativo o un programa. Aplicación . 1. En tecnología informática, una aplicación es el uso de una tecnología, sistema o producto. 2. El término "aplicación" es una forma abreviada para designar a un programa de aplicación. Un programa de aplicación es aquél diseñado para desempeñar una función específica directamente para el usuario o, en algunos casos, para otro programa de aplicación. Los ejemplos de estas aplicaciones incluyen los procesadores de textos, programas de bases de datos, navegadores de la Red, herramientas de desarrollo, programas de dibujo, pintura y edición de imágenes, y programas de comunicaciones. Las aplicaciones usan los servicios del sistema operativo de la computadora y otras aplicaciones de apoyo. La solicitud formal y los medios de comunicarse con otros programas que usa un programa de aplicación son lo que se denomina interfaz de programa de aplicación (application program interface, API). Arquitectura . Término que se refiere a la estructura general de un procesador, sistema operativo, computadora, línea de sistemas, etc. Arranque en caliente . Volver a arrancar o reinicializar la computadora sin apagarla. Arranque en frío . Arranque de un ordenador apagado (activando la alimentación eléctrica). BIOS . Basic Input Output System o Sistema Básico de Entrada y Salida. Pequeño programa que controla las funciones más básicas de una computadora, se encarga entre otras cosas de bajar el sistema operativo del disco duro hacia la memoria RAM y pasarle el control de la computadora a este último. Se encuentra en la memoria ROM.

335

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

BOOT . Deriva de bootstrap. Programa que inicia o reinicia el funcionamiento de la computadora. Buffer . Un buffer (a veces traducido como "memoria temporal") es un área de datos compartida por dispositivos de hardware o procesos de programas que operan a distintas velocidades o con diferenes conjuntos de prioridades. El buffer permite que cada dispositivo o proceso opere sin verse interferido por otro. Para que un buffer sea efectivo, su tamaño y los algoritmos para poner y retirar datos de él deben ser considerados por el diseñador. Como una caché, un buffer es "un punto intermedio de almacenamiento" pero existe no tanto para acelerar la velocidad de una actividad como para apoyar la coordinación de actividades separadas. Este término se usa tanto en programación como en hardware. En la programación, el uso del buffer en ocasiones implica la necesidad filtrar datos de su destino final para poderlos editar o procesar de alguna otra forma antes de transferirlos a un archivo o base de datos regular. BUG . Literalmente significa bicho o insecto. En computación se refiere a alguna falla o defecto de programación en la forma como debe operar una computadora con ciertas instrucciones, a veces se presenta solo en determinadas circunstancias. Caché . Área de almacenamiento temporal para datos accesados recientemente o con frecuencia, que agilizará el proceso de lectura. Existen dos tipos de caché: Interno (en el procesador) y Externo (en la motherboard). También se le llama caché a los datos almacenados en el disco, de dónde son leídos más rápido que por ejemplo de un CD-ROM o de una página Web. Cliente . Un cliente es el programa o usuario que realiza la solicitud en una relación cliente/servidor. Por ejemplo, el usuario de un navegador de la Red en realidad realiza solicitudes de cliente para recibir páginas de servidores en toda la Red. El navegador en sí es un cliente en su relación con la computadora que recibe y entrega el archivo HTML solicitado. La computadora que maneja la solicitud y envía de vuelta el archivo HTML es un servidor. Código Fuente . Sentencias de un lenguaje ordenadas en un archivo (o conjuntamente con otros archivos) que produce uno o varios resultados. Comandos . Instrucciones que se introducen en el teclado de la terminal y que dirigen las acciones de la computadora o de sus dispositivos periféricos. Compilación . Compilar consiste en reunir en un sólo archivo toda la información existente en archivos de texto que contienen sentencias ordenadas (Código fuente) para obtener un resultado concreto. Un archivo compilado no requiere ser interpretado, por lo que desde ese momento es ejecutable. Un archivo compilado para un Sistema Operativo, sólo funcionará en ese sistema operativo (o Emulador), pero con el código fuente, el mismo programa podrá funcionar, compilandolo en otros Sistemas Operativos. Compilador . Programa de computadora que analiza instrucciones de un cierto lenguaje de programación, detecta errores y los reporta para su corrección. Una vez que está correcto el programa fuente, genera un archivo que puede entender la computadora para la que fue desarrollado, este archivo se conoce como código ejecutable y es el que se ejecuta en la memoria RAM por el CPU.

336

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Controlador de Dispositivo . 1) Programa que permite la comunicación entre el sistema operativo y los diferentes dispositivos instalados, como cámaras o discos. Para un mejor rendimiento de dichos dispositivos es recomendable tener la versión más actualizada de estos drivers o controladores. 2) Programa que generalmente forma parte del sistema operativo y que controla una pieza específica de hardware (a menudo un dispositivo periférico como una impresora o un ratón). CP/M . Control Program for Microprocessors. Programa de control para microprocesadores. Sistema operativo monousuario para los microprocesadores 8080 y Z80, de Digital Research. Creado por Gary Kildall, CP/M tuvo su apogeo a principios de los años ochenta. Demonio . Son programas encargados de la gestión y administración del sistema, automatizando las tareas tediosas. Dirección . Un nombre, un número o una etiqueta que designa una posición particular en el almacenamiento primario o secundario. Un identificador de localización para nodos en una red de computadoras. Dispositivo periférico . Dispositivo de E/S externo al procesador central y la memoria principal. El dispositivo se conecta al procesador o a la memoria a través de un dispositivo o tarjeta de interfaz. Emulación . Característica que permite a un dispositivo funcionar como si fuera otro distinto, interoperando con otra PC. Por ejemplo, las PCs pueden emular el funcionamiento de determinadas terminales que se conectan a mainframes y que funcionan de forma totalmente diferente. EEPROM . Electrically Erasable Programmable Read Only Memory. Chip de memoria que puede ser borrado y sobre el que se puede escribir, pero que no pierde su contenido cuando no recibe corriente. Se le llama ROM porque grabarle datos es mucho más tardado que con el RAM. Estos chips pueden ser encontrados en los BIOS de módems y algunos otros dispositivos. FAT . File Allocation Table. Tabla de Asignación de Archivos. Es un archivo situado en el sector 0 del disco duro con información de todos los archivos almacenados (localización, tamaño, etc.). Generador de Aplicaciones . Application Generator. Software que genera programas de aplicación a partir de descripciones del problema en lugar de hacerlo desde una programación tradicional. Está a un nivel más alto que un lenguaje de programación de alto nivel. Una sentencia o línea descriptiva puede generar una enorme rutina o todo un programa. Sin embargo, los generadores de aplicaciones siempre tienen límites en cuanto a su posible uso. Interfaz . 1) Componente de hardware y software de un sistema utilizado específicamente para conectar un sistema o dispositivo a otro. 2) Conectar un sistema o dispositivo a otro para el intercambio de información. 3) El punto de contacto entre el usuario, la computadora y el programa, por ejemplo, el teclado o un menú. Internet . Es una red global que conecta millones de computadoras. En 1999, los usuarios conectados a Internet se estimaban en más de 200 millones y este número está creciendo muy rápidamente. A diferencia de otro tipo de servicios, controlados centralmente, Internet se

337

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

encuentra descentralizada por diseño. Cada computadora conectada a Internet (se denominan hosts) es independiente. Sus operadores eligen qué servicios de Internet utilizar y qué servicios locales hacer disponibles a la comunidad global. Sorprendentemente, esta anarquía por diseño funciona extraordinariamente bien. Intranet . Es una red basada en el protocolo TCP/IP, que pertenece a una organización, normalmente una corporación, accesible únicamente para aquellos miembros de la organización, empleados u otros con autorización para hacerlo. Los sitios de la Intranet lucen y funcionan como cualquier otro sitio, pero un Firewall, rodeando la Intranet, la defiende de accesos no autorizados. Al igual que Internet, una Intranet es utilizada para compartir información. Las Intranets seguras son el segmento de Internet que está creciendo con mayor rapidez, ya que son menos costosas de construir y mantener que las redes privadas. Java . Java es un lenguaje de programación expresamente diseñado para usarse en el entorno distribuido de Internet. Es parecido al lenguaje C++, pero es más sencillo de usar que éste y obliga a una visión de la programación completamente orientada a objetos. Java puede usarse para crear aplicaciones completas que corran en una sola computadora o se distribuyan entre servidores y clientes de una red. También puede usarse para construir pequeños módulos de aplicación o applets para utilizarlos como parte de una página web. Los applets hacen posible que el usuario de una página web interactúe con ella. Máquina virtual . Virtual Machine . Las capacidades de procesamiento de un sistema de computo creado por medio de software (y en ocasiones mediante hardware) en un computadora distinta. Modem . Es un acrónimo para modulador-demodulador. Un modem es un dispositivo o programa que permite a una computadora transmitir datos a través de líneas telefónicas. La información es almacenada digitalmente en la computadora, mientras que la información transmitida a través de las líneas telefónicas es en forma de ondas analógicas. Multitarea . Multitasking . Capacidad de ejecutar más de un programa o aplicación a la vez. Permite tener varios programas abiertos y poder cambiar de uno a otro sin necesidad de cerrarlos. Facilita el intercambio de información entre las aplicaciones con la técnica de copiar y pegar, además de que pueden hacerse varias cosas al mismo tiempo. NetBIOS . Network Basic Input/Output System. Interfaz de diferentes programas y aplicaciones usado en conjunto con otros programas para transmitir mensajes entre PC's conectadas a una red de área local. NTFS . Sistema de archivos utilizado por Windows NT. Tiene la capacidad de recuperar datos tras fallas del disco duro, puede utilizar nombres largos e los archivos, utiliza la tabla de código Unicode pero debido a su complejidad no puede accesarse desde MS-DOS o Windows 3.x ó 9x. Procesador . Componente lógico de un sistema de computación que interpreta y ejecuta instrucciones de programas. Protocolo . Un protocolo es un formato acordado previamente para poder transmitir información entre dos dispositivos. El protocolo determina: a) el tipo de verificación de errores empleado, b) el método de compresión de datos, c) la manera en que el dispositivo que envía información

338

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

indicará que ha concluido la transmisión de un mensaje, y d) la manera en la que el dispositivo que recibe información indica que ha recibido un mensaje. Desde un punto de vista del usuario, lo relevante en relación a los protocolos es que su computadora o dispositivo debe utilizar el protocolo correcto a fin de poder comunicarse con otros equipos de cómputo. Puerto . Un punto de acceso en un sistema de computación que permite la comunicación entre la computadora y un dispositivo periférico. RAM . Random Acces Memory. Memoria de Acceso Aleatorio. Parte fundamental de la computadora en donde se almacenan temporalmente datos mientras se trabaja con ellos o programas que se estén ejecutando. Se le llama aleatoria porque cualquier área de la memoria puede ser accesada en cualquier momento. Recolección de basura . Garbage Collection. Rutina que busca en la memoria segmentos de programas o de datos que ya no son activos, con el fin de recuperar ese espacio. Red . Dos o más computadoras conectadas entre sí, permitiendo a sus usuarios compartir archivos y recursos. Registro del Sistema . Archivos que contienen información acerca del funcionamiento general del equipo. Al registro es donde acude el sistema Windows cuando necesita saber alguna cosa sobre el hardware y el software del equipo, así como sobre otros aspectos relacionados con la configuración del sistema. Servidor . Genéricamente, dispositivo de un sistema que resuelve las peticiones de otros elementos del sistema, denominados clientes. SDK . Software Development Kit. Conjunto de herramientas que facilitan el trabajo del programador al escribir nuevas aplicaciones. Comúnmente está formado por iconos menús, cuadros de diálogo, y todo aquello que permita que la interfaz de la nueva aplicación sea lo más parecida posible al sistema operativo en el que se vaya a ejecutar. Shell . Es un tipo de utilidad cuya finalidad consiste en hacer más fácil el manejo del sistema operativo o de una aplicación por parte del usuario. Sistema . Cualquier grupo de componentes (funciones, gente, actividades, eventos y demás factores pertinentes) que tienen una interfaz con otros, con los cuales se complementan, para lograr uno o más objetivos definidos con anticipación. Sistema de computo . Una referencia colectiva a todo el hardware de computación interconectado, incluyendo procesadores, dispositivos de almacenamiento, dispositivos de entrada/salida y equipo de comunicaciones. Sistema operativo . El software de nivel bajo que se encarga de organizar la operación de la computadora, asignar recursos, manejar el interfaz con los diversos periféricos, y comunicarse con el usuario. El sistema operativo es el software más importante de una computadora, ya que sin el su operación no sería posible. Toda computadora de propósito general tiene un sistema

339

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

operativo para correr otros programas. Algunos de los sistemas operativos más comunes son Windows, MS-DOS, MacOS, Linux, y Solaris. Software . Los programas que se usan para dirigir las funciones de un sistema de computo. X Window . Sistema desarrollado en el MIT que permite a los usuarios de UNIX correr programas en otras máquinas pero manejando todo desde su propio monitor.

340

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Apéndices
Apéndice A. Programación de Cargadores (sectores de arranque)56
Al encender una computadora sucede lo siguiente: La corriente de la computadora es activada. El BIOS es ejecutado. El Bootstrap es ejecutado.

Crear un sector de arranque (cargador) es más simple de lo que se piensa, el único requerimiento es que dicho programa mida 512 bytes, y que en el offset 0x1FE (decimal=510) el valor de palabra 0xAA55 sea colocado, pues la primer cosa que hace el BIOS cuando una PC arranca, es buscar en el primer sector del disco flexible un valor de 0xAA55 al final, y si lo encuentra, lo carga en la memoria y empieza a ejecutarlo; si no, trata con el disco duro primario, y si no es así, entonces manda un error. El sector de arranque (boot sector) debe colocarse en: Sector 1 Cilindro 0 Cabeza (Head) 0 El BIOS carga el sector de arranque en el desplazamiento lineal (linear offset) 0x7C00, y los estados de los registros son: DL = Boot drive, 1h = floppy1, 80h = primary harddisk, etc CS = 0 IP = 0x7c00 Referencias: (1)How It Works -- Master Boot Record. Version 1a. by Hale Landis http://www.nondot.org/sabre/os/files/Booting/mbr.txt (2) "Making plain binary files using a C compiler" by Cornelis Frank http://www.nondot.org/sabre/os/files/Booting/CompilingBinaryFilesUsingACompiler.pdf (3) Daniels NASM bootstrap tutorial - by Daniel Marjamäki http://www.nondot.org/sabre/os/files/Booting/nasmBoot.txt (4) Das Boot -- H. Gilbert http://pclt.cis.yale.edu/pclt/BOOT/DEFAULT.HTM (5) WRITING A BOOTSECTOR Jeff Weeks and Code X software. (c)1997 http://www.nondot.org/sabre/os/files/Booting/PolyOS.html (6) My Experiences with the Boot Sector. Chris Lattner. 1994-8. http://www.nondot.org/sabre/os/files/Booting/MyBootSector.html (7) Bootsector authoring by Gareth Owen. http://www.nondot.org/sabre/os/files/Booting/gbootsect.txt
56

341

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Así que en lugar de agregar una instrucción [ORG 7C00h] al principio del archivo, puede agregarse: mov mov mov mov mov ax, ds, es, fs, gs, 0x7C0 ax ax ax ax

lo que inicializará los registros de segmento para que apunten al inicio del sector de arranque. La mayoría de los sectores de arranque, solo almacenan la unidad de arranque, cargan el kernel del disco y saltan a él para comenzar la ejecución. Algunas de las reglas para codificar un programa de arranque (bootstrap) son: Debe ser un archivo binario plano (sin redirecciones; ej. formato COM). El tamaño debe ser de 512 bytes. Losa últimos dos bytes deben ser 0AA55h Es cargado en la dirección de memoria 0x7C00.

Para generar el código ejecutable de los ejemplos aquí presentados use el ensamblador NASM (gratuito) y la utilería de transferencia PartCopy. El siguiente es un pequeño ejemplo de un arrancador, el cual sólo se queda ciclado: hang: jmp hang times 512-($-$$)-2 db 0 dw 0AA55h Ahora veamos un caso un poco más complicado. Este consiste de: • Un cargador • • Un programa Una utilería para poner el cargador y el programa en un disco.

El siguiente ejemplo carga un programa del disco y lo ejecuta: bits 16 org 0x7C00 start: cli ; Disable interrupts

342

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

mov ax, 0x9000 mov ss, ax mov sp, 0 sti l1: push ds mov dl, 0 mov ax, 0 int 13h pop ds jc fail push es mov ax,0x1000 mov es,ax mov bx, 0 mov mov mov mov int ah, al, cx, dx, 13h 2 5 2 0

; Put stack at 0x90000

; Enable interrupts

; Reset disk controller

; ES:BX = 10000

; ; ; ;

Read disk sectors read 5 sectors Cylinder=0, sector=2 head=0, drive=0 ; ES:BX = data from disk

pop es jc l1 mov ax,0x1000 mov es,ax mov ds,ax push ax mov ax,0 push ax retf fail: jmp fail times 512-($-$$)-2 db 0 dw 0AA55h El programa a cargar y ejecutar debe ser algo así: mov ax, 1000h ; Update segment registers ; set segment registers and jump

343

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

mov ds, ax mov es, ax mov si, msg ; Print "JIPPIKAYE!" call putstr hang: jmp hang putstr: lodsb or al,al jz short putstrd mov ah,0x0E mov bx,0x0007 int 0x10 jmp putstr putstrd: retn msg db 'JIPPIKAYE!',13,10,0 ; Just hang

Por último, aquí esta el código para escribir el sector de arranque en un disco flexible (ha sido compilado con el DJGPP para DOS). Escribe el archivo 'bootsect', en el Sector 1, Cilindro 0, Cabeza 0 del disco flexible. #include <bios.h> #include <stdio.h> void main() { FILE *in; unsigned char buffer[520]; if((in = fopen("bootsect", "rb"))==NULL) { printf("Error loading file\n"); exit(0); } fread(&buffer, 512, 1, in); while(biosdisk(3, 0, 0, 0, 1, 1, buffer)); fclose(in); }

344

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Adicionalmente, he aquí otro caso más: un mini-kernel (muy similar al programa anterior), por si alguien quiere seguir haciendo pruebas ;*****************start of the kernel code*************** [org 0x0000] [bits 16] [SEGMENT .text] mov ax, 0x0100 loaded mov ds, ax mov es, ax cli mov ss, ax mov sp, 0xFFFF sti mov si, strWelcomeMsg call _disp_str mov ah, 0x00 int 0x16 service int 0x19 _disp_str: lodsb or al, al jz .DONE mov ah, 0x0E mov bh, 0x00 mov bl, 0x07 int 0x10 jmp _disp_str .DONE: ret [SEGMENT .data] strWelcomeMsg [SEGMENT .bss] ;********************end of the kernel code********************

;location where kernel is

;stack segment ;stack pointer at 64k limit

;load message

; await keypress using BIOS ; reboot

; load next character ; test for NUL character ; ; ; ; BIOS teletype display page 0 text attribute invoke BIOS

db

"Welcome to JOSH!", 0x00

345

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Apéndice B. Simulación de un sistema mínimo de hardware y su sistema operativo
Los conceptos en los que se baso este primer intento de simulación de un SO, se encuentran en los capítulos 1 y 2. Los principales elementos modelados son los siguientes: • • • • Procesador, de donde se deriva el procesador URM y su ALU Registros, de donde se derivan los registros URM Memoria, de donde se deriva la memoria de la URM Sistema operativo mínimo (similar a un monitor residente), compuesto por un cargador de programas y un interprete de comandos

La descripción de como se llegó a esta solución se encuentra en el capítulo 3.

TestSimulator
/** Aplicación de prueba que integra todos los elementos del modelo. * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 (0.4) */ import java.io.*; import java.util.*; public class TestSimulator { public TestSimulator() { } public void runProgram () { Processor p=new URMProcessor(); Memory m=new URMMemory(20); Monitor os=new Monitor(p,m); System.out.println("Iniciando ejecución de instrucciones JCL..."); os.startMonitor(); os.userInput("LOAD c:\\sw\\oses\\OS\\prog.urm"); os.userInput("RUN"); os.userInput("SHUTDOWN"); } public static void main(String args[]) { new TestSimulator(); } }

Registers
/** Operaciones con los registros del procesador * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */

346

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

import java.io.*; import java.util.*; interface Registers { public public public public } void setReg(int id, int regValue); int getReg(int id); void incReg(int id, int increment); void reset();

public void showRegs();

URMRegisters
/** Registros específicos del modelo URM * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ import java.io.*; import java.util.*; class URMRegisters implements Registers {

int aRegisters[]; //arreglo de registros. Aunque en teoria pueden ser ilimitados //un arreglo es bueno para mantener finita la máquina int iregNum; //numero máximo de registros public URMRegisters(){ this(5); } public URMRegisters(int num){ iregNum=num; aRegisters=new int[iregNum]; this.reset(); } public void setReg(int id, int regValue) { if (id<iregNum) aRegisters[id]=regValue; else System.out.println("registro fuera de rango"); } public int getReg(int id) { if (id<iregNum) return aRegisters[id]; else return -1; } public void reset() { for (int i=0;i<iregNum;i++)

347

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
aRegisters[i]=0; } public void incReg(int id, int increment) { aRegisters[id]+=increment; } public void showRegs(){ StringBuffer sb=new StringBuffer(); for (int i=0; i<iregNum; i++) sb.append(aRegisters[i] + " - "); System.out.println("URM Regs->"+ sb.toString()); } }

Processor
/** Interfaz de métodos para un procesador * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ import java.io.*; import java.util.*; 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 y se ejecuta El ciclo de Ejecución -Si tiene que ir a Memoria -va a Memoria -ejecuta instrucción -almacena resultados. */ public void execInstruction(); /** Inicia ejecución del procesador*/ public void start(Memory m); /** Métodos para manipular el PC y obtener su valor*/ public void setPC(int c);

348

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
public int getPC(); /**Obtener los valores de todos los registros*/ public Registers getRegisters(); /**Restaurar registros*/ public void setRegisters(Registers regs); }

URMProcessor
/** Procesador URM. * Implementa la interfaz Processor * @author (Eugenio Jacobo Hernández Valdelamar) * @version Marzo, 2001 */ import java.io.*; import java.util.*; class URMProcessor implements Processor { Registers urmRegs; ALU urmALU; int pc; //Program counter String ir; //Instruction Register //(donde se coloca la instrucción a ser decodificada por el CU) boolean stop; // : boolean; public URMProcessor () { urmRegs=new URMRegisters(); urmALU=new ALU(); this.setPC(0); stop=false; } public void setPC(int c){ pc=c; } public int getPC(){ return pc; } //Instrucciones basicas de la URM -----------------------------private void Z (int ireg) { // {Asigna cero a un registro dado} urmRegs.setReg(ireg,0); } private void S (int ireg) { // {Incrementa en uno un registro dado} urmRegs.setReg(ireg,urmALU.add(urmRegs.getReg(ireg),1)); }

349

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
private void T (int r1, int r2) { // {Transfiere el valor de un registro a otro} urmRegs.setReg(r2,urmRegs.getReg(r1)); } private void J (int r1, int r2, int ins) { //; {Salto} if (urmRegs.getReg(r2)==urmRegs.getReg(r1)) pc=ins; } //-------------------------------------------------------------public void fetchInstruction(Memory m) { ir=(String) m.getMemLoc(pc); pc++; } public void execInstruction(){ StringTokenizer stInst=new StringTokenizer(ir); System.out.println(ir); String s = stInst.nextToken(); if (s.equals("Z")){ this.Z(Integer.parseInt(stInst.nextToken())); } if (s.equals("S")){ this.S(Integer.parseInt(stInst.nextToken())); } if (s.equals("T")){ this.T(Integer.parseInt(stInst.nextToken()), Integer.parseInt(stInst.nextToken())); } if (s.equals("J")){ this.J(Integer.parseInt(stInst.nextToken()), Integer.parseInt(stInst.nextToken()), Integer.parseInt(stInst.nextToken())); } if (s.equals("STOP")){ stop=true; } } public void start(Memory m){ while(!stop) { fetchInstruction(m); execInstruction(); urmRegs.showRegs(); } } public Registers getRegisters(){ return urmRegs; } public void setRegisters(Registers regs) {

350

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
urmRegs=regs; } }

ALU
/** * ALU para el procesador. Contiene las operaciones lógicas y aritméticas. * * @author (Eugenio Jacobo Hernández Valdelamar) * @version March, 2001 */ public class ALU { public ALU() } {

public int add(int x, int y){ return x+y; } public int sub(int x, return x-y; } public int mul(int x, return x*y; } public int div(int x, return x/y; } public int mod(int x, return x%y; } public int shr(int x, return x>>y; } public int shl(int x, return x<<y; } int y){

int y){

int y){

int y){

int y){

int y){

/* public int not(int x){ return !x; }*/ public int and(int x, int y){ return x&y; } public int or(int x, int y){ return x|y; } public int xor(int x, int y){ return x^y;

351

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
} }

Memory
/** Interfaz para operaciones de una memoria * @author (Eugenio Jacobo Hernández Valdelamar) * @version Marzo, 2001 */ import java.io.*; import java.util.*; interface public public public } Memory { void setMemLoc(int adr, Object value); Object getMemLoc(int adr); void showMem();

URMMemory
/** Implementación de las operacione de memoria para el modelo URM * @author (Eugenio Jacobo Hernández Valdelamar) * @version Marzo, 2001 */ import java.io.*; import java.util.*; class URMMemory implements Memory String mem[]; int memSize; public URMMemory () { this(10); } public URMMemory (int size) { memSize=size; mem=new String[size]; } public void setMemLoc(int adr, Object value) { mem[adr]=(String) value; } public Object getMemLoc(int adr) { return mem[adr]; } public void showMem() { String smem=""; for (int i=0; i<memSize; i++) smem+=mem[i] + " | "; {

352

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
System.out.println("URM mem->"+ smem); } }

Monitor
/** Monitor es la clase encargada de cargar un programa o un conjunto de programas en memoria para luego ejecutarlos. Este sería el equivalente a uno de los primeros sistemas operativos (se esta automatizando la carga y ejecución de programas) * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ import java.io.*; import java.util.*; class Monitor { Processor lp; Memory lm; JCLInterpreter jclinterp; public Monitor(Processor p, Memory m) { lp=p; lm=m; } public void startMonitor () { System.out.println("Iniciando Monitor Residente de la URM...."); Loader loader = new Loader(lm); jclinterp = new JCLInterpreter(lp,lm,loader); } public void userInput (String commandLine) { jclinterp.doCommands(commandLine); } }

Loader
/** Cargador de programas. El programa indicado por el nombre de un archivo lo carga en memoria para su ejecución. * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ import java.io.*; import java.util.*;

353

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

class Loader { int startAdress; Memory lm; public Loader(Memory m) { lm=m; this.setStartAdress(0); //debe quedar después del bloque que ocupa el SO System.out.println("Iniciando cargador de programa...."); } public void setStartAdress(int adress){ startAdress=adress; } //archivo de programa (el ejecutable!!) public void loadProgram(String fSource) { try { File inFile = new File(fSource); BufferedReader in = new BufferedReader(new FileReader(inFile)); int c; StringBuffer sline=new StringBuffer(); while ((c = in.read()) != -1) { if (c=='\n'){ //carga instruccion en memoria this.loadInstruction(sline.toString()); sline=new StringBuffer(); } else sline.append((char)c); } in.close(); lm.showMem(); } catch (FileNotFoundException e) { System.out.println(e.getMessage()); } catch (IOException e) { System.out.println(e.getMessage()); } } /** Carga una instrucción del archivo a memoria */ private void loadInstruction(String sline) {

354

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
lm.setMemLoc(startAdress++,sline); System.out.println(sline); } }

JCLInterpreter
/** * El interprete de Lenguaje de Control de Trabajos (JCL), es un programa * que acepta instrucciones del usuario, y procesa cada una de forma * secuencial, realizando la tarea indicada. * 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 * * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 (0.4) */ import java.util.*; public class JCLInterpreter { Loader loader; //instancia del cargador Processor lp; //instancia del procesador Memory lm; //instancia de la memoria /** * Constructor */ public JCLInterpreter(Processor p, Memory m, Loader ld) lp=p; lm=m; loader=ld; }

{

/** Procesamiento de instrucciones del JCL */ public void doCommands(String sCommandLine) { StringTokenizer stok= new StringTokenizer(sCommandLine); System.out.println("Instrucción JCL:" + sCommandLine); String scom=stok.nextToken(); if (scom.equals("LOAD")){ System.out.println("Cargando programa...."); this.doLoad(stok.nextToken()); return; } if (scom.equals("RUN")){

355

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
System.out.println("Ejecutando programa...."); this.doRun(); return; } if (scom.equals("SHUTDOWN")){ this.doShutDown(); return; } } //Acciones que realiza el interprete JCL public void doShutDown() { System.out.println("Terminando sesión...."); //System.exit(0); } /** El monitor recibe la orden de cargar un programa, y cede el control al cargador para que lo haga. */ public void doLoad(String fSource) { loader.setStartAdress(0); loader.loadProgram(fSource); } /** Ejecutar un programa previamente cargado en memoria */ public void doRun() { lp.start(lm); } /** Carga un conjunto de programas para que se ejecuten. Incluye el concepto de PCL (Process Control Language) para el procesamiento en batch */ public void doBatch(String jobsFile) { //this.loadProgram(); //this.execute(); } }

356

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Apéndice C. Simulador del servicio de administración de la memoria
En este apéndice se encuentra el código del simulador de administración de memoria. Los archivos que componen al simulador son los siguientes: • • • • • • • • • • • SimulationController.java ProgramGenerator.java Program.java Manager.java MainMemory.java Table.java DynamicPartitionTable.java FixedPartitionTable.java PRegister.java FPRegister.java DPRegister.java

Para ejecutar el simulador, se integran los archivos con la herramienta BlueJ en un proyecto, y se crea una instancia de la clase SimulationController(pasando un parámetro numerico para elegir el tipo de particiones a simular). Para iniciar la simulación debe accederse al método simulate(), tantas veces como ciclos de simulación se deseen.

SimulationController
/** * class SimulationController. * * @author E.J. Hernández Valdelamar * @version julio, 2002 */ import java.util.*; public class SimulationController { private ProgramGenerator pgen; private Manager memman; private List programs=null; int pos=0; //contador de programas generados int ciclos; //contador de ciclos de simulacion int modo; //para decidir que tipo de particiones usar /** * Constructor

357

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
*/ public SimulationController(int m) { //m=1 particiones fijas ; m=2 , dinámicas modo=m; pgen= new ProgramGenerator(); memman= new Manager(modo); programs= new ArrayList(); } /** Ciclo de Simulación */ public void simulate() { int i=3; Random r= new Random(); ciclos++; System.out.println("Ciclo de simulación: "+ ciclos + "---------------"); //se genera un programa de forma aleatoria if (r.nextInt(4)==2) { System.out.println("Programas generados: "+ (pos+1)); programs.add(pgen.generate()); memman.allocate((Program)programs.get(pos++)); } //se ejecutan todos los programas en memoria this.executePrograms(programs); this.deallocation(programs); memman.show(); } /** se simula la ejecución de los programas cargados en memoria */ private void executePrograms(List ps) { Program p; if (ps!=null) for (Iterator i=ps.iterator();i.hasNext();) { p=(Program)i.next(); if (p.isLoaded()) p.run(); } } /** si alguno de los programas ha terminado de ejecutarse se quita de la memoria y se limpia la tabla de asignaciones */ private void deallocation(List ps) { Program p; if (ps!=null) for (Iterator i=ps.iterator();i.hasNext();) { p=(Program)i.next(); if (p.isAlive()==false) {

358

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
memman.deallocate(p); } } } }

ProgramGenerator
/** * class ProgramGenerator. * Generador de datos relativos a los programas a cargar. * * @author E.J. Hernández Valdelamar * @version julio, 2002 */ import java.util.*; public class ProgramGenerator { private int idcounter; /** * Constructor */ public ProgramGenerator() idcounter=1; }

{

/** genera los datos de un programa a ajecutar en el simulador */ public Program generate() { Random rg= new Random(); int id=idcounter++; int csize = rg.nextInt(10); int msize = rg.nextInt(10); int time = rg.nextInt(20); System.out.println("Generando programa:"+ (idcounter-1)+ "- mem:"+ (csize+msize) + " time:"+time); return new Program(id,csize,msize,time); } }

Program
/** * class Program. * El programa que se llevará a memoria en el simulador * * @author E.J. Hernández Valdelamar * @version julio, 2002 */ public class Program {

359

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
private int id; //identificador del programa private int csize; //tamaño del código private int xmsize; //tamaño de la memoria requerida por el programa private int lifeTime; //tiempo de latencia (en ciclos) private int counter=0; private boolean loaded=false; /** * Constructor */ public Program(int name, int psize, int msize, int time) id = name; csize = psize; xmsize = msize; lifeTime=time; } /** se declara el inicio de ejecución del programa public void run() { counter++; } /** se determina si el programa está aun en ejecución */ public boolean isAlive() { if (counter>lifeTime) return false; else return true; } /** se marca si el programa logró cargarse */ public void loadedOK() { loaded=true; } /** se determina si el programa está aun en ejecución */ public boolean isLoaded() { return loaded; } public int getId() { return this.id; } public int getCodeSize() { return this.csize; }

{

*/

360

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
public int getPMemSize() { return this.xmsize; } public int getSize() { return this.csize+this.xmsize; } public int getLifeTime() { return this.lifeTime; } }

11.3.3 Manager
/** * class Manager. * * @author E.J. Hernández Valdelamar * @version julio, 2002 */ public class Manager { private MainMemory mm; //memoria principal de la computadora private Table table; //tabla de particiones /** * Constructor */ public Manager(int mode) { mm = new MainMemory(); //particiones fijas if (mode==1) { table = new FixedPartitionTable(); int appStart=0; initFixed(appStart); } if (mode==2) { table = new DynamicPartitionTable(mm); } } /** inicialización de las particiones fijas la distribución es de 3 pequeñas, 2 medianas */ public void initFixed(int startAdress) { int adress=startAdress; int size = mm.getSize(); System.out.println("Inicializando particiones...mem="+size); table.add(adress, (size/3)/3); adress+=(size/3)/3;

361

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
table.add(adress, (size/3)/3); adress+=(size/3)/3; table.add(adress, (size/3)/3); adress+=(size/3)/3; table.add(adress, size/3); adress+=(size/3); table.add(adress, size/3); table.show(); } /** método para ejecutar el alojamiento en memoria de un programa */ public void allocate(Program p) { //primero se trata de insertar la info. del programa en la tabla if (table.insert(p.getId(), p.getSize())) { //si es exitoso se marca el programa como cargado p.loadedOK(); //se marca la memoria principal con el id del proceso cargado int pHandler = table.getLastAdress(); int csize= p.getSize(); int id= p.getId(); for (int i=0; i<csize; i++) mm.write(pHandler++,new Integer(id)); } } /** método para ejecutar el desalojamiento en memoria de un programa */ public void deallocate(Program p) { table.remove(p.getId()); } /** mostrar contenido de la tabla y la memoria*/ public void show() { mm.show(); table.show(); } }

MainMemory
/** * class MainMemory. * * @author E.J. Hernández Valdelamar * @version julio, 2002 */ import java.util.*; public class MainMemory {

362

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
//cada elemento de esta lista equivale a una unidad //de almacenamiento; cuanto el programa se carga, se pondrá //el id del programa correspondiente private List mem=null; private int memsize; /** Constructor */ public MainMemory() this(50); }

{

public MainMemory(int capacity) { memsize=capacity; mem= new ArrayList(capacity); for (int i=0;i<capacity;i++) mem.add(new Integer(0)); } /** devuelve el tamaño de la memoria */ public int getSize() { return this.memsize; } /** devuelve cuantos elementos activos hay en la memoria */ public int getMemElements() { return mem.size(); } /** mostrar el contenido en memoria */ public void show() { System.out.println("Memory: "+mem.toString()); } /** leer el contenido en memoria */ public Object read(int adress) { return mem.get(adress); } /** escribir el contenido en memoria */ public void write(int adress, Object data) { mem.set(adress,data); } public void clear(int adress) { mem.remove(adress); } public void clear() { mem.clear(); }

363

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
}

Table
/** * interface Table. * * @author E.J. Hernández Valdelamar * @version julio, 2002 */ public interface Table { /** agrega un registro a la tabla */ void add(int adress, int size); boolean insert(int id, int size); void remove(int id); int getLastAdress(); void show(); }

DynamicPartitionTable
/** * class DynamicPartitionTable. * * @author E.J. Hernández Valdelamar * @version julio, 2002 */ import java.util.*; public class DynamicPartitionTable implements Table { private List ptable=null; //lista de registros de particiones private int lastUsedAdress; private MainMemory mm; /** * Constructor */ public DynamicPartitionTable(MainMemory mem) { mm=mem; ptable= new ArrayList(); } /** agrega un registro a la tabla en este caso es una partición de tamaño variable */ public void add(int adress, int size) { ptable.add(new DPRegister(adress, size));

364

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
} /** registra un programa en la tabla de particiones */ public boolean insert(int id, int size) { boolean assigned=false; int adress= searchPartition(size); //si hay espacio, crear la partición if (adress!=-1) this.add(adress, size); for (Iterator i=ptable.iterator(); i.hasNext();) { DPRegister fpr= (DPRegister)i.next(); //si el tamaño es adecuado y esta libre if ((size<=fpr.getPartitionSize()) && (fpr.getPartitionStatus()==0)) { fpr.setProcessId(id); fpr.setPartitionStatus(1); assigned=true; break; } } if (assigned==false) { System.out.println("El programa "+id +" no pudo ser alojado"); } return assigned; } /** buscar un bloque del tamaño requerido para cargar el programa y devuelve la dirección de inicio del bloque libre */ private int searchPartition(int size) { //calcular a partir de los registros de la tabla que areas //de la memoria están libres int base=0; //dir. en memoria int tidx=0; //indice de elementos de la tabla System.out.println("searchp"); for (Iterator i=ptable.iterator(); i.hasNext();) { DPRegister pr= (DPRegister)i.next(); tidx++; int pa= pr.getStartAdress(); int pend= pa + pr.getPartitionSize(); //si la dir. base empata con una partición existente //revisar el edo. de la partición, y si está ocupada //asignar a la dir.base la dir. donde acaba el bloque if ((base==pa)&&(pr.getPartitionStatus()!=0)) { base=pend; } else { //si no hay coincidencia, el espacio debe estar vacio //pero hay que checar si hay una sig. partición //y su dir. de inicio es mayor al espacio que se requiere

365

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
if (tidx<ptable.size()) { pr= (DPRegister)i.next(); tidx++; int paa= pr.getStartAdress(); if (pr.getStartAdress()>(base+size)) { break; } } } } if (mm.getSize()>(base+size)) { lastUsedAdress=base; return base; } else { //no hay espacio disponible para crear la partición System.out.println("(!) no hay espacio para crear la partición" + mm.getSize() +"-"+ (base+size)); return -1; } } /** obtener la dir. de la ultima partición asignada*/ public int getLastAdress() { return this.lastUsedAdress; } /** quita un programa y el registro de la partición en la tabla de particiones */ public void remove(int id) { for (Iterator i=ptable.iterator(); i.hasNext();) { DPRegister fpr= (DPRegister)i.next(); //si el id del procesos es igual se libera la partición if (fpr.getProcessId()==id) { fpr.setProcessId(0); fpr.setPartitionStatus(0); //ptable.remove(ptable.indexOf(fpr)); break; } } compactMem(); } /** puesto que si no hay mantenimiento en la tabla de particiones, se comporta como la tabla de particiones fijas, se decició agregar este método de optimización, encargado de compactar los datos en memoria y actualizar la tabla de particiones */ public void compactMem() { List newlst= new ArrayList(); int adress=0; for (Iterator i=ptable.iterator(); i.hasNext();) {

366

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
DPRegister fpr= (DPRegister)i.next(); //aplicar la compactación a todas las particiones activas if (fpr.getPartitionStatus()!=0) { fpr.setStartAdress(adress); newlst.add(fpr); adress += fpr.getPartitionSize(); //ptable.remove(ptable.indexOf(fpr)); } } adress=0; //ahora hay que compactar los datos en la memoria for (Iterator j=newlst.iterator(); j.hasNext();) { DPRegister fpr= (DPRegister)j.next(); int csize= fpr.getPartitionSize(); int id= fpr.getProcessId(); for (int i=0; i<csize; i++) mm.write(adress+i,new Integer(id)); adress += fpr.getPartitionSize(); } ptable=newlst; System.out.println("Compactación finalizada"); this.show(); mm.show(); } /** muestra el contenido de la tabla de asignaciones y sus registros */ public void show() { System.out.println("Tabla de asignaciones de particiones dinámicas" ); for (Iterator i=ptable.iterator(); i.hasNext();) { DPRegister fpr= (DPRegister)i.next(); fpr.show(); } } }

FixedPartitionTable
/** * class FixedPartitionTable. * * @author E.J. Hernández Valdelamar * @version julio, 2002 */ import java.util.*; public class FixedPartitionTable implements Table { private List ptable=null; //lista de registros de particiones private int lastUsedAdress;

367

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

/** Constructor */ public FixedPartitionTable() { ptable= new ArrayList(); lastUsedAdress=-1; } /** agrega un registro a la tabla en este caso es una partición de tamaño fijo */ public void add(int adress, int size) { ptable.add(new FPRegister(adress, size)); } /** registra un programa en la tabla de particiones */ public boolean insert(int id, int size) { boolean assigned=false; //buscar en la tabla de particiones for (Iterator i=ptable.iterator(); i.hasNext();) { FPRegister fpr= (FPRegister)i.next(); //si el tamaño es adecuado y esta libre la partición if ((size<=fpr.getPartitionSize()) && (fpr.getPartitionStatus()==0)) { fpr.setProcessId(id); fpr.setPartitionStatus(1); assigned=true; lastUsedAdress=fpr.getStartAdress(); break; } } if (assigned==false) { System.out.println("El programa "+id +" no pudo ser alojado"); } return assigned; } /** obtener la dir. de la ultima partición asignada*/ public int getLastAdress() { return this.lastUsedAdress; } /** quita un programa en la tabla de particiones */ public void remove(int id) { for (Iterator i=ptable.iterator(); i.hasNext();) { FPRegister fpr= (FPRegister)i.next(); //si el id del procesos es igual se libera la partición if (fpr.getProcessId()==id) { fpr.setProcessId(0); fpr.setPartitionStatus(0); } }

368

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
} /** muestra el contenido de la tabla de asignaciones y sus registros */ public void show() { System.out.println("Tabla de asignaciones de particiones fijas" ); for (Iterator i=ptable.iterator(); i.hasNext();) { FPRegister fpr= (FPRegister)i.next(); fpr.show(); } } }

PRegister
/** * class PRegister. * * Registro de partición de memoria * * @author E.J. Hernández Valdelamar * @version julio, 2002 */ public class PRegister private private private private int int int int { //tamaño de la partición //dirección de inicio de la partición de la partición (0-libre) //id. del proceso alojado en la partición

partitionSize; partitionStartAdress; partitionStatus; //edo. processId;

/** * Constructores */ public PRegister(int size) partitionSize=size; partitionStatus=0; processId=0; }

{

public PRegister(int start, int size) { this(size); partitionStartAdress=start; } /** obtiene el tamaño de la partición */ public int getPartitionSize() { return this.partitionSize; } public int getPartitionStatus() { return this.partitionStatus; }

369

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

public void setPartitionStatus(int status) { this.partitionStatus=status; } public int getProcessId() { return this.processId; } public void setProcessId(int id) { this.processId=id; this.partitionStatus=1; } public int getStartAdress() { return this.partitionStartAdress; } public void setStartAdress(int adress) { this.partitionStartAdress=adress; }

public void show() { System.out.println("Reg: "+ this.partitionStartAdress +"-"+ this.partitionSize +"-"+ this.partitionStatus + "-" +this.processId ); } }

FPRegister
/** * class FPRegister. * * @author E.J. Hernández Valdelamar * @version julio, 2002 */ public class FPRegister extends Pregister /** Constructor public FPRegister() this(0); } */ {

{

public FPRegister(int size) super(size); }

{

public FPRegister(int adress, int size) super(adress, size); } }

{

370

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

DPRegister
/** * class DPRegister. * * @author E.J. Hernández Valdelamar * @version julio, 2002 */ public class DPRegister extends Pregister /** Constructores */ public DPRegister(int size) super(size); } {

{

public DPRegister(int adress, int size) super(adress, size); } }

{

371

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Apéndice D. Simulador del servicio de administración de procesos
En este apéndice se encuentra el código del simulador de administración de memoria. Los archivos que componen al simulador son los siguientes: • • • • • • • • • CPUnit.java Timer.java ProcessManager.java ProcessList.java Dispatcher.java ProcessContext.java ScheduleStrategy.java FCFSSchedule.java PrioritySchedule.java

Para ejecutar el simulador, se integran los archivos con la herramienta BlueJ en un proyecto, y se crea una instancia de la clase ProcessManager. Esto desplegará el estado inicial de la lista de procesos (vacía; aunque el primer proceso es un proceso vacío en la posición 0). Adicionalmente hay que crear algunos procesos para que se ejecuten en el simulador, llamando al método createProcess(); y elegir la política de planificación a usar, invocando al método makeFCFSSched() o al método makePrioritySched(). Para iniciar la simulación debe llamarse al método run() lo que provocará la evaluación de los procesos durante 10 ciclos de simulación.

CPUnit
/** class CPUnit * El modelo del procesador. Versión 1. Solo es un contenedor de registros y estado de programas. Versión 2. Se introdujo un método que corresponde al ciclo de fetch para tener un medio para medir los ciclos de ejecución de los procesos, y un método para iniciar la ejecución del procesador. * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ import java.util.*; public class CPUnit {

//id y prioridad del proceso private int pid; private int prior; // registros del procesador

372

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
private List regs; private Timer timer; /** Constructor */ public CPUnit() { regs = new ArrayList(); //asociando un timer timer = new Timer(); } public List getRegisters() return regs; } {

public void setRegisters(List rs) regs=rs; } public int getProcId() { return pid; } public void setProcId(int id) { pid=id; } public int getProcPrior() { return prior; } public void setProcPrior(int p) { prior=p; }

{

public void printState() { System.out.println("Executing Process: "+ pid + " regs:" + regs.toArray()); } public void start() { //bandera para captar si el timer genera la señal de interrupción boolean cswitch=false; this.printState(); while (!cswitch) { cswitch=this.fetchCycle(); } } public boolean fetchCycle() { //aqui se obtendría la siguiente instrucción del //del programa y se ejecutaria la instrucción //terminado el ciclo de instrucción, se sincroniza //el timer return timer.syncSignal(); }

373

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

public void setTimer(int cycles) { timer.setTimer(cycles); } }

Timer
/** class Timer * Esta clase modela a un temporizador, un elemento de hardware que puede ser programado para que cada determinado tiempo envíe señales que permitan retomar el control al sistema operativo. El Timer deberá coordinarse con el procesador para que después de ciertos ciclos de ejecución las señales sean enviadas * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ public class Timer { //estado del timer private boolean status; // contador del temporizador private int counter; // ciclos que el Timer esperará private int waitFor; public Timer() { } public void reset() { status = false; counter = 0; waitFor = 0; } public boolean isActive() return status; } {

public void setTimer(int cycles) { this.reset(); waitFor=cycles; status=true; System.out.println("Timer set to:"+cycles); } /** con este método el CPU puede actualizar los

374

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
parámetros del timer (si es que está activado) y se checa si el numero de ciclos ha sido alcanzado */ public boolean syncSignal() { if (isActive()) { counter++; //si el timer esta activo, aumentar el contador de ciclos //si se alcanza el numero de ciclos, generar la señal if (counter > waitFor) { status=false; System.out.println("Timer interrupt signal("+counter+")"); return true; } } return false; } }

ProcessManager
/** * class ProcessManager . * * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ import java.util.*; public class ProcessManager private private private private {

ProcessList plist; Dispatcher disp; ScheduleStrategy sched; int pid;

/** Constructor */ public ProcessManager() { pid=0; plist = new ProcessList(); plist.printState(); //plist.addPCB(new ProcessContext()); disp = new Dispatcher(plist); disp.dispatchCPU(new CPUnit()); } public void makeFCFSSched() { System.out.println("Schedule policy: FCFS"); sched = new FCFSSchedule(); sched.relatedPList(plist); } public void makePrioritySched() { System.out.println("Schedule policy: Process Priority"); sched = new PrioritySchedule();

375

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
sched.relatedPList(plist); } public void run() { //loop infinito int i=0; while (i++ < 10) { disp.dispatch((ProcessContext)sched.scheduleProcess()); } } public void createProcess() { //crear un proceso implicara : //- subir el programa a memoria //- crear un nuevo PCB con la información de la memoria //- agregar el nuevo PCB a la lista de procesos plist.createPCB(++pid,pid,new ArrayList()); plist.printState(); } /** Para destruir un proceso se necesita su indice en la lista de procesos. Aqui, podría invocarse al adm. de memoria para que se encargue de marcar el espacio ocupado por el programa como libre, o hacer funciones de compactación. */ public void destroyProcess(int idx) { //quitar el PCB del proceso de la lista plist.removePCB(idx); } }

ProcessList
/** * class ProcessList * Esta clase es un contenedor de Bloques de Control de Proceso (PCBs) (aunque en el modelo la clase es ProcessContext). * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ import java.util.*; public class ProcessList {

//Lista de PCBs (ProcessContext procs[];) private List procs; /** Constructor */ public ProcessList() { procs = new ArrayList();

376

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
} /** * crea y agrega un proceso a la lista de procesos * @param pcb el contexto de un proceso **/ public void createPCB(int id, List regs) { ProcessContext pcb=new ProcessContext(id,regs); procs.add(pcb); } public void createPCB(int id, int priority, List regs) ProcessContext pcb=new ProcessContext(id,regs); pcb.setPriority(priority); procs.add(pcb); } /** * se agrega un proceso a la lista de procesos * @param pcb el contexto de un proceso **/ public void addPCB(Object pcb) { procs.add(pcb); } /** * se agrega un proceso a la lista de procesos * @param pcb el contexto de un proceso **/ public void removePCB(int idx) { procs.remove(idx); //procs.trimToSize(); } /** * se agrega un proceso a la lista de procesos * @param index indice de la lista **/ public Object getPCB(int index) { return procs.get(index); } public void printState() { System.out.println("Process list(" + procs.size() + "): " + procs.toString()); } //obtiene el indice del elemento con la mayor prioridad public int getMaxPriorityProcess() { //indice del proceso con la mayor prioridad int ihighPriorProc=0; //maxima prioridad registrada int maxprior=-1; //indice de la lista de procesos {

377

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
int idx=0; for (Iterator iter=procs.listIterator();iter.hasNext();) { ProcessContext pctx=(ProcessContext)iter.next(); int prior=pctx.getPriority(); //si la prioridad del proceso es mayor a la ultima cotejada //asignar como máxima prioridad la del proceso actual y salvar //el indice del elemento if (prior > maxprior) { maxprior=prior; ihighPriorProc=idx; } idx++; } System.out.println(idx+" Pick priority:"+maxprior+ " at:"+ihighPriorProc); return ihighPriorProc; } }

ProcessContext
/** * class ProcessContext * El contexto del proceso esta formado por la información que los registros del procesador contienen al ejecutar un programa. Esta clase creará objetos equivalentes a los Bloque de Control de proceso (PCBs). Para fines de diseño, puede modificarse esta clase para un PCB más completo , o crear una subclase con dicho fin. Versión 1. Solo se tiene un identificador de proceso y los registros del contexto del procesador. private int proc_id; private List cpu_regs; Versión 2. Se agregó soporte de intervalos de tiempo para usarlos en conjunto con el temporizador, además de un campo de prioridad para determinar que procesos tienen mayor jerarquia en la ejecución. * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ import java.util.*; public class ProcessContext { //identificador del proceso private int proc_id; // los registros del CPU

378

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
private List cpu_regs; //cuota de tiempo de ejecución (basada en ciclos de instrucción) private int timeQuantum; //prioridad del proceso private int priority; /** Constructor */ public ProcessContext(int id, List regs) proc_id=id; this.addRegs(regs); } public ProcessContext() proc_id=0; } {

{

public void addRegs(List regs) cpu_regs=regs; } public List getRegs() { return cpu_regs; } public void setProcId(int id) { proc_id=id; } public int getProcId() { return proc_id; } public void setPriority(int p) priority=p; } public int getPriority() return priority; } } {

{

{

Dispatcher
/** * class Dispatcher * El despachador es el encargado de intercambiar el contexto del proceso en ejecución, por un nuevo proceso a ejecutarse. Para llevar a cabo esta función, debe asociarse una lista de procesos al despachador para que pueda obtener el siguiente proceso. * @author (Eugenio Jacobo Hernández Valdelamar)

379

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
* @version 2001 */ public class Dispatcher {

// Lista de procesos asociada private ProcessList plist; //CPU en el que se controlara el contexto private CPUnit localCPU; private int lastDispatchedId; /** Constructor */ public Dispatcher(ProcessList pl) plist=pl; lastDispatchedId = -1; } public void dispatchCPU(CPUnit cpu) localCPU=cpu; } {

{

//ningun proceso despachado

/** * Funcionamiento: 1. obtiene el contexto del proceso en ejecución 2. inserta el nuevo contexto en la lista de procesos, y cambia su estado 3. envia el contexto en espera de ejecución al procesador para que se ejecute * * @param pcb contexto del proceso a ejecutar */ public void dispatch(ProcessContext pcb) { //obtener el proceso del proceso en ejecución y //se envia a la lista de procesos this.sendContextToPList(this.getContextFromCPU()); //falta por enviar el contexto en turno de ejecución al //procesador this.sendContextToCPU(pcb); } /** * Envia el contexto al procesador para ejecutar un nuevo proceso * * @param pcb contexto del proceso que estaba en el procesador **/ private void sendContextToPList(ProcessContext pcb) { System.out.println("From CPU to PList:"+pcb.getProcId()); plist.addPCB(pcb); } /**

380

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
* Obtiene el contexto del proceso que se ejecuta en el procesador **/ private ProcessContext getContextFromCPU() { //instancia para salvar el contexto del proceso en ejecución ProcessContext inExec = new ProcessContext(); //obtener la información del procesador, o estructura //que contenga esta info. //* en el caso del procesador, debe ejecutarse la instrucción //para obtener los registros del procesador inExec.setProcId(localCPU.getProcId()); inExec.setPriority(localCPU.getProcPrior()); inExec.addRegs(localCPU.getRegisters()); return inExec; } /** * envio del contexto de un proceso al procesador * * @param pcb contexto del proceso que estaba en espera y se va a ejecutar **/ private void sendContextToCPU(ProcessContext pcb) { //*en el caso del procesador, debe ejecutarse la instrucción que //permite establecer los valores de los registros localCPU.setProcId(pcb.getProcId()); localCPU.setProcPrior(pcb.getPriority()); localCPU.setRegisters(pcb.getRegs()); localCPU.setTimer(20); localCPU.start(); } }

ScheduleStrategy
/** * abstract class ScheduleStrategy * * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ public abstract class ScheduleStrategy { ProcessList plist; /*public void init (Dispatcher dispatch) { dispatcher = dispatch; } */ public void relatedPList(ProcessList pl) { plist=pl; }

381

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

public Object getProcess(int idx) { Object p=plist.getPCB(idx); plist.removePCB(idx); return p; } public abstract Object scheduleProcess(); }

FCFSSchedule
/** * class FCFSSchedule * Política First-Come, First-Served (FIFO) de planificación * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ public class FCFSSchedule extends ScheduleStrategy /** Constructor */ public FCFSSchedule() { //init(d); System.out.println("FCFS Scheduler"); } /** * Se obtiene el primer elemento de la lista de procesos * @param y a sample parameter for a method */ public Object scheduleProcess() { return super.getProcess(0); } } {

PrioritySchedule
/** * class PrioritySchedule * Implementación de la planificación por prioridades. Se elige al proceso en la lista de procesos preparados con la mayor prioridad. * @author (Eugenio Jacobo Hernández Valdelamar) * @version 2001 */ import java.util.*; public class PrioritySchedule extends ScheduleStrategy { /** Constructor */

382

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
public PrioritySchedule() { System.out.println("Process Priority Scheduler"); } /** Obtener el proceso de mayor prioridad de la lista. */ public Object scheduleProcess() { return super.getProcess(plist.getMaxPriorityProcess()); } }

383

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

Apendice E. Caso de estudio: Implementación de un microkernel57
Como caso de estudio práctico, decidí incluir el código de la implementación del microkernel RTMK (Real Time Micro-Kernel), basado en la especificación Screpte. El conjunto de servicios del kernel Screpte son: MANEJO DE TAREAS State SEÑALES Send Wait Clear (reset) Arrived ESTADOS DE LAS TAREAS Wait Ready Active Hay que hacer notar que no se encuentran los servicios para realizar la exclusión mutua entre los procesos (RTMK solo toma un subconjunto de la especificación para su implementación). Esta implementación consta de 4 archivos: RTMKTYPE.H RTMK.H RTMK.C TestRTMK.C Cabe mencionar que existen librerías standart de C que simplifican la operación de cambio de contexto (pues si no tendría que hacerse en ensamblador), en específico la librería setjmp.h, que contiene las siguientes funciones: a. setjmp - Preparación para una operación de salto (goto) no local Sintáxis: int setjmp(jmp_buf jmpb);

setjmp captura el estado completo de la tarea en la estructura jmp_buf y regresa 0.

57

Adaptado de [G6]

384

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

typedef struct { unsigned j_sp, unsigned j_ip, unsigned j_di, unsigned j_si, } jmp_buf[1];

j_ss, j_bp; j_es; j_ds;

unsigned

j_flag, j_cs;

Una llamada posterior a la función longjmp (setjmp siempre debe llamarse antes de longjmp) con jmpb restaura el estado capturado de la tarea, y regresa de manera que setjmp regresa un valor diferente de cero. El estado de una tarea consta de: todos los registros de segmento (CS, DS, ES, SS) las variables de registro (SI, DI) el apuntador de la pila (SP) frame base pointer (BP) las banderas (flags)

El estado de una tarea es lo suficientemente completo como para usar setjmp para implementar corrutinas. Portabilidad: setjmp esta disponible en sistemas UNIX y esta definida en ANSI C.

b. longjmp - Realiza un salto (goto) no local. Sintáxis: void longjmp(jmp_buf jmpb, int retval);

Una llamada a longjmp restaura el estado de la tarea capturado por la ultima llamada a setjmp con el argumento jmpb. Entonces regresa de manera que parece que setjmp ha regresado con el valor del parámetro retval. A continuación se encuentra el código fuente del microkernel.

/* RTMKType.H Definicion de la estructura del PCB de los procesos Controlados por el kernel */ #include <setjmp.h> typedef unsigned long word32; typedef word32 SIGNALS;

385

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
struct PCS { /* Contexto del microprocesador.*/ jmp_buf context; /* Si el bit n esta prendido la se¤al n puede activar el proceso*/ SIGNALS expected_signals; /* Cada bit encendido indica que la se¤al correspondiente ha sido enviada al proceso*/ SIGNALS received_signals; word32 pmask,priority; }; typedef struct PCS *PROCESS; /* Fin RTMKType.H */ /* RTMK.H Definicion de prototipos de funciones */ #include "rtmktype.h" #define ANY_SIGNAL 0xffffffff #define ALL_SIGNALS 0xffffffff /* Prototipos de las funciones del RTMK. */ void create_process (PROCESS *,void far *); void send (PROCESS,SIGNALS); /* Fin RTMK.H */ /* RTMK.C Implementacion de los servicios del microkernel */ #include "rtmktype.h" #include <dos.h> #define NULL 0 #define PROCESS_STACK_SIZE 500 unsigned _stklen=20; /*Apuntador al PCS*/ /* Prioridad del proceso.*/

/*tama¤o del stack para cada proceso*/

/*stack minimo para inicializar el kernel*/

struct PCS pcs_tab[32]; /*tabla de Estructuras de Contexto de Procesos*/ unsigned stack[32*PROCESS_STACK_SIZE]; /*tabla de stacks para los procesos*/ unsigned nbr_process; /*numero de proceso declarado*/ PROCESS current_process; /*apuntador al proceso actual PCS*/ word32 ready_process; /*lista de procesos 'ready'*/ word32 free_time; /*tiempo no usado por el proceso*/

386

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

/*-------------------------------------------------------------*/ /* create_process: declara el proceso donde p es el identificador para el kernel y entry_point es la direccion del codigo del proceso. */ void create_process (PROCESS *process_id,void far *entry_point()) { if (nbr_process<32) /*32 es el numero maximo de procesos*/ { *process_id=pcs_tab+nbr_process; (pcs_tab[nbr_process].context)->j_ip=FP_OFF(entry_point); (pcs_tab[nbr_process].context)->j_cs=FP_SEG(entry_point); (pcs_tab[nbr_process].context)->j_flag=0; /* Stack del proceso */ (pcs_tab[nbr_process].context)->j_sp= (unsigned)stack+PROCESS_STACK_SIZE*(32-nbr_process); (pcs_tab[nbr_process].context)->j_bp= (pcs_tab[nbr_process].context)->j_sp; (pcs_tab[nbr_process].context)->j_ds=FP_SEG((void far *)stack); (pcs_tab[nbr_process].context)->j_ss=FP_SEG((void far *)stack); nbr_process++; } } /* Scheduler: el contexto del proceso actual es salvado y el sistema cambia al proceso listo. Si next_process=NULL el proceso listo con mayor prioridad es buscado, de otra forma el proceso es el proceso listo. En este caso la planificacion esta basada en la prioridad (variable priority de la estructura PCS; pmask ademas es usada para llevar a cabo el switcheo de contexto, siendo precalculada durante la creacion del proceso, evitando operaciones extras a tiempo de ejecucion (p.ej.shifts)) de los procesos que se encuentran en la lista de PCS. */ void scheduler (PROCESS next_process) { word32 n,i; if (setjmp(current_process->context)==0) { if (next_process) current_process=next_process; else { n=0; i=0x80000000; while (!(i&ready_process)) { n++; i>>=1; } current_process=pcs_tab+n; }

387

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
longjmp(current_process->context,1); } } /* Manejo de señales.*/ /* send: envia las señales del proceso que estan en (1) en signals_mask. */ void send (PROCESS proceso,SIGNALS signals_mask) { proceso->received_signals|=signals_mask; if (proceso->received_signals&proceso->expected_signals) { ready_process|=proceso->pmask; proceso->expected_signals=0; if (current_process->priority < proceso->priority) scheduler(proceso); } } /* wait: coloca al proceso actual en espera de que signals_mask regrese las se¤ales recibidas. */ SIGNALS wait (SIGNALS signals_mask) { if (!(current_process->received_signals&signals_mask)) { current_process->expected_signals=signals_mask; ready_process^=current_process->pmask; scheduler(NULL); /*cambia al sig. proceso*/ } return (current_process->received_signals); } /* reset: pone a las se¤ales encendidas en signals_mask en cero y regresa las se¤ales que han llegado */ SIGNALS reset (SIGNALS signals_mask) { SIGNALS old_signals; old_signals=current_process->received_signals; current_process->received_signals= current_process->received_signals&~signals_mask; return (old_signals); } SIGNALS arrived_signals (void) { return (current_process->received_signals); } /*Regresa las señales esperadas del proceso.*/ SIGNALS process_state (PROCESS proceso) { return (proceso->expected_signals); }

388

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
/* Kernel:inicializa las variables del kernel y cambia al primer proceso el ultimo ciclo es el proceso idle del sistema. La prioridad del proceso esta definida en este caso en orden descendente de la lista de PCS y el numero que se le asigna es la diferencia entre el numero maximo de procesos y el numero de procesos a ejecutar. Las señales son enviadas */ directamente a las tareas y no al kernel.

int run_kernel (void) { int i; word32 current_process_mask; PROCESS pcs_ptr; disable(); current_process_mask=0x80000000; ready_process=0; for (i=0;i<=nbr_process;i++) { pcs_ptr=pcs_tab+i; pcs_ptr->received_signals=0; pcs_ptr->pmask=current_process_mask; pcs_ptr->priority=nbr_process-i; ready_process|=current_process_mask; current_process_mask=current_process_mask>>1; } current_process=pcs_tab+nbr_process; free_time=0; scheduler(pcs_tab); enable(); for(;;) free_time++; } /* Fin RTMK.C */ /* TestRTMK.C Programa de prueba para el RTMK */ #include #include #include #include #include "RTMK.H" <stdio.h> <conio.h> <dos.h> <signal.h>

/* Esta interrupción (1Ch- CLOCK TICK) es llamada al final de cada operación de up-date de una rutina, y es redireccionada por el programa para llamar a los procesos concurrentes por el kernel. */

389

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar
#define IT 0x1C #define VIDEO 0xB8000000

/* Memoria de video.*/

PROCESS p1,p2; int i,j; char far* p=(char far*)VIDEO+1;

/* Apuntador a la mem. de video. */

/*-------------------------------------------------------------*/ void interrupt (*old_vector) (); void interrupt clock_it() { outp(0x20,0x20); i++; if (i==100) { i=0; send(p2,1); } else send(p1,1); } far process1() { while(1) { p++; *p++=0x31; /* caracter desplegado en pantalla (1) */ if (p>(char far *)VIDEO+25*80*2) /*si llega al final de la pantalla*/ p=(char far *) VIDEO+1; /* vuelve a posicionar al principio*/ wait(ANY_SIGNAL); reset(ALL_SIGNALS); } } far process2() { static long n; enable(); while(1) { printf("process2 : esperando \t"); wait(1); printf("process2 : reset a se¤ales \t"); reset(1); printf("process2 : calculando "); for (j=0;j<60;j++) { for (n=0;n<100000;n++); printf("."); } printf("calculo terminado \n"); sound(2000); delay(200); nosound(); } } jmp_buf sys_context;

390

Diseño y simulación de sistemas operativos – Eugenio Jacobo Hernández Valdelamar

void terminate() { longjmp(sys_context,1); } void main() { clrscr(); create_process(&p1,process1); create_process(&p2,process2); old_vector=getvect(IT); disable(); signal(SIGINT,terminate); setvect(IT,clock_it); if (!setjmp(sys_context)) run_kernel(); setvect(IT,old_vector); } /* Fin TestRTMK.C */

391

You're Reading a Free Preview

Descarga