Está en la página 1de 407

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. Fundamentos de los Sistemas Operativos _______________________ 7
1.1 ¿Qué es un sistema operativo? ___________________________________________ 7
1.1.1 Definiciones ______________________________________________________________ 8
1.1.2 Características principales__________________________________________________ 10
1.2 Principales conceptos de los Sistemas Operativos___________________________ 11
1.2.1 Administración de procesos _________________________________________________ 12
1.2.2 Administración de memoria _________________________________________________ 13
1.2.3 La gestión de la integridad __________________________________________________ 13
1.2.4 Administración de dispositivos ______________________________________________ 14
1.2.5 Almacenamiento secundario ________________________________________________ 14
1.2.6 Transmisión de datos e información __________________________________________ 15
1.2.7 Núcleo del sistema (Kernel)_________________________________________________ 15
1.2.8 Comunicación con el usuario ________________________________________________ 16
1.3 Desarrollo histórico de los Sistemas Operativos ____________________________ 18
1.3.1 En el principio...__________________________________________________________ 20
1.3.2 Procesamiento por lotes y monitores __________________________________________ 21
1.3.3 Sistemas de operación simultanea de periféricos en línea __________________________ 23
1.3.4 Sistemas de Multiprogramación______________________________________________ 24
 Sistemas de tiempo compartido (Timesharing) ____________________________________ 25
 Sistemas de Tiempo Real _____________________________________________________ 27
1.3.5 Sistemas Multiprocesador, distribuidos y en red _________________________________ 28
1.3.6 Computadoras Personales __________________________________________________ 30
1.4 Comentarios _________________________________________________________ 32
1.5 Obras consultadas ____________________________________________________ 33
Capitulo 2. Funcionamiento básico de un sistema operativo_________________ 35
2.1 El hardware y la ejecución de programas _________________________________ 35
2.1.1 La unidad central de procesamiento___________________________________________ 36
2.1.2 La memoria _____________________________________________________________ 38
2.1.3 Ejecución de programas ____________________________________________________ 39
2.1.4 Interacción entre los componentes de hardware__________________________________ 41
 Tipos de interrupciones ______________________________________________________ 45
2.2 Software para el control del hardware____________________________________ 46
2.2.1 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. Simulación de Hardware y Sistemas Operativos _________________ 59
3.1 La simulación en el diseño de sistemas operativos __________________________ 60
3.2 Emulación y Simulación de hardware ____________________________________ 63
3.2.1 Emulación de hardware ____________________________________________________ 63
 ¿Cómo se instrumenta un emulador? ____________________________________________ 65
3.2.2 Simulación de hardware____________________________________________________ 65
3.3 Máquinas virtuales ____________________________________________________ 66
3.3.1 El sistema P _____________________________________________________________ 67
3.4 Plataformas de simulación de Sistemas Operativos _________________________ 68
3.4.1 Java Operating System Simulation ___________________________________________ 68
3.4.2 NachOS ________________________________________________________________ 71
 La máquina Nachos _________________________________________________________ 72
3.4.3 RCOS __________________________________________________________________ 73
3.5 Simulación de un Sistema Operativo mínimo ______________________________ 75
3.5.1 El hardware: URM ________________________________________________________ 76
3.5.2 El software: SOM_________________________________________________________ 78
3.5.3 Consideraciones para el modelado de dispositivos de E/S__________________________ 81
3.5.4 Resultados ______________________________________________________________ 83
3.5.5 morfo-Hardware__________________________________________________________ 84
3.6 Comentarios _________________________________________________________ 86
3.7 Obras consultadas ____________________________________________________ 87
Capitulo 4. Administración de la memoria _______________________________ 89
4.1 La memoria__________________________________________________________ 89
4.1.1 Asignación de direcciones __________________________________________________ 90
4.1.2 La unidad de administración de memoria (MMU)________________________________ 91
 Memoria asociativa _________________________________________________________ 92
4.1.3 Manejo estático y dinámico de la memoria _____________________________________ 93
4.1.4 Carga de programas en memoria _____________________________________________ 93
 Overlays __________________________________________________________________ 94
 Relocalización _____________________________________________________________ 95
4.2 Administración de la memoria __________________________________________ 96
4.2.1 Administración manual ____________________________________________________ 97
4.2.2 Administración automática _________________________________________________ 98
4.2.3 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
4.3.1 Alojamiento contiguo y no contiguo _________________________________________ 110
4.3.2 Estrategias de asignación __________________________________________________ 111
4.3.3 Fragmentación y compactación _____________________________________________ 111

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

 Subalojadores_____________________________________________________________ 112
4.3.4 Paginación _____________________________________________________________ 112
 Reemplazo de páginas ______________________________________________________ 115
4.3.5 Segmentación ___________________________________________________________ 116
4.3.6 Segmentación con paginación ______________________________________________ 117
4.4 Simulación del servicio de administración de memoria _____________________ 119
4.5 Comentarios ________________________________________________________ 122
4.5 Obras consultadas ___________________________________________________ 123
Capitulo 5. Administración de procesos ________________________________ 125
5.1 Ejecución de programas y procesos _____________________________________ 125
5.1.1 Modelos de ejecución_____________________________________________________ 125
5.1.2 Procesos _______________________________________________________________ 127
5.1.3 Hilos__________________________________________________________________ 128
5.1.4 Representación de los procesos _____________________________________________ 129
5.1.5 Creación de procesos _____________________________________________________ 130
5.1.6 Estados de un proceso ____________________________________________________ 132
5.1.7 Colas de procesos________________________________________________________ 133
 Llamadas de servicios ______________________________________________________ 134
5.1.8 Operaciones de manipulación de procesos_____________________________________ 134
5.1.9 ¿Por qué usar procesos? ___________________________________________________ 135
5.2 Planificación de procesos ______________________________________________ 136
5.2.1 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 Simulación del servicio de administración de procesos _____________________ 152
5.4 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 Comentarios ________________________________________________________ 180
5.6 Obras consultadas ___________________________________________________ 181
Capitulo 6. Administración de dispositivos, almacenamiento y comunicaciones. 183
6.1 Administración de dispositivos y periféricos ______________________________ 184
6.1.1 Dispositivos de Entrada - Salida ____________________________________________ 185
6.1.2 Controladores de Dispositivos ______________________________________________ 185
6.1.3 Manejadores de dispositivos (device drivers) __________________________________ 187
6.1.4 Acceso Directo a Memoria_________________________________________________ 190
6.1.5 Caso de estudio: Manejo de dispositivos en UNIX ______________________________ 191
6.2 Administración de archivos____________________________________________ 193
6.2.1 Medios de almacenamiento ________________________________________________ 194
6.2.2 Manejador de discos______________________________________________________ 195
6.2.3 Archivos_______________________________________________________________ 196
6.2.4 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 Comentarios ________________________________________________________ 223
6.5 Obras consultadas ___________________________________________________ 225
Capitulo 7. Diseño de sistemas operativos_______________________________ 227
7.1 El software y sus características ________________________________________ 228
7.1.1 ¿Por qué es necesario un sistema operativo? ___________________________________ 229
7.1.2 ¿Para qué escribir un sistema operativo? ______________________________________ 230
7.2 Desarrollo de sistemas de software ______________________________________ 230
7.2.1 Proceso de desarrollo de software ___________________________________________ 230
7.2.2 Ingeniería de software ____________________________________________________ 231
 Concepto de ciclo de vida ___________________________________________________ 232
 Fases genéricas de la ingeniería de software _____________________________________ 233

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

 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
7.4.1 Preguntas importantes: en busca de requerimientos______________________________ 252
7.4.2 Metas del diseño_________________________________________________________ 254
7.4.3 Estructura del sistema operativo ____________________________________________ 255
7.4.4 Mecanismos y políticas ___________________________________________________ 257
7.5 Diseño de sistemas operativos: el enfoque de los desarrolladores _____________ 257
7.5.1 El enfoque de diseño más simple ____________________________________________ 258
7.5.2 Consideraciones de diseño de sistemas operativos ______________________________ 260
7.5.3 Diseño de kernels ________________________________________________________ 262
 Clasificación de los kernels __________________________________________________ 263
 Criterios de planificación ____________________________________________________ 265
7.5.4 Consideraciones sobre la codificación del sistema ______________________________ 266
7.5.5 Uso de estándares y portabilidad ____________________________________________ 266
7.6 Diseño de sistemas operativos: la interacción con el usuario _________________ 267
7.6.1 Interacción humano-computadora_______________________________________________ 268
7.6.2 Interfaz basada en texto_______________________________________________________ 269
7.6.3 Interfaz gráfica de usuario ____________________________________________________ 270
7.6.4 Interfaces alternativas ________________________________________________________ 273
7.6.5 Diseño de interfaces de usuario_________________________________________________ 274
7.7 Diseño de sistemas operativos: la administración de sistemas ________________ 276
7.8 Comentarios ________________________________________________________ 277
7.9 Obras consultadas ___________________________________________________ 280
Capitulo 8. Arquitecturas de Sistemas Operativos ________________________ 285
8.1 Representación de la arquitectura ______________________________________ 286
8.2 Arquitecturas de Sistemas Operativos ___________________________________ 287
8.3 Arquitectura de kernel monolítico ______________________________________ 288
8.4 Arquitectura de capas y anillos_________________________________________ 290
8.5 Arquitectura de máquina virtual _______________________________________ 293
8.6 Arquitectura de microkernel y multihilado _______________________________ 295
8.7 Arquitecturas Orientadas a Objetos_____________________________________ 298
8.7.1 Sistemas operativos basados en componentes __________________________________ 301

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

8.8 Arquitectura cliente-servidor __________________________________________ 302


 Implantación del modelo C/S para sistemas operativos distribuidos ___________________ 304
8.9 Arquitecturas en red y distribuidas _____________________________________ 305
8.9.1 Criterios de diseño de sistemas distribuidos____________________________________ 308
8.9.2 Mach _________________________________________________________________ 309
8.10 Arquitecturas adaptables____________________________________________ 312
8.11 Arquitectura de Exokernel __________________________________________ 314
8.12 Arquitecturas orientadas a agentes____________________________________ 317
8.13 Comentarios ______________________________________________________ 319
8.14 Obras consultadas__________________________________________________ 321
Resultados, conclusiones y perspectivas ___________________________________ 325
a. Resultados __________________________________________________________ 325
b. Aportaciones ________________________________________________________ 326
c. Conclusiones __________________________________________________________ 328
c.1 ¿Por qué seguir desarrollando nuevos sistemas operativos? _________________________ 329
c.2 Los sistemas operativos y el desarrollo de marcos conceptuales (frameworks)___________ 330
c.3 Tendencias en el desarrollo de sistemas operativos ________________________________ 330
d. Perspectivas_________________________________________________________ 330
e. Referencias ___________________________________________________________ 332
Bibliografía__________________________________________________________ 333
Glosario_____________________________________________________________ 335
Apéndices ___________________________________________________________ 341
Apéndice A. Programación de Cargadores (sectores de arranque) _________________ 341
Apéndice B. Simulación de un sistema mínimo de hardware y su sistema operativo___ 346
Apéndice C. Simulador del servicio de administración de la memoria ______________ 357
Apéndice D. Simulador del servicio de administración de procesos_________________ 372
Apendice E. Caso de estudio: Implementación de un microkernel _________________ 384

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

Lista de figuras y tablas

Organización del trabajo. ................................................................................................................................ 3


Figura 1.1 Vista de los programas de sistema y de aplicación........................................................................ 8
Figura 1.2 El SO administra los recursos de hardware y software de la computadora, y provee un medio
estable y consistente donde las aplicaciones puedan usar el hardware. .................................................. 8
Figura 1.3 Soporte de software necesario para aprovechar los recursos del hardware. ................................ 11
Tabla 1. Recursos de la arquitectura, administración del sistema operativo y abstracciones del usuario. .... 12
Figura 1.4 Esquema de los diferentes tipos de memoria en un sistema de cómputo..................................... 13
Figura 1.5 Niveles de interacción de un shell ............................................................................................... 17
Figura 1.6 Ejemplos de interfaz gráfica de usuario: (a) el sistema NeXT; (b) Mac OS X............................ 18
Figura 1.7 Cronología del desarrollo de las computadoras y los sistemas operativos. ................................ 19
Figura 1.8 Esquema de operación de las primeras computadoras................................................................. 20
Figura 1.9 Esquema básico de la memoria de una computadora con procesamiento por lotes (monitor
residente)............................................................................................................................................... 22
Figura 1.10 Esquemas básicos de procesamiento. Nótese como el tiempo desperdiciado ha ido
disminuyendo........................................................................................................................................ 23
Figura 1.11 Esquema de sistema de multiprogramación (o multitarea), donde varias tareas son ejecutadas
simultáneamente. .................................................................................................................................. 24
Figura 1.12 Esquema de ejecución de dos procesos con y sin multiprogramación....................................... 25
Figura 1.13 Esquema de un sistema de tiempo compartido. ......................................................................... 26
Figura 1.14 Esquema de un sistema de control, en donde deben ser aceptados y procesados gran cantidad de
sucesos. ................................................................................................................................................. 27
Figura 1.15 Configuraciones de multiprocesamiento asimétrico(a) y simétrico(b). ..................................... 28
Figura 1.16 Esquema de un sistema operativo distribuido........................................................................... 30
Figura 1.17 Las primeras PCs: (a) MITS Altair (1974), (b) Radio Shack TRS-80 (1977), (c) Apple I (1976),
(d) Apple Lisa (1983)............................................................................................................................ 31
Figura 2.1 Modelo de Von Neumann............................................................................................................ 36
Figura 2.2 El procesador y demás dispositivos se conectan por medio de enlaces físicos conocidos como
buses. .................................................................................................................................................... 36
Figura 2.3 Modelo de un microprocesador simple....................................................................................... 37
Figura 2.4 El CPU accede diferentes tipos de memoria................................................................................ 39
Tabla 2. Comparación de un programa en lenguaje de alto nivel, ensamblador y código máquina............. 40
Figura 2.5 Esquema de la ejecución de un programa.................................................................................... 41
Figura 2.6 Los componentes de hardware pueden comunicarse con el CPU mediante controladores.......... 42
Figura 2.7 Software relacionado al control del hardware. ............................................................................ 46
Figura 2.8 Secuencia del inicio de ejecución del sistema operativo. ............................................................ 52
Figura 3.1a Esquema de la arquitectura del FLUX OSKit........................................................................... 61
Figura 3.1b Esquema de la arquitectura del Palm OS................................................................................... 62
Figura. 3.2 Emulación interpretativa............................................................................................................. 64
Figura 3.3 Emulación de compilación dinámica........................................................................................... 64
Figura 3.4 Clases y métodos del JOSS.......................................................................................................... 69
Figura 3.5 Forma en que los diferentes componentes de Nachos están ligados durante la ejecución........... 72
Figura 3.6 Arquitectura del RCOS................................................................................................................ 75
Figura 3.7 Modelo del simulador con un cargador de programas................................................................. 78
Figura 3.8 Modelo del simulador con un SOM para una URM modificada, basado en el concepto de un
monitor residente. ................................................................................................................................. 80
Figura 3.9 Patrón de diseño Modelo-Vista-Controlador............................................................................... 84
Figura 3.10 Esquema del modelo morfo-Hardware ..................................................................................... 85
Figura 3.11 Modelo de clases de morfo-Hardware v.0.1 .............................................................................. 85
Figura 3.12 Modelo de clases de morfo-Hardware v.0.2 .............................................................................. 86
Figura 4.1 Vista simplificada del espacio de direcciones en la memoria...................................................... 90
Figura 4.2 La MMU se sitúa justo entre el CPU y la memoria.................................................................... 92
Figura 4.3 Cuando el CPU quiere acceder a la memoria, le manda la dirección que quiere a la MMU quien

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

la traduce en otra dirección que le pasa a la unidad de memoria. ......................................................... 92


Figura 4.4 Carga de un programa en memoria virtual .................................................................................. 94
Figura 4.5 Esquema de un sistema que implementa recubrimientos............................................................ 95
Figura 4.6 Esquemas de organización de memoria con manejo de dos particiones...................................... 99
Figura 4.7 Administración con particiones fijas ......................................................................................... 100
Figura 4.8 Administración con particiones variables.................................................................................. 101
Figura 4.9 Administración con mapa de bits .............................................................................................. 102
Figura 4.10 Administración con listas ligadas ............................................................................................ 102
Figura 4.11 Intercambio.............................................................................................................................. 105
Figura 4.12 Administración con memoria virtual ....................................................................................... 106
Figura 4.13 Dependencias y flujos de control y datos en el administrador de memoria............................. 109
Figura 4.14 Estructura del administrador de memoria de Linux................................................................. 110
Figura 4.15 En la paginación el tamaño de la página debe ser una potencia de 2....................................... 113
Figura 4.16 Traducción de direcciones en un sistema de paginación ......................................................... 113
Figura 4.17 Direccionamiento en MS-DOS usando segmentación (8086-16 bits). Capacidad de
direccionamiento 220=1'048,576=1MB............................................................................................... 114
Figura 4.18 Traducción de direcciones en la segmentación........................................................................ 116
Figura 4.19 Traducción de direcciones en un sistema con segmentación ................................................... 117
Figura 4.20 Método de segmentación y paginación.................................................................................... 118
Figura 4.21 Traducción de direcciones en un sistema con segmentación y paginación.............................. 118
Figura 4.22 Los esquemas de particiones fijas, variables y paginación manejan programas como bloques
únicos. ................................................................................................................................................. 119
Figura 4.23 La segmentación y la segmentación con paginación son más aptos para manejar programas y
módulos dinámicos. ............................................................................................................................ 120
Figura 4.24 Modelo de clases del simulador de administración de memoria.............................................. 121
Figura 4.25 Ejecución del simulador. ......................................................................................................... 122
Figura 5.1 Modelos de ejecuciónen sistemas de cómputo .......................................................................... 126
Figura 5.1a Esquema de un sistema monotarea .......................................................................................... 126
Figura 5.1b Esquema de un sistema multitarea........................................................................................... 127
Figura 5.2 Esquema del intercambio de procesos con el CPU en un sistema multitarea. .......................... 129
Figura 5.3 Esquemas de estados y transiciones de un proceso .................................................................. 132
Figura 5.4 Niveles de planificación ............................................................................................................ 137
Figura 5.5 Esquema de las dependencias y flujos de control y datos en el planificador de procesos ......... 141
Figura 5.6 Estructura del planificador de procesos de Linux...................................................................... 142
Figura 5.7 Para un quantum=1 se presenta la secuencia de ejecución de procesos .................................... 146
Figura 5.8 Ejemplo de los algoritmos SJF y SRTF..................................................................................... 148
Figura 5.9 Colas múltiples de prioridad...................................................................................................... 149
Figura 5.10 Planificación de 2 niveles ........................................................................................................ 151
Figura 5.11 Esquema del funcionamiento de la administración de procesos.............................................. 152
Figura 5.11a Modelo de clases del simulador de administración de procesos. ........................................... 154
Figura 5.12 Ejecución del simulador. ......................................................................................................... 155
Figura 5.12 Los procesos P1 y P2, así como P2 y P3 son concurrentes, en cambio P3 y P1 no lo son ...... 155
Figura 5.13 Interbloqueo............................................................................................................................. 167
Figura 5.14 Esquema donde los procesos que requieren acceder a un recurso compartido ........................ 170
Figura 5.15 Entrega de mensajes con múltiples colas................................................................................. 173
Figura 5.16 Estructura del subsistema IPC de Linux .................................................................................. 175
Figura 5.17 Esquema de procesos que se ejecutan en una computadora y en un sistema distribuido......... 176
Figura 5.18 Modelo cliente-servidor en un escenario distribuido.............................................................. 177
Figura 5.19 Esquema de invocación local y remota de procedimientos ..................................................... 179
Figura 6.1 Capas del sistema de entrada-salida........................................................................................... 184
Figura 6.2 Arquitecturas de entrada-salida y disposiciones de los dispositivos conectados al bus............. 186
Figura 6.3 Esquemas de E/S y su acceso mediante instrucciones en ensamblador..................................... 186
Figura 6.4 Capas del software de entrada-salida......................................................................................... 188
Figura 6.5 Flujo de operaciones en un manejador de dispositivo. .............................................................. 189
Figura 6.6 Flujos de E/S por el DMA ......................................................................................................... 190
Figura 6.7 Estructura de un manejador de discos........................................................................................ 195

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

Figura 6.8 Objetos del sistema operativo y sus operaciones relacionadas con archivos. ............................ 197
Figura 6.9 Esquema del sistema de almacenamiento secundario............................................................... 197
Figura 6.10 Esquema del sistema de almacenamiento terciario.................................................................. 199
Figura 6.11 Formato de un archivo ejecutable............................................................................................ 200
Figura 6.12 Organización de archivos con directorios................................................................................ 200
Figura 6.13 Representaciones de archivos en UNIX, MS-DOS y Windows NT ........................................ 201
Figura 6.14 Ejemplos de estructuras en sistemas operativos como UNIX, MS-DOS y Windows. ............ 202
Figura 6.15 Esquema de la aplicación de operaciones de acceso y manipulación en un archivo .............. 204
Figura 6.16 Sistema virtual de archivos de Linux....................................................................................... 209
Figura 6.17 Estructura del administrador de archivos de Linux ................................................................. 210
Figura 6.18a Algunas ejemplos de las topologías que una red puede adoptar. .......................................... 213
Figura 6.18b Modelo OSI y los equivalentes en el modelo de protocolos TCP/IP..................................... 214
Figura 6.19 Arquitectura de Netware 2.2.................................................................................................... 214
Figura 6.20 Estructura del subsistema de red de Linux .............................................................................. 216
Figura 6.21 Conjunto de protocolos TCP/IP y su relación con el modelo OSI........................................... 218
Tabla 3. Relación de dispositivos de cómputo y sus sistemas operativos................................................... 229
Figura 7.1 Esquema del proceso unificado de desarrollo (RUP) ................................................................ 231
Figura 7.2 Ciclo de vida en cascada............................................................................................................ 232
Figura 7.3 Visiones de un sistema de software ........................................................................................... 237
Figura 7.4 La definición de la arquitectura está entre el análisis del sistema y su diseño........................... 240
Figura 7.5 Descomposición de elementos de diseño................................................................................... 241
Tabla 4. Estructuras de una arquitectura de software.................................................................................. 243
Figura 7.6 Vistas posibles de un elemento de diseño (lógica, concurrente o de instalación)...................... 244
Figura 7.7 Algunos tipos de estilos arquitectónicos.................................................................................... 247
Figura 7.8 Diagrama de clase del patrón microkernel ................................................................................ 250
Figura 7.9 Vista de capas de la arquitectura de un sistema operativo ......................................................... 256
Figura 7.10 Dispositivos de interfaz ........................................................................................................... 268
Figura 7.11 Interfaz de usuario del MS-DOS ............................................................................................. 269
Figura 7.12 Patrón de diseño Interpreter..................................................................................................... 270
Figura 7.13 Interfaz de la aplicación shell de MS-DOS.............................................................................. 270
Figura 7.14 Interfaz gráfica GNOME en Linux[7.87] ................................................................................ 271
Figura 7.15 Patrón MVC como base de una GUI ...................................................................................... 272
Figura 7.16 Elementos de la interfaz de usuario de Swing en Java ............................................................ 272
Figura 7.17 Arquitectura de la GUI del WCEfA ........................................................................................ 273
Figura 7.18 Arquitectura del Mac OS X y su interfaz de usuario Aqua ..................................................... 275
Figura 7.19 Consideraciones para el desarrollo de software....................................................................... 278
Figura 7.20 Diseño de sistemas operativos ................................................................................................. 279
Figura 8.1 Arquitectura de Windows NT representada en un esquema de módulos................................... 286
Figura 8.2 Especificación formal de alto nivel de la arquitectura de Windows NT usando UML (paquetes y
relaciones)........................................................................................................................................... 287
Figura 8.3 Arquitectura de kernel monolítico ............................................................................................. 289
Figura 8.4 Arquitectura conceptual de Linux ............................................................................................. 290
Figura 8.5 Esquema de la organización en capas de un sistema operativo ................................................. 291
Figura 8.6 Organización del sistema operativo en anillos........................................................................... 291
Figura 8.7 La característica central de la arquitectura de Mac OS X es la división en capas del software del
sistema ................................................................................................................................................ 292
Figura 8.8 Esquema de una arquitectura de máquina virtual ...................................................................... 293
Figura 8.9 Niveles de máquinas virtuales ................................................................................................... 294
Figura 8.10 Convivencia entre el sistema operativo nativo y ..................................................................... 295
el creado por la máquina virtual.................................................................................................................. 295
Figura 8.11 Esquema de la arquitectura de un microkernel. Pueden identificarse los modos de operación
(modo kernel y modo usuario), así como los procesos del sistema y los procesos de usuario............ 296
Figura 8.12 Esquema de la arquitectura del Palm OS. El núcleo de este sistema es el microkernel AMX
(Kadak) que implementa multiprocesamiento .................................................................................... 297
Figura 8.13 La arquitectura de paso de mensajes del QNX RTOS forma un bus de software que permite
conectar o desconectar los módulos del SO que se necesiten, sin reiniciar el sistema........................ 298

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

Figura 8.14 En el corazón del JavaOS se encuentra la máquina virtual de Java (JVM). Los servicios del
sistema, manejadores, applets y aplicaciones se ejecutan en la VM y un microkernel provee los
servicios básicos de la plataforma....................................................................................................... 300
Figura 8.15 La red de módulos de software que forma una aplicación puede visualizarse en distintos niveles
............................................................................................................................................................ 301
Figura 8.16 Arquitectura del sistema operativo Go .................................................................................... 302
Figura 8.17 Arquitectura del sistema X Window, para el intercambio de mensajes de interfaz gráfica de
usuario................................................................................................................................................. 304
Figura 8.18 Esquema de operación de un sistema operativo de red............................................................ 305
Figura 8.18a Arquitectura de Windows NT en referencia al modelo OSI .................................................. 306
Figura 8.19 Esquema de operación de un sistema operativo distribuido .................................................... 307
Figura 8.20 Esquema del middleware y entornos distribuidos .................................................................. 308
Figura 8.21 Esquema de la arquitectura de Mach ....................................................................................... 310
Figura 8.22 Arquitectura del microkernel Darwin del Mac OS X que integra el kernel Mach 3.0 y servicios
del BSD UNIX.................................................................................................................................... 312
Figura 8.23 Estructura de un sistema exokernel. Las aplicaciones usan sus propias librerías de Sistema
Operativo (Library Operating System (LibOS)) que a su vez usan el exokernel para cargar y descargar
recursos de hardware........................................................................................................................... 314
Figura 8.24 Esquema de un servidor Web montado en un SO convencional ............................................. 315
Figura 8.25 El solicitar una página HTML desencadena una serie de procesos que el SO tiene que hacer
para darle el soporte a la aplicación, lo cual no necesariamente puede ser óptimo. En el segundo
diagrama pueden apreciarse las dependencias del sistema de administración de memoria de Linux. 315
Figura 8.26 El exokernel provee la protección del hardware y las librerías de aplicación, pero el control lo
tiene la aplicación, lo que elimina procesos que el servidor Web no necesita .................................... 316
Figura 8.27 Un sistema de exokernel simplificado con dos aplicaciones, cada una ligada con su propia
libOS y compartiendo páginas por medio de un registro .................................................................... 316
Figura 8.28 Arquitecturas de sistemas operativos y sus características ...................................................... 320
Figura 9.1 Simulador de administración de memoria con particiones fijas (Oscar Ceceña)....................... 328
Figura 9.2 Simulador de administración de procesos (Christian Islas) ....................................................... 328
Figura 9.3 Simulador de administración de procesos (Josué Huizar) ......................................................... 328

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

Introducción
Algunos ven las cosas como son y preguntan:¿Por qué?
Yo sueño en lo que nunca existió y pregunto:¿Por qué no?
Robert F. Kennedy

Las computadoras desde un principio han sido máquinas complejas (y un gran logro técnico
iniciado por Babbage en el siglo XIX y desarrollado en el siglo XX), compuestas de diversas partes
físicas (el hardware), las cuales realizan acciones cuando se les dan instrucciones (el llamado
software). Los conjuntos ordenados de instrucciones son llamados programas, y son los que le
dicen a la computadora como debe hacer diferentes cosas con objetivos específicos y
particulares.

Es un tipo especial de programas llamados sistemas operativos, los que permiten a la


computadora brindar una plataforma para realizar una gran variedad de tareas complejas.

La idea de realizar notas y hasta un libro de sistemas operativos nació en 1997 cuando daba un
curso relacionado al tema en la Fundación Arturo Rosenblueth (el titulo de ese proyecto era
"Sistemas operativos: Teoría y práctica"), sin embargo por motivos de trabajo la idea quedó en el
baúl. Fue hasta 1999 (tal vez un poco antes) con el advenimiento de un movimiento importante
en el país respaldando a Linux (por parte de entusiastas estudiantes de diversas universidades)
que decidí retomar el tema de los sistemas operativos.

Una motivación adicional apareció durante el tiempo que pasé colaborando en el Instituto de
Química de la UNAM; hubo una pregunta que me intrigó cuando charlábamos sobre las analogías
de los mecanismos celulares con las computadoras: "Si el núcleo celular era el hardware, ¿cuál
era el software (y el sistema operativo) de la célula?" Aunque se comentó que el ADN podía
considerarse como el software de control, me pareció que debía estudiar a fondo la teoría de los
sistemas operativos para un análisis futuro del tema.

Después de investigar caí en cuenta de algunos hechos importantes:

• El desarrollo de este tipo de sistemas está en manos de una élite de desarrolladores (ya sean
los apoyados por universidades o compañías, o los que lo hacen como pasatiempo; esfuerzos
sin duda, loables). Aunque hacer sistemas operativos no es una de las ofertas de trabajo que
salgan a menudo en los periódicos, el conocimiento de este tema es obligado para cualquier
profesional del área de cómputo.
• La bibliografía relacionada es escasa e importada (aunque hay traducciones) y en general
más teórica que práctica. Esto último no ha tenido un balance (hay obras con mucha teoría y
otras con la mitad de la publicación con listados de código fuente) y ante todo, no ha
reportado la experiencia de las personas o equipos de trabajo, exponiendo cómo es que
llegaron a sus soluciones (es decir, a sistemas que actualmente se usan en ambientes de
producción).
• Un experto en sistemas operativos debe tener una perspectiva amplia sobre los diferentes
sistemas operativos existentes. Alguien que trata o logra recompilar el kernel de Linux, o que

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

obtiene una certificación en el uso o administración de algún otro sistema, no


necesariamente sabe cómo está funcionando dicho sistema, cómo está construido o cómo
puede modificarse para mejorar su rendimiento.
• Deben tomarse en cuenta los avances en otras áreas de las ciencias de la computación, para
aplicarlos a los problemas clásicos de los sistemas operativos, o para proveerlos de nuevas
funcionalidades o incluso para proponer nuevos enfoques en su desarrollo (p.ej. técnicas de
IA, agentes, etc.).
• Al no tener una referencia práctica sobre el desarrollo de este tipo de sistemas, se limita el
avance e innovación potencial que pudiera lograrse, por falta de conocimiento. No solo hay
pocos libros, sino que hay poco interés.
• Es necesario crear y difundir una cultura sobre los sistemas operativos para reducir la
dependencia tecnológica del extranjero (cosa difícil a estas alturas, pero no imposible), y
mejorar los criterios de consumo de los usuarios finales (¿por qué debo cambiar de sistema si
el que uso funciona? ¿qué mejoras tiene la nueva versión? ¿qué otras opciones existen?).

Por todo lo anterior, decidí llevar a cabo una investigación que lograra, ante todo, aclarar
muchas dudas que creo compartir con muchas personas (sin ir mas lejos, preguntas sobre qué
son o cómo funcionan los sistemas operativos) con respuestas convincentes que vayan a la
médula de la principal interrogante de todo estudiante de ciencias de la computación: ¿cómo se
diseña y construye un sistema operativo?

Para ello, me he apoyado en toda la bibliografía a mi alcance y sobre todo en la información


disponible en Internet (la cual de unos años para acá se ha incrementado, afortunadamente), así
como en mi experiencia como desarrollador de software (que es donde hay que lidiar con los
sistemas operativos, y donde surgen los retos).

El objetivo es organizar y analizar la información existente sobre los sistemas operativos, en


aspectos tales como:

• la conceptualización general de este tipo de sistemas,


• la integración de algoritmos y subsistemas que forman parte de ellos,
• la concepción y la implementación en código de todos sus elementos conceptuales, pues
como desarrollador de sistemas sé apreciar la importancia de hacer las cosas para
entenderlas,
• el aprendizaje de técnicas de un área de conocimiento, sirve para aplicarlas en la solución de
problemas en otros contextos.

No he querido tomar un solo sistema como caso de estudio, pues esto sería limitado, dada la
variedad que existe (además tratar de adivinar por qué se codificó de cierta manera un
programa, o conjeturar sobre las decisiones de diseño del sistema puede ser poco objetivo). Por
el contrario, he tratado de integrar las diversas visiones en torno a los sistemas operativos para
ejemplificar (en lo posible), las ideas y técnicas más representativas aplicadas a estos sistemas (a
nivel de sus componentes y su estructura general).

Con base en lo anterior, la propuesta de este trabajo es identificar los principales


elementos de los sistemas operativos y analizar las técnicas de diseño e
implementación de estos sistemas, para establecer lineamientos precisos para su
concepción, su diseño y su construcción. 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) Costos. A causa de que proveer con equipo suficiente a varios usuarios resulta muy
caro.
ii) Reutilización. Utilización de de programas o rutinas ya existentes para desarrollar
nuevas aplicaciones.
iii) Compartir datos de una misma base de datos para diferentes programas.
iv) 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

b) Tiempo de respuesta (en sistemas multiusuario)


c) Utilización de recursos.
d) Libre de errores.
2. 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.
3. 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.
4. Interoperabilidad. Es la habilidad del sistema de facilitar intercambio de información
entre los componentes heterogéneos en el sistema.
5. 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.
6. Autonomía. Es la independencia de los sistemas operativos con respecto al hardware, lo
que permite que el sistema trabaje con unidades autónomas.

En la siguiente sección se revisan los principales conceptos relacionados a los sistemas


operativos, los cuales serán explorados con más detalle en capítulos subsecuentes.

1.2 Principales conceptos de los Sistemas Operativos⊕

Básicamente el sistema operativo “enseña a la computadora como comportarse”, es decir, como


controlar y coordinar su procesador, la memoria, los dispositivos periféricos y como comunicarse
con los usuarios.

Figura 1.3 Soporte de software necesario para aprovechar los recursos del hardware.


Obras consultadas: [1.11] [1.12]

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

La idea de crear un sistema tan grande y complejo como un SO, solo puede manejarse
partiéndolo en pequeños módulos, los cuales poseen una función bien definida en el sistema, con
sus correspondientes entradas y salidas.

Hardware Ejemplos de servicios de SO Abstracción del usuario


Administración de Procesos,
Procesador Planificación (scheduling), Excepciones, Proceso
Protección, Sincronización
Administración, Protección,
Memoria Espacio de direcciones
Memoria Virtual
Concurrencia con el CPU, Terminal, Mouse, Impresora,
Dispositivos de E/S
Manejo de Interrupciones (Llamadas al sistema)
Sistema de archivos Administración, Persistencia Archivos
Llamadas al sistema, llamado
Seguridad en red remoto de procedimientos (RPC),
Sistemas distribuidos
Sistema de archivos distribuido Acceso transparente de archivos
(Transparent file sharing)
Tabla 1. Recursos de la arquitectura, administración del sistema operativo y
abstracciones del usuario.

En las siguientes secciones se define el objetivo y actividades de cada uno de esos módulos (el
criterio de selección de los módulos expuestos es que en su mayoría aparecen de forma
constante en casi cualquier sistema operativo).

1.2.1 Administración de procesos


Uno de los conceptos fundamentales en casi todo SO es el de proceso. Como se mencionó
anteriormente, un proceso es un programa en ejecución, y el SO debe encargarse de proveer los
medios para controlar dicha ejecución. De ahí nace el concepto de administración de procesos.

El microprocesador no hace las cosas por si solo; el sistema operativo es el que


determina que proceso se debe ejecutar y cuanto tiempo debe estar ejecutándose. A
todo esto se le denomina administración de procesos.

El SO es responsable de las siguientes actividades relacionadas con la administración de


procesos:

• Creación y borrado de procesos del sistema y el usuario.


• La suspensión y rehabilitación de procesos.
• Proveer mecanismos para la sincronización de procesos.
• Proveer mecanismos para la comunicación entre procesos (IPC).
• Proveer mecanismos para el manejo de bloqueos (deadlocks).

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

1.2.2 Administración de memoria


Para que los programas se ejecuten, deben ser almacenados en la memoria de la máquina, por
lo que el SO debe ser capaz de interactuar con la memoria primaria de la computadora, así como
con las abstracciones que el sistema realice con ella (p.ej. estructuras de datos) para gestionar
los datos que van entrando y saliendo de la memoria de la computadora (fig. 1.4).

Figura 1.4 Esquema de los diferentes tipos de memoria en un sistema de cómputo.

El SO es responsable de las siguientes actividades relacionadas con la administración de


memoria:

• Mantener un seguimiento de que partes de la memoria están uso y por quién.


• Decidir que procesos serán cargados en memoria cuando exista espacio disponible.
• Asignar y quitar espacio en memoria como sea requerido.

Una de las abstracciones más importantes relacionadas con la administración de la memoria, es


el concepto de memoria virtual.

La administración de la memoria virtual se encarga de mantener el mapeo de la memoria virtual


y física, decidir en el tamaño de la memoria asignada a los procesos y reforzar la política de
reemplazo.

1.2.3 La gestión de la integridad

Hay que tener en cuenta que cualquier programa puede, aunque no sea deseable, hacer
mención a recursos, direcciones y otros accesos indebidos; si dichos accesos no son controlados,
se produciría un error que daría como origen algo que no nos podríamos imaginar (reinicio de la
máquina, bloqueo, etc.).

Para evitar todos estos problemas, los sistemas operativos tienen distintos niveles de
seguridad:

a. En la memoria: Hemos dicho que los programas se cargan en la memoria, pero imaginemos
que un programa hace una escritura en una zona de memoria que es de otro programa, para
evitar esto el sistema operativo realiza una gestión de la memoria entre los usuarios.

b. En el uso del CPU: Los programas se dividen en procesos que se ejecutan en el


microprocesador (CPU), pero si varios procesos intentaran ejecutarse a la vez se produciría un

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

efecto imprevisible. Para ello el sistema operativo controla la ejecución de los procesos, la
duración de cada uno de ellos y cuando deben entrar o salir de la ejecución.

c. En el uso de las entradas y salidas (E/S): En realidad no es que el sistema operativo


controle la E/S aunque si lo haga cuando es necesario, lo que ocurre es que si hay un proceso
ejecutándose en la cpu y va a imprimir en la impresora algo, el sistema operativo, bloquea el uso
de la impresora hasta que el proceso no termine con ella para que no haya otro proceso
enviando información a la impresora por que si fuera así entonces provocaría un conflicto en la
impresora, y al mismo tiempo saca del procesador el proceso que esta imprimiendo, por que sino
los demás procesos tendrían que esperar a que el proceso terminara de imprimir para seguir con
el CPU y entonces el CPU estaría bloqueado perdiendo tiempo inútilmente, por que el proceso
consume el tiempo del procesador, cuando en realidad no hace nada con él pues está
imprimiendo.

1.2.4 Administración de dispositivos

Puesto que las configuraciones de hardware de las computadoras varían según las necesidades
y desarrollo tecnológico, un área de constante desarrollo es la construcción de nuevos
dispositivos periféricos que permitan a las computadoras expandir sus capacidades básicas. Para
ello, es necesario que un SO cuente con subsistemas que permitan acceder a tales dispositivos.
Dichos subsistemas son los siguientes:

1. Administración del sistema de E/S (I/O). Puesto que uno de los propósitos del SO es
hacer transparente las peculiaridades del hardware al usuario, se tiene un sistema de E/S que
consiste de:
• Una interfaz general dispositivo-controlador (device-driver).
• Manejadores para dispositivos específicos de hardware.

2. Manejadores de dispositivos (device drivers): Los manejadores son piezas de código


especiales que se encargan de la comunicación de todos los periféricos de la computadora (como
terminales, impresoras, discos, etc.) Debe existir un manejador especial para cada diferente tipo
de dispositivo conectado, y puesto que hay tantas posibilidades y cada día aparecen nuevos
periféricos, no se pueden construir directamente en el kernel. Es necesario hacerlos una parte
diferente que pueda ser sustituida o removida de la computadora.

1.2.5 Almacenamiento secundario


Tal vez los dispositivos periféricos más usados, sean los de almacenamiento secundario
(cintas, discos, etc.). Como la información se ha vuelto un bien vital para los usuarios, se
requiere que los sistemas operativos provean servicios que hagan seguro, fácil y transparente
el manejo y almacenamiento de información. Los servicios implementados por el SO son los
siguientes:

a. Administración de almacenamiento secundario. El SO es responsable de las siguientes


actividades relacionadas con la administración de discos:
• Manejo del espacio libre.

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

• Distribución de almacenamiento.
• Organización del disco.

b. Administración de archivos. El SO es responsable de las siguientes actividades


relacionadas con la administración y organización de archivos:
• La creación y borrado, de archivos y directorios.
• Bloqueo y protección de archivos y directorios.
• Soporte de operaciones primitivas para la manipulación de archivos y directorios.
• El mapeo de archivos en almacenamiento secundario.
• El respaldo de archivos en un medio estable de almacenamiento.

La principal abstracción que provee el SO para el manejo del almacenamiento secundario es


el sistema de archivos, el cual permite ordenar los datos en una forma estructurada, fácil de
recordar y manejar (p.ej. archivos de tamaño variable, directorios, etc.).

El sistema de archivos trabaja sobre los manejadores de dispositivos para proveer una
interfaz abstracta con los diferentes manejadores. Define la forma de almacenar información en
dispositivos de almacenamiento, por lo que no es necesario aprender un nuevo método de
almacenamiento para cada dispositivo posible.

1.2.6 Transmisión de datos e información


Además de almacenar información, otra necesidad imperiosa es la de transmitirla. Cuando las
computadoras cuentan con los dispositivos necesarios, pueden ser conectadas entre si,
formando redes. Nuevamente el SO debe ofrecer la capacidad de conectarse a estas redes, y
transmitir y recibir información de forma segura. Para ello se necesitan:

a. Servicios de Comunicación en Red (networking). Se refiere a la conexión de múltiples


procesadores por medio de una red, que puede ser configurada de diferentes maneras, y debe
tomar en cuenta estrategias de conexión y ruteo, así como casos de contención y seguridad,
además de dar soporte a varios protocolos y medios de comunicación.

b. Protección del sistema. Se refiere a mecanismos para controlar el acceso de programas,


procesos o usuarios a los recursos definidos por un sistema de cómputo.

c. Programas Auxiliares. Estos programas se encargan de ayudar al SO a llevar a cabo sus


tareas. Estos programas pueden encargarse de controlar comunicaciones, seguridad, etc.
Algunos son visibles como el programa de autentificación de usuarios (login), pero muchos
otros trabajan escondidos en el trasfondo (en algunos sistemas son llamados demonios).

1.2.7 Núcleo del sistema (Kernel)


Una abstracción fundamental hecha con base en los conceptos anteriores, es la de organizar
todos estos módulos de forma que pueda contarse con un mayor o menor número de servicios
por parte del SO. Tal abstracción es llamada núcleo o kernel del sistema operativo.

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

El kernel (o núcleo) es la parte del sistema que en realidad se encarga de los aspectos más
básicos de la funcionalidad, principalmente con la forma en que la computadora se comportará.
Comúnmente, el kernel establecerá las políticas de trabajo (tarea simple o multi-tarea; métodos
de planificación), como manejar a los componentes básicos (p.ej. políticas de manejo de
memoria como el uso de la memoria virtual), las medidas de seguridad básica y como iniciar,
comunicarse y apagar todos los demás componentes.

Toda esta gestión la realiza para atender al funcionamiento y peticiones de los trabajos que se
ejecutan en el sistema.

El núcleo normalmente representa sólo una pequeña parte de lo que por lo general se piensa
que es todo el sistema operativo, pero es el código que más se utiliza. Por esta razón el núcleo
reside por lo regular en la memoria principal, mientras que otras partes del sistema
operativo son cargadas en la memoria principal sólo cuando se necesitan.

1.2.8 Comunicación con el usuario⊕


Una vez establecidos los conceptos relativos al control de los recursos de hardware y software,
podemos hablar de la forma en que una computadora con sistema operativo se comunica con el
usuario.

a. Interfaz de usuario. La Interfaz de usuario es la parte del sistema que provee una forma en
que la computadora capte y reaccione a las acciones del usuario, y transmita la información que
el usuario produce. Es el componente que se encarga de traducir los datos binarios en números y
caracteres en la pantalla, o interpretar los códigos binarios del teclado, y si se trata de una
interfaz grafica de usuario (GUI), se encarga de dibujar las ventanas y otros objetos en la
pantalla. Nótese que una computadora puede tener varias interfaces de usuario para adaptarse a
diferentes modelos de terminales o preferencias del usuario.

b. Shells - Sistema interprete de comandos (Command Language Interpreter, CLI). El SO


esta diseñado para trabajar en conjunto con otros programas, y no se pretende que sea accedido
directamente por el usuario. Así que por lo menos se requiere un programa que sirva de interfaz
entre el usuario y el sistema para permitir el uso de la computadora. La mayor parte de los
sistemas operativos cuentan con uno o mas de estos programas (los cuales solo reciben
comandos y los traducen en instrucciones del SO). Varias ordenes le son dadas al SO por medio
de sentencias de control. Cuando un nuevo trabajo comienza en un sistema batch, o cuando un
usuario accede en un sistema de tiempo compartido, un programa que lee e interpreta dichas
ordenes es ejecutado inmediatamente. Se le llama también intérprete de tarjetas de control,
intérprete de comandos en línea, el shell (en UNIX), etc. Su función es bastante simple: obtener
el siguiente comando y ejecutarlo.


Obras consultadas: [1.29]

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

Figura 1.5 Niveles de interacción de un shell

Los SOs se distinguen frecuentemente en el área de interpretación de comandos, por


interpretes más amigables que hacen más agradable el sistema a los usuarios. Un ejemplo es el
intérprete de Mac, que es un sistema basado en ventanas que es exclusivamente activado en
ciertas regiones (iconos) por el ratón.

c. Interfaz gráfica de usuario (GUIs -Graphical User Interfaces). Las GUIs despliegan objetos
gráficos en la pantalla (imágenes, iconos, botones, etc.) y el usuario interactúa con ellos usando
un dispositivo apuntador (por lo general un ratón (mouse)). Las interfaces gráficas modernas
usan una "metáfora de escritorio" en las que áreas conocidas como ventanas, contienen
actividades de trabajo, como hojas de papel sobre un escritorio real.

Las GUIs hacen uso extensivo de los gráficos por computadora para organizar el área de trabajo
del usuario, y presentan formas intuitivas para realizar diversas tareas. En 1968 Doug Engelbart
del Stanford Research Center's Augmentation Research Center, patrocinado por la Agencia de
Proyectos de Investigación Avanzados del Departamento de Defensa (ARPA), instrumentó el
primer sistema de ventanas (windowing system). En 1970, investigadores del Centro de
Investigación de Palo Alto (XEROX PARC) diseñaron la primera computadora con interfaz gráfica
(Alto Computer).

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

(a) (b)
Figura 1.6 Ejemplos de interfaz gráfica de usuario: (a) el sistema NeXT; (b) Mac OS X.

Por lo anterior, se puede decir que aunque el SO es una parte muy importante del sistema de
computo, este queda fuera de la vista de los usuarios, los cuales lo notan de forma indirecta por
medio de las capacidades que el SO provee y las cosas que permite y no permite hacer, cuando
lo acceden por medio de otros programas como los shells o las GUIs, que son los que
comprenden e interpretan las acciones que el usuario quiere realizar.

Para entender cómo es que aparecieron este tipo de sistemas, revisaremos la historia de la
computación con la intención de entender las motivaciones que condujeron al desarrollo de los
sistemas operativos.

1.3 Desarrollo histórico de los Sistemas Operativos⊕

Para tener una perspectiva completa de los sistemas operativos, es importante revisar su
historia, la cual es paralela al desarrollo del hardware de las computadoras, pues los nuevos
avances requerían de nuevas soluciones. Basado en algunas referencias relativas a la historia y
evolución de las computadoras, se ha desarrollado la siguiente cronología (fig. 1.7) la cual integra
a las generaciones de computadoras digitales y a los sistemas operativos. En ella se han tratado
de incluir los principales paradigmas de ambas áreas.

Por convención, la primera generación inicia con las primeras computadoras electrónicas, en
lugar de las máquinas mecánicas y electromecánicas que les antecedieron. Cabe mencionar que
de todas las referencias consultadas, no hay un consenso en cuanto a los periodos de tiempo que
cada generación cubre, o incluso a los criterios que se usan para definirlas. Un criterio
interesante se basa en los cambios en la tecnología de implementación dominante, que permiten
crear nuevas computadoras. Sin embargo, es posible obtener nuevas configuraciones con la
tecnología disponible, creando arreglos complejos de procesadores (que además implica
desarrollar tecnologías de conectividad y sincronización).


Obras consultadas: [1.1] [1.2] [1.3] [1.4] [1.5] [1.6] [1.7] [1.8] [1.9] [1.10]

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

Figura 1.7 Cronología del desarrollo de las computadoras y los sistemas operativos.

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

En las siguientes secciones se explora el desarrollo histórico de los sistemas operativos, con el
fin de tener una idea de como han ido evolucionando, y para apreciar un poco más "los lujos"
que hoy disfrutamos en nuestras computadoras. Aunque los primeros sistemas ahora pueden ser
(o parecer) obsoletos, no deja de ser interesante su análisis para comprender las tendencias
actuales en su desarrollo.

1.3.1 En el principio...
Las primeras computadoras de fines de los 1940s no tenían sistema operativo. En un
principio solo existía el hardware de la computadora. Las primeras computadoras eran
(físicamente) grandes máquinas que se operaban desde una consola. El programador escribía un
programa y luego lo controlaba directamente.

En primer lugar, el programa se cargaba manualmente en la memoria, desde los interruptores


del tablero frontal, desde una cinta de papel o desde tarjetas perforadas. Luego se pulsaban los
botones adecuados para establecer la dirección de inicio y comenzar la ejecución del programa.
Mientras este se ejecutaba, el programador-operador lo podía supervisar observando las luces en
la consola. Si se descubrían errores, el programador podía detener el programa, examinar el
contenido de la memoria y los registros y depurar el programa directamente desde la consola. La
salida del programa se imprimía, o se perforaba en cintas de papel o tarjetas para su impresión
posterior. Un aspecto importante de ese entorno era su naturaleza interactiva directa. El
programador también era el operador del sistema de cómputo (figura 1.8). Al mismo tiempo, el
problema matemático a resolver, se mezclaba con los problemas físicos de la computadora.

El trabajo de los operadores humanos, quienes planificaban los trabajos listos para ejecutar y
supervisaban el uso de los recursos de la computadora, fue una de las primeras ocupaciones en
ser automatizada.

Figura 1.8 Esquema de operación de las primeras computadoras.

Estas computadoras eran tan caras, que el principal objetivo de un sistema operativo era hacer
al hardware tan eficiente como fuera posible. Además, los programadores producían su propio

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

código objeto para los programas, incluyendo todas las instrucciones para entrada de datos de
las tarjetas o cinta de papel y salida de resultados a impresoras o cinta magnética.

Un programa (o trabajo) era cargado y ejecutado a la vez hasta su término o detenido a causa
de un error; el sistema estaba ocioso hasta que el siguiente programa fuera cargado y ejecutado.

Durante los 1950s, los cargadores, rutinas estándar de entrada/salida (E/S), ligadores,
ensambladores y compiladores fueron introducidos, junto con el concepto de archivo, así que el
código de programa o conjuntos de datos podían ser referidos por medio de nombres de
archivos.

Lotes de archivos de programas eran cargados de una sola vez (a través de lectoras de
tarjetas), y compartían el CPU y la memoria primaria: cuando un programa esperaba por el
término de la lenta E/S, era suspendido de forma que otro programa pudiera usar el CPU (multi-
programació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 ; identificar un nuevo usuario


$LOAD application ; cargar aplicación
$RUN ; ejecutar la aplicación
data
$EOJ ; fin del trabajo

Por lo general se usaban cintas magnéticas o tambores para almacenar los datos intermedios y
programas compilados. Las ventajas y desventajas de este tipo de sistemas son:
1. Ventajas
 mueve mucho del trabajo del operador a la computadora
 incrementa el desempeño, puesto que es posible para un trabajo comenzar tan pronto
como el anterior termina
2. Desventajas
 depuración complicada de programas
 debido al esquema de protección, un trabajo del lote puede afectar a los demás trabajos
pendientes (p.ej. a causa de la lectura de demasiadas tarjetas, etc.)
 un trabajo puede corromper al monitor, afectando también a los trabajos pendientes
 un trabajo puede entrar en un ciclo infinito

Como se mencionó, una de las mayores carencias de los sistemas por lotes era que no existía
un esquema de protección para prevenir que algún trabajo afecte adversamente a otros. La
solución a esto era un simple esquema de protección, donde cierta memoria (p.ej. donde reside

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

el monitor) era restringida a los programas de usuario. Esto prevenía que los programas de
usuario corrompieran al monitor.

Para evitar que los programas de usuario leyeran demasiadas (o pocas) tarjetas, el hardware
era cambiado para permitir a la computadora operar en uno de dos modos: uno para el monitor y
uno para los programas de usuario. La entrada/salida (E/S) podría solo ser realizada en modo de
monitor, así que las peticiones de E/S de los programas de usuario eran pasadas al monitor. De
esta manera, el monitor podría evitar que un trabajo no leyera su tarjeta de fin de trabajo
($EOJ).

Para prevenir un ciclo infinito, un temporizador (timer) fue agregado al sistema y la tarjeta
$JOB fue modificada para que el tiempo máximo de ejecución de un trabajo fuera enviado al
monitor. La computadora podría interrumpir el trabajo y regresar el control al monitor si se
excedía este tiempo.

Cuando estos sistemas son bien planeados, pueden tener un tiempo de ejecución muy alto,
porque el procesador es mejor utilizado y los Sistemas Operativos pueden ser simples, debido a
la naturaleza secuencial de la ejecución de los trabajos.

Algunos ejemplos de Sistemas Operativos por lotes exitosos son el SCOPE, del DC6600, el cual
está orientado a procesamiento científico pesado, y el EXEC II para el UNIVAC 1107, orientado a
procesamiento académico.

1.3.3 Sistemas de operación simultanea de periféricos en línea


Una dificultad con los sencillos sistemas de lotes es que la computadora aún necesitaba leer el
bloque de tarjetas antes de comenzar a ejecutar un trabajo. Esto significa que el CPU estaría
ocioso durante estas operaciones relativamente lentas.

Figura 1.10 Esquemas básicos de procesamiento. Nótese como el tiempo desperdiciado


ha ido disminuyendo

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

Puesto que es más rápida la lectura de una cinta magnética que un bloque de tarjetas, se volvió
común para los centros de cómputo tener una o más computadoras menos potentes en
complemento a su computadora principal. Las computadoras pequeñas eran usadas para leer y
cargar las tarjetas a las cintas, por lo que la cinta podía contener varios trabajos en lote. Esta
cinta era entonces cargada en la computadora principal y los trabajos de la cinta eran
ejecutados. La salida de los trabajos podía ser escrita a otra cinta que era retirada y cargada en
una computadora de menor capacidad para producir cualquier salida deseada (p.ej. impresiones).

Una extensión lógica del temporizador en el sistema por lotes, fue tener un temporizador que
pudiera permitir a los trabajos ejecutarse solo por un corto periodo de tiempo antes de
interrumpirlos para que el monitor pudiera iniciar alguna operación de E/S.

Puesto que la operación de E/S podría proceder mientras el CPU se ocupaba en un programa de
usuario (realizar E/S y cálculos en paralelo), fue posible que la computadora leyera tarjetas a las
cintas, tambores o discos y escribir la salida a una cinta mientras seguía procesando programas.

Este proceso es llamado SPOOLing (Simultaneous Peripheral Operation OnLine). Los sistemas
por lotes Spooling (Spooling Batch Systems) fueron los primeros (y más simples) sistemas de
multiprogramación.

Una ventaja de los sistemas de spooling era que la salida estaba disponible tan pronto como el
trabajo se completara, en vez de tenerla cuando todos los trabajos del lote se completaran.

1.3.4 Sistemas de Multiprogramación


Cuando máquinas con mayor cantidad de memoria estuvieron disponibles, fue posible extender
la idea de multiprogramación como se hizo en los sistemas de spooling al crear sistemas capaces
de cargar varios trabajos en memoria de una sola vez y ciclarlos en el mismo orden, trabajando
en cada uno por un periodo específico de tiempo.

Figura 1.11 Esquema de sistema de multiprogramación (o multitarea), donde varias


tareas son ejecutadas simultáneamente.

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

En este punto, el monitor crece hasta el punto de parecer un sistema operativo moderno, el
cual es responsable de:

• iniciar trabajos de usuario


• operaciones de spooling
• E/S para trabajos de usuario
• switcheo entre trabajos de usuario
• asegurar la protección adecuada mientras realiza las tareas anteriores

Como un simple y común ejemplo, considérese una máquina que puede correr dos trabajos a la
vez. Incluso, supongamos que un trabajo es de E/S intensiva y que el otro usa el CPU
intensivamente. Una forma para el monitor de obtener tiempo de CPU entre estos trabajos podría
ser dividir el tiempo equitativamente entre ellos. Sin embargo, el monitor podría estar ocioso
gran parte del tiempo durante la ejecución del proceso de E/S.

Una buena solución en este caso es permitir al trabajo del CPU (background job) ejecutarse
hasta que el trabajo de E/S (foreground job) necesite tiempo de CPU, momento en el cual el
monitor le permite ejecutarse, y cuando requiera de nuevo realizar sus operaciones de E/S, se
devuelve el control al trabajo anterior.

Los Sistemas Operativos de multiprogramación (o de multitarea) se distinguen por sus


habilidades para poder soportar la ejecución de dos o más trabajos activos (que se están
ejecutado) al mismo tiempo. Esto trae como resultado que el CPU siempre tenga alguna tarea
que ejecutar, aprovechando al máximo su utilización.

Figura 1.12 Esquema de ejecución de dos procesos con y sin multiprogramación.

Su objetivo es tener a varias tareas en la memoria principal, de manera que cada uno está
usando el procesador, o un procesador distinto, es decir, involucra máquinas con más de una
CPU.

Sistemas Operativos como UNIX, Windows 95, Windows 98, Windows NT, MAC-OS, OS/2,
soportan la multitarea.

 Sistemas de tiempo compartido (Timesharing)


En los tiempos en los que no se disponía de un sistema operativo, el programador tenía
acceso completo a la máquina. Al desarrollarse hardware y software para crear monitores,
sistemas de lotes y multiprogramación, la separación entre el usuario y la computadora de
volvió más pronunciada.

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

Uno de los problemas más comunes era que los usuarios y los programadores en particular,
tardaban en tener acceso a la máquina (sobre todo en los esquemas de lotes). Tal cuestión
trato de solucionarse por medio de un esquema llamado de tiempo compartido
(timesharing/timeslicing).

La idea de multiprogramación fue extendida para permitir que varias terminales fueran
conectadas a la computadora, y que a cada terminal en uso se le asociaran uno o más trabajos
en la computadora. El SO era entonces responsable de intercalar (switching) los trabajos
(también llamados procesos) de manera que se favoreciera la interacción con el usuario. Si el
cambio de contexto (context-switches) ocurría lo suficientemente rápido y con la suficiente
frecuencia, el usuario tenía la impresión de tener acceso directo a la computadora.

A los procesos interactivos se les da una mayor prioridad, así que cuando una E/S es
requerida (p.ej. una tecla presionada), el control del CPU le es dado al proceso asociado, así
que puede procesarlo. Esto es instrumentado mediante el uso de una interrupción que causa
que la computadora se de cuenta que un evento de E/S ha ocurrido.

Debe mencionarse que existen varios tipos de sistemas de tiempo compartido. Una clase es
representada por computadoras como las VAX/VMS y las estaciones de trabajo UNIX. En estas
computadoras, procesos enteros se encuentran en memoria, y la computadora intercala la
ejecución entre ellos. En otros tipos de sistemas, como los de reservación de vuelos, una sola
aplicación puede hacer la distribución de tiempo entre las terminales. De esta forma no se
necesita ejecutar un programa diferente asociado a cada terminal.

Los Sistemas Operativos de tiempo compartido permiten simular que el sistema y sus
recursos son todos para cada usuario. El usuario hace una petición a la computadora, esta la
procesa tan pronto como le es posible, y la respuesta aparecerá en la terminal del usuario en
un tiempo muy corto, dando la impresión al usuario de tener al sistema bajo su control
exclusivo.

Figura 1.13 Esquema de un sistema de tiempo compartido.

Los principales recursos del sistema, el procesador, la memoria, dispositivos de E/S, son
continuamente utilizados entre los diversos usuarios, dando a cada usuario la ilusión de que
tiene el sistema dedicado para sí mismo. Esto trae como consecuencia una gran carga de
trabajo al sistema operativo, principalmente en la administración de la memoria principal y
secundaria.

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

Ejemplos de sistemas operativos de tiempo compartido son Multics, OS/360 y DEC-10.

 Sistemas de Tiempo Real⊕


Para empezar, un sistema de tiempo real es aquel sistema informático en el que el
desempeño del sistema no sólo depende de los resultados lógicos de los algoritmos, sino que
también depende del momento en el que estos se producen.

Una computadora de tiempo real es aquella que ejecuta programas que están
garantizados en poseer un desempeño superior en las tareas que desarrollan. Por ejemplo los
sistemas de guía de misiles y equipo de monitoreo médico. Las computadoras dedicadas son
computadoras de propósito especial que son usadas para realizar solo una o más tareas.
Comúnmente estas son computadoras de tiempo real que incluyen aplicaciones de control
(misiles, inyección electrónica de gasolina, control automático de trenes, etc.).

Los sistemas operativos de este tipo de computadoras están severamente restringidos por
requerimientos de tiempo.

Figura 1.14 Esquema de un sistema de control, en donde deben ser aceptados y


procesados gran cantidad de sucesos.

Los Sistemas Operativos de tiempo real son aquellos en los cuales no tiene importancia
el usuario, sino los procesos. Por lo general, están subutilizados sus recursos con la finalidad de
prestar atención a los procesos en el momento que lo requieran. Se utilizan en entornos donde
son procesados un gran número de sucesos o eventos.

Muchos sistemas operativos de tiempo real son construidos para aplicaciones muy específicas
como control de tráfico aéreo, bolsas de valores, refinerías, etc. También en el ramo
automovilístico y de la electrónica de consumo, las aplicaciones de tiempo real están creciendo
muy rápidamente.

Otros campos de aplicación de los Sistemas Operativos de tiempo real son los siguientes:
- Control de trenes.
- Control automático de procesos químicos.
- Telecomunicaciones.

Obras consultadas: [1.18] [1.19]

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

- Sistemas de fabricación integrada.


- Producción y distribución de energía eléctrica.
- Control de edificios.
- Sistemas multimedia.

Algunos ejemplos de Sistemas Operativos de tiempo real son: VxWorks, Solaris, Lyns OS y
Spectra.

1.3.5 Sistemas Multiprocesador, distribuidos y en red⊕


Un sistema de cómputo multiprocesador es aquel con más de un CPU. Los dos grandes
problemas que se tienen en este tipo de sistemas tienen que ver con:

1. El control de los procesadores. Dos o más procesadores similares están conectados por
medio de conexiones de alta velocidad y son administrados por un sistema operativo, donde cada
procesador tiene el mismo acceso a los dispositivos de entrada/salida. Los procesadores son
tratados más o menos igual, permitiendo que los programas de aplicación se ejecuten en
cualquiera o tal vez, hasta en todos los procesadores del sistema, bajo la dirección del sistema
operativo.

El multiprocesamiento simple usualmente consiste en asignar a cada procesador una tarea fija
(como administrar el sistema de archivos), reservando el CPU principal para tareas generales (fig.
1.15).

Figura 1.15 Configuraciones de multiprocesamiento asimétrico(a) y simétrico(b).

2. La administración de la memoria. Esta categoría puede ser subdividida en:


a. Multiprocesadores de memoria compartida que tienen varios CPUs, todos con
acceso a la misma memoria. La comunicación entre los procesadores es fácil de
implementar, pero el punto crítico es la sincronización del acceso a memoria.
b. Multiprocesadores de memoria distribuida con varios CPUs, donde cada CPU
tiene su propia memoria asociada. Aquí, la sincronización del acceso a memoria no es un
problema, pero la comunicación entre los procesadores por lo general es lenta y
complicada.


Obras consultadas: [1.20] [1.30] [1.31]

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

En los Sistemas Operativos Paralelos se pretende que cuando existan dos o más procesos
que compitan por algún recurso, se puedan realizar o ejecutar al mismo tiempo.

En una máquina paralela, el sistema operativo paralelo se construye encima de los sistemas
operativos (o kernels) de cada procesador. Por ejemplo, en la IBM SP-2, el sistema operativo
paralelo consiste de procesadores individuales ejecutando AIX y un componente unificador
paralelo conocido como POE (Parallel Operating Environment).

En UNIX existe también la posibilidad de ejecutar programas sin tener que atenderlos en forma
interactiva, simulando paralelismo (es decir, atender de manera concurrente varios procesos de
un mismo usuario). Así, en lugar de esperar a que el proceso termine de ejecutarse (como lo
haría normalmente), regresa a atender al usuario inmediatamente después de haber creado el
proceso.

Ejemplos de Sistemas Operativos Paralelos son: Alpha, PVM, la serie AIX (que es utilizado en los
sistemas RS/6000 de IBM), Tornado, Hurricane y Helios.

También relacionado al multiprocesamiento se encuentran los siguientes tipos de sistemas:

a. Sistemas en red, que consisten de varias computadoras que están conectadas entre si,
usualmente con un sistema operativo común y recursos compartidos. Los usuarios sin embargo,
están informados de las computadoras que conforman el sistema.

Los sistemas operativos de red son aquellos sistemas que mantienen a dos o más
computadoras unidas a través de algún medio de comunicación (físico o no), con el objetivo
primordial de poder compartir los diferentes recursos y la información contenida en cada equipo.
Los Sistemas Operativos de red más usados son: Novell Netware, Personal Netware, LAN
Manager, Windows NT Server, UNIX y, LANtastic.

b. Sistemas distribuidos, también consisten de varias computadoras pero difieren del enfoque
de redes en que estas computadoras son transparentes al usuario. Por lo general hay recursos
redundantes y se comparte la carga de trabajo entre las diferentes computadoras, pero esto es
transparente al usuario (fig. 1.16).

Los sistemas operativos distribuidos permiten distribuir trabajos, tareas o procesos, entre un
conjunto de procesadores. Puede ser que este conjunto de procesadores esté en un equipo o en
diferentes, en este caso es transparente para el usuario.

Existen dos esquemas básicos:


1. Un sistema fuertemente acoplado es aquel que comparte la memoria y un reloj global, cuyos
tiempos de acceso son similares para todos los procesadores.
2. En un sistema débilmente acoplado los procesadores no comparten ni memoria, ni reloj, ya
que cada uno cuenta con su memoria local.

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

Figura 1.16 Esquema de un sistema operativo distribuido.

Los sistemas distribuidos deben de ser muy confiables, ya que si un componente del sistema se
descompone, otro componente debe de ser capaz de reemplazarlo. Entre los diferentes Sistemas
Operativos distribuidos que existen tenemos los siguientes: Sprite, Solaris-MC, Mach, Chorus,
Spring, Amoeba, Taos, etc.

No hay que confundir un Sistema Operativo de Red con un Sistema Operativo


Distribuido. En un Sistema Operativo de Red las computadoras están interconectadas por
medios de comunicación: software y hardware. En este tipo de sistema los usuarios saben donde
están ejecutando su trabajo y guardando su información. En cambio en los Sistemas
Operativos Distribuidos existe un software que distribuye las tareas de los usuarios sobre una
red de computadoras y para los usuarios es transparente donde realizan sus tareas y guardan su
información.

Existen dos esquemas básicos de éstos sistemas. Un sistema fuertemente acoplado es


aquel que comparte la memoria y un reloj global, cuyos tiempos de acceso son similares para
todos los procesadores. En un sistema débilmente acoplado los procesadores no comparten
ni memoria ni reloj, ya que cada uno cuenta con su memoria local.

1.3.6 Computadoras Personales⊕


En los inicios, los sistemas operativos estaban individualizados. Puesto que las computadoras
eran una rareza, la cuestión de la estandarización era ignorada, pues había pocas computadoras
para ello, y por lo tanto los SOs estaban atados a las capacidades y propósitos de cada sistema.

La segunda forma en la que los programadores y usuarios retomaron las computadoras fue el
advenimiento de las computadoras personales cerca de 1980. Finalmente las computadoras
fueron suficientemente pequeñas y baratas que un individuo podía tener una (fig. 1.17).

Las primeras microcomputadoras fueron la Altair, la Commodore PET, la Tandy, y la Apple II


(hay de hecho una Apple I, pero solo 200 fueron manufacturadas. Una de ellas cuelga en las
oficinas de Apple con la leyenda "Nuestra Fundadora").


Obras consultadas: [1.25] [1.26] [1.27] [1.28]

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

La primera computadora de Tandy fue la TRS-80. La TRS, cuando se presentó, fue un gran
éxito de venta gracias a su poderoso sistema operativo y el creciente numero de aplicaciones
desarrolladas para él. En lo que falló, fue en mantenerse al día en los campos de mejoras de
video y facilidad de uso de su SO.

Las series Apple II (hasta que oficialmente fueron descontinuadas), fue usada por todos los
sistemas escolares y muchos hogares estadounidenses. La Apple tenía varios sistemas
operativos, como el Integer BASIC, el DOS 3.3, y el sofisticado ProDOS.

(a) (b)

(c) (d)
Figura 1.17 Las primeras PCs: (a) MITS Altair (1974), (b) Radio Shack TRS-80 (1977),
(c) Apple I (1976), (d) Apple Lisa (1983).

Sin embargo la mayor contribución de Apple viene con la línea Macintosh. Steve Jobs estaba
buscando una forma para mejorar la Apple II. En diciembre de 1979, fue invitado a participar en
un paseo por el centro de desarrollo de Xerox (PARC), el cual estaba tecnológicamente avanzado
para su tiempo y tenia dispositivos de los que no se había escuchado. Durante este paseo, le
mostraron tres paradigmas revolucionarios: Ethernet, impresoras láser, y lo que más impresiono
a Jobs, la interfaz gráfica de usuario (GUI). De inmediato Jobs vio esto como el futuro de los
sistemas operativos (lo cual se plasmó en LISA).

Cuando Commodore introdujo la PET, era bastante popular, pero no tanto como cuando
introdujo su línea de 8-bits de color, con la VIC-20, la 64 y la 128. El contemporáneo sistema
operativo de Commodore estaba basado en su versión de BASIC. Todos los comandos a
periféricos, los cuales eran "inteligentes" (tenían su propia memoria, procesador y manejadores),
eran hechos por medio de BASIC; la computadora arrancaba en BASIC; y BASIC estaba
construido en ROM.

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

La Commodore 64 fue la caja maravilla para el mundo desde su llegada en 1982, con gráficos
extraordinarios de 16 colores y sonido 3-voice, basada en la eficiente serie MOS 6500 (como
nota, una variante del 6510 de 16 bits, el 65816, es el que soporta al Super Nintendo). Puesto
que el BASIC no tenia los comandos nativos para manipular muchas de las avanzadas
características de la 64, aparecieron una gran cantidad de accesorios: cargadores rápidos para
mejorar la velocidad de las unidades de disco 1541; extensiones de BASIC de todo tipo, y
mejoras de hardware, como extensiones de RAM, cajas de alta velocidad RS232 e interfaces a
impresoras no-Commodore.

Otra clave fue el sistema operativo GEOS, hecho por Berkeley Softworks (ahora GeoWorks).
Aunque era lento y beligerante, desarrolló un fiel grupo de seguidores por a su poderosa GUI de
80 columnas (a la Mac) en la 64, y la gran cantidad de software existente para el (desde juegos
hasta programas de negocio). La 64 podía incluso comportarse como una PC o estación Unix:
programas como CS-DOS y los potentes sistemas operativos A64/OS y Lunix, que convertían a la
64 en pequeñas versiones de sus competidores más grandes.

OS9 fue uno de los pocos SO, sino el único, multitarea, multihilado y, con un poco de suerte,
multiusuario en los sistemas de 8 bits. Corriendo en sistemas basados en versiones del 6809,
como CoCos, para sistemas 68000 como el Atari STs, e incluso para la Apple II.

La gran piedra angular de los sistemas operativos de 8 bits fue CP/M (el cual casi reemplaza al
MS-DOS como el SO para la PC, de no haber sido por una compañía de software de Redmond,
Washington que hizo un mejor trabajo de relaciones públicas). Desarrollado por Gary Kildall (de
Digital Research) a mediados de los 1970s, CP/M fue el primer SO estandarizado jamás creado
para microcomputadoras. CP/M tenía un conjunto estándar de comandos, (eventualmente) un
DOS estandarizado, e incluso utilerías del sistema.

MS-DOS no fue el primero, ni el mejor de los sistemas operativos para microcomputadoras


cuando fue licenciado por Microsoft para las PCs IBM (el sistema operativo de Tim Patterson,
QDOS como lo llamaba, no era enteramente suyo. Él trabajo para Seattle Computer Products, así
que ellos poseían los derechos de QDOS. Microsoft decidió comprar los derechos de QDOS por
US$50,000 y cambio su nombre a PCDOS 1.0 (cerca de agosto de 1981)).

Las primeras versiones presentadas eran similares al interprete de comandos de CP/M. MS-DOS
fue escrito en lenguaje ensamblador de 16-bits (Intel) por lo que era difícil de portar a otras
máquinas, a diferencia de CP/M, que en su mayor parte estaba escrito en un lenguaje de alto
nivel. El DOS era un SO monousuario y monotarea, donde el usuario puede ejecutar un programa
a la vez hasta su termino.

1.4 Comentarios

La principal contribución de todos estos desarrollos, fue enfrentar a un mercado creciente de


usuarios con necesidades de usabilidad. En retrospectiva, los científicos que usaban las grandes
computadoras estaban capacitados para operarlas, pero esto requería de un alto grado de
especialización y es aquí donde las interfaces gráficas y los periféricos encontraron su lugar.

En el siguiente capitulo se analizar el funcionamiento básico de un sistema operativo con el fin


de integrar los conceptos expuestos hasta el momento.

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

1.5 Obras consultadas

[1.1] IIC 2332 -- Sistemas Operativos


Apuntes 01 1er Semestre 1996 [1.12] Introduction to Operating Systems
http://www.cs.virginia.edu/~knabe/iic2332/ Kathryn S. McKinley. University of Massachusetts .Fall
1997
[1.2] CS322: A Brief History of Computer Operating http://www-aml.cs.umass.edu/~cs377/
Systems
Prof. R. Bjork, Gordon College [1.13] DESDE QUE PULSAMOS EL BOTON DE NUESTRO
http://www.cs.gordonc.edu/courses/cs322/lectures/hist PC HASTA...
ory.html José Manuel Tella Llop, extraído de
microsoft.public.es.windows98
[1.3] Operating Systems Lecture notes http://www.duiops.net/windows/articulos/
Lecture 1: Overview and History
Martin C. Rinard [1.14] How Operating Systems Work
http://williamstallings.com/Extras/OS-Notes/notes.html Marshal Brain's HowStuffWorks
http://www.howstuffworks.com/operating-system.htm
[1.4] A BRIEF HISTORY OF OPERATING SYSTEMS
THROUGH TIME by Cameron Kaiser [1.15] Sistemas operativos I: Interrupciones del
http://www.armory.com/~spectre/tech.html procesador
http://itver.edu.mx/so1/24.htm
[1.5] Brad A. Myers. "A Brief History of Human
Computer Interaction Technology." [1.16] CSC 277- Operating Systems (handouts)
ACM interactions. Vol. 5, no. 2, March, 1998. pp. 44-54. Michael Lynch
http://www.qvctc.commnet.edu/classes/csc277/handou
[1.6] The computer museum history center. Timeline of ts.html
computer history.
http://www.computerhistory.org [1.17] Introduction to Operating Systems
Kathryn S. McKinley. University of Massachusetts .Fall
[1.7] Curso de sistemas operativos 1997
Enrique Sánchez Lara http://www-aml.cs.umass.edu/~cs377/
http://lara.pue.udlap.mx/sist_oper/index.html
[1.18] Real Time Linux (RT-Linux)
Aitor Cuesta
[1.8] Un paseo por la historia
http://members.es.tripod.de/Arioch/
Lidón García , Luis Peralta & Samuel Fernández
http://spisa.act.uji.es/~peralta/os/
[1.19] Sistemas Operativos Curso 2000-2001
http://www.esi.uem.es/~gachet/s_oper.htm
[1.9] An Overview Of Computational Science
Copyright (C) 1991, 1992, 1993, 1994, 1995 by the
Computational Science Education Project [1.20] Symmetric multiprocessing
http://csep1.phy.ornl.gov/ov/ov.html The Free Online Dictionary of Computing
http://burks.brighton.ac.uk/burks/foldoc/67/111.htm
[1.10] BITSYS: Operating Systems Lecture Notes
http://ironbark.bendigo.latrobe.edu.au/subjects/bitsys/ [1.21] Notas del Curso MATE 4096- Estructura de un
oslect/lectlist.html Sistema Operativo
http://cuhwww.upr.clu.edu/~jse/cursos/4096/notas/n4
096c04.html
[1.11] Curso de sistemas operativos
Crysoft
[1.22] Tornado operating system
http://crysoft.com/cursos/endetalle.asp?pide=sisope
http://www.eecg.toronto.edu/parallel/tornado.html

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

[1.23] Operating System Basics/Architecture [1.27] Apple history.com


Kurt Hudson & Andy Ruth. Published: July 1999 http://www.apple-history.com/frames/?
http://www.windowsitlibrary.com/Content/175/09/toc.h
tml [1.28] Old computers.com
http://www.old-computers.com/
[1.24] X Window System Architecture Overview
HOWTO
[1.29] The real history of the GUI
Daniel Manrique. 2001
http://www.webmasterbase.com/article/511/62
http://linuxselfhelp.com/HOWTO/XWindow-Overview-
HOWTO/
[1.30] Clusters en México
http://clusters.unam.mx/Historia/
[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.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.

/* //ASM //Lenguaje máquina


factorial - // Asumir a esta en la dir. 128 // Asumir a esta en la dir. 128
lenguaje C // Asumir F esta en la dir. 129 // Asumir F esta en la dir. 129
*/ 0 CONB 1 // a=1; Addr opcode/value
1 SAVEB 128 0 3 // CONB 1
a=1; 2 CONB 1 // f=1; 1 1
f=1; 3 SAVEB 129 2 4 // SAVEB 128
while (a <= 5) 4 LOADA 128 // if a > 5 the jump to 17 3 128
{ 5 CONB 5 4 3 // CONB 1
f = f * a; 6 COM 5 1
a = a + 1; 7 JG 17 6 4 // SAVEB 129
} 8 LOADA 129 // f=f*a; 7 129
9 LOADB 128 8 1 // LOADA 128
10 MUL 9 128
11 SAVEC 129 10 3 // CONB 5
12 LOADA 128 // a=a+1; 11 5
13 CONB 1 12 10 // COM
14 ADD 13 14 // JG 17
15 SAVEC 128 14 31
16 JUMP 4 // loop back to if 15 1 // LOADA 129
17 STOP 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 CD-
ROM.

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. El CD-ROM puede arrancar como la unidad A o C.


2. Si el CD-ROM arranca como A, la unidad debe contener imágenes de floppies de 1.2M,
1.4M o 2.88M.
3. 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.
4. Si el CD-ROM arranca como la unidad C, entonces reemplaza a la unidad C.
5. 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 CD-
ROM 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.
6. Dar formato a una parte del CD ROM como disco duro protegido contra escritura es un
método sencillo de protección contra copias.
7. Puede protegerse contra copia las porciones no formateadas del disco agregando
algunos manejadores especiales de CD-ROM en el CD.


Obras consultadas: [2.6]

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

 Carga por medio de conexión en red⊕


Existen otro tipo de arrancadores, para máquinas sin disco (las alguna vez llamadas
"terminales tontas"), que cargan los archivos necesarios por medio de una conexión en red.

El arranque por red (network booting) es una idea vieja. La idea central es que la
computadora tenga algún código de bootstrap en memoria no volátil (p.ej. un chip ROM), que
le permita el contacto con un servidor y obtenga los archivos del sistema por medio de una
conexión de red.

Uno de los objetivos es evitar el uso del disco duro para inicializar. Hay varias razones para
hacer esto. Una es reducir el costo de mantener software en diferentes máquinas. Con el
arranque por red los archivos son administrados en un servidor central y pueden ser
actualizados en un solo sitio. Otro objetivo es usar computadoras en sitios donde los discos
duros no son lo suficientemente robustos. Por ejemplo, esto podría ser una computadora en el
piso de una fábrica donde el disco duro puede ser frágil o estar expuesto a golpes. Finalmente,
otro objetivo es tener un sistema que pueda cambiar de sistemas operativos, sin tener que
instalar el software.

Para poder arrancar sobre una red, la computadora necesita obtener:


1. una identidad
2. la imagen de un sistema operativo
3. un sistema de archivos activo.

Consideremos una computadora sin disco (diskless computer -DC) que tiene una ROM de
arranque en red, y que puede ser una de varias computadoras idénticas. ¿Cómo podemos
distinguir esta computadora de las otras? Hay una pieza de información que es única para esta
computadora que es su dirección Ethernet (contenida en su adaptador de red). Cada adaptador
Ethernet en el mundo tiene una dirección Ethernet única de 48 bits por que cada a constructor
de hardware Ethernet le ha sido asignado un bloque de direcciones. Por convención estas
direcciones están escritas en dígitos hexadecimales donde cada dos dígitos se separan
mediante dos puntos (p.ej. 00:60:08:C7:A3:D8).

Los protocolos para obtener la dirección IP dada una dirección Ethernet, son llamados Boot
Protocol (BOOTP) y Dynamic Host Configuration Protocol (DHCP). DHCP es la evolución del
BOOTP (de hecho casi todo lo aplicable a BOOTP se aplica también en DHCP).

Después de obtener una dirección IP, la computadora debe descargar la imagen de un


sistema operativo y ejecutarlo. Para ello se usa otro protocolo de Internet llamado Trivial File
Transfer Protocol (TFTP). TFTP es como una versión recortada de FTP; no hay autentificación,
y se ejecuta sobre UDP (User Datagram Protocol) en lugar de TCP (Transmission Control
Protocol). UDP fue escogido en lugar de TCP por simplicidad. La implementación de UDP en la
computadora puede ser pequeña, por lo que el código cabe en una ROM.

Cuando todos los bloques se han recibido, la ROM de arranque en red le cede el control al
punto de inicio de la imagen del sistema operativo. Finalmente para ejecutar un SO, un
sistema de archivos raíz debe proveerse. El protocolo usado por Linux y otros sistemas Unix es


Obras consultadas: [2.7] [2.8]

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

normalmente el Network File System (NFS), aunque otras opciones son posibles. En este caso
el código no tiene que residir en la ROM pero puede ser parte del sistema operativo que se
descargó. Sin embargo el SO debe ser capaz de ejecutarse con un sistema de archivos raíz que
es un NFS, en lugar de un disco verdadero. Linux tiene las variables de configuración
requeridas para construir una versión que pueda hacerlo.

2.2.3 Inicio de la ejecución del sistema operativo


Para entender como funciona el SO, puede tomarse como punto de partida el análisis de su
ejecución, la cual inicia al encender la computadora.

Figura 2.8 Secuencia del inicio de ejecución del sistema operativo.

Cuando esto ocurre sucede lo siguiente:

a. Primero se ejecuta el programa de arranque (bootstrap) que inicializa todos los aspectos del
sistema, como los registros del CPU, controladores de dispositivos, la unidad de administración
de memoria, etc.
• El programa de arranque es el software alojado en memoria ROM (boot firmware)
que controla la computadora desde el momento que se enciende, hasta que el sistema
operativo primario toma control de la máquina. La función principal de este software
es inicializar el hardware y luego, cargar y ejecutar (boot) el sistema operativo.

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

b. Se localiza el sistema operativo (puede ser por medio de una rutina en ROM).

• En el caso de las PCs, estas primeras tareas se hacen con un programa que reside en
un chip de memoria llamado BIOS (Basic In-Out System) ROM y que al encender la
computadora, ocupa una posición FIJA de memoria en cualquier PC. Suponiendo que
el BIOS ya ha inicializado todos los dispositivos de la máquina (asignado las
correspondientes IRQs y recursos a los dispositivos), ahora va a proceder a cargar el
sistema operativo. Lo más normal es que intente su carga primero desde un disco. Si
esta carga falla, lo intenta desde el primer disco duro.

c. Una vez localizado, se carga en memoria por medio de un programa llamado Cargador
(Loader).
• Generalmente las partes críticas del SO se mantienen en RAM mientras la computadora
este encendida. Esto permite al CPU tener acceso inmediato al SO, lo que mejora el
rendimiento y funcionalidad de todo el sistema.

d. Durante el proceso de carga se instalan todas las RSI en el vector de interrupciones.

e. Entonces el SO se ejecuta y espera un evento o bien cede el control a algún programa de


usuario.

Un ejemplo de la ejecución inicial de un sistema operativo, es el proceso de carga del MS-DOS.


Suponiendo que la carga es desde un disco flexible, el sector de arranque (boot) del disco (el
cual es creado con una utilería de formateo), contiene un mini programa que lo único que sabe
hacer es buscar un archivo oculto en esa unidad de disco, llamado IO.SYS, cargarlo en memoria
y cederle control.

• EL IO.SYS inicia la carga y ejecución. Lo primero que busca es otro archivo oculto en la
misma unidad llamado MSDOS.SYS. Este archivo no es un archivo de ejecución, sino un
archivo de parámetros del sistema que en cualquier momento podemos ver (no es
aconsejable tocarlo), con un editor. Mas adelante veremos el posible contenido de este
archivo.
• A continuación el IO.SYS, busca en el directorio raíz de esa unidad un archivo llamado
CONFIG.SYS. Sí el archivo existe, lo lee y ejecuta las instrucciones que lleva dicho
archivo. Básicamente el config.sys, contiene los parámetros del propio sistema y sobre
todo, carga de manejadores de dispositivo. No es obligatorio que exista. Solo si lo
encuentra lo ejecuta.
• A continuación, el IO.SYS, busca el COMMAND.COM, es decir al intérprete de comandos.
• El COMMAND, busca a su vez la existencia de un archivo llamado AUTOEXEC.BAT
también en el directorio raíz de la unidad de arranque y lo lee para ejecutar los
comandos que allí existan. Dichos comandos, serian básicamente programas (no pueden
ser ya manejadores de dispositivos) y algún parámetro de configuración (como el PATH
por ejemplo) propio del interprete de comandos.

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

2.2.4 Protección del hardware⊕


Para asegurar el correcto funcionamiento del SO, debe impedirse que los programas de usuario
puedan realizar ciertas operaciones:
• Acceso a la memoria del SO y de otros programas
• Acceso directo al uso de dispositivos de E/S
• Uso libre del tiempo de CPU

Además, ciertas instrucciones de la máquina no pueden ser usadas por cualquiera. Por ejemplo,
la instrucción de paro (Halt) podría ser peligrosa en manos de usuarios maliciosos o descuidados,
por lo que ciertas instrucciones deberían ser usadas solo por usuarios privilegiados. Estas son
llamadas Instrucciones Privilegiadas. Por esta razón la computadora ejecutará sus tareas en
uno de (por lo menos) dos modos:

• Modo Usuario: Donde las instrucciones privilegiadas no pueden ser usadas; en caso de que
se trate de usar una de estas instrucciones el sistema interrumpe la ejecución y genera una
excepción.
• Modo Supervisor (Kernel): Donde todas las instrucciones pueden ser ejecutadas.

Un ejemplo de procesador con modos es el MC6800 [2.19], que define sus modos de la
siguiente manera:

• El MODO USUARIO conforma un entorno de programación para la ejecución de los


programas de aplicación. En este modo no se pueden ejecutar ciertas instrucciones y no se
puede acceder a parte del registro de Estado.
• El MODO SUPERVISOR permite utilizar el juego de instrucciones completo y acceder a todo el
registro de Estado, tanto en lectura como en escritura. Se establecen así unos "privilegios" de
utilidad en sistemas operativos y software de base de los sistemas.

La protección del uso sin control de las instrucciones de la máquina es consecuencia de la


distinción de modo. Cuando se está en modo supervisor, el programa usará un nueva pila
(stack), tendrá un vector de estado de programa diferente y acceso a un conjunto de direcciones
diferente al de modo de usuario.

Al iniciar el CPU se encuentra en modo supervisor. Cuando el SO cede el control a otro


programa conmuta previamente a modo de usuario (no privilegiado), y solo se vuelve al modo
supervisor cuando ocurre una interrupción, una llamada al sistema o una excepción.

La transferencia del modo supervisor a modo usuario ocurre por una instrucción explicita de
regreso llamada REI (REturn from Interrupt). Cada transferencia al modo de supervisor a causa
de una llamada supervisora debe guardar el estado del emisor, y debería llevar los parámetros
del modo en la petición, y debería dársele seguimiento checando la legalidad de dicha petición.

El hardware debería ayudar a identificar la causa para la transferencia a modo de supervisor. La


transición de modos usuario-supervisor y viceversa debe ser muy eficiente, lo cual no es fácil de
hacer pues pueden haber muchos cambios en los espacios de memoria.


Obras consultadas: [2.17] [2.18] [2.19] [2.21]

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

El código ejecutado en modo supervisor es llamado ejecutivo, y una porción de este es el núcleo
del sistema. La idea de modos separados e instrucciones privilegiadas ha sido tan exitosa que ya
se han encontrado usos para más de dos modos.

 Funcionamiento del kernel


El kernel de un SO (los que lo tienen) tiene la responsabilidad de la ejecución del sistema. Es
usualmente el kernel el que realiza las tareas de controlar el hardware. En un escenario típico,
el kernel realiza inicializaciones de hardware (además de algunas inicializaciones del software
como estructuras de datos, etc.) como actualizar el estado del procesador, ajustes del reloj
interno, inicialización de dispositivos, etc.

Todas estas tareas son muy delicadas, por lo que deben realizarlas programas especializados.
La protección (verificación de nivel de confianza del código) usualmente viene del hardware. El
hardware reconoce el código por medio de un nivel de privilegio (más alto para el kernel).

La regla del pulgar seguida por el procesador es que un código puede siempre disminuir sus
privilegios pero no aumentarlos, excepto en algunas condiciones especiales que son
determinadas por el código de alto nivel de privilegio (las cuales son llamadas trampas o
llamadas al sistema).

El kernel puede proveer ciertos puntos de entrada que permitan la ejecución de cierto código
en el nivel más alto de privilegio en un punto posterior en el tiempo, y esta facilidad es
extensamente usada por el enfoque de manejadores de dispositivos modulares.

La forma de proceder es que dependiendo de la configuración del hardware, el kernel decide


que código debe ser ejecutado. Este código es cargado de la memoria secundaria a la memoria
primaria, y se le asigna un nivel de privilegio equivalente al del kernel (este código puede
proceder de la misma forma).

Al final de tales inicializaciones, el kernel cambia su nivel de privilegio a un valor menor y


levanta el código que realiza el trabajo de interacción con el usuario.

2.3 Comentarios ⊕

Con respecto a la protección del hardware mediante el uso de modos, vale la pena comentar
que el principal atributo que distingue a los kernels monolíticos y micro-kernels es lo que sus
respectivas arquitecturas implementan en modo supervisor (kernel mode) de la CPU y lo que se
implementa en el modo usuario (user mode) de la CPU.


Obras consultadas: [2.22]

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

La arquitectura monolítica implementa todos los servicios del sistema operativo (controladores
de dispositivos, memoria virtual, sistema de archivos, comunicación en redes, etc.) en el
espacio dominado por el modo supervisor de la CPU. En cambio, la arquitectura micro-kernel
hace una división entre los servicios del sistema operativo dividiéndolos en "alto-nivel"
implementados en el espacio dominado por el modo usuario y "bajo nivel" implementados en el
espacio dominado por el modo supervisor.

Ya contando con un panorama de las principales consideraciones relacionadas al


funcionamiento de un sistema operativo, en el siguiente capítulo se exponen algunos conceptos
sobre simulación de sistemas, en específico de sistemas operativos.

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

2.4 Obras consultadas


[2.1] DESDE QUE PULSAMOS EL BOTON DE NUESTRO [2.11] How computer memory works. Marshall Brain's
PC HASTA... HowStuffWorks
José Manuel Tella Llop, extraído de http://www.howstuffworks.com/computer-memory.htm
microsoft.public.es.windows98
http://www.duiops.net/windows/articulos/ [2.12] A Designer's Assistant Tool Home Page.
http://www.duiops.net/windows/tablacw.htm Computer Systems Group University of Waterloo.
http://csg.uwaterloo.ca/dptool/
[2.2] How Operating Systems Work. Marshall Brain's
HowStuffWorks
[2.12] Bootsector authoring.
http://www.howstuffworks.com/operating-system.htm
Gareth Owen gaz@athene.co.uk

[2.3] Sistemas operativos I: Interrupciones del


[2.13] Daniels NASM bootstrap tutorial
procesador
http://itver.edu.mx/so1/24.htm Daniel Marjamäki. daniel.marjamaki@home.se
http://www.nondot.org/sabre/os/files/Booting/nasmBoo
t.txt
[2.4] CSC 277- Operating Systems (handouts). Michael
Lynch
[2.14] Operating system design & implementation –
http://www.qvctc.commnet.edu/classes/csc277/handou
tutorial. Dr. Mohan Raj Dhanagopal.
ts.html
http://www.ansawide.com/josh/index.htm

[2.5] Introduction to Operating Systems. Kathryn S.


McKinley. University of Massachusetts .Fall 1997 [2.15] La memoria
http://www-aml.cs.umass.edu/~cs377/ http://fismat.umich.mx/~htejeda/introduccion/inf003.ht
ml
[2.6] "El Torito" : Bootable CD-ROM Format
Specification Version 1.0. [2.16] Funcionamiento del bus de direcciones
Curtis E. Stevens (Phoenix Technologies), Stan Merkin http://www.pchardware.org/buses/busfunci.php
(IBM) January 25, 1995.
[2.17] Contexto de un proceso
[2.7] RFC Repository. Ross Finlayson. Bootstrap http://labsopa.dis.ulpgc.es/psis/gesproc/Expo%20conte
Loading using TFTP. RFC 906, NIC, June, 1984 xto%20de%20un%20proceso.htm
RFC 951 (Croft & Gilmore, Septiembre 1985).
BOOTSTRAP PROTOCOL (BOOTP)K. R. Sollins, Noel [2.18] Memoria virtual
Chiappa.
http://www.multingles.net/docs/memoria_virtual.htm
The TFTP Protocol. RFC 783, NIC, June, 1981.
http://www.cis.ohio-
state.edu/hypertext/information/rfc.html [2.19] EL µPROCESADOR 68000
http://www.ii.uam.es/~fjgomez/68000/tutorial/cap1.ht
ml
[2.8] An Introduction to Network Booting and
Etherboot. Ken Yap.
http://www.linuxfocus.org/English/index.html [2.20] Sistema operativo UNIX
http://www.arrakis.es/~ofafian/unix-lec1.html
[2.9] JavaOS: Thin Client, Fat Service. Charles Mirho
and Tom Clements .Byte. July 1997. [2.21] Estructura de los sistemas operativos
http://www.byte.com/art/9707/sec4/art4.htm http://bari.ufps.edu.co/personal/150802A/estructura.ht
m
[2.10] How Microprocessors Work. Marshall Brain's
HowStuffWorks [2.22] Linux FAQs
http://www.howstuffworks.com/microprocessor.htm http://www.angelfire.com/ar/favaloro1/faqs3.html

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

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

Capitulo 3.
Simulación de Hardware y Sistemas Operativos
Escucho y olvido, veo y recuerdo, hago y comprendo.
Proverbio chino

Largo es el camino de la enseñanza por medio de teorías;


breve y eficaz por medio de ejemplos.
Séneca

El esfuerzo de utilizar las máquinas para emular


el pensamiento humano siempre me ha parecido
bastante estúpido. Preferiría usarlas para emular
algo mejor.
Edsger Dijkstra

Es muy interesante que algunos autores citen la posibilidad de simular un sistema operativo, así
que en este capítulo se tratará de implementar uno propio para entender los conceptos e ideas
que se han expuesto hasta el momento. Tal vez parecería que aun no se han tratado los temas
suficientes como para emprender un esfuerzo de este tipo, pero cabe aclarar que no se quiere
simular un Windows o un Linux, sino entender las funciones más primitivas del sistema, es decir:

• qué se requiere para ejecutar un programa


• cómo se controla el hardware
• cómo funciona la secuencia de arranque
• cómo funciona un cargador del sistema

Para ello el principal elemento a simular es el hardware. Es un hecho que la complejidad de


instrumentar un sistema operativo es considerable, pero al parecer del autor debe ser más fácil
entender como funciona un SO, si se tiene la experiencia de modelar los componentes de más
bajo nivel.

Adicionalmente se trata el tema de la simulación de SOs por dos razones:

1. Ya existen programas que instrumentan modelos de sistemas operativos y que permiten


que pueda entenderse su funcionamiento.
2. El enfoque de simulación de sistemas, es una herramienta con la que pueden modelarse
algunos de los subsistemas expuestos en los capítulos anteriores, y que puede ser un
enfoque alternativo a la construcción de un sistema operativo, con fines de entender y
experimentar en la parte de diseño.

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

En los apéndices se ha incluido como caso de estudio el código del simulador propuesto en este
capítulo (apéndice B).

3.1 La simulación en el diseño de sistemas operativos⊕

La simulación, es un método científico no obstructivo de estudio que involucra experimentos


con un modelo en lugar de la porción de la realidad que el modelo representa. La simulación es
no obstructiva por que no perturba el objeto de estudio (excepto tal vez cuando un actor aplica
sus resultados).

A pesar de que mucha de la información provista por la simulación esté ya contenida en el


modelo, la simulación es útil cuando gran cantidad de partes interactúan con muchas rutas que
necesitan ser rastreadas simultáneamente, lo que requiere realizar una gran cantidad de
iteraciones para aproximarse a los resultados. El poder generar una historia sintética de
procesos dinámicos y poder manipular los eventos y condiciones del modelo es lo que hacen de
la simulación una técnica idónea para el diseño de sistemas operativos, como se verá más
adelante.

Aún cuando se considera que una implantación real es la única forma de comprobar la eficacia
de un diseño, en el caso de los sistemas operativos, la simulación ha sido aplicada por varios
grupos de trabajo. Aún cuando Silberschatz menciona en su tercera edición de Conceptos de
sistemas operativos (pp. 126) que "las simulaciones pueden ser muy caras, al requerir horas de
tiempo de computo, y más cuando se desea mucho detalle", es claro que con el poder de las
actuales computadoras, y lo que está por venir, las consideraciones de recursos pueden quedar
en un segundo plano.

Entre los principales simuladores de SOs destacan:

a. NachOS (Berkeley). Nachos es un sistema instruccional para la enseñanza de cursos de


sistemas operativos. La distribución de Nachos contiene:
- el código base para un SO operacional
- un simulador de una computadora genérica
Los temas ilustran y exploran todas las áreas de los sistemas operativos modernos, incluyendo
hilos (threads) y concurrencia, multiprogramación, llamadas al sistema (system calls), memoria
virtual, tablas de translación de direcciones virtuales a físicas (TLB), sistemas de archivos,
protocolos de red, llamadas remotas a procedimientos (remote procedure call), y sistemas
distribuidos.

b. SimOS. Simula el hardware de una computadora con detalle suficiente para cargar y ejecutar
sistemas operativos comerciales, además de proveer un ambiente completo de análisis de
ejecución y carga de trabajo (workload).

c. RCOS. Está diseñado para demostrar los principios generales de los sistemas operativos por
medio de animación controlada. Básicamente es una herramienta diseñada para ayudar a la
gente a comprender el funcionamiento interno de un sistema operativo. RCOS es un sistema
operativo multitarea que se ejecuta en hardware simulado, el cual esta basado en la máquina P

Obras consultadas: [3.1] [3.2] [3.22] [3.23] [3.24]

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

(P-Machine), un sistema de computo hipotético simple. Incluye un compilador de C/C++ que


genera P-Code que puede ejecutar la máquina P.

d. SOS (Simple Operating System Simulator). El libro "Operating Systems: A Design-Oriented


Approach" (Charles Crowley, Irwin, 1997) contiene el código (C++) para un sencillo sistema
operativo llamado SOS, el cual se ejecuta en una plataforma de hardware llamada CRA-1, la cual
es una máquina RISC simple.

e. Flux OSKit (Utah). Es una plataforma con un conjunto de 34 librerías de componentes que
facilita la creación de un nuevo sistema operativo portando un SO existente a otra plataforma
(p.ej. x86), ampliar el soporte de dispositivos, formatos de sistemas de archivos, formatos
ejecutables, o servicios de red; así como construir programas relacionados, como cargadores o
servidores montados sobre un microkernel.

Figura 3.1a Esquema de la arquitectura del FLUX OSKit2

Las librerías contienen el código nativo del OSKit, código para integrar subsistemas y código
legado (fig. 3.1a). La funcionalidad del OSKit se divide en tres categorías: interfaces, librerías de
funciones y librerías de componentes. Las interfaces proveen el “pegamento” nuevos
componentes a un SO. Las librería de funciones proveen servicios básicos de bajo nivel (manejo
de memoria, carga de programas, manejo de interrupciones, etc.). Las librerías de componentes
proveen funcionalidad de alto nivel (administración de memoria y procesos, soporte POSIX,
sistemas de archivos, comunicaciones en red, multimedia, etc.).

f. Palm OS Simulator. Es el simulador del Palm OS 5.0; no es una emulación del hardware
como el PalmOS Emulator, sino el sistema operativo real ejecutándose sobre una DAL (capa de
abstracción de dispositivos). Se usa más como herramienta para validar los posibles errores y

2
Imagen reproducida de [3.24]

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

compatibilidad de las aplicaciones en dispositivos PDA que tengan esta versión del sistema (que
en el momento en el que lo descubrí, es una versión de prueba del sistema que esta compañía
liberará, por lo que su estrategia para con los desarrolladores resulta sumamente útil). Se
recomienda su uso en conjunto con el emulador para asegurar una buena compatibilidad de los
desarrollos.

Figura 3.1b Esquema de la arquitectura del Palm OS3

Por lo anterior, puede decirse que los objetivos de la simulación de sistemas operativos
son:
• entender el funcionamiento interno de un SO
• determinación de cargas de trabajo del SO en un procesador especifico (SimOS)
• diseño de nuevas arquitecturas de SOs

A estos puede agregarse


 Migración de sistemas operativos. Dado un sistema con una arquitectura modular,
podría seleccionarse un subconjunto de módulos tales que puedan formar una nueva
distribución del meta conjunto de módulos (algo similar a lo que ocurre con las distintas
distribuciones de Linux actualmente), portarla a una arquitectura especifica, soportar un
rango mas amplio de dispositivos y servicios.
 Desarrollo de SOs basado en componentes, de forma que puedan probarse nuevos
kernels, servidores, manejadores, cargadores, etc. en diferentes condiciones y
configuraciones (podría ser el inicio para una herramienta RAD)

Un ejemplo de esto es la propuesta del OSKit con un enfoque basado en componentes, donde
los diseñadores de SOs se beneficiarían de las técnicas de ingeniería de software como la
orientación a objetos y excepciones, tal como los desarrolladores de aplicaciones lo hicieron en la
década de los noventas.

Algunos de los enfoques de los simuladores existentes se orientan a:


• 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. Seleccionar el lenguaje de programación a usar.


2. Encontrar toda la información disponible sobre el hardware a emular.
3. Escribir la emulación del CPU u obtener algún código existente para la emulación del CPU.
4. Escribir un prototipo del código para emular el resto del hardware, al menos parcialmente.
5. 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 priority;
int cpu_time_required;
int cpu_time_slice;
int cpu_time_total;
int io_time_required;
int io_time_total;
int response_time;
int time_in;
public int nextPos; /* next process array index--"pointer" */
...

Hecho esto podemos hablar de la estructura que contendrá y planificará a los procesos. Cada
cola debe tener un máximo de procesos que puede atender (esto de forma dinámica tiene que
ver con la memoria disponible del sistema) así como implementar un tipo de algoritmo de
planificación (esto lo implementa la clase OSQueue).

La principal operaciones de una cola de procesos es insertar un proceso en la estructura


(insert).

public class OSQueue extends Object {


int queueType; /* 1 = FIFO, 2 = LIFO, 3 = SJF,
4 = LJF, 5 = RR */
int maxElements, curElements, qHead;

public OSQueue(int q, int max) {


queueType = q;
maxElements = max;
qHead = -1;
}

Esta implementación en particular usa una estructura OSProcess[] ProcessArray que se


encarga de almacenar todos los procesos del sistema. Debe resaltarse que esta estructura no
pertenece a OSQueue, sino que aplica para cualquier cola de procesos existente en el sistema. Lo
que sucede, es que al llamar al método insert de OSQueue, de actualizan los índices a los
procesos siguientes de los PCBs. Esta implementación permite que cualquier cola de procesos
pueda usar diferentes algoritmos de planificación.

/*** put processes into the queue based on the queue type's ***/
/*** algorithm. The head must be the next in line to leave. ***/
public void insert(int P) {
int ptr, optr=0;
System.out.println("We are in Q insert");
if (curElements == maxElements)
return;
switch(queueType) {
case 1: /* FIFO */
case 5: /* Round Robin */
/* traverse the Q to first */
System.out.println("IN OSQueueInsert, Qtype: "+queueType+
",qHead: "+qHead+" P: "+P);

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

ptr = qHead;
if(qHead == -1) {
qHead = P;
OSSystem.ProcessArray[qHead].nextPos = -1;
} else {
optr = ptr;
while(ptr != -1) {
System.out.println("We are in FIFO while ptr = "+ptr);
optr = ptr;
ptr = OSSystem.ProcessArray[ptr].nextPos;
}
OSSystem.ProcessArray[optr].nextPos = P;
}
curElements++;
System.out.println("We are leaving FIFO; current elements: "+
curElements);
break;
}
System.out.println("We are at the end of Q insert");
}

Tomemos como ejemplo la implementación para los algoritmos FIFO y Round robin (que en
este caso es casi lo mismo). En realidad se esta implementando una estructura FIFO, pero lo
interesante es que la inserción solo está operando sobre los índices del arreglo principal de
procesos.

Si el dispositivo en el que el proceso se ejecuta es el CPU se incrementan los valores de tiempo


que el proceso ha pasado en el dispositivo; lo mismo pasa para la E/S.

if (devName.equals("CPU")) {
System.out.println("Qtype inside: "+devName);
OSSystem.ProcessArray[curr_process].cpu_time_total++;

if (devName.equals("IO")) {
System.out.println("Qtype inside IO device: "+devName);
OSSystem.ProcessArray[curr_process].io_time_total++;

3.4.2 NachOS⊕
Nachos es un software instruccional que permite a los estudiantes analizar y modificar un
sistema operativo real operacional. Fue desarrollado en la Universidad de Berkeley y es usado por
varias escuelas para la enseñanza de cursos de sistemas operativos.

Como en cualquier sistema operativo, hay un planificador (Scheduler) que mantiene el control
de los procesos en el sistema y los alterna periódicamente, y mantiene una lista de procesos
(readyList) para este propósito. Todos los procesos en Nachos se ejecutan como hilos. Esto
significa que todos los programas que se ejecutan en Nachos son implementados como hilos.


Obras consultadas: [3.11] [3.12] [3.13]

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

Figura 3.5 Forma en que los diferentes componentes de Nachos están ligados durante la
ejecución4

El lapso de tiempo para la ejecución de cada proceso es determinado por el componente


Temer, que causa una interrupción cuando el lapso de tiempo para un proceso en ejecución
expira.

El componente Interrupt maneja todas las interrupciones generadas por el componente Timer.
La causa de las interrupciones pueden ser la E/S de algún dispositivo (p.ej. la escritura a un
archivo por parte de un proceso, una señal del planificador para cambiar a otro proceso, etc.).

Todos los sistemas operativos necesitan al hardware para ejecutar sus procesos. El componente
Machine provee dicha funcionalidad, al simular la arquitectura MIPS. El componente FileSystem
administra todas las operaciones de archivos. SynchDisk provee acceso sincronizado al disco.
Para conectar una maquina con otras, se tiene el componente PostOffice que administra la
recepción y envió de mensajes a través de una red. Stats es un componente que mantiene
ciertas estadísticas sobre la ejecución y eficiencia del sistema. Por ejemplo, puede mantener el
rastro de cuantos caracteres han sido escritos en la pantalla, cuantos errores de paginación han
ocurrido, cuantos paquetes han sido recibidos por medio de la red, etc.

 La máquina Nachos
Nachos simula una máquina parecida a la arquitectura MIPS. La máquina tiene registros,
memoria y CPU. Además, un reloj simulado manejado por eventos provee un mecanismo para
planificar las interrupciones y ejecutarlas posteriormente. La simulación de la máquina MIPS
puede ejecutar cualquier programa. Solo hay que cargar las instrucciones en la memoria de la

4
Imagen reproducida de [3.11]

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

máquina, inicializar los registros (incluyendo el contador de programa PCReg) y entonces


decirle a la máquina que empiece a ejecutar las instrucciones. La máquina obtiene entonces la
instrucción a la que apunta el PCReg, la decodifica y ejecuta. El proceso es repetido
indefinidamente, hasta que una operación ilegal es realizada o una interrupción de hardware es
generada. Cuando ocurre una trampa o interrupción, la ejecución de las instrucciones MIPS es
suspendida, y una rutina de servicio de interrupción es invocada para atender la petición.

Conceptualmente, Nachos tiene 2 modos de ejecución:


• Nachos ejecuta procesos a nivel de usuario cargándolos en la memoria del simulador,
inicializando los registros del simulador y luego ejecutando el simulador. Los programas de
usuario solo pueden accesar la memoria asociada con la máquina simulada.
• El segundo modo corresponde al kernel de Nachos. El kernel se ejecuta cuando Nachos se
inicia, o cuando un programa de usuario ejecuta una instrucción que causa una trampa de
hardware (p.ej. una instrucción ilegal, falló de paginación, llamada al sistema, etc.). En
modo de kernel, Nachos se ejecuta igual que un proceso normal de Unix. Es decir, las
declaraciones correspondientes al código fuente de Nachos son ejecutadas, y la memoria
accesada corresponde a la memoria asignada a las variables de Nachos.

3.4.3 RCOS⊕
RCOS esta implementado en Java (aunque la distribución original está en C++), y pertenece a la
categoría de sistemas operativos basados en kernels.

RCOS.java esta dividido en las siguientes secciones:

1. Hardware

• CPU. Hasta el momento está basado en el código de la máquina P. La intención es reutilizar


el compilador RCOS PLL/2 y el intérprete de C++ existentes.
• Disco. Se usa una estructura pequeña para producir una representación gráfica de la
asignación/desasignación de los bloques del disco por medio del sistema de archivos.
• Terminal y Memoria (RAM). La Terminal provee la interfaz física con el usuario, incluyendo
el teclado y monitor. La Memoria consiste de 2 secciones. La primera es el cache del CPU, la
cual es ajustada dinámicamente para almacenar programas en ella. Esto incrementa la
velocidad y reduce la complejidad principalmente. La memoria RAM secundaria contiene
todos los programas cargados y los almacena en dos secciones: código de proceso y pila
(stack).

2. Sistema operativo

- Kernel. RCOS usa un micro-kernel basado en una estructura de paso de mensajes. El kernel es
responsable de varias funciones específicas de la plataforma incluyendo:
a. manejo de interrupciones
b. salvado/restauración del contexto (saving/retrieving context)


Obras consultadas: [3.16] [3.17] [3.18] [3.19] [3.20]

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

c. generación de mensajes al componente apropiado del SO como resultado de una


llamada al sistema

- Paso de mensajes (Message passing). Las funciones estándar del sistema operativo están
divididas en diversos componentes. Toda la comunicación entre ellos debe ser en forma de
mensajes. Todos los mensajes pasan por el componente Post Office que es responsable de
entregar los mensajes a los destinos correctos. La intención es que componentes diferentes
puedan ser localizados en computadoras diferentes.

- Funciones del SO. Las responsabilidades restantes de SO están divididas en los siguientes
componentes:

a. Planificador de disco. Responsable de administrar las peticiones de planificación al


disco, traducir los números de bloque lógico a sectores específicos del disco, cilindro y
superficie. Hay un planificador de disco para cada disco.
b. Sistema de archivos. Responsable de implementar un sistema de archivos particular
(MS-DOS, CP/M, UNIX, NTFS, etc.). Maneja mensajes estándar como abrir archivo, cerrar,
leer, escribir, abrir directorio, obtener atributos del archivo, etc. Es posible para una
instancia del RCOStener varios objetos FileSystem, dando la habilidad para soportar más
de un sistema de archivos a la vez.
c. Planificador de procesos. Responsable de administrar la creación de procesos,
terminación y planificación. Maneja mensajes como dividir un proceso (fork), ejecutar
proceso, matar un proceso, planificar un nuevo proceso, bloquear proceso, etc. Mantiene
todas las colas de discos e incluye métodos como runningToReady, runningToBlocked,
getNextRunningProcess.
d. Administrador de memoria. Responsable de administrar la memoria, asignar y
desasignar memoria para los procesos, lectura y escritura de memoria para otros
componentes.
e. Terminales. Proveen el mecanismo para escribir/leer a/de una terminal.

3. Animación

El sistema de Animación esta oculto del resto del sistema por la clase Post Office Animator. Sus
responsabilidades incluyen:

- dibujar la pantalla de perspectiva principal


- manejar eventos de entrada e inicializar nuevos hilos para manipular la animación de
varios componentes del SO.
- decidir que mensajes son interesantes para el sistema de animación y distribuirlos en los
hilos apropiados (si existen).

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

Figura 3.6 Arquitectura del RCOS5

3.5 Simulación de un Sistema Operativo mínimo

Aunque sería en extremo interesante poder simular cada una de las configuraciones históricas
de los diversos sistemas operativos (una idea extremista pero interesante si se quiere hacer una
exploración desde los inicios), esto sería en extremo un esfuerzo de mucho tiempo y escapa al
objetivo de este trabajo.

Para capitalizar las ideas expuestas anteriormente, con respecto al funcionamiento de un


sistema operativo (capítulo 2) y la simulación de este tipo de sistemas, en esta sección he
documentado una primera experiencia en este sentido.

En cuanto todos los conceptos y sus interacciones cobraron sentido, se decidió hacer el intento
de codificar un simulador que hiciera las cosas más sencillas que un SO se supone que realiza. La
primera pregunta que surgió fue: ¿modelar solo el SO, o se requiere modelar también el
hardware donde se ejecuta? Este primer problema no es tan sencillo como podría suponerse.
Modelar una computadora es un ejercicio bastante complejo; y por lo visto hasta el momento un
SO también es un sistema bastante complejo, como para aumentar la complejidad de la
implementación. Sin embargo, hay algunos hechos que no pueden dejarse de lado:

5
Imagen reproducida de [3.17]

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

- el sistema operativo se crea para administrar los recursos de una computadora;


- el SO en la mayoría de los casos es muy dependiente del hardware, pues aunque se creen
abstracciones de alto nivel para modelar sus servicios, los niveles de base siguen encargados de
el acceso al hardware y su control;
- el SO por más portable que sea, necesita realizar funciones básicas para su inicialización y
configuración, las cuales son dependientes de los recursos y arquitectura de la computadora.

Esto deja claro que es necesario modelar el hardware para tener una simulación completa.
Basta con ver los casos de estudio expuestos (NachOS y RCOS) para ver que es necesario
(consulte los detalles de la implementación en el Apéndice. Simulación de un sistema mínimo de
hardware y su sistema operativo).

3.5.1 El hardware: URM


Así, se decidió retomar un modelo de computadora llamado URM (Unlimited Register Machine)
implementado en el curso "Computabilidad y Funciones recursivas" de la licenciatura en
ingeniería en Computación (FAR). Puesto que este modelo es un procesador abstracto, y tiene
muy pocas instrucciones, es un ejemplo de dimensiones controlables (haber elegido un
microprocesador como un Pentium o un PowerPC, seria tema de otro trabajo).

La URM tiene un numero infinito de registros (R1,R2,R3...) cada uno de los cuales contiene en
todo momento un numero natural. El contenido de los registros puede ser alterado por la URM
en respuesta a ciertas instrucciones que puede reconocer. Estas instrucciones corresponden a
operaciones simples usadas para realizar cálculos con números. Una lista finita de instrucciones
constituye un programa. Las instrucciones son las siguientes:

- Z(n). Instrucción cero. Cambia el contenido del registro Rn a cero, dejando sin alteración a
los demás registros.
- S(n). Instrucción sucesora. Incrementa el valor del número contenido en Rn en 1, dejando a
los otros registros sin alteración.
- T(m,n). Instrucción de transferencia. Reemplaza el contenido del registro Rn por el valor
contenido en Rm.
- J(m,n,q). Instrucción de salto. El contenido de los registros Rm y Rn son comparados; si
rm=rn la URM procede a la instrucción q-ésima del programa en ejecución; si 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 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();

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 Memory {
public void setMemLoc(int adr, Object value);
public Object getMemLoc(int adr);
public void showMem();
}

En el simulador se cuenta con un genérico de estas funciones, y una implementación específica


para la memoria de la URM.

3.5.2 El software: SOM


En lo que respecta al software, en específico al sistema operativo de esta máquina, hay dos
alternativas:
1. Codificar el sistema operativo en código del modelo simulado.
2. Crear un módulo que se encargue de las funciones propias del sistema operativo.

Como se mencionó al principio, lo que se quiere es un sistema operativo mínimo, pero... ¿qué
es eso? En concreto, es una pieza de software que permita cargar un programa a la memoria del
modelo y que el procesador lo ejecute.

Figura 3.7 Modelo del simulador con un cargador de programas.

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

Si tomáramos la primera opción, lo primero que salta a la vista es que como el modelo solo
consta de 4 instrucciones, el conjunto de instrucciones tendría que ser ampliado para permitir el
acceso al disco, controlar dispositivos, mostrar resultados en un dispositivo de salida, etc. Aunque
puede hacerse, el modelo se convertiría en un nuevo procesador, y en ese caso sería mejor
emular un procesador con las instrucciones suficientes como para implementar un SO completo.

El segundo enfoque es igualmente válido, pues si el mismo simulador implementa el modelado


de las funciones de nuestro SO mínimo, el resultado de la simulación es el mismo. Esta opción es
la que se ha implementado.

Tomar esta decisión implica algunas consideraciones extra, como:


- Que la dirección de carga de programas, será el inicio del arreglo que se use. Esto se
interpretaría como que el SO ya está cargado en memoria, y esa área está protegida
contra el acceso de otros programas.
- Que el SO implemente funciones de acceso a dispositivos, aunque estos no formen parte
explicita del modelo. La entrada/salida estándar es equivalente a que el simulador cuente
con un monitor, y el acceso a los archivos es equivalente a contar con dispositivos y sus
respectivos manejadores.

De esta forma el SOM tendría todas las características de un monitor residente, uno de los
primeros SOs, las cuales pueden extenderse para implementar el procesamiento por lotes
(batch), para lo que se debe incluir un JCL (Job Control Language).

El JCL propuesto es el siguiente:


• LOAD - carga un programa
• RUN - ejecuta un programa
• EOJ - Fin del trabajo (End Of Job)
• LDBATCH - Carga un archivo con comandos para procesarlos en lote
• SHUTDOWN - Apaga el SO

El modelo solo ejecutará un programa a la vez, por lo que la administración de procesos no fue
implementada. Además con la simplificación del acceso a memoria tampoco se necesita un
administrador de memoria, aunque pudiera ser útil si se quisiera expandir la memoria base del
modelo.

El SOM está compuesto de las clases:


 Loader, se encarga de cargar los programas desde su archivos a la memoria para su
ejecución.
 JCLInterpreter, se encarga de interpretar los comandos JCL.
 Monitor, esta compuesta por Loader y JCLInterpreter y se encarga de cargar un
programa o un conjunto de programas en memoria para luego ejecutarlos, en base a
una secuencia de comandos JCL.

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

Figura 3.8 Modelo del simulador con un SOM para una URM modificada, basado en el
concepto de un monitor residente.

Figura 3.8a Ejecución del simulador

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

Aunque sin incorporar el manejo de interrupciones, dispositivos, etc., este primer diseño es lo
bastante ilustrativo como para entender lo que hace un sistema operativo, y como codificarlo (a
un nivel muy básico).

En la siguiente sección se comentan algunos de los elementos que no han sido considerados en
el simulador, pero podrían ser modelados para incluir los aspectos del manejo de dispositivos,
pero por el momento eso no está incluido en la implementación del apéndice B.

3.5.3 Consideraciones para el modelado de dispositivos de E/S⊕


Uno de los elementos básicos de cualquier computadora, son sus dispositivos de entrada y
salida (E/S). Aunque en la sección anterior la E/S de datos no era explicita en el modelo, estaba
implícita en las funcionalidades del lenguaje.

En el caso de la entrada de datos, el método runProgram() de la clase TestSimulator, captaba


las instrucciones del Lenguaje de Control de Trabajos, a nivel de instrucciones en Java
(hardcoded).

public void runProgram () {


Processor p=new URMProcessor(); //creando un nuevo procesador
//creando la memoria donde se almacenarán los programas
Memory m=new URMMemory(20);
Monitor os=new Monitor(p,m); //creando una nueva instancia del SO
System.out.println("Iniciando ejecución de instrucciones JCL...");
os.startMonitor(); //inicializando SO
os.userInput("LOAD c:\\sw\\oses\\OS\\prog.urm");
//comandos JCL para que los ejecute el SO
os.userInput("RUN");
os.userInput("SHUTDOWN");
}

En el caso de la salida, la instrucción System.out.println() hacia las veces de un dispositivo de


despliegue (monitor), permitiéndonos ver el resultado de la ejecución del programa. Incluso el
sistema de archivos también se vio encapsulado, y tampoco forma parte del modelo
explícitamente.

Aunque la abstracción es válida, y no impidió que el modelo se desarrollara hasta obtener un


prototipo funcional, la verdad es que se supone que parte del trabajo del sistema operativo es
controlar los dispositivos de E/S de la computadora, por lo que si no los tomamos en cuenta, el
modelo del SO quedará incompleto, y no podrán apreciarse los detalles relacionados a este
servicio.

Para mejorar el modelo propuesto, será entonces necesario incluir el sistema de E/S en el
simulador. Puede resumirse de lo expuesto en la sección 1.4.2, que los elementos a tomar en
cuenta son:

• El dispositivo


Obras consultadas: [3.14]

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

• El controlador del dispositivo


• El sistema de interrupciones

Esto implica las siguientes consideraciones:

a. Modelar un dispositivo abstracto, con un protocolo de mensajes que sea aceptado por
cualquier implementación de un dispositivo específico. El dispositivo genérico deberá proveer
como mínimo la lectura y escritura de sus datos, así como su configuración e identificación. Esto
será ampliado después por las implementaciones específicas, pero debe tomarse en cuanta que
el protocolo de mensajes puede verse ampliado, según el tipo de dispositivo (un monitor es
mucho más complejo que un teclado en su funcionamiento e interfaz).

b. Modelar el concepto de controlador de dispositivo. Todo dispositivo se conecta al bus por


medio de un controlador. Además, cada controlador tiene un buffer local, de donde el CPU
recoge y envía datos.

c. Modelar un sistema de interrupciones genérico que pueda ser aprovechado por


implementaciones de arquitecturas específicas. Los principales elementos del sistema de
interrupciones son:

- Las interrupciones, que notifican al CPU de una operación o llegada de nuevos datos.
- Las rutinas de servicio de interrupción (ISR), que son los procesos que se ejecutan
cuando llega una señal de interrupción y el CPU debe atenderla.
- El vector de interrupciones, que es una tabla en memoria con las direcciones de las ISRs
con que se cuenta.

Debe tomarse en cuenta que:

- las ISRs son instaladas en el vector por el sistema operativo;


- el dispositivo que interrumpe envía un numero por el bus de datos, el cual sirve de índice en el
vector de interrupciones para que el CPU pueda ejecutar la ISR adecuada;
- existen diferentes tipos de eventos:
• Interrupciones de hardware, por señales de los dispositivos.
• Interrupciones de software (llamadas al sistema; excepciones) por medio de
instrucciones especificas del procesador.
y cada evento activa una ISR diferente;
- el control de interrupciones puede ser síncrono (el SO espera a que la E/S termine) o asíncrono
(el SO continua su ejecución mientras la E/S se lleva a cabo).

d. Puede tenerse en cuenta el mecanismo de acceso directo a memoria (DMA), por medio del
cual los dispositivos tienen acceso a la memoria principal sin necesidad de que el CPU intervenga.

Ahora hay que revisar si el modelo actual permite la comunicación entre los dispositivos y
el CPU. Puesto que todo lo anterior no fue considerado desde un principio, es casi seguro que se
tenga que modificar una buena parte de la estructura del modelo.

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

Lo que se mantendrá en el modelo es la protección del SO y los programas de usuario como


una abstracción, puesto que el SO forma parte de la implementación del simulador no habrá que
implementar ese detalle.

3.5.4 Resultados
La estrategia para la construcción del modelo de simulación consistió en modelar los principales
servicios de administración de los sistemas operativos (procesos, memoria y dispositivos), para
después integrarlos en diferentes configuraciones, esperando que la tarea de integración arroje
problemas y consideraciones que aporten soluciones y experiencias interesantes para la
comprensión del diseño e implementación del simulador.

Aunque al principio se había planteado solo codificar los algoritmos y módulos que son
importantes para los sistemas basados en núcleos modulares (los más difundidos actualmente),
la simulación de cada una de estas partes, y del hardware relacionado a su funcionamiento, ha
dado como resultados algunas configuraciones similares a los primeros sistemas (sencillos pero
muy ilustrativos). Lo positivo de esto, es que se brinda al lector una perspectiva real, no sólo de
como funciona un sistema operativo y como hacerlo, sino de todas las reflexiones y decisiones
que involucra su diseño.

Los principales resultados de este primer experimento son:

• El escoger el modelo de URM para la simulación, no permite experimentar con programas


que tengan un control total sobre los recursos. Para este fin, el conjunto de instrucciones
debería ser lo más real posible, aunque para los fines de este trabajo, conviene que tenga el
menor numero de elementos posibles.
• El conjunto de instrucciones de la URM es suficiente para crear programas útiles, sin
embargo, habría que agregar instrucciones adicionales para el control de registros, accesos a
memoria y recursos, etc.; por eso es que los conjuntos de instrucciones de los procesadores
reales tienen tantas instrucciones.
• Implementar la abstracción de dispositivos de E/S reduce la complejidad, pues modelar
dispositivos específicos, como tarjetas de red, etc. hace necesario contar con más elementos
teórico-prácticos.
• No existió una fase previa de diseño. El "tener claro" que componentes era necesario
modelar, hizo que la improvisación reinara, y al final aunque se cuenta con un modelo que
funciona, hay muchas mejoras que pueden hacerse.
• En este momento se hizo patente la necesidad de una metodología clara para proceder.
Podría haber usado una metodología de ingeniería de software como RUP, o la que fuera,
pero sin perder el foco de este trabajo de este trabajo que son los SOs, usar una
metodología tan grande para un SO como el SOM hubiera sido excesivo (aunque en general
para al simulador le hubiera caído bien)
• La cohesión entre las clases del simulador es muy fuerte, por lo que hacer cambios en su
configuración es algo difícil.
• Las capacidades del BlueJay y su depurador permitieron contar con una visualización del
proceso de simulación (primitiva pero efectiva)
• Para reforzar el modelo de simulación, es recomendable (sino indispensable) permitir que el
usuario de la herramienta pueda visualizar el comportamiento del modelo, e incluso modificar
su comportamiento, en cualquier momento. Para ello debe considerarse agregar a los
elementos más significativos del modelo, la funcionalidad para que puedan desplegar su

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

comportamiento a través de una interfaz gráfica. Preferentemente debe permitir visualizar el


modelo a nivel general, y además permitir el seguimiento de cada módulo que implique un
servicio relevante a todo el sistema. En el paradigma MVC (Modelo-Vista-Controlador) las
entradas producidas por el usuario, el modelado del mundo exterior, y la retroalimentación
visual al usuario están explícitamente separadas y manejadas por tres tipos de objetos, cada
uno especializado en su tarea. La Vista administra la salida gráfica y/o textual a la porción
del área de despliegue asignada a la aplicación. El Controlador interpreta las entradas del
usuario provenientes del teclado o ratón, ordenándole al Modelo y/o a la Vista cambiar como
sea apropiado. Finalmente, el Modelo maneja el comportamiento y datos del dominio de la
aplicación, responde a requerimientos de información sobre su estado (usualmente de la
Vista), y responde a las instrucciones al cambio de estado (usualmente del Controlador). Este
modelo deberá ser considerado más adelante.

Figura 3.9 Patrón de diseño Modelo-Vista-Controlador.

En los siguientes capítulos se presentarán a detalle los diversos sistemas de administración de


servicios que comúnmente forman parte de un sistema operativo. La idea es que una vez que se
ha mostrado que la simulación es una herramienta útil, se continuará usando para demostrar el
funcionamiento de estos sistemas.

Debo hacer notar que el enfoque de simular el hardware y el SO, es el más completo. Sin
embargo, en los siguientes tres capítulos es probable que se simulen solo los elementos
relacionados a cada sistema de administración, o probablemente solo se modelen puramente los
elementos de administración, sin el hardware. Ambos enfoques considero que siguen siendo
válidos, sobre todo para aclarar que hace cada parte y tomar a sus simulaciones como pruebas
de concepto.

3.5.5 morfo-Hardware
Uno de los resultados adicionales de este primer modelo de simulación fue la idea de crear un
sistema de hardware que pudiera modificarse para probar diferentes conjuntos de instrucciones.
A este modelo se le llamó morfo-Hardware.

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

Figura 3.10 Esquema del modelo morfo-Hardware

La idea es contar con una abstracción genérica de un dispositivo de hardware (HWDevice), del
cual se puedan derivar procesadores, memoria, y dispositivos periféricos, quienes se comunican
por medio de señales administradas por medio de un controlador.

Figura 3.11 Modelo de clases de morfo-Hardware v.0.1

Se incluyen algunos de los diagramas de clases preliminares de este modelo (figuras 3.11 y
3.12), pues a consideración del autor esto sería de mucha utilidad si se quieren comprobar
cuestiones de portabilidad de una plataforma de hardware a otra.

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

Figura 3.12 Modelo de clases de morfo-Hardware v.0.2

Lo interesante del modelo es que una vez que el framework quede establecido solo hay que
codificar el conjunto de instrucciones del nuevo procesador; todo lo demás quedaría intacto. En
fin, esta es una idea que sigue en desarrollo.

3.6 Comentarios

Como ya se comentó, simular el hardware puede ser una tarea exhaustiva, y dependerá mucho
del nivel de detalle y realismo que se desee en el simulador. Para muchos fines bastará con
incluir en los modelos elementos que efectúen las operaciones básicas de los dispositivos de
hardware; sobre todo si en lo que se quiere hacer énfasis, es en los componentes del sistema
operativo. En tal caso debe tenerse en cuenta que muchos algoritmos relacionados a la
administración de recursos ya están disponibles, por lo que es deseable hacer énfasis en el
análisis y visualización de resultados.

Ya que se han planteado los principales elementos para la simulación de sistemas operativos,
en los siguientes dos capítulos se planteará el desarrollo de simuladores para los subsistemas de
administración de memoria y de procesos, respectivamente.

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

3.7 Obras consultadas


[3.1] Guide to the Java Version of the Simple Operating Research Center,Duke University.
System (SOS) Simulator. Charles Crowley. August 1997. narten@cs.duke.edu February 3, 1997
http://www.cs.duke.edu/~narten/110/nachos/main/mai
[3.2] The Flux OS Toolkit: Reusable Components for OS n.html
Implementation.
The Flux OS Kit: A Substrate for OS and Language [3.14] A Designer's Assistant Tool Home Page.
Research Computer Systems Group . University of Waterloo
ftp://mancos.cs.utah.edu/papers/oskit-hotos6-abs.html http://csg.uwaterloo.ca/dptool/

[3.3] How To Write a Computer Emulator [3.15] The OS Emulation HomePage


Marat Fayzullin. 1997-2000. http://www.kearney.net/~mhoffman/
http://www.komkon.org/fms/EMUL8/
[3.16] RCOSjava
[3.4] The SNES Developers Corner http://rcosjava.sourceforge.net/
http://emureview.ztnet.com/developerscorner/index.ht
m
[3.17] RCOS.java
http://webfuse.cqu.edu.au/Information/Resources/Rea
[3.5] Emulation programmers resource dings/RCOS.java/
http://www.classicgaming.com/EPR/
[3.18] RCOS: Yet Another Teaching Operating System
[3.6] Trends in Hardware/Software Codesign Ron Chernich, Bruce Jamieson, David Jones
Larry Mittag Proceedings of the First Australasian Conference on
http://www.embedded.com Computer Science Education.
http://webfuse.cqu.edu.au/Information/Resources/Rea
[3.7] Truth, Beauty, and the Virtual Machine dings/RCOS.java/yato/
David Gelernter
http://rum.cs.yale.edu/jvmsem/lecture/0922/gelernter. [3.19] The Design and Construction of a Simulated
html Operating System. Ron Chernich, David Jones. Asia
Pacific Information Technology in Education
Conference, Brisbane, July 1994.
[3.8] Visible Virtual Machine (VVM) Page
http://webfuse.cqu.edu.au/Information/Resources/Rea
http://www.cba.uri.edu/faculty/vvm/
dings/RCOS.java/Design/

[3.9] THE UCSD P-SYSTEM MUSEUM IN THE WEST [3.20] Not just another teaching operating system
WING OF THE JEFFERSON COMPUTER MUSEUM
http://webfuse.cqu.edu.au/Information/Resources/Rea
http://www.threedee.com/jcm/psystem/index.html dings/RCOS.java/njato/
http://cq-pan.cqu.edu.au/david-jones/Projects/rcos/
[3.10] The Free Online Dictionary of Computing Edited
Denis Howe
[3.21] Modern Operating Systems Simulators
http://foldoc.doc.ic.ac.uk/
http://www.ontko.com/moss/

[3.11] NACHOS
[3.22] Palm OS Simulator
http://http.cs.berkeley.edu/~tea/nachos/
http://www.palmos.com/dev/tools/simulator/

[3.12] Salsa - An Operating Systems Tutorial. University


of Massachusetts, Amherst [3.23] SimOS
http://ali-www.cs.umass.edu/salsa/about.html http://simos.stanford.edu/

[3.13] A Road Map Through Nachos. Thomas Narten. [3.24] The OS Kit Project
Department of Computer Sciences, Levine Science 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 Look-
aside 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
Imagen reproducida de [4.5]
8
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 worst-
fit 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
Imagen reproducida de [4.3]
13
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
Imagen reproducida de [4.3]
18
Imagen reproducida de [4.3]

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

4.4 Simulación del servicio de administración de memoria

Con el fin de integrar los conceptos y técnicas descritos en las secciones anteriores de este
capítulo, se implemento un pequeño simulador para ejemplificar la administración de la memoria.
Después de analizar la información presentada en este capítulo, pueden distinguirse 2 escenarios
de administración en relación a los programas:

• Los esquemas que manejan programas como bloques monolíticos (todo el código del
programa está en un bloque)
• Los esquemas que manejan programas en forma de módulos (p.ej. en el caso de usar
overlays, librerías dinámicas, etc.)

Programa = un solo bloque de código

Particiones
fijas
PP

Particiones
PP variables

Paginación
PP

Figura 4.22 Los esquemas de particiones fijas, variables y paginación manejan


programas como bloques únicos.

Para mostrar el funcionamiento de la administración de memoria, se eligió implementar la


simulación usando el esquema de multiprogramación en sus dos variantes: particiones fijas y
particiones dinámicas. Esto permite mostrar los mecanismos que se requieren para la
administración de forma sencilla (si alguien se interesa en los otros esquemas es un buen
ejercicio pero está fuera del alcance del trabajo; sin embargo hay simuladores específicos que
abordan el tema).

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

Programa = Programa principal + módulos

PP
Segmentación

PP
Segmentación con
Paginación por
demanda

Figura 4.23 La segmentación y la segmentación con paginación son más aptos para
manejar programas y módulos dinámicos.

Los objetivos del simulador son:

• aplicar los conceptos relacionados a la administración de la memoria


• entender cómo se implementan los componentes de un administrador de memoria
• contar con una herramienta que permita visualizar el comportamiento de la memoria durante
la ejecución de programas
• tener la capacidad de observar fenómenos como la fragmentación

En principio, lo único que se modelará será la memoria y el administrador de la memoria.


Elementos como el almacenamiento secundario, el procesador, etc., no son modelados de forma
explicita. Para acotar el modelo hay que tomar en cuenta que:

• el único hardware a modelar es la memoria principal (RAM)


• el esquema de alojamiento de memoria es contiguo
• la administración se hará de forma automática
• solo se tomará en cuenta el tamaño y tiempo de ejecución de los programas
• no se implementan métodos sofisticados de optimización (pero se implementa un sencillo
mecanismo de compactación en el caso de las particiones variables)

Así, los principales componentes del simulador son:

• Programa. El programa que se cargará en la memoria, convirtiéndose en proceso. En el


simulador se representará mediante un objeto con atributos de tiempo y tamaño (del código
y memoria reservada), así como un identificador.
• Generador de Programas. Se encarga de generar de forma aleatoria, programas que serán
procesados por el administrador de memoria.

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

• Memoria principal. El almacenamiento primario donde se almacenan las instrucciones del


programa; en este caso, no son instrucciones lo que se almacena, sino que solo se marca la
memoria usada por un proceso con el valor del identificador del proceso correspondiente.
• Administrador de memoria. Encargado de la carga, asignación y desasignación de la memoria
para los procesos.
• Tablas de asignación. Son las estructuras encargadas de registrar la relación entre la
memoria disponible, y los recursos asignados. Su implementación varía dependiendo del tipo
de particiones a manejar.
• Controlador del simulador. Encargado de implementar el control de los componentes del
modelo. Cabe mencionar que parte de su implementación funciona de forma indirecta como
el procesador del sistema modelado, pues es el encargado de determinar que procesos han
cumplido con su tiempo de latencia en el sistema.

Figura 4.24 Modelo de clases del simulador de administración de memoria.

Lo más interesante es observar el comportamiento de cada enfoque de manejo de memoria, y


como al transcurrir el tiempo, los recursos deben de ser reasignados.

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

Figura 4.25 Ejecución del simulador.

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

4.5 Comentarios

El sistema de administración de memoria está dedicado a manipular el código y los datos que
integran una aplicación, y por lo tanto está muy relacionado al sistema de administración de
procesos. Por ello fue necesario en el primer capítulo introducir toda la terminología relacionada a
todos los subsistemas de los sistemas operativos, pues es difícil hablar de ambos en forma
aislada.

Cabe mencionar que todos los esquemas de administración de memoria presentados se aplican
por lo general a una sola máquina, aunque es posible ampliar estos conceptos a esquemas
distribuidos donde se trate de unificar las capacidades de memoria de varios equipos en un solo
recurso.

En el siguiente capítulo se exponen los principales aspectos de la administración de procesos, y


con ello se tendrá una visión más amplia de las funciones de base de un sistema operativo.

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

4.5 Obras consultadas


[4.1] Estudio Sistemas Operativos [4.10] Operating Systems concepts. A. Silberschatz, J.
Moisés Domènech Lloca. 1998. Peterson, P. Galvin. Addison Wesley. 1991.
ISBN 0-201-54873-9
[4.2] Fundamentals of operating systems
http://www.cs.wayne.edu/~tom/guide/os.html [4.11] IIC2332- Apuntes de clase
http://www2.ing.puc.cl/~jnavarro/iic2332/apuntes/apu
ntes_6.html
[4.3] Tutorial de sistemas operativos II. ITLP
http://www.itlp.edu.mx/publica/tutoriales/sistemasoper
ativos2/index.htm [4.12] Introduction to Operating Systems
Kathryn S. McKinley. University of Massachusetts .Fall
1997
[4.4] Sistemas Operativos. UDLA
http://www-aml.cs.umass.edu/~cs377/
http://lara.pue.udlap.mx/sist_oper/

[4.13] Memoria Virtual. Alberto Pacheco


[4.5] 150802 SISTEMAS OPERATIVOS I. UFPS. Facultad
http://www.socrates.itch.edu.mx/~apacheco/os/memvi
de Ingeniería.
rt.htm
http://bari.ufps.edu.co/personal/150802A/memoria.htm http://200.34.100.10/~apacheco/os/memvirt.htm
http://www.mycgiserver.com/~apacheco/os.html
[4.6] The Free Online Dictionary of Computing.
Denis Howe [4.14] Basics of computer memory. OSData.com
http://foldoc.doc.ic.ac.uk http://www.osdata.com/system/physical/memory.htm

[4.7] Webopedia [4.15] Conceptual Architecture of the Linux Kernel. Ivan


http://www.pcwebopedia.com/TERM/m/MMU.html Bowman (ibowman@sybase.com) January 1998
http://plg.uwaterloo.ca/~itbowman/CS746G/a1/
[4.8] The Memory Management Reference. Xanalys,
Harlequin. [4.16] Concrete Architecture of the Linux Kernel. Ivan
http://www.xanalys.com/software_tools/mm/ Bowman (ibowman@sybase.com), Saheem Siddiqi
(s4siddiqi@neumann), Meyer C. Tanuan
(mtanuan@descartes.com). Department of Computer
[4.9] CS 537 Lecture Notes Paging
Science, University of Waterloo. Winter 1998
http://www.cs.wisc.edu/~solomon/cs537-
http://plg.uwaterloo.ca/~itbowman/CS746G/a2
old/f96/paging.html

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 un proceso pasa de estado Running a Waiting.
• Cuando un proceso pasa de estado Running a Ready
• Cuando un proceso pasa de estado Waiting a Ready
• Cuando un proceso 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 Tiempo ejecución


P1 20
P2 5
P3 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 Tiempo ejecución Prioridad


P1 10 3
P2 5 2
P3 7 1
P4 8 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 (Long-


term 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


Obras consultadas: [5.7] [5.8] [5.9] [G19]
24
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 pointer (SP) y salta a la primera


corrutina */
void salto_ac1() {
AlmacenTmp=(WPointer)_SP;
_SP=(WORD)Almacen1;
}

/* 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. Compartir recursos (una computadora, varios usuarios).


2. Acelerar la ejecución (dividir un trabajo en subtrabajos que se ejecuten en paralelo).
3. 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 Swap Exclusión mutua


function Test-and-Set (var procedure Swap (var a,b: (*lock iniciado a falso*)
target: boolean): boolean; boolean); while Test-and-Set(lock)
begin var temp: boolean; do no-op;
Test-and-Set := target; begin <SC>
target := true temp := a; lock := false;
end; a := b;
b := temp;
end;

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.


Obras consultadas: [5.10] [5.33] [5.34]
25
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
PROCESO RECURSOS ASIGNADOS
NECESARIOS
P1 4 8
P2 3 7
P3 3 5
P4 0 5

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:


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

26
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.1] Weaving a Thread. Shashi Prasad. October, 1995.
http://www.byte.com/art/9510/sec12/sec12.htm [5.13] CPU SCHEDULING
http://www.cs.njit.edu/~web332/F98/CPU_scheduling/
[5.2] An Operating Systems Vade Mecum. Raphael A. cpuschd_obj.html
Finkel.University of Wisconsin at Madison
Prentice Hall [5.14] Operating systems concepts. A. Q. Davis 1999 -
2000
[5.3] Student Operating System. R. Lambert, J. http://www.personal.comp.brad.ac.uk/~aqdavis/fullInd
Homack, B. Kennedy, T. Nassif & A. Biver ex!.htm
COP 4610. Dr. Coulter 12-3-97
[5.15] Esquemas de Planificación. Angela Di Serio USB
- Sistemas Paralelos y Distribuidos. 1998
[5.4] Curso de sistemas operativos. Capitulo 10.
Procesos. http://ci.ldc.usb.ve/~spd/Docencia/ci-
3821/Tema4/node6.html
http://crysoft.com/cursos/endetalle.asp?pide=sisope&c
apitulo=10
[5.16] FCFS Scheduling
[5.5] The 'standard' cpu scheduling algorithm - A short http://www-ec.njit.edu/~yxy8776/node100.html
description of the basic cpu scheduling algorithm used
by most OSs today. [5.17] First-Come First-Served Scheduling
Pieter Dumon. 1998. http://www.personal.comp.brad.ac.uk/~aqdavis/cpu/sc
http://unios.dhs.org/std-sched.html heduling/FIFO.htm

[5.6] Sistemas operativos I. Instituto tecnologico de [5.18] Sistemas operativos. Gabriela Herrera B.
Veracruz http://www.inf.udec.cl/~sistcomp/SistOpe/
http://itver.edu.mx/so1/sistemas_operativos.htm
[5.19] Round Robin Scheduling
[5.7] CS 537 Notes, Section #4: Independent and http://megahertz.njit.edu/~wxl3226/rr.html
Cooperating Processes. Barton P. Miller. 1997.
http://www.cs.wisc.edu/~bart/537/lecturenotes/
[5.20] Round Robin CPU Scheduling
http://www.cs.njit.edu/~web332/F98/CPU_scheduling/
[5.8] Monitores, variables condición y los cpuschd_rr.html
lectores/escritores
Adaptado del original de Tom Anderson (Universidad de
[5.21] Priority scheduling
Berkeley)
http://megahertz.njit.edu/~wxl3226/pr.html

[5.9] CS 537 Notes, Section #8: Monitors. Barton P.


Miller. 1997. [5.22] Shortest-Job-First algorithm
http://www.cs.wisc.edu/~bart/537/lecturenotes/ http://megahertz.njit.edu/~pxl8936/sjf.html

[5.10] UFPS Sistemas Operativos I [5.23] Multilevel Queue Scheduling


http://bari.ufps.edu.co/personal/150802A/procesos.htm http://megahertz.njit.edu/~pxl8936/mqs.html

[5.11] Sistemas operativos. Master David Luis la Red [5.24] Multilevel Feedback Queue Scheduling
Martínez http://megahertz.njit.edu/~yxy8776/node200.html
http://exa.unne.edu.ar/depar/areas/informatica/Sistem
asOperativos/SOF.htm
[5.25] Evolutionary Computation for Scheduling
Controls in Concurrent Object-Oriented Systems.
[5.12] Scheduling Simulations. Charles Baldridge and Tzilla Elrad, Jinlong Lin & Douglas J. Cork
Karl Papadantonakis. CS414 project
IJCA, PP.11-20, Vol.5, No.3, Sept, 1998, Published by
http://www.people.cornell.edu/pages/csb11/CS414/sim
ISCA.
.html

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

[5.33] Mecanismos para evitar el interbloqueo


http://www.itver.edu.mx/so1/44.htm

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
Imagen reproducida de [6.26]
28
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 Dirección (Hex) Vector de Interrupción

Reloj 040 - 043 8


Teclado 060 - 063 9
Disco Duro 320 - 32F 13
Impresora 378 - 37F 15
Monitor Mono 380 - 3BF -
Monitor Color 3D0 - 3DF -
Disco Flexible 3F0 - 3F7 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
Subsistema
o DLL
Copia en
memoria del
Modo usuario usuario
Modo núcleo
Servicios
SW de E/S Gestor de
independiente archivos
de dispositivo Gestor de
bloques Copia en el
Gestor de sistema
SW de E/S cache operativo
independiente
de dispositivo Manejador
SW de E/S de
dependiente
dispositivo
de dispositivo

Manejador de
Software interrupción

Hardware Copia en el
Controlador controlador

Dispositivo Bloque del


(disco) 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 Contestación a


E/S de la lista la petición

Traducir a formato Preparar Operaciones


del controlador respuesta sobre datos
de error

Si No

Enviar mandatos
Error
al controlador

Programación del
controlador

No Leer registros
Bloqueo estado del
controlador

Si

Esperar Interrupción
interrupción

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

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


• 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.

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 máquina, y la ROM, que no
puede aprender nada nuevo, los dispositivos de almacenamiento secundario permiten que la
computadora registre información en forma semi-permanente, para que pueda ser leída después
por el mismo u otro computador. El almacenamiento secundario es más barato y de mayor
capacidad que el almacenamiento primario.

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 disco
Manejador Manejador Manejador … Manejador
de CD_ROM SCSI IDE 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
Controlador del
Sistema de ficheros dispositivo
[alto nivel]
Caché de
páginas de Caché de bloques
memoria
Gestor de peticiones a los discos
Planificador de los discos
Controlador de dispositivos
[bajo nivel]

Sistem a de Almac enamiento Sec undario


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.
• Secuencia de registros:
• El archivo es una secuencia de registros de longitud fija, cada uno con su
propia estructura interna.
• Árbol :
• 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.

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: nodo-
i, registro Windows, etc.

cabecera
Atributos
Tamaño
Nombre
Nombre Seguridad
Atrib.
Size KB
Agrup. FAT 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 de
dispositivo, es más común acceder dispositivos de bloque por medio de un sistema lógico de
archivos. Un sistema de archivos lógico puede ser montado en algún punto del sistema virtual de
archivos, lo que significa que el dispositivo de bloque asociado contiene archivos y estructuras de
información que permiten al sistema lógico de archivos acceder al dispositivo.

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. Aplicación
6. Proveedores de red
5. Administradores IFS
4. Redirector red Microsoft/compatible NetWare
3. Protocolo de transporte
2. NDIS.YXD
1. 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.1] Sistemas operativos: una visión aplicada. Félix [6.13] Linux Device Drivers Demystified. James
García Carballeira, et. al. 1999 Andrews
http://laurel.datsi.fi.upm.es/~ssoo/DSO/ http://www.linuxplanet.com/linuxplanet/tutorials/

[6.2] HOW TO WRITE DEVICE DRIVERS. Stephen [6.14] SISTEMAS OPERATIVOS


Williams steve@icarus.com http://server2.southlink.com.ar/vap/sistemas_operativo
http://icarus.com/linux_driver/device-driver-1.html s.htm

[6.3] [6.15] Sistemas Operativos de Red


http://ironbark.bendigo.latrobe.edu.au/subjects/bitsys/ http://www.itmorelia.edu.mx/mats-
oslect/lectlist.html dsc/sor/indice~1.html

[6.4] Plan 9: Feature Film to Feature-Rich OS. Paul [6.16] Sistemas operativos para redes punto a punto
Fillinich. March, 1996.
http://www.geocities.com/SiliconValley/8195/nospp.ht
http://www.byte.com/art/9603/sec14/sec14.htm ml

[6.5] EL UNIVERSO DIGITAL DEL IBM PC, AT Y PS/2 [6.17] Sistemas Operativos de Red y Distribuidos
Ciriaco García de Celis. Edición 4.0 http://www.lafacu.com/apuntes/informatica/Sistemas_
http://udigital.homepage.com/libro/index.html Operativos_en_Red_y_Distribuidos/default.htm

[6.6] Curso de sistemas operativos [6.18] FAMILIA DE PROTOCOLOS TCP/IP


http://lara.pue.udlap.mx/sist_oper/index.html http://www.uca.edu.sv/investigacion/tutoriales/tcp-
ip.html
[6.7] JavaOS: Thin Client, Fat Service. Charles Mirho http://members.tripod.com/~MoisesRBB/tcpip.html
and Tom Clements. July, 1997.
http://www.byte.com/art/9707/sec4/sec4.htm [6.19] PUNTONET TUTORIAL REDES
http://epuntonet.com/tu/estu_reti.htm
[6.8] Tecnología de Redes y Sistema de cableado
Estructurado Conceptos generales [6.20] La interfaz Socket
http://www.solnet.com.pe/cursos/redes_conceptos_gen http://www.lcc.uma.es/~eat/services/i_socket/i_socket.
erales/index.htm html

[6.9] Historia de Sistemas Operativos para Red y [6.21] The Box: A Replacement for Files
Porque es más fácil y económico configurar Unix que
Francisco J. Ballesteros
Windows en Red ?
http://plan9.escet.urjc.es/who/nemo/export/2kblocks/in
http://www.osmosislatina.com/diversos/mas_facil.htm
dex.html

[6.10] Introducción a los Sistemas de Información-SCI


[6.22] Pequeña introducción a los sockets
210
http://members.easyspace.com/hackuma/socketz.htm
http://www.ucb.edu.pr/SCI210/LESSONS/L5.HTM

[6.23] Conceptual Architecture of the Linux Kernel. Ivan


[6.11] ESO-SOL Práctica 3: Manejadores de dispositivo
Bowman (ibowman@sybase.com) January 1998
Ismael Ripoll, Juan Carlos Pérez, y Sergio Sáez
http://plg.uwaterloo.ca/~itbowman/CS746G/a1/

[6.12] Device Drivers. The HyperNews Linux KHG


Discussion Pages [6.24] Concrete Architecture of the Linux Kernel. Ivan
Bowman, Saheem Siddiqi , Meyer C. Tanuan.
http://khg.redhat.com/HyperNews/get/khg.html
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.26] Programación de bajo nivel. Juan Antonio


[6.25] Sistemas operativos. David Luis la Red Martínez. de la Puente. DIT/UPM. 2001
http://exa.unne.edu.ar/depar/areas/informatica/Sistem http://polaris.dit.upm.es/~jpuente/strl/transparenc
asOperativos/SOF.htm 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 Sistema Operativo


Tarjeta inteligente OSSCA, MULTOS
Dispositivos incrustados QNX, Linux, eCos, Inferno, MS Windows CE, EYRX
Teléfonos celulares y dispositivos móviles EPOC, Symbian OS, Linux
Auto PC MS Windows CE
Consolas de juegos Linux, MS, Windows, Roundtable, Sony
Handheld/PC (PDA) Palm OS, MS Windows CE, Linux
Computadora personal DOS, MS Windows (3.x, 9x, Me, XP), Mac OS, Linux, Be OS, IBM
OS/2
Estación de trabajo BSD, SCO UNIX, IRIX, Linux, MS Windows (NT, 2000), Mac OS
Servidor Sun Solaris, MS Windows (NT, 2000), Mac OS, Linux, SCO UNIX,
IBM VM/CMS, IBM z/VM, Open VMS, Sun OS,
Cluster Linux, MS Windows (2000, .Net)
Supercomputadora UNIX, Cray UNICOS, IBM AIX, SGI IRIX, OSF/1, PUMA OS

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. Qué información es la que tiene que ser procesada.


2. Qué función y rendimiento son los que se esperan.
3. Qué restricciones de diseño existen.
4. Qué interfaces deben utilizarse.
5. Qué lenguaje de programación, sistema operativo y soporte hardware van a ser
utilizados.
6. 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 Descomposición Representación


estructura gráfica
Estructura de •Componentes: módulos, asignaciones de trabajo
módulos •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
Estructura de •Componentes: tareas, procesos
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

Estructura de •Componentes: procedimientos


uso •Relaciones: “asume la presencia correcta de”
•Uso: para especificar subconjuntos y superconjuntos
•Atributos: Reusabilidad, pruebas, desarrollo incremental
Estructura de •Componentes: procedimientos o b je c t 1 o b je c t 2 o b je c tk

llamadas •Relaciones: “invoca”


•Uso: para establecer el flujo de control, para depuración
•Atributos: construcción, pruebas, mantenimiento,
comprensión

Estructura de •Componentes: programas, módulos


flujo de datos •Relaciones: “puede enviar datos a”
•Uso: para seguimiento de la funcionalidad
•Atributos: desempeño, exactitud

Estructura de •Componentes: objetos NewClass5

clases •Relaciones: “hereda de”, “es instancia de” NewClass


NewClass2
•Uso: para explotar las similaridades entre objetos
•Atributos: tiempo de desarrollo, mantenimiento 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 filtro-
tuberí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ón-
Control (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:
• Reuso de capas
• Soporta la estandarización
• Las dependencias se mantienen locales
• Intercambio
Ejemplos:
• 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

Mi cr o ke r n el
Exte rnal Server
Internal Serve r
+calls +a ctiva tes
in itC om m u nicatio n()
rece ive R equ es t()
fin dR ec eiver() 1..* r eceiveR eq u e s t()
dis p atchR e que s t() 1..* 1 1
e xe cuteMe chan is m () execu teService()
execute Se rvic e()
ca llInternalServe r()
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() +calls s ervice
crea teR eq ues t()

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:
• Transparencia en la localización
• Independencia del sistema
• Interoperabilidad y portabilidad
• Modificabilidad y reusabilidad
• Configuración a tiempo de ejecución
Ejemplos:
• 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

• ¿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.
2. ¿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?
3. ¿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?
4. ¿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?
5. ¿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?
6. ¿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?
7. ¿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?

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 de
interfaces basadas en menús en modo texto (fig. 7.13), donde se podía interactuar por medio de
un ratón en lugar de escribir el comando correspondiente en el teclado. Esto demandaba un
esfuerzo considerable de programación, y por lo general no había una manera estandarizada de
programar este tipo de interfaces.

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 modelo-
vista-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


[7.1] Argante virtual operating system http://www.nondot.org/sabre/os/articles
http://agt.buka.org/concept.html
[7.13] OS Design for Ametures (my FAQ). Brian Klock
[7.2] Introduction to Operating Systems http://www.overwhelmed.org/shawn/faq.html
Kathryn S. McKinley. University of Massachusetts .Fall
1997 [7.14] Questions For an OS Designer.
http://www-aml.cs.umass.edu/~cs377/ http://phantom.urbis.net.il/bphantom/OS_Design_Qs.ht
ml
[7.3] Write Your Own Operating System [FAQ]. Stuart
'Dark Fiber' George <dfiber@mega-tokyo.com> [7.15] Code your own OS
http://www.nondot.org/sabre/os/S9Misc/os- http://www.openbg.net/sto/os/
faq/index.html

[7.16] Write Your Own Operating System [FAQ] Stuart


[7.4] OS Design for Amatures (my FAQ). Brian Klock 'Dark Fiber' George 2001
http://www.overwhelmed.org/shawn/faq.html http://www.mega-tokyo.com/os/os-faq.html

[7.5] Applications Programming in Smalltalk- [7.17] OSFAQ.com


80(TM):How to use Model-View-Controller (MVC) Steve
http://www.osfaq.com/
Burbeck, Ph.D.
http://st-www.cs.uiuc.edu/users/smarch/st-
docs/mvc.html [7.18] Operating System Development For Dummies
(OSD) A project of the alt.os.development Usenet
discussion group
[7.6] Model View Controller
http://www.execpc.com/~geezer/osd/index.htm
http://www.object-
arts.com/EducationCentre/Overviews/MVC.htm
[7.19] Answers to frequently asked questions for
comp.os.research. Bryan O'Sullivan
[7.7] Towards a New Strategy of OS Design Thomas
Bushnell, BSG http://www.serpentine.com/~bos/os-faq/welcome.html
http://www.serpentine.com/~bos/os-faq/FAQ-1.html
http://www.gnu.org/software/hurd/hurd-paper.html
http://www.serpentine.com/~bos/os-faq/FAQ-2.html
http://www.serpentine.com/~bos/os-faq/FAQ-3.html
[7.8] The Hurd presentation by Marcus Brinkmann
http://www.gnu.org/software/hurd/hurd-talk.html
[7.20] The Triple Fault Club
http://www.execpc.com/~geezer/os/
[7.9] How operating systems work. How stuff works.
Lycos.
http://howstuffworks.lycos.com/operating-system.htm [7.21] Operating System Directions for the Next
Millennium. William J. Bolosky, Richard P. Draves,
Robert P. Fitzgerald, Christopher W. Fraser, Michael B.
[7.10] What Operating System? Who Cares! Chuck Jones, Todd B. Knoblock, Rick Rashid
Jazdzewski The Future of software. Winter 2000.
Microsoft Research One Microsoft Way Redmond WA
http://www.futureofsoftware.net/cj0010/cj0010.asp 98052
http://research.microsoft.com/research/sn/Millennium/
[7.11] Techniques for the Design of Java Operating mgoals.html
Systems. Back et al (Univ. of Utah)
http://www.cs.wpi.edu/~cs535/f00/back:usenix00/ [7.22] Strategies for the Future of System Integration
By James B. Bassich Jim.Bassich@cpu.com
[7.12] The Operating System resource center. Chris http://www.cpu.com
Lattner
[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 [7.39] Sitio www de apoyo al texto de R. Pressman.
ydisesis.shtml http://www.rspa.com/

[7.25] Operating system design & implementation - [7.40] Software Architecture and Related Concerns
tutorial.
http://www.bredemeyer.com/whatis.htm
http://www.ansawide.com/josh/index.htm

[7.41] Software Architecture: An Executive Overview


[7.26] How to Write an Operating System. SigOPS
http://www.sei.cmu.edu/publications/documents/96.rep
http://www.acm.uiuc.edu/sigops/roll_your_own/ orts/96.tr.003.html

[7.27] The Special Interest Group for Operating [7.42] Model Problems
Systems. ACM
http://www-2.cs.cmu.edu/People/ModProb/
http://www.acm.uiuc.edu/sigops/

[7.43] Software Architecture Documentation in


[7.28] What is POSIX? The Portable Application Practice: Documenting Architectural Layers
Standards Committee (PASC)
http://www.sei.cmu.edu/publications/documents/00.rep
http://www.pasc.org/#POSIX orts/00sr004.html

[7.29] The POSIX/2 Project [7.44] Introduction to the Architecture-Based Design


http://posix2.sourceforge.net/ Method" tutorial
http://www.sei.cmu.edu/plp/symposium00/ABD/current
[7.30] The Serial Programming Guide for POSIX _activities.html
Operating Systems
http://www.easysw.com/~mike/serial/serial.html [7.45] Seminario de Arquitectura de Software
http://www.dcc.uchile.cl/~cc61h/intro/index.htm
[7.31] PW32 the Posix-over-Win32 layer
http://pw32.sourceforge.net/main.html [7.46] Patrones o Estilos de Arquitectura de Software
http://www.dcc.uchile.cl/~cc61h/patrones/index.htm
[7.32] The Posix Basic Regular Expression language
http://www.delorie.com/gnu/docs/rx/rx_3.html [7.47] GNU GRUB
http://www.gnu.org/software/grub/
[7.33] Programming Posix threads
http://www.humanfactor.com/pthreads/ [7.48] The Multiboot Specification
OKUJI Yoshinori, Bryan Ford, Erich Stefan Boleyn,
[7.34] POSIX Threads Tutorial Kunihiro Ishiguro
http://www.math.arizona.edu/swig/pthreads/threads.ht http://www.mcc.ac.uk/grub/multiboot_toc.html
ml
[7.49] Multiboot Standard - Version 0.6
[7.35] Legion The Grid operating system http://www.uruk.org/orig-grub/boot-proposal.html
http://legion.virginia.edu/presentations/UMBC-Apr2001/
[7.50] 2K Motivation
[7.36] Tutorial Interactivo Programación II http://choices.cs.uiuc.edu/2k/Motivation.html
http://sistemas.ing.ula.ve/sistemas/pd20/
[7.51] Quality assurance tips
[7.37] Los Modelos Dinámicos y la Ingeniería del http://developer.apple.com/testing/docs/TNqatips.html
Software
Isabel Ramos Román, isabel.ramos@lsi.us.es [7.52] JX operating system
http://www.sc.ehu.es/jiwdocoj/remis/docs/modelos.ht http://www4.informatik.uni-erlangen.de/Projects/JX/
ml

[7.53] A Brief History of PC Operating Systems


[7.38] Introducción a la Ingeniería de Software
http://www.viewz.com/shoppingguide/os2.shtml
Lic. Yadira Esparza Rodríguez
http://www.uag.mx/66/portada.htm

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

[7.54] Operating System 2010 by Steven J. Vaughan- [7.67] WCEfA. Using Automotive Graphical User
Nichols Interface
Byte. November 5, 2001 http://msdn.microsoft.com/library/default.asp?url=/libr
http://www.byte.com/documents/s=1778/byt20011031 ary/en-us/apcguide/htm/acc_guide_1.asp
s0004/
[7.68] WCEfA. Using Automotive Speech Architecture
[7.55] The Design and Implementation of the 4.4BSD http://msdn.microsoft.com/library/default.asp?url=/libr
Operating System ary/en-us/apcguide/htm/spc_overview_1.asp
Marshall Kirk McKusick, Keith Bostic, Michael J. Karels,
John S. Quarterman [7.69] A Graphical User Interface Toolkit Approach to
Addison-Wesley Longman, Inc, 1996 Thin-Client Computing
http://www.freebsd.org/doc/en_US.ISO8859- Simon Lok, Steven K. Feiner, William M. Chiong and
1/books/design-44bsd/ Yoav J. Hirsch
http://www2002.org/CDROM/refereed/577/
[7.56] DROS
http://www.dros.com/ [7.70] Fundamentals of Swing: Part I Short Course
By MageLang Institute
[7.57] Software Architecture in Practice http://developer.java.sun.com/developer/onlineTraining
http://www.cs.vu.nl/~hansdb/state/node6.html /GUI/Swing1/shortcourse.html

[7.58] Architectural Styles, Design Patterns and [7.71] MVC meets Swing
Objects. Robert T. Monroe, Andrew Kompanek, Ralph Todd Sundsted
Melton, and David Garlan http://www.javaworld.com/javaworld/jw-04-1998/jw-
IEEE Software, January 1997, pp. 43-52. 04-howto_p.html
http://pecan.srv.cs.cmu.edu/afs/cs/project/able/www/p
aper_abstracts/ObjPatternsArch-ieee.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.73] Java Look and Feel Design Guidelines, second
edition. Copyright 2001. Sun Microsystems
[7.60] Architectural Patterns, Design Patterns, Idioms http://java.sun.com/products/jlf/ed2/book/HIGTitle.htm
http://www.tml.hut.fi/Opinnot/Tik-109.450/1998/niska/ l

[7.61] Architectural patterns [7.74] Microsoft, Apple and Xerox. The History of the
Graphical User Interface . David K. Every
http://www.opengroup.org/togaf/p4/patterns/patterns.
htm http://www.mackido.com/Interface/ui_history.html

[7.62] Layers [7.75] Mouse Site


http://home.earthlink.net/~huston2/dp/layers.html http://sloan.stanford.edu/MouseSite/

[7.63] Sistemas operativos- prácticas y apuntes [7.76] IBM Ease of use


http://www.dc.uba.ar/people/materias/so/html/practica http://www-
s.html 3.ibm.com/ibm/easy/eou_ext.nsf/publish/558

[7.64] Operating Systems Widely Used on Personal [7.77] User interface Markup Language
Computers http://www.uiml.org/index.php
http://www.abilityhub.com/information/os.htm
[7.78] GUI – Webopedia
[7.65] The X Window system http://www.webopedia.com/TERM/G/Graphical_User_I
http://www.viewtouch.com/xwindows.html nterface_GUI.html

[7.66] OPERATING SYSTEMS [7.79] Interpreter pattern


http://www.computerhope.com/os.htm http://home.earthlink.net/~huston2/dp/interpreter.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 [7.88] Mac OS X Update: Quartz & Aqua
apers/tutnotes/sld021.htm John Siracusa
http://www.arstechnica.com/reviews/1q00/macos-x-
[7.81] HCI- Webopedia gui/macos-x-gui-1.html
http://www.webopedia.com/TERM/H/HCI.html
[7.89] ACM SIGCHI Curricula for Human-Computer
[7.82] Human Interface Devices Interaction
http://www.nondot.org/sabre/os/articles/HumanInterfa http://sigchi.org/cdg/index.html
ceDevices/
[7.90] System Management Concepts: Operating
[7.83] VR Interface devices System and Devices. IBM.
http://archive.ncsa.uiuc.edu/Cyberia/VETopLevels/VR.I http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_
nterface.html lib/aixbman/admnconc/admnconctfrm.htm

[7.84] ATRC – Neural interface devices [7.91] Windows 95 System Management Architecture
http://www.utoronto.ca/atrc/reference/tech/neuralinter Windows Development Management Technical Articles
face.html July 26, 1994
http://msdn.microsoft.com/archive/default.asp?url=/arc
[7.85] Architecture of the Runtime Engine hive/en-us/dnarmgmt/html/msdn_chic_mgt.asp
http://developer.apple.com/techpubs/macosx/Carbon/g
raphics/OpenGL/OpenGL/chap2/chapter_2_section_4.ht [7.92] Web-based System Manager Administration
ml Guide. IBM.
http://publib16.boulder.ibm.com/pseries/en_US/aixbma
[7.86] User Interface Design n/wsmadmn/mastertoc.htm
Common Front Group
http://cfg.cit.cornell.edu/cfg/design/contents.html [7.93] BolinOS
http://www.med-ia.ch/med-ia/bolinos/
[7.87] GUI Gallery
http://toastytech.com/guis/

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:
• primitivas como las unidades más pequeñas (funciones aritméticas o gráficas básicas),
• componentes, y
43
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:
• Protocolo de comunicaciones cliente - servidor.

46
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

Obras consultadas: [8.25] [8.26] [8.58][8.59]
50
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
Imagen reproducida de [8.58]
52
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
Imagen reproducida de [8.58]
54
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.qvctc.commnet.edu/classes/csc277/os_arc
http://www.sanmartinbaq.edu.co/cursos/sistemas/0105 h.html
1/guia05.html
[8.13] Palm OS platform
[8.2] Virtual Virtual Machines. Bertil Folliot, Ian http://www.palmos.com/platform/architecture.html
Piumarta, Fabio Riccard. Projet SOR, INRIA
Rocquencourt, B.P. 105, 78153 Le Chesnay Cedex,
[8.14] Kadak AMX RTOS
France.
http://www.kadak.com/html/kdkp2500.htm
http://www-sor.inria.fr/publi/HTML/VVM_radical97/
http://www-sor.inria.fr/publi/VVM_radical97.html
[8.15] ISE2 Literature Review : Article1. Distributed
Real-time Applications and their Operating Systems.
[8.3] Object Orientation in Operating Systems Sarfraz Bacchus
Michael Lazebnik. May 1997, Rutgers University http://www.iis.ee.ic.ac.uk/~frank/surp98/article1/sb19/
Email:mxl5294@megahertz.njit.edu
[8.16] CS134c Computing Systems Laboratory, 2001.
[8.4] Sistema de Computación para un Sistema Instructor: Jason Hickey Caltech Computer Science
Operativo Orientado a Objetos basado en una Máquina Department
Abstracta Orientada a Objetos Reflectiva http://www.cs.caltech.edu/cs134/cs134c/index.html
http://www3.uniovi.es/~oviedo3/so4/concurrencia.html
[8.17] An Overview of Projects on Distributed
[8.5] JavaOS: Thin Client, Fat Service. Charles Mirho Operating Systems
and Tom Clements .Byte. July 1997. Alfred J. Lupper Computer Science Department,
http://www.byte.com/art/9707/sec4/art4.htm Distributed Systems Laboratory University of Ulm
http://www-vs.informatik.uni-
ulm.de/DOSinWWW/DistribSys.html
[8.6] QNX Forges Ahead. Peter D. Varhol. October,
1994.
http://www.byte.com/art/9410/sec14/sec14.htm [8.18] Related Work in Adaptive Operating Systems.
Crispin Cowan
http://www.cse.ogi.edu/DISC/projects/synthetix/related
[8.7] An Architectural Overview of QNX. Dan
.html
Hildebrand, Senior Architect (danh@qnx.com)
QNX Software Systems Ltd.
[8.19] A Detailed Description of Off++, a Distributed
Adaptable kernel
[8.8] QNX Neutrino OS. Francisco J. Ballesteros Fabio Kon Roy H. Campbell.
http://qdn.qnx.com/support/docs/qnx_neutrino/index.h Department of Computer Science, University of Illinois
tml at Urbana-Champaign August, 1997
http://gsyc.escet.urjc.es/off/dd.html
[8.9] Inside Mac OS X - System overview
http://developer.apple.com/techpubs/macosx/SystemO [8.20] Synthetix project
verview/SystemOverview/SystemOverview.pdf
http://www.cse.ogi.edu/DISC/projects/synthetix/

[8.10] MIT Exokernel Operating System


[8.21] Incremental specialization: the key to high
March 5, 1998 performance, modularity and portability in operating
http://www.pdos.lcs.mit.edu/exo.html systems. C. Consel, C. Pu, and J. Walpole
In ACM Symposium on Partial Evaluation and
Semantics-Based Program Manipulation (PEPM '93),
[8.11] IBM Research work on Operating Systems pages 44-46, 1993. Invited paper.
http://www.research.ibm.com/compsci/os/index.html http://www.irisa.fr/lande/consel/papers/inc-spec.ps.gz

[8.12] Operating System Architecture. Michael Lynch. [8.22] Adaptive Distributed Computing. Ray Ozzie The
1999 future of software. Winter 2000.
http://www.futureofsoftware.net/ro0010/ro0010.asp

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

[8.23] Operating System Services For Wide Area [8.35] Conceptual Architecture of the Linux Kernel. Ivan
Applications,'' Amin Vahdat. November 1998. Bowman (ibowman@sybase.com) January 1998
PhD Dissertation, Department of Computer Science, http://plg.uwaterloo.ca/~itbowman/CS746G/a1/
University of California, Berkeley
http://www.cs.duke.edu/~vahdat/ps/thesis.pdf
[8.36] Concrete Architecture of the Linux Kernel. Ivan
Bowman (ibowman@sybase.com), Saheem Siddiqi
[8.24] WebOS: Operating System Services for Wide (s4siddiqi@neumann), Meyer C. Tanuan
Area Applications (mtanuan@descartes.com). Department of Computer
http://www.cs.duke.edu/ari/issg/webos/ Science, University of Waterloo. Winter 1998
http://plg.uwaterloo.ca/~itbowman/CS746G/a2
[8.25] Exokernels (or, making the operating system just
another application library) [8.37] Real-Time Mach OS. Real-Time and Multimedia
http://amsterdam.lcs.mit.edu/exo/exo-slides/index.htm Laboratory in the Department of Computer Science at
Carnegie Mellon University
http://www-2.cs.cmu.edu/afs/cs/project/art-6/www/
[8.26] The exokernel operating system architecture
Dawson R. Engler PhD CSE Thesis MIT 1998
[8.38] MACH - An example of a Distributed Operating
System . Ken Kellow
[8.27] Architectural Styles, Design Patterns and
http://www.rit.edu/~kjk2135/MACH.html
Objects. Robert T. Monroe, Andrew Kompanek, Ralph
Melton, and David Garlan
IEEE Software, January 1997, pp. 43-52. [8.39] Resource Kernel and Services. Raj Rajkumar
http://pecan.srv.cs.cmu.edu/afs/cs/project/able/www/p http://www-2.cs.cmu.edu/afs/cs/project/art-
aper_abstracts/ObjPatternsArch-ieee.html 6/www/Overview97/index.htm

[8.28] AgentOS: The Agent-based Distributed [8.40] ChorusOS


Operating System for Mobile Networks. Larry T. Chen http://www.sun.com/chorusos/
http://www.acm.org/crossroads/espanol/xrds5-
2/agentos.html [8.41] Sun™ Embedded Telecom Platform - Combining
the Power of Solaris Computing with the Real-Time
[8.29] Go! - Genuine Componentisation of the Performance of the ChorusOS™ Operating System
Operating System White Paper
http://www.soi.city.ac.uk/~gel/go/overview.html http://www.sun.com/software/chorusos/wp-
emb.telecom.platform/index.html
[8.30] 3-D Visual Operating System
http://atwww.hhi.de/blick/3-D_Visual_OS/3- [8.42] Metodologias informáticas- Arquitectura cliente-
d_visual_os.html servidor
http://www.inei.gob.pe/cpi-
mapa/bancopub/libfree/lib616/INDEX.HTM
[8.31] Lo básico de UNIX
Vicente González Ruiz . 1998
[8.43] Distributed Operating Systems
http://www.ace.ual.es/~vruiz/docencia/cursos/linux/ht
ml/node1.html http://www.cs.arizona.edu/people/bridges/os/distribute
d.html

[8.32] An Overview of the UNIX* Operating System


[8.44] Fluke: Flux µ-kernel Environment
Bell Labs innovations history
http://www.cs.utah.edu/flux/fluke/html/
http://www.bell-labs.com/history/unix/tutorial.html

[8.45] The Globe project


[8.33] Unix history
http://www.cs.vu.nl/~steen/globe/
http://perso.wanadoo.fr/levenez//unix/

[8.46] Mac OS X System architecture


[8.34] An Introduction to the Linux Operating System
Architecture http://developer.apple.com/macosx/architecture/#
Meyer C. Tanuan, (mtanuan@descartes.com).
Department of Computer Science, University of [8.47] Mac OS X Development
Waterloo. CS 746G, Winter 1998, 27-Jan-98 http://developer.apple.com/macosx/

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

[8.48] Darwin Documentation [8.56] The Foundations of Microsoft Windows NT


http://www.opensource.apple.com//projects/document System Architecture
ation/howto/ Microsoft Corporation, September 1997
http://msdn.microsoft.com/archive/default.asp?url=/arc
[8.49] Apple Open Source Projects - Darwin hive/en-us/dnarwbgen/html/msdn_ntfound.asp
http://www.opensource.apple.com//projects/darwin/
[8.57] The X window system
[8.50] Mac OS X - An overview for developers http://www.northants.lug.org.uk/meetings/notes/x-
talk/arch.html
http://developer.apple.com/macosx/pdf/macosx_overvi
ew.pdf
[8.58] Exokernels (or, making the operating system just
another application library). F. Kaashoek, G. Ganger, H.
[8.51] A Big Day for Mac Fans. Cade Metz. PC
Briceño, R. Hunt, D. Mazières, T. Pinckney, J. Jannotti
Magazine, March 23, 2001 12:46 PM PT
http://www5.zdnet.com/zdnn/stories/news/0,4586,270 MIT Lab for Computer Science. 1998.
0598,00.html http://amsterdam.lcs.mit.edu/exo/exo-slides/index.htm

[8.52] HISTORY OF APPLE™ MACINTOSH™ [8.59] Exokernel: an operating system architecture for
OPERATING SYSTEM application-level resource management. Dawson R.
http://perso.club-internet.fr/jctrotot/Perso/History.html Engler, M. Frans Kaashoek and James O’Toole Jr.
M.I.T. Laboratory for Computer Science. 1995.
[8.53] SciNet - ISTP Perceptual OS http://citeseer.nj.nec.com/engler95exokernel.html
http://www.scinet-
corp.com/associates/index.htm?rsi.htm~index2

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. Steve Ciarcia.
A. Silberschatz, J. Peterson, P. Galvin. Byte books/ McGraw-Hill. 1981.
Addison Wesley. 1991.
ISBN 0-201-54873-9 [G12] An Operating Systems Vade Mecum
Raphael A. Finkel.University of Wisconsin at Madison
[G2] Computer systems Prentice Hall
J. Stanley Warfold
Jones & Bartlett. 1999. [G13] Conceptos de sistemas operativos.
ISBN 0-7637-0794-5 José Torres Jiménez. Trillas.
ISBN 968-24-5959-1
[G3] Sistemas operativos. Diseño e implementación.
Andrew S. Tanenbaum. [G14] El proceso unificado de desarrollo de software
Prentice-Hall. 1988. Ivar Jacobson, Graidy Booch & James Rumbaugh
ISBN 968-880-153-4 Addison Wesley, 2000
ISBN 84-7829-036-2
[G4] Sistemas operativos. Conceptos y diseño.
Milan Milenkovic. McGraw-Hill. 1987. [G15] Inside Microsoft Windows CE
ISBN 0-07-041920-5 John Murray
Microsoft press. 1998.
[G5] Trends in operating system design. ISBN 1-57231-854-6
Peter D. Varhol.
Dr. Dobb's Journal, May 1994. [G16] Operating systems. A systematic view.
William S. Davis
[G6] RTMK: A real-time microkernel. Addison-Wesley publishing Co. 1987.
J.F. Bortolotti, P. Bernard and E. Bouchet. ISBN 0-201-11185-3
Dr. Dobb's Journal, May 1994.
[G17] Computer organization & design. The
[G7] MMURTL: Your own 32-bit operating system. hardware/software interface.
Richard Burgess. David A. Patterson & John L. Hennessy
Dr. Dobb's Journal, May 1994. Morgan Kaufmann Publishers. 1998.
ISBN 1-55860-428-6
[G8] Fundamentals of operating systems.
A. M. Lister. [G18] Introducción a la computación.
MacMillan Publishers. 1984. Jorge Vasconcelos Santillán.
ISBN 0-333-37097-X Publicaciones Patria Cultural. 1999.
ISBN 9684398735
[G9] Operating systems theory.
Edward G. Coffman Jr., Peter J. Denning. [G19] Diseño de un sistema de multiprogramación CPU.
Prentice-Hall. 1973. Héctor Bolívar Olmos Ramirez, Héctor Ruiz Barradas.
ISBN 0-13-637868-4 Universidad Autónoma Metropolitana – Azcapotzalco.
2000. ISBN 970-654-677-4
[G10] Distributed operating systems: The logical
design. [G20] Avances en informática y computación
A. Goscinski. Addison-Wesley. 1991. Editores: Juan Humberto Sossa Azuela, María de
ISBN 0-201-41704-9 Lourdes Sánchez Guerrero.
XV CONGRESO NACIONAL Y I CONGRESO
INTERNACIONAL DE INFORMÁTICA Y COMPUTACIÓN
[G11] Construya una microcomputadora basado en el
Z80. pp. 371-380. Octubre, 2002.

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

[G22] Serious play. How the world’s best companies


[G21] Sistemas distribuidos. Conceptos y diseño. simulates to innovate. Michael Schrage. Hardvard
George Couloris, Jean Dollimore, Tim Kindberg. Addison business school press. 2000.
Wesley. 2001 ISBN 0-87584-814-1
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 o fórmula para resolver un problema. La
palabra se deriva del nombre del matemático árabe Al-Juarismi (825 DC). Un programa de
ordenador puede considerarse como un algoritmo elaborado. En matemáticas o ciencia
informática, un algoritmo generalmente es un pequeño procedimiento que resuelve un problema
recurrente.

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

56
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

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 ax, 0x7C0


mov ds, ax
mov es, ax
mov fs, ax
mov gs, 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 ; Put stack at 0x90000


mov ss, ax
mov sp, 0
sti ; Enable interrupts

l1:
push ds
mov dl, 0 ; Reset disk controller
mov ax, 0
int 13h
pop ds
jc fail

push es

mov ax,0x1000 ; ES:BX = 10000


mov es,ax
mov bx, 0

mov ah, 2 ; Read disk sectors


mov al, 5 ; read 5 sectors
mov cx, 2 ; Cylinder=0, sector=2
mov dx, 0 ; head=0, drive=0
int 13h ; ES:BX = data from disk

pop es

jc l1

mov ax,0x1000 ; set segment registers and jump


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

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: ; Just 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

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 ;location where kernel is
loaded
mov ds, ax
mov es, ax

cli
mov ss, ax ;stack segment
mov sp, 0xFFFF ;stack pointer at 64k limit
sti

mov si, strWelcomeMsg ;load message


call _disp_str

mov ah, 0x00


int 0x16 ; await keypress using BIOS
service
int 0x19 ; reboot

_disp_str:
lodsb ; load next character
or al, al ; test for NUL character
jz .DONE
mov ah, 0x0E ; BIOS teletype
mov bh, 0x00 ; display page 0
mov bl, 0x07 ; text attribute
int 0x10 ; invoke BIOS
jmp _disp_str
.DONE:
ret

[SEGMENT .data]
strWelcomeMsg db "Welcome to JOSH!", 0x00

[SEGMENT .bss]

;********************end of the kernel code********************

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 void setReg(int id, int regValue);


public int getReg(int id);
public void incReg(int id, int increment);
public 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, int y){


return x-y;
}
public int mul(int x, int y){
return x*y;
}
public int div(int x, int y){
return x/y;
}
public int mod(int x, int y){
return x%y;
}
public int shr(int x, int y){
return x>>y;
}
public int shl(int x, int y){
return x<<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 Memory {
public void setMemLoc(int adr, Object value);
public Object getMemLoc(int adr);
public 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 int partitionSize; //tamaño de la partición


private int partitionStartAdress; //dirección de inicio de la partición
private int partitionStatus; //edo. de la partición (0-libre)
private int processId; //id. del proceso alojado en la partición

/**
* 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 ProcessList plist;


private Dispatcher disp;
private ScheduleStrategy sched;
private 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; //ningun proceso despachado
}

public void dispatchCPU(CPUnit cpu) {


localCPU=cpu;
}

/**
* 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, j_ss, unsigned j_flag, j_cs;
unsigned j_ip, j_bp;
unsigned j_di, j_es;
unsigned j_si, j_ds;
} jmp_buf[1];

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; /* Prioridad del proceso.*/


};

typedef struct PCS *PROCESS; /*Apuntador al PCS*/

/* 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 /*tama¤o del stack para cada proceso*/

unsigned _stklen=20; /*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 "RTMK.H"
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <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

También podría gustarte