Está en la página 1de 812

00 MAQ. PRELIMI(F0694).

indd ii 8/10/07 12:35:38 AM


SISTEMAS
OPERATIVOS

00 MAQ. PRELIMI(F0694).indd i 8/10/07 12:35:37 AM


00 MAQ. PRELIMI(F0694).indd ii 8/10/07 12:35:38 AM
2
Segunda edición

SISTEMAS
OPERATIVOS

Dhananjay M. Dhamdhere
Indian Institute of Technology, Mumbai

Revisor técnico
Jorge Valeriano Assem
Universidad Nacional Autónoma de México

MÉXICO • BOGOTÁ • BUENOS AIRES • CARACAS • GUATEMALA • LISBOA


MADRID • NUEVA YORK • SAN JUAN • SANTIAGO
AUCKLAND • LONDRES • MILÁN • MONTREAL • NUEVA DELHI
SAN FRANCISCO • SINGAPUR • SAN LUIS • SIDNEY • TORONTO

00 MAQ. PRELIMI(F0694).indd iii 8/10/07 12:35:38 AM


Director Higher Education: Miguel Ángel Toledo C.
Director editorial: Ricardo del Bosque A.
Editor sponsor: Pablo Eduardo Roig V.
Editora de desarrollo: Ana Laura Delgado R.
Supervisor de producción: Zeferino García G.

Traducción: Thomas W. Bartenbach


Hugo Villagómez Velázquez
Raúl Arrioja Juárez

SISTEMAS OPERATIVOS
Segunda edición

Prohibida la reproducción total o parcial de esta obra,


por cualquier medio, sin la autorización escrita del editor.

DERECHOS RESERVADOS © 2008, respecto a la segunda edición en español por


McGRAW-HILL/INTERAMERICANA EDITORES, S.A. de C.V.
A Subsidiary of The McGraw-Hill Companies, Inc.
Edificio Punta Santa Fe
Prolongación Paseo de la Reforma 1015, Torre A
Piso 17, Colonia Desarrollo Santa Fe,
Delegación Álvaro Obregón
C.P. 01376, México, D. F.
Miembro de la Cámara Nacional de la Industria Editorial Mexicana, Reg. Núm. 736

ISBN-13: 978-970-10-6405-4
ISBN-10: 970-10-6405-4

Traducido de la segunda edición de: Operating Systems. A Concept-based Approach.


Copyright © MMVI by Tata McGraw-Hill Publishing Company Limited.
All rights reserved

ISBN: 0-07-061194-7

1234567890 09765432108

Impreso en México Printed in Mexico

00 MAQ. PRELIMI(F0694).indd iv 8/10/07 12:35:38 AM


A
mi esposa Snehalata

00 MAQ. PRELIMI(F0694).indd v 8/10/07 12:35:38 AM


00 MAQ. PRELIMI(F0694).indd vi 8/10/07 12:35:38 AM
Contenido
Acerca del autor xiii
Prefacio xv
1 Introducción 1
1.1 Visión abstracta del sistema operativo 1
1.2 Metas de un sistema operativo 5
1.3 La operación de un sistema operativo 7
1.4 Panorama preliminar del libro 16
Ejercicio 1 23
Bibliografía 25

Parte I
Conceptos fundamentales
2 Visión general de los sistemas operativos 31
2.1 El sistema operativo y el sistema de cómputo 31
2.2 La eficiencia, el desempeño de sistema y la conveniencia del usuario 46
2.3 Las clases de sistemas operativos 49
2.4 Los sistemas de proceso por lotes 52
2.5 Sistemas de multiprogramación 56
2.6 Los sistemas de tiempo compartido 65
2.7 Sistemas operativos de tiempo real 71
2.8 Los sistemas operativos distribuidos 73
2.9 Los sistemas operativos modernos 75
Ejercicio 2 77
Bibliografía 80
3 Los procesos y los hilos 84
3.1 Los procesos y los programas 84
3.2 El punto de vista del programador sobre los procesos 87
3.3 La visión del sistema operativo de los procesos 92
3.4 Los hilos 106
3.5 Estudios de casos de procesos y de hilos 115
3.6 Procesos interactuantes: una vista avanzada del programador de los procesos 130
Ejercicio 3 139
Bibliografía 141
4 Planificación 143
4.1 Preliminares 143
4.2 Políticas de planificación no priorizante 148
4.3 Políticas de planificación priorizante 151
4.4 La planificación en la práctica 156
4.5 Planificación en tiempo real 168
4.6 Planificación en Unix 175

00 MAQ. PRELIMI(F0694).indd vii 8/10/07 12:35:38 AM


viii Contenido

4.7 Planificación en Linux 178


4.8 Planificación en Windows 181
4.9 Análisis de desempeño de las políticas de planificación 181
Ejercicio 4 186
Bibliografía 188
5 Administración de la memoria 191
5.1 Administración de la jerarquía de la memoria 191
5.2 Asignaciones estática y dinámica de la memoria 193
5.3 Asignación de memoria a un proceso 196
5.4 Reúso de la memoria 202
5.5 Asignación de memoria contigua 211
5.6 Asignación de memoria no contigua 213
5.7 Paginamiento 217
5.8 Segmentación 219
5.9 Segmentación con paginamiento 220
5.10 Asignación de memoria por el kernel 221
5.11 Repaso de relocalización, ligamiento y formas del programa 226
Ejercicio 5 233
Bibliografía 235
6 Memoria virtual 237
6.1 Fundamentos de la memoria virtual 237
6.2 Paginamiento por demanda 240
6.3 Políticas de reemplazo de página 266
6.4 Asignación de memoria a un proceso 275
6.5 Páginas compartidas 279
6.6 Archivos mapeados en la memoria 282
6.7 Memoria virtual Unix 284
6.8 Memoria virtual Linux 288
6.9 Memoria virtual en Windows 290
6.10 Memoria virtual usando segmentación 291
Ejercicio 6 295
Bibliografía 299
7 Sistema de archivos 302
7.1 Sistema de archivos e IOCS 302
7.2 Archivos y operación de archivos 305
7.3 Organizaciones fundamentales de archivos 307
7.4 Estructuras de directorio 311
7.5 Protección de archivos 318
7.6 Interfaz entre el sistema de archivos y el IOCS 319
7.7 Asignación de espacio de disco 322
7.8 Implementación del acceso a archivos 326
7.9 Semántica para compartir archivos 331
7.10 Confiabilidad del sistema de archivos 333
7.11 Sistema de archivos virtuales 341

00 MAQ. PRELIMI(F0694).indd viii 8/10/07 12:35:39 AM


Contenido ix

7.12 Sistema de archivos de Unix 343


7.13 Sistema de archivos Linux 348
7.14 Sistema de archivos Windows 348
7.15 Desempeño de los sistemas de archivos 350
Ejercicio 7 352
Bibliografía 355
8 Seguridad y protección 357
8.1 Visión general de seguridad y protección 357
8.2 Objetivos de la seguridad y de la protección 360
8.3 Ataques a la seguridad 362
8.4 Aspectos formales y prácticos de la seguridad 364
8.5 Cifrado 366
8.6 Autentificación y seguridad de la contraseña 373
8.7 Descriptores de acceso y matriz de control de acceso 375
8.8 Estructuras de protección 377
8.9 Capacidades 382
8.10 Seguridad Unix 390
8.11 Seguridad Linux 391
8.12 Seguridad Windows 392
Ejercicio 8 394
Bibliografía 395

Parte II
Tópicos avanzados
9 Sincronización de procesos 403
9.1 La sincronización de acceso a datos y la sincronización de controles 403
9.2 Secciones críticas 404
9.3 Condiciones de ejecución en la sincronización de controles 409
9.4 La implementacion de secciones críticas y operaciones indivisibles 411
9.5 Problemas clásicos de la sincronización de procesos 414
9.6 Estructura de sistemas concurrentes 421
9.7 El planteamiento algorítmico para la implementación de secciones críticas 423
9.8 Semáforos 431
9.9 Regiones críticas condicionadas 443
9.10 Monitores 447
9.11 La sincronización de procesos en Unix 456
9.12 La sincronización de procesos en Linux 457
9.13 La sincronización de procesos en Windows 458
Ejercicio 9 459
Bibliografía 463
10 Paso de mensajes 466
10.1 Vista de conjunto del paso de mensajes 466
10.2 Implementar el paso de mensajes 470

00 MAQ. PRELIMI(F0694).indd ix 8/10/07 12:35:39 AM


x Contenido

10.3 Buzones 474


10.4 Paso de mensajes en Unix 476
10.5 El paso de mensajes en Windows 480
Ejercicio 10 481
Bibliografía 482
11 Bloqueos mutuos 483
11.1 Definición del bloqueo mutuo 483
11.2 Bloqueos mutuos en la asignación de recursos 484
11.3 El manejo de bloqueos mutuos 490
11.4 Detección y resolución de bloqueos mutuos 491
11.5 Prevención de bloqueos mutuos 496
11.6 Cómo evitar los bloqueos mutuos 500
11.7 Caracterización formal de bloqueos mutuos de recursos 506
11.8 Manejo del bloqueo mutuo en la práctica 513
Ejercicio 11 515
Bibliografía 518
12 Implementación de operaciones de archivos 520
12.1 Capas del sistema de control entrada salida 520
12.2 Visión general de la organización de E/S 523
12.3 Dispositivos de E/S 525
12.4 E/S de nivel de dispositivo 537
12.5 Planificación del disco 551
12.6 Almacenamiento temporal de registros 554
12.7 Bloqueo de registros 559
12.8 Métodos de acceso 562
12.9 Caché de disco unificada 564
12.10 Procesamiento de archivos en Unix 565
12.11 Procesamiento de archivos en Linux 568
12.12 Procesamiento de archivos en Windows 569
Ejercicio 12 571
Bibliografía 573
13 Sincronización y planificación en sistemas operativos multiprocesador 576
13.1 La arquitectura de sistemas multiprocesadores 576
13.2 Sistemas operativos multiprocesadores 583
13.3 Estructura del kernel 584
13.4 Sincronización de procesos 587
13.5 Planificación de procesos 591
13.6 Estudio de caso real 593
Ejercicio 13 596
Bibliografía 597
14 La estructura de los sistemas operativos 599
14.1 Operación de un SO 600
14.2 Estructura de un sistema operativo 601
14.3 Sistemas operativos con estructura monolítica 603

00 MAQ. PRELIMI(F0694).indd x 8/10/07 12:35:39 AM


Contenido xi

14.4 El diseño por capas de sistemas operativos 604


14.5 Sistemas operativos de máquina virtual 607
14.6 Sistemas operativos basados en el kernel 610
14.7 Sistemas operativos basados en microkernel 612
14.8 Configuración e instalación del kernel 614
14.9 Arquitectura de Unix 615
14.10 El kernel de Linux 617
14.11 Arquitectura de Windows 618
Ejercicio 14 619
Bibliografía 619

Parte III
Sistemas operativos distribuidos
15 Sistemas operativos distribuidos 625
15.1 Características de sistemas distribuidos 625
15.2 Nodos de sistemas distribuidos 627
15.3 Sistemas operativos de red 627
15.4 Sistemas operativos distribuidos 628
15.5 Comunicación interproceso confiable 631
15.6 Paradigmas de computación distribuidos 637
15.7 Realización de redes (Networking) 644
15.8 Modelo de un sistema distribuido 657
15.9 Cuestiones de diseño en sistemas operativos distribuidos 659
Ejercicio 15 661
Bibliografía 662
16 Problemas teóricos en sistemas distribuidos 664
16.1 Nociones de tiempo y estado 665
16.2 Estados y eventos en un sistema distribuido 665
16.3 Precedencias de tiempo, relojes y eventos 666
16.4 Registrar el estado de un sistema distribuido 672
Ejercicio 16 680
Bibliografía 682
17 Algoritmos de control distribuido 684
17.1 Operación de algoritmos de control distribuido 684
17.2 Corrección de algoritmos de control distribuido 686
17.3 Exclusión mutua distribuida 688
17.4 Manejo del bloqueo mutuo distribuido 693
17.5 Algoritmos de planificación distribuida 698
17.6 Detección de terminación distribuida 701
17.7 Algoritmos de elección 703
17.8 Asuntos prácticos en el uso de algoritmos de control distribuido 705
Ejercicio 17 707
Bibliografía 708

00 MAQ. PRELIMI(F0694).indd xi 8/10/07 12:35:39 AM


xii Contenido

18 Recuperación y tolerancia de fallas 710


18.1 Fallas, averías y recuperación 711
18.2 Fallas bizantinas y protocolos de acuerdo 714
18.3 Recuperación 715
18.4 Técnicas de tolerancia de fallas 717
18.5 Resiliencia 721
Ejercicio 18 722
Bibliografía 723
19 Sistemas de archivos distribuidos 725
19.1 Asuntos de diseño en sistemas de archivos distribuidos 725
19.2 Transparencia 728
19.3 Semántica de compartición de archivos 729
19.4 Tolerancia de fallas 730
19.5 Desempeño de DFS 735
19.6 Estudios de casos reales 740
Ejercicio 19 747
Bibliografía 748
20 Seguridad de archivos distribuidos 750
20.1 Problemas de seguridad en sistemas distribuidos 750
20.2 Seguridad de mensajes 753
20.3 Autentificación de datos y mensajes 760
20.4 Autentificación por terceros 762
Ejercicio 20 768
Bibliografía 769
Índice analítico 770

00 MAQ. PRELIMI(F0694).indd xii 8/10/07 12:35:40 AM


Acerca del autor
Dhananjay Dhamdhere es profesor y ex director del Departamento de Ciencias de la Computación e Ingeniería
del Indian Institute of Technology (IIT) de Bombay. Durante más de treinta años ha impartido cursos de siste-
mas operativos, lenguajes de programación y compiladores, a nivel de licenciatura y de posgrado, en universi-
dades de India y Estados Unidos.
El autor ha publicado libros y artículos especializados sobre algoritmos distribuidos para los sistemas
operativos y optimización de compiladores, y ha recibido apoyo para investigación de Sun Microsystems,
Microsoft e Intel. Además, es consultor con diversas compañías de tecnologías de la información, como Tata
Consultancy Services y Wipro.

00 MAQ. PRELIMI(F0694).indd xiii 8/10/07 12:35:40 AM


00 MAQ. PRELIMI(F0694).indd xiv 8/10/07 12:35:40 AM
Prefacio
El objetivo principal de un primer curso sobre este tema es desarrollar una comprensión de los conceptos
y las técnicas fundamentales de los sistemas operativos. Actualmente, una gran porción de estudiantes ya está
expuesta a información diversa sobre los sistemas operativos debido al acceso práctico a los mismos y a la
literatura existente en el Internet; estos estudiantes tienen mucha información pero pocos conceptos acerca de
los sistemas operativos. Tal situación hace que la enseñanza de estos conceptos sea un reto; por un lado, es ne-
cesario remodelar los conceptos en la información presentada a estos estudiantes a fin de no aburrirlos; y, por el
otro, hacerlo de manera que se introduzcan los conceptos a los alumnos aprendices de los sistemas operativos,
sin espantarlos. Este libro presenta los conceptos y las técnicas de los sistemas operativos de modo que se in-
corporan los requerimientos citados.

Enfoque general

El libro comienza con la formación de un núcleo de conocimientos sobre lo que hace funcionar a un sistema
operativo, expuestos en el capítulo 2. Se presenta a un sistema operativo como un intermediario entre un sis-
tema de cómputo y los cálculos de los usuarios, cuya tarea es suministrar un buen servicio a éstos y alcanzar
un uso eficiente del sistema de cómputo. Un estudio de la interacción de un sistema operativo con el sistema
de cómputo, por un lado, y con los cálculos del usuario, por el otro, consolida esta visión y le añade detalles
prácticos. Este enfoque tiene el efecto de desmitificar al sistema operativo para el lector nuevo, y adaptarlo a la
formación de un lector experimentado. También enfatiza los aspectos clave de la arquitectura de computadoras,
esenciales para el estudio de los sistemas operativos. Esta parte del libro suministra una base para el estudio de
los detalles de las funciones que realiza un sistema operativo más a fondo.
El resto del libro sigue un enfoque análogo. Cada capítulo identifica conceptos fundamentales incluidos en
alguna funcionalidad de un sistema operativo, describe aspectos relevantes de la arquitectura de computadoras,
estudia técnicas relevantes de los sistemas operativos e ilustra su operación a través de ejemplos. Los aspectos
más importantes de este enfoque son:

• Los conceptos fundamentales se introducen mediante términos sencillos.


• Se incluyen numerosos ejemplos con el fin de ilustrar los conceptos y las técnicas.
• Se organizan detalles de implementación y de casos de estudio como cápsulas pequeñas diseminadas a
lo largo del texto.
• Secciones optativas son dedicadas a temas avanzados; por ejemplo, la caracterización del bloqueo mu-
tuo, la asignación de la memoria de núcleo, la sincronización y la programación en los sistemas de
multiprocesos, la semántica para compartir archivos, la confiabilidad y las capacidades de un sistema
de archivos.

La principal ventaja de este enfoque es que los conceptos, las técnicas y los casos de estudio se integran en
capítulos coherentes. Así, muchos detalles de diseño y de implementación parecen “obvios” cuando el lector
los encuentra. Este hecho ayuda a enfatizar la idea de que el estudio de los sistemas operativos debe basarse en
una comprensión sólida de los conceptos. Éste es el mensaje más importante que un texto puede dar a un estu-
diante de sistemas operativos, quien enfrentará tanto una rica diversidad como rápidos cambios en los sistemas
operativos durante su carrera.

00 MAQ. PRELIMI(F0694).indd xv 8/10/07 12:35:40 AM


xvi Prefacio

Aspectos pedagógicos

Parte I Parte Introducción


Cada parte del libro comienza con una
descripción de su contenido y con un
Conceptos fundamentales mapa de caminos de los capítulos que
incluye.

Un sistema operativo controla el uso de los recursos de un sistema de cómputo, tales como los
CPU, la memoria y los dispositivos de E/S a fin de satisfacer los requerimientos computacionales
de los usuarios. Éstos esperan conveniencia, calidad de servicio y seguridad al ejecutar sus pro-
gramas, mientras que los administradores del sistema esperan un uso eficiente de los recursos de
la computadora y un buen desempeño al ejecutar los programas de los usuarios. Estas diversas
expectativas se conocen como la conveniencia del usuario, la seguridad y el uso eficiente de
los recursos, y forman las metas principales de un sistema operativo. El grado hasta el cual el
sistema operativo satisface estas metas depende del ambiente de cómputo, es decir, del hardware
del sistema de cómputo, sus interfaces con otras computadoras y la naturaleza de los cómputos
realizados por los usuarios.

Figuras y cuadros
Las figuras ilustran disposiciones prácti-
cas empleadas para manejar los cálculos
Evento
del usuario y el uso de los recursos, la
Contexto de salvar
operación paso a paso de técnicas es-
Manipulación de eventos pecíficas, o la comparación de técnicas
Planificación
alternas para proyectar sus fortalezas y
debilidades. Los cuadros se usan para
Despacho
encerrar aspectos clave de las funcio-
Figura 3.5 Funciones fundamentales para los procesos de control. nalidades del sistema operativo que se
esté estudiando. También sirven como
panorama general o como resúmenes de
temas específicos

Secuencia de programas individuales Cada programa individual en la secuencia es ini- Ejemplos


ciado por el usuario a través de un comando separado. Sin embargo, una secuencia de programas
individuales tiene su propia semántica: un programa deberá ejecutarse sólo si los progra-
mas previos en la secuencia se ejecutaron con éxito. Para lograr una meta común, los programas Los ejemplos muestran los aspectos cla-
explícitamente deben hacer interfaz de las entradas y las salidas con otros programas de la se-
cuencia. El ejemplo 1.1 analiza la noción de secuencia de programas individuales en el sistema
ve relativos a los conceptos y las técni-
operativo de disco de Microsoft Corp (MS DOS). cas que se estudian. Están impresos en
Ejemplo 1.1 El archivo .bat del MS DOS, puede usarse para formar una secuencia de programas
individuales. Contiene una secuencia de comandos y cada comando indica la ejecución de un pro-
un estilo diferente para distinguirlos del
grama. En el caso de un archivo .bat que contiene comandos para iniciar una secuencia de
programas para compilar, ligar y ejecutar un programa en C: el compilador de C compila un pro-
cuerpo principal del texto. Esta opción
grama en C existente en el archivo alfa.c, el ligador liga la salida del compilador para generar
un programa ejecutable nombrado demo y el programa demo se ejecuta con los datos contenidos en ayuda al lector a no detenerse en un
el archivo muestra. El intérprete de comandos carga el compilador C en la memoria para la ejecu-
ción. Cuando el compilador termina su operación, el intérprete de comandos inicia la ejecución del ejemplo si no quiere interrumpir el flujo
ligador. Finalmente, inicia la ejecución de demo.
de ideas, especialmente cuando lee un
capítulo por primera vez.

00 MAQ. PRELIMI(F0694).indd xvi 8/10/07 12:35:40 AM


Prefacio xvii

begin
size : integer value (..);
buffer: array[1..size] of ...;
copy sample, disk write, housekeeping : string;
Código de programa no of samples : integer;
/* Crear los procesos */
copy sample := create process(move to buffer(), 3);
El código de programa se presenta en for- disk write := create process(write to disk(), 2);
housekeeping := create process(analysis(), 1);
ma de pseudocódigo fácil de entender. /* Mandar información del tamaño a copy sample y disk write */
send (copy sample, size);
send (disk write, size);
/* Verificar el estatus de todos los procesos */
over := false;
while (over = false)
if status(copy sample) = terminated and status(disk write) =
terminated and status(housekeeping) = terminated then
over := true;
terminate();
end;

procedure move to buffer();


buf size : integer;

Ejercicios EJERCICIO 2

Se incluyen ejercicios al final de cada ca- 1. ¿Cuáles de las siguientes deberían ser instrucciones privilegiadas? Explique por qué.
a) Ponga al CPU en modo privilegiado
pítulo. Éstos contienen problemas numé- b) Cargue los registros acotados
c) Cargue un valor en un registro del CPU
ricos basados en el material estudiado en d) Desenmascare algunas interrupciones
e) Termine a la fuerza la operación de E/S.
el texto, así como preguntas conceptuales 2. El CPU deberá estar en el modo privilegiado al ejecutar el código del kernel y en el modo de usuario
(es decir, el modo no privilegiado) al ejecutar un programa del usuario. Explique cómo se logra esto
desafiantes que miden la comprensión de durante la operación de un sistema operativo.
3. Justifique la siguiente declaración: “Debido a la presencia de la memoria cache, un programa requiere
los conceptos y de las técnicas compren- más tiempo del CPU para ejecutarse en un sistema de multiprogramación o de tiempo compartido que
lo que requeriría si fuera a ejecutarse completamente solo, es decir, sin tener a ningún otro programa en
didas en cada capítulo y que también su- el sistema”.

ministran una visión más profunda. 4. Escriba una nota sobre el contenido de los diversos campos de un vector de interrupción.
5. ¿Qué es un estado del CPU? Explique cómo es útil la noción de estado del CPU para implementar la
multiprogramación.

Introducción del capítulo La introducción precede a la primera sección de cada capítulo. Describe su
objetivo, la importancia del capítulo y los temas cubiertos en el mismo.
Instantáneas de los sistemas concurrentes Los estudiantes tienen dificultad para visualizar la operación
concurrente de los procesos en un sistema de software. Esta dificultad conduce a una comprensión inadecuada
de la sincronización de los procesos. Una instantánea ilustra el estado de los diferentes procesos y de los datos de
sincronización a fin de suministrar una visión holística de las actividades en un sistema concurrente.
Secciones optativas Las secciones optativas están dedicadas a temas avanzados. Estas secciones estudian
las bases teóricas de ciertos temas o de aspectos avanzados de su implementación. El instructor las puede incluir
como oferta para un curso de sistemas operativos, dependiendo de la disponibilidad de tiempo, o asignarlas en
forma selectiva para su estudio en casa.
Casos de estudio Los casos de estudio se organizan como secciones independientes. Ilustran aspectos
prácticos, disposiciones e intercambios en el diseño y la implementación de un sistema operativo. Los principa-
les sistemas operativos cubiertos por los casos de estudio son las diferentes versiones de los sistemas operativos
de Unix y Windows, así como el Linux.

00 MAQ. PRELIMI(F0694).indd xvii 8/10/07 12:35:45 AM


xviii Prefacio

Organización del libro


El libro trata tanto los sistemas operativos convencionales para usarse en los sistemas de cómputo independien-
tes, como los sistemas operativos distribuidos, que se usan en sistemas de cómputo formados por computadoras
independientes organizadas en red. La introducción estudia los aspectos fundamentales de un sistema operativo
y describe los diferentes tipos de cálculos y métodos empleados para asegurar el uso eficiente de los recursos. El
estudio de los sistemas operativos convencionales está organizado en dos partes, dedicadas a los conceptos fun-
damentales y a los temas avanzados, respectivamente. El estudio de los sistemas operativos distribuidos forma
por sí mismo la tercera parte. La estructura de las partes y la interdependencia entre capítulos es la siguiente:

Parte I: Conceptos fundamentales


Panorama general
de los sistemas
operativos

Estructuras Procesos Administración Sistemas


de los sistemas y hebras de de la memoria de archivos
operativos control

Protección
Sincronización Memoria
Programación y
de procesos virtual
seguridad

Implementación
Pase de Bloqueos Sincronización y programación de las operaciones
mensajes mutuos en los SO de multiproceso con archivos

Parte II: Conceptos avanzados

Parte I: Conceptos fundamentales La primera parte consta de siete capítulos. El capítulo 2 se centra en la
interacción de un sistema operativo con un sistema de cómputo y con los cálculos del usuario. También describe
diferentes clases de sistemas operativos, así como los conceptos y las técnicas fundamentales que emplean.
Un sistema operativo usa los conceptos de proceso y hebra de control para administrar la ejecución de los pro-
gramas: de manera informal, tanto un proceso como una hebra de control representan la ejecución de un progra-
ma; usamos proceso como un término genérico. El capítulo 3 describe la visión de los procesos del usuario y del
sistema operativo, es decir, cómo se crean los procesos, cómo interactúan entre sí y cómo los controla el sistema
operativo. Éste traslapa la ejecución de los procesos para suministrar un buen servicio al usuario y asegurar el uso
eficiente de los recursos. El capítulo 4 describe las técnicas de programación que se usan con este propósito.
El sistema operativo comparte la memoria de la computadora entre los procesos. El capítulo 5 trata del
aspecto clave de la fragmentación de la memoria, que es una situación en la cual un área de ésta no puede ser
usada porque es demasiado pequeña; igualmente, este capítulo se refiere a técnicas que abordan la fragmenta-
ción de la memoria. También se estudian las técnicas usadas por el núcleo para administrar sus propias estruc-
turas de datos. El capítulo 6 estudia la implementación de la memoria virtual, que permite la ejecución de un
programa cuyo tamaño excede al de la memoria.
Los dos siguientes capítulos tratan del sistema File, así como la seguridad y la protección de los datos y
los programas almacenados en los archivos. El capítulo 7 describe las instalaciones para la creación, el acceso,

00 MAQ. PRELIMI(F0694).indd xviii 8/10/07 12:35:46 AM


Prefacio xix

la forma de compartir y el almacenaje confiable de los archivos. El capítulo 8 estudia la manera como se prote-
gen los archivos contra formas ilegales de acceso cometidas por los usuarios.

Parte II: Conceptos avanzados Esta parte consta de seis capítulos dedicados a temas avanzados que tie-
nen que ver con los procesos y su operación, con la implementación de los sistemas de archivos y con la estruc-
tura de los sistemas operativos. El capítulo 9 trata de las técnicas de sincronización que permiten a los procesos
de una aplicación compartir los datos comunes o coordinar sus actividades para alcanzar un objetivo común,
mientras que el capítulo 10 estudia cómo los procesos intercambian mensajes a fin de pasarse información. El
capítulo 11 estudia el bloqueo mutuo, una situación en la cual los procesos se esperan mutuamente por tiempo
indefinido, paralizando con ello una aplicación. El capítulo 12 describe cómo un SO administra los dispositivos
de E/S y describe las técnicas que usa para alcanzar una implementación eficiente de las operaciones con archi-
vos. El capítulo 13 trata acerca de la sincronización y la programación en un sistema operativo de multiproceso.
El capítulo 14 estudia las técnicas de diseño de los sistemas operativos que facilitan la modificación sencilla de
un sistema operativo: 1) para usarse en un sistema de cómputo con una arquitectura diferente, o 2) para satisfa-
cer los nuevos requerimientos de los usuarios.

Parte III: Sistemas operativos distribuidos Un sistema operativo distribuido difiere de uno convencio-
nal en que los recursos, los procesos y las operaciones de control del SO se distribuyen entre nodos diferentes.
Esta diferencia da lugar a una multiplicidad de aspectos relativos a la confiabilidad, la eficiencia, la consistencia
y la seguridad de los cálculos y del SO mismo. Esta parte contiene seis pequeños capítulos que encaran tales
aspectos.

Sistemas
operativos
distribuidos

Aspectos teóricos Seguridad de


de los sistemas un sistema
distribuidos distribuido

Algoritmos Tolerancia en la
de control recuperación
distribuidos y en las fallas

Sistemas de
archivos
distribuidos

Parte III: Sistemas operativos distribuidos

Cómo usar este libro


Este libro está pensado como un texto para un curso sobre sistemas operativos que está modelado de acuerdo
con los planes de estudio del IEEE y de la ACM para ciencias de la computación. La primera parte cubre los

00 MAQ. PRELIMI(F0694).indd xix 8/10/07 12:35:46 AM


xx Prefacio

principios fundamentales de los SO, de modo que por sí misma es adecuada para un curso introductorio sobre
los principios de los sistemas operativos. Las dos primeras partes del libro y las secciones seleccionadas de los
capítulos 15 a 20 de la tercera parte pueden funcionar como un curso sobre los principios de los sistemas opera-
tivos para un plan de estudios de ciencias de la computación o temas relacionados. Sin embargo, todos los temas
estudiados aquí no pueden cubrirse en un semestre, de modo que el instructor podría escoger omitir algunas de
las secciones sobre temas avanzados o los capítulos sobre el pase de mensajes, la sincronización y la programa-
ción en los sistemas operativos de multiproceso, y la estructura de los sistemas operativos; o asignarlos para su
estudio en casa. Juntas, las tres partes del libro cubren los temas necesarios para una secuencia de dos cursos
sobre los principios de los sistemas operativos. Un curso sobre sistemas operativos distribuidos, posiblemente
para alumnos de posgrado, podría emplear la tercera parte del libro como parte sustancial.
Con la excepción de una introducción a la computación, este libro no requiere de ninguna formación
específica. Así, los instructores y los estudiantes posiblemente encuentren que contiene una gran cantidad de
material introductorio que éstos ya conocen. He incluido este material por una razón muy importante: como
se menciona al inicio del prefacio, los estudiantes saben muchas cosas por sí mismos, pero frecuentemente les
faltan conceptos. De modo que es útil que lean incluso material elemental que se presenta con base en concep-
tos. Por la misma razón, considero esencial que los instructores cubran en la clase la mayoría del capítulo 2, y
especialmente los siguientes temas:

• Sección 2.1: SO y el sistema de cómputo, especialmente el hardware para E/S, interrupciones y de pro-
tección de la memoria; y las llamadas del sistema.
• Sección 2.5: Multiprogramación, especialmente la mezcla y la prioridad de los problemas.

Diferencias con la primera edición


El libro ha sido reestructurado sustancialmente. Ciertas partes de los capítulos y su secuencia son diferentes de
los de la primera edición. Los capítulos y sus secciones han sido reorganizados, se han agregado nuevos temas
y se han introducido tablas para lograr un mejor enfoque de los conceptos. En el primer capítulo se ha añadido
una sección que contiene un preámbulo del libro, e introducciones a partes y capítulos para motivar mejor al
lector. Espero que a los estudiantes y a los instructores les guste el nuevo formato del libro.

D. M. DHAMDHERE

La presente edición en español contó con el apoyo de:

Sergio Fuenlabrada Velázquez Instituto Politécnico Nacional


Raúl Morales Carrasco Instituto Tecnológico de Puebla

00 MAQ. PRELIMI(F0694).indd xx 8/14/07 11:01:18 AM


Capítulo
1
Introducción

Un sistema operativo (SO) tiene significados distintos para diferentes usuarios. La visión de cada
uno de éstos se denomina visión abstracta porque enfatiza las características que son importan-
tes desde la perspectiva del observador, ignorando todos los otros aspectos. Un sistema operativo
implementa una visión abstracta al actuar como intermediario entre el usuario y el sistema de
cómputo. Este arreglo no solamente permite que un sistema operativo suministre varias funcio-
nalidades al mismo tiempo, sino que también cambie y evolucione con el tiempo. Estudiaremos
de qué manera las visiones abstractas también son útiles para el diseño y la operación de un
sistema, así como durante su operación.
Un sistema operativo tiene dos metas: el uso eficiente de un sistema de cómputo y la conve-
niencia del usuario. Desafortunadamente, esta última a menudo está en conflicto con la primera.
En consecuencia, un sistema operativo no puede proveer a ambos. Comúnmente, encuentra el
equilibrio que resulte más efectivo en el ambiente en el cual se usa un sistema de cómputo;
el uso eficiente es importante cuando un sistema de cómputo es compartido por varios usuarios,
mientras la conveniencia del usuario es importante en computadoras personales. Destinamos
el término utilización efectiva para referirnos al balance entre la eficiencia y la conveniencia
del usuario, que a su vez se ajuste mejor al ambiente. En este capítulo analizamos las facetas de
la conveniencia de uso eficiente y del usuario.
La función primaria de un sistema operativo es admitir la ejecución de los programas del
usuario para asegurar su conveniencia y el uso eficiente de los recursos. En este capítulo descri-
bimos las funciones realizadas por el sistema operativo para atender estas preocupaciones.

1.1 VISIÓN ABSTRACTA DEL SISTEMA OPERATIVO

La pregunta ¿qué es un sistema operativo? probablemente evoque respuestas diferentes. Por


ejemplo,
• Para un escolar o estudiante joven de universidad, un sistema operativo es el software
que permite el acceso a la riqueza de conocimiento disponible en el Internet.
• Para un programador, un sistema operativo es el software que permite el uso de un siste-
ma de cómputo para el desarrollo de programas.

01 MAQ. CAP. 01(F0694).indd 1 8/10/07 12:44:42 AM


2 CAPÍTULO 1 Introducción

• Para una persona que usa un paquete de aplicaciones, un sistema operativo es simple-
mente el software que hace posible que use el paquete.
• Para un técnico en una planta química informatizada, el sistema operativo es el compo-
nente invisible de un sistema de cómputo que controla la planta.

Las respuestas difieren porque la percepción de un usuario acerca de un sistema operativo depen-
de de tres factores: el propósito para el cual una computadora está siendo usada; el ambiente de
cómputo, es decir, el ambiente en el cual se usa el sistema de cómputo; y el grado de identidad
del sistema de cómputo con el propósito que se está atendiendo.
Para el estudiante, el propósito único del sistema de cómputo podría ser usar un navegador
del Internet. El sistema operativo coadyuva a lograr esto, así es que se identifica con el uso del
sistema de cómputo para la navegación en Internet. Un programador desea destinar un sistema
de cómputo al desarrollo de programas de uso general, así es que la habilidad para usar un
compilador para un lenguaje específico es de importancia suprema. Para una persona que usa
un paquete de aplicaciones, el sistema operativo es simplemente un medio de uso del paquete.
Tal usuario es indiferente a las demás capacidades de un sistema operativo. De manera semejan-
te, un técnico en una planta química informatizada considera al sistema operativo como un todo
en el sistema de control de la planta. Un diseñador de sistemas operativos indudablemente tiene
una percepción diferente acerca de lo que es un sistema operativo.
Un concepto común en todas estas percepciones es la utilización de un sistema de cómputo
para un propósito específico o para un conjunto de propósitos. Las intenciones en los ejemplos
anteriores son diferentes, así es que las percepciones del papel del sistema operativo lo son
también.
De entre estos ejemplos, es claro que un usuario percibe al sistema operativo como el soft-
ware que le ayuda a lograr el uso buscado de un sistema de cómputo; las demás capacidades
del sistema de cómputo y su ambiente no parecen tener importancia. Así, el sistema operativo
es simplemente una manera de lograr un propósito establecido. Un usuario preferirá un sistema
operativo que le permite alcanzar su propósito de la manera más simple y rápida posible. Así,
la perspectiva de un usuario siempre está determinada por la conveniencia y la rapidez en la
utilización de la computadora.
Ninguno de los cuatro puntos de vista de un sistema operativo descritos al principio de esta
sección (que se ilustran en la figura 1.1) es completo, pero cada visión es correcta y útil porque le
ayuda a un usuario a entender cómo usar un sistema operativo. Tales visiones se llaman visiones
abstractas. Una visión abstracta se centra en las características esenciales de una entidad desde
la perspectiva del observador. Consecuentemente, contiene algunos elementos de realidad, pero
ignora otros.

1.1.1 Usos de las visiones abstractas

La visión abstracta de un usuario contiene características importantes de un sistema desde su


perspectiva. Le ayuda al diseñador de sistemas operativos a entender los requisitos del usuario,
lo cual coadyuva a planificar las características de un sistema operativo. Los puntos de vis-
ta abstractos son útiles para otros propósitos, resumidos en la tabla 1.1. La ventaja crucial de
usar una visión abstracta en el diseño es que ayuda a controlar la complejidad del diseño al sepa-
rar las funciones de las diferentes partes del sistema. Las visiones abstractas son también útiles
para entender el diseño y la implementación del sistema.

01 MAQ. CAP. 01(F0694).indd 2 8/10/07 12:44:43 AM


1.1 Visión abstracta del sistema operativo 3

INTERNET

INVERSIONES EN LA
BOLSA DE VALORES

Figura 1.1 La visión abstracta de un sistema operativo en el caso del estudiante,


el programador, el usuario y el técnico.

Tabla 1.1 Usos de las visiones abstractas

Uso Descripción
Recopilación de los La visión abstracta del usuario indica los servicios importantes que un sis-
requerimientos del tema debe suministrar. Puede usarse un conjunto de visiones abstractas para
sistema integrar una especificación de los requerimientos del sistema.
Diseño del sistema El uso de las visiones abstractas permite que un diseñador se centre en una
parte específica del sistema. Los detalles de las demás partes están “ocultos”;
se supone que estas partes se encuentran disponibles. Este enfoque ayuda a
controlar la complejidad del proceso de diseño.
Implementación del La parte cuyos detalles están ocultos en una visión de diseño se convierte en
sistema un módulo, que puede invocarse desde otros módulos. Este hecho conduce
a una implementación modular.

La figura 1.2 contiene una visión abstracta de la estructura de un sistema operativo, que
muestra tres partes principales del mismo. Cada una consta de varios programas. El núcleo
(kernel) es el corazón del sistema operativo, controla la operación de la computadora y provee
un conjunto de funciones y servicios para usar el CPU y los recursos de la computadora. Los
programas que no son de kernel implementan los comandos del usuario. Estos programas no
interactúan con el hardware, sino que usan recursos provistos por los programas de kernel. Los
programas de la interfaz del usuario proveen al usuario una interfaz de comando de línea o bien
una de usuario gráfico (la interfaz gráfica del usuario). Estos programas usan recursos provistos

01 MAQ. CAP. 01(F0694).indd 3 8/10/07 12:44:44 AM


4 CAPÍTULO 1 Introducción

por los programas que no son de kernel. Un usuario interactúa con los programas en la interfaz
del usuario (comúnmente con el intérprete de comandos) para solicitar el uso de recursos y los
servicios provistos por el sistema.

Interfaz del usuario

Programas que no
son de kernel

Kernel (núcleo)

Hardware de la computadora

Figura 1.2 La visión abstracta de un diseñador de sistemas operativos.

La visión abstracta de la figura 1.2 tiene propiedades interesantes. Contiene un arreglo jerár-
quico de las capas del programa, en el cual los programas de la capa más alta usan los recursos
provistos por los programas de la capa de abajo. De hecho, cada capa toma una visión abstracta
de la capa inferior. En esta visión, la capa inferior aparece como un sistema que es capaz de eje-
cutar ciertos comandos. Incluso podría ser una máquina que es capaz de realizar ciertas operacio-
nes. El hecho de que la capa inferior conste de un conjunto de programas en vez de un sistema de
cómputo da lo mismo para la capa superior. Cada capa prolonga las capacidades de la máquina
provistas por la capa inferior. La máquina provista por la capa de la interfaz del usuario entiende
los comandos en el lenguaje de comandos del sistema operativo. Esta visión abstracta ayuda a
entender el diseño de un sistema operativo.

Organización lógica y física La visión del programador de una entidad es comúnmente


una visión abstracta. Contiene características y propiedades útiles de la entidad desde la perspec-
tiva del programador. Tres entidades importantes de esta clase son el programa, el archivo y el
dispositivo de E/S. La visión abstracta de una entidad se designa como visión lógica, y el arreglo
y la relación entre los componentes de la entidad se conocen como organización lógica. La vi-
sión real de una entidad, que a menudo coincide con la visión de la entidad del sistema operativo,
es llamada visión física y el arreglo bosquejado adentro se designa como organización física.
Considere la ejecución de un programa P en un sistema de cómputo. La visión lógica del
programa P se observa en la figura 1.3a). Se muestra el código de P escrito en un lenguaje de
nivel más alto, y los datos que lee durante su ejecución. La visión física de la ejecución de P
se muestra en la figura l.3b). El programa P ha sido compilado en el lenguaje de máquina del
sistema de cómputo. De esta manera, el programa consta de instrucciones que la computadora
puede entender y ejecutar, y de los datos almacenados en la memoria de la computadora. El
rectángulo representa la memoria del sistema de cómputo. El código de P ocupa sólo una parte
de la memoria de la computadora. También existen algunos otros programas en la memoria de
la computadora. Los datos de P se registran en un archivo nombrado info, que se guarda en un
disco. Durante su ejecución, P lee algunos datos de info, los manipula e imprime sus resultados.

01 MAQ. CAP. 01(F0694).indd 4 8/10/07 12:44:48 AM


1.2 Metas de un sistema operativo 5

Esta visión incluye el disco en el cual la información se graba, la impresora en la cual los re-
sultados de P deben imprimirse, la memoria del sistema de cómputo y el CPU para ejecutar las
instrucciones de P.

Memoria
Sistema operativo
(SO)
info
Programa P Instrucciones
+ espacio de
datos de P Impresora
CPU
Datos Resultados
Otros
programas

a) b)
Figura 1.3 Visiones lógica y física de la ejecución de un programa.

En la sección 1.3.2.1, analizamos las visiones lógica y física de los dispositivos de E/S.
Estudiaremos organizaciones lógica y física de los archivos en el capítulo 7.

1.2 METAS DE UN SISTEMA OPERATIVO

Un sistema operativo no sólo debe asegurar el uso eficiente de un sistema de cómputo, sino que
también debe proveer la conveniencia del usuario. Sin embargo, estas consideraciones a menudo
están en conflicto. Por ejemplo, el suministro de un servicio rápido a una petición del usuario po-
dría implicar que hay que despreciar a otros usuarios del sistema. También podría significar que
los recursos deberían permanecer asignados al programa de un usuario aun cuando el programa
no los está usando, lo cual conduciría a la subutilización de recursos. En tales casos, el diseñador
del sistema operativo debe tomar una decisión consciente para intercambiar la conveniencia y la
velocidad de un usuario con las de otros, o bien con el uso eficiente del sistema de cómputo. En
consecuencia, la meta crucial de un sistema operativo es proveer la combinación que mejor se
ajuste al ambiente de uso eficiente y de conveniencia del usuario. Ésta es la noción de utilización
efectiva de un sistema de cómputo.
Encontramos un gran número de sistemas operativos en uso porque cada uno de ellos pro-
vee un gusto diferente de utilización efectiva. En un extremo tenemos sistemas operativos que
proveen servicio rápido requerido por las aplicaciones de comandos y de control, mientras
que en el otro tenemos sistemas operativos que hacen un uso eficiente de los recursos de la
computadora para proveer computación de bajo costo. En medio tenemos sistemas operativos
que proveen combinaciones diferentes de servicio rápido y de uso eficiente. A continuación,
analizamos varios aspectos de uso eficiente y de la conveniencia del usuario para entender la
noción de utilización efectiva.

El sistema operativo y la utilización efectiva de sistemas de cómputo La noción de uti-


lización efectiva abarca un espectro amplio de consideraciones. En un extremo del espectro se
ubican consideraciones centradas en el usuario, como la conveniencia del usuario y el servi-
cio rápido para las peticiones del usuario. Son importantes en sistemas operativos que admiten
computación interactiva o aplicaciones de tiempo crítico. Las consideraciones centradas en el

01 MAQ. CAP. 01(F0694).indd 5 8/10/07 12:44:49 AM


6 CAPÍTULO 1 Introducción

sistema existen en el otro extremo del espectro. El uso eficiente del sistema es la preocupación
suprema en un ambiente de computación que se centra en el sistema, tal como el procesamiento
de datos no interactivo. Esto se obtiene a través del uso de buenas políticas de asignación de
recursos.
La eficiencia de uso tiene dos aspectos. Un sistema operativo consume algunos recursos de
un sistema de cómputo durante su propia operación; por ejemplo, ocupa memoria y usa el CPU.
Este consumo de recursos constituye una sobrecarga (overhead ) que reduce los recursos dispo-
nibles a los programas de los usuarios.
El otro aspecto del uso eficiente tiene que ver con el empleo de recursos que realizan los
programas del usuario. Puede resultar una eficiencia baja debido a dos causas: si un sistema
operativo le asigna exceso de recursos a los programas o si es incapaz de asignar recursos libres
a los programas que los necesiten. Lo primero conduce a un derroche de recursos, mientras
que lo último produce entorpecimiento de los recursos y afecta el progreso de los programas.
Para lograr una buena eficiencia, un sistema operativo debe compensar estos dos efectos y tam-
bién minimizar la sobrecarga.

El uso eficiente El uso eficiente de recursos puede obtenerse mediante la revisión cons-
tante de su empleo y realizando medidas correctivas cuando sean necesarias. Sin embargo, un
sistema de cómputo contiene varios recursos, como la memoria, los dispositivos de E/S y el
CPU, por lo que un método comprehensivo de revisión de la eficiencia puede conducir a una
sobrecarga alta. Consecuentemente, los sistemas operativos utilizan estrategias que son de apli-
cación simple y fácil, pero que se sabe que no son del todo óptimas para asegurar una buena
eficiencia; por ejemplo, se centran en la eficiencia de algunos recursos importantes, como el
CPU y la memoria, o manejan los programas del usuario de manera que garanticen una eficiencia
alta. La última alternativa evita computación de eficiencia, lo cual implica una sobrecarga (over-
head ) recurrente. El proceso por lotes y la multiprogramación —que son dos sistemas operativos
anteriores que usan la eficiencia de uso como una meta del diseño— usaron este enfoque (véase
el capítulo 2).

La conveniencia del usuario La conveniencia del usuario tiene varias facetas, resumidas
en la tabla 1.2. En los inicios de la computación, los sistemas de cómputo eran caros, por lo que
los sistemas operativos enfatizaron el uso eficiente. Como consecuencia, la conveniencia del
usuario fue sinónimo de pura necesidad: la simple habilidad para ejecutar un programa escrito
en un lenguaje de alto nivel se consideraba adecuada. La experiencia con sistemas operativos
anteriores condujo a la demanda de un mejor servicio, donde la noción de servicio se limitaba a
una respuesta rápida a la petición del usuario.
Otras facetas de la conveniencia del usuario pueden asociarse con el uso de computadoras y
con las aplicaciones informatizadas en nuevos campos. Los primeros sistemas operativos tenían
interfaces de usuario complicadas cuyo uso requería de mucho entrenamiento del usuario. Esto
era aceptable porque la mayoría de éstos eran científicos e ingenieros. Tuvieron que desarrollarse
interfaces de uso sencillo para facilitar el uso de la computadora a los nuevos tipos de usuarios.
Los sistemas operativos amigables con el usuario lograron este efecto. De muchas formas, este
movimiento puede compararse con la diversificación de habilidades para conducir automóviles
en la primera mitad del siglo XX. Con el tiempo, la conducción de automóviles se convirtió me-
nos en una pericia y más en una habilidad que podía adquirirse con experiencia y entrenamiento
limitados.

01 MAQ. CAP. 01(F0694).indd 6 8/10/07 12:44:49 AM


1.3 La operación de un sistema operativo 7

Tabla 1.2 Facetas de la conveniencia del usuario

Faceta Ejemplos
Necesidad Capacidad para ejecutar programas, uso del sistema de archivos.
Buen servicio Respuesta rápida a las peticiones de computación.
Sistema operativo amigable con Comandos de uso sencillo, interfaz gráfica del usuario (GUI).
el usuario
Nuevo modelo de programación Programación concurrente.
Características para expertos Medios para construir estructuras computacionales complejas.
Características orientadas a la red Medios para construir servidores con capacidad de red.
Evolución Capacidad para añadir nuevas características, uso de nuevas
computadoras.

Los usuarios de la computadora abordaron la solución de problemas nuevos a medida que


aumentaba la potencia de cómputo. Se propusieron modelos nuevos para desarrollar soluciones
eficientes con base en costos para los tipos nuevos de problemas. Algunos de estos modelos
podían ser admitidos por la tecnología del compilador y requerían poco soporte específico del
sistema operativo. El diseño modular y el orientado a objetos de los programas son dos modelos
de este tipo. Otros, como el modelo de programación concurrente, requerían de características
específicas de soporte en el sistema operativo. Los programadores profesionales consideraban
aburridas las interfaces del usuario amigables con el usuario, por lo que se desarrollaron interfa-
ces especializadas para usuarios expertos.
Pero otra clase de características del sistema operativo estaba motivada por el advenimiento
del Internet. El uso efectivo de la red requiere la habilidad de instalar servidores que sean uti-
lizables en la red. Esta característica requiere un soporte extensivo de los sistemas de redes y
una habilidad para escalar el desempeño de un servidor o desactivarlo, dependiendo de la carga
dirigida hacia éste.
Finalmente, los usuarios esperan que su sistema operativo evolucione con el tiempo para
admitir características nuevas a medida que se desarrollan áreas de aplicación nuevas y tecnolo-
gías nuevas de computadora.

1.3 LA OPERACIÓN DE UN SISTEMA OPERATIVO


Un sistema operativo implementa requisitos computacionales de sus usuarios con la ayuda de
recursos del sistema de cómputo. Sus funciones cruciales están descritas en la tabla 1.3.

Tabla 1.3 Funciones clave de un sistema operativo

Función Responsabilidad del sistema operativo


Programas Iniciación y terminación de los programas. Suministrar métodos convenientes, de
modo que varios programas puedan trabajar con un objetivo común.
Recursos Asegurar la disponibilidad de los recursos en el sistema y asignarlos a los programas.
Planificación Decidir cuándo y durante cuánto tiempo dedicar el CPU a un programa.
Protección Proteger los datos y los programas contra la interferencia de otros usuarios y de sus
programas.

Para darse cuenta de la ejecución de un programa, un sistema operativo debe asegurar que
recursos tales como la memoria y los dispositivos de E/S están disponibles para aquél. También

01 MAQ. CAP. 01(F0694).indd 7 8/10/07 12:44:50 AM


8 CAPÍTULO 1 Introducción

debe proveerse suficiente atención del CPU a la ejecución de un programa. Esta función se llama
planificación. Un usuario puede utilizar varios programas para cumplir con un requisito compu-
tacional; por eso un sistema operativo debe proporcionar medios para asegurar funcionamiento
armonioso de tales programas. Para ganarse la confianza de los usuarios, un sistema operativo
debe proveer una garantía de que sus datos no se usarán ilegalmente ni se perderán, y que la eje-
cución de sus programas no afrontará la interferencia de otros programas en el sistema.
Un sistema operativo realiza varias tareas de limpieza para admitir las funciones de creación
y terminación de programas, asignación de recursos, planificación y protección. También realiza
otras tareas para implementar su noción de utilización efectiva. La tabla 1.4 describe tareas del
sistema operativo comúnmente realizadas.

Tabla 1.4 Tareas comunes realizadas por los sistemas operativos

Tarea Cuándo/quién ejecuta


1. Mantener una lista de usuarios autorizados. Administrador del sistema
2. Construir una lista de todos los recursos del sistema. Cuándo se inicia el sistema operativo
3. Iniciar la ejecución de los programas. Con comandos del usuario
4. Mantener la información del uso de recursos por los Continuamente durante la operación
programas y el estado actual de todos los programas. del sistema operativo
5. Mantener el estado actual de todos los recursos y Cuando se soliciten recursos
asignar los recursos a los programas cuando se solicite. o se liberen
6. Realizar la planificación. Durante la operación del sistema
operativo
7. Mantener información para la protección. Durante la operación del sistema
operativo
8. Manejar las peticiones hechas por los usuarios y Con las peticiones del usuario
sus programas.

La lista de personas que están autorizadas para usar el sistema de cómputo es mantenida por
el administrador del sistema operativo. Él suma y suprime nombres de esta lista, de conformidad
con la política de uso de la computadora. Cuando el sistema de cómputo se conecta, invoca un
procedimiento que se conoce como cargado (booting), el cual realiza varias acciones preparato-
rias e inicia la operación del sistema operativo. Una de estas acciones es hacer una lista de todos
los recursos que hay en el sistema. El sistema operativo inicia un programa nuevo cuando el
usuario emite una orden para ejecutarlo. El sistema operativo rastrea el uso que los programas
hacen del recurso, ya que esta información podría ser necesaria para implementar su noción de
utilización efectiva, por ejemplo, para asegurar equidad en el uso de recursos. El sistema operati-
vo también mantiene información acerca del estatus actual de recursos y de los programas para el
uso, al realizar la asignación de recursos y la planificación. Las siguientes secciones estudian los
antecedentes de cómo el sistema operativo maneja los programas, los recursos y la planificación.

1.3.1 Programas
Una estructura computacional es una configuración de uno o más programas que trabajan con
una meta común. Se crea al emitir uno o más comandos para especificar las relaciones entre los
programas y para iniciar su ejecución. Algunas estructuras computacionales comunes son:

01 MAQ. CAP. 01(F0694).indd 8 8/10/07 12:44:50 AM


1.3 La operación de un sistema operativo 9

• Un programa individual
• Una secuencia de programas individuales
• La coejecución de programas.

Estas estructuras computacionales se definirán y describirán en capítulos posteriores; sólo se


describen aquí sus características más destacadas a fin de ilustrar la conveniencia que ofrecen
para el usuario. La tabla 1.5 resume las responsabilidades del sistema operativo para estas es-
tructuras computacionales.

Tabla 1.5 Estructuras computacionales y responsabilidades del sistema operativo

Estructura computacional Responsabilidades del sistema operativo


Programa individual Ejecutar la iniciación/terminación de los programas, administración
de recursos.
Secuencia de programas Implementar la dependencia de los programas: terminar la secuencia
individuales si un programa experimenta una terminación anormal.
Coejecución de programas Suministrar las interfaces apropiadas entre los programas, ejecutar la
terminación de los programas coejecutados.

Programa individual El cómputo de un programa individual consta de la ejecución de


un programa para un conjunto determinado de datos. El programa puede ser secuencial o con-
currente. Un programa individual es la estructura computacional más simple; concuerda con la
noción convencional de programa. En un programa concurrente, sus diferentes partes pueden
ejecutarse concurrentemente. El sistema operativo necesita conocer las identidades de estas par-
tes para organizar su ejecución concurrente. Esta función no es proporcionada por la interfaz del
usuario del sistema operativo; el capítulo 9 describe cómo se implementa. En esta sección se
supone que cada programa es de naturaleza secuencial.

Secuencia de programas individuales Cada programa individual en la secuencia es ini-


ciado por el usuario a través de un comando separado. Sin embargo, una secuencia de programas
individuales tiene su propia semántica: un programa deberá ejecutarse sólo si los progra-
mas previos en la secuencia se ejecutaron con éxito. Para lograr una meta común, los programas
explícitamente deben hacer interfaz de las entradas y las salidas con otros programas de la se-
cuencia. El ejemplo 1.1 analiza la noción de secuencia de programas individuales en el sistema
operativo de disco de Microsoft Corp (MS DOS).

Ejemplo 1.1 El archivo .bat del MS DOS, puede usarse para formar una secuencia de programas
individuales. Contiene una secuencia de comandos y cada comando indica la ejecución de un pro-
grama. En el caso de un archivo .bat que contiene comandos para iniciar una secuencia de
programas para compilar, ligar y ejecutar un programa en C: el compilador de C compila un pro-
grama en C existente en el archivo alfa.c, el ligador liga la salida del compilador para generar
un programa ejecutable nombrado demo y el programa demo se ejecuta con los datos contenidos en
el archivo muestra. El intérprete de comandos carga el compilador C en la memoria para la ejecu-
ción. Cuando el compilador termina su operación, el intérprete de comandos inicia la ejecución del
ligador. Finalmente, inicia la ejecución de demo.

01 MAQ. CAP. 01(F0694).indd 9 8/10/07 12:44:51 AM


10 CAPÍTULO 1 Introducción

compilador
ligador demo
C

Figura 1.4 Pasos de la ejecución de una secuencia de programas.

La figura 1.4 ilustra los tres cómputos. Observe que cada programa de la secuencia debe hacer
sus propios arreglos para comunicar sus resultados a otros programas. Comúnmente, esto se logra
usando algunas convenciones para nombrar los archivos; por ejemplo, la salida del compilador
C puede ponerse en un archivo llamado alfa.obj a fin de que el ligador lo pueda recoger de
allí. El intérprete de comandos es ajeno a estos arreglos; simplemente implementa los comandos
emitidos para ello.
La semántica de una secuencia de programas dicta que el ligador sea ejecutado sólo si la
compilación del programa en C tiene éxito, y que demo se ejecutará sólo si el ligado tiene éxito.
Esto no sería el caso si los mismos tres programas fuesen iniciados como tres programas indivi-
duales.

Coejecución de programas El usuario inicia la coejecución de programas indicando sus


nombres en un solo comando. La semántica de la coejecución requiere que los programas se eje-
cuten al mismo tiempo —en vez de uno tras otro como en una secuencia de programas— y que
interactúen entre sí durante su ejecución. La naturaleza de la interacción es específica para un
comando de coejecución. El sistema operativo provee interfaces apropiadas entre los programas
de coejecución. El ejemplo 1.2 estudia la coejecución de programas en Unix.

Ejemplo 1.2 El comando de Unix

cat names | sort | uniq | wc -1

inicia la ejecución de cuatro programas de coejecución para contar el número de nombres úni-
cos en el archivo names. Estos programas son: cat, sort, uniq y wc. ‘|’ es el símbolo de
una tubería Unix, que envía la salida de un programa como la entrada a otro. Así, la salida
de cat da a sort como su entrada, la salida de sort da a uniq y la salida de uniq da a wc.
cat lee el contenido del archivo names y escribe en su archivo de salida estándar cada nombre
que encuentra allí. La salida de cat es la entrada de sort, de modo que sort lee estos nombres,
los ordena alfabéticamente y los escribe en su archivo de salida. uniq quita nombres duplicados
que aparecen en su archivo y regresa nombres únicos. wc cuenta y reporta el número de nombres
en su entrada. (-1 es una opción para el comando wc que le pide contar el número de renglones en
su entrada, ya que uniq pone cada nombre en un renglón por sí mismo.)
Observe que los cuatro programas no forman una secuencia de programas. Coexisten en la
memoria y cooperan entre sí durante su ejecución (véase la figura 1.5). A diferencia de una secuencia
de programas, la transición de resultados de un programa al siguiente es responsabilidad del SO.
El procesador de comandos también tiene que proveer sincronización apropiada entre los progra-
mas para asegurar que un programa consume algunos datos sólo después de que se haya producido.
Todos los programas de coejecución terminan al mismo tiempo. Después, el control regresa al
procesador de comandos.

01 MAQ. CAP. 01(F0694).indd 10 8/10/07 12:44:51 AM


1.3 La operación de un sistema operativo 11

cat sort uniq wc

Figura 1.5 La coejecución de programas.

1.3.2 La asignación y planificación de recursos

La función de asignación de recursos realiza la unión de uno o más recursos con un programa
solicitante: es decir, asocia los recursos con un programa. También retira la asignación de ellos
de un programa y los asigna a otros. De esta manera, la asignación y el retiro de asignación de
recursos ayudan a implementar el uso compartido de recursos por los usuarios. Los recursos se
dividen en recursos de sistema y creados por el usuario.
La función de protección de los recursos impide la interferencia mutua entre usuarios que
comparten un conjunto de ellos. La protección se implementa realizando una asignación sólo si
una petición satisface un conjunto de restricciones. Algunas de éstas guardan relación con la na-
turaleza de un recurso, por ejemplo, si un recurso puede ser usado concurrentemente por varios
usuarios. Otras son especificadas por el dueño de un recurso. Estas restricciones comúnmente
encarnan la noción de privilegios de acceso y especifican si un usuario determinado debe o no
tener permiso para acceder a un recurso.
Dos estrategias comunes para la asignación de recursos son:

• La partición de los recursos.


• La asignación de los recursos en común.

En el enfoque de partición de recursos, el sistema operativo decide a priori qué recursos deberán
asignarse al programa del usuario. Este enfoque se llama asignación estática porque la asigna-
ción se hace antes de que comience la ejecución de un programa. La asignación estática de recur-
sos es simple de implementar. Sin embargo, carece de flexibilidad, lo que conduce a problemas
tales como el derroche de recursos que se asignan a un programa pero permanecen sin uso, y la
incapacidad del sistema operativo para conceder recursos adicionales para un programa durante
su ejecución. Estas dificultades surgen porque la asignación se hace con base en las necesidades
percibidas de un programa, en vez de en sus necesidades reales.
En el enfoque basado en los recursos en común, el sistema operativo mantiene un grupo
común de recursos y los asigna desde éste cada vez que un programa pide un recurso. Este
enfoque se llama asignación dinámica porque la asignación tiene lugar durante la ejecución de
un programa, lo que evita derroche de recursos asignados; por tanto, puede proveer una mejor
utilización de éstos.
Un esquema simple de asignación de recursos usa una tabla de recursos como la estructura
central de datos (véase la tabla 1.6). Cada elemento en la tabla contiene el nombre y la dirección
de una unidad de recurso y su estatus presente, es decir, si está libre o asignado a algún pro-
grama. Esta tabla se construye por el procedimiento de cargado al detectar la presencia de los
dispositivos de E/S en el sistema. En el enfoque de la asignación particionada de recursos, el SO

01 MAQ. CAP. 01(F0694).indd 11 8/10/07 12:44:52 AM


12 CAPÍTULO 1 Introducción

Tabla 1.6 Tabla de asignación de recursos

Nombre del recurso Clase Dirección Estatus de asignación


impresora1 Impresora 101 Asignado a P1
impresora2 Impresora 102 Libre
impresora3 Impresora 103 Libre
disco1 Disco 201 Asignado a P1
disco2 Disco 202 Asignado a P2
escritor en disco Escritor en disco 301 Libre
compacto 1 compacto

considera el número de recursos y los programas en el sistema y decide cuántos recursos de cada
clase serán asignados a un programa. Por ejemplo, un sistema operativo puede decidir que a un
programa se le puede asignar 1 megabyte de memoria, 2 000 bloques de discos y un monitor. Tal
colección de recursos se designa como partición.
En el enfoque de asignación de recursos en común, el sistema operativo consulta la tabla de
recursos cuando un programa presenta una solicitud, y asigna en consecuencia. Cuando existen
en el sistema muchas unidades de una clase del recurso, una petición del recurso sólo indica la
clase del recurso, y el sistema operativo verifica si cualquier unidad de esa clase está disponi-
ble para la asignación. La asignación basada en los recursos en común causa sobrecarga por la
asignación y para el retiro de asignación individual de los recursos; sin embargo, evita los dos
problemas encarados por el enfoque de la partición de recursos, al adaptar la asignación a
los requisitos de recursos de los programas.

1 MB 1 MB 1 MB 1 MB 1 MB 1 MB

Recursos
en común

Partición 1 · · · Partición n
P1 P2
a) b)
Figura 1.6 La partición de recursos y la asignación basada en recursos en común.

La figura 1.6a) muestra un conjunto de particiones que se definen durante el tiempo del
cargado. La tabla de recursos contiene entradas para particiones de los recursos en vez de para
recursos individuales. Se asigna una partición gratuita a cada programa antes de iniciar su ejecu-
ción. La figura 1.6b) ilustra la asignación basada en recursos en común. Se ha asignado el monitor
al programa P1, un área del disco de 2 000 bloques y 1 megabyte de memoria. Al programa P2
se le ha asignado un monitor y 2 megabytes de memoria; el área del disco no se asigna porque
P2 no lo pidió. Así, la asignación basada en recursos en común evita la asignación de recursos

01 MAQ. CAP. 01(F0694).indd 12 8/10/07 12:44:52 AM


1.3 La operación de un sistema operativo 13

que el programa no necesita. Los programas con requisitos de recursos grandes o inusuales
pueden ser manejados por el sistema operativo siempre que los recursos requeridos existan en
el sistema.

El uso de recursos compartidos Los programas pueden compartir un recurso en dos formas:
• El uso compartido secuencial.
• El uso compartido concurrente.
En el uso compartido secuencial, se asigna un recurso para su uso exclusivo por parte de un pro-
grama. Cuando el recurso se retira, se le marca como libre en la tabla de recursos. Entonces pue-
de asignarse a otro programa. En el uso compartido concurrente, dos o más programas pueden
usar concurrentemente el mismo recurso. Los ejemplos de uso compartido concurrente son los
archivos de datos, como los horarios de autobús. La mayoría de los demás recursos no pueden
compartirse concurrentemente. A menos que se diga otra cosa, a lo largo de este texto se supone
que los recursos son sólo secuencialmente repartibles.
El sistema operativo retira la asignación de un recurso cuando el programa al cual se le
asigna lo termina o cuando hace una petición explícita para su retiro. Algunas veces retira un
recurso por la fuerza para asegurar equidad en su utilización entre los programas, o para alcanzar
ciertas metas en el nivel del sistema. A esta acción se le llama priorización de recursos. Usamos
el término más corto priorización para el retiro forzado del CPU. Un programa que pierde el
CPU de esta manera es llamado un programa priorizado.

Compartición del CPU El CPU puede compartirse sólo de manera secuencial, así es que
puede asignarse únicamente a un programa a la vez. Otros programas en el sistema tienen
que esperar su turno para el CPU. El sistema operativo debe compartir el CPU entre los pro-
gramas de manera equitativa. Por consiguiente, después de que un programa ha sido ejecutado
durante un lapso razonable de tiempo, prioriza al programa y le da el CPU a otro programa. La
función de decidir a cuál programa deberá dársele el CPU y durante cuánto tiempo se llama
planificación.

Programa priorizado

Programa ... Programa


nuevo Planificador CPU terminado
Programas que
esperan por el CPU Programa
seleccionado
Figura 1.7 Un esquema de planificación.

La figura 1.7 muestra un esquema de la planificación del CPU. Varios programas esperan
asignación del CPU. El planificador selecciona uno de estos programas para la ejecución en el
CPU. El programa priorizado se añade al conjunto de programas en espera del CPU.

Compartición de la memoria Pueden tratarse partes de la memoria como recursos inde-


pendientes. Tanto la partición como la asignación basada en recursos en común pueden usarse

01 MAQ. CAP. 01(F0694).indd 13 8/10/07 12:44:53 AM


14 CAPÍTULO 1 Introducción

para manejar memoria. La partición es simple de implementar. También simplifica la protección


de áreas de memoria asignadas a programas diferentes. Sin embargo, la asignación basada en
recursos en común logra un mejor uso de la memoria. La memoria puede priorizarse de los
programas inactivos y puede usarse para acomodar programas activos. El término especial inter-
cambio se usa para la priorización de la memoria. El término “priorización de memoria” se usa
raramente en la literatura de sistemas operativos.

Partición
#
1 A A
2 B

3 B Recursos en común
Sin uso
de la memoria
4

a) b)
Figura 1.8 Esquema de asignación de memoria: a) asignación particionada,
b) asignación basada en recursos en común.

La figura 1.8 ilustra los enfoques de la asignación de memoria. En el enfoque particionado


fijo, la memoria se divide a priori en muchas áreas. Una partición se asigna a un programa en su
iniciación. La figura 1.8a) ilustra la situación cuando la memoria ha sido dividida en particiones
de igual tamaño y dos de ellas han sido asignadas a los programas A y B. En ese momento dos
particiones están libres. Observe que el tamaño de B es más pequeño que el de la partición, de
manera que alguna memoria asignada a ésta permanece sin uso. La figura 1.8b) ilustra el enfo-
que basado en recursos en común. A los programas recién iniciados se les asigna memoria de
los recursos en común. A cada programa se le asigna sólo la memoria que solicite, por lo que la
memoria asignada no se desaprovecha.

Compartición de discos Las diferentes partes de un disco pueden tratarse como recursos
independientes. Son factibles ambos enfoques de partición y el que se basa en los recursos en
común; sin embargo, los sistemas operativos modernos muestran una preferencia por el enfoque
basado en los recursos en común. El sistema operativo no practica la priorización de discos;
los usuarios individuales pueden priorizar sus áreas de disco copiando sus archivos encima de
cartuchos de cinta magnética.

1.3.2.1 Recursos virtuales


Un recurso virtual es un recurso ficticio, una ilusión admitida por un sistema operativo a través
del uso de un recurso real. Un sistema operativo puede usar el mismo recurso real para admitir
varios recursos virtuales. Así, puede dar la impresión de tener un mayor número de recursos de
los que realmente tiene. Cada uso de un recurso virtual da como resultado el uso de un recurso
real apropiado. En ese sentido, un recurso virtual es una visión abstracta de un recurso tomado
por un cómputo.
El uso de recursos virtuales comenzó con el empleo de dispositivos virtuales. Para impedir
la interferencia mutua entre programas, fue una buena idea asignar un dispositivo exclusiva-

01 MAQ. CAP. 01(F0694).indd 14 8/10/07 12:44:54 AM


1.3 La operación de un sistema operativo 15

mente para ser usado por un programa. Sin embargo, un sistema de cómputo no poseía mu-
chos dispositivos reales, así que se usaban dispositivos virtuales. Un sistema operativo creaba
un dispositivo virtual cuando un usuario necesitaba un dispositivo de E/S. Así, las áreas de disco
llamadas disco1 y disco2 en la tabla 1.6 podían considerarse como pequeños discos virtuales
basados en el disco real. Los dispositivos virtuales también se usan en los sistemas operati-
vos contemporáneos. Un servidor de impresora es un ejemplo común de un dispositivo virtual.
Cuando un programa desea imprimir un archivo, el servidor de impresora simplemente copia el
archivo en la cola de la impresora. El programa que pide la impresión continúa con su operación
como si la impresión se hubiera realizado. El servidor de impresora continuamente examina
la cola de la impresora e imprime cualquier archivo que encuentra en la cola.
La mayoría de sistemas operativos proveen un recurso virtual llamado memoria virtual, lo
cual es una ilusión de una memoria de mayor tamaño que la memoria verdadera de una compu-
tadora. Su uso le permite a un programador ejecutar un programa cuyo tamaño puede exceder el
de la memoria real.
Algunos sistemas operativos crean máquinas virtuales (VM) a fin de que se asigne cada
máquina a un usuario. Las máquinas virtuales se crean particionando la memoria y los dispositi-
vos de E/S de una máquina real. La ventaja de este enfoque es doble. La asignación de una má-
quina virtual a cada usuario elimina la interferencia mutua entre los usuarios. También le permite
a cada usuario seleccionar el sistema operativo de su preferencia para ejecutar en su máquina
virtual. En efecto, este arreglo le permite a los usuarios usar sistemas operativos diferentes en el
mismo sistema de cómputo, simultáneamente (véase la sección 14.5).

1.3.3 Seguridad y protección

Una persona no autorizada puede tratar de usar o modificar un archivo. También puede tratar de
interferir con el uso del archivo por los usuarios autorizados y sus programas. Un sistema opera-
tivo debe frustrar tales intentos. La protección y la seguridad son dos aspectos de este problema.
La función de protección contrarresta las amenazas de interferencia o uso no autorizado que son
planteadas por los usuarios de un sistema de cómputo, mientras que la función de seguridad con-
trarresta las amenazas similares que son planteadas por personas fuera del control de un sistema
operativo.
Cuando un sistema de cómputo funciona en aislamiento completo, los aspectos de protec-
ción y de seguridad pueden separarse fácilmente. El sistema operativo verifica la identidad de
una persona cuando entra al sistema a través de una revisión de la contraseña. Este procedimien-
to se llama autenticación. Por consiguiente, las amenazas a la seguridad no surgen en el sistema
si el procedimiento de autenticación es a prueba de tontos. Una declaración de abrir un archivo
ejecutada por un programa plantea una amenaza de protección si el usuario que inició el progra-
ma no está autorizado para acceder al archivo. El sistema de archivo contrarresta esta amenaza
abortando tal programa. La figura 1.9 ilustra este arreglo.
Cuando un sistema de cómputo está conectado al Internet, y un usuario descarga un pro-
grama, hay peligro de que el programa descargado pueda interferir con otros programas o con
recursos del sistema. Ésta es una amenaza a la seguridad porque la interferencia se debe a alguna
persona fuera del sistema, llamada intruso, quien escribió el programa descargado o lo modi-
ficó, a fin de interferir con otros programas. Tales amenazas a la seguridad se plantean a través
de un caballo de Troya, el cual es un programa con una función legítima conocida y una fun-
ción maliciosa bien disfrazada, o a través de un virus, el cual es un pedazo de código con una

01 MAQ. CAP. 01(F0694).indd 15 8/10/07 12:44:54 AM


16 CAPÍTULO 1 Introducción

Sistema de cómputo
Amenazas a
la seguridad Recursos
Intruso

Amenazas a
la protección
Internet
Autenticación
de programas Usuarios

Figura 1.9 Panorama general de las funciones de protección y seguridad.

función maliciosa que se adhiere a otros programas y se dispersa a otros sistemas cuando tales
programas se copian. Otra clase de amenazas a la seguridad está planteada por los gusanos, que
son programas que se reproducen por sí mismos a través de huecos hallados en los mecanismos
de seguridad de los sistemas operativos.
Los sistemas operativos enfrentan las amenazas de seguridad al garantizar que un programa
no puede modificarse mientras está siendo copiado del Internet, y taponando huecos de seguri-
dad cuando son descubiertos. Se espera que los usuarios contribuyan a la seguridad actuando con
cautela cuando descargan programas del Internet.

1.4 PANORAMA PRELIMINAR DEL LIBRO

Las visiones abstractas nos ayudan a limitar el alcance de estudio a fin de que podamos cen-
trar la atención en una característica seleccionada, y para presentar ideas o conceptos genéricos.
Usaremos visiones abstractas para presentar el diseño e implementación de características de un
sistema operativo a lo largo de este libro.
En la parte I del libro, enfocamos la atención en conceptos fundamentales, es decir, cómo
organiza un sistema operativo su propio funcionamiento y cómo maneja los programas del usua-
rio, así como los recursos fundamentales en el sistema, es decir, el CPU, la memoria y los archivos.
La parte II del libro se dedica a temas avanzados de la administración de programas del usuario
y de los recursos del buzón, a las técnicas del diseño usadas para asegurar que los sistemas ope-
rativos puedan adaptarse a la evolución en la tecnología de las computadoras y a las expectativas
de los usuarios de la computadora. Las partes I y II estudian principalmente los sistemas ope-
rativos para ambientes convencionales de computación caracterizados por el uso de un sistema
de cómputo individual que tenga un CPU individual; sólo el capítulo 13 estudia los siste-
mas operativos para el ambiente de computación de multiprocesadores. La parte III del libro
se dedica a un estudio de los sistemas operativos distribuidos, lo cual cobró importancia en
la década de los noventa debido a los avances en redes y a la disponibilidad de hardware de
computación barato.

01 MAQ. CAP. 01(F0694).indd 16 8/10/07 12:44:54 AM


1.4 Panorama preliminar del libro 17

1.4.1 Parte I: Conceptos fundamentales

Se dice que un sistema operativo es manejado por eventos. Un evento es cualquier situación que
requiere atención del sistema operativo, por ejemplo, una petición del recurso por un programa
del usuario o el fin de una operación de E/S. Cuando ocurre un evento, el control del CPU se
pasa al sistema operativo. Éste analiza el acontecimiento y realiza las acciones apropiadas. Por
ejemplo, cuando un programa pide un recurso, el sistema operativo lo asigna si está disponible
y cuando termina la operación de E/S, informa al programa que solicitó la operación de E/S e
inicia otra operación de E/S en el dispositivo, si alguno está pendiente. Después de atender el
evento, el sistema operativo da las indicaciones a un programa de usuario para la ejecución en
el CPU.

Sistema
operativo

Evento Evento
Sistema de Programas de
cómputo los usuarios

Ambiente de cómputo

Figura 1.10 Un sistema operativo en su ambiente de cómputo.

El funcionamiento manejado por eventos del sistema operativo mostrado en la figura 1.10
es una visión lógica de su funcionamiento. En la visión física correspondiente, el fin de una ope-
ración de E/S o una solicitud del recurso pedido por un programa causa una interrupción en el
sistema de cómputo. El CPU se diseña para reconocer una interrupción y desviarse a sí mismo a
la ejecución de una rutina de interrupción del proceso, que activa una rutina apropiada de manejo
de los eventos. Esta visión física, que es el fundamento del estudio de los sistemas operativos,
se desarrolla en la sección 2.1.
Como se mencionó en la sección 1.2, un sistema operativo tiene que lograr la utilización
efectiva del sistema de cómputo, que es la combinación del uso eficiente y de la conveniencia
del usuario que se ajuste mejor a su ambiente de cómputo. Los ambientes diferentes de compu-
tación, tales como los interactivos y de tiempo real, evolucionaron en respuesta a los avances
en las computadoras y en los nuevos requisitos de los usuarios de la computadora. En cada
ambiente de cómputo, un sistema operativo usa técnicas apropiadas para manejar los programas
del usuario y los recursos de sistema. Estudiamos estas técnicas en el capítulo 2 del libro. Un
ambiente moderno de computación contiene aspectos de varios ambientes de cómputo, tales
como no interactivo, interactivo, es decir, de tiempo compartido, de tiempo real y los ambientes
de computación distribuida, por lo que estas técnicas se usan también en un sistema operativo
moderno.

01 MAQ. CAP. 01(F0694).indd 17 8/10/07 12:44:55 AM


18 CAPÍTULO 1 Introducción

Manejo de los cómputos del usuario El sistema operativo usa la abstracción llamada pro-
ceso para ayudarlo a organizar la ejecución de los programas. Un proceso es simplemente una
ejecución de un programa. Las estructuras computacionales dan lugar a procesos con carac-
terísticas diferentes; por ejemplo, la ejecución secuencial de programas individuales produce
los procesos que operan uno tras otro, mientras que los programas coejecutables dan lugar a los
procesos que operan concurrentemente. El uso de la abstracción de proceso le permite al sistema
operativo manejar tales ejecuciones de programa de manera uniforme. La noción de un hilo se
introduce para reducir la sobrecarga del sistema operativo que interviene en la administración de
la ejecución de los programas. Un sistema operativo necesita rastrear mucho menos información
cuando se trata de un hilo que cuando se trata de un proceso. Excepto por esta diferencia, los
procesos y los hilos son similares en otros aspectos; por eso usamos el término proceso como
un término genérico tanto para el proceso como para el hilo. Analizamos procesos e hilos en el
capítulo 3.
Un sistema operativo pone la mira en lograr la utilización efectiva de un sistema de cómpu-
to, compartiendo el CPU entre varios procesos. Usa una política de planificación para decidir
cuál proceso debería ejecutarse en cualquier momento. En el capítulo 4, estudiamos las políti-
cas clásicas de planificación, que están dirigidas al uso eficiente de un sistema de cómputo o a
una conveniencia alta del usuario; y las políticas de planificación usadas en los sistemas ope-
rativos modernos, que ponen la mira en las combinaciones adecuadas del uso eficiente y de la
conveniencia del usuario.

Administración de la memoria Un sistema operativo asigna un área de memoria cuando


un proceso solicita memoria, rastrea las áreas de memoria liberadas por los procesos e intenta
usar otra vez las áreas de memoria liberadas eficazmente, mientras que satisface las nuevas
solicitudes de memoria. El aspecto clave de la administración de memoria es la fragmentación
de memoria, que es la presencia de áreas libres de memoria inutilizables. En la figura 1.11a),
alguna memoria ha sobrado después de asignarle la memoria a los procesos Pi y Pj . Esta área
de memoria permanece sin uso porque es demasiado pequeña para acomodar un proceso. La
situación empeora cuando el proceso Pi completa su operación, y el sistema operativo inicia un
proceso nuevo Pk en alguna parte de la memoria liberada por Pi . Ahora, la memoria contiene dos
áreas libres pero sin uso de memoria, si bien conjuntamente son bastante grandes para acomodar
algún otro proceso Pl . Describimos técnicas de aprovechamiento de memoria y el problema de
fragmentación de memoria en el capítulo 5.
Los sistemas operativos modernos proveen la memoria virtual, lo cual es una ilusión de una
memoria que es mayor que la memoria real de un sistema de cómputo. El uso de memoria virtual
también supera el problema de la fragmentación de memoria. La memoria virtual se implementa
como sigue: el código y los datos de un proceso se almacenan en un disco. En cualquier instante
durante la operación del proceso, sólo algunas partes de su código y los datos se guardan en la
memoria; las partes nuevas se cargan en ésta sólo cuando se necesitan durante su operación. El
sistema operativo remueve una parte del código de un proceso o datos de la memoria si considera
que la parte no es necesaria durante algún tiempo en el transcurso de la operación del proceso.
La memoria virtual se implementa usando el modelo de la asignación de memoria no con-
tigua. El CPU pasa cada dirección de la instrucción o la dirección de datos usada durante la
operación del proceso a una unidad especial del hardware llamada unidad de administración
de memoria, que consulta la información de asignación de memoria para el proceso y calcula
la dirección en la memoria donde realmente reside la instrucción o los datos. Si la parte de un

01 MAQ. CAP. 01(F0694).indd 18 8/10/07 12:44:55 AM


1.4 Panorama preliminar del libro 19

Sistema Sistema
operativo operativo

Proceso Pk
Proceso Pi

Proceso Pj Proceso Pj

a) b)

Figura 1.11 Fragmentación de la memoria: áreas libres no utilizables.

proceso que contiene una dirección requerida no existe en la memoria, ocurre una interrupción
“ausente en la memoria” y el sistema operativo carga la parte perdida en la memoria y reanuda la
operación del proceso (véase la figura 1.12). Para lograr una operación eficiente, el sistema ope-
rativo tiene que asegurar una tasa baja de interrupciones “ausente en la memoria”. Las técnicas
destinadas para este propósito se describen en el capítulo 6.

Memoria

Sistema
Interrupción operativo
“ausente en Carga/remoción de
la memoria” códigos y datos
Unidad de Código y datos de
administración los procesos
de memoria Memoria
asignada
a Pi

Figura 1.12 Operación de la memoria virtual.

Manejo de los archivos Los usuarios de la computadora esperan un acceso rápido a los
archivos, confiabilidad al encarar las fallas, habilidad para compartir los archivos con compañe-
ros de trabajo y una garantía de que ninguna de las personas no autorizadas pueden usar o ma-
nipular indebidamente sus archivos. El sistema de archivo provee una visión lógica al usuario,
que consta de una jerarquía del directorio del sistema de archivos, en el cual cada usuario tiene
un directorio raíz. El usuario puede crear directorios, o carpetas, como se señala en el sistema
operativo Windows, en su directorio raíz, y otros directorios u otras carpetas en estos directorios,
etc. Un usuario puede autorizar a algunos compañeros de trabajo usar una cierta cantidad de

01 MAQ. CAP. 01(F0694).indd 19 8/10/07 12:44:56 AM


20 CAPÍTULO 1 Introducción

sus archivos, informando al sistema de archivos los nombres o identidades de los compañeros
de trabajo y los archivos o los directorios que tienen autorizado usar. El sistema de archivo
también realiza algunas otras tareas. Asigna espacio en un disco para grabar un archivo. Para
asegurar fiabilidad, protege los datos en el archivo, y también lo hace con sus propios datos,
tales como directorios, en contra de daño debido a fallas, como los medios defectuosos de E/S
o las fallas de energía eléctrica. Todas estas características de sistemas de archivo se discuten
en el capítulo 7.
El arreglo usado para implementar protección y seguridad de archivos se describió ante-
riormente, en la sección 1.3.3. Para fortalecer el arreglo de seguridad, los datos de contraseñas
almacenados en el sistema operativo se cifran con una llave secreta conocida sólo por el sistema
operativo. Por tanto, un intruso no puede obtener contraseñas de usuarios excepto por prueba y
error, lo cual es prohibitivamente caro y consume mucho tiempo. La protección y las amenazas
a la seguridad, la técnica de cifrado y los diversos métodos usados para implementar protección
se describen en el capítulo 8.

1.4.2 Parte II: Temas avanzados

Sincronización de procesos y bloqueos mutuos (deadlocks) Los procesos de una aplica-


ción coordinan sus actividades para realizar sus acciones en un orden deseado; a esto se le llama
sincronización de procesos. La figura 1.13 ilustra dos clases de sincronización de procesos. La
figura 1.13a) muestra los procesos denominados crédito y débito que tienen acceso al balance
en una cuenta bancaria. Los resultados pueden ser incorrectos si ambos procesos actualizan el
balance al mismo tiempo, así que deben realizar sus actualizaciones estrictamente una tras otra.
La figura 1.13b) muestra un proceso denominado generar —que produce algunos datos y los
pone en una variable denominada muestra— y el proceso denominado analizar —que realiza
análisis en los datos contenidos en la variable muestra—. En ese momento, el proceso analizar
no debe realizar el análisis hasta que el proceso generar haya depositado el siguiente lote de
datos en muestra, y el proceso generar no debe producir el siguiente lote de datos hasta que el
proceso analizar haya analizado los datos previos. Los lenguajes de programación y los sistemas
operativos proveen varias facilidades que los procesos pueden usar para realizar la sincroniza-
ción, mientras que la arquitectura de computadoras provee algunas instrucciones especiales para
admitir la implementación de estas facilidades. Todas estas características y técnicas de sincro-
nización de proceso se describen en el capítulo 9.
Los procesos también pueden interactuar a través del paso de mensajes. Cuando un proceso
envía alguna información en un mensaje para otro proceso, el sistema operativo almacena el
mensaje en sus propias estructuras de datos hasta que el proceso del destino haga una petición
para recibir un mensaje. También sincroniza la operación del remitente y los procesos del desti-
no. Los detalles del paso de mensajes se describen en el capítulo 10.
Los procesos comparten los recursos de un sistema de cómputo. Si un recurso solicitado por
algún proceso Pi se asigna en ese momento al proceso Pj, Pi tiene que esperar a que Pj libere el
recurso. Un bloqueo mutuo es una situación en la cual algunos procesos esperan las acciones
mutuas indefinidamente. Éste afecta adversamente la actuación de un sistema porque los pro-
cesos participantes no pueden hacer ningún progreso y los recursos que se les asignan se des-
aprovechan. Un sistema operativo usa varias técnicas para manejar los bloqueos mutuos. Éstas
abarcan desde las medidas drásticas, como abortar un proceso involucrado en un bloqueo mutuo
y distribuir sus recursos entre otros procesos, hasta usar políticas de asignación de recursos que

01 MAQ. CAP. 01(F0694).indd 20 8/10/07 12:44:59 AM


1.4 Panorama preliminar del libro 21

Crédito Débito

Generar Analizar

Balance Muestra
a) b)

Figura 1.13 Dos tipos de sincronización de procesos.

aseguran que no surjan bloqueos mutuos en un sistema. Estudiamos las técnicas de manejo de
bloqueos mutuos que se usan en los sistemas operativos en el capítulo 11.

Implementación de operaciones con archivos Al implementar operaciones con archivos,


es importante asegurar el buen desempeño de un proceso que participa en una actividad de pro-
cesamiento de archivos, así como un buen desempeño de los dispositivos de E/S. Para lograr
esto, las operaciones del archivo son de hecho implementadas por un sistema de control de
entradas y salidas (IOCS). Cuando un proceso emite una operación de lectura en un archivo,
el sistema de archivos invoca al IOCS para que implemente la operación de lectura al realizar
las operaciones apropiadas de E/S en un dispositivo. El IOCS utiliza varias técnicas para im-
plementar eficazmente las operaciones de E/S. Las técnicas de buffering y de bloqueo aceleran
el acceso a los datos almacenados en el dispositivo de E/S, mientras que las técnicas de caching
y de planificación de discos se usan para asegurar el buen desempeño de un disco. Los diferentes
tipos de dispositivos de E/S y las técnicas de buffering, bloqueo y planificación de discos que se
usan en un IOCS se analizan en el capítulo 12.

Sistemas operativos de multiproceso Un sistema de cómputo de multiproceso puede pro-


veer un alto desempeño al prestar servicio a varios procesos simultáneamente. También acelera
los cómputos del usuario al planificar sus procesos de manera simultánea. El sistema operativo
tiene que usar técnicas especiales de planificación y de sincronización para alcanzar estas venta-
jas. Analizamos estas técnicas en el capítulo 13.

La estructura de los sistemas operativos Los sistemas operativos modernos, tales como
Unix y Windows, cuentan con una vida útil muy larga durante la cual tienen lugar varios cam-
bios en la arquitectura de computadoras y en los ambientes de cómputo. Por tanto, tales sistemas
operativos tienen que ser portátiles a fin de que puedan implementarse en muchas arquitectu-
ras de computadora, y extensibles a fin de que puedan satisfacer los nuevos requisitos producto
de los cambios de la naturaleza del ambiente de cómputo. Estudiamos técnicas de diseño del
sistema operativo para la portabilidad y la extensibilidad en el capítulo 14.

01 MAQ. CAP. 01(F0694).indd 21 8/10/07 12:44:59 AM


22 CAPÍTULO 1 Introducción

1.4.3 Parte III: Los sistemas operativos distribuidos

La arquitectura de los sistemas distribuidos Un sistema de cómputo distribuido consta


de varios sistemas de cómputo, llamados nodos, conectados a través de una red. El uso de un
sistema de cómputo distribuido provee tres ventajas cruciales: la aceleración de un cálculo al
planificar simultáneamente sus procesos en nodos diferentes del sistema, la alta fiabilidad a
través de la redundancia de los recursos y la compartición de recursos en nodos diferentes. Se
utilizan paradigmas nuevos de computación, tales como las llamadas de procedimiento remoto
para sacar provecho de las características de un sistema distribuido. El modelo de un sistema de
cómputo distribuido, su hardware de sistema de redes y el software, los paradigmas de compu-
tación distribuida y las clases de sistemas operativos usados para los sistemas distribuidos se
analizan en el capítulo 15.

Aspectos teóricos de los sistemas distribuidos Las demoras en la red en un sistema dis-
tribuido pueden conducir a una visión inconsistente de datos localizados en diferentes nodos del
sistema distribuido. La figura 1.14 muestra las cuentas bancarias A y B ubicadas en los nodos X y
Y del sistema distribuido que contienen 2 000 dólares y 500 dólares, respectivamente. Una tran-
sacción bancaria transfiere 1 000 dólares de la cuenta A a la cuenta B. El observador localizado
en el nodo Z obtendría una visión inconsistente de los balances en las cuentas A y B si él regis-
trara el balance en la cuenta A anterior a la transferencia, y el balance en la cuenta B posterior a
la transferencia; se encontraría con que las cuentas A y B contienen 2 000 y 1 500 dólares, res-
pectivamente. Los algoritmos para registrar una visión coherente de datos en un sistema distri-
buido deben evitar tales problemas. Se confrontan problemas similares al determinar el orden
cronológico de los eventos que ocurren en nodos diferentes del sistema. Estos problemas y los
métodos para abordarlos se estudian en el capítulo 16.

Nodo A B Nodo
2000 500
X Y

Nodo
Z

Figura 1.14 Un observador registra balances inconsistentes en las cuentas de banco A y B.

Las funciones de control distribuido Las funciones de control de un sistema operativo


convencional, tales como la planificación, la asignación de recursos y la detección de bloqueos
mutuos, requieren una visión coherente de: 1) los datos relativos a los recursos, y 2) las activida-
des en los procesos. Sin embargo, en un sistema distribuido, el uso de algoritmos para registrar
visiones coherentes involucra demoras y sobrecarga, de modo que los sistemas operativos dis-
tribuidos usan algoritmos especiales para realizar funciones de control sin requerir información
coherente acerca de los recursos y los procesos localizados en los diferentes nodos del sistema.
Estos algoritmos se analizan en el capítulo 17.

01 MAQ. CAP. 01(F0694).indd 22 8/10/07 12:44:59 AM


Ejercicio 1 23

La recuperación El estado de un proceso es el conjunto de información que describe la


actividad existente durante el proceso. Una falla, como un choque de un nodo o de un enlace de
comunicación, puede afectar o destruir los estados de algunos de los procesos que estaban en
operación cuando la falla ocurrió. Los sistemas operativos usan dos enfoques para restaurar los
procesos afectados por un choque. En el enfoque de tolerancia de falla, suficiente información
concerniente al estado de un proceso es guardada durante la operación de un proceso. Se usa
para reparar el estado de un proceso cuando una falla ocurre. En el enfoque de recuperación,
el estado de un proceso se graba periódicamente en forma de respaldo, y el proceso se restaura
a ese estado cuando una falla ocurre. Para evitar incongruencias cuando un proceso se restau-
ra a un estado previo, algunos otros procesos también tendrían que restaurarse a sus estados ante-
riores, etc. Por ejemplo, considere la falla del nodo Y en la transacción bancaria de la figura 1.14
mientras que 1 000 dólares se suman al balance de la cuenta B. Una técnica de tolerancia de falla
completaría la operación de actualización después de la falla y obtendría el balance correcto, es
decir, 1 500 dólares en la cuenta B. Una técnica de recuperación podría restaurar el balance en
la cuenta B a un valor anterior, es decir, 500 dólares. Entonces, también tendría que restaurar el
balance de la cuenta en A para un valor anterior mutuamente consistente, es decir, 2 000 dólares.
La tolerancia de falla y las técnicas de recuperación usadas en los sistemas distribuidos se estu-
dian en el capítulo 18.

Sistema de archivos distribuidos El sistema de archivos distribuidos almacena archivos


en varios nodos del sistema distribuido, de tal manera que un archivo y un proceso que tengan
acceso al sistema pueden existir en nodos diferentes. Esta situación tiene varias consecuencias:
el desempeño de la actividad de procesamiento de archivos es deficiente porque se tiene acceso
en la red a los datos del archivo. También, la falla de alguno de los dos nodos, o el de la red que
conecta a los dos, puede afectar la actividad de proceso del archivo. Un sistema de archivos
distribuidos mejora el desempeño al colocar el archivo en la memoria caché en el nodo donde el
proceso existe, y también lo hace con la fiabilidad a través de las técnicas especiales que asegu-
ran que una falla transitoria de un nodo que contiene el proceso o el archivo no desestabiliza la
actividad de procesamiento del archivo. Éstas y otras técnicas usadas por los sistemas de archi-
vos distribuidos se analizan en el capítulo 19.

La seguridad del sistema distribuido Cuando los procesos en un sistema distribuido inter-
cambian mensajes, éstos pueden viajar sobre los canales de comunicación públicos y atravesar
sistemas de cómputo que no están bajo el control del sistema operativo distribuido. Como se
estudia en la sección 1.3.3, un intruso puede tomar el control de estos canales de comunicación o
sistemas de cómputo y manipular indebidamente mensajes, copiarlos o destruirlos, o crear falsos
mensajes. Al usar mensajes modificados, copiados o falsos, el intruso puede aun engañar al pro-
cedimiento de autenticación y suplantar a un usuario del sistema. Estas amenazas a la seguridad
son contrarrestadas usando el cifrado para impedir el manoseo de los mensajes, y usando proce-
dimientos especiales de autenticación a fin de impedir la suplantación de los usuarios a través de
mensajes copiados. Estas técnicas se estudian en el capítulo 20.

EJERCICIO 1
1. Dé ejemplos de dos situaciones en las cuales la conveniencia del usuario está en conflicto con el uso
eficiente de un sistema de cómputo.

01 MAQ. CAP. 01(F0694).indd 23 8/10/07 12:45:00 AM


24 CAPÍTULO 1 Introducción

2. La priorización de los recursos puede realizarse para proveer: a) equidad en el uso de los recursos,
b) un uso más eficiente. Describa una situación en la cual la priorización de los recursos provea equidad
en el uso de recursos. Lea el capítulo 2 y describa una situación en la cual la priorización se usa para
obtener un uso eficiente.
3. Un diseñador del sistema operativo hace la siguiente declaración de las políticas: “Considere la priori-
zación de un recurso de un programa sólo si el programa puede reanudar su operación después de que el
recurso se le vuelve a conceder como si la priorización no hubiera ocurrido.” Justifique la priorización
del CPU y la memoria de un programa. También analice por qué la priorización de un cartucho de cinta
magnética o una impresora no es aconsejable.
4. En el sistema operativo Unix, un servidor de impresora implementa la impresión de archivos de acuer-
do con el deseo de los usuarios. Cuando un usuario ejecuta un comando para imprimir un archivo, el
servidor de la impresora copia el archivo en el disco y lo forma en la cola de la impresora. Se imprime
cuando su entrada alcanza el inicio de la cola de la impresora. Escriba una descripción del servicio de
impresión como un uso de dispositivos virtuales y la operación simultánea de periféricos en línea.
5. Haga comentarios sobre la validez de la siguiente declaración: la asignación de recursos particionada
provee una mayor conveniencia al usuario que la asignación basada en los recursos en común, pero
puede proveer una mala eficiencia.
6. Escriba una nota pequeña sobre los costos y los beneficios de la asignación de recursos basada en los
recursos en común. Describa situaciones en las cuales se magnifique: a) la eficiencia y b) la convenien-
cia del usuario.
7. Escriba una nota pequeña sobre el intercambio describiendo: a) la sobrecarga del sistema operativo y
b) el impacto sobre la eficiencia.
8. Haga comentarios sobre implicaciones de las siguientes características del uso eficiente y de la conve-
niencia del usuario:
a) la secuencia de programas;
b) los dispositivos virtuales.
9. Un programa está en un estado inactivo si no participa en ninguna actividad (puede estar esperando
la acción del usuario). Haga comentarios sobre la validez de la siguiente declaración: “Un programa
inactivo también consume recursos.”
10. Si un “componente de un sistema operativo” se define como un programa que coadyuva a manejar los
cálculos del usuario o los recursos, ¿calificarían los siguientes programas para ser designados como
componentes de un sistema operativo? Dé una respuesta de sí/no sustentada con argumentos. Si usted
tiene dudas acerca de una respuesta de sí/no, descríbala, pero dé una respuesta de sí/no de cualquier
manera.
a) el compilador para un lenguaje de programación concurrente,
b) el procesador de comandos,
c) el programa ssh (este programa se usa para el uso remoto de un sistema de cómputo, security
shell),
d) el sistema de archivos.
11. Una visión lógica de ejecución de un programa escrito en un lenguaje L de alto nivel consta de los datos
del programa que se alimentan para su código en lenguaje L para producir resultados (véase la figura
1.3a)). Desarrolle una vista física de la compilación y la ejecución de este programa.
12. Una vista lógica del procesamiento de archivos realizada por un usuario consta de directorios, archivos
y declaraciones en un programa para abrir un archivo y la lectura/escritura de sus datos. Escriba una
nota sobre la visión física del procesamiento de archivos realizada por un usuario.

01 MAQ. CAP. 01(F0694).indd 24 8/10/07 12:45:00 AM


Bibliografía 25

13. Un ambiente de cómputo es simplemente el ambiente en el cual se usa un sistema de cómputo. Haga
una lista de ambientes de cómputo que tengan características bien definidas concernientes a la utiliza-
ción efectiva.

BIBLIOGRAFÍA

En la mayoría de los textos de SO, generalmente se propone la visión de un sistema operativo como un
conjunto de programas. Tanenbaum (2001), Stallings (2001), Nutt (2004) y Silberschatz et al. (2005) son
algunos de los textos recientes sobre sistemas operativos.
Berzins et al. (1986) analizan cómo la complejidad de diseño de un sistema de software puede redu-
cirse construyendo un conjunto de abstracciones que oculten el funcionamiento interno de un subsistema.
La mayoría de los libros en la ingeniería de software discuten el papel de la abstracción en el diseño de
software. El artículo de Parnas y Siewiorek (1975) sobre el concepto de la transparencia en el dise-
ño de software se considera un clásico de la ingeniería de software. El libro de Booch (1994) estudia las
abstracciones en el desarrollo del software orientado a objetos.
El concepto de dispositivos virtuales se usó primero en el sistema de operación simultánea de perifé-
ricos en línea del sistema de cómputo Atlas, desarrollado en la Universidad de Manchester. Se le describe
en Kilburn et al. (1961).
Ludwig (1998) y Ludwig (2002) describen diferentes tipos de virus, mientras que Berghel (2001)
describe el gusano de Código Rojo que causó descalabros en 200l. Pfleeger y Pfleeger (2003) es un texto
sobre la seguridad de computadoras. Garfinkel et al. (2003) analizan la seguridad en los sistemas operati-
vos Solaris, Mac SO, Linux y FreeBSD. Russinovich y Salomon (2005) estudian aspectos de seguridad en
Windows.

1. Berghel, H. (2001): “The Code Red worm”, Communications of the ACM, 44 (12), 15-19.
2. Berzins, V., M. Gray y D. Naumann (1986): “Abstraction-based software development”, Commu-
nications of the ACM, 29 (5), 403-415.
3. Booch, G. (1994): Object-Oriented Analysis and Design, Benjamin-Cummings, Santa Clara.
4. Garfinkel, S., G. Spafford y A. Schwartz (2003): Practical UNIX and Internet Security, 3a. ed.,
O’Reilly, Sebastopol.
5. Kilburn, T., D.J. Howarth, R.B. Payne y F.H. Sumner (1961): “The Manchester University Atlas
Operating System, Part I: Internal Organization”, Computer Journal, 4 (3), 222-225.
6. Ludwig, M.A. (1998): The Giant Black Book of Computer Viruses, 2a. ed., American Eagle, Show
Low.
7. Ludwig, M.A. (2002): The Little Black Book of Email Viruses, American Eagle, Show Low.
8. Nutt, G. (2004): Operating Systems—A Modern Perspective, 3a. ed., Addison Wesley, Reading.
9. Parnas, D.L. y D.P. Siewiorek (1975): “Use of the concept of transparency in the design of hierar-
chically structured systems”, Communications of the ACM, 18 (7), 401-408.
10. Pfleeger, C.P. y S. Pfleeger (2003): Security in Computing, Prentice Hall, N.J.
11. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.

01 MAQ. CAP. 01(F0694).indd 25 8/10/07 12:45:01 AM


26 CAPÍTULO 1 Introducción

12. Silberschatz, A., P.B. Galvin y G. Gagne (2005): Operating System Principles, 7a. ed., John Wiley,
Nueva York.
13. Stallings, W. (2001): Operating Systems—Internals and Design Principles, 4a. ed., Pearson Edu-
cation, Nueva York.
14. Tanenbaum, A.S. (2001): Modern Operating Systems, 2a. ed., Prentice-Hall, Englewood Cliffs.

01 MAQ. CAP. 01(F0694).indd 26 8/10/07 12:45:01 AM


Parte I
Conceptos fundamentales
Un sistema operativo controla el uso de los recursos de un sistema de cómputo, tales como los
CPU, la memoria y los dispositivos de E/S a fin de satisfacer los requerimientos computacionales
de los usuarios. Éstos esperan conveniencia, calidad de servicio y seguridad al ejecutar sus pro-
gramas, mientras que los administradores del sistema esperan un uso eficiente de los recursos de
la computadora y un buen desempeño al ejecutar los programas de los usuarios. Estas diversas
expectativas se conocen como la conveniencia del usuario, la seguridad y el uso eficiente de
los recursos, y forman las metas principales de un sistema operativo. El grado hasta el cual el
sistema operativo satisface estas metas depende del ambiente de cómputo, es decir, del hardware
del sistema de cómputo, sus interfaces con otras computadoras y la naturaleza de los cómputos
realizados por los usuarios.
Un proceso es la ejecución de un programa. Los programadores y los sistemas operativos
consideran y usan los procesos de manera diferente. Para un programador, la característica más
importante de los procesos es su capacidad para ejecutarse en forma concurrente y de interac-
cionar entre sí a fin de alcanzar una meta común. Para un sistema operativo, un proceso es un
medio para alcanzar la ejecución de los programas. De acuerdo con esto, analizaremos aspectos
relacionados con la creación de los procesos y su interacción mutua, así como su planificación
para el uso del CPU.
La memoria de un sistema de cómputo es compartida por un gran número de procesos. El
número de procesos que pueden alojarse en la memoria en cualquier momento influye en el
desempeño del sistema porque la presencia de muy pocos procesos podría conducir a la sub-
utilización del CPU. El desempeño del sistema se deteriora cuando algunas áreas de la memoria
permanecen sin usarse por ser demasiado pequeñas para alojar un proceso. A esta situación se
le llama fragmentación de la memoria; el sistema operativo debe evitar que esto suceda. Tam-
bién debe permitir la ejecución de programas grandes, cuyo tamaño podría sobrepasar el de la
memoria.
Los usuarios de la computadora esperan conveniencia y eficiencia mientras que crean, ma-
nipulan y comparten archivos con otros usuarios del sistema. También esperan que el sistema
de archivos suministre protección, seguridad y fiabilidad, de modo que sus archivos no se vean
sometidos al acceso ilegal o a la manipulación por otras personas, o a un daño debido a fallas.
En esta parte, estudiamos los conceptos y las técnicas fundamentales que se usan en los
sistemas operativos para gobernar el uso del CPU, la memoria y los archivos.

02 MAQ. PARTE 1.indd 27 8/10/07 12:53:01 AM


28 PARTE I Conceptos fundamentales

Mapa de ruta de la parte I

Parte I: Conceptos fundamentales

Visión general
de los sistemas
operativos

Estructura de Administración
Procesos Los sistemas
los sistemas de la memoria
e hilos de archivos
operativos

Protección
Sincronización La memoria
Planificación y
de procesos virtual
seguridad

Sincronización y programación Implementación


Paso de Bloqueos en sistemas operativos de las operaciones
mensajes mutuos de multiprocesador con archivos

Parte II: Tópicos avanzados

Capítulo 2: Visión general de los sistemas operativos


Este capítulo clave introduce los principios fundamentales de un sistema operativo (SO).
Las secciones iniciales analizan cómo el sistema operativo usa las características del hardware
del sistema de cómputo para controlar las actividades computacionales y de los dispositivos E/S
en los programas de los usuarios, y cómo los programas de los usuarios usan las características
del hardware para interaccionar con el sistema operativo y obtener los servicios que necesitan.
Las secciones posteriores estudian cinco clases de sistemas operativos (procesamiento por lotes,
multiprogramación, tiempo compartido, tiempo real y sistemas distribuidos) y describen los
principales conceptos y técnicas que se usan para satisfacer sus metas. La última sección analiza
la manera en que un sistema operativo moderno usa la mayoría de estos conceptos y técnicas.

Capítulo 3: Procesos e hilos


Este capítulo estudia tanto la visión del programador como la del sistema operativo de los
procesos. El análisis de la visión del programador tiene que ver con la manera en que se crean y
se terminan los procesos, y cómo interactúan entre sí. El estudio de la visión del sistema operati-
vo se centra en la manera en que el sistema operativo administra un proceso: cómo usa la noción
del estado del proceso para rastrear lo que está haciendo el proceso y cómo refleja los efectos de
un evento sobre los estados de los procesos afectados. El capítulo también introduce la noción
de hilos e ilustra sus características.

Capítulo 4: Planificación
La planificación es el acto de seleccionar el siguiente proceso que va a ser atendido por el
CPU. Este capítulo estudia cómo un planificador usa las técnicas fundamentales de prioridades

02 MAQ. PARTE 1.indd 28 8/10/07 12:53:02 AM


PARTE I Conceptos fundamentales 29

del proceso, el reordenado de las peticiones y la variación del intervalo de tiempo (time slice)
para alcanzar una combinación adecuada del servicio al usuario, el uso eficiente de los recursos
y el desempeño del sistema. Describe diferentes políticas de planificación y sus propiedades.

Capítulo 5: Administración de la memoria


Este capítulo se dedica a los fundamentos de la administración de la memoria. Comienza
con el estudio del modelo de asignación de memoria usado para un proceso y el soporte de hard-
ware para la protección de la memoria. Esto es seguido por un análisis de las técnicas de asigna-
ción de memoria y las causas de la fragmentación de la memoria. Luego estudia los elementos
del modelo de asignación no contigua de memoria, que se usa para reducir su fragmentación. El
soporte de hardware para el modelo de asignación no contigua de memoria y los dos enfoques
de la asignación no contigua de memoria llamados paginamiento y segmentación también son
estudiados.

Capítulo 6: La memoria virtual


Un sistema de memoria virtual usa el modelo de la asignación no contigua de memoria.
Conserva el código y la fecha de un proceso en un disco y carga porciones de éste en la memoria
cuando se requiere. El principio de la localidad de referencia ayuda a predecir qué partes de un
proceso posiblemente sirvan de referencia en el futuro inmediato. El desempeño de un proceso
se determina por la tasa a la cual sus partes se cargan en la memoria, lo que depende de la can-
tidad de memoria asignada.
Este capítulo trata de la implementación de la memoria virtual usando el paginamiento
con detalle. Estudia la noción de conjunto de trabajo que se usa para determinar la cantidad
de memoria que deberá asignarse a cada proceso y emplea algoritmos de reemplazo de página
para decidir qué páginas de un proceso deberán estar en la memoria en cualquier momento. Se
estudian los aspectos de código y de datos compartidos. También se describe la implementación
virtual de la memoria usando la segmentación.

Capítulo 7: Los sistemas de archivos


Este capítulo estudia la visión de un programador de los archivos y del sistema de archivos.
Describe los fundamentos de las organizaciones de archivos, las estructuras de directorios, las
operaciones con archivos y directorios, y la semántica de archivos compartidos, que determinan
la manera en que los resultados de las manipulaciones de archivos realizadas por los procesos
concurrentes son visibles entre sí. Se describen la tolerancia a las fallas usando las acciones
atómicas y la recuperación usando respaldos.

Capítulo 8: Protección y seguridad


Juntas, las medidas de protección y seguridad garantizan que solamente usuarios autoriza-
dos pueden tener acceso a un archivo. Este capítulo estudia los diferentes tipos de protección
y de amenazas a la seguridad en un sistema operativo, las medidas de protección y seguridad
que se usan para contrarrestar estas amenazas y el papel jugado por la técnica de cifrado en la
implementación de estas medidas.

02 MAQ. PARTE 1.indd 29 8/10/07 12:53:02 AM


02 MAQ. PARTE 1.indd 30 8/10/07 12:53:02 AM
Capítulo
2
Visión general de los
sistemas operativos

La interacción del sistema operativo con el sistema de cómputo y los programas del usuario es
un aspecto crucial de su operación. Las características de arquitectura del sistema de cómputo
se usan para realizar ésta. Estudiamos dos modos usados para implementar esta interacción: el
procesamiento de interrupción y las llamadas de sistema.
Un ambiente de cómputo se caracteriza por un sistema de cómputo, sus interfaces con otros
sistemas, sus usuarios y la naturaleza de sus requisitos computacionales. Las metas de un sistema
operativo se determinan por la noción de la utilización efectiva de un sistema de cómputo en el
ambiente de cómputo donde se usa, de modo que los sistemas operativos se clasifican sobre la
base de los ambientes de cómputo donde se emplean.
Analizaremos las clases diferentes de sistemas operativos. Para cada clase, caracterizaremos
el ambiente de cómputo en el cual un sistema operativo de esa clase funciona y describiremos las
técnicas típicas usadas para lograr la utilización efectiva de un sistema de cómputo. También in-
troduciremos definiciones y terminología pertinente de conceptos.
Un sistema operativo moderno contiene características de varias clases de sistemas opera-
tivos, así es que la visión general de conceptos y las técnicas previstas en este capítulo son im-
portantes para apreciar la necesidad y la importancia de las diversas características. La visión
general también provee un fondo útil para el estudio de componentes de los sistemas operativos
en posteriores capítulos.

2.1 EL SISTEMA OPERATIVO Y EL SISTEMA DE CÓMPUTO

La figura 2.1 ilustra el uso de la memoria durante la operación de un sistema operativo. La me-
moria está dividida en un área de sistema y un área del usuario. Algunos programas del sistema
operativo existen permanentemente en el área de sistema de la memoria para revisar y controlar
las actividades en el sistema de cómputo. Otros programas existen en un disco y son cargados en
el área transitoria cuando es necesario. El remanente de la memoria es ocupado por los progra-
mas del usuario. Se han usado diferentes términos para describir el conjunto de programas del
sistema operativo que existen en la memoria, por ejemplo, el monitor, el supervisor, el ejecutivo

03 MAQ. CAP. 02(F0694).indd 31 8/10/07 12:53:43 AM


32 CAPÍTULO 2 Visión general de los sistemas operativos

y el kernel (núcleo). De hecho, se usaron términos diferentes en el contexto de clases diferentes


de sistemas operativos. En este libro usamos uniformemente el término kernel para el conjun-
to de programas del sistema operativo existentes en la memoria.

Área del Kernel


sistema
Área transitoria

Área Programas de
de los los usuarios
usuarios

Figura 2.1 Utilización de la memoria durante la operación del sistema operativo.

El kernel cumple con las metas de un sistema operativo realizando un cúmulo de funciones
de control. Es un conjunto de programas y no una unidad del hardware, así es que desempeña
funciones de control al ejecutar las instrucciones en el CPU. Así, éste es usado por ambos: por
los programas del usuario y por el sistema operativo. Lo primero constituye el uso productivo
del CPU y contribuye a la eficiencia de éste. Lo segundo constituye la carga general del sistema
operativo.
Usamos el término conmutación del CPU para referirnos a la acción que fuerza éste a dejar de
ejecutar un programa y comenzar la ejecución de otro. Cuando el kernel necesita desempeñar
funciones de control, el CPU debe conmutarse a la ejecución del kernel. Después de comple-
tar las funciones de control, el CPU se conmuta nuevamente a la ejecución del programa de un
usuario. La conmutación del CPU entre los programas de los usuarios y el kernel es el aspecto
crucial de la operación de un sistema operativo. La sección 2.1.2 describe cómo se realiza.
Empezaremos esta sección describiendo las características importantes de un sistema de
cómputo.

2.1.1 El sistema de cómputo

La figura 2.2 recrea un modelo de un sistema de cómputo que muestra sólo aquellas unidades
funcionales que tienen importancia desde el punto de vista del sistema operativo. A continuación
describimos detalles importantes de estas unidades.

La Unidad Central de Proceso (CPU)


El CPU contiene dos clases de registros. Registros accesibles al programa, algunas veces lla-
mados registros de uso general o simplemente registros del CPU, que se usan para almacenar
direcciones o datos durante la ejecución de un programa. Y registros de control, que contienen
información que controla o influye la operación del CPU mismo. El registro del contador del
programa (PC) contiene la dirección de la siguiente instrucción a ejecutarse por el CPU. El re-
gistro de código de condición (CC) contiene un código que describe algunas propiedades del

03 MAQ. CAP. 02(F0694).indd 32 8/10/07 12:53:43 AM


2.1 El sistema operativo y el sistema de cómputo 33

Interrupciones
Bus
Unidad de Protección de E/S
Memoria administración ....
de la memoria
PSW

Registros
CPU

DMA
Controladores
del dispositivo
Dispositivos
Trayectoria de datos
Trayectoria de control
Trayectoria de interrupción

Figura 2.2 Modelo de un sistema de cómputo.

último resultado aritmético o lógico calculado por el CPU (por ejemplo, si es menor que cero).
El contenido de otros registros de control se describe posteriormente en esta sección. La palabra
de estado del programa (PSW) es un conjunto de registros de control en el sistema. La figura 2.3
ilustra la PSW. Nos referimos a cada registro de control individual como un campo de la PSW.

IM P IC MPI CC PC
IM : Máscara de interrupción
P : Modo privilegiado
IC : Código de interrupción
MPI : Información de protección de la memoria
CC : Código de condición
PC : Contador del programa

Figura 2.3 Campos de la palabra de estado del programa (PSW).

El modo privilegiado de operación del CPU El CPU puede operar en dos modos, desig-
nados modo del usuario y modo privilegiado. El campo del modo privilegiado (P) de la PSW es
un campo con un solo bit. Suponemos que este campo contiene un 1 si el CPU está en el modo
privilegiado y un 0 si está en el modo del usuario. Ciertas instrucciones pueden ejecutarse sólo
cuando el CPU está en el modo privilegiado. Tales instrucciones se llaman instrucciones privi-
legiadas.
Las instrucciones privilegiadas comúnmente implementan operaciones de control reque-
ridas por un sistema operativo para realizar una función de control, por ejemplo, la iniciación
de una operación de E/S o la colocación de información de protección para los programas. Las
instrucciones que cambian el contenido de los campos de PSW son en sí mismas instrucciones

03 MAQ. CAP. 02(F0694).indd 33 8/10/07 12:53:44 AM


34 CAPÍTULO 2 Visión general de los sistemas operativos

privilegiadas. El CPU está en el modo privilegiado cuando el kernel ejecuta, de modo que éste
pueda realizar funciones de control. El CPU está en el modo de usuario cuando se ejecuta un pro-
grama del usuario. Esta acción asegura que el programa del usuario no pueda ejecutar ninguna
instrucción que llegue a interferir con la operación de otros programas de usuarios o con el sis-
tema operativo.

El estado del CPU El conjunto de los registros accesibles al programa y la PSW conjun-
tamente contienen toda la información necesaria para ejecutar un programa en el CPU. Los
registros accesibles al programa contienen todos los valores de los datos y de las direcciones
puestos ahí durante la ejecución del programa. El campo del contador del programa (PC) contie-
ne la dirección de la siguiente instrucción que debe ejecutarse. El campo de código de condición
(CC) contiene un código que describe el último resultado aritmético o lógico calculado por el
CPU. Este código puede ser usado por una instrucción condicional de bifurcación. El campo de
modo privilegiado (P) indica si el CPU está en el modo privilegiado. El campo de información
de protección de la memoria (MPI) contiene información que indica las entidades de memoria a
las que el programa puede tener acceso. La máscara de interrupción (IM) y los campos de código
de interrupción (IC) contienen información relativa al manejo de las interrupciones. El uso de
esta información se describe posteriormente en esta sección.
El contenido de los registros del CPU y de la PSW conjuntamente indican lo que el CPU
está haciendo en cada momento, por lo que se dice que sus contenidos constituyen el estado del
CPU. Si el kernel necesita realizar una función de control mientras que un programa de usuario
se ejecuta en el CPU, guarda el estado del CPU y usa a éste para ejecutar su propio código. Cuan-
do la ejecución del programa del usuario debe reanudarse, el kernel simplemente vuelve a cargar
el estado salvado del CPU en los registros y en la PSW. La ejecución del programa entonces se
reanuda desde el punto en el cual el CPU fue retirado.

Dirección Instrucción P
0142 MOVE A, ALPHA 0
PSW
0146 COMPARE A, 1 00 0150
0150 BEQ NEXT CC PC
...
1 A
0192 NEXT Registros
... B
del CPU
0210 ALPHA DS 1 X
a) b)

Figura 2.4 a) Un programa, b) estado del CPU después de ejecutar la instrucción COMPARE.

Ejemplo 2.1 La figura 2.4 muestra un programa para una computadora hipotética. El CPU tiene
dos registros de datos A y B y un registro índice X. El programa mueve el valor de ALFA al registro
A y lo compara con 1. Sea 1 el valor de ALFA, por tanto, la operación de comparación coloca el
código de condición en 00 para señalar que los dos operandos son iguales. Ocurre una interrupción
al final de la instrucción COMPARE. El estado del CPU es como se muestra en la figura 2.4b).
Contiene a la PSW y al contenido de los registros A, B y X. El registro de código de condición
contiene 00 y el PC contiene 150, que es la dirección de la instrucción BEQ (bifurcación si es

03 MAQ. CAP. 02(F0694).indd 34 8/10/07 12:53:44 AM


2.1 El sistema operativo y el sistema de cómputo 35

igual). Si el estado del CPU se carga nuevamente en el CPU, el programa reanudará su ejecución
en la instrucción BEQ. El registro de código de condición contiene 00, así es que la instrucción se
ejecutará correctamente.

La jerarquía de la memoria
Idealmente, un sistema de cómputo debería contener una memoria grande y rápida a fin de que
el CPU no se haga más lento debido al acceso a la memoria. Sin embargo, la memoria rápida es
cara, así es que se usa una jerarquía de memoria para dar la impresión de una memoria grande
y rápida a un bajo costo. Una jerarquía de memoria contiene varias unidades de memoria con
velocidades discrepantes. La memoria más acelerada en la jerarquía es la de menor tamaño; las
memorias más lentas son de mayor tamaño. El CPU accede sólo a la memoria más rápida. Si
los datos o instrucción necesarios para el CPU no existen en esta memoria, se transfiere ahí desde
una memoria más lenta. El tiempo de acceso efectivo de memoria depende de con qué frecuencia
tales transferencias son necesarias durante la ejecución de un programa.
La figura 2.5 muestra un esquema de una jerarquía de memoria. La jerarquía contiene tres
unidades de memoria. La memoria caché es rápida y pequeña. La memoria principal (simple-
mente le llamaremos a ella memoria) es lenta y grande. El disco es la unidad más lenta y más
grande en la jerarquía. La memoria caché apresura el acceso a la memoria principal y ésta apre-
sura el acceso al disco. La unidad de administración de memoria (MMU) coadyuva a la gestión
efectiva de memoria realizada por el sistema operativo. El CPU pasa la dirección del byte para
la cual desea acceder al MMU. El MMU pasa una dirección traducida a la memoria caché. La
memoria caché lee o escribe el byte requerido, accediendo a la memoria principal sólo si el byte
requerido no está presente en la memoria caché. Se accede al disco sólo si el byte requerido no
está presente en la memoria principal.

Unidad de
administración Memoria Memoria
CPU
de la memoria caché principal
(MMU)

Figura 2.5 Jerarquía de la memoria que contiene la memoria caché, la memoria principal y el disco.

La unidad de administración de memoria (MMU) La MMU “traduce” cada dirección


de la memoria generada por el CPU a otra dirección llamada dirección física de memoria. La
característica de traducción de la dirección se usa en la asignación de memoria poco contigua.
También se emplea para implementar sistemas de memoria virtual que usan el disco como una
parte de la jerarquía de memoria (véase el capítulo 6). En interés de la simplicidad, no describi-
mos esta característica aquí.

La memoria caché La memoria caché guarda algunas instrucciones y valores de datos a los
que recientemente tuvo acceso el CPU. Si éste desea leer un byte de memoria, la memoria caché
es registrada para verificar si el byte existe en la memoria caché. Si es así, se le accede desde la
memoria caché. Si el byte no está presente en la memoria caché, se le carga desde la memoria

03 MAQ. CAP. 02(F0694).indd 35 8/10/07 12:53:44 AM


36 CAPÍTULO 2 Visión general de los sistemas operativos

y se completa el acceso. Para potenciar el desempeño de la memoria caché, el hardware de


la memoria no carga un byte individual de memoria en la memoria caché. Siempre carga un
bloque de memoria de tamaño fijo, designado como bloque de caché o línea de caché, en la
memoria caché. De esta manera, el acceso a un byte que está en la proximidad de un byte
de reciente acceso puede implementarse sin tener que acceder a la memoria. Cuando el CPU
escribe un valor nuevo en un byte, el valor se escribe en la memoria caché. Tarde o temprano
también deberá escribirse en la memoria. Existen esquemas diferentes para actualizar el byte
en la memoria. Un esquema simple es escribir el byte en la memoria caché y en la memoria
principal al mismo tiempo.
La relación de impactos (h) de la memoria caché indica la fracción de bytes accedida por
el CPU que se encontró en la memoria caché. En la práctica, se observan valores altos por dos
razones: los programas tienden a hacer accesos de memoria que están en la proximidad de ac-
cesos previos, lo que se llama localidad espacial, y algunos datos e instrucciones se acceden
repetidamente, lo que se llama localidad temporal. El tiempo de acceso efectivo a la memoria
está dado por la fórmula
Tiempo de acceso efectivo a la memoria:

 h  tiempo de acceso de la memoria caché


 (1  h)  (ttra  tiempo de acceso de memoria caché) (2.1)

donde ttra es el tiempo tomado para transferir un bloque de la memoria caché de la memoria a la
memoria caché. Si consideramos un bloque de memoria caché que tiene un tamaño de 1 byte, y
una memoria caché que es diez veces más rápida que la memoria, una relación de impacto de 0.8
provee un tiempo de acceso efectivo a la memoria que es solamente 30 por ciento del tiempo de
acceso de memoria, es decir, ¡apresura el acceso a la memoria más de tres veces! Sin embargo,
el tamaño de 1 byte del bloque de memoria caché no explota la localidad espacial, por tanto, una
relación de impacto de 0.8 es poco realista. Por consiguiente, en la práctica se usan bloques de
memoria caché mayores y se emplean organizaciones avanzadas de memoria para reducir ttra.
El procesador Intel Pentium usa un tamaño de bloque de memoria caché de 128 bytes y una or-
ganización de memoria que hace que ttra sea aproximadamente 10 veces el tiempo de acceso a la
memoria. Con una relación de impacto de la memoria caché de 0.97, esta organización provee un
tiempo de acceso efectivo a la memoria que es 40 por ciento del tiempo de acceso de memoria.
Las arquitecturas del procesador proveen varios niveles de memorias de caché para magnifi-
car la rapidez de acceso. Observe que la relación de impacto de la memoria caché es deficiente al
inicio de la ejecución de un programa porque ninguna de sus instrucciones o datos existen en la
memoria caché. La relación de impacto es más alta si el programa ha estado en ejecución durante
algún tiempo.
Las arquitecturas del procesador usan varios niveles de memorias caché para reducir el
tiempo de acceso efectivo a la memoria. Una memoria caché L1 (es decir, una memoria caché de
nivel 1) está incorporada en el chip mismo del CPU. Una memoria caché L2 puede ser externa
al CPU, pero estar directamente conectada. Una memoria caché L3 puede ser parte de un chip
de memoria.

La memoria principal Las unidades de memoria están directamente conectadas al bus. El


CPU está conectado al bus a través de la unidad de administración de la memoria y la memoria
caché, y los dispositivos de E/S están conectados al bus a través de controladores de dispositivo
(véase la figura 2.2). Si el CPU y los dispositivos de E/S tratan de acceder a la memoria al mismo

03 MAQ. CAP. 02(F0694).indd 36 8/10/07 12:53:45 AM


2.1 El sistema operativo y el sistema de cómputo 37

tiempo, el bus permite que sólo uno de ellos prosiga. Los otros accesos se demoran hasta que
este acceso se termina.

La protección de la memoria Muchos programas coexisten en la memoria del sistema de


cómputo, así es que hay que impedir que las instrucciones de un programa destruyan el contenido
de la memoria que está siendo usado por otro programa. A esta función se le llama protección de
la memoria. La protección de la memoria se implementa verificando si una palabra de memoria
a la que ha accedido por un programa está fuera del área de memoria asignada.
Una técnica popular de protección de la memoria usa la noción de registros acotados de
memoria (también llamados registros de valla). Las direcciones de principio y de fin del área
de memoria asignadas a un programa se cargan en el límite inferior del registro (LBR) y en el lí-
mite superior del registro (UBR) del CPU, respectivamente. Antes de hacer cualquier referencia
a la memoria, hagamos una referencia a la localidad de memoria con dirección aaa; el hardware
de protección de la memoria verifica si aaa está fuera del rango de direcciones definidas por los
contenidos de LBR y UBR. Si es así, genera una interrupción para indicar una violación de la
protección de la memoria. Como se describe en una sección posterior, el kernel ahora termina
el programa que ha fallado. El campo MPI de la PSW (véase la figura 2.3) contiene a LBR y
UBR. De esta manera, la información de protección de la memoria también pasa a formar parte
del estado del CPU. El ejemplo 2.2 ilustra cómo se implementa la protección de memoria.

Ejemplo 2.2 El kernel le asigna a un programa el área de memoria de 200 K-250 K. La figura 2.6
ilustra la protección de la memoria para este programa que usa registros acotados de memoria. El
LBR se carga con la dirección inicial del área asignada (es decir, 200 K) mientras que el UBR se
carga con la dirección final (es decir, 250 K). Se generaría una interrupción de violación de pro-
tección de la memoria si una dirección usada durante la ejecución de P1 estuviera fuera del rango
de 200 K-250 K.

Interrupción Memoria
de violación de 0 K
protección Kernel
de la memoria 200 K
Cargar 285252 P1
CPU
250 K
LBR 200 K ?
P2
UBR 250 K

dirección P3
285252

Figura 2.6 Protección de la memoria con el uso de registros acotados.

El subsistema E/S
Las operaciones de E/S pueden realizarse en uno de los tres modos descritos en la tabla 2.1. El
modo programado de E/S es lento e involucra al CPU en una operación de E/S. Por consiguiente,
sólo puede ejecutarse una operación de E/S. El modo de interrupción es también lento, de modo

03 MAQ. CAP. 02(F0694).indd 37 8/10/07 12:53:45 AM


38 CAPÍTULO 2 Visión general de los sistemas operativos

que se ejecuta una transferencia de datos byte por byte; de cualquier forma, aquél libera al CPU
de las transferencias de bytes. El modo directo de acceso a la memoria (DMA) puede transferir
un bloque de datos entre la memoria y un dispositivo de E/S sin involucrar al CPU. La interrup-
ción y los modos DMA permiten la ejecución simultánea de varias operaciones de E/S.

Tabla 2.1 Modos de entrada-salida

Modo de E/S Descripción


E/S programadas Los operandos de una instrucción de E/S indican los detalles de una ope-
ración de E/S. El CPU decodifica la instrucción y manda una señal a un
dispositivo de E/S. La transferencia de datos entre el dispositivo de E/S y la
memoria tiene lugar a través del CPU. Éste no puede ejecutar ninguna otra
operación mientras que la de E/S está en curso.
Interrupción de E/S El CPU ejecuta una instrucción de E/S. Inicia una operación de E/S y libera al
CPU para ejecutar otras instrucciones. Surge una interrupción cuando un byte
de datos debe transferirse entre el dispositivo de E/S y la memoria. El CPU
ejecuta una rutina de procesamiento de interrupción que transfiere al byte.
Acceso directo a la Una instrucción de E/S indica la operación de E/S que debe ejecutarse y
memoria (DMA) también el número de bytes que deben transferirse. La operación de E/S inicia
cuando se ejecuta la instrucción. La transferencia de datos entre el dispositivo
y la memoria tiene lugar en el bus del sistema. El CPU no participa en la
transferencia de datos. Surge una interrupción cuando la transferencia de
todos los bytes está completa.

Las operaciones DMA las ejecuta un procesador de propósito especial que está dedicado a
la ejecución de las operaciones de E/S. Muchas variantes del controlador de DMA se usan en
arquitecturas diferentes, por tanto, se emplean términos diferentes para eso. Usaremos el tér-
mino genérico DMA. La figura 2.2 ilustra el uso de DMA por el subsistema de E/S. Uno o más
controladores de dispositivo se conectan al DMA. Los dispositivos de E/S están conectados
a los controladores del dispositivo. El DMA transfiere los datos entre el dispositivo de E/S y
la memoria sin involucrar al CPU. Cuando se ejecuta una instrucción de E/S, por ejemplo, una
instrucción de lectura en el dispositivo d, el CPU transfiere detalles de la operación de E/S al
DMA. El CPU no participa en la operación de E/S más allá de este punto; está libre para ejecutar
instrucciones mientras que la operación de E/S está en curso. El DMA inicia la operación de
lectura en el dispositivo d y la transferencia de datos entre el dispositivo d y la memoria tiene
lugar en el bus. Así el CPU y el subsistema de E/S pueden operar concurrentemente. Al final
de la operación de E/S, la DMA genera una interrupción de E/S. El hardware de interrupción
conmuta al CPU para la ejecución del kernel, lo cual procesa la interrupción y se percata de que
la operación de E/S esté completa.

Interrupciones
La función de una interrupción es llamar la atención del kernel hacia una condición o un evento
que ha ocurrido en el sistema. El hardware de la computadora asocia una prioridad numérica
con cada interrupción. Si condiciones o eventos que corresponden a varias interrupciones surgen
al mismo tiempo, el mecanismo de interrupción permite que ocurra la interrupción prioritaria

03 MAQ. CAP. 02(F0694).indd 38 8/10/07 12:53:46 AM


2.1 El sistema operativo y el sistema de cómputo 39

más alta. Un código único de interrupción se asocia con cada interrupción. Este código provee
suficiente información relativa a la condición o el evento a fin de que el kernel pueda tomar ac-
ciones apropiadas. El término “interrumpir el procesamiento” se usa para describir la ejecución
de tales acciones.
La interrupción del procesamiento requiere que el CPU sea desviado de cualquier cómputo
que esté ejecutando a la ejecución de una rutina de procesamiento de interrupción en el kernel.
El mecanismo de interrupción logra este efecto guardando el contenido de la PSW en la memoria
y cargando el contenido nuevo en la PSW que ordena al CPU la ejecución de la rutina de pro-
cesamiento de interrupción. El kernel determina la causa de la interrupción y toma las acciones
apropiadas. Al final del procesamiento de la interrupción, aquél reanuda la ejecución del progra-
ma interrumpido al cargar nuevamente el contenido guardado de la PSW o desvía el CPU para
la ejecución de otro programa.

Tabla 2.2 Clases de interrupciones

Clase Descripción
Interrupción del Causado por las condiciones internas del CPU que requieren atención del
programa supervisor, por ejemplo, excepciones aritméticas como el desbordamiento
y la pérdida de precisión, el manejo de excepciones y las violaciones a la
protección de la memoria.
Una interrupción llamada interrupción de software es causada por la ejecución
de una instrucción especial llamada instrucción de interrupción de software.
Interrupción de E/S Causado por condiciones tales como la terminación de la operación de E/S y
el funcionamiento defectuoso de los dispositivos de E/S.
Interrupción del Causado por el cronómetro del sistema de cómputo.
cronómetro

Clases de interrupciones La tabla 2.2 describe tres clases de interrupciones que son im-
portantes durante la operación normal de un sistema operativo. Una interrupción de programa
surge debido a la ejecución de una instrucción y comúnmente indica una condición excepcional,
como una condición de aritmética o una violación de protección de la memoria. La mayoría de
dispositivos CPU proveen una instrucción especial cuyo propósito exclusivo es causar una in-
terrupción de programa. Suponemos una instrucción hipotética llamada instrucción de interrup-
ción del software con el código de operación SI, y llamamos a la interrupción causada por ella
una interrupción del software. Como se describe posteriormente, un programa usa la instrucción
de interrupción del software para hacer peticiones al kernel.

Enmascaramiento de la interrupción El campo de la máscara de interrupción (IM) de


la PSW indica cuáles interrupciones se permite que ocurran en cualquier momento. El campo
puede contener un entero m, en cuyo caso sólo se permite que ocurran interrupciones con
prioridad ≥ m. Alternativamente, el campo IM puede contener un valor de bit cifrado; cada bit
indica si se permite que ocurra una clase específica de interrupción. Se dice que las interrup-
ciones cuya ocurrencia se permite son habilitadas; las otras se dice que son enmascaradas
(o camufladas). Las interrupciones enmascaradas permanecen pendientes hasta que se permita
su ocurrencia.

03 MAQ. CAP. 02(F0694).indd 39 8/10/07 12:53:46 AM


40 CAPÍTULO 2 Visión general de los sistemas operativos

..
1 .
IM P Vectores de
3 PC interrupción
IC
ddd
PSW Información
2 guardada de
CPU ddd
.. la PSW
.

Figura 2.7 La acción de interrupción.

Acción de interrupción El propósito de la acción de interrupción es transferir control a


una rutina apropiada en el kernel. La figura 2.7 contiene un esquema de la acción de interrupción.
Dos áreas de memoria llamadas área de vectores de interrupción y área de información salvada
de la PSW participan en estas acciones. Cada unidad en el área de vectores de interrupción es un
vector de interrupción que controla el procesamiento de una clase de interrupciones. Contiene la
siguiente información:

1. La dirección de una rutina de procesamiento de interrupción.


2. Una máscara de interrupción indicando si puede permitirse que ocurran otras interrupcio-
nes mientras esta interrupción está siendo procesada.
3. Si el CPU debería estar en modo de privilegio al procesar la interrupción.

Por simplicidad, se supone que un vector de interrupción tiene el mismo formato que una PSW
y que contiene estos puntos anteriores de información en el contador del programa (PC), la
máscara de interrupción (IM) y los campos de modo privilegiado (P), respectivamente. Los
vectores de interrupción se inicializan con valores apropiados al arrancar el sistema. Cada uni-
dad en el área salvado de información en la PSW almacena información que se copia de la
PSW cuando ocurre una interrupción. En algunos sistemas de cómputo, se asocia un área fija
de memoria con cada clase de interrupción para almacenar la información salvada de la PSW,
mientras en otros sistemas la información salvada de la PSW se inserta hacia una pila (véase el
problema 7).
El CPU verifica la ocurrencia de una interrupción al final de cada ciclo de instrucciones.
Si ha ocurrido una interrupción, realiza la acción de interrupción para ella. La acción de inte-
rrupción le concierne a la PSW, a una unidad del área de salvado de información de la PSW
y a un vector de interrupción del área de vectores de interrupción. La acción consta de tres
pasos señalados 1 3 en la figura 2.7 y descritos en la tabla 2.3. Al final de la acción de in-
terrupción, el código de interrupción que describe la causa de la interrupción se ha guardado
como una parte de la información salvada de la PSW y la información del vector pertinente
de interrupción ha sido cargada en los diversos campos de la PSW (palabra de estado del pro-
cesador).
Las subsiguientes acciones del CPU dependen del contenido nuevo de la PSW (palabra
de estado del procesador), específicamente los campos de modo de privilegio, máscara de

03 MAQ. CAP. 02(F0694).indd 40 8/10/07 12:53:46 AM


2.1 El sistema operativo y el sistema de cómputo 41

Tabla 2.3 Pasos de una acción de interrupción

Paso Descripción
1. Establecer el El hardware de interrupción para la interrupción escogida forma un código
código de que describe la causa de la interrupción. Éste se almacena en el campo de
interrupción código de interrupción de la PSW. Por ejemplo, para una interrupción ‘termi-
nación de E/S’, el código podría ser la dirección del dispositivo de E/S que
causa la interrupción.
2. Guardar la PSW La PSW se copia en el área de información guardada de la PSW en la unidad
correspondiente a la clase de la interrupción.
3. Cargar el vector Se tiene acceso al vector de interrupción que corresponde a la clase de in-
de interrupción terrupción. La información del vector de interrupción se carga en los campos
correspondientes de la PSW. Esta acción transfiere el control a una rutina
apropiada de procesamiento de interrupción.

interrupción y contador del programa. El vector de interrupción contiene la dirección de la


rutina que supuestamente maneja la interrupción, así es que la acción de interrupción transfiere
eficazmente el control a la rutina apropiada en el kernel. Observe que la acción de interrupción
debe poner al CPU en el modo privilegiado si el procesamiento de una interrupción requiere
el uso de instrucciones privilegiadas. Esto se logra poniendo un 1 en el campo de modo privi-
legiado del vector de interrupción. Sólo las interrupciones habilitadas en la máscara nueva de
interrupción pueden ocurrir después de que la acción de interrupción haya sido realizada; las
otras permanecen pendientes hasta que se habiliten al cambiar la máscara de interrupción.

2.1.2 La interacción del sistema operativo con el hardware


de la computadora y los programas del usuario

Para la buena eficiencia del CPU, éste debe ejecutar las instrucciones de los programas del
usuario la mayoría de las veces. Sin embargo, el CPU debería conmutarse para la ejecución
del kernel cuando éste necesita realizar una función de control. Tal requisito se satisface
usando un arreglo en el cual cualquier situación que requiere la atención del kernel conduce a
una interrupción. Los vectores de interrupción para las diversas interrupciones se forman
de tal manera que sus campos de PC apuntan para iniciar las instrucciones de las rutinas
apropiadas del kernel. En una interrupción, una rutina del kernel obtiene el control y reali-
za la función requerida de control. Así la operación del kernel está manejada por la inte-
rrupción.
La figura 2.8 muestra las acciones realizadas por el kernel cuando ocurre una interrupción.
El procesamiento de las interrupciones involucra guardar el estado del CPU de modo que el
programa que estaba siendo ejecutado en el momento de la interrupción pueda reanudarse en
lo futuro, y realizar acciones de control en respuesta a la interrupción. Después de procesar la
interrupción, el kernel selecciona un programa para la ejecución y le pasa el control. Esta acción
se llama planificación. Dependiendo de la situación que causó la interrupción, el kernel puede se-
leccionar el programa que ejecutaba cuando ocurrió la interrupción o puede escoger otro pro-
grama.

03 MAQ. CAP. 02(F0694).indd 41 8/10/07 12:53:47 AM


42 CAPÍTULO 2 Visión general de los sistemas operativos

Ocurrencia de
una interrupción

Procesamiento
de la interrupción

Planificación

Salida del
kernel

Figura 2.8 Operación del kernel manejado por la interrupción.

La operación manejada por la interrupción del kernel requiere que un programa sea capaz
de causar una interrupción que atraiga la atención del kernel, por ejemplo, cuando necesita más
memoria, o cuando desea iniciar una operación de E/S. Una llamada de sistema es un término
genérico que se usa para tal solución. Cada vez que un programa del usuario requiere alguna
asistencia del sistema operativo, realiza una llamada de sistema ejecutando una instrucción de
interrupción del software. Esta llamada conduce a una interrupción y el kernel responde a la
petición del usuario. La sección 2.1.2.2 estudia las llamadas de sistema.
Las acciones de procesamiento de interrupción y de planificación del sistema operativo
consumen recursos del sistema de cómputo, en particular el tiempo del CPU. La sobrecarga
por la planificación es lo que llamamos el tiempo que el CPU ocupó en tomar una decisión de
planificación; lo denotamos por  (la letra griega sigma).

2.1.2.1 Procesamiento de las interrupciones


El procesamiento de las interrupciones incluye los pasos para manejar la condición que causó
una interrupción y para continuar la operación del sistema operativo. Una rutina de procesamien-
to de interrupción realiza las siguientes acciones:
1. Guarda el contenido de los registros del CPU para usarse cuando el programa se planifi-
que otra vez. (Esta acción no es necesaria si la acción de interrupción guarda los registros
del CPU.)
2. Toma las acciones apropiadas para manejar la situación que causó la interrupción. El
campo de código de interrupción de la unidad de información guardada en la PSW co-
rrespondiente a la interrupción contiene información útil con este propósito. Una inte-
rrupción puede deberse a tres clases de situaciones:
a) Un evento como el que ocurre al final de una operación de E/S.
b) El programa que se ejecuta en el CPU hace una petición al sistema operativo.
c) Ocurre una condición de error como la violación de protección.
La rutina de procesamiento de interrupción invoca los módulos del kernel que manejan
el evento, satisface la petición del programa o termina el programa que ha fallado.
3. Pasa el control al planificador para conmutar el CPU a un programa de usuario.

03 MAQ. CAP. 02(F0694).indd 42 8/10/07 12:53:47 AM


2.1 El sistema operativo y el sistema de cómputo 43

La planificación El planificador es el componente del kernel responsable de decidir cuál


programa deberá ejecutarse en el CPU. Cuando recibe control, el planificador selecciona un pro-
grama de usuario según la política predominante para planificar, obtiene el estado del CPU del
programa seleccionado (recuerde que el estado del CPU se guardó cuando la ejecución del pro-
grama se interrumpió en alguna ocasión en el pasado), el cual consta de los contenidos de los
registros del CPU y la PSW, y lo carga en el CPU. Esta acción conmuta el CPU al programa
seleccionado.
El ejemplo 2.3 ilustra el procesamiento de la interrupción cuando ocurre una interrupción
de E/S.

Ejemplo 2.3 La figura 2.9 muestra las rutinas de procesamiento de interrupción y los vectores de
interrupción usados en un kernel. El programa del usuario está a punto de ejecutar la instrucción
con la dirección ddd cuando ocurre una interrupción de E/S. El contenido de la PSW se guarda en el
área de información guardada en la PSW. Éstos incluyen el ‘0’ en el campo de modo privilegiado,
ddd en el campo del PC y el código de interrupción en el campo IC. El vector de interrupción para
la interrupción de la terminación de E/S contiene bbb en el campo correspondiente al campo PC
de la PSW y ‘1’ en el campo correspondiente al campo de modo privilegiado. El contenido de este
vector de interrupción se carga en la PSW. Efectivamente, el control se transfiere a la rutina con la
dirección de inicio bbb. El campo P de la PSW ahora contiene ‘1’, así es que el CPU se pone en el
modo privilegiado.
La rutina de procesamiento de interrupción guarda primero el contenido de los registros del
CPU. Luego consulta el campo IC de la unidad de información guardada en la PSW para encon-
trar la dirección del dispositivo de E/S que haya terminado su operación y realiza las funciones
necesarias de control. Al final, transfiere el control al planificador. Si el planificador selecciona el
mismo programa interrumpido para la ejecución, conmutará el CPU a la ejecución del programa al
cargar nuevamente el contenido de los registros del CPU y al cargar la PSW guardada. El programa
reanudará la ejecución en el lugar donde se interrumpió (véase el ejemplo 2.1).

Procesamiento anidado de las interrupciones La figura 2.10a) ilustra las acciones del
procesamiento de interrupción del ejemplo 2.3 si la rutina de interrupción ‘a’ maneja la inte-
rrupción y el planificador selecciona el mismo programa interrumpido para la ejecución. Si
ocurre otra interrupción mientras que la rutina de interrupción ‘a’ está procesando la prime-
ra interrupción, ocurrirán acciones idénticas en el hardware y software, así es que el CPU será
conmutado a la ejecución de otra rutina de interrupción, por ejemplo, la rutina de interrupción
‘b’ (véase la figura 2.10b)). Esta situación atrasa el procesamiento de la primera interrup-
ción y también requiere una codificación cuidadosa del kernel para evitar una confusión si la
misma clase de interrupción surgiera otra vez (vea también el problema 7). Estas consecuencias
pueden evitarse camuflando completamente todas las interrupciones que usa el campo de la
máscara de interrupción (IM) en el vector de interrupción (vea la figura 2.9). Sin embargo, el
enmascaramiento de una interrupción atrasa la respuesta del sistema operativo a la condición
que lo causó. Por consiguiente, para evitar demoras en el procesamiento de la interrupción, el
kernel define la máscara de interrupción en cada vector de interrupción para camuflar comple-
tamente sólo las menos interrupciones críticas. Más interrupciones críticas serían procesadas
en una manera anidada.

La priorización del programa La priorización de un programa ocurre cuando surge una


interrupción durante su ejecución y el planificador selecciona otro programa para su ejecución.
La PSW (palabra de estado del procesador) y los registros del CPU son guardados por la rutina

03 MAQ. CAP. 02(F0694).indd 43 8/10/07 12:53:47 AM


44 CAPÍTULO 2 Visión general de los sistemas operativos

Memoria

aaa: bbb: ccc:


Guardar la Guardar la
PSW y los {Seleccionar
PSW y los un programa}
registros registros
Cargar los
{Procesar la {Procesar la registros
interrupción} interrupción}
Transferir al
Bifurcación Bifurcación programa del
ccc ccc usuario
Rutina de servicio Rutina de
para la interrupción servicio para la Planificador
del programa interrupción de E/S

Conmutación
del CPU cuando PC P PC P
ocurre una Vector de bbb 1 ddd 0
interrupción interrupción
de E/S d1
de E/S IM IC
PC P
Vector de aaa
interrupción 1
del programa
IM

Área de vectores Área de información


de interrupción guardada en la PSW
Kernel

Conmutación del
<instrucción anterior> CPU para regresar
• del servicio de
ddd: <siguiente instrucción> interrupción

Programa del usuario

Figura 2.9 Servicio para una interrupción de E/S y retorno al mismo programa de usuario.

03 MAQ. CAP. 02(F0694).indd 44 8/10/07 12:53:47 AM


2.1 El sistema operativo y el sistema de cómputo 45

Programa Rutina de Programa Rutina de Rutina de


del usuario interrupción ‘a’ del usuario interrupción ‘a’ interrupción ‘b’

a) b)
Figura 2.10 Procesamiento de interrupción simple y anidado.

de procesamiento de interrupciones, así que no hay dificultad en reanudar su ejecución cuando


sea programado otra vez.

2.1.2.2 Las llamadas del sistema

Definición 2.1 (La llamada del sistema) Una llamada de sistema es una petición que un
programa hace al sistema operativo.

Una llamada de sistema usa la instrucción especial conocida como instrucción de interrup-
ción de software y descrita en la sección 2.1.1. Esta instrucción tiene el formato
<SI _ instrn> <int_code>
donde los valores de <int_code> tienen significados estándar en el sistema operativo. Una in-
terrupción de programa ocurre cuando un programa ejecuta esta instrucción. El paso 1 de la
acción de interrupción copia <int_code> de la instrucción SI en el campo de claves de interrup-
ción de la PSW. El paso 2 copia la PSW en el área información guardada en la PSW. La rutina de
procesamiento de interrupción analiza este código para determinar la petición hecha por el pro-
grama. En la mayoría de los sistemas de cómputo, <int_code> tiene un tamaño de cuando menos
8 bits, así es que pueden definirse hasta 256 peticiones diferentes. El ejemplo 2.4 describe la
ejecución de una llamada de sistema para obtener el tiempo actual.
Ejemplo 2.4 Un sistema de cómputo contiene un reloj de tiempo real. El acceso para el reloj se
provee a través de las instrucciones privilegiadas; por tanto, se proporciona una llamada de sistema
para obtener la hora actual. Considere un código de10 para el servicio de la hora en este día. Cuando
un programa desea saber la hora, ejecuta la instrucción
<SI_instrn> 10
que causa una interrupción del software. Entonces se ingresa 10 en el campo del código de inte-
rrupción de la PSW (palabra de estado del procesador) antes de guardar la PSW. Como se muestra
en la figura 2.9, el vector de interrupción para la interrupción del software contiene aaa en su PC,
por lo que el control pasa a la rutina con la dirección inicial aaa. La rutina analiza el código de
interrupción y encuentra que el programa desea saber la hora del día. Según las convenciones de-
finidas en el sistema operativo, la información de la hora debe devolverse al programa en una
posición estándar, comúnmente en un registro de datos. La rutina de interrupción toma las acciones

03 MAQ. CAP. 02(F0694).indd 45 8/10/07 12:53:48 AM


46 CAPÍTULO 2 Visión general de los sistemas operativos

necesarias con este propósito y le pasa el control al planificador. El planificador selecciona un


programa del usuario y conmuta el CPU para su ejecución.

Si un sistema de cómputo no provee un operando en la instrucción SI, el programa inserta un


código correspondiente a la llamada de sistema que se hace en la pila antes de ejecutar la instruc-
ción SI. El kernel analiza el código y realiza la acción necesaria. En el ejemplo 2.4, el programa
inserta 10 en la pila antes de ejecutar la instrucción SI.
La tabla 2.4 indica algunos tipos genéricos de llamadas de sistema y enlista algunos ejem-
plos de cada tipo. Las llamadas relacionadas con el recurso proveen los servicios de asignación y
retiro de asignación de recursos. Si el recurso pedido está disponible, la petición de asignación de re-
cursos se cumple enseguida; de otra manera, la ejecución del programa peticionario se demora
hasta que el recurso esté disponible. Por consiguiente, un programa puede desear revisar la disponi-
bilidad de un recurso antes de hacer una petición. Las llamadas relacionadas con el recurso proveen
servicios para iniciar o terminar la ejecución de otros programas, y para esperar un cierto periodo.
Las llamadas relacionadas con la comunicación establecen comunicación con otros programas en
el sistema y ejecutan intercambio de mensajes. Con la excepción de estos tipos genéricos, cada
sistema operativo provee una multiplicidad de llamadas especializadas de sistema.

Tabla 2.4 Llamadas de sistema

Tipo Ejemplos
Recurso Asignar/retirar asignación de recursos, verificar la disponibilidad de los recursos.
Programa Interrupción de activación/espera del cronómetro, programa de ejecución/termina-
ción.
Archivo Abrir/cerrar un archivo, lectura/escritura de archivos.
Información Obtener la hora y la fecha, obtener información del sistema operativo, obtener in-
formación de los recursos.
Comunicación Mandar/recibir mensajes, activación/terminación de la conexión.

2.2 LA EFICIENCIA, EL DESEMPEÑO DE SISTEMA


Y LA CONVENIENCIA DEL USUARIO
En el capítulo 1 analizamos los aspectos del uso eficiente de un sistema de cómputo y la con-
veniencia del usuario provista por un sistema operativo. También introdujimos tres estructuras
computacionales fundamentales (un programa individual, una secuencia de programas individua-
les y los programas coejecutables) para ilustrar cómo puede proveer un sistema operativo la con-
veniencia del usuario. En esta sección estudiamos la naturaleza de los cómputos realizados en
un sistema operativo y describimos cierta métrica usada para medir la eficiencia, el desempeño del
sistema y la conveniencia del usuario. Los conceptos y los términos introducidos aquí serán útiles
en las secciones posteriores de este capítulo y en los siguientes.

2.2.1 La naturaleza de los cómputos en un sistema operativo

En un ambiente no interactivo, se realiza un cómputo al someter al sistema operativo su proce-


samiento y se obtienen sus resultados al final de éste. En el ambiente clásico no interactivo, los

03 MAQ. CAP. 02(F0694).indd 46 8/10/07 12:53:48 AM


2.2 La eficiencia, el desempeño de sistema y la conveniencia del usuario 47

cómputos se clasificaban en programas y trabajos. Un programa es un conjunto de funciones o


módulos, incluidos algunos que se obtienen de las bibliotecas. Un trabajo es una secuencia de
programas individuales (vea la sección 1.3.1 y el ejemplo 1.1). Consta de una secuencia de pasos
del trabajo, donde cada paso del trabajo constituye la ejecución de un programa. Así, un trabajo
para compilar y ejecutar un programa en C consta de tres pasos de trabajo, para compilar,
enlazar y ejecutar el programa. No tiene sentido ejecutar un paso de trabajo a menos que cada
uno de los pasos de trabajo previos se haya ejecutado exitosamente; por ejemplo, el ligamiento
no es significativo a menos que la recopilación haya sido exitosa. La noción de un trabajo es
de menos relevancia en ambientes interactivos de computación porque un usuario comúnmente
alimenta un comando a la vez al procesador de comandos.
Un proceso representa la ejecución de un programa. Ilustramos algunas ventajas de los
procesos cuando analizamos los sistemas de tiempo real en la sección 2.7. En interés de la sim-
plicidad, diferimos el análisis de otras características de procesos hasta el capítulo 3.
En un ambiente interactivo, un usuario interactúa con su programa. Una interacción consta
de la presentación de un requisito computacional por el usuario al programa (llamamos a esto
una subpetición) y del cómputo de una respuesta por el programa. Dependiendo de la naturaleza
de una subpetición, la respuesta puede estar en la forma de un resultado o ser una acción realiza-
da por el programa, por ejemplo, una actualización de la base de datos.

Tabla 2.5 Cómputos en el sistema operativo

Cómputo Descripción
Programa Un programa es un conjunto de funciones o de módulos, incluyendo algunas
funciones o módulos que se obtienen de bibliotecas.
Trabajo Un trabajo es una secuencia de pasos de trabajo, donde cada uno de ellos
está constituido por la ejecución de un programa. No tiene sentido ejecutar el
programa en un paso de trabajo a menos que los programas en los pasos de
trabajo anteriores se hayan ejecutado con éxito (vea la sección 1.3.1).
Proceso Un proceso es la ejecución de un programa.
Subpetición Una subpetición es la presentación al proceso de un requerimiento compu-
tacional por un usuario. Cada subpetición produce una respuesta individual,
que es un conjunto de resultados o de acciones.

La tabla 2.5 describe el trabajo, el programa, el proceso y los cómputos de subpetición. Las
nociones de desempeño de sistema y conveniencia del usuario en un sistema operativo dependen
de la naturaleza de los cómputos. Estudiamos este asunto en la siguiente sección.

2.2.2 Cómo medir la eficiencia, el desempeño del sistema


y la conveniencia del usuario
La medida provee una base cuantitativa para comparar técnicas alternativas usadas en el diseño
e implementación de un sistema operativo. Sin embargo, varias dificultades prácticas surgen al
hacer comparaciones cuantitativas. Algunos atributos de un sistema operativo pueden ser intan-
gibles, de modo que las comparaciones numéricas no son posibles, o las técnicas pueden poseer
atributos diferentes y, por tanto, las comparaciones pueden no tener sentido.

03 MAQ. CAP. 02(F0694).indd 47 8/10/07 12:53:48 AM


48 CAPÍTULO 2 Visión general de los sistemas operativos

Encontramos ambas dificultades cuando consideramos la eficiencia de uso y la conveniencia


del usuario en las diferentes clases de sistemas operativos. Algunas características, como las inter-
faces amigables con el usuario, proveen conveniencias intangibles, y los diferentes ambientes de
computación usan nociones diferentes de la eficiencia y de la conveniencia del usuario. Sin em-
bargo, las medidas resumidas en la tabla 2.6 son útiles para entender el impacto de una técnica en
los sistemas operativos de una clase específica. Usamos estas medidas en las siguientes secciones.

Tabla 2.6 Las medidas de la eficiencia y la conveniencia del usuario

Atributo Concepto Descripción


Eficiencia de uso Eficiencia del CPU Porcentaje de utilización del CPU.
Desempeño del Desempeño Cantidad de trabajo hecha por unidad de tiempo.
sistema
Servicio al usuario Tiempo de demora Tiempo de terminación de un trabajo o de un proceso.
Tiempo de respuesta Tiempo de implementación de una interacción entre
un usuario y su proceso.

La eficiencia y el desempeño del sistema Aunque la buena eficiencia de uso es importan-


te, es raramente una meta del diseño de un sistema operativo. Un buen desempeño en su am-
biente de cómputo es una meta importante del diseño. La eficiencia de uso puede ser un medio
para este fin, por ejemplo, la eficiencia de recursos como el CPU y los discos son parámetros
importantes para afinar el desempeño de un sistema. En los capítulos 6 y 4 vemos ejemplos de
tal uso en el contexto de planificación y memorias virtuales.
El desempeño del sistema se mide comúnmente como desempeño específico.

Definición 2.2 (Desempeño) El desempeño específico de un sistema es el número de traba-


jos, programas, procesos o subpeticiones que se completan por unidad de tiempo.

La unidad de trabajo que se usa para calcular el rendimiento específico depende de la na-
turaleza del ambiente de cómputo. En un ambiente no interactivo, el rendimiento específico
de un sistema operativo se mide en términos del número de trabajos, programas o procesos
completados por unidad de tiempo. En un ambiente interactivo, el rendimiento específico puede
medirse en términos del número de subpeticiones completadas por unidad de tiempo. En un
ambiente especializado de computación, el desempeño se mide en términos significativos por la
aplicación a la que se sirve, por ejemplo, el número de transacciones en un ambiente bancario. El
rendimiento específico también puede utilizarse como una medida de desempeño de los disposi-
tivos de E/S. Por ejemplo, el rendimiento específico de un disco puede medirse como el número
de operaciones de E/S terminadas por unidad de tiempo o el número de bytes transferidos por
unidad de tiempo.

El servicio para el usuario El servicio para el usuario es un aspecto mensurable de con-


veniencia del usuario. Indica cómo ha sido tratado el cómputo de un usuario por el sistema opera-
tivo. Definimos dos medidas de servicio para el usuario: el tiempo de demora y el de respuesta.
Éstos se usan en los ambientes de computación no interactivos e interactivos, respectivamente.

03 MAQ. CAP. 02(F0694).indd 48 8/10/07 12:53:49 AM


2.3 Las clases de sistemas operativos 49

Definición 2.3 (Tiempo de demora) El tiempo de demora de un trabajo, programa o pro-


ceso es el tiempo que dura desde su alimentación al procesamiento hasta que sus resultados
están disponibles para el usuario.

Definición 2.4 (Tiempo de respuesta) El tiempo de respuesta provisto para una subpetición
es el tiempo que transcurre entre la alimentación de la subpetición por un usuario y la formu-
lación de respuesta del proceso para él.

2.3 LAS CLASES DE SISTEMAS OPERATIVOS

2.3.1 Características clave de las diferentes clases de sistemas operativos


La tabla 2.7 resume las características clave de cinco clases fundamentales de sistemas operativos.

Tabla 2.7 Características clave de las clases de sistemas operativos

Clase de SO Periodo Preocupación principal Conceptos clave


Procesamiento por 1960 Tiempo muerto del CPU Operación periférica simultánea en
lotes línea, procesador de comandos.
Multiprogramación 1970 Utilización de los recursos Prioridades, priorización del programa.
Tiempo compartido 1970 Un buen tiempo de Intervalo de tiempo, planificación
respuesta round-robin.
Tiempo real 1980 Cumplir con el tiempo Planificación en tiempo real.
límite
Distribuido 1990 Recursos compartidos Transparencia, control distribuido.

La columna de periodo muestra la época en que se generalizó el uso de los sistemas operati-
vos de esa clase por primera vez. ¡De manera interesante, las características clave de las anterio-
res clases del sistema operativo también pueden encontrarse hoy en día en los sistemas operativos
actuales! De hecho, por eso es que los estudiamos hoy. La columna de preocupación principal de
la tabla 2.7 demuestra el criterio fundamental de efectividad que motivó el desarrollo de esa clase
de sistema operativo. La columna conceptos clave indica aquellos que fueron desarrollados para
coadyuvar a implementar las preocupaciones principales de un sistema operativo.

El proceso por lotes y los sistemas de multiprogramación Una vista superficial de las
preocupaciones principales en las diferentes clases de sistemas operativos revela una tendencia
interesante. Las primeras dos clases de sistema operativo, es decir, el procesamiento por lotes y
la multiprogramación, destacaban el uso eficiente del sistema de cómputo. En el procesamiento
por lotes, la preocupación se limitaba a la eficiencia del CPU, por lo que evitar el derroche de
tiempo del CPU era la preocupación principal. En la multiprogramación, la preocupación se
amplió para incluir otros recursos, principalmente la memoria y el subsistema de E/S, así es
que una utilización balanceada de todos los recursos en el sistema era la principal preocupación.
Estas preocupaciones provinieron del alto precio de hardware en esos días, y la satisfacción de
estas preocupaciones no proveyó ningún beneficio directo a los usuarios.

03 MAQ. CAP. 02(F0694).indd 49 8/10/07 12:53:49 AM


50 CAPÍTULO 2 Visión general de los sistemas operativos

Los sistemas de tiempo compartido y de tiempo real A mediados de los setenta, el en-
foque se desplazó del uso eficiente de un sistema de cómputo a la productividad de los usuarios
de la computadora. Este cambio se justificó por el clamor de los usuarios para tener un servicio
eficiente, y se volvió práctico debido a la reducción de los costos de hardware. Los sistemas de
tiempo compartido se enfocaban en suministrar una respuesta rápida a una subpetición. Este en-
foque proveyó beneficios tangibles a los usuarios de la computadora. Casi al mismo tiempo, las
aplicaciones de computadoras en ambientes críticos en tiempo condujeron al desarrollo de siste-
mas operativos en tiempo real que se enfocaban en completar una tarea computacional antes del
tiempo límite especificado por una aplicación. Debido a la necesidad de cumplir fechas límite, un
sistema de tiempo real está a menudo dedicado a una sola aplicación crítica en tiempo.
Los sistemas distribuidos En los noventa, los costos descendientes del hardware condu-
jeron al desarrollo de sistemas distribuidos que constaban de varios sistemas de cómputo con
una sofisticación y número de variables de recursos. Un sistema distribuido permite los recursos
compartidos a través de las fronteras de los sistemas de cómputo individuales. Así, un usuario de
un sistema de cómputo de bajo costo puede usar recursos caros existentes en otros sistemas
de cómputo. Algunas características de los recursos compartidos se parecen al uso eficiente de
los recursos. Sin embargo, posee otras características importantes, como la tolerancia de falla,
que tiene mucho que ver con la conveniencia del usuario.

Multipro-
gramación
↑ Tiempo Sistema
compartido operativo
Eficiencia distribuido

Sistema
operativo en
tiempo real
Procesamiento
por lotes

Necesidad Buen servicio Recursos compartidos


Conveniencia del usuario →

Figura 2.11 Eficiencia y conveniencia del usuario para diferentes clases de sistemas operativos.

2.3.2 El uso eficiente y la conveniencia del usuario


Como se analizó en la introducción, el uso eficiente y la conveniencia del usuario a menudo
ejercen presiones contrarias en el diseño de un sistema operativo. Sin embargo, la tendencia del
diseño del sistema operativo ha estado dirigida hacia la conveniencia creciente del usuario. La
figura 2.11 muestra el balance entre la eficiencia y la conveniencia del usuario logrado por las
diferentes clases de sistemas operativos. Observe que ninguno de los dos ejes de esta gráfica es
homogéneo. La noción de conveniencia del usuario cambia de una clase de sistema operativo

03 MAQ. CAP. 02(F0694).indd 50 8/10/07 12:53:49 AM


2.3 Las clases de sistemas operativos 51

a otro. Los recursos cuya eficiencia ha sido graficada también cambian a través de las clases de
sistemas operativos. Como se estudió en la sección 1.2, la necesidad está en el extremo más bajo
de la conveniencia del usuario. Los sistemas operativos de procesamiento por lotes y multipro-
gramación proveen este nivel de conveniencia del usuario. El proceso por lotes provee una efi-
ciencia baja porque procesa un programa del usuario a la vez. La multiprogramación provee una
eficiencia más alta porque procesa a muchos programas de usuario en una manera interpaginada
para el mismo lapso de tiempo.
Un sistema de tiempo compartido provee buen servicio, que se evalúa más alto en la escala
de conveniencia del usuario. Un sistema de tiempo compartido procesa muchos programas para
el mismo periodo; por tanto, puede proveer mejor eficiencia que el proceso por lotes puro. Sin
embargo, la eficiencia puede estar más abajo de la de los sistemas de multiprogramación debido
a una operación más alta de la carga general del sistema operativo. Un sistema de tiempo real
puede proveer una eficiencia más baja que un sistema de tiempo compartido porque puede estar
dedicada a una sola aplicación.
Un sistema operativo distribuido provee el uso compartido de los recursos a través de las
fronteras de los sistemas de cómputo, por lo que la eficiencia provista cubre un rango más am-
plio que cualquier otro sistema operativo. En el extremo inferior, la computación de bajo costo
puede parecerse en muchas maneras al proceso por lotes. Los recursos disponibles en un sistema
de cómputo pueden ser adecuados sólo para un pequeño número de programas. Las ventajas de
la multiprogramación están disponibles si un sistema de cómputo bajo el control de un sistema
operativo distribuido tiene recursos razonables de computación. Aún más, el uso compartido de
los recursos a través de las fronteras de los sistemas de cómputo individuales puede magnificar la
utilización del recurso. Por consiguiente, un sistema operativo distribuido tiene el potencial para
proveer una eficiencia más alta que un sistema de multiprogramación.

2.3.3 La ejecución de los cómputos del usuario en las diferentes


clases de sistemas operativos
La tabla 2.8 resume la manera en la cual la ejecución de los cómputos del usuario se organiza
en sistemas operativos de clases diferentes. Un sistema de proceso por lotes opera de manera
estricta de un trabajo a la vez. Dentro de un trabajo, ejecuta los programas uno tras otro. Así,
sólo un programa se ejecuta en cualquier momento. La eficiencia del CPU se magnifica al iniciar
eficazmente el siguiente trabajo cuando termina el anterior.
En un sistema de multiprogramación, varios programas están en un estado de terminación
parcial en cualquier momento. Los recursos asignados a un programa se utilizan cuando se ejecu-
ta el programa. El sistema operativo conmuta el CPU entre la ejecución de programas diferentes
para asegurar una utilización balanceada de los recursos. Usa la noción de prioridad para decidir
cuál programa deberá ser ejecutado en el CPU en cualquier momento.
Un sistema de tiempo compartido también interpagina la ejecución de procesos. Sin em-
bargo, el propósito de la interpaginación es proveer buenos tiempos de respuesta a todos los
procesos. Por tanto, un sistema operativo de tiempo compartido no asigna las prioridades a
los procesos; provee la oportunidad equitativa de ejecución a cada uno.
Un sistema de tiempo real le permite a un usuario crear varios procesos dentro de un pro-
grama de aplicación y asignarles prioridades de ejecución. Interpagina la ejecución de procesos
para satisfacer el tiempo límite de la aplicación.
Un sistema operativo distribuido provee el uso compartido y el uso eficiente de recursos lo-
calizados en todas las computadoras en el sistema. Una forma para lograr esto es permitir que los

03 MAQ. CAP. 02(F0694).indd 51 8/10/07 12:53:49 AM


52 CAPÍTULO 2 Visión general de los sistemas operativos

Tabla 2.8 Ejecución de los cómputos del usuario en diferentes sistemas operativos

Clase de sistema operativo Cómputos Concepto de ejecución clave


Procesamiento por lotes Trabajos Se ejecuta un trabajo a la vez. Los programas del
trabajo se ejecutan en forma secuencial.
Multiprogramación Programas El sistema operativo interpagina la ejecución de
varios programas para mejorar la utilización de los
recursos y el desempeño del sistema.
Tiempo compartido Procesos El sistema operativo interpagina la ejecución de los
procesos para proveer una buena respuesta a todos
los procesos.
Tiempo real Procesos El sistema operativo interpagina la ejecución de los
procesos en un programa de aplicación para cumplir
un tiempo límite.
Distribuidos Procesos Se tiene acceso a los recursos remotos con el uso de
redes. Ejecución de los procesos de una aplicación en
diferentes computadoras para lograr la compartición
y el uso eficiente de los recursos.

recursos de acceso de un proceso localizados en una computadora remota usen el componente


del sistema de redes. Sin embargo, el uso de la red causa retrasos, por lo que el sistema operativo
puede ejecutar los procesos de un programa en computadoras diferentes para lograr una buena
utilización de recursos.
Así, las cinco clases fundamentales de sistemas operativos atienden a las nociones diferen-
tes de efectividad, y usan técnicas y conceptos diferentes para alcanzar sus metas del diseño.
En las secciones 2.4 a 2.8 analizamos las características de las clases fundamentales del sistema
operativo. Los conceptos nuevos y las técnicas usadas en su implementación se definen e ilustran
con la ayuda de ejemplos.

2.4 LOS SISTEMAS DE PROCESO POR LOTES

Los sistemas de cómputo de la década de los sesenta usaban tarjetas perforadas como el medio
primario de entrada. Un programa y sus datos constaban de un paquete de tarjetas. El programa-
dor entregaba el programa en un mostrador en el centro de cómputo. El personal del centro de
cómputo manipulaba los paquetes de tarjetas y finalmente el operador de la computadora realizaba
la ejecución del programa en la computadora. El operador también tenía que manipular los paquetes
de tarjetas y realizar acciones físicas, como cargarlas en el lector de tarjetas y presionar algunos
interruptores en la consola para iniciar el procesamiento de un programa. El CPU del sistema de
cómputo estaba ocioso mientras el operador realizaba estas acciones. De esta manera, una gran
cantidad de tiempo de procesador se desaprovechaba. Se introdujo el proceso por lotes para evitar
este derroche.
Un lote es una secuencia de trabajos de los usuarios formado con el objeto de procesarse
en un sistema operativo de procesamiento por lotes. Observe que un lote no es una estructura
computacional de un usuario. Cada trabajo en el lote es independiente de otros trabajos en el
lote; los trabajos comúnmente pertenecen a usuarios diferentes. Un operador de la computadora

03 MAQ. CAP. 02(F0694).indd 52 8/10/07 12:53:50 AM


2.4 Los sistemas de proceso por lotes 53

forma un lote organizando un conjunto de trabajos de los usuarios en secuencia e insertando


tarjetas especiales de marcado para indicar el principio y el final del lote. El operador alimenta
un lote como una unidad de procesamiento al sistema operativo de procesamiento de lotes. La
función primaria del sistema de procesamiento por lotes es dar servicio a los trabajos en un lote,
uno tras otro sin requerir intervención del operador. Esto se logra automatizando la transición de
la ejecución de un trabajo a la del siguiente trabajo en el lote.
El procesamiento por lotes es implementado por el kernel (también llamado monitor de
lotes), que radica en una parte de memoria de la computadora. La memoria restante se usa para
dar servicio a un trabajo de usuario: el trabajo actual en el lote. Cuando el operador da una orden
para iniciar el procesamiento de un lote, el monitor del lote establece el procesamiento del pri-
mer trabajo del lote. Al final del trabajo, realiza el procesamiento de la terminación del trabajo
e inicia la ejecución del siguiente trabajo. Al final del lote, realiza el procesamiento de la termi-
nación del lote y espera el inicio del siguiente por parte del operador. Así, el operador necesita
intervenir sólo al principio y al final del lote.

Área del Monitor ...


sistema de lotes
↑ trabajo 1 trabajo 2 trabajon ↑
Área del Trabajo Tarjeta de “inicio Tarjeta de
usuario actual de lote” “final de lote”
del lote

Figura 2.12 Esquema de un sistema de procesamiento por lotes.

La figura 2.12 muestra un esquema de un sistema de procesamiento por lotes. El lote con-
siste en n trabajos, trabajo1, trabajo2, ... trabajon, uno de los cuales está en ese momento en
ejecución. La figura bosqueja un mapa de la memoria que muestra el arreglo del monitor de lotes
y el trabajo actual del lote en la memoria de la computadora. La parte de la memoria ocupada
por el monitor de lotes se llama área del sistema, y la parte ocupada por el trabajo del usuario se
conoce como el área del usuario.
Los sistemas de procesamiento por lotes usaron la noción de dispositivos virtuales descritos
en la sección 1.3.2.1 para conservar el tiempo de procesador de un sistema de cómputo pode-
roso como sigue: el sistema de cómputo usó dispositivos virtuales para la entrada y la salida,
comúnmente discos o cintas en lugar de tarjetas perforadas e impresoras. Para hacer posible
esto, un programa registraba primero un lote de trabajos en una cinta magnética. El sistema de
procesamiento por lotes procesaba estos trabajos y escribía sus resultados en otra cinta mag-
nética. Entonces otro programa imprimía el contenido de esta cinta magnética. Las dos opera-
ciones periféricas simultáneas en línea, llamadas inspooling y outspooling, respectivamente,
se realizaban comúnmente en un sistema de cómputo más pequeño que tenía un CPU lento. La
computadora principal usaba el medio de cinta magnética más rápido y por ello experimentaba
tiempos muertos más pequeños del CPU. Los resultados del trabajo no se entregaban al usuario
inmediatamente después de que el trabajo era procesado; se entregaban sólo después de que la
impresión se terminaba.

03 MAQ. CAP. 02(F0694).indd 53 8/10/07 12:53:50 AM


54 CAPÍTULO 2 Visión general de los sistemas operativos

2.4.1 El servicio del usuario


La noción del tiempo de demora se usa para cuantificar el servicio del usuario en un sistema de
proceso por lotes. Debido a la operación periférica simultánea en línea, el tiempo de demora
de un trabajo trabajoi procesado en un sistema de procesamiento de lotes incluye los siguientes
intervalos de tiempo:
1. Tiempo de formación de un lote (es decir, el tiempo de entrega de los trabajos trabajoil ,
. . . trabajon)
2. El tiempo transcurrido en ejecutar todos los trabajos del lote
3. El tiempo transcurrido en imprimir y ordenar los resultados pertenecientes a trabajos
diferentes.
Así, el tiempo de demora para trabajoi está en función de muchos factores, siendo su propio
tiempo de ejecución sólo uno de ellos. Es claro que el uso del procesamiento de lotes no ga-
rantiza mejoras en los tiempos de reprocesamiento de los trabajos. De hecho, el servicio para
los usuarios individuales probablemente se deteriorará debido a los tres factores anteriormente
citados. Esto no es sorprendente porque el procesamiento de lotes no apunta a mejorar el servicio
para el usuario: apunta a mejorar la utilización del CPU.

Ejemplo 2.5 La figura 2.13 ilustra los diferentes componentes del tiempo de demora de un trabajo.
El usuario entrega el trabajo en el instante t0. Sin embargo, el lote no se forma inmediatamente. El
personal de operaciones del centro de cómputo forma un lote sólo después de que se ha entregado
un suficiente número de trabajos. Consecuentemente, el lote realmente se forma en el instante t1.
Su procesamiento principia en el instante t2 y acaba en el instante t3. La impresión de los resultados
comienza en el instante t4 y se completa en el instante t5. Los resultados son devueltos al usuario
sólo en el instante t6. Así, el tiempo de demora del trabajo es (t6  t0). No tiene relación directa con
su propio tiempo de ejecución.

Ejecución Impresión
del lote de resultados

t0 t1 t2 t3 t4 t5 t6

Se entrega Se forma Los resultados se


el trabajo el lote devuelven al usuario
Tiempo de demora

Figura 2.13 Tiempo de demora en un sistema de procesamiento de lotes.

2.4.2 Las funciones de control de lotes

Para ejercitar un control efectivo sobre el ambiente de procesamiento por lotes, el monitor de
lotes realiza tres funciones: la planificación, la administración de la memoria, y el uso compar-
tido y la protección. Las primeras dos funciones son triviales. La planificación está implícita
en la formación de los lotes, mientras la asignación de memoria se realiza en el instante de
arranque del sistema, asignándole toda la memoria que no usa el sistema operativo al procesa-

03 MAQ. CAP. 02(F0694).indd 54 8/10/07 12:53:50 AM


2.4 Los sistemas de proceso por lotes 55

miento de trabajos del usuario. La memoria es compartida secuencialmente por los trabajos de
los usuarios.
La función de protección es más compleja. Los trabajos de usuario no pueden interferirse
directamente en la ejecución porque nunca coexisten en la memoria de una computadora. Sin
embargo, en contra de la intuición de uno, aun el uso compartido secuencial de recursos puede
conducir a la pérdida de protección. Este problema se estudia a continuación.

Los problemas de protección en los sistemas basados en tarjetas Como lo mencionamos


en el principio de esta sección, los primeros sistemas de procesamiento por lotes, en la década
de los sesenta, estuvieron basados en tarjetas. Estos sistemas poseían pocas unidades de memo-
ria secundarias, como cintas y discos, así que los comandos, los programas del usuario y los
datos se derivaban todos de una sola fuente de entrada: el lector de tarjetas. Esta característica
podría conducir a la interferencia entre los trabajos consecutivos en un lote. El ejemplo 2.6 ilus-
tra cómo puede ocurrir esto.

Ejemplo 2.6 A y B son trabajos consecutivos en un lote. Cada trabajo consta de un programa y sus
datos. El programa de trabajo A requiere diez tarjetas de datos mientras que el usuario que entregó
el trabajo A ha incluido sólo cinco tarjetas de datos. Cuando se ejecuta el trabajo A, éste lee sus
cinco tarjetas de datos y las primeras cinco tarjetas del trabajo B como sus propios datos. Cuando
se procesa el trabajo B, el compilador encuentra muchos errores, ya que faltan las primeras cinco
tarjetas de B. Así, el trabajo A ha interferido con la ejecución del trabajo B.

Declaraciones de control y el procesador de comandos Un sistema de procesamiento


por lotes requiere que un usuario inserte un conjunto de declaraciones de control en un trabajo.
Las declaraciones de control sirven para dos propósitos: para implementar un trabajo como una
“secuencia de programas” (vea la sección 1.3.1) y para evitar la interferencia mutua entre los
trabajos. La figura 2.14 muestra las declaraciones de control usadas para compilar y ejecutar
un programa en Pascal. Por simplicidad, se omiten las declaraciones relativas a las definiciones
de los conjuntos de datos o asignaciones del dispositivo que fueron necesarias en la mayoría de
sistemas de proceso por lotes.
La declaración // JOB indica el principio de un trabajo. Contiene información de contabilidad
para el usuario, como su nombre, categoría del usuario y límites de los recursos. Una declaración
// EXEC <program_name>, donde <program_name> es el nombre del programa que se va a eje-
cutar, constituye un paso de trabajo. Las tarjetas que contienen los datos de <program_name>
siguen a esta declaración. La declaración ‘/*’ marca el final de los datos. Así, la declaración
// EXEC PASCAL en la figura 2.14 señala que el compilador de Pascal debe ejecutarse para compi-
lar un programa de Pascal. El programa de Pascal que va a ser compilado se coloca entre esta de-
claración y la primera declaración ‘/*’. La declaración // EXEC sin un nombre de programa en la
figura 2.14 señala que el programa recién compilado debería ejecutarse. La segunda declaración
‘/*’ indica el final de los datos del programa y la declaración ‘/&’ indica el final del trabajo.
Una declaración de control es procesada por el componente del procesador de comandos del
kernel de procesamiento por lotes. El procesador de comandos lee una declaración de control, la
analiza y lleva a cabo la acción requerida. También revisa en busca de situaciones que podrían
conducir a la interferencia entre los trabajos. En una declaración de // JOB, verifica la validez de
la información de contabilidad del usuario e inicializa sus propias bases de datos para indicar que
el procesamiento de un nuevo trabajo ha principiado. En una declaración // EXEC organiza carga
y ejecución del programa apropiado.

03 MAQ. CAP. 02(F0694).indd 55 8/10/07 12:53:51 AM


56 CAPÍTULO 2 Visión general de los sistemas operativos

// JOB ··· → Declaración de ‘inicio del trabajo’


// EXEC PASCAL

Programa
en Pascal
/* → Declaración de ‘fin de datos’
// EXEC
Datos del
programa
en Pascal
/* → Declaración de ‘fin de datos’
/& → Declaración de ‘fin de trabajo’

Figura 2.14 Declaraciones de control en los sistemas IBM 360/370.

Si se encuentra una declaración ‘/*’ o ‘/&’ durante la ejecución de un programa, el procesa-


dor de comandos se da cuenta de que el programa ha alcanzado el fin de sus datos. Si el programa
trata de leer más tarjetas de datos, es terminado, saltándose a la declaración ‘/&’.
El procesador de comandos debe procesar cada declaración de control para implementar
estas funcionalidades. A fin de asegurarse que el procesador de comandos vea cada declaración
de control, al programa del usuario no se le permite leer las tarjetas directamente. Debe hacer
una petición al kernel para leer una tarjeta. (Esto se hace a través de una llamada de sistema:
véase la sección 2.1.2.2.) El control entonces alcanza al procesador de comandos, el cual lee
la tarjeta y verifica si la tarjeta contiene una declaración de control. Si es así, el procesador de
comandos inicia la terminación anormal del trabajo; de otra manera, entrega la tarjeta al pro-
grama del usuario.

2.5 SISTEMAS DE MULTIPROGRAMACIÓN

La concurrencia de operación entre el CPU y el subsistema de E/S (vea la sección 2.1.1) puede
explotarse para hacer que el sistema haga más trabajo. El sistema operativo puede poner a mu-
chos programas del usuario en la memoria, y permitir que el CPU ejecute las instrucciones de
un programa mientras que el subsistema de E/S está ocupado con una operación de E/S para otro
programa. Esta técnica se llama multiprogramación.
La figura 2.15 ilustra la operación de un sistema operativo de multiprogramación. La memo-
ria contiene tres programas. Una operación de E/S está en curso para el programa1, mientras que
el CPU ejecuta el programa2. El CPU es conmutado al programa3 cuando el programa2 inicia
una operación de E/S, y se le conmuta al programa1 cuando se termina la operación de E/S del
programa1. El kernel de multiprogramación realiza la planificación, la administración de la me-
moria y la administración de E/S. Usa una política simple de planificación, que analizaremos en
la sección 2.5.3.1, y realiza la asignación particionada simple o basada en los recursos en común
de la de memoria y de los dispositivos de E/S. (La planificación, la administración de memoria y
la administración de E/S se estudian en detalle en los capítulos 4, 5-6 y 7-12, respectivamente.)
Como se muestra en la figura 2.12, cada programa en la memoria podría ser un programa en

03 MAQ. CAP. 02(F0694).indd 56 8/10/07 12:53:51 AM


2.5 Sistemas de multiprogramación 57

kernel de kernel de kernel de


multiprogramación multiprogramación multiprogramación

E/S programa1 E/S programa1 CPU programa1

CPU programa2 E/S programa2 E/S programa2

programa3 CPU programa3 programa3

a) b) c)
Figura 2.15 Operación de un sistema de multiprogramación.

el trabajo actual de un lote de trabajos. Así, uno podría tener al mismo tiempo tanto el proceso
por lotes como la multiprogramación.
En principio, el CPU y el subsistema de E/S podrían operar en el mismo programa. Sin em-
bargo, en este caso el programa explícitamente debe sincronizar las actividades del CPU y del
subsistema de E/S para asegurarse de que el programa se ejecuta correctamente. El ejemplo 2.7
ilustra la necesidad para la sincronización.

Ejemplo 2.7 Considere el siguiente segmento de programa

Número de declaración Declaración


1. read a;
...
5. b := a+5;

Después de iniciar una operación de E/S para implementar la declaración read, el CPU podría
continuar con la ejecución del programa. Sin embargo, ¡no deberá usarse el valor de a en la quinta
declaración antes de que su lectura sea completada por la primera declaración! El CPU y las activi-
dades de E/S en el programa se sincronizan para asegurarse de que esto no ocurra.

El arreglo de multiprogramación asegura la sincronización del CPU y de las actividades de


E/S de una manera sencilla: asigna el CPU a un programa solamente cuando el programa no esté
ejecutando una operación de E/S.

2.5.1 El soporte arquitectónico para la multiprogramación

Una computadora debe poseer las características resumidas en la tabla 2.9 para admitir la mul-
tiprogramación (véase la sección 2.1.1). El DMA (acceso directo a la memoria) hace posible la
multiprogramación al permitir la operación concurrente del CPU y de los dispositivos de E/S.
La protección de la memoria impide la interferencia mutua entre los programas. El modo privi-
legiado del CPU provee un método infalible de implementar protección de la memoria y otras
medidas que evitan la interferencia entre los programas. Por ejemplo, las instrucciones para
cargar direcciones en el límite inferior del registro (LBR) y en el límite superior del registro
(UBR) del CPU son instrucciones privilegiadas. Si un programa trata de cambiar el contenido

03 MAQ. CAP. 02(F0694).indd 57 8/10/07 12:53:51 AM


58 CAPÍTULO 2 Visión general de los sistemas operativos

del LBR y del UBR usando estas instrucciones, surgirá una interrupción de programa porque el
CPU está en el modo del usuario mientras ejecuta los programas de usuario; el kernel abortará
el programa mientras da servicio a esta interrupción.

Tabla 2.9 Soporte arquitectónico para la multiprogramación

Característica Descripción
DMA El CPU inicia una operación de E/S cuando se ejecuta una instrucción de E/S.
El DMA implementa la transferencia de datos que interviene en la operación
de E/S sin involucrar al CPU, y ocasiona una interrupción de E/S cuando se
termina la transferencia de datos.
Protección de la Asegura que un programa no tenga acceso ni destruya el contenido de las áreas
memoria de la memoria ocupadas por otros programas o por el sistema operativo.
Modo privilegiado Ciertas instrucciones, llamadas instrucciones privilegiadas, pueden realizarse
del CPU solamente cuando el CPU esté en el modo privilegiado. Se ocasiona una
interrupción de programa si éste trata de ejecutar una instrucción privilegiada
cuando el CPU está en el modo de usuario.

Como varios programas están en memoria al mismo tiempo, las instrucciones, los datos y
las operaciones de E/S de un programa deberán protegerse contra la interferencia de otros pro-
gramas. Esto se logra simplemente colocando el CPU en el modo del usuario mientras se ejecu-
tan los programas del usuario.

2.5.2 El servicio del usuario


En un sistema de multiprogramación, el tiempo de demora es afectado por la cantidad de aten-
ción del CPU que se dedica a otros trabajos que se ejecutan concurrentemente, de modo que el
tiempo de demora de un trabajo depende del número de trabajos en el sistema y de las priorida-
des relativas que el planificador asigna a los diferentes trabajos. Como en un sistema de proceso
por lotes, el tiempo de demora de un trabajo no está directamente relacionado con sus propios
requisitos de ejecución. La influencia de las prioridades en el servicio del usuario se analiza en
la sección 2.5.3.1.

2.5.3 Las funciones del kernel de multiprogramación


Las funciones importantes del kernel de multiprogramación son:
1. La planificación
2. La administración de la memoria
3. La administración de E/S.
La planificación es realizada después de dar servicio a cada interrupción (véase la figura
2.8). Los sistemas de multiprogramación usan un esquema simple de planificación basado en
prioridades, que se describe en la siguiente sección. Las funciones 2 y 3 involucran la asignación
de memoria y de los dispositivos de E/S. Puede usarse con este propósito la asignación simple
particionada o basada en los recursos en común. Los recursos compartidos requieren protección
contra la interferencia mutua: las instrucciones, los datos y las operaciones de E/S de un progra-

03 MAQ. CAP. 02(F0694).indd 58 8/10/07 12:53:52 AM


2.5 Sistemas de multiprogramación 59

ma deberán protegerse contra la interferencia de los otros programas. Se usan dos disposiciones
para lograr esto: un hardware de protección de la memoria para impedir que un programa inter-
fiera con la memoria asignada a otros programas y el CPU se coloca en el modo no privilegiado
mientras que se ejecutan los programas del usuario. Cualquier esfuerzo de un programa del usua-
rio para tener acceso a localidades de memoria situadas fuera de su área de memoria, o para usar
una instrucción privilegiada entonces conduce a una interrupción. Las rutinas de procesamiento
de interrupción para estas interrupciones simplemente terminan el programa que las causó.

2.5.3.1 El desempeño de un sistema de multiprogramación


Una medida apropiada de desempeño de un sistema operativo de multiprogramación es el
desempeño específico, que es la relación del número de programas procesados con respecto
al tiempo total asumido para procesarlos. El desempeño específico de un sistema operativo
de multiprogramación que procesa n programas para el periodo que inicia en t0 y termina en tf
es n/(tf  t0). Esto puede ser mayor que el desempeño específico de un sistema de proce-
samiento por lotes porque las actividades en varios programas pueden tener lugar simultánea-
mente: un programa puede ejecutar instrucciones en el CPU, mientras que otros programas
realizan operaciones de E/S. Sin embargo, el desempeño específico real depende de la natura-
leza de los programas que se están procesando, es decir, cuántos de cómputo y cuántos de E/S
realizan, y cuán bien puede traslapar el kernel sus actividades con el tiempo. Para optimizar
el desempeño específico, un sistema de multiprogramación usa los conceptos y las técnicas
que se describen en la tabla 2.10. El sistema guarda un número suficiente de diferentes tipos
de programas en memoria y traslapa su ejecución usando planificación prioritaria basada en
prioridades. A continuación estudiamos estos conceptos y estas técnicas.

Tabla 2.10 Conceptos y técnicas de multiprogramación

Concepto/técnica Descripción
Grado de El número de programas de usuario que el sistema operativo guarda en la
multiprogramación memoria en cualquier momento.
Mezcla de El kernel guarda una mezcla de programas acotados por el CPU y por la E/S
programas en la memoria, donde
• Un programa acotado por el CPU es un programa que emplea mucho
cómputo y muy poca E/S. Usa el CPU en ráfagas largas: es decir, usa el
CPU durante mucho tiempo antes de iniciar una operación de E/S.
• Un programa acotado por E/S emplea muy poco cómputo y mucha
E/S. Usa el CPU en pequeñas ráfagas.
Planificación A cada programa se le asigna una prioridad. El CPU siempre se asigna al
priorizante y basada programa con la prioridad más alta que desee usarla. Se prioriza a un programa
en prioridades de prioridad baja que se ejecute en el CPU si un programa de prioridad más
alta desea usar el CPU.

La mezcla de programa Para ver por qué un sistema operativo debe conservar una mezcla
correcta de programas en ejecución, considere un sistema de multiprogramación con m  2.
Sean progl y prog2 los dos programas en procesamiento. Demos por supuesto que ambos pro-
gramas están fuertemente acotados por el CPU y prog1 se está ejecutando. Siendo acotado por

03 MAQ. CAP. 02(F0694).indd 59 8/10/07 12:53:52 AM


60 CAPÍTULO 2 Visión general de los sistemas operativos

el CPU, prog1 realiza una larga ráfaga de actividad del CPU antes de ejecutar una operación de
E/S. El CPU se da al prog2 cuando el prog1 inicia una operación de E/S. prog2 también realiza
una larga ráfaga de actividad del CPU antes de ejecutar una operación de E/S. prog1 habrá
terminado su operación de E/S en ese momento, así es que puede usar el CPU para otra ráfaga
de computación. De esta manera, el CPU se mantiene ocupado la mayoría de las veces. Per-
manece ocioso sólo cuando ambos programas ejecutan simultáneamente la E/S. El subsistema
de E/S está subcargado. De hecho, está ocioso la mayoría de las veces porque los programas
contienen ráfagas largas del CPU, de modo que los periodos de las actividades concurrentes
del CPU y de E/S son raros. Consecuentemente, el desempeño específico es bajo.
Para analizar el desempeño específico de este sistema de multiprogramación, lo compa-
raremos con un sistema de procesamiento por lotes que procesan los mismos dos programas.
El sistema de procesamiento por lotes dará servicio a los programas uno tras otro, es decir, ya
sea en la secuencia prog1, prog2 o en la secuencia prog2, prog1. El desempeño específico será
idéntico en ambos casos. Para comparar el desempeño específico del procesamiento por lotes y
de los sistemas de multiprogramación, introducimos la noción de progreso de un programa. Un
programa “progresa” cuando el CPU ejecuta sus instrucciones o cuando su operación de E/S
está en curso. El desempeño específico será mayor si varios programas progresan concurrente-
mente.
En nuestro ejemplo, prog1 y prog2 progresan concurrentemente sólo cuando uno de ellos
ejecuta la E/S y el otro ejecuta en el CPU, es decir, sólo cuando el CPU y el subsistema de E/S
se ejecutan concurrentemente. Tales periodos son raros, por lo que los periodos en que ambos
programas progresan también son raros. Consecuentemente, el desempeño específico del sistema
de multiprogramación posiblemente sea muy parecida al sistema de procesamiento por lotes.
Una forma práctica para mejorar el desempeño específico es seleccionar una mezcla de
programas que contengan algunos programas acotados por el CPU y otros acotados por la E/S.
Por ejemplo, sea un sistema de multiprogramación con m  2 que contiene los siguientes pro-
gramas:

progcb : el programa acotado por el CPU


progiob : el programa acotado por la E/S

El progcb puede mantener el CPU ocupado mientras que progiob mantiene ocupado al subsistema
de E/S. Así, ambos programas harán buen progreso y el desempeño específico será más alto que
en un sistema de procesamiento por lotes.

La prioridad de programa Asumimos un esquema simple de implementación en el cual


cada programa tiene una prioridad numérica donde un mayor valor implica una prioridad más
alta.

Definición 2.5 (Prioridad) La prioridad es una noción que rompe los empates que usa el
planificador para decidir cuál petición debería programarse en el servidor cuando muchas
peticiones esperan servicio.

Cuando muchos programas están listos para usar el CPU, el kernel de multiprogramación
le da el CPU al programa con la prioridad más alta. Esta regla conduce a la priorización de

03 MAQ. CAP. 02(F0694).indd 60 8/10/07 12:53:52 AM


2.5 Sistemas de multiprogramación 61

un programa de prioridad baja cuando un programa de prioridad alta está listo para usar el
CPU.

Definición 2.6 (Priorización) La priorización es la desasignación forzada del CPU de un


programa.

El ejemplo 2.8 ilustra cómo tiene lugar la priorización en un sistema de multiprograma-


ción.

Ejemplo 2.8 En un sistema de multiprogramación, un programa de prioridad alta está ejecutando


una operación de E/S y un programa de prioridad baja está en ejecución. Como se analizó en el
ejemplo 2.3 y como se ilustra en la figura 2.9, cuando ocurre una interrupción el CPU es conmutado
a la ejecución de la rutina de procesamiento de interrupción de la E/S que tiene la dirección
inicial bbb. Después de las acciones de procesamiento de interrupción, el control se transfiere al
planificador, que selecciona el programa de prioridad alta para su ejecución. Efectivamente, el
programa de prioridad baja que se ejecutaba en el CPU ha sido priorizado.

Contraste el ejemplo 2.8 con el ejemplo 2.3 en el contexto de un sistema de multiprogra-


mación. En el ejemplo 2.3 se supuso que el programa que se ejecutaba cuando ocurrió una
interrupción se programa otra vez para la ejecución. Esta hipótesis implica que la operación
de E/S cuya terminación fue señalizada por la interrupción debió haber pertenecido a algún
programa de prioridad más baja. El programa interrumpido todavía sigue siendo el programa
de prioridad más alta que puede usar el CPU, así es que se le selecciona para su ejecución por
el planificador.

La asignación de prioridades de programa El kernel del sistema de multiprogramación


tiene que asignar las prioridades de los programas. La mezcla de programas consta de algunos
programas acotados por la CPU y otros acotados por la E/S, por lo que el kernel tiene que decidir
si los programas acotados por el CPU o los acotados por la E/S deberán tener una prioridad más
alta. Ésta es una decisión crucial porque puede influir en el desempeño específico del sistema. La
regla de asignación de prioridades en los sistemas de multiprogramación es como sigue:

• En los sistemas de multiprogramación, los programas acotados por la E/S deberán tener
una prioridad más alta que los programas acotados por el CPU.

Para ilustrar esta regla, y su influencia en el desempeño específico del sistema, conside-
ramos un sistema de multiprogramación que contiene a progcb y a progiob. Las actividades del
CPU y de E/S de estos programas se ilustran en forma de una gráfica de tiempo en la cual el eje
x muestra el tiempo y el eje y muestra las actividades del CPU y de la E/S de los dos programas
(véase la figura 2.16). Comparamos las gráficas de tiempo para las diferentes asignaciones de
prioridad para progcb y progiob. A fin de enfatizar por qué los programas acotados por la E/S de-
berán tener una prioridad más alta, primero estudiamos cómo funcionaría mal un sistema cuando
a un programa acotado por el CPU se le da una prioridad más alta.

Prioridad más alta para los programas acotados por el CPU El ejemplo 2.9 estudia las
características de la operación del sistema cuando los programas acotados por el CPU tienen una
prioridad más alta que los acotados por la E/S.

03 MAQ. CAP. 02(F0694).indd 61 8/10/07 12:53:53 AM


62 CAPÍTULO 2 Visión general de los sistemas operativos

Ejemplo 2.9 La gráfica de tiempo de la figura 2.16 bosqueja la operación del sistema cuando
progcb, el programa acotado por el CPU, tiene prioridad más alta. Observe que la gráfica está fuera
de escala. La actividad del CPU de progiob y las actividades de E/S de ambos programas se han
exagerado para mayor claridad.

CPU ocioso
progiob
actividad
del CPU
progcb

progiob
actividad
de E/S
progcb
E/S
ociosa
0 t11 t12 t13 t14 t15 t16 t17 t18
tiempo →

Figura 2.16 Gráfica de tiempo cuando el programa acotado por el CPU tiene prioridad más alta.

progcb es el programa de prioridad más alta, así es que comienza a ejecutarse para el instante t  0.
Después de una larga ráfaga de actividad del CPU, inicia una operación de E/S (instante de tiempo
t11). Ahora el CPU se conmuta a progiob, el programa acotado por la E/S. Así, el procesamiento de
progiob por el CPU es concurrente con la operación de E/S de progcb. progiob inicia pronto una ope-
ración de E/S, es decir, para t12. Entonces están en curso dos operaciones de E/S y el CPU estará
ocioso hasta que una de ellas termine. Suponiendo que la E/S de progcb termina antes, comenzará la
ejecución en el CPU para tl3. La terminación de la E/S de progiob para t14 no hace ninguna diferen-
cia para el progreso de progcb, el cual continúa su ejecución, ya que es el programa de prioridad
más alta. Su ráfaga del CPU termina en el instante t15 cuando inicia una operación de E/S. Entonces
puede repetirse el ciclo de eventos del intervalo de tiempo t11-t15. Observe que el CPU está ocioso
en los intervalos t12-t13 y t16-t17. De modo semejante, el subsistema de E/S está ocioso en los inter-
valos t14-t15 y t17-t18.

Del ejemplo 2.9 uno puede hacer las siguientes observaciones relativas a la operación del
sistema cuando los programas acotados por el CPU tienen una prioridad más alta que los progra-
mas acotados por la E/S:
1. La utilización del CPU es razonable.
2. La utilización de la E/S es deficiente porque el programa acotado por el CPU y el progra-
ma acotado por la E/S no obtienen una oportunidad para ejecutarse.
3. Los periodos de las actividades concurrentes del CPU y de la E/S son raros.
De la observación 3 es claro que la mayoría de las veces sólo uno de los dos programas
puede progresar, así es que el desempeño específico no es mucho mejor que en un sistema de
procesamiento por lotes. Los intentos de mejorar el desempeño específico aumentando el grado
de multiprogramación tienen poco éxito. Por ejemplo, aumentemos el grado de multiprograma-

03 MAQ. CAP. 02(F0694).indd 62 8/10/07 12:53:53 AM


2.5 Sistemas de multiprogramación 63

ción (m) a 3 e introduzcamos un programa prog3 acotado por el CPU con una prioridad entre las
de progcb y progiob. Esta acción mejora la utilización del CPU, ya que el programa nuevo puede
conservar el CPU ocupado en intervalos donde habría estado desocupada si la m fuese 2 (véase
el intervalo t12-t13). Sin embargo, induce a fomentar el deterioro de la utilización de la E/S por-
que el progiob recibe menos oportunidad para ejecutar. La adición de un programa acotado por la
E/S (digamos que prog4) en lugar de prog3 representa muy poca diferencia para el CPU y para
la utilización de la E/S porque el prog4 tendría la prioridad mínima, así es que no obtiene mucha
oportunidad para su ejecución.

CPU ocioso
progiob
Actividad
del CPU
progcb

progiob
Actividad
de la E/S
progcb
E/S ociosa

0 t21 t22 t23 t24 t25 t26 t27 t28 t29


tiempo →

Figura 2.17 Gráfica de cronometrado cuando el programa acotado por la E/S tiene prioridad más alta.

Prioridad más alta para los programas acotados por la E/S El ejemplo 2.10 analiza
las características de la operación del sistema cuando los programas acotados por la E/S tienen
prioridad más alta que los acotados por el CPU.

Ejemplo 2.10 La figura 2.17 bosqueja la operación del sistema cuando el programa acotado por la
E/S tiene una prioridad más alta. progiob es el programa de prioridad más alta; por tanto, recibe el
CPU cada vez que lo necesita, es decir, siempre que la E/S no está ejecutándose. Cuando el progiob
inicia una operación de E/S, progcb obtiene el CPU. Siendo un programa acotado por el CPU, progcb
lo mantiene ocupado hasta que la E/S de progiob se termina. progcb se prioriza cuando progiob com-
pleta su E/S, ya que progiob tiene una prioridad más alta que progcb. Esto explica el comportamiento
del sistema en el periodo 0-t26. Las desviaciones de este comportamiento ocurren cuando el progcb
inicia una operación de E/S. En ese momento ambos programas se involucran en la E/S y el CPU
permanece ocioso hasta que uno de ellos completa su E/S. Esto explica los periodos ociosos del
CPU t26-t27 y t28-t29. Los periodos ociosos de E/S ocurren cada vez que progiob se ejecuta en
el CPU y progcb no está ejecutando la E/S (vea los intervalos t22-t23 y t24-t25).

Del ejemplo 2.10, uno puede hacer las siguientes observaciones relativas a la operación del
sistema cuando los programas acotados por la E/S tienen prioridades más altas:
1. La utilización del CPU es razonable.
2. La utilización de la E/S es razonable [sin embargo, existiría una E/S ociosa si el sistema
contiene muchos dispositivos capaces de operar en el modo DMA (acceso directo a la
memoria)].

03 MAQ. CAP. 02(F0694).indd 63 8/10/07 12:53:53 AM


64 CAPÍTULO 2 Visión general de los sistemas operativos

3. Los periodos de las actividades concurrentes del CPU y de la E/S son frecuentes.
progiob hace buen progreso, ya que es el programa de prioridad más alta. Hace muy poco
uso del CPU, así es que progcb también hace buen progreso. El desempeño específico es así sus-
tancialmente mayor que en el sistema de procesamiento por lotes. Otra característica importante
de esta asignación de prioridad es que el desempeño específico del sistema puede mejorarse
sumando más programas. La tabla 2.11 muestra cómo puede lograrse esto. Por tanto, uno puede
concluir que la asignación de prioridades más altas para los programas acotados por la E/S con-
duce a un buen desempeño específico. También permite al sistema operativo combatir el desem-
peño específico escaso en el sistema, aumentando el grado de multiprogramación.

Tabla 2.11 Mejoramiento del desempeño específico en un sistema de multiprogramación

Añadir un programa Puede introducirse un programa acotado por el CPU (digamos, prog3) para
acotado por el CPU utilizar algún tiempo del CPU que se desperdicia en el ejemplo 2.10 (por
ejemplo, los intervalos t26-t27 y t28-t29). prog3 tendrá la prioridad más baja.
Entonces su presencia no afectará el progreso hecho por progcb y progiob.
Añadir un programa Puede introducirse un programa acotado por la E/S (digamos, prog4). Su prio-
acotado por la E/S ridad será entre las prioridades de progiob y progcb. La presencia de prog4 me-
jorará la utilización de la E/S. Tampoco afectará mucho al progreso de progcb,
ya que prog4 no usa un lapso importante de tiempo de CPU.

El grado de multiprogramación Cuando se mantiene una mezcla correcta de programas,


un incremento en el grado de multiprogramación, m, dará como resultado un incremento en el
desempeño específico. La capacidad de memoria y los requisitos promedio de memoria de los
programas del usuario determinan los valores prácticos de m. La figura 2.18 muestra cómo varía
el desempeño específico de un sistema con el grado de multiprogramación.


Desempeño
específico

1 2 3 m
Grado de multiprogramación →

Figura 2.18 Variación del desempeño específico con el grado de multiprogramación.

Cuando m  1, el desempeño específico se determina por el tiempo transcurrido del pro-


grama solitario en el sistema. Para valores mayores de m, los programas de prioridad más baja

03 MAQ. CAP. 02(F0694).indd 64 8/10/07 12:53:54 AM


2.6 Los sistemas de tiempo compartido 65

también contribuyen al desempeño específico. De cualquier forma su contribución se limita por


su oportunidad para usar el CPU. El desempeño específico se estanca para valores crecientes de
m si los programas de prioridad baja no obtienen ninguna oportunidad para ejecutarse.

2.6 LOS SISTEMAS DE TIEMPO COMPARTIDO

En un ambiente de cómputo no interactivo, un usuario no tiene contacto con su programa du-


rante su ejecución. En tal ambiente es natural usar el procesamiento por lotes o el paradigma de
la multiprogramación. Los dos sistemas proveen un servicio deficiente al usuario. Sin embargo,
esto es inevitable debido a la naturaleza de los dispositivos de la E/S en uso.
En un ambiente interactivo de computación, un usuario puede proveer entradas a un pro-
grama desde el teclado y examinar su salida en la pantalla del monitor. Se usa un paradigma
diferente del sistema operativo en tales ambientes para proveer un servicio rápido a lo que el
usuario pide; crea la ilusión de que cada usuario tiene un sistema de cómputo para su disposición
exclusiva. Este paradigma se llama tiempo compartido.

2.6.1 El servicio para el usuario


El servicio para el usuario se caracteriza en términos del tiempo asumido para dar atención a
una subpetición, es decir, el tiempo de respuesta (rt). Los beneficios de los buenos tiempos de
respuesta se aprecian mejor durante el desarrollo del programa. Un usuario comprometido en el
desarrollo de programas compila y prueba un programa repetidamente. Una petición típica emi-
tida por el usuario implica la compilación de una declaración o una ejecución de un programa
para los datos dados. La respuesta consta de un mensaje del compilador o de resultados compu-
tados por un programa. Un usuario emite la siguiente petición después de recibir la respuesta a
la petición previa. Los buenos tiempos de respuesta conducirán a una mejora en la productividad
del usuario. Cualquier aplicación en la cual un usuario tiene que interactuar con un cómputo
derivará beneficios similares de los buenos tiempos de respuesta.
El énfasis en los buenos tiempos de respuesta, en vez de en el uso eficiente o en el desem-
peño específico, requiere empleo de nuevos principios y técnicas de diseño. La noción de un
trabajo ya no tiene importancia, tiene que diseñarse una interfaz interactiva del usuario, y son
necesarias nuevas técnicas de planificación y de administración de memoria para proveer buenos
tiempos de respuesta a un gran número de usuarios. Estos cambios se estudian en las siguientes
secciones.

2.6.2 La planificación
El servicio para el usuario en un sistema de tiempo compartido se caracteriza por los tiempos
de respuesta a las peticiones del usuario, por eso el kernel de tiempo compartido debe proveer
buenos tiempos de respuesta para todos los usuarios. Para alcanzar esta meta, todos los usuarios
deben obtener una oportunidad igual para presentar sus peticiones computacionales y hacer que
se les dé atención. Cada usuario también debe recibir un servicio razonable. Se hacen dos pro-
visiones para asegurar esto.
1. A los programas no se les asignan prioridades porque la asignación de prioridades puede
negar la atención del sistema operativo a los programas de prioridad baja. En lugar
de eso, los programas se ejecutan por turno.

03 MAQ. CAP. 02(F0694).indd 65 8/10/07 12:53:54 AM


66 CAPÍTULO 2 Visión general de los sistemas operativos

2. Se evita que un programa consuma cantidades irrazonables de tiempo de procesador


cuando se programa su ejecución. Esta provisión asegura que cada petición recibirá aten-
ción del sistema operativo sin retrasos irrazonables.
Estas provisiones se implementan usando las técnicas de planificación round-robin e intervalo
de tiempo, respectivamente.
La planificación round-robin Cuando un usuario hace una petición computacional para
su programa, éste se añade al final de una lista de planificación. El planificador siempre retira
el primer programa de la lista de planificación y le da el CPU. Cuando un programa termina de
computar su respuesta para una petición, se le retira del CPU y se selecciona el primer programa
en la lista nueva para la ejecución. Cuando el usuario hace otra petición, el programa se agrega
de nuevo al final de la lista de planificación.
La división en intervalos de tiempo La noción de un intervalo de tiempo se usa para im-
pedir la monopolización del CPU por un programa.

Definición 2.7 (Intervalo de tiempo) Un intervalo de tiempo  es la cantidad más grande de


tiempo de procesador que cualquier programa puede consumir cuando se le programa para
ejecutarse en el CPU.

La división del tiempo en un intervalo es una implementación de la noción de un intervalo


de tiempo. Cada programa se sujeta al límite de tiempo especificado por el intervalo de tiempo.
Se prioriza al programa que sobrepase este límite. La figura 2.19 ilustra un esquema de la pla-
nificación round-robin con el tiempo acotado en intervalos. El programa priorizado se añade al
final de la lista de planificación. Un programa puede programarse y priorizarse algunas veces
antes de que produzca una respuesta.

Programa priorizado

.. Terminación del
. intervalo de tiempo
Planificador CPU
Cómputo
Lista de Programa terminado
planificación seleccionado
Figura 2.19 Un esquema de la planificación round-robin con intervalo de tiempo.

El kernel de tiempo compartido usa el contador de intervalos de la computadora para im-


plementar la división del tiempo en intervalos. El contador de intervalos consta de un registro
llamado registro del cronometrador (timer), que puede almacenar un número entero que repre-
sente un intervalo de tiempo en horas, minutos y segundos. El contenido del registro se reduce
con una periodicidad apropiada, comúnmente unas cuantas veces cada segundo. Surge una inte-
rrupción del cronometrador cuando el contenido del registro del cronometrador se hace cero, es
decir, cuando el espacio de tiempo expira.
Un sistema operativo de tiempo compartido usa la planificación round-robin con el tiempo
dividido en intervalos. El algoritmo 2.1 muestra las acciones del kernel de tiempo compartido.

03 MAQ. CAP. 02(F0694).indd 66 8/10/07 12:53:54 AM


2.6 Los sistemas de tiempo compartido 67

Algoritmo 2.1 (Tiempo dividido en intervalos)


1. Seleccione el primer programa en la lista de planificación para la ejecución. Sea P el
programa seleccionado. Retire a P de la lista de planificación.
2. Cargue el valor del intervalo de tiempo () en el contador de intervalos.
3. Inicie la ejecución del programa P en el CPU.
4. Si P inicia una operación de E/S, vaya al paso 1 para programar otro programa para la
ejecución.
5. Cuando ocurra una interrupción del cronometrador, priorice a P y agréguelo al final de la
lista de planificación. Vaya al paso 1.
En el paso 5, el programa priorizado se coloca al final de la lista de planificación. Si un
programa no consume  segundos de tiempo de procesador, por ejemplo, si inicia una operación
de E/S, el kernel simplemente procede a planificar el siguiente programa. Cuando surge una
interrupción de terminación de la E/S, el kernel identifica el programa cuya operación de E/S ha
completado y agrega el programa al final de la lista de planificación.

Ejemplo 2.11 La figura 2.20 ilustra la operación del algoritmo 2.1 en un sistema de tiempo com-
partido que usa un intervalo de tiempo . Se supone que la carga general de planificación del
sistema operativo es de  segundos. La figura 2.20a) bosqueja la situación cuando el intervalo de
tiempo expira durante la ejecución de un programa. El kernel prioriza este programa y planifica otro
para la ejecución. Por consiguiente, el programa nuevo comienza a ejecutarse  segundos después
de que expira el intervalo de tiempo. En la figura 2.20b), el programa que se ejecuta en el CPU
hace una petición de E/S. Después de empezar la operación de E/S, el kernel procede a programar
otro programa para la ejecución. Si ignoramos la carga general del sistema operativo al iniciar una
operación de E/S, el programa recién planificado comienza a ejecutarse  segundos después de que
se hizo petición de E/S.

El programa El programa El programa El programa


es planificado es planificado es planificado es planificado
δ σ <δ σ

Expira el intervalo Inicia la operación


de tiempo de E/S
a) b)

Figura 2.20 Operación de un planificador con intervalo de tiempo.

Cuando se usa la planificación round-robin con intervalo de tiempo, el tiempo de respues-


ta para cada petición del usuario puede estimarse de la siguiente manera: sea n el número de
usuarios que usan el sistema en cualquier momento. Supongamos que cada petición del usuario
requiere exactamente  segundos del CPU para la terminación. Como en el ejemplo 2.11, sea 
el tiempo de procesador que transcurre al conmutar de la ejecución de un programa al siguiente

03 MAQ. CAP. 02(F0694).indd 67 8/10/07 12:53:55 AM


68 CAPÍTULO 2 Visión general de los sistemas operativos

programa. Si suponemos que la operación de E/S se completa instantáneamente y un usuario


alimenta la siguiente petición inmediatamente después de recibir la respuesta a la petición ante-
rior, el tiempo de respuesta (rt) y la eficiencia del CPU () están dados por

rt  n.(  ) (2.2)


    (2.3)


El tiempo de respuesta real puede ser diferente al valor de rt predicho por la ecuación 2.2.
Hay varias razones para esto. Primero, el valor de rt puede ser más pequeño que lo predicho por
la ecuación 2.2 porque tal vez no todos los usuarios hicieron las peticiones para sus programas.
Por tanto, el rt no sería influido por n, el número total de usuarios en el sistema, sino por el
número de usuarios activos (na), na
n. Segundo, las peticiones de los usuarios no requieren
exactamente  segundos del CPU para producir una respuesta; así, la relación de rt y  con 
es más compleja que lo mostrado en las ecuaciones 2.2 y 2.3. La tabla 2.12 resume el efecto de
valores pequeños o grandes de . De aquí se puede concluir que el rt tal vez no sea pequeño para
un  pequeño y  tal vez no sea grande para  grande, lo que hace la elección de  una decisión
sensible del diseño.

Tabla 2.12 Influencia de  en el tiempo de respuesta

Valor de ␦ Influencia sobre el tiempo de respuesta


 muy pequeño El valor de  puede hacerse más pequeño que el tiempo de
CPU necesario para satisfacer una petición computacional.
Un programa de este tipo tendría que planificarse algunas
veces antes de que pueda producir una respuesta. Así, el
tiempo de respuesta sería mayor que na  (  ) segun-
dos. También, las magnitudes de  y  pueden ser compa-
rables, lo que conduce a valores bajos de  de la ecuación
2.3. El desempeño de la memoria caché también puede ser
más deficiente (véase la sección 2.1.1).
 grande La mayoría de las peticiones de los usuarios pueden proce-
sarse en menos que  del CPU. Así, la mayoría de los pro-
gramas liberan el CPU antes de  segundos (véase el paso
4 del algoritmo 2.1). De esta manera, rt
na  (  ) y
 es peor que el valor predicho por la ecuación 2.3.

Ejemplo 2.12 La figura 2.21 muestra la operación de un sistema de tiempo compartido con dos
programas P1 y P2. Las partes a) y b) muestran la ejecución de los programas totalmente solos.
Ambos programas tienen un comportamiento cíclico, donde cada ciclo contiene una ráfaga de acti-
vidad del CPU seguido por una ráfaga de actividad de E/S. Las ráfagas del CPU de los programas
P1 y P2 son 15 y 30 mseg, respectivamente, mientras que las ráfagas de E/S son 100 y 60 mseg, res-
pectivamente. Cuando se ejecutan solos, los programas tienen tiempos de respuesta de 115 mseg y
90 mseg, respectivamente, ya que un programador ve los resultados de una computación en el
monitor al final de una operación de E/S.

03 MAQ. CAP. 02(F0694).indd 68 8/10/07 12:53:55 AM


2.6 Los sistemas de tiempo compartido 69

CPU P1
a)
E/S P1 ···

0 50 100 150 200

CPU P2
b)
E/S P2

0 50 100 150 200

CPU P1
P2
c) P1
E/S P2

0 50 100 150 200


tiempo →

Figura 2.21 Ejecución de los programas P1 y P2 solos y juntos.

Tabla 2.13 Planificación de tiempo compartido

Lista de Programa
Tiempo planificación planificado Observaciones
0 {P1,P2} P1 P1 se prioriza a los 10 mseg
10 {P2,P1} P2 P2 se prioriza a los 20 mseg
20 {P1,P2} P1 P1 inicia la E/S a los 25 mseg
25 {P2} P2 P2 se prioriza a los 35 mseg
35 {P2} P2 P2 inicia la E/S a los 45 mseg
45 {} El CPU está ocioso
105 {P2} P2 P2 se prioriza a los 115 mseg
115 {P2} P2 P2 se prioriza a los 125 mseg
125 {P1,P2} P1 P1 se prioriza a los 135 mseg

La parte c) demuestra ejecución de los programas en un sistema de tiempo compartido usando


un intervalo de tiempo de 10 mseg. Los programas P1 y P2 entonces obtienen ráfagas de CPU limi-
tadas a 10 mseg. Ambos programas tienen que planificarse un poco antes de que puedan completar
las ráfagas del CPU de su ciclo de ejecución y puedan iniciar la E/S. Así P1 inicia una operación de
E/S a 25 mseg desde el inicio de operación del sistema. Ahora P2 obtiene dos intervalos de tiempo
consecutivos (separados, por supuesto, por la carga general del sistema operativo para las acciones
que prioricen primero el programa P2 y luego lo programan otra vez porque ningún otro programa
en el sistema necesita el CPU). La operación de E/S de P1 se completa en 125 mseg. P2 empieza una

03 MAQ. CAP. 02(F0694).indd 69 8/10/07 12:53:55 AM


70 CAPÍTULO 2 Visión general de los sistemas operativos

operación de E/S en 45 mseg, que la completa en 105 mseg. Así, los tiempos de respuesta son 125
mseg y 105 mseg, respectivamente. La tabla 2.13 muestra la lista de planificación y las decisiones
de planificación del kernel entre 0 y 105 mseg, suponiendo que la carga general de planificación
es insignificante.

2.6.3 La administración de memoria

En el ejemplo 2.12, el CPU estaba ocioso entre 45 mseg y 105 mseg, por lo que el sistema puede
dar servicio a unos pocos programas de usuario adicionales. Sin embargo, el sistema de cómputo
debe poseer una memoria grande para acomodar todos estos programas, lo cual es una proposi-
ción cara. La técnica de intercambio provee una alternativa por medio de la cual un sistema de
cómputo puede admitir a un gran número de usuarios sin tener que poseer una memoria grande.

Definición 2.8 (Intercambio) El intercambio es la técnica de retirar temporalmente los pro-


gramas inactivos de la memoria de un sistema de cómputo.

Un programa inactivo es aquel que no está ejecutándose en el CPU, ni está ejecutando una
operación de E/S. La figura 2.22 ilustra el intercambio tal como se usa en una situación práctica.
Los programas existentes en la memoria se clasifican en tres categorías:
1. Los programas activos: un programa activo se ejecuta en el CPU mientras que otros eje-
cutan la E/S.
2. Programas que se están intercambiando para que salgan de la memoria.
3. Programas que se están intercambiando para que entren a la memoria.

Kernel
Programas que se
están intercambiando
para que salgan
Programa en Programas
ejecución intercambiados
Programas que se
están intercambiando
para que entren

Figura 2.22 Esquema del intercambio.

Cada vez que un programa en ejecución se vuelve inactivo, el sistema operativo lo intercambia
para que salga, copiando sus instrucciones y datos en un disco. Se carga un programa nuevo en
su lugar. El programa nuevo se agrega al final de la lista de planificación; recibe la atención del
CPU en su debido momento.
El uso del intercambio es factible en los sistemas de tiempo compartido porque el kernel
de tiempo compartido puede estimar cuándo es probable que un programa se planifique como

03 MAQ. CAP. 02(F0694).indd 70 8/10/07 12:53:56 AM


2.7 Sistemas operativos de tiempo real 71

el siguiente. Puede usar esta estimación para asegurar que el programa se intercambie a fin de
que entre antes de su turno en el CPU. Observe que el intercambio aumenta la carga general del
sistema operativo debido al disco de E/S que interviene.

2.7 SISTEMAS OPERATIVOS DE TIEMPO REAL

En una clase de aplicaciones llamadas aplicaciones de tiempo real, los usuarios necesitan que la
computadora realice algunas acciones de manera oportuna para controlar las actividades en un
sistema externo, o participar de ellas. La puntualidad de acciones es determinada por las restric-
ciones de tiempo del sistema externo. Consecuentemente, definimos una aplicación de tiempo
real como sigue:

Definición 2.9 (Aplicación de tiempo real) Una aplicación de tiempo real es un programa
que responde a las actividades en un sistema externo dentro de un tiempo máximo determi-
nado por el sistema externo.

Si la aplicación se toma mucho tiempo para responder a una actividad, puede ocurrir un fra-
caso en el sistema externo. Usamos el término requisito de respuesta de un sistema para indicar
el valor más grande de tiempo de respuesta para el cual el sistema puede funcionar perfectamen-
te; una respuesta oportuna es aquella cuyo tiempo de respuesta es más pequeño que el requisito
de respuesta del sistema.
Considere un sistema que almacena datos recibidos de un satélite sensor remoto. El saté-
lite envía muestras digitalizadas a la estación terrena a razón de 10 000 muestras por segundo.
El proceso de aplicación está obligado simplemente a almacenar estas pruebas en un archivo.
Como llega una muestra nueva cada 100 microsegundos, la computadora debe responder a cada
petición de “almacenar la muestra” en menos de 100 microsegundos, o la llegada de una muestra
nueva borrará la muestra anterior en la memoria de la computadora. Este sistema es una aplica-
ción de tiempo real porque una muestra debe guardarse en menos de 100 microsegundos para
impedir un fracaso. Su requisito de respuesta es 99.9 microsegundos. El tiempo límite de una
acción en una aplicación de tiempo real es el tiempo para el cual la acción deberá realizarse. En
el ejemplo anteriormente citado, si una muestra nueva es recibida del satélite en el instante t, el
tiempo límite para almacenarla en disco es t  99.9 microsegundos.
Los ejemplos de aplicaciones de tiempo real pueden encontrarse en las aplicaciones de guía,
dirección y control de misiles, como el control de procesos y el control de tráfico aéreo; los sis-
temas de muestreo de datos y de adquisición de datos, como los sistemas de despliegue en autos;
los sistemas multimedia y las aplicaciones, como los sistemas bancarios y las reservaciones que
se basan en el uso de bases de datos en tiempo real. Los requisitos de respuesta de estos sistemas
varían de algunos microsegundos o milisegundos para los sistemas de control y de guía hasta
algunos segundos para los sistemas bancarios y de reservaciones.

2.7.1 Sistemas de tiempo real duros y suaves

Para aprovechar las características de los sistemas de tiempo real al tiempo que se logra una
máxima efectividad de costos, han evolucionado dos clases de sistemas de tiempo real. Un siste-

03 MAQ. CAP. 02(F0694).indd 71 8/10/07 12:53:56 AM


72 CAPÍTULO 2 Visión general de los sistemas operativos

ma de tiempo real duro que está comúnmente dedicado a procesar aplicaciones de tiempo real,
y probablemente cumple con el requisito de respuesta de una aplicación bajo todas las condi-
ciones. Un sistema de tiempo real suave hace el mejor esfuerzo para cumplir con el requisito de
respuesta de una aplicación de tiempo real, pero no puede garantizar que podrá cumplirlo bajo
todas las condiciones. Comúnmente, cumple con los requisitos de respuesta en alguna manera
probabilística, digamos, 98 por ciento del tiempo. Las aplicaciones de guía y de control fracasan
si no pueden cumplir con el requisito de tiempo de respuesta; por tanto, es común que reci-
ban servicio mediante el uso de sistemas de tiempo real duros. Las aplicaciones que intentan
suministrar una buena calidad de servicio, por ejemplo, las aplicaciones multimedia y las aplica-
ciones para reservaciones y para la banca, no tienen una noción de fracaso, así que se les puede
dar servicio usando sistemas de tiempo real suaves; la calidad de la imagen provista por un
video en un sistema sobre demanda puede deteriorarse ocasionalmente, ¡pero uno todavía puede
observar el video!

2.7.2 Características de un sistema operativo en tiempo real

Un sistema operativo en tiempo real provee las características especiales resumidas en la tabla
2.14. Una aplicación en tiempo real puede ser codificada de manera tal que el sistema operativo
puede ejecutar sus partes concurrentemente. Cuando se usa la planificación basada en priori-
dades, tenemos una situación análoga a la multiprogramación dentro de la aplicación: si una
parte de la aplicación inicia una operación de E/S, el sistema operativo planificaría otra parte de
la aplicación. Así, el CPU y las actividades de E/S de la aplicación pueden traslaparse entre sí,
lo cual ayuda a reducir el peor caso de tiempo de respuesta de la aplicación. La planificación de
plazos límites es una técnica especial de planificación que ayuda a que una aplicación cumpla
con su tiempo límite. Algunos aspectos de planificación de tiempo límite se describen posterior-
mente en la sección 4.2.

Tabla 2.14 Características de un sistema operativo en tiempo real (RTOS)

1. Permite la creación de procesos múltiples dentro de una aplicación.


2. Permite la asignación de prioridades a los procesos.
3. Permite al programador definir las interrupciones y las rutinas de
procesamiento de las interrupciones.
4. Usa planificación accionada por prioridades u orientada a los plazos
límite.
5. Suministra tolerancia a las fallas y capacidades de degradación
parcial.

La especificación de las interrupciones específicas de dominio y las acciones para dar servi-
cio a las interrupciones le permite una aplicación de tiempo real para responder en una manera
oportuna a las condiciones y eventos especiales en el sistema externo. La pronosticabilidad de
las políticas y de la carga general del sistema operativo le permite a un desarrollador de aplica-
ciones calcular el tiempo de respuesta más desfavorable que el sistema operativo puede proveer
y determina si puede cumplir con los requisitos de respuesta de la aplicación. Cuando los recur-

03 MAQ. CAP. 02(F0694).indd 72 8/10/07 12:53:56 AM


2.8 Los sistemas operativos distribuidos 73

sos se sobrecargan, la carga general del sistema operativo puede volverse no acotada, es decir,
arbitrariamente grande. Por ejemplo, si la utilización de memoria es muy alta, el asignador de
memoria puede tardar en encontrar un área libre de memoria para cumplir con la petición de me-
moria. Un sistema operativo duro de tiempo real debe evitar tales situaciones. Por consiguiente
los sistemas de tiempo real duros particionan sus recursos (véase la sección 1.3.2) y los asignan
permanentemente a los procesos que compiten en la aplicación. Este enfoque reduce la carga
general de asignación y garantiza que la respuesta del kernel para una petición de recursos hecha
por un proceso sería independiente de la utilización del recurso por otros procesos en el sistema.
Los sistemas de tiempo real duros también evitan el uso de características cuyo desempeño no
puede preverse con precisión, por ejemplo la memoria virtual (véase el capítulo 6).
Un sistema operativo de tiempo real utiliza dos técnicas para asegurar la continuidad de
operación cuando las fallas ocurren: la tolerancia de falla y la degradación parcial. Un sistema
de cómputo tolerante con las fallas usa la redundancia de los recursos para asegurar que el siste-
ma se mantendrá funcionando aun si una falla ocurre; por ejemplo, puede tener dos discos aun
cuando la aplicación realmente necesita sólo uno. La degradación parcial es la capacidad de un
sistema para descender a un estado más bajo para un nivel reducido de servicio cuando una falla
ocurre y para volver a las operaciones normales cuando la falla es rectificada. El programador
puede asignarle prioridades altas a las funciones cruciales a fin de que se realicen en una manera
oportuna aun cuando el sistema opere en un modo degradado.

2.8 LOS SISTEMAS OPERATIVOS DISTRIBUIDOS

Un sistema de cómputo distribuido consta de varios sistemas de cómputo individuales conecta-


dos a través de una red. Así, muchos recursos de la misma clase, por ejemplo, muchas memorias,
CPU y dispositivos de E/S, existen en el sistema distribuido. Un sistema operativo distribuido
saca provecho de la multiplicidad de recursos y de la presencia de una red para proveer las venta-
jas de los recursos compartidos a través de las computadoras, la fiabilidad de operación, la acele-
ración de aplicaciones y la comunicación entre usuarios. Sin embargo, la posibilidad de fracasos
de la red o los fracasos de sistemas de cómputo individuales complica el funcionamiento del
sistema operativo y necesita el uso de técnicas especiales en su diseño. Los usuarios también
necesitan usar técnicas especiales para acceder a los recursos sobre la red. Analizamos estos
aspectos en la sección 2.8.1.

Tabla 2.15 Características de los sistemas operativos distribuidos

Característica Descripción/implicación
Recursos Mejora la utilización de los recursos a través de las fronteras de los sistemas de
compartidos cómputo individuales.
Fiabilidad Disponibilidad de recursos y servicios a pesar de las fallas.
Rapidez del Las partes de un cálculo pueden ejecutarse en diferentes sistemas de cómputo
cómputo para acelerar el cómputo.
Comunicación Suministra medios de comunicación entre entidades remotas.
Crecimiento por Pueden magnificarse las capacidades del sistema (por ejemplo, su poder de
incrementos procesamiento) a un costo proporcional a la naturaleza y tamaño de la mag-
nificación.

03 MAQ. CAP. 02(F0694).indd 73 8/10/07 12:53:57 AM


74 CAPÍTULO 2 Visión general de los sistemas operativos

La tabla 2.15 resume las ventajas de los sistemas operativos distribuidos. Los recursos com-
partidos han sido la motivación tradicional de los sistemas operativos distribuidos. La forma
más antigua de un sistema operativo distribuido fue un sistema operativo de red que permitió el
uso de recursos especializados del hardware y del software por usuarios geográficamente dis-
tantes. Los recursos compartidos continúan siendo un aspecto importante de sistemas operativos
distribuidos hoy, aunque la naturaleza de la distribución y el uso compartido de recursos ha
cambiado debido a los avances en la tecnología de los sistemas de redes. El uso compartido de
recursos es ahora igualmente significativo en una red de área local (LAN). Así, las computadoras
baratas y las estaciones de trabajo en una oficina o en un laboratorio pueden compartir algunos
recursos caros, como las impresoras láser.
Un aspecto de fiabilidad es la disponibilidad de un recurso a pesar de los fracasos en el sis-
tema. Un ambiente distribuido puede ofrecer disponibilidad magnificada de recursos a través
de la redundancia de recursos y de las trayectorias de comunicación. Por ejemplo, la disponibi-
lidad de un recurso del disco puede aumentarse localizando dos o más discos en sitios diferen-
tes en el sistema. Si un disco no está disponible debido a un fracaso, el proceso puede usar otro
disco. La disponibilidad de un recurso de datos, por ejemplo un archivo, puede magnificarse
de modo semejante al guardar copias del archivo en partes diversas del sistema.
La aceleración de computación implica obtener mejores tiempos de respuesta o tiempos
de reprocesamiento para una aplicación. Esto se logra dispersando los procesos de una apli-
cación entre computadoras diferentes en el sistema distribuido, a fin de que puedan ejecutarse
al mismo tiempo. Este arreglo es cualitativamente diferente de la operación traslapada de
procesos de una aplicación en un sistema operativo convencional (véase la sección 2.7).
Los usuarios de un sistema operativo distribuido tienen identificadores del usuario y con-
traseñas que son válidas a todo lo largo del sistema. Esta característica facilita mucho la comu-
nicación entre usuarios en dos formas. La primera, la comunicación a través de identificadores
del usuario invoca automáticamente los mecanismos de seguridad del sistema operativo y así
asegura la autenticidad de comunicación. En segundo lugar, los usuarios pueden tener movilidad
dentro del sistema distribuido y todavía pueden poder comunicarse con otros usuarios del siste-
ma convenientemente.

2.8.1 Las técnicas especiales de los sistemas


operativos distribuidos

Un sistema distribuido es más que una mera colección de computadoras conectadas en red: debe
integrarse el funcionamiento de las computadoras individuales para lograr la utilización efecti-
va de los servicios y los recursos en el sistema en la manera resumida en la tabla 2.15. Esto se
logra a través de la participación de todas las computadoras en las funciones de control del sis-
tema operativo. Consecuentemente, definimos un sistema distribuido como sigue:

Definición 2.10 (Sistema distribuido) Un sistema distribuido es un sistema consistente en


dos o más nodos, donde cada nodo es un sistema de cómputo con su propia memoria, algún
hardware de sistema de redes y capacidad de realizar algunas de las funciones de control de
un sistema operativo.

03 MAQ. CAP. 02(F0694).indd 74 8/10/07 12:53:57 AM


2.9 Los sistemas operativos modernos 75

Tabla 2.16 Conceptos clave y técnicas empleadas en un sistema operativo distribuido

Técnica Descripción
Control distribuido Se realiza una función de control a través de la participación de varios nodos,
posiblemente todos los nodos, en un sistema distribuido.
Transparencia Puede tenerse acceso a un recurso o un servicio sin tener que saber su
localización en el sistema distribuido.
Llamada al Un proceso llama a un procedimiento que se ubica en un sistema de cómputo
procedimiento diferente. La llamada al procedimiento es análoga a una llamada a un pro-
remoto (RPC) cedimiento o función en un lenguaje de planificación, excepto porque es el
sistema operativo el que pasa los parámetros al procedimiento remoto y de-
vuelve los resultados. La operación del proceso que hace la llamada se reanu-
da cuando se devuelven los resultados.

Las funciones de control realizadas por los sistemas de cómputo individuales contribuyen
a la utilización efectiva del sistema distribuido. La tabla 2.16 resume tres conceptos y técnicas
cruciales que se usan en un sistema operativo distribuido. El control distribuido es lo contra-
rio del control centralizado: significa que las funciones de control del sistema distribuido son
realizadas por varias computadoras en el sistema a la manera de la definición 2.10, en lugar de
ser realizadas por una computadora individual. El control distribuido es esencial para asegurar
que el fracaso de una computadora individual o de un grupo de computadoras no detenga la
operación del sistema entero. La transparencia de un recurso o servicio significa que un usuario
deberá poder acceder a ella sin tener que saber cuál nodo en el sistema distribuido lo contiene.
Esta característica le permite al sistema operativo cambiar la colocación de un recurso del soft-
ware o servicio para optimizar su uso por las computaciones. Por ejemplo, en un sistema que
suministra transparencia, un sistema de archivos distribuidos puede mover un archivo al nodo
que contiene una computación que use al archivo, de modo que se eliminen los retrasos involu-
crados en el acceso al archivo en la red. La llamada de procedimiento remoto (RPC) es usada por
una aplicación para ejecutar un procedimiento en otra computadora del sistema distribuido. El
procedimiento remoto puede realizar una parte de la computación en la aplicación o puede usar
un recurso localizado en esa computadora.

2.9 LOS SISTEMAS OPERATIVOS MODERNOS

Los usuarios se involucran en actividades diversas en un ambiente moderno de computación.


Por tanto, un sistema operativo moderno no puede usar una estrategia uniforme para todos
los procesos; debe usar una estrategia que sea apropiada para cada proceso individual. Por
ejemplo, un usuario puede abrir un manipulador del correo, editar algunos archivos, ejecutar
algunos programas y observar un video al mismo tiempo. Aquí, la ejecución de un programa
puede ser interactiva e involucrar una actividad en otro nodo de un sistema de cómputo distri-
buido, y la vigilancia de un video es una actividad de tiempo real suave, así es que el sistema
operativo debe usar la planificación round-robin para la ejecución del programa, debe usar la
planificación basada en prioridades para los procesos de la aplicación de video e implementar

03 MAQ. CAP. 02(F0694).indd 75 8/10/07 12:53:57 AM


76 CAPÍTULO 2 Visión general de los sistemas operativos

las llamadas de procedimiento remoto (RPC) para admitir las actividades en otro nodo. Así,
un sistema operativo moderno usa la mayoría de conceptos y de técnicas que estudiamos con
respecto al proceso por lotes, multiprogramación, tiempo compartido, tiempo real y sistemas
operativos distribuidos. La tabla 2.17 contiene un resumen de tales conceptos y técnicas.

Tabla 2.17 Uso de los conceptos clásicos de los sistemas operativos en los sistemas operativos modernos

Concepto Ejemplo típico del uso


Procesamiento por lotes Las actualizaciones y las consultas en la base de datos se procesan por
(sistema operativo para lotes para evitar el inicio de una base de datos para cada consulta o
procesamiento por lotes) actualización. El procesamiento por lotes también se usa rutinariamente
para cálculos científicos en las organizaciones de investigación y en los
laboratorios clínicos.
Planificación priorizante Usado por el kernel para suministrar un tratamiento preferencial a las
basada en prioridades aplicaciones de alta prioridad y para lograr un uso eficiente de los re-
(sistema operativo cursos, asignando una prioridad alta a los procesos interactivos y una
para multiprocesamiento) prioridad baja a los procesos no interactivos.
Intervalo de tiempo Usado por el kernel para evitar que un proceso monopolice el CPU.
(sistema operativo para Ayuda a suministrar buenos tiempos de respuesta.
tiempo compartido)
Intercambio Usado por el kernel para aumentar el número de procesos a los que se
(sistema operativo para puede dar servicio al mismo tiempo.
tiempo compartido)
Procesos múltiples en una Usado por una aplicación para acelerar su ejecución al reducir el tiempo
aplicación de expiración. Este enfoque es muy efectivo cuando la aplicación con-
(sistema operativo tiene actividades sustanciales del CPU y de E/S.
en tiempo real)
Recursos compartidos Se usa rutinariamente en un ambiente LAN para compartir los recursos
(sistema operativo centralizados, como las impresoras láser.
distribuido)

Un sistema operativo no puede destinar estrategias diferentes para distintos tipos de pro-
cesos, por lo que un sistema operativo moderno realmente usa una estrategia individual com-
pleja que adapta su funcionamiento a la satisfacción de cada proceso individual. Por ejemplo, la
estrategia de planificación puede basarse en prioridades; sin embargo, en lugar de asignarle una
prioridad fija a un proceso como en un sistema de multiprogramación, la estrategia de planifica-
ción podría considerar que el comportamiento reciente de un proceso decida su prioridad actual.
Así, un proceso de tiempo real obtendría una alta prioridad, todos los procesos interactivos ob-
tendrían una prioridad moderada y los procesos no interactivos obtendrían la prioridad mínima.
Así, la esencia de las estrategias usadas en los sistemas operativos modernos es la flexibilidad y
una habilidad para adaptar la estrategia a fin de satisfacer los requisitos de un proceso. Este en-
foque se refleja en el diseño de las estrategias del sistema operativo presentadas en los siguientes
capítulos.

03 MAQ. CAP. 02(F0694).indd 76 8/10/07 12:53:58 AM


Ejercicio 2 77

EJERCICIO 2
1. ¿Cuáles de las siguientes deberían ser instrucciones privilegiadas? Explique por qué.
a) Ponga al CPU en modo privilegiado
b) Cargue los registros acotados
c) Cargue un valor en un registro del CPU
d) Desenmascare algunas interrupciones
e) Termine a la fuerza la operación de E/S.
2. El CPU deberá estar en el modo privilegiado al ejecutar el código del kernel y en el modo de usuario
(es decir, el modo no privilegiado) al ejecutar un programa del usuario. Explique cómo se logra esto
durante la operación de un sistema operativo.
3. Justifique la siguiente declaración: “Debido a la presencia de la memoria caché, un programa requiere
más tiempo del CPU para ejecutarse en un sistema de multiprogramación o de tiempo compartido que
lo que requeriría si fuera a ejecutarse completamente solo, es decir, sin tener a ningún otro programa en
el sistema.”
4. Escriba una nota sobre el contenido de los diversos campos de un vector de interrupción.
5. ¿Qué es un estado del CPU? Explique cómo es útil la noción de estado del CPU para implementar la
multiprogramación.
Ocurre una interrupción cuando un programa está a punto de ejecutar una instrucción de “bifurca-
ción condicionada”. El control se devuelve al programa después de procesar la interrupción. Explique
cómo la ocurrencia de la interrupción no afecta la ejecución correcta de la instrucción de bifurcación.
6. El kernel de un sistema operativo camufla todas las interrupciones durante el procesamiento de la inte-
rrupción. Analice sus ventajas y sus desventajas.
7. Un sistema de cómputo organiza el área de información guardada en la PSW (palabra de estado del
procesador) como una pila. Inserta el contenido de la PSW (palabra de estado del procesador) hacia
la pila durante el paso 2 de la acción de interrupción (véase la figura 2.7). Explique las ventajas de la
pila para el procesamiento de la interrupción.
8. Cuando un programa hace una petición a través de una llamada de sistema, el kernel la suspende si la
petición no se satisface enseguida. Clasifique las llamadas de sistema de la tabla 2.4 en dos clases: las
que pueden conducir a la suspensión del programa que hace la llamada de sistema y las que no.
9. Un sistema operativo provee una llamada de sistema para pedir asignación de memoria. Un progra-
mador experimentado ofrece el siguiente consejo: “Si su programa contiene muchas peticiones de
memoria, usted puede apresurar la ejecución combinando todas estas peticiones en una sola llamada
de sistema.” Explique por qué esto es así.
10. Un trabajo contiene 5 tarjetas de datos en un paso del trabajo. Sin embargo, el programa de paso del
trabajo trata de leer 10 tarjetas. Explique claramente las acciones del procesador de comandos cuando
el programa trata de leer la sexta tarjeta y las subsiguientes.
11. Un sistema se denomina sobrecargado si su capacidad para realizar trabajo es más pequeña que el
trabajo que le llega; de otra manera, es un sistema subcargado. La siguiente política se propone para
mejorar el desempeño específico de un sistema de procesamiento por lotes: clasifique los trabajos en
trabajos pequeños y trabajos grandes dependiendo de sus requisitos de tiempo de CPU. Forme lotes
separados de trabajos cortos y largos. Ejecute un lote de trabajos largos sólo si no existen los trabajos
cortos.
¿Mejora esta política el desempeño específico de un sistema de proceso por lotes que es: a) sub-
cargado, b) sobrecargado?

03 MAQ. CAP. 02(F0694).indd 77 8/10/07 12:53:58 AM


78 CAPÍTULO 2 Visión general de los sistemas operativos

12. Estudie los archivos .bat de MS DOS y los Shells de Unix. Haga comentarios sobre sus méritos y sus
deméritos para el procesamiento por lotes.
13. Analice la operación del kernel de multiprogramación y enliste todas sus acciones que contribuyen a la
carga general del sistema operativo.
14. La semilla de un sistema de multiprogramación clasifica un programa como acotado por el CPU o por
la E/S y le asigna una prioridad apropiada. ¿Cuál sería la consecuencia de una clasificación equivocada
de programas para el desempeño específico y los tiempos de respuesta en un sistema de multiprograma-
ción? ¿Cuáles serían las consecuencias para el desempeño específico vs. el grado de multiprogramación
característico de la figura 2.18?
15. Cuando un programa de prioridad alta inicia una operación de E/S, un sistema de multiprograma-
ción conmuta a la ejecución de un programa de prioridad baja. Dé una explicación paso a paso
de cómo se logra esto. (Sugerencia: Un programa inicia una operación de E/S haciendo una llamada de
sistema.)
16. El CPU de un sistema de multiprogramación está ejecutando un programa de prioridad alta cuando
ocurre una interrupción que señaliza la terminación de una operación de E/S. Muestre todas las accio-
nes y todas las actividades en el sistema operativo siguientes a la interrupción si
a) La operación de E/S había sido iniciada por un programa de prioridad menor.
b) La operación de E/S había sido iniciada por un programa de prioridad mayor.
Ilustre cada caso con la ayuda de una gráfica de tiempo.
17. Dibuje una gráfica de tiempo para un sistema que contiene dos programas acotados por el CPU y dos
programas acotados por la E/S cuando a) los programas acotados por el CPU tienen una prioridad
mayor, b) los programas acotados por la E/S tienen una prioridad mayor.
18. Un programa consta de un ciclo individual que se ejecuta 50 veces. El ciclo contiene un cómputo que
consume 50 mseg de tiempo de procesador, seguido por una operación de E/S que dura 200 mseg.
Si el programa se ejecuta en un sistema operativo de multiprogramación cuya carga general es insigni-
ficante, prepare una gráfica de tiempo que muestre las actividades del CPU y de la E/S del programa y
compute el tiempo transcurrido en los siguientes casos:
a) El programa tiene la prioridad más alta en el sistema.
b) El programa está multiprogramado con otros n programas con características idénticas y tiene la
prioridad mínima. Considere los casos i) n  3, ii) n  4, y ii) n  5.
19. Se dice que un programa “progresa” si el CPU está ejecutando sus instrucciones o si su operación de E/S
está en curso. El coeficiente de progreso de un programa es la fracción de su vida útil en el sistema durante
el cual hace progreso. Calcule los coeficientes de progreso de los programas en el problema 18b).
20. Haga comentarios sobre la validez de la siguiente declaración:
“Un programa acotado por el CPU siempre tiene un coeficiente de progreso bajo en un sistema de
multiprogramación.”
21. Un sistema de multiprogramación usa un grado de multiprogramación (m) 1. Se propone duplicar
el desempeño específico del sistema por la adición/reemplazo de sus componentes de hardware. Haga
comentarios sobre las siguientes cuatro propuestas en este contexto.
a) Reemplace el CPU con una CPU de velocidad doble.
b) Expanda la memoria principal hasta dos veces su tamaño presente.
c) Reemplace el CPU por una CPU con una velocidad del doble y expanda la memoria principal a dos
veces su tamaño presente.

03 MAQ. CAP. 02(F0694).indd 78 8/10/07 12:53:58 AM


Ejercicio 2 79

22. Todos los programas en un sistema de multiprogramación son de naturaleza cíclica, con cada ciclo
conteniendo una ráfaga de actividad del CPU y una ráfaga de actividad de E/S. Sean b icpu y b iio las
ráfagas de CPU y de E/S del programa Pi. Los programas se nombran P1 . . . Pm, donde la m es el grado
de multiprogramación, tal que la prioridad del programa Pi la prioridad del programa Pil. Haga
comentarios sobre la validez de las siguientes declaraciones:
j
a) la ociosidad del CPU ocurre si b hio jh (bcpu) donde Ph es el programa prioritario más alto.
b) se garantiza que el programa Pm recibe el tiempo de procesador si para todo i  1 . . . m  1, b iio

i1 i j
(b i1
cpu  b io ) y b io ji1…m (b cpu).

23. Se dice que un programa muere de inanición si no recibe tiempo de procesador. ¿Cuál de las siguientes
condiciones implica la inanición del programa de prioridad más baja en un sistema de multiprograma-
ción? (Nota: La notación es idéntica a la del problema 22.)
a) Para algún programa Pi, b iio
ji1… m  1 (b cpu
j ).
i j )ybj j
b) Para algún programa Pi, b io
ji1… m  1 (b cpu cpu b io para toda j i.

24. Un sistema de tiempo compartido contiene n programas idénticos; cada uno ejecuta un bucle que con-
tiene un cómputo que requiere tp segundos de CPU y una operación de E/S que requiere tw segundos.
Dibuje una gráfica que bosqueje la variación del tiempo de respuesta con los valores del intervalo de
tiempo . (Sugerencia: Considere los casos para tp
, 
tp
2   y tp 2  .)
25. Dos personas que usan el mismo sistema de tiempo compartido al mismo tiempo observan que los
tiempos de respuesta para sus programas difieren ampliamente. ¿Cuáles son las razones posibles para
esta diferencia?
26. Haga comentarios sobre la validez de la siguiente declaración: la operación de un sistema de tiempo
compartido es idéntica a la operación de un sistema de multiprogramación que ejecuta los mismos
programas si  excede la ráfaga del CPU de cada programa.
27. a) ¿El intercambio mejora/degrada la eficiencia de utilización del sistema?
b) ¿Aumenta el intercambio el grado efectivo de multiprogramación?
c) ¿Puede usarse el intercambio en un sistema de multiprogramación?
Justifique claramente sus respuestas.
28. Un sistema de tiempo compartido usa el intercambio como la técnica fundamental de administración
de memoria. Use las siguientes listas para gobernar sus acciones: una lista de planificación, una lista de
intercambio para salida que contiene programas que salen, una lista de programas de intercambio que
van a salir y que contiene programas que van a salir por intercambio, y una lista de programas de inter-
cambio que van a entrar y que contiene programas que van a entrar por intercambio. Explique cuándo
y por qué el kernel de tiempo compartido deberá poner programas en las listas de intercambio para
entrar y salir.
29. Una aplicación en tiempo real requiere un tiempo de respuesta de 2 segundos. Analice la viabilidad de
destinar un sistema de tiempo compartido para la aplicación de tiempo real si el tiempo de respuesta
promedio en el sistema de tiempo compartido es: a) 20 segundos, b) 2 segundos o c) 0.2 segundos.
30. Un sistema de tiempo compartido procesa n programas. Usa un intervalo de tiempo de  segundos de
CPU y requiere tv segundos del CPU para conmutar entre los programas. Una aplicación de tiempo real
requiere tC segundos de tiempo de procesador, involucra operaciones de E/S que requieren tI segundos
y requiere que una respuesta se produzca en menos de tD segundos. ¿Cuál es el valor más grande de 
para el cual el sistema de tiempo compartido puede satisfacer los requisitos de respuesta de la aplica-
ción de tiempo real?

03 MAQ. CAP. 02(F0694).indd 79 8/10/07 12:53:58 AM


80 CAPÍTULO 2 Visión general de los sistemas operativos

31. En un sistema de multiprogramación a una actividad acotada por E/S se le da una prioridad más alta
que a las actividades que no están acotadas por E/S; sin embargo, en una aplicación de tiempo real a
una actividad acotada por E/S se le puede dar una prioridad más baja. ¿Por qué es esto así?
32. Un sistema operativo no puede cumplir el requisito de respuesta de una aplicación de tiempo real
si se ejecuta como un proceso individual. Explique con un ejemplo cómo la creación de procesos
múltiples puede ayudar a cumplir los requisitos de respuesta de la aplicación en el mismo sistema
operativo.
33. Un programa de aplicación está siendo desarrollado para un controlador de automóvil basado en un
microprocesador. La aplicación está obligada a realizar las siguientes funciones:
a) Revisar y exhibir la velocidad del automóvil
b) Revisar el nivel de combustible y activar una alarma si es necesario
c) Exhibir la eficiencia de combustible, es decir, millas/galón para la velocidad actual
d) Revisar la condición del motor y activar la alarma si surge una condición extraordinaria
e) Periódicamente registrar alguna información auxiliar, como la velocidad y el nivel de combustible
(es decir, implementar una “caja negra” como si fuera un avión de línea).
Conteste las siguientes preguntas relativas a la aplicación:
a) ¿Es esta una aplicación de tiempo real? Justifique su respuesta.
b) Se propone crear procesos múltiples para reducir el tiempo de respuesta de la aplicación. ¿Cuáles
son los procesos incluidos? ¿Cuáles deberían ser sus prioridades?
c) ¿Es necesario definir cualesquiera interrupciones específicas en la aplicación? Si es así, especifique
las interrupciones y sus prioridades.
34. Si dos eventos independientes e1 y e2 tienen una probabilidad de ocurrencia de pr1 y pr2, donde tanto
pr1 como pr2
1, la probabilidad de que ambos eventos ocurran simultáneamente es pr1  pr2. Un
sistema de cómputo que contenga dos CPU debe diseñarse de modo que la probabilidad de que ambos
CPU fallen es 1 en 10 000. ¿Cuál debería ser la probabilidad de fracaso de un CPU?
35. Para obtener mayor velocidad de cómputo en un sistema distribuido, se codifica una aplicación como
tres partes que pueden ejecutarse en tres sistemas de cómputo bajo el control de un sistema operativo
distribuido. Sin embargo, la aceleración obtenida es
3. Enliste todas las razones posibles para una
aceleración tan baja.

BIBLIOGRAFÍA
Smith (1982) y Handy (1998) describen las organizaciones de la memoria caché. Przybylski (1990) estudia
el diseño de las jerarquías de la memoria y de la memoria caché. La jerarquía de memoria y la organización
de E/S también se estudian en la mayoría de los libros sobre arquitectura y organización de computadora,
por ejemplo, Hayes (1988), Patterson y Hennessy (1998), Hennessy y Patterson (2002), Hamacher et al.
(2002), y Stallings (2003).
La mayoría de los libros sobre sistemas operativos estudian la interfaz de las llamadas al sistema.
Bach (1986) contiene una sinopsis útil de llamadas del sistema Unix. O’Gorman (2003) describe el proce-
samiento de las interrupciones en Linux. Beck et al. (2002), Bovet y Cesati (2003) y Love (2005) contienen
debates extensos acerca de las llamadas del sistema Linux. Mauro y McDougall (2001) describen las lla-
madas del sistema en Solaris, mientras Russinovich y Solomon (2005) lo hacen respecto a las llamadas del
sistema en Windows.

03 MAQ. CAP. 02(F0694).indd 80 8/10/07 12:53:59 AM


Bibliografía 81

Denning (1971) y Weizer (1981) son artículos de encuesta en sistemas operativos. Metzner (1982) y
Brumfield (1986) son bibliografías comprehensivas que cubren todos los aspectos de literatura sobre sis-
temas operativos. Varias bibliografías recientes sobre el sistema operativo están disponibles en el Internet.
Todos los textos sobre sistemas operativos cubren las clases diferentes de sistemas operativos descritos en
este capítulo; algunos recientes sobre sistemas operativos son Tanenbaum (2001), Stallings (2001), Nutt
(2004) y Silberschatz et al. (2005).
Otra literatura sobre el procesamiento por lotes, multiprogramación y sistemas de tiempo compartido
se remonta a la década de los setenta. Liu (2000) y Zhao (1989) son buenas fuentes para los sistemas de
tiempo real.
Tanenbaum y Renesse (1985) son un buen punto de partida para un estudio de los sistemas operativos
distribuidos. Analizan los aspectos principales del diseño de los sistemas operativos distribuidos y contiene
una encuesta acerca de algunos sistemas operativos distribuidos. Tanenbaum (2003) estudia los principios
del diseño de redes de computadoras. Fortier (1988) analiza los aspectos del diseño de los sistemas ope-
rativos distribuidos. Tanenbaum (1995) estudia algunos sistemas operativos distribuidos muy conocidos.
Singhal y Shivaratri (1994) estudian todas las facetas de los sistemas operativos distribuidos. Coulouris et
al. (2001) lo hacen con respecto a los conceptos y el diseño de los sistemas distribuidos.
Varios libros describen sistemas operativos modernos específicos. Bach (1986) y Vahalia (1996) lo
hacen en relación con el sistema operativo Unix. Beck et al. (2002) y Bovet y Cesati (2003) estudian el
sistema operativo Linux, mientras que Stevens y Rago (2005) describen los sistemas operativos Unix,
Linux y BSD. Mauro y McDougall (2001) analizan Solaris. Russinovich y Solomon (2005) describen los
sistemas operativos Windows.

1. Arden, B. y D. Boettner (1969): “Measurement and performance of a multiprogramming system”,


Second ACM Symposium on Operating System Principles.
2. Bard, Y. (1971): “Performance criteria and measurement for a time-sharing system”, IBM Systems
Journal, 10 (3), 193.
3. Bach, M.J. (1986): The Design of the Unix Operating System, Prentice-Hall, Englewood Cliffs.
4. Beck, M., H. Bohme, M. Dziadzka, U. Kunitz, R. Magnus, C. Schroter y D. Verwomer (2002):
Linux Kernel Programming, 3a. ed., Pearson Education.
5. Bic, L. y A.C. Shaw (1988): The Logical Design of Operating Systems, 2a. ed., Prentice-Hall,
Englewood Cliffs.
6. Bovet, D.P. y M. Cesati (2003): Understanding the LINUX Kernel, 2a. ed., O’Reilly, Sebastopol.
7. Brumfield, J.A. (1986): “A guide to operating systems literature”, Operating Systems Review, 20
(2), 38-42.
8. Bull, G.M. y S.F.G. Packham (1971): Time-Sharing Systems, McGraw-Hill, Londres.
9. Coulouris, G., J. Dollimore y T. Kindberg (2001): Distributed Systems—Concepts and Design, 3a.
ed., Addison- Wesley, Nueva York.
10. Crowley, C. (1997): Operating Systems—A Design Oriented Approach, McGraw-Hill, Nueva York.
11. Denning, P.J. (1971): “Third generation operating systems”, Computing Surveys, 4 (1), 175-216.
12. Fortier, P.J. (1988): Design of Distributed Operating Systems, McGraw-Hill, Nueva York.
13. Goscinski, A. (1991): Distributed Operating Systems—The Logical Design, Addison Wesley,
Nueva York.
14. Hamacher, C., Z. Vranesic y S. Zaky (2002): Computer Organization, 5a. ed., McGraw-Hill.
15. Hamlet, R.G. (1973): “Efficient multiprogramming resource allocation and accessing”, Commu-
nications of the ACM, 16 (6), 337-343.
16. Handy, J. (1998): The Cache Memory Book, 2a. ed., Academic Press.

03 MAQ. CAP. 02(F0694).indd 81 8/10/07 12:53:59 AM


82 CAPÍTULO 2 Visión general de los sistemas operativos

17. Hayes, J. (1988): Computer Architecture and Organization, 2a. ed., McGraw-Hill, Nueva York.
18. Hennessy, J. y D. Patterson (2002): Computer Architecture: A Quantitative Approach, 3a. ed.,
Morgan Kaufmann, San Mateo.
19. Liu, J.W.S. (2000): Real-Time systems, Pearson Education.
20. Love, R. (2005): Linux Kernel Development, 2a. ed., Novell Press.
21. Mauro, J. y R. McDougall (2001): Solaris Internals—Core Kernel Architecture, Prentice-Hall.
22. McQuillan, J.M. y D.C. Walden (1977): “The ARPA network design decisions”, Computer Net-
works, 1, 243-289.
23. Metzner, J.R. (1982): “Structuring operating systems literature for the graduate course”, Opera-
ting Systems Review, 16 (4), 10-25.
24. Nutt, G. (2004): Operating Systems—A Modern Perspective, 3a. ed., Addison-Wesley, Reading.
25. O’Gorman, J. (2003): Linux Process Manager: The internals of Scheduling, Interrupts and Sig-
nals, Wiley and Sons.
26. Patterson, D. y J. Hennessy (1998): Computer Organization and Design: The Hardware/Software
Interface, Morgan Kaufman, San Mateo.
27. Przybylski, A. (1990): Cache and Memory Hierarchy Design: A Performance-Directed Approach,
Morgan Kaufmann.
28. Rosin, R.F. (1969): “Supervisory and monitor systems”, Computing Surveys, 1 (1), 15-32.
29. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.
30. Silberschatz, A., P.B. Galvin y G. Gagne (2005): Operating System Principles, 7a. ed., John Wiley,
Nueva York.
31. Singhal, M. y N.G. Shivaratri (1994): Advanced Concepts in Operating Systems, McGraw-Hill,
Nueva York.
32. Sinha, P.K. (1997): Distributed Operating Systems, IEEE Press, Nueva York.
33. Smith, A.J. (1980): “Multiprogramming and memory contention”, Software-Practice and Expe-
rience, 10 (7), 531-552.
34. Smith, A J. (1982): “Cache memories”, ACM Computing Surveys, 14, 473-530.
35. Smith, L.B. (1967): “A comparison of batch processing and instant turnaround”, Communications
of the ACM, 10 (8).
36. Stallings, W. (2001): Operating Systems—Internals and Design Principles, 4a. ed., Pearson Edu-
cation, Nueva York.
37. Stallings, W. (2003): Computer Organization and Architecture, 6a. ed., Prentice Hall, Upper
Saddle River.
38. Stevens, W.R. y S.A. Rago (2005): Advanced Programming in the Unix Environment, 2a. ed.,
Addison Wesley Professional.
39. Tanenbaum, A.S. (2003): Computer Networks, 4a. ed., Prentice-Hall, Englewood Cliffs.
40. Tanenbaum, A.S. (2001): Modern Operating Systems, 2a. ed., Prentice-Hall, Englewood Cliffs.
41. Tanenbaum, A.S. y R. Van Renesse (1985): “Distributed Operating Systems”, Computing Surveys,
17 (1), 419-470.
42. Tanenbaum, A.S. (1995): Distributed Operating Systems, Prentice-Hall, Englewood Cliffs, N.J.
43. Vahalia, U. (1996): Unix Internals: The New Frontiers, Prentice Hall, Englewood Cliffs.
44. Watson, R.W. (1970): Time Sharing System Design Concepts, McGraw-Hill, Nueva York.

03 MAQ. CAP. 02(F0694).indd 82 8/10/07 12:53:59 AM


Bibliografía 83

45. Weizer, N. (1981): “A history of operating systems”, Datamation, enero, 119-126.


46. Wirth, N. (1969): “On multiprogramming, machine coding, and computer organization”, Commu-
nications of the ACM, 12 (9), 489-491.
47. Wilkes, M.V. (1968): Time Sharing Computer Systems, Macdonald, Londres.
48. Zhao, W. (1989): Special issue on real-time operating systems, Operating System Review, 23, 7.

03 MAQ. CAP. 02(F0694).indd 83 8/10/07 12:54:00 AM


Capítulo
3
Los procesos y los hilos

El concepto de proceso ayuda a explicar, entender y organizar la ejecución de programas en un


sistema operativo. Un proceso es una ejecución de un programa. El énfasis en “una” significa
que varios procesos pueden representar distintas ejecuciones del mismo programa. Esta situa-
ción surge cuando se inician varias ejecuciones de un programa, cada una con sus propios datos
y al mismo tiempo está en ejecución un programa que está codificado con técnicas concurrentes
de planificación.
Un programador usa los procesos para lograr la ejecución de los programas en una manera
secuencial o concurrente, como se desee. Un OS usa procesos para organizar la ejecución de
los programas. El uso del concepto de procesos le permite a un sistema operativo ejecutar los
programas tanto secuencial como concurrentemente con la misma facilidad.
Analizamos dos puntos de vista de los procesos en este capítulo: el del programador y el del
sistema operativo. Desde el punto de vista del programador, estudiamos cómo se crean los pro-
cesos concurrentes y cómo interactúan entre sí para alcanzar una meta común. Desde el punto de
vista del sistema operativo, analizamos cómo crea procesos un sistema operativo, cómo le sigue
la pista a los estados de proceso y de qué manera usa la información del estado de proceso para
organizar la ejecución de los programas.
Un hilo es una ejecución de un programa que usa el ambiente de un proceso, es decir, su có-
digo, sus datos y sus recursos. Si muchos hilos usan el ambiente del mismo proceso, comparten
estos elementos. Un OS aprovecha esta circunstancia para reducir la sobrecarga mientras que
conmuta entre tales hilos.

3.1 LOS PROCESOS Y LOS PROGRAMAS

Un programa es una entidad pasiva que no realiza ninguna acción por sí misma; tiene que ser
ejecutado para realizar las acciones especificadas en él. Como hemos indicado, un proceso es
una ejecución de un programa; realmente realiza las acciones especificadas en un programa. Un
sistema operativo considera los procesos como entidades para planificarse. De esta manera es
como se lleva a cabo la ejecución de programas del usuario.

04 MAQ. CAP. 03(F0694).indd 84 8/10/07 12:54:40 AM


3.1 Los procesos y los programas 85

Para entender lo que es un proceso, debatamos cómo ejecuta el sistema operativo un pro-
grama. El programa P mostrado en la figura 3.1a) contiene las declaraciones del archivo info y
una variable item, de la misma manera que las declaraciones que leen los valores de info
los usan para realizar algunos cálculos e imprimir un resultado antes de detenerse. Durante la
ejecución, las instrucciones de este programa usan valores en su área de datos y la pila a fin de
realizar los cálculos pretendidos. La figura 3.1b) muestra una vista abstracta de su ejecución.
Las instrucciones, los datos y la pila del programa P constituyen su espacio de dirección. Para
darse cuenta de la ejecución de P, el sistema operativo asigna la memoria con el fin de acomodar
el espacio de la dirección de P, destina una impresora para imprimir sus resultados, establece
un acomodamiento a través del cual P puede acceder al archivo info y programa a P para la
ejecución. El CPU se muestra como rectángulo con líneas punteadas porque no siempre ejecuta
las instrucciones de P; el sistema operativo comparte el CPU entre la ejecución de P y las ejecu-
ciones de otros programas.

Programa P
file info;
int item; Espacio de la
open (info, "read"); dirección de P
while not info
end-of-file(info) Instrucciones,
read (info, item); área de datos
y pila de P Impresora
CPU
print ;
stop;

a) b)

Figura 3.1 Un programa y una vista abstracta de su ejecución.

La tabla 3.1 muestra dos clases de relaciones que pueden existir entre los procesos y los
programas. Existe una relación uno a uno cuando está en curso una ejecución individual de
un programa secuencial. El programa consta de un programa principal y un conjunto de funcio-
nes. Durante su ejecución, el control fluye entre el programa principal y las funciones según la
lógica del primero. El sistema operativo no se da cuenta de la existencia de las funciones. Por
tanto, la ejecución del programa constituye un proceso individual. Existirá una relación muchos
a uno entre muchos procesos y tal programa si varias ejecuciones de éste están en curso al mismo
tiempo.

Tabla 3.1 Relaciones entre procesos y programas

Relación Ejemplos
Uno a uno Una ejecución individual de un programa secuencial
Muchos a uno Muchas ejecuciones simultáneas de un programa, ejecución
de un programa concurrente

04 MAQ. CAP. 03(F0694).indd 85 8/10/07 12:54:41 AM


86 CAPÍTULO 3 Los procesos y los hilos

La mayoría de los lenguajes de planificación contienen características para la planificación


concurrente. Durante la ejecución, un programa codificado que use estas características le in-
forma al OS acerca de sus partes que deben ejecutarse concurrentemente. El sistema operativo
considera cada una de estas ejecuciones como un proceso. Por tanto, los procesos establecen una
relación muchos a uno con el programa. Llamamos a tal programa concurrente. Los procesos
que en algún momento coexisten en el sistema se llaman procesos concurrentes. Éstos tienen
oportunidades para interactuar entre sí durante su ejecución.

Procesos hijo El sistema operativo inicia la ejecución de un programa creando un proceso


para él. Éste es designado el proceso principal para la ejecución, y puede crear otros proce-
sos, que se convierten en sus procesos hijo. Un proceso hijo a su vez puede crear otros procesos.
Todos éstos forman un árbol que tiene al proceso principal como su raíz. El ejemplo 3.1 ilustra
la creación de los procesos hijo.

Ejemplo 3.1 La aplicación del registro secuencial de datos de tiempo real de la sección 2.7 recibe
muestras de datos de un satélite a razón de 10 000 muestras por segundo y las almacena en un disco.
Suponemos que cada prueba que llega del satélite se pone en un registro especial de la computado-
ra. El proceso primario de la aplicación, que llamaremos el proceso data_logger, tiene que realizar
las siguientes tres funciones:

l. Copie la muestra del registro especial a la memoria.


2. Escriba la muestra en un archivo de discos.
3. Realice algunas operaciones de limpieza, por ejemplo, copie algunos archivos selecciona-
dos de las muestras entrantes en otro destinado al análisis estadístico.

El proceso primario crea tres procesos hijo, conduciendo al árbol de proceso mostrado en la fi-
gura 3.2a). Como se muestra en la figura 3.2b), copy_sample copia la muestra del registro a un
área de memoria nombrada buffer_ area que puede contener, por ejemplo, 50 muestras. disk_write
escribe una muestra de buffer_area en un archivo de disco. housekeeping realiza operaciones
de limpieza. La llegada de una muestra nueva se define como una interrupción en la aplicación y
se asocia a una rutina de interrupción definida por el programador con esta interrupción. El sistema
operativo ejecuta esta rutina cada vez que llega una muestra nueva y activa el copy_sample.
La ejecución de los tres procesos puede traslaparse como sigue: copy_sample puede copiar
una muestra en buffer_area, disk_write puede escribir una muestra previa en el disco y housekee-
ping puede copiar los campos de las muestras ya almacenadas en disco para el análisis estadístico.
Este arreglo provee un tiempo de respuesta más pequeño que el peor caso de la aplicación si estas
funciones fueran ejecutadas secuencialmente. Siempre que un buffer_area tiene algún espacio li-
bre, sólo tiene que completarse copy_sample antes de que llegue la siguiente muestra. Los otros
procesos pueden ejecutarse más tarde. Esta posibilidad se explota asignando la prioridad más alta
a copy_sample.

La tabla 3.2 describe tres ventajas de la creación de los procesos hijo: la aceleración de la
computación, una prioridad más alta de las funciones críticas y la protección del proceso pa-
dre contra un mal funcionamiento de los procesos hijo. La tercera ventaja necesita alguna ex-
plicación. Cuando un sistema de software tiene que invocar un programa en el que no se confió,
debe protegerse a sí mismo en contra de los errores en el programa. Puede lograr esto creando
un proceso hijo para ejecutar el programa. Si surge un error durante su ejecución, el sistema ope-
rativo abortará el proceso hijo. Así, el proceso padre no será afectado por el error. El procesador
de comandos del sistema operativo aprovecha esta característica y crea un nuevo proceso para

04 MAQ. CAP. 03(F0694).indd 86 8/10/07 12:54:41 AM


3.2 El punto de vista del programador sobre los procesos 87

registro

copy
sample
buffer area
disk
data logger write

house-
keeping
copy sample disk write housekeeping

a) b)

Figura 3.2 Aplicación de tiempo real de la sección 2.7: a) árbol del proceso, b) procesos.

Tabla 3.2 Ventajas de los procesos hijo

Ventaja Explicación
Aceleración del La creación de procesos múltiples en una aplicación suministra las tareas
cómputo múltiples. Sus beneficios son similares a los de la multiprogramación; ca-
pacita al sistema operativo para interpaginar la ejecución de los procesos
acotados por la E/S y por el CPU en una aplicación, suministrando con ello
la aceleración del cómputo.
Prioridad de A un proceso hijo creado para ejecutar una función crítica en una aplica-
las funciones críticas ción se le puede asignar una prioridad más alta que a otras funciones. Estas
asignaciones de prioridad pueden ayudar al sistema operativo a cumplir los
requerimientos de tiempo real de una aplicación.
Protección del proceso El sistema operativo cancela un proceso hijo si surge un error durante su
padre contra errores ejecución. Esta acción no afecta al proceso padre.

ejecutar un programa del usuario. De esta manera, el procesador de comandos no experimenta


ningún daño aun si el programa funciona mal.

3.2 EL PUNTO DE VISTA DEL PROGRAMADOR


SOBRE LOS PROCESOS
Desde el punto de vista del programador, los procesos son un camino para lograr la ejecución
concurrente de un programa. El proceso principal de un programa concurrente crea procesos
hijo. Deberá asignarles las prioridades apropiadas para alcanzar la aceleración del cómputo o
para ejecutar algunas funciones en una prioridad alta, si así se desea (véase la sección 3.1). El

04 MAQ. CAP. 03(F0694).indd 87 8/10/07 12:54:41 AM


88 CAPÍTULO 3 Los procesos y los hilos

proceso principal y los procesos hijo también tienen que interactuar para lograr su meta común.
Esta interacción puede involucrar cambio de datos o requerir que los procesos coordinen sus
actividades entre sí.
Consecuentemente, un sistema operativo provee las siguientes cuatro operaciones para im-
plementar la visión de los procesos del programador:

1. Creación de los procesos hijo y asignación de prioridades.


2. Terminación de los procesos hijo.
3. Determinación del estatus de los procesos hijo.
4. El uso compartido, la comunicación y la sincronización entre los procesos.

Analizamos las primeras tres operaciones aquí con la ayuda de un ejemplo. El uso compartido, la
comunicación y la sincronización entre los procesos se estudian en la sección 3.2.1.
Ilustramos las características de los procesos con la ayuda de la aplicación en tiempo real
analizada en el ejemplo 3.1. La figura 3.3 da un pseudocódigo más bien simplista de la aplica-
ción escrita para un sistema operativo hipotético. El código usa las siguientes tres llamadas de
sistema:

create_ process : Crea un nuevo proceso, y le asigna una prioridad y un


identificador único llamado su id de proceso. Le devuel-
ve el id de proceso a la persona que llama.
status : Comprueba el estatus de un proceso y devuelve un códi-
go terminado o vivo.
terminate : Termina el proceso hijo especificado o se termina a sí
mismo si no se especifica ningún proceso.

create_process adopta dos parámetros: un nombre de procedimiento y un valor entero. El


procedimiento se convierte en el componente de código del nuevo proceso y la dirección
del procedimiento se anota como la dirección componente de la siguiente instrucción para
ejecutarse durante el proceso. La prioridad del nuevo proceso se obtiene añadiéndole el valor
entero a la prioridad del proceso padre. Se supone que un mayor valor numérico representa
una prioridad más alta de planificación. La llamada devuelve el id de proceso único asignado
al nuevo proceso.
El proceso principal, del cual se supone que tiene por nombre main, empieza creando tres
procesos para las tres funciones en la aplicación y almacena sus id en las cadenas copy_sam-
ple, disk_write y housekeeping. De acuerdo con el debate expuesto en la sección 2.7,
la prioridad más alta se asigna al proceso que mueve las muestras a la memoria temporal. El
proceso que escribe muestras en el disco tiene la siguiente prioridad más alta y el que realiza
análisis estadísticos tiene la prioridad más baja. Otras características del código se describen en
la siguiente sección.
El programa de la figura 3.3 tiene un punto débil. El proceso principal gasta su tiempo en un
lazo donde usa la llamada de estatus para comprobar si todos los procesos hijo han terminado
y se termina cuando esto ocurre. Esto es derrochador. En la sección 3.5.1 analizamos las carac-
terísticas que evitan este tipo de lazos. El programa tampoco especifica cuándo deberán terminar
los procesos hijo.

04 MAQ. CAP. 03(F0694).indd 88 8/10/07 12:54:42 AM


3.2 El punto de vista del programador sobre los procesos 89

begin
size : integer value (..);
buffer: array[1..size] of ...;
copy sample, disk write, housekeeping : string;
no of samples : integer;
/* Crear los procesos */
copy sample := create process(move to buffer(), 3);
disk write := create process(write to disk(), 2);
housekeeping := create process(analysis(), 1);
/* Mandar información del tamaño a copy sample y disk write */
send (copy sample, size);
send (disk write, size);
/* Verificar el estatus de todos los procesos */
over := false;
while (over = false)
if status(copy sample) = terminated and status(disk write) =
terminated and status(housekeeping) = terminated then
over := true;
terminate();
end;

procedure move to buffer();


buf size : integer;
/* Manipulador de la señal para cambiar el buf_size */
receive (main, buf size);
/* Repetir hasta su terminación: encontrar una entrada vacía en la memoria temporal, copiar una muestra */
/* en ella, e informar a write_to_disk que la entrada está ocupada */
...
terminate();
end;

procedure write to disk();


buf size : integer;
/* Manipulador de señal para cambiar buf size */
receive (main, buf size);
/* Repetir hasta su terminación: encontrar una entrada ocupada en la memoria temporal, copiar una muestra */
/* desde ahí en el disco, e informar a nive_to_disk que la entrada está ocupada */
...
terminate();
end;

procedure analysis();
/* Ejecutar el análisis estadístico y la limpieza */
...
terminate();
end;

Figura 3.3 Pseudocódigo para una aplicación en tiempo real.

04 MAQ. CAP. 03(F0694).indd 89 8/10/07 12:54:42 AM


90 CAPÍTULO 3 Los procesos y los hilos

3.2.1 El uso compartido, la comunicación y la sincronización


entre los procesos
Los procesos de una aplicación necesitan interactuar entre sí porque trabajan dirigidos hacia
una meta común. La tabla 3.3 describe cuatro clases de interacción de proceso. Resumimos sus
características importantes en lo siguiente.

Tabla 3.3 Cuatro tipos de interacción de procesos

Interacción Descripción
Datos compartidos Los datos compartidos pueden hacerse inconsistentes si varios procesos actuali-
zan los datos al mismo tiempo. Así, los procesos deben interactuar para decidir
cuándo es seguro que un proceso tenga acceso a los datos compartidos.
Paso de mensajes Los procesos intercambian información al mandarse mensajes entre sí.
Sincronización Para satisfacer una meta en común, los procesos deben coordinar sus actividades
y realizar sus acciones en un orden deseado.
Señales Se usa una señal para transmitir la ocurrencia de una situación excepcional a un
proceso.

Los datos compartidos Como se analiza posteriormente, en la sección 3.6.1, una variable
compartida puede adoptar valores inconsistentes si muchos procesos la actualizan concurrente-
mente. Para evitar este problema, un acceso de datos en un proceso tendrá que ser demorado si
otro proceso tiene acceso a los datos. Así, los datos compartidos por los procesos concurrentes
tienen un costo.

El paso de mensajes Un proceso puede poner alguna información en un mensaje y enviarla


a otro proceso. Éste puede copiar la información del mensaje en sus propias estructuras de datos.
Tanto el proceso remitente como el receptor deben anticipar el intercambio de información, es
decir, un proceso debe saber cuándo se espera que envíe o reciba un mensaje, por lo que el cam-
bio de información pasa a formar parte de la convención o protocolo entre los procesos.

La sincronización Si una acción ai debe realizarse sólo después de una acción aj, al pro-
ceso que desea realizar la acción ai se le obliga a esperar a que algún otro proceso realice aj. Un
sistema operativo provee facilidades para comprobar si otro proceso ha realizado una acción
específica.

Las señales Una señal se usa para comunicarle una situación excepcional a un proceso a
fin de que pueda realizar algunas acciones especiales para manejar la situación. El código que
el proceso desea ejecutar al recibir una señal se llama manipulador de la señal. El mecanismo
de la señal se modela a lo largo de las líneas de interrupciones. Así, cuando una señal se envía a
un proceso, el sistema operativo interrumpe la ejecución de éste y ejecuta un manipulador de la
señal especificado por el proceso. Los sistemas operativos difieren en la manera en que manipu-
lan las señales pendientes y la reanudación de los procesos después de ejecutar un manipulador
de la señal.

04 MAQ. CAP. 03(F0694).indd 90 8/10/07 12:54:42 AM


3.2 El punto de vista del programador sobre los procesos 91

Los detalles del uso compartido, la comunicación y la sincronización entre los procesos se
estudian en la sección 3.6. El ejemplo 3.2 ilustra las interacciones entre los procesos en la apli-
cación de tiempo real de la figura 3.3.

Ejemplo 3.2 En la aplicación de tiempo real de la figura 3.3, la variable no_of_samples es com-
partida por el proceso que mueve las muestras a la memoria temporal y con el proceso que las
escribe en el disco. El valor de no_of_samples indica cuántas muestras existen en la memo-
ria temporal. Ambos procesos necesitan actualizar el no_of_samples, por lo que su consistencia
deberá ser protegida atrasando un acceso al no_of_samples si otro proceso accede a él. Estos
procesos también necesitan sincronizar sus actividades de modo que una nueva muestra se mueva
en una entrada de la memoria temporal sólo después de que la muestra previa contenida ahí se es-
criba en el disco, y el contenido de una entrada de la memoria temporal se escriba en el disco sólo
después de que una nueva muestra se mueva en él.
Estos procesos también necesitan conocer el tamaño de la memoria temporal, es decir, el nú-
mero de muestras que pueden sujetar. Al igual que el no_of_samples, el tamaño podrá utilizarse
como datos compartidos. Sin embargo, esto causará retrasos al acceder a su valor. Este retraso
no se justifica porque el tamaño de la memoria temporal no se actualiza con regularidad; cambia
sólo en situaciones excepcionales. Por tanto, estos procesos se codifican a fin de usar el elemento
local de dato buf_size para indicar el tamaño de la memoria temporal. Su valor es enviado a
ellos por el proceso principal a través de mensajes. El proceso principal manda señales a estos
procesos si el tamaño de la memoria principal tiene que variarse.

3.2.2 La concurrencia y el paralelismo

El paralelismo es la cualidad de suceder al mismo tiempo. Dos eventos son paralelos si ocurren
simultáneamente, y dos tareas son paralelas si son realizadas al mismo tiempo. La concurren-
cia es una ilusión de paralelismo. Así, dos tareas son concurrentes si hay una ilusión de que se
realizan en paralelo, mientras que en la realidad sólo una de ellas puede realizare en cualquier
momento.
En un sistema operativo, la concurrencia se obtiene interpaginando la operación de procesos
en el CPU, lo cual crea la ilusión de que estos procesos están operando al mismo tiempo. El pa-
ralelismo se obtiene usando CPU múltiples, como en el sistema del multiprocesador, y operando
procesos diferentes en estos CPU.
¿Cómo provee la simple concurrencia algún beneficio? Hemos visto varios ejemplos de esto
anteriormente, en el capítulo 2. En la sección 2.5 analizamos cómo la producción específica de
un sistema operativo de multiprogramación aumenta al interpaginar la operación de los procesos
en un CPU, porque una operación de E/S en un proceso se traslapa con una actividad compu-
tacional en otro proceso. En la sección 2.6 vimos cómo la operación de interpaginado de los pro-
cesos creada por los diferentes usuarios en un sistema de tiempo compartido hace pensar a cada
usuario que él tiene una computadora para sí mismo, aunque es más lenta que la computadora
verdadera que se está usando. En el ejemplo 3.1 vimos que un cómputo puede terminarse con
más rapidez, es decir, con un tiempo transcurrido más pequeño, debido a la interpaginación de
procesos. Llamamos a esta propiedad la aceleración de computación.
El paralelismo puede proveer mejor producción específica en una forma obvia porque los
procesos pueden operar en CPU múltiples. También puede proveer una aceleración del cómpu-
to; sin embargo, la que se provee es cualitativamente diferente de la suministrada a través de la

04 MAQ. CAP. 03(F0694).indd 91 8/10/07 12:54:42 AM


92 CAPÍTULO 3 Los procesos y los hilos

concurrencia: cuando se utiliza la concurrencia, la aceleración se obtiene al traslapar las activi-


dades de E/S de un proceso con las actividades del CPU de otros procesos, mientras que cuando
se utiliza el paralelismo, las actividades del CPU y de E/S en un proceso pueden traslaparse con
el CPU y las actividades de E/S de otros procesos.
Cuando los procesos se utilizan como modelo de ejecución de programas, la concurrencia y
el paralelismo dependen de que haya suficiente trabajo para que el sistema operativo lo realice.
En la sección 3.4 introducimos un modelo alternativo de ejecución de programas, llamado hi-
los, donde la concurrencia y el paralelismo dependen no sólo de la disponibilidad de suficiente
cantidad de trabajo para realizar, sino también del modelo de hilos implementado en el sistema
operativo.

3.3 LA VISIÓN DEL SISTEMA OPERATIVO DE LOS PROCESOS

De acuerdo con la visión del sistema operativo, un proceso es la ejecución de un programa. Para
darse cuenta de esta visión, el sistema operativo crea procesos, los planifica para el uso del CPU
y los termina. Como se analizó anteriormente, en las secciones 2.5.3.1 y 2.6.2, para realizar la
planificación, un sistema operativo debe saber cuáles procesos requiere el CPU en cualquier
momento. Entonces, la clave para contemplar la visión del sistema operativo de los procesos
es rastrear todos éstos y saber lo que cada proceso está haciendo en cualquier momento: ya
sea ejecutando en el CPU, en espera de que le sea asignado éste; en espera de que se termine
una operación de E/S o en espera de ser intercambiado en la memoria. El sistema operativo
usa la noción de estado del proceso para rastrear lo que un proceso está haciendo en cualquier
momento.
En esta sección analizaremos la noción de estado de proceso, los estados diferentes de un
proceso y los arreglos usados por el sistema operativo para mantener información acerca del
estado de un proceso. No estudiamos la planificación en este capítulo; se analiza más tarde, en
el capítulo 4.

3.3.1 Antecedente: la ejecución de programas


Cuando se planifica un proceso, es decir, la ejecución de un programa, el CPU ejecuta instruc-
ciones en el programa. Cuando el CPU debe conmutarse a otros procesos, el kernel guarda el
estado del CPU. Este estado se descarga nuevamente en el CPU cuando el proceso se programa
otra vez. Tal visión conduce a la siguiente definición de un proceso.

Definición 3.1 (Proceso) Un proceso está compuesto por seis componentes:


(id, código, datos, recursos, pila, estado del CPU )
donde el id es un nombre/cédula de identidad único asignado a la ejecución de programa,
el código es el código de programa,
los datos son los datos y los archivos usados en la ejecución del programa,
los recursos es el conjunto de recursos asignados por el sistema operativo,
la pila contiene los parámetros de funciones y los procedimientos designados, así
como sus direcciones de retorno,
el estado del CPU está compuesto por el contenido de los campos de la PSW (pala-
bra de estado del procesador) y los registros del CPU.

04 MAQ. CAP. 03(F0694).indd 92 8/10/07 12:54:43 AM


3.3 La visión del sistema operativo de los procesos 93

Como se describe en la sección 2.1.1, el estado del CPU contiene información, como la
dirección de la instrucción para ser ejecutada enseguida, el código de condición, que también
se denomina banderas, y el contenido de los registros del CPU. El estado del CPU cambia a
medida que prosigue la ejecución del programa. El código, los datos y la pila del proceso cons-
tituyen el espacio de la dirección.

3.3.2 Cómo controlar los procesos

Un proceso es una ejecución de programa. Por tanto, de acuerdo con la definición 3.1, un
proceso tiene los cinco componentes de proceso: id, código, datos, pila y estado del CPU.
El proceso usa el CPU cuando es planificado. También usa otros recursos. Éstos incluyen los
recursos del sistema, como la memoria, y los recursos creados por el usuario, como los archi-
vos. El sistema operativo tiene que mantener información acerca de todas estas características
de un proceso.
La visión del sistema operativo de un proceso consta de dos partes:

• El código y las áreas de datos del proceso, incluidos su pila y los recursos asignados.
• La información relativa a la ejecución de un programa.

La figura 3.4 muestra el arreglo usado para controlar un proceso. Consta de un ambiente
de proceso y del bloque de control de proceso (PCB). El id de un proceso se usa para tener
acceso a su ambiente de proceso y al PCB. Este arreglo permite que los diferentes módulos
del sistema operativo tengan acceso conveniente y eficazmente a los datos relacionados con
el proceso.

info de la info del apuntadores


memoria recurso del archivo
id del proceso
estado del proceso
valores del registro
código datos pila valor de PC

Ambiente del proceso Bloque de control de


procesos (PCB)

Figura 3.4 Visión del sistema operativo de un proceso.

El ambiente de proceso También designado el contexto de proceso, el ambiente de proce-


so contiene el espacio de la dirección de un proceso, es decir, su código, sus datos y la pila, así
como toda la información necesaria para acceder y controlar los recursos que se le han asignado.
El sistema operativo crea un ambiente de proceso asignándole memoria al proceso, cargando el
código de proceso en la memoria asignada y estableciendo su espacio de datos. El sistema

04 MAQ. CAP. 03(F0694).indd 93 8/10/07 12:54:43 AM


94 CAPÍTULO 3 Los procesos y los hilos

operativo también alimenta información relativa al acceso a los recursos asignados al proceso y
su interacción con otros procesos y con el sistema operativo.
La tabla 3.4 describe las componentes del ambiente de proceso. Su contenido cambia du-
rante la ejecución de un proceso debido a acciones como la apertura y cierre de archivos, y la
creación y destrucción dinámicas de los datos por el proceso.

Tabla 3.4 Componentes del ambiente de proceso

Ambiente del proceso


El ambiente del proceso del código y de los datos del proceso y de toda la información necesaria para
la operación del proceso.
Componente Descripción
Códigos y datos Código del programa —incluidos sus funciones y sus procedimientos— y
sus datos, incluida la pila.
Información de Información relativa a las áreas de memoria asignadas al proceso. Esta
la asignación información se usa para implementar los accesos a la memoria hechos
de memoria por el proceso.
Estado de las actividades Los apuntadores a los archivos abiertos por el proceso y las posiciones
del procesamiento de presentes en los archivos.
archivos
Información Toda la información necesaria para controlar las interacciones del proceso
de interacción del con otros procesos, por ejemplo, los mensajes de interprocesos, los mani-
proceso puladores de las señales, los id de los procesos padre y los procesos hijo.
Información de los Información relativa a los recursos asignados a un proceso.
recursos
Información diversa Información diversa necesaria para la interacción de un proceso con el
sistema operativo.

El bloque de control de proceso (PCB) El bloque de control de proceso es una estruc-


tura de datos del kernel que contiene información relativa al primero y quinto componentes de
la definición 3.1, es decir, el id de proceso y el estado del CPU. Los detalles del PCB se describen
en la sección 3.3.4.
El kernel usa tres funciones fundamentales para controlar los procesos:
1. La planificación: Seleccionar el proceso que debe ejecutarse enseguida en el CPU.
2. El despacho: Establecer la ejecución del proceso seleccionado en el CPU.
3. El contexto de salvar: Guardar la información relativa a un proceso en curso cuando su
ejecución se suspende.
La función de planificación selecciona un proceso basado en la política de planificación
vigente. El despacho incluye establecer el ambiente del proceso seleccionado y la carga de in-
formación en el CPU, de modo que éste empieza (o resume) la ejecución de instrucciones en el
código de proceso. La función del contexto salvar realiza la limpieza cada vez que un proceso
libera el CPU o se prioriza. Guarda información relativa al estado del CPU y al ambiente del
proceso a fin de que la ejecución del proceso pueda reanudarse en algún momento futuro. De
hecho, el contexto de salvar es el inverso de la función de despacho.

04 MAQ. CAP. 03(F0694).indd 94 8/10/07 12:54:43 AM


3.3 La visión del sistema operativo de los procesos 95

Evento

Contexto de salvar

Manipulación de eventos

Planificación

Despacho

Figura 3.5 Funciones fundamentales para los procesos de control.

El esquema de la figura 3.5 ilustra el uso de estas funciones por el kernel cuando sucede un
evento. La ocurrencia de un evento invoca la función del contexto de salvar y una rutina apro-
piada del procesamiento de los eventos. Las acciones del procesamiento de los eventos pueden
activar algunos procesos; por tanto, se invoca la función de planificación para seleccionar un
proceso y la de despacho transfiere el control al proceso seleccionado.

3.3.3 Los estados y las transiciones del proceso

Se introduce la noción de estado de proceso para simplificar el control de los procesos por el
sistema operativo.

Definición 3.2 (Estado de proceso) El estado de proceso es un indicador de la naturaleza


de la actividad actual en un proceso.

La tabla 3.5 describe cuatro estados fundamentales de proceso. Un proceso está en el esta-
do bloqueado si ha hecho una petición del recurso al kernel y ésta todavía no se concede, o si
desea esperar a que ocurra algún evento. El proceso entra en el estado listo cuando se concede
la petición o el evento ocurre, y en el estado en ejecución cuando es despachado. El proceso entra
en el estado terminado cuando su ejecución se termina o cuando el sistema operativo la termina
por alguna razón.
Un sistema de cómputo convencional contiene un CPU, de modo que cuando mucho un
proceso puede estar en el estado en ejecución. Sin embargo, puede existir cualquier número
de procesos en los estados bloqueado, listo y terminado. Un sistema operativo puede definir más
estados de proceso para simplificar su propio funcionamiento o para admitir funcionalidades
adicionales, como hacer un intercambio.

Las transiciones del estado de proceso Una transición de estado para un proceso Pi es
un cambio en su estado, y se debe a la ocurrencia de algún evento en el sistema. Cuando un
proceso Pi que está en el estado de ejecución hace una petición de E/S, tiene que entrar en el
estado bloqueado hasta que se termine su operación de E/S. Al final de la operación de E/S, el es-
tado de Pi cambia de bloqueado a listo. Ocurren cambios similares de estado cuando un proceso

04 MAQ. CAP. 03(F0694).indd 95 8/10/07 12:54:44 AM


96 CAPÍTULO 3 Los procesos y los hilos

Tabla 3.5 Estados de procesos fundamentales

Estado Descripción
en ejecución En ese momento el CPU está ejecutando instrucciones en el código del proceso.
bloqueado El proceso tiene que esperar hasta que se conceda una petición de recurso formulada
por aquél, o hasta que ocurra un evento específico. No debe asignársele un CPU hasta
que su espera esté terminada.
listo El proceso desea usar el CPU para continuar su operación; sin embargo, no ha sido
planificado.
terminado La operación del proceso, es decir, la ejecución del programa representado por aquél,
se ha terminado normalmente, o el sistema operativo la ha abortado.

hace una cierta petición que el sistema operativo no puede satisfacer inmediatamente. El es-
tado de proceso cambia a bloqueado cuando la petición está hecha, es decir, cuando ocurre el
evento de petición, y a listo cuando la petición se satisface. Un proceso listo se cambia a en
ejecución cuando se le asigna el CPU. Un proceso en ejecución se convierte en listo cuando se
prioriza porque está listo un proceso de prioridad más alta o porque expira su intervalo de tiempo
(vea las secciones 2.5.3.1 y 2.6).
La figura 3.6 muestra las transiciones de estado fundamentales para un proceso. La tabla
3.6 resume las causas de las transiciones de estado. Un nuevo proceso se pone en el estado listo
después de que todos los recursos requeridos por éste han sido asignados. Puede entrar en los
estados en ejecución, bloqueado y listo varias veces debido a los eventos descritos en la tabla
3.6. Finalmente entra en el estado terminado.

En terminación
ejecución Terminado
petición de
despacho recurso o
de espera
priorización

proceso
nuevo Listo Bloqueado
recurso concedido
o espera terminada

Figura 3.6 Transiciones de estado fundamentales para un proceso.

Ejemplo 3.3 Considere el sistema de tiempo compartido del ejemplo 2.12, el cual usa un intervalo
de tiempo de 10 mseg. Contiene dos programas P1 y P2. P1 tiene una ráfaga de CPU de 15 mseg
seguida por una operación de E/S que dura 100 mseg, mientras que P2 tiene una ráfaga de CPU de
30 mseg seguida por una operación de E/S que dura 60 mseg. La ejecución de P1 y P2 se describió
en la figura 2.21 y en la tabla 2.13. Por simplicidad, suponemos que los procesos creados para
ejecutar los programas P1 y P2 son llamados por ellos mismos P1 y P2 respectivamente. La ejecu-

04 MAQ. CAP. 03(F0694).indd 96 8/10/07 12:54:44 AM


3.3 La visión del sistema operativo de los procesos 97

Tabla 3.6 Causas de las transiciones de estado fundamentales de un proceso

Transición de estado Descripción


listo → en ejecución El proceso se despacha. El CPU inicia o reanuda la ejecución de sus
instrucciones.
bloqueado → listo Se satisface una petición hecha por el proceso u ocurre un evento que
estaba esperándose.
en ejecución → listo El proceso se prioriza porque el sistema operativo decide planificar otro
proceso. Esta transición ocurre porque un proceso de prioridad más alta
queda listo o porque expira el intervalo de tiempo del proceso.
en ejecución → bloqueado El programa que está siendo ejecutado hace una llamada al sistema para
indicar que desea esperar hasta que se satisfaga alguna otra petición de
recurso hecha por aquél o hasta que ocurra un evento específico en el
<<
sistema. Las cinco causas principales de bloqueo son:

• El proceso solicita una operación de E/S.


• El proceso solicita memoria o cualquier otro recurso.
• El proceso desea esperar durante un intervalo específico de tiempo.
• El proceso espera el mensaje de otro proceso.
• El proceso desea esperar alguna otra acción de otro proceso.

en ejecución → terminado La ejecución del programa se completa o se termina. Las siguientes son
cinco razones principales para la terminación del proceso:
• Autoterminación: El programa que está siendo ejecutado termina su
tarea o descubre que no puede ejecutarse en forma significativa y hace
una llamada de “termíname” al sistema. Ejemplos de esta última con-
dición son datos incorrectos o inconsistentes, y la incapacidad de tener
acceso a los datos de la manera deseada, por ejemplo, privilegios de ac-
ceso al archivo que son incorrectos.
• Terminación por un padre: Un proceso hace una llamada de “termina
Pi” al sistema para terminar el proceso hijo Pi, cuando encuentra que ya
no es necesaria o significativa la ejecución del proceso hijo. (El mismo
efecto puede lograrse por el padre que manda una señal de “termina
ahora” al proceso hijo y el proceso que hace una llamada de “termína-
me” al sistema).
• Utilización excesiva de recursos: Un sistema operativo puede limitar
los recursos que un proceso puede consumir. Un proceso que sobrepase
un límite de recursos será terminado por el kernel.
• Condiciones anormales durante la ejecución: El kernel cancela un
proceso si surge una condición anormal en el programa que se está eje-
cutando, por ejemplo, la ejecución de una instrucción inválida, la
ejecución de una instrucción privilegiada, condiciones aritméticas como
el desbordamiento, la violación de la protección de la memoria, etcétera.
• La interacción incorrecta con otros procesos: El kernel puede can-
celar un proceso por la interacción incorrecta con otros procesos, por
ejemplo, si un proceso interviene en un bloqueo mutuo.

04 MAQ. CAP. 03(F0694).indd 97 8/10/07 12:54:44 AM


98 CAPÍTULO 3 Los procesos y los hilos

ción real de los programas procede como sigue: la tabla 3.7 ilustra las transiciones de estado en el
sistema. La operación de sistema comienza con ambos procesos en el estado listo en el instante 0.
El programador selecciona el proceso P1 para la ejecución y cambia su estado a en ejecución. A los
10 mseg, P1 es priorizado y P2 se programa, por lo que el estado de P1 se cambia a listo y el estado
de P2 se cambia a en ejecución. P1 se bloquea a los 25 mseg debido a una operación de E/S. A los
35 mseg, P2 se prioriza porque expira su intervalo de tiempo; de cualquier forma, se programa otra
vez, ya que ningún otro proceso está en el estado listo. La operación de la E/S de P1 se completa en
125 mseg, por lo que su estado cambia a listo. El programador lo selecciona para la ejecución; por
tanto, su estado se cambia nuevamente a en ejecución.

Tabla 3.7 Transiciones de estado en un sistema de tiempo compartido

Estado nuevo
Tiempo Evento Observaciones P1 P2
0 P1 se planifica en ejecución listo
10 P1 se prioriza P2 se planifica listo en ejecución
20 P2 se prioriza P1 se planifica en ejecución listo
25 P1 inicia la E/S P2 se planifica bloqueado en ejecución
35 P2 se prioriza bloqueado listo
P2 se planifica bloqueado en ejecución
45 P2 inicia la E/S bloqueado bloqueado
125 Interrupción de E/S P1 cambia a listo listo bloqueado
P1 se planifica en ejecución bloqueado

3.3.3.1 Los procesos suspendidos

Además de los cuatro estados de proceso fundamentales descritos en la tabla 3.5, el sistema ope-
rativo usa un quinto estado llamado de suspensión para un proceso que no debe ser considerado
para planificar. El estado de tal proceso se cambia a listo o bloqueado cuando su operación debe
reanudarse. El estado de suspensión difiere del estado bloqueado en que la razón de la suspen-
sión es externa a la actividad durante el proceso, mientras que la razón para bloqueo es interna a
su propia actividad. Dos causas típicas de suspensión son:

• Un proceso sale de la memoria, es decir, se intercambia hacia fuera.


• El usuario que inició un proceso especifica que el proceso no deberá planificarse hasta
que se satisfaga alguna condición.

El estado del proceso es una noción abstracta definida por un diseñador del sistema ope-
rativo y usado por el kernel para simplificar el control de los procesos. Un kernel puede usar
un estado individual suspendido y alguna información auxiliar para decidir si un proceso en el
estado suspendido deberá entrar en el estado listo o en el estado bloqueado cuando su operación
deba reanudarse. Alternativamente, el kernel puede dividir el estado suspendido en un número de
estados, dependiendo de la causa de la suspensión. Este enfoque simplifica la especificación
de las transiciones de estado dentro y fuera del estado suspendido.
Restringimos el debate de los procesos suspendidos a los procesos intercambiados y usamos
dos estados suspendidos llamados listo intercambiado y bloqueado intercambiado. Consecuen-
temente, la figura 3.7 muestra los estados de proceso y las transiciones de los estados. Las transi-

04 MAQ. CAP. 03(F0694).indd 98 8/10/07 12:54:45 AM


3.3 La visión del sistema operativo de los procesos 99

ciones del estado listo al estado listo intercambiado y del estado bloqueado al estado bloqueado
intercambiado se deben a una acción de intercambio hacia fuera. Las transiciones inversas tienen
lugar cuando estos procesos son intercambiados de regreso a la memoria. La transición bloquea-
do intercambiado → listo intercambiado tiene lugar si se concede la petición que el proceso
esperaba aun mientras el proceso está en un estado suspendido, por ejemplo, si se le concede un
recurso para el cual fue bloqueado. Sin embargo, el proceso continúa siendo intercambiado hacia
fuera. Cuando se intercambia nuevamente a la memoria, su estado cambiará a listo y competirá
con otros procesos listos para la atención del CPU.

En terminación
ejecución Terminado
petición de
despacho recurso o
de espera
priorización

proceso recurso concedido


Listo
nuevo o espera terminada Bloqueado

intercambio intercambio intercambio intercambio


hacia fuera hacia dentro hacia fuera hacia dentro

Listo recurso concedido Bloqueo


intercam-
biado o espera terminada intercam-
biado

Figura 3.7 Estados de proceso y transiciones de estado usando dos estados intercambiados.

3.3.4 El bloque de control de proceso


El bloque de control de proceso (PCB) contiene toda la información relacionada con un proceso
que se usa para controlar su operación (tal como su id, prioridad, estado, PSW y contenido de
los registros del CPU), así como la información usada en el acceso a los recursos y a la im-
plementación de la comunicación con otros procesos. La tabla 3.8 describe los campos de la
estructura de datos del PCB.
La información prioritaria y de estado es usada por el programador. Pasa el id del proceso
seleccionado al despachador. Para un proceso que no está en el estado en ejecución, los cam-
pos de los registros del CPU y de la PSW conjuntamente contienen una foto instantánea del
CPU del momento en que fue liberado por el proceso por última vez, es decir, tienen el conte-
nido de los diferentes registros de control y de datos del CPU cuando el proceso se bloqueó o
cuando fue priorizado. La ejecución del proceso puede reanudarse simplemente cargando esta
información de su PCB en el CPU. Esta acción será realizada la próxima vez que este proceso
se despache.

04 MAQ. CAP. 03(F0694).indd 99 8/10/07 12:54:45 AM


100 CAPÍTULO 3 Los procesos y los hilos

Tabla 3.8 Campos del bloque de control de procesos (PCB)

Campo del PCB Contenido


id del proceso El id único se asigna al proceso cuando se crea.
id del padre y del hijo Estos id se usan para la sincronización de los procesos, común-
mente para que el proceso verifique si se ha terminado el pro-
ceso hijo.
Prioridad Por lo general, la prioridad es un valor numérico. A un proceso
se le asigna una prioridad cuando es creado. La prioridad puede
cambiar durante la vida del proceso, dependiendo de su natura-
leza (acotado por el CPU o por la E/S), su edad y los recursos
que consuma (regularmente tiempo de CPU).
Estado del proceso El estado actual del proceso.
PSW Ésta es una instantánea, es decir, una imagen de la PSW cuando
el CPU fue liberado voluntariamente por el proceso o prioriza-
do por última vez por el kernel. El cargado de vuelta de esta
instantánea en la PSW reanudará la ejecución del programa
(véase la figura 2.3 sobre los campos de la PSW).
Registros del CPU Contenido de los registros cuando el CPU fue liberado por
última vez por el proceso o priorizado por última vez por el
kernel.
Información de los Para un proceso en el estado bloqueado, este campo contiene
eventos información relativa al evento por el cual espera el proceso.
Cuando ocurre un evento, el kernel usa esta información para
identificar el proceso que espera al evento y cambia su estado,
de bloqueado a listo.
Información de la señal Información relativa a las localidades de los manejadores de
señal (véase la sección 3.6.4).
Apuntador del PCB Este campo se usa para formar una lista de PCB. El kernel man-
tiene varias listas de los PCB, por ejemplo, una lista de PCB de
procesos listos, otra de PCB de procesos bloqueados, etcétera.

El campo de información de eventos de la PCB juega un papel importante para poder efec-
tuar las transiciones de estado apropiadas en el sistema. Considere un proceso Pi que se bloqueó
en una operación de E/S. El campo de información de evento en la PCB del Pi indica el id del
dispositivo, digamos el dispositivo d, en el cual se está realizando la operación de E/S. Cuando
se termina la operación de E/S en el dispositivo d, el kernel debe encontrar el proceso que espera
a ese evento y cambiar su estado a listo. El campo información de evento del PCB del Pi indica
que espera el final de la E/S en el dispositivo d, por lo que el kernel concluye que el estado de Pi
deberá cambiar de bloqueado a listo.

3.3.5 El contexto salvar, planificar y despachar

La función de contexto salvar realiza la limpieza cada vez que un proceso libera al CPU o es
priorizado. Incluye salvar los registros de la PSW y del CPU en los campos apropiados del PCB

04 MAQ. CAP. 03(F0694).indd 100 8/10/07 12:54:45 AM


3.3 La visión del sistema operativo de los procesos 101

del proceso, y también el guardado de la información relativa a su ambiente de proceso (véase


la sección 3.3.2). También marca al estado del proceso como listo. Una acción de procesamiento
de eventos puede cambiar más tarde el estado a bloqueado.
La función de planificación usa la información de estado de proceso de los PCB para
seleccionar un proceso listo para la ejecución. Cambia el estado del proceso a listo y pasa su
id a la función de despacho. La función de despacho establece el ambiente del proceso selec-
cionado y carga información de los campos de los registros de la PSW y del CPU de su PCB
al CPU.

Ejemplo 3.4 Un sistema operativo contiene 2 procesos: P1 y P2; P2 tiene una prioridad más alta que
P1. P2 se bloquea en una operación de E/S y P1 está en ejecución. Las siguientes acciones tienen
lugar cuando ocurre el evento de terminación de E/S para la operación de E/S de P2:

1. Se realiza la función del contexto salvar para P1 y su estado cambia a listo.


2. Se procesa el evento de terminación de E/S y el estado de P2 cambia de bloqueado a
listo.
3. Se realiza la planificación. P2 se selecciona porque el proceso listo es de prioridad más
alta.
4. P2 se despacha.

Conmutación de procesos Las funciones 1, 3 y 4 del ejemplo 3.4 realizan colectivamente


la conmutación entre los procesos P1 y P2. La conmutación entre los procesos también ocurre
cuando un proceso en ejecución se bloquea debido a una petición o es priorizado. Un evento no
conduce a la conmutación entre procesos si la ocurrencia del evento provoca una transición de
estado para un proceso de prioridad más baja o si no causa ninguna transición de estado (por
ejemplo, si el evento se debe a una petición que se satisface enseguida). En el primer caso, la
función de planificación selecciona el mismo proceso interrumpido para su despacho. En el
último caso, la planificación no necesita realizarse en absoluto; después del procesamiento
del evento, el control puede darse al despachador, el cual simplemente despachará el proceso
interrumpido.
La conmutación entre los procesos representa más que salvar el estado del CPU de
un proceso y cargar el estado del CPU de otro proceso. El ambiente de proceso necesita ser
conmutado igualmente. El guardado y la carga de la información de la administración de
memoria es una parte cara de la conmutación de los procesos, en particular cuando se usa
la memoria virtual. Algunos sistemas de cómputo proveen instrucciones especiales para re-
ducir la sobrecarga de conmutación del proceso, por ejemplo, una instrucción que salva o
carga la PSW y todos los registros del CPU. Usamos el término información del estado de un
proceso para referirnos a toda la información que necesita ser salvada y recuperada durante la
conmutación de los procesos. La sobrecarga de la conmutación de los procesos depende del
tamaño de esta información.
La conmutación de los procesos también tiene alguna sobrecarga indirecta. El proceso
recién planificado no cuenta con ninguna parte de su espacio de la dirección en la memoria
caché; por tanto, funciona deficientemente hasta que acumula suficiente información en ella.
La operación de memoria virtual es también más deficiente inicialmente porque la memoria
temporal de traducción no contiene ninguna información pertinente para el proceso recién pla-
nificado.

04 MAQ. CAP. 03(F0694).indd 101 8/10/07 12:54:46 AM


102 CAPÍTULO 3 Los procesos y los hilos

3.3.6 Eventos relacionados con el proceso

Los siguientes eventos ocurren durante la operación de un sistema operativo:

1. Evento de creación de proceso: Se crea un nuevo proceso.


2. Evento de terminación de proceso: Un proceso termina su ejecución.
3. Evento del temporizador: Ocurre la interrupción del temporizador.
4. Evento de petición del recurso: El proceso hace una petición del recurso.
5. Evento de liberación del recurso: Se libera un recurso.
6. Evento de petición de iniciación de la E/S: El proceso desea iniciar una operación de
E/S.
7. Evento de terminación de la E/S: Se completa una operación de E/S.
8. Evento de enviar mensaje: Un mensaje es enviado por un proceso a otro.
9. Evento de recibir mensaje: Un mensaje es recibido por un proceso.
10. Evento de enviar señal: Una señal es enviada por un proceso a otro.
11. Evento de recibir la señal: Una señal es recibida por un proceso.
12. Interrupción de programa: Una instrucción que se ejecutó en el proceso de la corrida
funciona mal.

Los eventos del temporizador y de la terminación de la E/S son causados por situaciones
externas al proceso en ejecución. Todos los demás eventos se deben a las acciones en el pro-
ceso en ejecución. Agrupamos los eventos 1-9 en dos clases amplias para analizar las acciones
de las rutinas de manejo de eventos, y estudiamos los eventos 10 y 11 en la sección 3.6.4. El
kernel realiza una acción estándar, como abortar el proceso en ejecución, cuando ocurre el
evento 12.

Eventos relacionados con la creación, la terminación y la priorización de procesos Un


nuevo proceso puede crearse en dos formas: a través de la interfaz de usuario o mediante
otro proceso. Cuando un usuario emite una orden para ejecutar un programa, el intérprete de
comandos de la interfaz del usuario invoca algún programa (con el nombre de éste como un
parámetro) que no esté en el kernel que hace la llamada de sistema create_process mencionada
en la sección 3.2. Cuando un proceso desea crear un proceso hijo para ejecutar un programa,
él mismo hace una llamada de sistema create_ process con el nombre del programa como un
parámetro.
El evento de manejo de rutina para la llamada de sistema create_ process crea una PCB
para el nuevo proceso, le asigna un id único de proceso y una prioridad, y pone esta información
y el id del proceso padre en campos pertinentes de la PCB. Entonces determina la cantidad de
memoria requerida para acomodar el espacio de la dirección del proceso, es decir, el código y
los datos del programa que va a ejecutarse y su pila, y arregla la asignación de esta cantidad
de memoria al proceso (las técnicas de asignación de memoria se analizan más adelante, en
los capítulos 5 y 6). La mayoría de sistemas operativos asocian algunos recursos estándar con
cada proceso, como un monitor y los archivos estándar de entrada y salida. El kernel le asigna
estos recursos estándar al proceso en ese momento. Entonces alimenta información acerca de

04 MAQ. CAP. 03(F0694).indd 102 8/10/07 12:54:46 AM


3.3 La visión del sistema operativo de los procesos 103

los recursos y la memoria asignados en el contexto del nuevo proceso. Después de completar
estas tareas, coloca al estado del proceso en listo en su PCB e introduce este proceso en una
lista apropiada de PCB.
Cuando un proceso hace una llamada de sistema para terminarse o para terminar un proceso
hijo, el kernel atrasa la terminación hasta que se completan las operaciones de E/S que fueron
iniciadas por el proceso. Entonces libera la memoria y los recursos asignados. Esta función es
realizada usando la información en campos correctos del contexto de proceso. En ese momento
el kernel cambia el estado del proceso a terminado. Son necesarias dos disposiciones adicionales
porque el padre del proceso terminado puede desear comprobar su estatus. Primero, si el padre
del proceso ya está esperando su terminación, el kernel debe activar al proceso padre. Para reali-
zar esta acción, el kernel toma el id del proceso padre de la PCB del proceso terminado y verifica
el campo de información de evento del PCB del proceso padre para investigar si el proceso padre
está esperando la terminación del proceso hijo (véase la sección 3.3.4). En segundo lugar, el
PCB del proceso terminado no se destruye en ese momento para permitir al padre verificar
el estatus del proceso terminado en algún momento futuro, lo que se hará después de que el
proceso padre termine.
El proceso en el estado en ejecución deberá priorizarse si expira su intervalo de tiempo. La
función de contexto salvar ya habrá cambiado el estado del proceso en ejecución a listo antes
de invocar el manipulador de eventos para las interrupciones del temporizador, por lo que el
manipulador de eventos simplemente informa al programador acerca del final del intervalo de
tiempo y el programador mueve el PCB a una lista de planificación apropiada. La priorización
también deberá ocurrir cuando un proceso de prioridad más alta se convierte en listo, pero eso
está implícito en la planificación, por lo que una rutina de manejo de eventos no necesita realizar
ninguna acción explícita para él.

Los eventos relacionados con la utilización del recurso Cuando un proceso pide un
recurso a través de una llamada de sistema, el kernel puede ser capaz de ubicar el recurso inme-
diatamente, en cuyo caso el manejo de eventos no causa ninguna transición del estado de pro-
ceso, por lo que el proceso interrumpido será planificado y despachado otra vez. Para reducir la
sobrecarga, el kernel puede saltarse la planificación en tales casos y directamente puede invocar
que el despachador reanude la ejecución del proceso interrumpido. Si el recurso no puede asig-
narse, la rutina del manejo de eventos cambia el estado del proceso interrumpido a bloqueado y
anota el id del recurso en el campo de información de eventos del PCB.
Cuando un proceso libera un recurso a través de una llamada de sistema, la rutina de manejo
de eventos no necesita cambiar el estado del proceso que hizo la llamada de sistema. Sin embar-
go, deberá verificar si algunos otros procesos fueron bloqueados porque necesitaban el recurso,
y, si es así, deberán asignar el recurso a uno de los procesos bloqueados y cambiar su estado a
listo. Esta acción requiere un arreglo especial que analizaremos más adelante.
Una llamada de sistema para pedir la iniciación de una operación de E/S y un final de se-
ñalamiento de interrupción de la operación de E/S conducen a acciones de manejo de eventos
que son análogas a una petición de un recurso y a la asignación del recurso posteriormente.
El estado del proceso cambia a bloqueado cuando se inicia la operación de E/S y la causa del
bloqueo se anota en el campo de información de eventos de su PCB; su estado cambia nueva-
mente a listo cuando se completa la operación de E/S. Una petición para recibir un mensaje de
otro proceso y una petición para enviar un mensaje a otro proceso también conducen a acciones
análogas.

04 MAQ. CAP. 03(F0694).indd 103 8/10/07 12:54:46 AM


104 CAPÍTULO 3 Los procesos y los hilos

El bloque de control de eventos (ECB) Cuando un evento ocurre, el kernel debe encon-
trar el proceso que lo afecta. Por ejemplo, cuando sucede una interrupción de terminación de la
E/S, el kernel debe identificar el proceso que espera su terminación. Puede lograr esto registran-
do el campo de información de eventos de los PCB de todos los procesos. Esta búsqueda es cara,
y los sistemas operativos usan esquemas diversos para apresurarla. Analizaremos un esquema
que usa bloques de control de eventos (ECB).
Como se muestra en la figura 3.8, un ECB contiene tres campos. El campo de descripción
de eventos describe un evento, y el del id de proceso contiene el id del proceso que espera al
evento. Cuando un proceso Pi se bloquea por la ocurrencia de un evento ei, el kernel forma un
ECB y pone información pertinente relativa a ei y Pi en él. El kernel puede mantener una lista
separada de ECB para cada clase de eventos, como mensajes de interproceso u operaciones de
E/S, por lo que el campo del apuntador ECB se usa para entrar en el ECB recién creado en una
lista correcta de ECB.

Descripción
del evento
id de proceso
del proceso
que espera
Apuntador
de ECB

Figura 3.8 Bloque de control de eventos (ECB).

Cuando un evento ocurre, el kernel escudriña la lista correcta de ECB para encontrar uno
con una descripción del evento que concuerde. El campo del id de proceso del ECB indica
qué proceso espera que el evento ocurra. El estado de este proceso se cambia para reflejar la
ocurrencia del evento. El siguiente ejemplo ilustra el uso de ECB para manipular el evento de
terminación de E/S; su empleo en los mensajes manipuladores de interproceso se describe en la
sección 10.2.2.

Ejemplo 3.5 Las acciones del kernel cuando el proceso Pi pide una operación de E/S en algún
dispositivo d y cuando la operación de E/S se completa son las siguientes:
1. El kernel crea un ECB y lo inicializa como sigue:
a) descripción del evento = Final de E/S en el dispositivo d.
b) Proceso que espera al evento = Pi.
2. El ECB recién creado (llamémosle ECBj) se añade a una lista de ECB.
3. El estado de Pi cambia a bloqueado y la dirección de ECBj se pone en el campo “Informa-
ción de eventos” del PCB del Pi (véase la figura 3.9).
4. Cuando ocurre la interrupción “Final de la E/S en el dispositivo d ”, ECBj se localiza al
buscar un ECB con un campo de descripción del evento que concuerde.
5. El id del proceso afectado, es decir, Pi, se extrae del ECBj. El PCB de Pi se localiza y su
estado cambia a listo.

04 MAQ. CAP. 03(F0694).indd 104 8/10/07 12:54:46 AM


3.3 La visión del sistema operativo de los procesos 105

PCB

Pi ECB
Final de E/S en d
Pi
bloqueado

Información de eventos

Figura 3.9 Interrelación de PCB-ECB.

Petición de
recurso o
de mensaje

Petición
de E/S Bloquear

Crear o
terminar
el proceso

Interrumpir Despachar
el temporizador Programar

Terminación
de E/S

Enviar
mensaje Desbloquear

Liberar
recurso

Figura 3.10 Acciones del kernel de manejo de eventos.

Resumen de manejo de eventos La figura 3.10 ilustra las acciones de manejo del kernel
descritas anteriormente. La acción de bloque siempre cambia el estado del proceso que hizo una
llamada de sistema de listo a bloqueado. La acción de desbloquear encuentra un proceso cuya
petición puede cumplirse entonces y cambia su estado de bloqueado a listo. Una llamada de
sistema para pedir un recurso conduce a una acción de bloqueo si el recurso no puede ser asig-
nado al proceso peticionario. Esta acción es seguida por la planificación y el despacho porque
otro proceso tiene que ser seleccionado para el uso del CPU. La acción de bloqueo no se realiza

04 MAQ. CAP. 03(F0694).indd 105 8/10/07 12:54:47 AM


106 CAPÍTULO 3 Los procesos y los hilos

si el recurso puede asignarse enseguida. En este caso, el proceso interrumpido simplemente se


despacha otra vez. Cuando un proceso libera un recurso, se realiza una acción de desbloqueo si
algún otro proceso está esperando al recurso liberado, seguido por la planificación y el despacho
porque el proceso de desbloqueo puede tener una prioridad más alta que el que liberó al recurso.
Otra vez se omite la planificación si ningún proceso es desbloqueado debido al evento.

3.4 LOS HILOS

El uso de procesos para proveer la concurrencia dentro de una aplicación ocupa una gran can-
tidad de conmutación de sobrecarga del proceso (véase la sección 3.3.5). Los hilos proveen un
método de bajo costo de implementación de la concurrencia, que sirve para ciertas clases de
aplicaciones.
La conmutación de la sobrecarga del proceso tiene dos componentes:

• Sobrecarga relacionada con la ejecución: Un proceso se define como la ejecución de


un programa. Por tanto, al conmutar entre procesos, el estado del CPU del proceso en
ejecución tiene que salvarse y el del CPU de un nuevo proceso tiene que cargarse en el
CPU. Esta sobrecarga es inevitable.
• Sobrecarga relacionada con el uso del recurso: Como se analiza en la sección 3.3, el
ambiente de proceso contiene información relativa a los recursos asignados a un proceso
y su interacción con otros procesos. Conduce a un tamaño grande de información del
estado de proceso, lo cual acrecienta la sobrecarga de conmutación del proceso.

La sobrecarga de conmutación puede reducirse eliminando la sobrecarga relacionada con


el recurso en algunas situaciones. Considere las funciones de contexto de salvado, planificación
y despacho que se ilustran en la figura 3.5 y que se discutieron en la sección 3.3.5. La ocurrencia
de un evento puede dar como resultado la conmutación de la ejecución de un proceso en ejecu-
ción Pi a la ejecución de algún otro proceso Pj. Si tanto Pi como Pj forman parte de la misma
aplicación, comparten el código, los datos y los recursos; su información de estado difiere sólo
en los valores contenidos en los registros del CPU y en las pilas. Mucho del salvado y la carga
de la información de estado del proceso al conmutar de Pi a Pj resulta así redundante. Se explota
esta característica para lograr una reducción en la sobrecarga de la conmutación. Se usa la noción
de hilo con este propósito.

Definición 3.3 (Hilo) Un hilo es una ejecución de programa que usa los recursos de un
proceso.

Ya que un hilo es una ejecución de programa, tiene su propia pila y su propio estado del
CPU (véase la definición 3.1). Usamos las locuciones “hilo(s) de un proceso” y “proceso padre
de un hilo” para describir la relación entre un hilo y el proceso cuyo ambiente usa. Los hilos del
mismo proceso comparten el código, los datos y los recursos entre sí. La abstracción de proceso
continúa siendo usada como antes, excepto porque los procesos comúnmente tienen partes bien
definidas de código y de datos.

04 MAQ. CAP. 03(F0694).indd 106 8/10/07 12:54:47 AM


3.4 Los hilos 107

Hilos

Proceso
Pi Pilas
info de la info de los apuntadores
memoria recursos de archivo

código datos pila

Ambiente del Bloques de control


proceso Pi Ambiente del PCB de hilos (TCB)
proceso Pi
a) b)

Figura 3.11 Hilos del proceso Pi: a) concepto, b) implementación.

La figura 3.11 ilustra la relación entre hilos y procesos. El proceso Pi tiene tres hilos re-
presentados por las líneas onduladas. El kernel asigna una pila y un bloque de control del hilo
(TCB) a cada hilo. Los hilos se ejecutan dentro del ambiente de Pi. El sistema operativo se da
cuenta de este hecho, y salva sólo el estado del CPU y el apuntador de la pila mientras que con-
muta entre hilos del mismo proceso. En la mayoría de los sistemas de cómputo, el apuntador de
la pila es mantenido en un registro del CPU; por tanto, sólo el estado del CPU necesita ser
conmutado. El uso de hilos divide eficazmente el estado del proceso en dos partes: el estado del
recurso permanece con el proceso mientras que el de ejecución se asocia con un hilo. El costo de
concurrencia dentro del ambiente de un proceso es ahora simplemente una copia del estado
de ejecución para cada hilo. El estado del recurso no se copia.

Los estados de los hilos y las transiciones de los estados Excepto por la diferencia de que
los hilos no tienen recursos asignados, éstos y los procesos son análogos. Por tanto, los estados
de los hilos y las transiciones de los estados de los hilos son análogos a los estados de proceso
y a las transiciones de los estados de proceso. Cuando un hilo es creado, se le pone en el estado
listo porque su proceso padre ya tiene los recursos necesarios asignados. Entra en el estado en
ejecución cuando es planificado. No entra en el estado bloqueado por las peticiones de recursos,
porque no hace ninguna petición de recursos; sin embargo, puede entrar en el estado bloqueado
debido a los requisitos de sincronización de proceso. Por ejemplo, si los hilos se usaran en la
aplicación de registro de datos de tiempo real del ejemplo 3.1, el hilo disk_write tendría que
entrar en el estado bloqueado si no existen datos de muestra en buffer_area.

Las ventajas de los hilos Un proceso aplicativo puede crear muchos hilos para ejecutar
su código. Es interesante ver las ventajas de este panorama sobre la creación de muchos pro-
cesos para ejecutar el código aplicativo. La ventaja fundamental es que la sobrecarga es baja al
conmutar el CPU de un hilo a otro del mismo proceso. El estado del recurso se conmuta sólo
al conmutar entre hilos de procesos diferentes.
El uso de hilos proporciona la concurrencia dentro de un proceso. Puede proveer la acelera-
ción del cómputo: si un hilo de un proceso se bloqueara en una operación de E/S, el CPU puede

04 MAQ. CAP. 03(F0694).indd 107 8/10/07 12:54:48 AM


108 CAPÍTULO 3 Los procesos y los hilos

conmutarse a otro hilo del mismo proceso. El uso de hilos también puede simplificar el diseño
y la codificación de aplicaciones que necesitan realizar el servicio o las peticiones concurrentes.
Por ejemplo, en un sistema de reservación de una aerolínea o en un sistema bancario, puede
crearse un hilo nuevo para manejar cada petición nueva. El sistema operativo planificará estos
hilos para proveer concurrencia. Este arreglo no recurre a la lógica compleja para lograr el pro-
cesamiento concurrente de las peticiones.
La creación de muchos procesos dentro del código de aplicación puede lograr el mismo
efecto. Sin embargo, hay una diferencia significativa. Las actividades concurrentes, ya sea de
los procesos o de los hilos, tienen que comunicarse o sincronizarse entre sí. Cuando estas acti-
vidades son implementadas por los procesos, la comunicación o la sincronización involucran al
kernel. Los procesos tienen que hacer llamadas de sistema para indicar sus requerimientos de co-
municación o de sincronización al kernel. Sin embargo, los hilos de un proceso comparten su es-
pacio de datos. Por tanto, pueden comunicarse o sincronizarse mediante el uso de la memoria
compartida, eliminando de esta manera las llamadas de sistema que son caras. Por consiguiente,
en la aplicación de tiempo real del ejemplo 3.1, será preferible usar hilos para implementar las
funciones 1 y 2, que comparten el área de la memoria temporal.
La tabla 3.9 resume las ventajas de los hilos. Como se estudia en el ejemplo 3.1, una apli-
cación puede crear muchos hilos para obtener la concurrencia y simplificar su funcionamien-
to. Pueden asignarse funciones específicas a los hilos. También pueden crearse para realizar
un servicio concurrente de peticiones recibidas por un servidor, por ejemplo, en un sistema de
reservaciones de una aerolínea o en un sistema bancario. En tales casos, los hilos ejecutarán la
misma función.

Tabla 3.9 Ventajas de los hilos

Ventaja Explicación
Sobrecarga El estado de hilo consiste solamente en el estado de
baja un cómputo. El estado de asignación de recursos y
el estado de comunicación no es parte del estado del
hilo, lo que conduce a una sobrecarga baja del inter-
cambio.
Aceleración La concurrencia dentro de un proceso puede obtener-
se mediante la creación de hilos. Esta técnica puede
acelerar la ejecución de una aplicación tanto en los
uniprocesadores como en los multiprocesadores.
Comunicación Los hilos de un proceso pueden comunicarse entre
eficiente sí a través del espacio compartido de datos, evitando
de esa forma la sobrecarga de las llamadas al sistema
para la comunicación.

Código para el uso de hilos Los hilos deberán asegurar exactitud de los datos compartidos
y la sincronización (véase la sección 3.2.1). La exactitud de los datos compartidos también tiene
otra faceta. Las funciones o las subrutinas que usan datos estáticos o globales para llevar valo-
res a través de sus activaciones sucesivas producen resultados incorrectos cuando se les invoca
concurrentemente, porque las invocaciones concurrentes realizan eficazmente la labor de com-

04 MAQ. CAP. 03(F0694).indd 108 8/10/07 12:54:48 AM


3.4 Los hilos 109

partir datos sin exclusiones mutuas. Se dice que tales rutinas son inseguras para los hilos. Una
aplicación que usa hilos debe ser codificada en una manera segura para los hilos y debe invocar
rutinas sólo de una biblioteca que sea segura para los hilos.
La manipulación de señales requiere atención especial en una aplicación multihilos. Re-
cuerde que el kernel acepta que un proceso especifique los manipuladores de la señal (véase la
sección 3.6.4). Cuando varios hilos son creados en un proceso, ¿cuál hilo deberá maniobrar
la señal? Hay varias posibilidades. El kernel puede seleccionar uno de los hilos para el manejo
de la señal. Esta elección puede estar hecha estadísticamente (por ejemplo, el primero o el último
hilo creado durante el proceso) o dinámicamente (por ejemplo, el hilo de prioridad más alta).
De manera alternativa, el kernel puede aceptar que una aplicación especifique cuál hilo deberá
maniobrar señales en cualquier momento.
Una señal síncrona surge debido a la actividad en un hilo, por lo que es más conveniente que
el hilo mismo la maniobre. Idealmente, cada hilo debería poder especificar cuáles señales sín-
cronas tiene interés en manipular. Sin embargo, para proveer esta característica, el kernel tendría
que reproducir el arreglo de manejo de la señal de la figura 3.11 para cada hilo, razón por la cual
pocos sistemas operativos la proveen. Una señal asincrónica puede ser maniobrada por cualquier
hilo en un proceso. Para asegurar atención inmediata para la condición que causó la señal, el hilo
de prioridad más alta deberá maniobrar tal señal.

La implementación de hilos Los hilos se implementan de diferentes maneras. La diferen-


cia principal radica en cuánto saben el kernel y el programa de aplicación acerca de los hilos.
Estas diferencias conducen a implicaciones diferentes para la sobrecarga y para la concurrencia
en un programa de aplicación.
En esta sección analizamos tres métodos para implementar hilos. Éstos son:

• Los hilos en el nivel del kernel.


• Los hilos en el nivel del usuario.
• Los hilos híbridos.

Los estudios experimentales han demostrado que la conmutación entre los niveles de los hilos
del kernel de un proceso es 10 veces más rápida que la conmutación entre los procesos, y la
conmutación entre los hilos en el nivel del usuario es 100 veces más rápida que la conmutación
entre los procesos. Los hilos en el nivel del kernel proveen mejor paralelismo y aceleración en
un sistema de multiprocesador.

3.4.1 Los hilos en el nivel del kernel

Un hilo en el nivel del kernel es implementado por éste. Por tanto, la creación y la terminación
de los hilos en ese nivel y la comprobación de su estatus se realizan a través de las llamadas de
sistema análogas a las estudiadas en la sección 3.2. La figura 3.12 muestra cómo el kernel maneja
los hilos en el nivel del kernel. Cuando un proceso hace una llamada de sistema create_thread,
el kernel le asigna un id y asigna un bloque de control de hilos (TCB). El TCB contiene un apun-
tador para la PCB del proceso.
Cuando un evento ocurre, el kernel salva el estado del CPU del hilo interrumpido en su
TCB. Después del manejo del evento, el programador considera los TCB de todos los hilos y
selecciona un hilo listo; el despachador usa el apuntador de PCB en su TCB para comprobar si

04 MAQ. CAP. 03(F0694).indd 109 8/10/07 12:54:48 AM


110 CAPÍTULO 3 Los procesos y los hilos

Pi Pj
PCB PCB

Bloques de control de hilos

Programador
TCB
seleccionada

Figura 3.12 Planificación de los hilos en el nivel del kernel.

el hilo seleccionado forma parte de un proceso diferente al hilo interrumpido. Si es así, salva el
contexto del proceso al que pertenece el hilo interrumpido y carga el del proceso al que pertene-
ce el hilo seleccionado. Luego despacha a éste. Las acciones para guardar y cargar el contexto
de proceso son innecesarias si ambos hilos forman parte del mismo proceso. Esta característica
reduce la sobrecarga de la conmutación.

Ventajas y desventajas de los hilos en el nivel del kernel Un hilo en el nivel del kernel es
como un proceso, excepto porque tiene una cantidad más pequeña de información de estado,
es decir, tiene un estado “más delgado”. Esta similitud entre hilos y procesos es conveniente para
los programadores: la planificación para hilos no es diferente a la planificación para los procesos.
En un sistema de multiprocesador, los hilos en el nivel del kernel proveen el paralelismo (vea
la sección 3.2.2), es decir, varios hilos que forman parte de un proceso pueden planificarse si-
multáneamente, lo cual no es posible cuando se usan hilos en el nivel del usuario, que se des-
criben en la siguiente sección; por eso aquél provee una mejor aceleración de cómputo que los
hilos en el nivel del usuario.
Sin embargo, el manejo de los hilos como si fueran procesos también tiene sus desventajas.
La conmutación entre hilos es realizada por el kernel como resultado del manejo de eventos.
Por tanto, incurre en la sobrecarga del manejo de eventos aun si el hilo interrumpido y el hilo
seleccionado forman parte del mismo proceso. Esta característica limita el guardado en la sobre-
carga de la conmutación.

3.4.2 Hilos en el nivel del usuario

Los hilos en el nivel del usuario se implementan mediante una biblioteca del hilo, que se enlaza
con el código de un proceso. La biblioteca establece el arreglo de implementación del hilo mos-

04 MAQ. CAP. 03(F0694).indd 110 8/10/07 12:54:48 AM


3.4 Los hilos 111

trado en la figura 3.11b) sin involucrar al kernel ni a la operación de interpaginado de hilos en


el proceso. Así, el kernel no se da cuenta de los hilos en el nivel del usuario en el proceso; ve
sólo el proceso. El programador considera los PCB y selecciona un proceso listo; el despachador
lo despacha. La mayoría de los sistemas operativos implementan de esta manera la interfaz del
programa de aplicación de los hilos-p provista en el estándar del IEEE Posix.
Una visión general de la creación y operación de hilos es la siguiente: un proceso invoca la
función de la biblioteca create_thread para crear un hilo nuevo. La función de la biblioteca crea
un TCB para el hilo nuevo y comienza a considerar a éste para “planificar”. Cuando el hilo en el
estado en ejecución invoca a una función de la biblioteca para que sincronice su ejecución con
otros hilos, la función de biblioteca realiza la “planificación” y conmuta a otro hilo del proceso.
Esto equivale a una conmutación del hilo. Así, el kernel es ajeno a la conmutación entre hilos;
cree que el proceso está continuamente en operación. Si la biblioteca del hilo no puede encontrar
un hilo listo durante el proceso, hace una llamada de sistema de “bloquéame”. Entonces el kernel
bloquea al proceso. El proceso será desbloqueado cuando algún evento active uno de sus hilos y
reanude la ejecución de la función de la biblioteca del hilo, la cual realizará la “planificación”
y conmutará a la ejecución del hilo recién activado.

La planificación de hilos en el nivel del usuario La figura 3.13 es un diagrama esque-


mático de la planificación de hilos en el nivel del usuario. El código de la biblioteca del hilo
es una parte de cada proceso. Realiza la “planificación” para seleccionar un hilo y organiza su
ejecución. Vemos esta operación como un mapeo del TCB del hilo seleccionado en la PCB del
proceso.

Pi Pj

Bloques de control de hilos


Mapeo realizado por
la biblioteca de hilos
Bloques de control del proceso

Programador
PCB
seleccionado

Figura 3.13 Planificación de los hilos en el nivel del usuario.

04 MAQ. CAP. 03(F0694).indd 111 8/10/07 12:54:49 AM


112 CAPÍTULO 3 Los procesos y los hilos

La biblioteca del hilo usa información en los TCB para decidir cuál hilo deberá operar en
cualquier momento. Para “despachar” el hilo, el estado del CPU del hilo deberá convertirse
en el estado del CPU del proceso, y el apuntador de la pila de proceso deberá apuntar hacia la
pila del hilo. Como la biblioteca del hilo es una parte de un proceso, el CPU está en el modo no
privilegiado. Por tanto, un hilo no puede ser despachado al cargar información nueva en la PSW;
la biblioteca del hilo tiene que usar instrucciones no privilegiadas para cambiar contenido de la
PSW, por lo que carga la dirección de la pila del hilo en el registro de dirección de la pila y
ejecuta una instrucción de bifurcación para transferir el control a la siguiente instrucción del
hilo. El siguiente ejemplo ilustra situaciones interesantes durante la planificación de hilos en
el nivel del usuario.

Ejemplo 3.6 La figura 3.14 ilustra cómo la biblioteca del hilo maneja tres hilos en un proceso Pi.
Los códigos N, R y B en los TCB representan los estados en ejecución, listo y bloqueado, respecti-
vamente. El proceso Pi está en el estado en ejecución y la biblioteca del hilo está ejecutando. Ésta
despacha al hilo h1. El proceso Pi es priorizado posteriormente por el kernel. La figura 3.14a)
ilustra los estados de los hilos y del proceso Pi. El hilo h1 está en el estado en ejecución y el proceso
Pi está en el estado listo. El hilo h1 reanudará su operación después, cuando el proceso Pi se plani-
fique. La línea del TCB de h1 al PCB de Pi indica que el TCB de h1 está mapeándose actualmente
en el PCB de Pi. Este hecho es importante para las acciones de despacho y del contexto de salvar
de la biblioteca del hilo.

h1 h2 h3 h1 h2 h3 h1 h2 h3 h1 h2 h3

Pi Pi Pi Pi

TCB N R B N R B R N B R N B
h1 h1 h1 h1

PCB Listo En ejecución En ejecución Bloqueado


de Pi d2

a) b) c) d)

Figura 3.14 Acciones de la librería de hilos (N, R, B indican en ejecución, listo y bloqueado).

El hilo h2 está en el estado listo en la figura 3.14a), por lo que su TCB contiene el código R. El
hilo h3 espera una acción de sincronización por h1, por lo que está en estado bloqueado. Su TCB
contiene el código B y h1 para señalar que espera un evento que es una acción de sincronización
por h1. La figura 3.14b) muestra la situación cuando el kernel despacha a Pi y cambia su estado a
en ejecución.
La biblioteca del hilo traslapa la operación de los hilos usando al temporizador. Cuando el hilo
h1 fue “planificado”, habrá pedido una interrupción después de un intervalo pequeño de tiempo.

04 MAQ. CAP. 03(F0694).indd 112 8/10/07 12:54:50 AM


3.4 Los hilos 113

Cuando ocurre la interrupción del temporizador, asume el control a través de la rutina de manejo de
eventos del kernel para las interrupciones del temporizador y se decide a priorizar h1. Así, salva el
estado del CPU en el TCB de h1 y “programa” a h2. Por tanto, los códigos de estado en los TCB
de h1 y h2 cambian a R y N, respectivamente (figura 3.14c)). Observe que la planificación de hilos
realizada por la biblioteca del hilo es invisible para el kernel. A través de estos acontecimientos, el
kernel ve al proceso Pi en el estado en ejecución.
Un hilo del usuario no deberá hacer una llamada de sistema de bloqueo; sin embargo, veamos
qué pasaría si el h2 hiciera una llamada de sistema para iniciar una operación de E/S en el dispo-
sitivo d2, que es una llamada bloqueadora de sistema. El kernel cambiará el estado de proceso Pi
a bloqueado y observará que está bloqueado debido a una operación de E/S en el dispositivo d2
(figura 3.14d)). En alguna ocasión después de que la operación de E/S se complete, el kernel
planificará el proceso Pi y la operación de h2 se reanudará. ¡Observe que el código de estado en
el TCB de h2 permanece como N, lo que implica al estado en ejecución, todo a través de su ope-
ración de E/S!

Ventajas y desventajas de los hilos en el nivel del usuario La biblioteca del hilo imple-
menta la sincronización y la planificación de los hilos. Este arreglo evita la sobrecarga de una
llamada de sistema para la comunicación y la sincronización entre hilos, por lo que la sobrecarga
de la conmutación de hilos es más pequeña que en los hilos en el nivel del kernel. Este arreglo
también le permite a cada proceso usar una política de planificación que se ajuste mejor a su
naturaleza. Un proceso que implemente una aplicación de tiempo real puede usar la planifica-
ción basada en prioridades de sus hilos para encontrar sus requisitos de respuesta, mientras que
un proceso que implemente a un servidor multihilos puede realizar una planificación round-
robin de sus hilos.
El manejo de los hilos sin involucrar al kernel también tiene algunas desventajas. Primera,
que el kernel no sabe la diferencia entre un hilo y un proceso, por lo que si un hilo se bloqueara
en una llamada de sistema, el kernel bloquearía su proceso padre. En efecto, todos los hilos del
proceso se bloquearían hasta que la causa del bloqueo se retirara: en la figura 3.14d) del ejem-
plo 3.6, el hilo h1 no puede ser planificado aunque esté en el estado listo porque el hilo h2 hizo
una llamada bloqueadora de sistema. Por tanto, los hilos no deben hacer llamadas de sistema
que pueden inducir al bloqueo. Para facilitar esto, un sistema operativo tendrá que tener dispo-
nible una versión no bloqueadora de cada llamada de sistema, pues de otra manera induciría al
bloqueo de un proceso. En segundo lugar, como el kernel planifica un proceso y la biblioteca
del hilo planifica los hilos dentro de un proceso, a lo sumo un hilo de un proceso puede estar en
operación en cualquier momento. Así, los hilos en el nivel del usuario no pueden proveer para-
lelismo (véase la sección 3.2.2) y la concurrencia prevista por ellos está seriamente deteriorada
si un hilo hace una llamada de sistema que induzca al bloqueo.

3.4.3 Modelos de hilos híbridos

Un modelo de hilo híbrido tiene ambos hilos en el nivel del usuario y en el nivel del kernel, y un
método de asociar unos hilos con otros. Los métodos diferentes para realizar lo anterior proveen
combinaciones diferentes de la sobrecarga de baja conmutación de los hilos en el nivel del usua-
rio, y el paralelismo y la concurrencia altas de los hilos en el nivel del kernel. A continuación
describimos tres métodos de este tipo y sus propiedades.

04 MAQ. CAP. 03(F0694).indd 113 8/10/07 12:54:50 AM


114 CAPÍTULO 3 Los procesos y los hilos

PCB PCB PCB

TCB TCB TCB

KTCB KTCB KTCB

a) b) c)

Figura 3.15 Asociaciones de a) muchos a uno, b) uno a uno, c) muchos a muchos en los hilos híbridos.

La figura 3.15 ilustra los métodos de asociación de los hilos en el nivel del usuario con
los hilos en el nivel del kernel. La biblioteca del hilo crea hilos en el nivel del usuario en un
proceso y asocia un bloque de control del hilo (TCB) con cada hilo en el nivel del usuario. El
kernel crea hilos en el nivel del kernel en un proceso y asocia un bloque de control del hilo
del kernel (KTCB) con cada hilo en el nivel del kernel. En el método de asociación muchos
a uno, un solo hilo en el nivel del kernel es creado en cada proceso por el kernel y todos los
hilos en el nivel del usuario creados en un proceso por la biblioteca del hilo son asociados con
este hilo en el nivel del kernel. Este método de asociación provee un efecto parecido a los sim-
ples hilos en el nivel del usuario: éstos pueden ser concurrentes sin ser paralelos, el intercam-
bio de hilos incurre en sobrecarga baja y el bloqueo de un hilo en el nivel del usuario induce
al bloqueo de todos los hilos durante el proceso.
En el método de asociación uno a uno, cada hilo en el nivel del usuario se mapea per-
manentemente en un hilo en el nivel del kernel. Esta asociación provee un efecto parecido a
simples hilos en el nivel del kernel: los hilos pueden operar en paralelo en CPU diferentes de
un sistema de multiproceso; sin embargo, la conmutación entre hilos se realiza en el nivel del
kernel e incurre en una sobrecarga alta. El bloqueo de un hilo en el nivel del usuario no bloquea
otros hilos en el nivel del usuario del proceso porque se mapean en hilos diferentes en el nivel
del kernel.
El método de asociación de muchos a muchos produce un efecto en el cual un hilo en el
nivel del usuario puede mapearse en cualquier hilo en el nivel del kernel. Así, es posible lograr
el paralelismo entre hilos en el nivel del usuario mapeándolos en diferentes hilos en el nivel del
kernel, pero realizan la conmutación entre los hilos en el nivel del usuario en el mismo hilo en
el nivel del kernel sin incurrir en una sobrecarga alta. Asimismo, el bloqueo de un hilo en el nivel
del usuario no bloquea a otros hilos en el nivel del usuario del proceso que se mapean en un hilo
en el nivel del kernel diferente. Este método requiere una implementación complicada. Analiza-
remos sus detalles cuando estudiemos el modelo del hilo híbrido usado en el sistema operativo
Sun Solaris en la sección 3.5.2.

04 MAQ. CAP. 03(F0694).indd 114 8/10/07 12:54:51 AM


3.5 Estudios de casos de procesos y de hilos 115

3.5 ESTUDIOS DE CASOS DE PROCESOS Y DE HILOS

3.5.1 Procesos en Unix


Las estructuras de datos Unix usa dos estructuras para mantener los datos de control
acerca de los procesos:

• El área u (que significa “el área del usuario”).


• La estructura proc.
Estas estructuras de datos mantienen conjuntamente información análoga a la estructura de datos
del PCB analizada en la sección 3.3. La estructura proc conserva principalmente datos relacio-
nados con la planificación mientras que el área u contiene datos relacionados con la asignación
de recursos y el manejo de señales. La estructura proc de un proceso siempre se mantiene en la
memoria. El área u de memoria necesita estar en memoria sólo cuando el proceso se ejecuta.
La tabla 3.10 describe campos importantes de la estructura proc y del área u.

Tabla 3.10 Campos de la estructura proc y del área u en Unix

estructura proc
• id del proceso.
• Estado del proceso.
• Prioridad.
• Apuntadores a otras estructuras proc.
• Máscara de manejo de señales.
• Información de la administración de memoria.
área u
• Bloqueo del control de procesos: para un proceso bloqueado este campo alma-
cena el estado del CPU.
• Apuntador a la estructura proc.
• id del usuario y del grupo.
• Información relativa a los manipuladores de señales para el proceso.
• Información relativa a todos los archivos abiertos y al directorio actual.
• Terminal adherida al proceso si hay alguna.
• Información de uso del CPU.

Los tipos de procesos Existen tres tipos de procesos en Unix: los del usuario, los del dae-
mon y los del kernel.
Los procesos del usuario ejecutan computaciones del usuario. Un proceso del usuario se
asocia con la terminal del usuario. Cuando un usuario inicia un programa, el kernel crea un
proceso principal, lo cual a su vez puede crear otros procesos. Así, la ejecución de un programa
conduce a un árbol de procesos del usuario. Éstos tienen una relación de niño a padre entre ellos
y pueden coordinar sus actividades entre sí. En ese sentido, se ejecutan de una manera densa-
mente integrada y las vidas útiles están relacionadas.
Los procesos del daemon realizan funciones en una base ancha del sistema. Éstas pueden ser
de una clase auxiliar, pero son vitales para el control del ambiente computacional del sistema.

04 MAQ. CAP. 03(F0694).indd 115 8/10/07 12:54:51 AM


116 CAPÍTULO 3 Los procesos y los hilos

Los ejemplos típicos de estas funciones son la operación simultánea de la impresora en línea y la
administración de red. Una vez creados, los procesos del daemon pueden existir durante la vida
útil del sistema operativo.
Los procesos del kernel ejecutan el código del kernel. Tienen que ver con actividades de
fondo del kernel, como la conmutación. Difieren de los procesos del daemon en dos aspectos:
son creados automáticamente cuando el sistema es arrancado y pueden invocar las funcionali-
dades del kernel o referirse a las estructuras de datos de éste sin tener que realizar una llamada
de sistema.

La creación y la terminación de procesos Unix acepta que un proceso del usuario cree
los procesos hijo y que sincronice sus actividades con respecto a ellos. Estas características son
análogas a las analizadas en la sección 3.3.6. Describimos algunos detalles pertinentes a conti-
nuación.
La llamada de sistema fork crea un proceso hijo y establece su ambiente (llamado el con-
texto en el nivel del usuario en la literatura Unix). Asigna una estructura proc al proceso recién
creado y marca su estado como listo; también ubica un área u al proceso. fork devuelve el id del
proceso hijo a su creador, es decir, a su proceso padre. Los procesos hijo y padre tienen ambien-
tes idénticos; por tanto, los datos y los archivos pueden compartirse directamente. Un proceso
hijo puede crear sus propios procesos hijo, conduciendo así a un árbol de procesos. El kernel
rastrea las relaciones padre-hijo usando la estructura proc.
El contexto en el nivel del usuario del proceso hijo es una copia del contexto en el nivel del
usuario del padre. Por tanto, el proceso hijo ejecuta el mismo código del padre. En la creación,
el contador del programa del proceso hijo se coloca para que contenga la dirección de la instruc-
ción a la cual regresa la llamada del fork. El contador del programa del proceso padre también
contiene la misma dirección cuando regresa la llamada del fork. La única diferencia entre los
procesos padre e hijo es que el fork del proceso padre devuelve el id de proceso del proceso hijo,
mientras que el proceso hijo devuelve un 0.
Un proceso hijo puede ejecutar el mismo programa que su padre u otro usando la familia
exec de llamadas de sistema. Una llamada exec toma el nombre de un archivo como parámetro.
Se espera que este archivo contenga el programa que debe ser ejecutado por el proceso. El
kernel carga el código del programa en el ambiente del proceso que realizó la llamada exec.
Aunque este arreglo es engorroso, tiene la ventaja de la flexibilidad, ya que un proceso hijo
cuenta con la opción de ejecutar el código del padre en el ambiente del padre o de escoger su
propio programa para la ejecución. La alternativa anterior se usó en los sistemas Unix antiguos
para establecer servidores que pudieran dar servicio a muchas peticiones de los usuarios con-
currentemente.
La vista completa de la creación y terminación de procesos en Unix es la siguiente: des-
pués de arrancar, el sistema crea un init de proceso. Este proceso crea un proceso hijo para cada
terminal conectada al sistema. Después de una secuencia de llamadas exec, cada proceso hijo
comienza a correr el shell de login. Cuando un programador indica el nombre de un archivo de
la línea de comando, el shell forma un nuevo proceso que ejecuta una llamada exec para el ar-
chivo nombrado, que se convierte de hecho en el proceso principal del programa. Así, el proceso
principal es un hijo del proceso del shell. Entonces éste ejecuta una llamada de sistema wait para
esperar el final del proceso principal del programa. En ese momento se bloquea hasta que el
programa termina y se activa otra vez para aceptar la siguiente orden del usuario. Si un proceso
shell realiza una llamada de exit para terminarse a sí mismo, init crea un nuevo proceso para que
la terminal ejecute el shell del login.

04 MAQ. CAP. 03(F0694).indd 116 8/10/07 12:54:52 AM


3.5 Estudios de casos de procesos y de hilos 117

Un proceso Pi puede terminarse a sí mismo a través de la llamada de sistema de la salida

exit (status_code);

donde status_code es un código que indica el estatus de terminación del proceso. Al recibir la
llamada exit, el kernel cierra todos los archivos abiertos del proceso, libera la memoria asignada
y destruye el área u del proceso. Sin embargo, no destruye la estructura proc; ésta se retiene
hasta que el padre de Pi la destruye. El código de estatus se salva en la estructura proc de Pi. De
esta manera, el padre de Pi puede indagar su estatus de terminación en cualquier momento.
En esencia, el proceso terminado está muerto pero existe. Se llama un proceso zombi.
La llamada exit (salida) también le envía una señal al padre de Pi, lo cual puede ser igno-
rado por éste (abundaremos acerca de ello más adelante). Los procesos hijo de Pi se convierten
en hijos del proceso del kernel init. De esta manera, init recibe una señal cuando un hijo de Pi,
digamos Pc, termina a fin de que pueda liberar la estructura proc de Pc.

En espera de la terminación de proceso Un proceso Pi puede esperar la terminación de


un proceso hijo a través de la llamada de sistema

wait (addr(...));

donde addr(...) es la dirección de una variable dentro del espacio de la dirección de Pi. Si el pro-
ceso Pi tiene procesos hijo y al menos uno de ellos ya ha terminado, la llamada wait almacena el
estatus de terminación de un proceso hijo terminado en xyz e inmediatamente regresa con el id
del proceso hijo terminado. Si existen más procesos hijo terminados, su estatus de terminación
se hará disponible a Pi sólo cuando se repita la llamada wait (de espera). El proceso Pi entonces
puede tomar una acción apropiada. El estado del proceso Pi se cambia a bloqueado si tiene hijos
pero ninguno de ellos ha terminado. Será desbloqueado cuando termine uno de los procesos hijo.
La llamada wait (de espera) regresa con un “l” si Pi no tiene hijos. El ejemplo 3.7 ilustra las
ventajas de esta semántica de la llamada de espera.

Ejemplo 3.7 La figura 3.16 muestra un proceso que crea tres procesos hijo en el lazo for y espera
su terminación. Observe que la llamada fork devuelve el id del proceso hijo recién creado en el
proceso de llamado, pero devuelve un 0 en el proceso hijo. Debido a esta peculiaridad, los procesos
hijo ejecutan el código en la declaración if mientras el proceso padre omite la declaración if y
ejecuta un wait (una espera) en el bucle while. La espera se satisface cada vez que un proceso hijo
termina al ejecutar la declaración exit (salida).
Sin embargo, el proceso padre desea esperar a que el último proceso termine, por lo que emite
otra espera (wait) si el valor devuelto es diferente de 1. La cuarta llamada de espera (wait) re-
gresa con un 1, que saca al proceso padre del lazo. El código de proceso del padre no contiene una
llamada explícita de la salida exit( ). El compilador del lenguaje automáticamente sumará esto al
final de main( ).

Interrupción del procesamiento Unix usa la noción del nivel de prioridad de interrupción
(ipl) para evitar interrupciones durante las acciones sensibles en el nivel del kernel. Este enfoque
ayuda a eliminar las inconsistencias de las estructuras de datos del kernel de la siguiente manera:
a cada interrupción se le asigna un nivel de prioridad de interrupción. Dependiendo del progra-
ma que esté ejecutando el CPU, también se asocia un nivel de prioridad de interrupción con el
CPU. Cuando surge una interrupción en el nivel l de prioridad, se le maneja sólo si l es mayor

04 MAQ. CAP. 03(F0694).indd 117 8/10/07 12:54:52 AM


118 CAPÍTULO 3 Los procesos y los hilos

main()
{
int saved status;
for (i = 0; i < 3; i++)
{
if (fork() == 0)
{ /* código de los procesos hijo */

exit();
}
}
while(wait(&saved status) != -1);
/* repetir hasta que terminen todos los procesos hijo */
}

Figura 3.16 Creación y terminación de un proceso en Unix.

que el nivel de prioridad de interrupción del CPU; de otra manera, se mantiene pendiente
hasta que el nivel de prioridad de interrupción del CPU se haga < l. El kernel levanta el ipl del
CPU a un valor alto antes de comenzar a actualizar sus estructuras de datos y lo baja sólo después
de que la actualización se completa. La acción de cambiar el valor de ipl ciertamente constituye
sobrecarga; sin embargo, este precio tiene que pagarse para garantizar la consistencia de las es-
tructuras de datos del kernel.

Las llamadas de sistema Cada llamada de sistema acepta los parámetros pertinentes para
su ejecución. Cuando una llamada ocurre, estos parámetros existen en la pila del usuario del pro-
ceso que emite la llamada de sistema. Se espera que el número de la llamada del sistema esté en
el registro 0 del CPU cuando la llamada está hecha. El manipulador de llamada de sistema obtie-
ne este número para determinar cuál funcionalidad del sistema se está invocando. De sus tablas
internas, aquél conoce la dirección del manipulador para esta funcionalidad. También conoce el
número de parámetros que esta llamada debe tomar. Sin embargo, estos parámetros existen en
la pila del usuario, lo cual es una parte del contexto de proceso del proceso que hace la llamada.
Así, antes de pasar el control al manipulador para la llamada específica, estos parámetros se co-
pian de la pila del proceso a algún lugar estándar en el área u del proceso. Esto simplifica la ope-
ración de los manipuladores individuales de eventos.

Las señales El concepto de señal se relata detalladamente en la sección 3.6.4. En Unix, un


proceso puede ignorar una señal, especificar un manipulador de la señal para realizar acciones de
su elección cuando se le envía una señal o dejar al sistema operativo tomar una acción por omi-
sión, como producir una descarga de núcleo o terminar el proceso. Empezaremos por analizar
cómo un proceso Unix realiza las siguientes acciones:

04 MAQ. CAP. 03(F0694).indd 118 8/10/07 12:54:52 AM


3.5 Estudios de casos de procesos y de hilos 119

• Enviar una señal a otro proceso.


• Especificar un manipulador de la señal para una señal.

Una señal puede ser enviada a un proceso o a un grupo de procesos dentro del mismo grupo
al que pertenezca el proceso que emite. Esto es realizado por la llamada de sistema kill

kill (<pid>, <signum>)

donde <pid> es un valor entero que puede ser positivo, cero o negativo.
Un valor positivo de <pid> es el id de un proceso al cual la señal debe ser enviada. Un valor
0 de <pid> significa que la señal debe ser enviada a algunos procesos dentro del mismo árbol
de proceso que el proceso que emite, es decir, algunos procesos que comparten a un antepasado
con el proceso que emite. Esta característica se implementa como sigue: en una llamada fork,
al proceso recién creado se le asigna un id de grupo que es el mismo que el número del grupo de
procesos de su proceso padre. Un proceso puede cambiar su número de grupo usando la llamada
de sistema setpgrp. Así, en cualquier momento, algunos procesos en el mismo árbol de proceso
al que pertenece aquel que emite la señal pueden tener el mismo número del grupo. Cuando
<pid> = 0, se envía una señal a todos estos procesos.
Una señal enviada con <pid> = 1 pretende alcanzar procesos fuera del árbol de proceso del
proceso que emite. Esta característica puede usarse para difundir una señal para todos los proce-
sos en el sistema. No la explicaremos en detalle aquí.
Un proceso especifica un manipulador de la señal al ejecutar la declaración

oldfunction = signal (<signum>, <function>)

donde signal es una función en la biblioteca en C que hace una llamada de sistema signal, <sig-
num> es un entero y <function> es el nombre de una función dentro del espacio de la dirección
del proceso. Esta llamada especifica que la función <function> deberá ser ejecutada al ocurrir
la señal <signum>. La llamada signal regresa con la acción previa especificada para la señal
<signum>. Un usuario puede especificar SIG_DFL como <function> para señalar que la acción
por omisión definida en el kernel debe ser ejecutada al ocurrir la señal, o especificar SIG_IGN
como <function> para señalar que la ocurrencia de la señal debe ignorarse.
El kernel usa el área u de un proceso para anotar las acciones del manejo de la señal especi-
ficadas por él, y un conjunto de bits en la estructura proc para registrar la ocurrencia de señales.
Cada vez que una señal es enviada a un proceso, el bit correspondiente a la señal se iguala a 1
en la estructura proc del proceso de destino. El kernel entonces determina si la señal está siendo
ignorada por el proceso de destino. En caso contrario, hace provisión para mandar la señal al
proceso. Una señal ignorada permanece pendiente y es entregada cuando el proceso especifica su
interés en recibir la señal (particularizando una acción o especificando que la acción por omisión
deberá ser usada por él). En Unix, una señal permanece pendiente si el proceso al cual está diri-
gida se encuentra en estado bloqueado. La señal será entregada cuando el proceso salga de ese
estado. En general, el kernel inspecciona las señales pendientes en los siguientes casos:

• Cuando un proceso regresa de una llamada de sistema o de una interrupción.


• Después de que un proceso queda desbloqueado.
• Antes de que un proceso se bloquee en un evento.

04 MAQ. CAP. 03(F0694).indd 119 8/10/07 12:54:53 AM


120 CAPÍTULO 3 Los procesos y los hilos

La invocación de la acción de procesamiento de señales se implementa de una manera


interesante. Al conocer la señal que debe entregarse al proceso, el kernel determina la direc-
ción de la acción correspondiente del manejo de señales especificada por el proceso. Entonces
cambia la pila del usuario del proceso y el estado del CPU asociada con el proceso para que
parezca como si éste realmente hubiera invocado la acción de manejo de la señal como una
función. Estos cambios involucran insertar el valor en el contador del programa (PC) del
estado del proceso en la pila del usuario y hacerlo parecerse a una dirección de retorno para
una llamada de función, poniendo la dirección de la acción del manejo de la señal en el com-
ponente del contador del programa del estado de proceso. El kernel también hace provisión,
de modo que al regresar de esta llamada de función, el CPU será puesto en el estado en que
existía cuando la señal ocurrió. Después de hacer estos cambios, el kernel devuelve el control
al proceso del usuario.
Debido a los cambios en la pila del usuario y al estado del CPU, el proceso entonces eje-
cutará la acción del manejo de la señal. Si el proceso no está en ejecución cuando la señal ocu-
rre, estas acciones tendrán lugar la siguiente vez que se planifique para la ejecución. Al final
del procesamiento de las señales, el proceso deberá regresar al punto en el cual se interrumpió
para entregar la señal. Sin embargo, como se explica a continuación, no siempre hace eso.
Existen algunas anomalías en el modo como se manejan las señales. Si una señal ocurre de
manera repetida, el kernel simplemente repara en lo que ha ocurrido, pero no cuenta el número
de sus ocurrencias. Consecuentemente, el manipulador de la señal puede ser ejecutado una o
varias veces, dependiendo del momento en que el proceso queda programado para ejecutar el
manipulador de la señal. Otra anomalía está relacionada con una señal enviada a un proceso
que se bloqueó en una llamada de sistema. Después de ejecutar el manipulador de la señal, este
proceso no reanuda su ejecución de la llamada de sistema. En lugar de eso, regresa de la llamada
de sistema. Si es necesario, tendrá que repetir ésta.
La tabla 3.11 enlista algunas señales interesantes de Unix. Observe que éstas pueden
surgir en forma asíncrona de fuentes fuera de un proceso, o en forma síncrona como resulta-
do de la ejecución del proceso mismo. Señales como la falla de segmentación, la instrucción
ilegal y la llamada ilegal de sistema que aparecen en la tabla 3.11 pertenecen a esta última
categoría.

Estados del proceso y transiciones de estado Hay una diferencia conceptual entre el mo-
delo de proceso descrito en la sección 3.3.3 y el que se usa en Unix. En el modelo de la sección
3.3.3, un proceso en el estado en ejecución se pone en el estado listo en el momento en que su
ejecución se interrumpe. Luego un proceso de sistema maneja el evento que causó la interrup-
ción. Si el proceso en ejecución hubiera causado por sí mismo una interrupción de software al
ejecutar un <SI_instrn>, su estado puede cambiar más adelante a bloqueado cuando su petición
no puede ser concedida inmediatamente. En este modelo, un proceso del usuario ejecuta sólo
código del usuario; no necesita ningún privilegio especial. Se usa un proceso de sistema para
manejar llamadas de sistema porque las instrucciones privilegiadas, como la iniciación de E/S y
el establecimiento de información de protección de la memoria, podrán ejecutarse. Por tanto, el
proceso de sistema se ejecuta con el CPU en el modo privilegiado.
Los procesos se comportan de manera diferente en el modelo Unix. Cuando un proceso hace
una llamada de sistema, el proceso mismo procede a ejecutar el código del kernel destinado a
manejarla. Para asegurar que tiene los privilegios necesarios, requiere ejecutarse en un modo
especial llamado modo del kernel. Al ejecutarse así, el CPU está en el modo privilegiado de

04 MAQ. CAP. 03(F0694).indd 120 8/10/07 12:54:53 AM


3.5 Estudios de casos de procesos y de hilos 121

Tabla 3.11 Señales interesantes de Unix

Señal Descripción
SIGCHLD el proceso hijo murió o fue
suspendido
SIGFPE falla aritmética
SIGILL instrucción ilegal
SIGINT interrupción tty (Control-C)
SIGKILL proceso kill
SIGSEGV falla de segmentación
SIGSYS llamada del sistema inválida
SIGXCPU se sobrepasa el límite de
tiempo del CPU
SIGXFSZ se sobrepasa el límite del
tamaño de archivo

operación. Entonces es necesario un cambio de modo cada vez que se hace una llamada de sis-
tema. El cambio de modo opuesto ocurre después de procesar una llamada de sistema. Suceden
cambios de modo similares cuando un proceso comienza a ejecutar el código de procesamiento
de interrupción en el kernel debido a una interrupción, y cuando regresa después de procesarla.
Un proceso puede bloquearse al ejecutar el código del kernel. Esto puede ocurrir si hace
una llamada de sistema para iniciar una operación de E/S, o si realiza una petición que no pue-
de ser concedida inmediatamente. El kernel de Unix usa código reentrante para manejar tales
situaciones. El concepto de reentrante implica que muchos procesos deberán poder ejecutar el
mismo código concurrentemente. Si este no fuera el caso, un proceso que se bloquee a sí mismo
en el modo del kernel congelará el sistema entero hasta que quede desbloqueado y salga de él.
Para asegurar el código reentrante, un proceso que se ejecuta en el modo del kernel debe usar
su propia pila del kernel. La pila del kernel de un proceso tiene que diferenciarse de su pila del
usuario porque la mayoría de las arquitecturas de máquina determinan qué pila usar, basándose
en el bit de modo en la PSW. La pila del kernel contiene la historia de invocaciones de función
desde el momento en que el proceso entró en el modo del kernel. Si otro proceso también entra
ahí, la historia de sus invocaciones de función será mantenida en su propia pila del kernel.
Otra consecuencia del modelo de proceso Unix es que este sistema operativo usa dos estados
en ejecución bien definidos. Éstos se llaman en ejecución para el usuario y en ejecución para el
kernel. Una diferencia más al comparar con los estados descritos en la sección 3.3.3 es el estado
del zombi discutido anteriormente. Un proceso del usuario ejecuta el código del usuario mientras
está en el estado en ejecución para el usuario, y el código del kernel, mientras está en el estado
en ejecución para el kernel. Hace la transición de en ejecución para el usuario a en ejecución
para el kernel cuando realiza una llamada de sistema, o cuando ocurre una interrupción. Puede
bloquearse mientras esté en el estado en ejecución para el kernel debido a una operación de E/S

04 MAQ. CAP. 03(F0694).indd 121 8/10/07 12:54:53 AM


122 CAPÍTULO 3 Los procesos y los hilos

o porque el recurso no está disponible. Cuando la operación de E/S se completa o el recurso


de petición le es concedido, el proceso regresa al estado en ejecución para el kernel y termina
la ejecución del código del kernel que realizaba. Entonces deja el modo del kernel y regresa al
modo del usuario. Consecuentemente, su estado cambia de en ejecución para el kernel a de en
ejecución para el usuario.

En
ejecución
para el
usuario

retorno interrupción/llamada
del sistema

En
ejecución salida
Zombi
para el
kernel

despacho petición de recurso


o de E/S
priorización

Listo Bloqueado
concesión o
terminación de E/S

Figura 3.17 Transiciones de estado de proceso en Unix.

Debido a este arreglo, un proceso no se bloquea ni se prioriza en el estado en ejecución para


el usuario; primero hace una transición a en ejecución para el kernel y luego queda bloqueado
o priorizado. De hecho, en ejecución para el usuario → en ejecución para el kernel es la única
transición fuera del estado en ejecución para el usuario. La figura 3.17 ilustra los estados de
proceso y las transiciones de estado en Unix. Como se muestra aquí, aun la terminación de pro-
ceso ocurre cuando un proceso está en el estado en ejecución para el kernel. Esto ocurre porque
ejecuta la salida de llamada de sistema mientras está en el estado en ejecución para el usuario.
Esta llamada cambia su estado a en ejecución para el kernel. El proceso realmente termina y se
convierte en un proceso zombi como resultado de procesar esta llamada.
Los procesos en el estado en ejecución para el kernel son no interrumpibles en Unix. El
razonamiento es el siguiente: en el modelo convencional de proceso analizado en la sección

04 MAQ. CAP. 03(F0694).indd 122 8/10/07 12:54:54 AM


3.5 Estudios de casos de procesos y de hilos 123

3.3.3, el procesamiento de la interrupción y el manejo de los eventos son realizados por el


kernel a través de los procesos del sistema. Tenemos que asegurarnos de que estas actividades
no se interrumpen en momentos inconvenientes debido a interrupciones adicionales, ya que
esto podría conducir a la incongruencia de estructuras de datos y a condiciones de carrera. Por
consiguiente, los sistemas operativos que usan el modelo convencional enmascaran todas las
interrupciones cuando el kernel está a punto de acceder o de actualizar algunos datos sensiti-
vos. En el modelo Unix el código del kernel es ejecutado por los procesos del mismo usuario
cuando están en el estado en ejecución para el kernel. En consecuencia, los procesos en este
estado se hacen no interrumpibles: el proceso no se interrumpe aun cuando expira su intervalo
de tiempo.
Esta característica no causa ninguna degradación de los tiempos de respuesta porque un
proceso que se ejecuta en el estado en ejecución para el kernel no consume mucho tiempo del
CPU: completa el procesamiento de la interrupción o la llamada de sistema que lo trajo al estado
en ejecución para el kernel y regresa al estado en ejecución para el usuario, o se bloquea. Este
bloqueo se hace cuidadosamente, de modo que no surjan problemas de incongruencia de datos
ni condiciones de carrera.

3.5.2 Los hilos en Solaris

Solaris, sistema operativo basado en Unix 5.4, usa tres clases de entidades para gobernar a la
concurrencia dentro de un proceso. Éstos son:

• Hilos del usuario: Los hilos del usuario comparten algunas propiedades con los hilos en
el nivel del usuario analizados en la sección 3.4.2; sin embargo, difieren de los hilos
en el nivel del usuario en otros aspectos. Los hilos del usuario son creados y maneja-
dos por una biblioteca de hilos y son invisibles para el kernel.
• Procesos ligeros: Un proceso ligero (LWP) es un intermediario entre los hilos del usuario
y los hilos del kernel. Un LWP es una unidad de paralelismo dentro de un proceso. Los
hilos del usuario se mapean en los LWP por la biblioteca de hilos. Este mapeo es análogo
al mapeo de hilos en el nivel del usuario en los procesos descritos en la sección 3.4.2.
Puede crearse más de un LWP para un proceso. El número de LWP para un proceso y la
naturaleza del mapeo entre los hilos del usuario y los LWP son decididos por el progra-
mador y se dan a conocer a la biblioteca de hilos a través de llamadas apropiadas de la
función.
• Hilos del kernel: Un hilo del kernel es un hilo creado por el kernel para el control de la
concurrencia. El kernel crea tantos hilos del kernel como LWP creados para todos los
procesos activos haya en el sistema y asocia un hilo de kernel con cada LWP. El kernel
también crea algunos hilos del kernel para su propio uso. Un buen ejemplo de esta clase
es un hilo para maniobrar las E/S de disco en el sistema.

La figura 3.18 ilustra un arreglo de hilos del usuario, varios LWP e hilos del kernel. Exis-
ten dos procesos Pi y Pj en el sistema. El proceso Pi ha creado tres hilos del usuario en aquél
y el proceso Pj ha creado cuatro hilos del usuario. Un LWP se crea para el proceso Pi mientras
tres LWP se crean para el proceso Pj. Los tres hilos del usuario del proceso Pi se mapean en
el mismo LWP, mientras que existe un mapeo complejo entre los cuatro hilos del usuario del

04 MAQ. CAP. 03(F0694).indd 123 8/10/07 12:54:54 AM


124 CAPÍTULO 3 Los procesos y los hilos

Hilos

Pi Pj
PCB PCB
Contexto
del proceso
+
biblioteca
de hilos Bloques de control de hilos
Mapeo ejecutado por
la biblioteca de hilos
Bloques de control de LWP

Bloques de control de
los hilos del kernel

Programador
KTCB
seleccionado

Figura 3.18 Hilos en Solaris.

proceso Pj y los tres LWP creados para él. Un hilo del usuario se mapea exclusivamente en un
LWP. Los otros LWP son compartidos entre los tres hilos restantes del usuario.
El kernel asigna un bloque de control LWP para cada LWP. Un hilo del kernel se crea para
cada LWP y se asocia exclusivamente con él. Algunos hilos de kernel adicionales se crean
para los propósitos descritos anteriormente. El kernel asigna un bloque de control de hilo del
kernel (KTCB) a cada hilo del kernel. El programador selecciona un KTCB correspondiente
a un hilo del kernel en el estado listo. El despachador despacha el hilo del kernel correspon-
diente a este KTCB. De hecho, el LWP correspondiente a este hilo del kernel es despachado.
La biblioteca de hilos puede conmutar entre los hilos del usuario mapeados en este LWP. En
un sistema operativo del multiprocesador, el programador selecciona un KTCB para cada CPU
en el sistema.
El arreglo Solaris, consistente en hilos en el nivel del usuario, LWP e hilos del kernel,
provee la concurrencia entre los hilos en el nivel del usuario y, en un sistema del multiproce-
sador, proporciona paralelismo entre los LWP. La concurrencia es provista por la biblioteca de
hilos. El paralelismo es proporcionado a través de LWP; sin embargo, está bajo control del pro-
gramador porque éste decide cuántos LWP deberán crearse para un proceso. Así, si un programa-
dor crea dos LWP en un proceso, existirá un paralelismo de 2 vías durante el mismo.
Un programador puede crear n LWP para obtener una concurrencia de n-maneras. Un valor
de n en el rango 1 ≤ n ≤ p, donde p es el número de CPU existentes, tiene sentido. Sin embargo,
¿es significativo un valor de n > p? La respuesta depende de las intenciones del programador.
1 ≤ n ≤ p puede proveer un paralelismo de n-maneras, ya que cada LWP puede ejecutarse en un

04 MAQ. CAP. 03(F0694).indd 124 8/10/07 12:54:54 AM


3.5 Estudios de casos de procesos y de hilos 125

procesador al mismo tiempo. n > p no puede proveer un paralelismo de n-maneras; sin embargo,
la concurrencia provista por él puede ser muy valiosa: si un LWP de un proceso es bloqueado
(es decir, si todos los hilos mapeados en el LWP son bloqueados), otro LWP del mismo proceso
puede ejecutarse en un procesador.
Debido al uso de LWP, Solaris provee una simplificación de los hilos en el nivel del usuario.
Permite que un hilo del usuario haga una llamada de bloqueo. Ésta bloqueará al LWP con el
cual el hilo es asociado. Sin embargo, otros hilos del usuario podrán ejecutarse en otros LWP.
De esta manera, el bloqueo de un hilo del usuario no necesariamente bloquea el proceso al cual
pertenece. El diseño de un programa se simplifica porque no es necesario hacer ningún esfuerzo
especial para eliminar el bloqueo de los hilos del usuario.
Se usa un arreglo complicado de los bloques de control para controlar la conmutación entre
los hilos del kernel. El bloque de control de los hilos del kernel contiene el apuntador del esta-
do del CPU y de la pila, la prioridad, la información de la planificación y un apuntador para el
siguiente KTCB en una cola de planificación. Además, contiene un apuntador para el bloque
de control LWP y para la PCB del proceso al cual pertenece el LWP. El bloque de control del
LWP contiene valores salvados de los registros del usuario del CPU, la información del manejo
de la señal y el apuntador para el PCB del proceso del dueño.
El arreglo del manejo de la señal es más bien interesante. Todos los LWP de un proceso
comparten manipuladores comunes de la señal. Sin embargo, cada uno tiene su propia máscara
de la señal que determina qué señales deberán entregársele y cuáles ignorarse. Además, la biblio-
teca de hilos mantiene un bloque de control para cada hilo del usuario. La información en este
bloque de control es similar a la descrita en la sección 3.4.2.
Solaris ejecuta la planificación en dos niveles. En el nivel inferior, una biblioteca de hilos
“planifica” los hilos de los usuarios para ejecutarse en un LWP. Esta planificación es análoga a la
planificación de los hilos en el nivel del usuario para ejecutarse en un proceso (véase la sección
3.4.2). Los LWP se asocian exclusivamente con los hilos del kernel; por tanto, no son programa-
dos explícitamente.
En el nivel más alto de planificación, el kernel programa los hilos del kernel para ejecutarse
en los CPU. Antes de despachar un hilo específico del kernel, tiene que encontrar el proceso al
cual pertenece el LWP asociado con el hilo del kernel. El ambiente de proceso del proceso tiene
que ser puesto al alcance antes de despachar el hilo del kernel. De modo semejante, mientras
conmuta entre los hilos del kernel, el kernel tiene que encontrar si el hilo del kernel que va a ser
despachado pertenece al mismo proceso que el que se ejecutaba. En caso de que no sea así, tiene
que realizar la conmutación de los procesos guardando el ambiente del proceso al cual pertene-
cía el hilo del kernel en ejecución y cargando el ambiente del proceso al cual pertenece el hilo
seleccionado del kernel.

3.5.3 Los procesos y los hilos en Linux

Las estructuras de datos El kernel de Linux usa un descriptor de procesos, que es una es-
tructura de datos del tipo task_struct, para contener toda la información relacionada con un
proceso o con un hilo. Para un proceso, esta estructura de datos contiene el estado del proceso,
información acerca de los procesos padre e hijo, la terminal usada por el proceso, su directorio
actual, sus archivos abiertos, la memoria asignada a él, las señales y los manipuladores de la
señal. El kernel crea subestructuras para sustentar información relativa a la terminal, archivos

04 MAQ. CAP. 03(F0694).indd 125 8/10/07 12:54:55 AM


126 CAPÍTULO 3 Los procesos y los hilos

del directorio, memoria y señales, y pone los apuntadores hacia ellos en el descriptor de proceso.
Esta organización guarda tanto la memoria como la sobrecarga cuando se crea un hilo.

La creación y la terminación de procesos y de hilos Linux admite las llamadas de sistema


fork y vfork cuyas funcionalidades son idénticas a las correspondientes llamadas de Unix. Estas
funcionalidades son de hecho implementadas por la llamada clone de sistema que está oculto
a la vista de los programas. Ambos procesos e hilos son creados así, la única diferencia está
en las banderas pasadas a la llamada clone como un parámetro, lo cual analizaremos más ade-
lante. Linux trata los procesos e hilos del mismo modo para propósitos de planificación; efecti-
vamente, los hilos Linux son hilos en el nivel del kernel.
La llamada de sistema clone toma cuatro parámetros: la dirección del inicio del proceso o
el hilo, los parámetros que se le deben pasar, las banderas y una especificación de la pila del hijo.
Algunas de las banderas importantes son:

CLONE_VM : Comparte la información de gestión de la memoria usa-


da por el MMU.
CLONE_FS : Comparte la información acerca del directorio raíz y del
directorio de trabajo actual.
CLONE_FILES : Comparte la información acerca de archivos abiertos.
CLON_SIGHAND : Comparte la información acerca de señales y manipula-
dores de la señal.

La organización de task_struct facilita el uso compartido selectivo de esta información,


ya que simplemente contiene apuntadores para las subestructuras donde se guarda la informa-
ción real. En una llamada a clone, el kernel hace una copia de task_struct en la cual se copian
algunos de estos apuntadores y los otros se cambian. Un hilo es creado por la llamada a clone
con todas las banderas colocadas, de modo que el nuevo hilo comparte el espacio de la direc-
ción, los archivos y los manipuladores de la señal del padre. Se crea un proceso por la llamada
a clone con todas estas banderas puestas en ceros; el nuevo proceso no comparte ninguno de
estos componentes.
El kernel Linux 2.6 continúa admitiendo el modelo 1:1 para hacer los hilos (es decir, los
hilos en el nivel del kernel) y el método anterior para crear los procesos y los hilos. También
incluye el soporte para el Native Posix Threading Library (NPTL), que provee un número de me-
joras que benefician a las aplicaciones que tienen muchos hilos. Puede mantener hasta 2 billones
de hilos mientras que el kernel del Linux 2.4 pudo admitir sólo hasta 8 192 hilos por CPU. Ha
sido introducida una nueva llamada de sistema exit_group() para terminar un proceso y todos
sus hilos; puede terminar un proceso que tenga 100 000 hilos en cuestión de 2 segundos, en
comparación con los aproximadamente 15 minutos en el kernel de Linux 2.4. La manipulación
de señales se realiza en el espacio del kernel y se entrega una señal a uno de los hilos disponibles
en un proceso. Las señales de paro y de continuar afectan al proceso completo, mientras que
las señales fatales terminan el proceso completo. Estas características simplifican el manejo
de los procesos de multihilos. El kernel del Linux 2.6 también admite un mutex del espacio de
usuario rápido llamado futex que reduce la sobrecarga de sincronización del hilo a través de una
reducción en el número de llamadas del sistema.

04 MAQ. CAP. 03(F0694).indd 126 8/10/07 12:54:55 AM


3.5 Estudios de casos de procesos y de hilos 127

Las relaciones padre-hijo La información acerca de los procesos o los hilos de padre e hijo
se guarda en un task_struct para mantener conciencia del árbol del proceso. task_struct
contiene un apuntador para el padre y para el padre estimado, el cual es un proceso a quien de-
berá reportarse la terminación de este proceso si su proceso padre ha terminado, un apuntador
para el hijo menor, y los apuntadores para los hermanos menores y mayores de un proceso. Así,
el árbol de proceso de la figura 3.2 será representado como se muestra en la figura 3.19.

data logger

copy sample disk write housekeeping

Figura 3.19 Árbol de proceso de Linux para los procesos de la figura 3.2a).

Los estados del proceso El campo del estado de un descriptor de proceso contiene una
bandera que indica el estado de un proceso. Éste puede estar en uno de cinco estados en cualquier
momento:

TASK_RUNNING : El proceso se programa o espera ser planifi-


cado.
TASK_INTERRUPTIBLE : El proceso está dormido con un evento, pero
puede recibir una señal.
TASK_UNINTERRUPTIBLE : El proceso está dormido con un evento, pero
no puede recibir una señal.
TASK_STOPPED : La operación de un proceso ha estado blo-
queada por una señal.
TASK_ZOMBIE : El proceso ha sido completado, pero el pro-
ceso padre aún no ha emitido una llamada de
sistema de la familia wait (de espera) para
comprobar si ha terminado.

El estado TASK_RUNNNING le corresponde a uno de los estados en ejecución o listo descritos


en la sección 3.3.3. Los estados de TASK_INTERRUPTIBLE y TASK_UNINTERRUPTIBLE corres-
ponden ambos al estado bloqueado. La división del estado bloqueado en dos estados resuelve el
dilema afrontado por un sistema operativo al manipular las señales enviadas a un proceso en
el estado bloqueado (véase la sección 3.6.4): un proceso puede decidir si quiere ser activado por
una señal mientras espera que un evento ocurra, o si quiere que se difiera la entrega de una señal

04 MAQ. CAP. 03(F0694).indd 127 8/10/07 12:54:55 AM


128 CAPÍTULO 3 Los procesos y los hilos

hasta que salga del estado bloqueado. Un proceso entra en el estado TASK_STOPPED cuando
recibe una señal SIGSTOP o SIGTSTP para indicar que su ejecución debe detenerse, o una señal
SIGTTIN o SIGTTOU para señalar que un proceso de fondo requiere entrada o salida.

3.5.4 Los procesos y los hilos en Windows

El gusto por los procesos e hilos en Windows difiere algo de aquél presentado anteriormente
en este capítulo: Windows trata un proceso como una unidad para la asignación de recursos y
usa un hilo como una unidad para concurrencia. Consecuentemente, un proceso de Windows
no funciona por sí mismo; debe tener al menos un hilo dentro de él. El sistema operativo mantie-
ne una tabla de manejo para cada proceso en el cual almacena manipulaciones para los recursos.
Un proceso hereda algunas manipulaciones para los recursos de su padre y puede abrir recursos
nuevos cuando sea necesario; el sistema operativo añade sus manipulaciones a la tabla de mani-
pulaciones cuando una apertura tiene éxito.
Windows usa tres bloques de control para manejar un proceso. Cada proceso tiene un blo-
que de proceso ejecutivo. Contiene campos que almacenan la id del proceso, la información de
gestión de memoria, la dirección de la tabla de manipulaciones, un bloque de proceso del kernel
para el proceso y un bloque del ambiente de proceso. El bloque del proceso del kernel contiene
información de planificación para los hilos del proceso, tales como la afinidad del procesador
para el proceso, el estado del proceso y los apuntadores para los bloques del hilo del kernel de
sus hilos. El bloque de proceso ejecutivo y el bloque de proceso del kernel están situados en el
espacio de la dirección de sistema. El bloque del ambiente de proceso está situado en el espacio
de la dirección del usuario porque contiene información que es usada por el cargador —a fin de
cargar el código para ser ejecutado— y por el administrador del montículo.
Los bloques de control utilizados para operar un hilo contienen información acerca de su
operación y del proceso que lo contiene. El bloque del hilo ejecutivo incluye un bloque del hilo
del kernel, un apuntador para el bloque de proceso ejecutivo del proceso que contiene el
hilo e información de suplantación para el hilo. El bloque del hilo del kernel contiene infor-
mación acerca de la pila del kernel del hilo y del almacenamiento local del hilo, que planifica
información para el hilo, y un apuntador para su bloque del ambiente del hilo, que contiene su id
e información acerca de sus requisitos de sincronización.
Windows admite la noción de un trabajo como un método de manejo de un grupo de pro-
cesos. Un trabajo está representado por un objeto de trabajo, lo cual contiene información, tal
como manipuladores para los procesos que se realizan en él, el límite de tiempo de procesador
para el ancho del trabajo, el límite de tiempo de procesador por clase de proceso, la clase de la
planificación de trabajos que coloca el intervalo de tiempo para los procesos del trabajo, la afi-
nidad del procesador para los procesos del trabajo y la clase de prioridad. Un proceso puede ser
un miembro de sólo un trabajo; todos los procesos creados por él automáticamente forman parte
del mismo trabajo.

La creación de proceso El ejecutivo de Windows provee un modelo general del proceso y


de la creación del hilo en la cual el proceso emite una llamada create para un proceso o hilo que
no es necesariamente su padre: la llamada create lleva un manipulador al padre del nuevo pro-
ceso o hilo como un parámetro. Este servicio es usado por un proceso del servidor para realizar
la suplantación: crea un hilo en un proceso cliente a fin de que pueda tener acceso a los recursos
con los privilegios del cliente.

04 MAQ. CAP. 03(F0694).indd 128 8/10/07 12:54:56 AM


3.5 Estudios de casos de procesos y de hilos 129

La semántica de creación de proceso depende del subsistema del ambiente usado por un
proceso de aplicación. En los ambientes operativos Win/32 y OS/2, un proceso tiene un hilo en
él cuando es creado; no es así en otros ambientes admitidos por el sistema operativo Windows.
Por tanto, la creación de proceso es de hecho manipulada por un subsistema del ambiente DLL
que se enlaza con un proceso de aplicación. Después de la creación, pasa el id del nuevo proceso
o hilo al proceso de subsistema del ambiente a fin de que pueda manejar el nuevo proceso o hilo
apropiadamente.
La creación de un proceso hijo por un proceso de aplicación en el ambiente Win/32 procede
como sigue: el subsistema del ambiente DLL enlazado al proceso de aplicación hace una llama-
da de sistema para crear un nuevo proceso. Ésta es manejada por el ejecutivo. Crea un objeto de
proceso, lo inicializa cargando la imagen del código para ser ejecutada y devuelve un manipula-
dor al objeto de proceso. El subsistema del ambiente DLL hace una segunda llamada de sistema
para crear un hilo y pasa el manipulador al nuevo proceso como un parámetro. El ejecutivo crea
un hilo en el nuevo proceso y devuelve su manipulador. El DLL entonces envía un mensaje al
proceso de subsistema del ambiente, pasándole los manipuladores de proceso y de hilo, y el id de
su proceso padre. El proceso de subsistema del ambiente ingresa el manipulador de proceso en la
tabla de procesos que en ese momento existen en el ambiente e ingresa el manipulador del hilo en
las estructuras de datos de planificación. El control entonces regresa al proceso de aplicación.

En Despacho En
ejecu- Termi-
espera nado
ción
Seleccionar
para
ejecución

Espe-
Listo
rando

Pila del kernel Pila del kernel


intercambiada intercambiada
hacia dentro Transi- hacia fuera
ción

Figura 3.20 Transiciones de estado de los hilos en Windows.

Estados de los hilos y las transiciones de estado Un hilo puede estar en uno de los si-
guientes seis estados:

1. Listo: El hilo puede ser ejecutado si un CPU está disponible.


2. En espera: Éste es un hilo que ha sido seleccionado para correr enseguida con un proce-
sador específico. Si su prioridad es alta, el hilo que está corriendo con el procesador será
priorizado y este hilo será planificado.
3. En ejecución: Actualmente se asigna un CPU al hilo y el hilo está en operación.

04 MAQ. CAP. 03(F0694).indd 129 8/10/07 12:54:56 AM


130 CAPÍTULO 3 Los procesos y los hilos

4. Esperando: El hilo está esperando un recurso o acontecimiento, o ha sido suspendido por


el subsistema del ambiente.
5. Transición: La pila del kernel del hilo ha sido retirada de la memoria porque el hilo ha
estado esperando durante mucho tiempo. Entra en el estado listo cuando la pila del kernel
es traída de vuelta a la memoria.
6. Terminado: El hilo ha completado su operación.

La figura 3.20 muestra el diagrama de transición de estado para los hilos. Aquí se muestran
las causas de las transiciones solamente dentro y fuera de los estados de en espera y de transi-
ción. Las causas de otras transiciones son como se estudian en la sección 3.3.3.

3.6 PROCESOS INTERACTUANTES: UNA VISTA AVANZADA


DEL PROGRAMADOR DE LOS PROCESOS
Una aplicación puede usar procesos múltiples para obtener los beneficios de la aceleración del
cómputo y tiempos de respuesta mejorados (véase la tabla 3.2). Otra razón podría ser que el sis-
tema del mundo real al cual da servicio la aplicación puede tener varias actividades en marcha al
mismo tiempo. El ejemplo 3.8 ilustra este aspecto.

Ejemplo 3.8 Una aplicación de reservaciones de una aerolínea usa un número de terminales de
agente conectadas a un sistema central de cómputo. La computadora almacena los datos de manera
centralizada y permite a los agentes en todas las terminales de agentes acceder a estos datos en
tiempo real. La ejecución de la aplicación puede estar estructurada en forma de procesos múltiples,
con cada proceso dando servicio a una terminal de agente (véase la figura 3.21). Este arreglo le
permite a un agente en una terminal teclear los requisitos de un cliente mientras otros agentes tienen
acceso y actualizan los datos en nombre de otros clientes.

Datos de
las reservaciones

Terminales de agente
Figura 3.21 Un sistema de reservación de una aerolínea.

Los procesos de una aplicación interactúan entre sí para coordinar sus actividades o com-
partir algunos datos. La naturaleza de estas interacciones se analiza en las siguientes secciones.
Empezamos por definir el término procesos interactuantes usando la siguiente notación:
read_seti : conjunto de elementos de datos leídos por el proceso Pi
write_seti : conjunto de elementos de datos modificados por el proceso Pi
Aquí los datos incluyen los datos del programa así como mensajes de interproceso y señales que
se discuten en secciones posteriores. (Un mensaje o una señal enviada por el proceso Pi se in-
cluye en write_seti, y un mensaje o una señal recibida por éste se incluye en read_seti.)

04 MAQ. CAP. 03(F0694).indd 130 8/10/07 12:54:56 AM


3.6 Procesos interactuantes: una vista avanzada del programador de los procesos 131

Definición 3.4 (Procesos interactuantes) Los procesos Pi y Pj son procesos interactuantes


si read_seti 艚 write_setj ≠ ␾ o read_setj 艚 write_seti ≠ ␾.

Se dice que los procesos que no interactúan son procesos independientes.

Implementación de las interacciones de procesos En la tabla 3.3 se resumen los di-


ferentes tipos de interacciones de proceso. Éstas se realizan coordinando las actividades
de procesos entre sí. Un tema común en toda clase de interacciones de procesos es que un
proceso hace llamadas de sistema para señalar que deberá ser bloqueado y activado bajo cier-
tas condiciones. El kernel implementa el bloqueo o la activación de procesos a través de
los cambios de estado apropiados. Describimos los detalles de las interacciones de los pro-
cesos en la siguiente sección. El capítulo 9 describe las técnicas usadas en el diseño de los
procesos interactuantes.

3.6.1 Las condiciones de carrera y la sincronización


del acceso a los datos

Una aplicación puede constar de un conjunto de procesos que comparten algunos datos ds. La
sincronización del acceso a los datos involucra el bloqueo y la activación de estos procesos de
modo que comparten correctamente a ds. La necesidad de la sincronización del acceso a los da-
tos surge porque los accesos a los datos compartidos de una manera arbitraria pueden inducir a
resultados incorrectos en los procesos y también afectar la consistencia de los datos. Empezare-
mos por analizar estos problemas.
Sean los procesos Pi y Pj que realizan las operaciones ai y aj en ds. Sea ai una operación de
actualización que incrementa el valor de ds en 10, es decir:

ai : ds : = ds + 10;

Esta operación puede implementarse usando tres instrucciones de máquina. La primera instruc-
ción carga el valor de ds en un registro de datos, la segunda suma 10 al contenido del registro de
datos y la tercera almacena el contenido del registro de datos de vuelta en la posición asignada a
ds. Llamamos a esta secuencia de instrucciones la secuencia carga-suma-almacena.
Sea la operación aj una operación de copia simple que copia el valor de ds en otra posición.
Si aj se ejecuta antes de la primera instrucción de ai, obtendrá el valor de ds antes del comienzo
de ai, es decir, el valor “antiguo” de ds. Si aj es ejecutado después de la última instrucción de ai,
obtendrá el valor nuevo de ds. Sin embargo, uno no puede predecir si aj obtendrá el valor nuevo
o el viejo si es ejecutado mientras que el proceso Pi está ocupado en la ejecución de ai. Por sí
solo, esto no hace daño; sin embargo, puede conducir a situaciones de la siguiente clase: ¡El pro-
ceso Pj comienza a tomar una cierta acción porque ds tiene un determinado valor; sin embargo,
el valor de ds es diferente cuando Pj completa la acción! Esta situación puede ser considerada
inconsistente en ciertas aplicaciones.
Una situación dañina llamada condición de carrera puede surgir durante la ejecución de
procesos concurrentes. (Este término se usa en la electrónica cuando los intentos de examinar
un valor mientras cambia, o de hacer mediciones en una forma de onda cambiante, conducen a
resultados equivocados.) Usamos la siguiente notación para analizar las condiciones de carrera.

04 MAQ. CAP. 03(F0694).indd 131 8/10/07 12:54:57 AM


132 CAPÍTULO 3 Los procesos y los hilos

Sean ai y aj las operaciones en los datos compartidos ds ejecutadas por dos procesos interactuan-
tes Pi y Pj. Sean fi(ds), fj(ds) representan los valores de ds después de realizar las operaciones ai,
aj, respectivamente.

Definición 3.5 (La condición de carrera) Una condición de carrera en un elemento de dato
compartido ds es una situación en la cual el valor de ds que resulta de la ejecución de dos
operaciones ai y aj puede ser diferente de fi(fj(ds)) y fj(fi(ds)).

Sean ai, aj las operaciones de actualización

ai : ds: = ds + 10;
aj : ds: = ds + 5;

Si los procesos Pi y Pj ejecutan las operaciones ai y aj, respectivamente, uno esperaría que se
sume 15 al valor de ds. ¡Una condición de carrera surge si éste no es el caso! Veamos cómo po-
dría ocurrir esto.
El resultado de ejecutar ai y aj será correcto si uno de ellos opera en el valor que resulta de
la otra operación, pero estará equivocado si tanto ai como aj operan en el valor viejo de ds. Esto
podrá ocurrir si un proceso se ocupa en realizar la secuencia de carga-suma-almacena, pero el
otro realiza una instrucción de carga antes de que esta secuencia sea completada. El ejemplo
3.9 ilustra las condiciones de carrera en una aplicación de reservaciones de una aerolínea y sus
consecuencias.

Ejemplo 3.9 Los procesos del sistema de reservaciones de la aerolínea del ejemplo 3.8 ejecutan
código idéntico mostrado en la columna izquierda de la figura 3.22. Los procesos comparten las
variables nextseatno y capacity. Cada proceso examina el valor de nextseatno y lo actualiza como
1 si un asiento está disponible. Así ai y aj son operaciones idénticas. La columna derecha de la
figura 3.22 demuestra las instrucciones de máquina correspondientes al código. La declaración
S3 le corresponde a 3 instrucciones, S3.1, S3.2 y S3.3, que forman una secuencia de instrucciones
carga-suma-almacena.
La figura 3.23 muestra tres ejecuciones de procesos Pi y Pj cuando nextseatno = 200 y capaci-
ty = 200. En el caso 1, el proceso Pi ejecuta la declaración if que compara los valores de nextseatno
con capacity y procede a ejecutar las declaraciones S2 y S3 que le asignan un asiento e incrementan
nextseatno. Cuando el proceso Pj ejecuta la declaración if, se encuentra con que ninguno de los
asientos está disponible, por lo que no realiza ninguna asignación de asiento.
En el caso 2, el proceso Pi ejecuta la declaración if y se encuentra con que un asiento puede
ser asignado. Sin embargo, Pi se prioriza antes de que pueda realizar la asignación. El proceso Pj
ahora ejecuta la declaración if y se encuentra con que un asiento está disponible. Lo asigna y sale.
Ahora nextseatno es 201. Sin embargo, cuando Pi se reanuda, procede a ejecutar la instrucción
S2.1 porque había averiguado la disponibilidad de un asiento antes de ser priorizada. Así, ¡ubica el
asiento numerado 201 si bien sólo existen 200 asientos! Éste es un resultado equivocado, ya que la
ejecución de la lógica de asignación de asientos cuando nextseatno = 201 no debería conducir a
la asignación de un asiento.
En el caso 3, el proceso Pi se prioriza después de que cargue 200 en regj. ¡Ahora, tanto Pi como
Pj asignan un asiento cada uno; sin embargo, ¡nextseatno se incrementa por sólo 1! Así, los casos 2
y 3 involucran condiciones de carrera.

04 MAQ. CAP. 03(F0694).indd 132 8/10/07 12:54:57 AM


3.6 Procesos interactuantes: una vista avanzada del programador de los procesos 133

S1 if nextseatno ≤ capacity S1 .1 Load nextseatno in regk


S1 .2 If regk > capacity goto S4 .1
then
S2 allotedno:=nextseatno; S2 .1 Move nextseatno to allotedno
S3 nextseatno:=nextseatno+1; S3 .1 Load nextseatno in regj
S3 .2 Add 1 to regj
S3 .3 Store regj in nextseatno
S3 .4 Go to S5 .1
else
S4 display “lo sentimos, no hay S 4 .1 Display “lo sentimos, ”
asientos disponibles”
S5 S5 .1

Programa Instrucciones de máquina

Figura 3.22 Datos compartidos en los procesos de un sistema de reservaciones.

La existencia de las condiciones de carrera en un programa conduce a una dificultad prácti-


ca. Tal programa es incorrecto; sin embargo, no siempre produce resultados incorrectos porque
su comportamiento depende de la orden de ejecución de las instrucciones de los diferentes pro-
cesos. ¡Consecuentemente, un programa que produjo resultados incorrectos para algunos datos
puede producir resultados correctos si su ejecución se repite en la misma información! Esta
característica complica las pruebas y la depuración de los programas que contienen procesos
concurrentes. Por tanto, la mejor forma de manejar las condiciones de carrera es impedir que
surjan.

Cómo evitar las condiciones de carrera Las condiciones de carrera no surgirán si asegu-
ramos que las operaciones ai y aj de la definición 3.5 no se ejecutan concurrentemente: es decir,
aj no estará en ejecución si ai está en ejecución, y viceversa. Este requisito se llama exclusión
mutua. Queda satisfecho al permitir que sólo una operación tenga acceso a los datos compartidos
ds en cualquier momento. Cuando se usa la exclusión mutua, podemos estar seguros de que el
resultado de ejecutar las operaciones ai y aj será fi(fj(ds)) o fj(fi(ds)).
La sincronización de acceso a los datos es una técnica del usuario para implementar la ex-
clusión mutua sobre datos compartidos. Atrasa un proceso que desea acceder a ds si otro proceso
accede a él. Se dice que un conjunto de procesos {Pi} requiere sincronización de acceso de datos
si las condiciones de carrera surgen durante su ejecución. Identificamos este conjunto de pro-
cesos de acuerdo con la definición 3.6 para cada par de procesos. Usamos la siguiente notación
con este propósito:

update_seti : conjunto de elementos de datos actualizados por el


proceso Pi, es decir, el conjunto de elementos de datos
cuyos valores son leídos, modificados y escritos de re-
greso por el proceso Pi.

Definición 3.6 (Procesos que contienen condiciones de carrera) Una condición de carrera
existe en los procesos Pi y Pj de una aplicación si update_ seti 艚 update_ setj ≠ ␾.

04 MAQ. CAP. 03(F0694).indd 133 8/10/07 12:54:58 AM


134 CAPÍTULO 3 Los procesos y los hilos

nextseatno = 200
capacity = 200

Instante Acciones de Acciones de Acciones de


de tiempo Pi Pj Pi Pj Pi Pj
1 S1 .1 – S1 .1 – S1 .1 –
2 S1 .2 – S1 .2 – S1 .2 –
3 S2 .1 – – S1 .1 S2 .1 –
4 S3 .1 – – S1 .2 S3 .1 –
5 S3 .2 – – S2 .1 – S1 .1
6 S3 .3 – – S3 .1 – S1 .2
7 S3 .4 – – S3 .2 – S2 .1
8 – S1 .1 – S3 .3 – S3 .1
9 – S1 .2 – S3 .4 – S3 .2
10 – S4 .1 S2 .1 – – S3 .3
11 – – S3 .1 – – S3 .4
12 – – S3 .2 – s3 .2 –
13 – – S3 .3 – s3 .3 –
14 – – S3 .4 – s3 .4 –

caso 1 caso 2 caso 3

Figura 3.23 Condiciones de carrera en el sistema de reservaciones de una aerolínea.

El siguiente método puede usarse para impedir condiciones de carrera en un programa de


aplicación:

• Para cada par de procesos Pi y Pj que comparte algunos datos, inspeccione si existe una
condición de carrera.
• Si es así, asegúrese de que los procesos Pi y Pj compartieron datos de una manera mutua-
mente excluyente.

La sincronización en el acceso de datos se analiza en el capítulo 9.

3.6.2 Sincronización de control

En la sincronización de control, los procesos que interactúan coordinan su ejecución entre sí.
La sincronización de control puede requerirse en cualquier momento de un proceso, incluido el
principio o el final de la duración de su vida.

Definición 3.7 (La sincronización de control) La sincronización de control entre un par de


procesos Pi y Pj implica que la ejecución de alguna instrucción (declaración) sj en proceso
Pj, y las instrucciones (declaraciones) que sigan en el orden de ejecución se demoran hasta
que el proceso Pi ejecute una instrucción (declaración) si.

04 MAQ. CAP. 03(F0694).indd 134 8/10/07 12:54:58 AM


3.6 Procesos interactuantes: una vista avanzada del programador de los procesos 135

La figura 3.24 ilustra situaciones diferentes en la sincronización de control. Cada parte de la


figura muestra la ejecución de los procesos Pi y Pj. Se elaboran dos hipótesis al dibujar esta fi-
gura. Primera, se supone que el eje de tiempo se prolonga verticalmente hacia abajo en la figura,
es decir, la ejecución de una declaración que se muestra en un nivel más alto en un proceso Pi o
Pj ocurre más temprano que la ejecución de una declaración mostrada en un nivel inferior en el
mismo u otro proceso. Segunda, la ejecución de una declaración en el proceso Pi o Pj se muestra
tan pronto como sea posible en relación con la ejecución de otras declaraciones en Pi y Pj.

sj−1
si si
sj sj

Pi Pj Pi Pj
a) b)

Figura 3.24 Sincronización de control entre los procesos Pi y Pj.

La figura 3.24a) muestra que la declaración sj es la primera declaración del proceso Pj. Su
ejecución no puede tener lugar hasta que el proceso Pi ejecute la declaración si. Así, la sincroni-
zación ocurre en el principio del proceso Pj. La parte b) muestra que la sincronización ocurre a
la mitad del proceso Pj porque la declaración sj del proceso Pj no puede ejecutarse hasta que el
proceso Pi ejecute la declaración si. Observe que el proceso Pj terminó de ejecutar la declaración
sj-1 desde mucho antes; sin embargo, la ejecución de sj fue demorada hasta que Pi ejecutó si.
El ejemplo 3.10 ilustra la necesidad de la sincronización de control cuando una aplicación
está estructurada en un conjunto de procesos que interactúan para mejorar su tiempo de res-
puesta.

Ejemplo 3.10 Un programa debe diseñarse para reducir el tiempo transcurrido de un cómputo que
consta de las siguientes acciones:

• Calcule Y = HCF (Amáx, X), donde el arreglo A contiene n elementos y Amáx es el valor
máximo en el arreglo A.
• Inserte Y en el arreglo A.
• Ordene A en orden ascendente.

El problema puede dividirse en los siguientes pasos:

1. Lea n elementos del arreglo A.


2. Encuentre la magnitud máxima Amáx.
3. Lea X.
4. Calcule Y = HCF(Amáx, X).
5. Incluya Y en el arreglo A y ordene los elementos de A en orden ascendente.

04 MAQ. CAP. 03(F0694).indd 135 8/10/07 12:54:58 AM


136 CAPÍTULO 3 Los procesos y los hilos

Para decidir cuál de estas declaraciones puede realizarse concurrentemente con alguna otra, se
considera que la ejecución de cada declaración es un proceso separado y se aplica la definición 3.7
para encontrar cuál de estos procesos interactúa. Los procesos para las declaraciones 1 y 3 pueden
realizarse concurrentemente. Los de las declaraciones 2, 4 y 5 son procesos que interactúan. No
pueden ejecutarse concurrentemente porque comparten el arreglo A y al menos uno de ellos lo mo-
difica. Sin embargo, la concurrencia puede lograrse dividiendo los pasos 2 y 5 en dos partes cada
uno, de modo que

2a). Copie el arreglo A en el arreglo B.


2b). Encuentre Amáx.
5a). Ordene el arreglo B en orden ascendente.
5b). Incluya Y en el arreglo B en el lugar correcto.

Entonces los procesos que ejecutan los pasos 2b) y 5a) son independientes, por lo que pueden
ser ejecutados concurrentemente. Una vez que el paso 2b) ha sido realizado, el paso 4 también
puede efectuarse concurrentemente con el paso 5a). Así, el problema puede codificarse como el
conjunto de seis procesos mostrado en la figura 3.25.

Proceso P1 Proceso P2 Proceso P3

Leer n elementos de A Encontrar A máx Leer X


Copiar A en el arreglo B

Proceso P4 Proceso P5 Proceso P6

Calcular Ordenar B en orden Incluir Y en el arreglo B


Y = HCF(Amáx , X) ascendente

Figura 3.25 Procesos concurrentes para el ejemplo 3.10.

Los procesos P1 y P3 pueden iniciarse concurrentemente. Los procesos P1 y P2 no pueden


iniciarse concurrentemente porque comparten el arreglo A. El proceso P2 debe ser iniciado después
de que el proceso P1 termina, debido al orden de aparición de estos pasos en la especificación del
problema. Por una razón similar, el proceso P4 puede ser iniciado sólo cuando ambos P2 y P3 ter-
minen. El proceso P5 puede ser iniciado tan pronto como el proceso P1 termine, mientras que P6
puede empezar sólo después de que P4 y P5 hayan terminado.

La motivación para estructurar la aplicación en un conjunto de procesos concurrentes a la


manera del ejemplo 3.10 es obtener los beneficios de multiprogramación y multiprocesamiento
dentro de un programa. El proceso P3 es un proceso acotado de E/S cuya ejecución se traslapa
parcialmente con P2, que es un proceso acotado por el CPU, y P1, el cual está acotado por el
CPU en la mitad posterior de su duración de vida. Esto le permite al programa progresar más
rápidamente que si fuera codificado como un proceso solo. La ejecución traslapada de P4 y P5
(procesos acotados por el CPU) es una ventaja si el sistema de cómputo tiene CPU múltiples.
Observe que no hemos descrito cómo se implementa la sincronización de control. Ésta se des-
cribe en el capítulo 9.

04 MAQ. CAP. 03(F0694).indd 136 8/10/07 12:54:59 AM


3.6 Procesos interactuantes: una vista avanzada del programador de los procesos 137

3.6.3 El paso de mensajes

En la sección 3.2.1 analizamos cómo los procesos usan el paso de mensajes para intercambiar
información. Tales mensajes se llaman mensajes de interproceso. El paso de mensajes se imple-
menta a través de dos llamadas de sistema. Éstas son emitidas por las funciones de la biblioteca
send (envía) y receive (recibe), respectivamente.

Proceso Pi Proceso Pj

send (Pj , <message>); receive (Pi , <area address>);

Figura 3.26 Mensajes de interproceso.

La figura 3.26 muestra el paso de mensajes entre los procesos Pi y Pj. El proceso Pi envía un
msgk al proceso Pj ejecutando la llamada de función send (Pj, msgk) que lleva a una llamada de
sistema send. El kernel tiene que asegurar que el msgk de mensaje alcance al proceso Pj cuando
desea recibir un mensaje, es decir, cuando ejecuta la llamada de sistema receive. Para implementar
esto, el kernel copia primero el mensaje en un área de memoria temporal y espera una llamada re-
ceive del proceso Pj. Ésta ocurre cuando Pj ejecuta la llamada de función receive (Pi, alfa); en-
tonces el kernel copia msgk fuera de la memoria temporal, en el área de datos asignada a alfa.
Las llamadas send (envía) y receive (recibe) son ejecutadas por procesos diferentes, de
modo que no puede suponerse que la llamada send (envíe) siempre precederá a la llamada re-
ceive (recibe). El kernel tiene que asegurar que la función pretendida se implemente a pesar del
orden en la cual estas llamadas son ejecutadas. Esto se logra de la siguiente manera: si ningún
mensaje ha sido enviado a Pj, para cuando Pj ejecuta una llamada receive (recibe), el kernel
bloquea a Pj y la activa cuando un mensaje llega por ella. Si muchos mensajes han sido enviados
a Pj, el kernel los pone en la cola y los entrega en el orden FIFO (first in, first out) cuando Pj
ejecuta las llamadas de receive (recibe).
En principio, los procesos pueden comunicarse usando variables compartidas. Los procesos
Pi y Pj pueden declarar algunas variables compartidas, y están de acuerdo en dejarse mensajes
mutuamente en estas variables compartidas. Sin embargo, este arreglo requeriría la sincroniza-
ción de sus actividades. Por tanto, se prefiere el paso de mensajes. Al evitar las variables com-
partidas, el paso de mensajes también facilita la comunicación entre los procesos de aplicaciones
diferentes y los procesos que se ejecutan en sistemas de cómputo diferentes. La tabla 3.12 resu-
me éstas y otras ventajas del paso de mensajes. Los detalles de la comunicación de interproceso
están descritos en el capítulo 10.

3.6.4 Las señales


El mecanismo de señales se implementa a lo largo de las mismas líneas como interrupciones. Un
proceso Pi que desea enviar una señal a otro proceso Pj invoca la señal de la función de biblioteca
con dos parámetros: el id del proceso de destino, es decir, Pj, y un número de señal que indica
el tipo de señal que debe pasarse. Esta función usa la instrucción de interrupción del software
<SI_instrn> <interrupt_code> para hacer una llamada de sistema designada como señal. Los
parámetros (o sus direcciones) se ponen en los registros del CPU antes de hacer la llamada.

04 MAQ. CAP. 03(F0694).indd 137 8/10/07 12:54:59 AM


138 CAPÍTULO 3 Los procesos y los hilos

Tabla 3.12 Ventajas del paso de mensajes

1. No es necesario que los procesos usen datos comparti-


dos para intercambiar información.
2. El paso de mensajes es a prueba de intrusos, ya que los
mensajes residen en la memoria temporal del sistema
hasta la entrega.
3. El kernel puede advertir si el área de datos mencionada
en una llamada receive es de tamaño más pequeño que
el mensaje que va a recibirse.
4. El kernel toma la responsabilidad de bloquear un pro-
ceso que ejecuta una llamada receive cuando no existen
mensajes para éste.
5. Los procesos pueden pertenecer a diferentes aplica-
ciones y aun pueden existir en diferentes sistemas de
cómputo.

La rutina de manejo de eventos para la llamada signal extrae los parámetros para encontrar el nú-
mero de la señal. Entonces hace una provisión para pasar la señal a Pj y regresa. No hace ningún
cambio en el estado del proceso del remitente, es decir, en Pi.
Dos asuntos interesantes surgen en la implementación de señales. El proceso de envío de
una señal deberá conocer el id del proceso de destino. Este requisito restringe el alcance de las
señales a los procesos dentro de un árbol de procesos. El segundo asunto le concierne a la acción
del kernel si el proceso al cual se está enviando la señal está en estado bloqueado. El kernel
tendrá que cambiar temporalmente el estado del proceso a listo a fin de que pueda ejecutar su
código de manejo de señales. Después de que se ejecuta el código de manejo de señales, el ker-
nel tendrá que volver a cambiar el estado del proceso a bloqueado. Algunos sistemas operativos
prefieren un enfoque que simplemente observa la llegada de una señal si el proceso de destino es
bloqueado y dispone la ejecución del código de señales cuando el proceso se activa.
En el principio de esta subsección se mencionó que el mecanismo de señales se implementa
como interrupciones a lo largo de las mismas líneas. ¿Cómo embona esto en la escena? En la
sección 2.1.1 describimos cómo el hardware de interrupción usa la noción de los vectores de in-
terrupción. Puede definirse un arreglo similar para cada proceso. Así, para cada proceso existirá
un vector de la señal para cada señal que pueda enviársele. Éste contendrá la dirección de un
manipulador. Un proceso puede proveer a los manipuladores para señales diferentes y puede dar
a conocer sus direcciones al kernel a través de la llamada init signal. Cuando se envía una señal,
el kernel puede inspeccionar si el proceso de destino le ha especificado un manipulador. Si es
así, el kernel dispondrá el paso del control al manipulador; de otra manera, el kernel ejecutará
un manipulador por omisión para esa señal. Este esquema puede implementarse añadiendo un
campo a la PCB para conservar la dirección del área de vectores de la señal.

Ejemplo 3.11 La figura 3.27 ilustra el arreglo usado para maniobrar señales. El proceso Pi hace la
llamada de biblioteca init_sig (sig1, sh1) donde sig1 es el id de la señal que va a inicializarse
y sh1 es la dirección del manipulador de la señal. La rutina de la biblioteca init_sig hace la lla-
mada al sistema init signal. Mientras que maneja esta llamada, el kernel tiene acceso al PCB de Pi,
obtiene la dirección de inicio del área de vectores de la señal e ingresa la dirección sh1 en el vector

04 MAQ. CAP. 03(F0694).indd 138 8/10/07 12:54:59 AM


Ejercicio 3 139

Dirección inicial Pi Área del Pi Área del


del área de kernel kernel
vectores de señal
sig1 sh1 sig1 sh1
PCB PCB
Vectores Vectores
de señal de señal

sh1: sh1:
{manipulador de señales} {manipulador de señales}

init sig(sig1,sh1) init sig(sig1,sh1)

b1:

a) b)

Figura 3.27 Manipulación de señales por el proceso Pi: a) inicialización de señales, b) manipulación de señales.

de señal de la señal sig1 (véase la figura 3.27a)). Entonces el control regresa a Pi, que opera nor-
malmente hasta que se le manda la señal sig1. Las flechas segmentadas indican cómo el CPU se
conmuta al kernel cuando se hace la llamada de sistema y cómo se conmuta de regreso a Pi.
Cuando algún proceso Pj desea enviar la señal sig1 a Pi, hace la llamada del sistema signal
(Pi, sig1). El kernel localiza la PCB de Pi, obtiene la dirección del área de vectores de la señal y en-
cuentra el vector de la señal para sig1. Entonces dispone que el proceso Pi ejecute el manipulador
de la señal empezando en la dirección sh1 antes de reanudar su ejecución (véase la figura 3.27b)).
Esto se logra salvando al estado de Pi (que muestra que está a punto de ejecutar una instrucción en
la dirección b1), cambiando el contenido del contador del programa en el estado de Pi a la dirección
en sh1 y reanudando la operación de Pi. Entonces Pi ejecutará el manipulador de la señal. El kernel
también tendrá que hacer provisión para que después de que la ejecución del manipulador de la
señal ha sido completada, el estado de Pi se reinicie en el estado salvado para reanudar la operación
normal de Pi. En efecto, como lo muestran las flechas segmentadas en la figura 3.27b), la ejecu-
ción de Pi se desvía a la ejecución del manipulador de la señal, principiando en la dirección sh1, y
se reanuda después de que el manipulador de la señal se ejecute.

EJERCICIO 3
1. En algunas situaciones, un cambio en el estado de un proceso puede causar un cambio en el estado de
otro proceso. Describa todas esas situaciones.
2. Describa las acciones del kernel cuando los procesos hacen llamadas de sistema para los siguientes
propósitos:
a) Una petición de recepción para un mensaje.
b) Una petición de memoria.
c) Solicitud de información del estatus en relación con un proceso.

04 MAQ. CAP. 03(F0694).indd 139 8/10/07 12:55:00 AM


140 CAPÍTULO 3 Los procesos y los hilos

d) Solicitud para crear un proceso.


e) Solicitud para terminar un proceso hijo.
3. Describa las condiciones bajo las cuales tienen lugar las transiciones de estado entre los estados listo,
bloqueado, listo para el intercambio y bloqueado para el intercambio de la figura 3.7.
4. Describa las condiciones bajo las cuales un kernel puede realizar un despacho sin realizar una planifi-
cación.
5. Describa cómo el número de acciones de planificación realizadas en un sistema operativo depende de
la ocurrencia de los eventos en el sistema. Desarrolle una fórmula para calcular el número de veces que
un sistema operativo realiza la planificación.
6. Haga comentarios sobre lo siguiente en el contexto de los procesos en Unix:
a) La implementación de la llamada wait (espera) usando la estructura de datos de la PCB.
b) Comparativas de las duraciones de vida de un proceso y su PCB.
7. Describa la necesidad del estado zombi en Unix.
8. Describa cómo cada señal enlistada en la tabla 3.11 se levanta y se manipula en Unix.
9. Una señal enviada a un proceso en el estado bloqueado puede manipularse en dos formas: activando
temporalmente el proceso para manipular la señal y devolverla al estado bloqueado, o dejando que el
proceso manipule la señal la próxima vez que ingrese en el estado en ejecución. Analice cómo pueden
implementarse estas alternativas.
10. En el sistema de reservaciones del ejemplo 3.8 y en la figura 3.22, ¿es preferible usar hilos en vez de
procesos? Explique con razones.
11. Haga una lista de llamadas de sistema que un hilo deberá evitar usar si los hilos se implementan en el
nivel del usuario.
12. Haga comentarios sobre la validez de la siguiente declaración: “La concurrencia aumenta la sobrecarga
de la planificación sin suministrar la aceleración de un programa de aplicación.”
13. Una aplicación debe codificarse usando hilos. Describa las condiciones bajo las cuales usted recomen-
daría uso de a) hilos en el nivel del kernel, b) hilos en el nivel del usuario.
14. Escriba una nota pequeña en relación con la forma de decidir el número de hilos del usuario y de LWP
que deberán crearse en una aplicación.
15. Un sistema operativo admite tanto los hilos en el nivel del usuario como los hilos en el nivel del kernel.
Justifique las siguientes recomendaciones encontradas en el manual de un programador de sistema:
a) Si el candidato para el hilo es un cómputo acotado por el CPU, haga un hilo en el nivel del kernel
si el sistema contiene procesadores múltiples; de otra manera, haga un hilo en el nivel del usuario.
b) Si el candidato para el hilo es un cómputo acotado por la E/S, haga un hilo en el nivel del usuario si
el proceso que lo contiene no contiene un hilo en el nivel del kernel; de otra manera, haga un hilo
en el nivel del kernel.
16. Un servidor de una aplicación escalable debe implementarse para manejar una aplicación basada en la
web. El servidor maneja peticiones recibidas en forma de mensajes. Inicia un hilo nuevo si la cola de
petición excede un cierto número de entradas, y cierra algún(os) hilo(s) si la carga de mensaje decrece.
Explique cómo puede implementarse el servidor usando hilos. ¿Pueden aprovecharse las señales?
17. Un proceso crea 10 procesos hijo. Se requiere que organice los procesos hijo en dos grupos de 5 proce-
sos cada uno, de modo que los procesos en un grupo puedan enviar señales a otros procesos en el grupo,
pero no a los procesos fuera del grupo. Implemente este requisito usando características de Unix.
18. Si el sistema de reservaciones del ejemplo 3.8 y la figura 3.22 también contiene un proceso de averigua-
ción que simplemente verifique la disponibilidad de asientos en un vuelo, ¿puede surgir una condición
de carrera debido a la ejecución de las operaciones de averiguación y de reservación? Justifique su
respuesta.

04 MAQ. CAP. 03(F0694).indd 140 8/10/07 12:55:00 AM


Bibliografía 141

19. ¿Cuáles son los requisitos de sincronización de acceso de datos y de control de los procesos en la figura
3.25? Explique cómo pueden implementarse estos requisitos de sincronización.

BIBLIOGRAFÍA
El concepto de proceso se analiza en Dijkstra (1968), Brinch Hansen (1973) y Bic y Shaw (1974). Brinch
Hansen (1988) describe la implementación de procesos en el sistema RC 4000.
Marsh et al. (1991) estudian los hilos en el nivel del usuario y los aspectos relativos a las bibliotecas
de hilos. Anderson et al. (1992) analizan el uso de las activaciones del programador para la comunicación
entre el kernel y una biblioteca de hilos. Engelschall (2000) estudia cómo los hilos en el nivel del usuario
pueden implementarse en Unix usando instalaciones Unix estándar. Él también resume las propiedades de
otros paquetes de multihilos.
Kleiman (1996), Butenhof (1997), Lewis y Berg (1997) y Nichols et al. (1996) analizan la planifica-
ción con hilos POSIX. Lewis y Berg (2000) estudian los multihilos en Java.
Bach (1986), McKusick (1996) y Vahalia (1996) analizan los procesos en Unix. Beck et al. (2002) y
Bovet y Cesati (2003) describen los procesos y los hilos en Linux. Stevens y Rago (2005) describen los
procesos y los hilos en Unix, Linux y BSD; también estudian procesos del daemon en Unix. O’Gorman
(2003) estudia la implementación de señales en Linux. Eykholt et al. (1992) describen los hilos en SunOS,
mientras que Vahalia (1996) y Mauro y McDougall (2001) describen los hilos y LWP en Solaris. Custer
(1993), Richter (1999) y Russinovich y Solomon (2005) describen procesos e hilos en Windows. Vahalia
(1996) y Tanenbaum (2001) analizan los hilos en Mach.

1. Anderson, T.E., B.N. Bershad, E.D. Lazowska y H.M. Levy (1992): “Scheduler activations: effec-
tive kernel support for the user-level management of parallelism”, ACM Transactions on Compu-
ter Systems, 10 (1), 53-79.
2. Bach, M.J. (1986): The Design of the Unix Operating System, Prentice Hall, Englewood Cliffs.
3. Beck, M., H. Bohme, M. Dziadzka, U. Kunitz, R. Magnus, C. Schroter y D. Verwomer (2002):
Linux Kernel Programming, 3a. ed., Pearson Education.
4. Bic, L. y A.C. Shaw (1988): The Logical Design of Operating Systems, 2a. ed., Prentice Hall,
Englewood Cliffs.
5. Brinch Hansen, P. (1970): “The nucleus of a multiprogramming system”, Communications of the
ACM, 13, 238-241, 250.
6. Brinch Hansen, P. (1973): Operating System Principles, Prentice Hall, Englewood Cliffs.
7. Bovet, D.P. y M. Cesati (2003): Understanding the Linux Kernel, O’Reilly, Sebastopol.
8. Butenhof, D. (1997): Programming with POSIX threads, Addison Wesley, Reading.
9. Custer, H. (1993): Inside Windows/NT, Microsoft Press, Redmond.
10. Dijkstra, E.W. (1968): “The structure of THE multiprogramming system”, Communications of the
ACM, 11, 341-346.
11. Engelschall, R.S. (2000): “Portable Multithreading: The signal stack trick for use space thread
creation”, Proceedings of the 2000 USENIX Annual Technical Conference, San Diego.
12. Eykholt, J.R., S.R. Kleiman, S. Barton, S. Faulkner, A. Shivalingiah, M. Smith, I. Stein, J. Voll,
M. Weeks y D. Williams (1992): “Beyond multiprocessing: multithreading the SunOS kemel”,
Proceedings of the Summer 1992 USENIX Conference, 11-18.
13. O’Gorman, J. (2003): Linux Process Manager: The internals of Scheduling, Interrupts and Sig-
nals, Wi1ey and Sons.

04 MAQ. CAP. 03(F0694).indd 141 8/10/07 12:55:00 AM


142 CAPÍTULO 3 Los procesos y los hilos

14. Kleiman, S., D. Shah y B. Smaalders (1996): Programming with Threads, Prentice Hall, Englewo-
od Cliffs.
15. Lewis, B. y D. Berg (1997): Multithreaded Programming with Pthreads, Prentice Hall, Engle-
wood Cliffs.
16. Lewis, B. y D. Berg (2000): Multithreaded Programming with Java Technology, Sun Microsys-
tems.
17. Mauro, J. y R. McDougall (2001): Solaris Internals—Core Kernel Architecture, Prentice Hall.
18. Marsh, B.D., M.L. Scott, T.J. LeBlanc y E.P. Markatos (1991): “First-class user level threads”,
Proceedings of the Thirteenth ACM Symposium on Operating Systems Principles, octubre de
1991, 110-121.
19. McKusick, M.K., K. Bostic, M.J. Karels y J.S. Quarterman (1996): The Design and Implementa-
tion of the 4.4 BSD Operating System, Addison Wesley, Reading.
20. Nichols, B., D. Buttlar y J.P. Farrell (1996): Pthreads Programming, O’Reilly and Associates,
Sebastopol.
21. Richter, J. (1999): Programming Applications for Microsoft Windows, 4a. ed., Microsoft Press,
Redmond.
22. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.
23. Silberschatz, A., P.B. Galvin y G. Gagne (2005): Operating System Principles, 7a. ed., John Wiley,
Nueva York.
24. Stevens, W.R. y S.A. Rago (2005): Advanced Programming in the Unix Environment, 2a. ed.,
Addison Wesley Professional.
25. Tanenbaum, A.S. (2001): Modern Operating Systems, 2a. ed., Prentice Hall, Englewood Cliffs.
26. Vahalia, U. (1996): Unix Internals—The New Frontiers, Prentice Hall, Englewood Cliffs.

04 MAQ. CAP. 03(F0694).indd 142 8/10/07 12:55:01 AM


Capítulo
4
Planificación

La política de planificación que se utiliza en un sistema operativo afecta al servicio del usuario,
al uso eficaz de los recursos y al desempeño del sistema. Para lograr los fines que se proponen
las políticas de planificación se usan las técnicas fundamentales de priorización, reordenamiento
de las solicitudes y variación del intervalo de tiempo. A continuación se analizará la forma
en que estas técnicas se emplean en políticas de planificación clásicas sin priorización y con
priorización.
Un sistema operativo debe adaptar su funcionamiento a la disponibilidad de recursos que
hay en el sistema; para este efecto, utiliza una combinación de tres programadores denominados
de largo, mediano y corto plazos. Importante en la planificación práctica es la imparcialidad en
el servicio del usuario. Se analizará cómo los sistemas operativos incorporan imparcialidad al
modificar de manera dinámica la prioridad de un proceso. También se estudiará la planificación
en un entorno en tiempo real.
El análisis de desempeño de las políticas de planificación es relevante para ajustar el
desempeño de una política de planificación y comparar políticas alternativas. Se analizarán los
elementos principales del análisis de desempeño.

4.1 PRELIMINARES

La planificación consiste en seleccionar la siguiente solicitud que deberá ser atendida por un
servidor. Una política de planificación determina la calidad del servicio proporcionado a los
usuarios. También tiene que ver con el desempeño de un sistema de cómputo. En las secciones
2.5.3.1 y 2.6.2 se analizaron las políticas de planificación usadas en multiprogramación y en
sistemas de tiempo compartido, respectivamente, y se vio cómo las técnicas de priorización, de
asignación de prioridades a los procesos y de intervalo de tiempo se usan para lograr la combina-
ción deseada entre servicio del usuario y desempeño del sistema. En este capítulo se analizarán
características y propiedades de muchas otras políticas de planificación.

05 MAQ. CAP. 04(F0694).indd 143 8/10/07 12:58:46 AM


144 CAPÍTULO 4 Planificación

4.1.1 Conceptos y terminología de planificación

La figura 4.1 muestra un esquema de planificación. Todas las solicitudes en espera de ser atendidas
están en una lista de solicitudes pendientes. Una solicitud recién llegada se agrega a esta lista.
Siempre que se lleve a cabo una planificación, el programador analiza las solicitudes pendientes
y elige la que será atendida (esto se muestra con la flecha discontinua en la figura 4.1). Ésta se
entrega al servidor. Una solicitud sale del servidor cuando está terminada o cuando es priorizada
por el programador, en cuyo caso vuelve a ponerse en la lista de solicitudes pendientes. De
cualquier modo, el programador realiza la planificación a fin de seleccionar la siguiente solicitud
que deberá ser atendida. Así, cuatro eventos relacionados con la programación son la llegada, la
planificación, la priorización y la terminación.

La solicitud es priorizada

Programador

Llega la La solicitud La solicitud


solicitud es admitida es planificada
Servidor
La solicitud
es terminada

Solicitudes que Solicitudes


han llegado pendientes

Figura 4.1 Esquema de la planificación.

Una solicitud es la ejecución de una tarea o de un proceso. Un usuario hace una solicitud y
espera su terminación. En un entorno interactivo, un usuario puede interactuar con un proceso
durante su ejecución: el usuario hace una subsolicitud a un proceso y éste responde llevando a
cabo una acción o calculando un resultado.
En la tabla 4.1 se muestra un resumen de conceptos y términos relacionados con la pla-
nificación. El tiempo de servicio de una tarea o proceso es el tiempo total de CPU y el tiempo
E/S requeridos por la tarea o proceso para terminar su operación. Es una propiedad intrínseca de
una tarea o proceso. El tiempo total empleado por ellos en el SO puede ser mayor que su tiempo
de servicio porque puede haber momentos en los que el proceso no está siendo ejecutado en el
CPU ni está realizando E/S. En consecuencia, su tiempo de terminación depende de su tiempo
de llegada, del tiempo de servicio y del tipo de servicio que le proporciona el SO. Los conceptos
relacionados con la planificación pueden agruparse en conceptos centrados en el usuario y en
conceptos centrados en el sistema. A continuación se abordará este tema.

Conceptos de planificación centrados en el usuario Tiempo de respuesta, rebase de tiem-


po límite, tiempo de demora y tiempo de demora ponderado son enfoques del desempeño de un
programador centrados en el usuario o en la aplicación. El tiempo de respuesta es el lapso que
transcurre desde que se plantea una subsolicitud hasta el instante en el que termina su procesa-
miento. Es una medida absoluta del servicio otorgado a una subsolicitud. El tiempo de demora es

05 MAQ. CAP. 04(F0694).indd 144 8/10/07 12:58:47 AM


4.1 Preliminares 145

Tabla 4.1 Términos y conceptos de la planificación

Término o concepto Definición o descripción

Solicitud relacionada
Tiempo de llegada Instante en el que un usuario plantea una tarea o un proceso.
Tiempo de admisión Tiempo en el que el sistema comienza a considerar una tarea/proceso para
su planificación.
Tiempo de Instante en el que se termina una tarea o un proceso.
terminación
Tiempo límite Lapso en el que debe terminarse una tarea o un proceso a fin de satisfacer el
requerimiento de respuesta de una aplicación en tiempo real.
Tiempo de servicio Total de tiempo de CPU y tiempo E/S requerido por una tarea, un proceso
o una subsolicitud para terminar su operación.
Priorización Retiro de la asignación forzada del CPU de una tarea o de un proceso.
Prioridad La prioridad es una regla de desempate usada para seleccionar una solici-
tud cuando hay muchas solicitudes en espera de servicio.

Relacionado con el servicio del usuario: solicitud individual


Rebase de tiempo Cantidad de tiempo en la que el tiempo de terminación de una tarea o un
límite proceso excede su tiempo límite. Los rebases del tiempo límite pueden ser
ambos positivos o negativos.
Compartición equi- Una parte específica del tiempo de CPU que debe dedicarse a la ejecución
tativa de un proceso o de un grupo de procesos.
Relación tiempo desde la llegada  tiempo de servicio del proceso
La relación
de respuesta tiempo de servicio del proceso
Tiempo de Tiempo que transcurre desde la presentación de una subsolicitud que se
respuesta (rt) va a procesar hasta el momento en que su resultado está disponible. Este
concepto es aplicable a procesos interactivos.
Tiempo de Tiempo que transcurre entre la presentación de una tarea o un proceso y su
demora (ta) terminación por el sistema. Este concepto tiene sentido sólo para tareas o
procesos no interactivos.
Giro ponderado (w) Relación que hay entre el tiempo de demora de una tarea o un proceso y su
propio tiempo de servicio.

Relacionado con el servicio del usuario: servicio medio


Tiempo medio de Promedio de los tiempos de respuesta de todas las subsolicitudes atendidas
respuesta (rt) por el sistema.
Tiempo de demora Promedio de los giros de tiempo necesarios de todas las tareas o procesos
medio (ta) atendidos por el sistema.

Relacionado con la planificación


Longitud de la Tiempo necesario para terminar un conjunto específico de tareas o pro-
planificación cesos.
Rendimiento Número medio de tareas, procesos o subsolicitudes terminadas por el siste-
ma en una unidad de tiempo.

05 MAQ. CAP. 04(F0694).indd 145 8/10/07 12:58:47 AM


146 CAPÍTULO 4 Planificación

una medida absoluta análoga del servicio proporcionado a una solicitud. Es diferente al tiempo
de servicio de una solicitud porque también incluye el tiempo en el que la solicitud existe en el
sistema aunque no se esté ejecutando en el CPU ni esté realizando operaciones de E/S. El tiempo
de demora medio es una medida del servicio medio proporcionado a solicitudes o procesos. El
giro ponderado relaciona el tiempo de demora de un proceso con su propio tiempo de servicio.
Por ejemplo, un giro ponderado de 5 indica que el tiempo de demora recibido por una solicitud
es 5 veces mayor que su propio tiempo de servicio. La comparación de giros ponderados de
solicitudes distintas indica el servicio comparativo que recibieron éstas.
Los tiempos límite son relevantes en aplicaciones en tiempo real. El rebase del tiempo límite
es la cantidad de tiempo en el que un proceso no ha cumplido su tiempo límite. Un valor negativo
del rebase del tiempo límite indica que un proceso se terminó antes de su tiempo límite, mientras
que un valor positivo indica que no se cumplió en ese tiempo. Estos tiempos límite carecen de
sentido en aplicaciones en tiempo no real.

Conceptos de planificación centrados en el sistema El rendimiento y la longitud de


la planificación constituyen criterios de desempeño centrados en el sistema. El rendimiento
indica el número medio de solicitudes o subsolicitudes terminadas por unidad de tiempo (con-
sulte la sección 2.5). Constituye una base aceptable para comparar el desempeño de dos o más
sistemas, o bien el del mismo sistema en diferentes momentos. La longitud de la planificación
indica la cantidad total de tiempo necesario para que un servidor termine un conjunto de so-
licitudes.
El rendimiento y la longitud de la planificación están relacionados. Sin embargo, en un
SO, no es posible calcularlos uno en función del otro. La longitud de la planificación puede
calcularse sólo cuando un servidor manipula un conjunto fijo de solicitudes y se detiene. Un
SO puede empezar procesando nuevas solicitudes aun antes de haber terminado solicitudes
previas, por lo que no es posible calcular la longitud de la planificación para un subconjunto de
solicitudes procesadas por un SO. No obstante, la longitud de la planificación constituye una
base importante para comparar el desempeño de las políticas de planificación, especialmente
cuando no es posible omitir la carga general de programación.
Desde el punto de vista del administrador del sistema, la longitud de la planificación y
el rendimiento constituyen índices importantes del desempeño del sistema. Para un usuario, el
tiempo de demora de una solicitud es un índice absoluto del servicio. Los giros ponderados de
diversas solicitudes reflejan el servicio comparativo que se ha proporcionado a éstas: valores
muy próximos entre sí de giros ponderados indican un servicio equitativo.

4.1.2 Técnicas fundamentales de planificación

Los programadores usan tres técnicas fundamentales a fin de proporcionar un buen servicio al
usuario, eficacia de uso y desempeño del sistema.

• Planificación basada en la prioridad: El proceso en ejecución es el de mayor prioridad


que requiere el uso del CPU. Es priorizado cuando un proceso de mayor prioridad pasa
al estado listo.
• Reordenamiento de las solicitudes: El reordenamiento implica la atención de solicitudes
en algún otro orden que el de su llegada. El reordenamiento puede usarse de suyo o
junto con la priorización. En el primer caso, puede ser útil para mejorar el servicio del

05 MAQ. CAP. 04(F0694).indd 146 8/10/07 12:58:47 AM


4.1 Preliminares 147

usuario. Por ejemplo, atender solicitudes breves en lugar que grandes reduce el tiempo
de demora necesario medio de las solicitudes. El reordenamiento puede usarse junto
con la priorización para mejorar el servicio del usuario, como en un sistema de tiem-
po compartido, o bien para mejorar el rendimiento del sistema, como en un sistema de
multiprogramación.
• Variación del intervalo de tiempo: Cuando se utilizan intervalos de tiempo, de acuerdo
con la ecuación (2.3) de la sección 2.6.2, se tiene que η = δ+σ δ , donde  es la eficacia

del CPU,  es el intervalo de tiempo y  es la sobrecarga del SO por decisión de planifi-


cación. Los mejores tiempos de respuesta se obtienen para valores más pequeños que el
intervalo de tiempo; no obstante, la eficacia del CPU es menor porque se incurre en un
considerable intercambio de sobrecarga. Para equilibrar la eficacia del CPU y los tiempos
de respuesta, un SO puede utilizar valores distintos de  para solicitudes diferentes —usar
un valor pequeño de  para solicitudes ligadas a E/S y un valor grande para solicitudes
ligadas al CPU— o bien variar el valor de  para un proceso cuando su comportamiento
cambie de limitado por el CPU a ligado a E/S, o viceversa.

En las secciones 4.2 y 4.3 se analizará la forma en que estas técnicas se utilizan en las políti-
cas de planificación clásicas no priorizante y priorizante. En la sección 4.4 se abordará la manera
en que se usan en la práctica.

4.1.3 El papel de la prioridad

La prioridad es una regla de desempate que usan los programadores cuando muchas solicitudes
están en espera de ser atendidas por el servidor. La prioridad de una solicitud puede ser una
función de muchos parámetros, donde cada uno refleja un atributo intrínseco de la solicitud o
un aspecto que concierne a su servicio. Se denomina prioridad dinámica si algunos de sus pa-
rámetros cambian durante la operación de la solicitud; en caso contrario, se le llama prioridad
estática.
Algunos reordenamientos de procesos pueden obtenerse también por medio de las priori-
dades. Por ejemplo, los procesos cortos deben atenderse antes que los largos si la prioridad es
inversamente proporcional al tiempo de servicio de un proceso, y los procesos que han recibido
menos tiempo de CPU deben procesarse primero si la prioridad es inversamente proporcional
al tiempo de CPU consumido por un proceso. No obstante, para restringir la sobrecarga, a los
programadores les agrada evitar el empleo de funciones de prioridad complejas o propieda-
des dinámicas; para ello usan algoritmos que determinan el orden en el que deben atenderse las
solicitudes.
Si dos o más solicitudes tienen la misma prioridad, ¿cuál debe programarse primero? Un
esquema común consiste en usar planificación round-robin para solicitudes con la misma priori-
dad. Así, los procesos con la misma prioridad comparten el CPU cuando ninguno de los procesos
con mayor prioridad está listo, con lo cual se obtiene mejor servicio del usuario que si alguna de
las solicitudes se favorece con respecto a otras que tienen la misma prioridad.
La desventaja de la planificación basada en prioridades es que una solicitud con baja
prioridad jamás puede ser atendida si llegan solicitudes de mayor prioridad. Esta situación se
denomina inanición. Puede evitarse incrementando la prioridad de una solicitud si no se pro-
grama durante cierto lapso. Así, la prioridad de una solicitud con baja prioridad puede seguir

05 MAQ. CAP. 04(F0694).indd 147 8/10/07 12:58:48 AM


148 CAPÍTULO 4 Planificación

aumentando mientras la solicitud espera ser planificada, hasta que su prioridad excede la prio-
ridad de todas las demás solicitudes pendientes. Es entonces cuando debe ser planificada. Esta
técnica también se denomina envejecimiento de las solicitudes.

4.2 POLÍTICAS DE PLANIFICACIÓN NO PRIORIZANTE

En la planificación no priorizante, un servidor siempre procesa una solicitud programada hasta


su terminación. Así, jamás ocurre la priorización de una solicitud como se muestra en la figura
4.1. La planificación sólo se lleva a cabo una vez que termina el procesamiento de la solicitud
programada previamente. Este tipo de planificación es atractiva gracias a su sencillez: no es ne-
cesario mantener una distinción entre una solicitud no atendida y una parcialmente atendida.
Debido a que no utiliza priorización, el programador depende del reordenamiento de las
solicitudes para obtener una mejora en el servicio del usuario o en el desempeño del sistema. En
esta sección se analizan tres políticas de planificación no priorizante:

• Planificación FCFS.
• Planificación de la siguiente solicitud más corta (SRN).
• Planificación de la siguiente máxima relación de respuesta (HRN).
Aquí se utilizan los cinco procesos que se muestran en la tabla 4.2 para analizar la operación
y el desempeño de varias políticas de planificación. A fin de facilitar las cosas, se supone que
ningún proceso ejecuta operaciones E/S.

Tabla 4.1 Procesos de la planificación

Proceso P1 P2 P3 P4 P5
Tiempo de llegada 0 2 3 5 9
Tiempo de servicio 3 3 2 5 3

Planificación FCFS Las solicitudes se programan en el orden en que llegan al sistema. La


lista de solicitudes pendientes se organiza como una cola. El programador siempre elige para
planificar la primera solicitud de la lista. Un ejemplo de planificación FCFS es un sistema de pro-
cesamiento por lotes en el cual las tareas se ordenan según sus tiempos de llegada (o de manera
arbitraria si los tiempos de llegada son idénticos) y los resultados de una tarea se suministran a
un usuario inmediatamente después de su terminación. En el ejemplo 4.1 se ilustra la operación
de un programador FCFS.

Ejemplo 4.1 La mitad superior de la figura 4.2 muestra las decisiones de planificación ejecuta-
das por la política FCFS para los procesos de la tabla 4.2. En la mitad izquierda de la tabla 4.3 se
resume el desempeño del programador FCFS. La columna Terminado muestra la identificación
del proceso terminado, su tiempo de demora (ta) y su giro ponderado (w). Observe que hay una
variación considerable en los giros ponderados. Ésta hubiera sido mayor si los procesos que expe-
rimentan grandes tiempos de giro fuesen breves; por ejemplo, el giro ponderado de P5 sería mayor
si su requerimiento de ejecución fuese igual a 1 segundo o a 0.5 segundo. Bajo la tabla se muestran
ta y w medios (es decir, ta y w).

05 MAQ. CAP. 04(F0694).indd 148 8/10/07 12:58:48 AM


4.2 Políticas de planificación no priorizante 149

P1
Primero en P2
llegar, primero P3
en ser servido P4
(FCFS) P5

P1
Solicitud P2
más corta a P3
continuación P4
(SRN) P5

0 5 10 15

Figura 4.2 Planificación en que se utilizan las políticas FCFS y SRN.

Tabla 4.3 Desempeño de las planificaciones FCFS y SRN

FCFS SRN
Completado Procesos en Plani- Completado Procesos en Plani-
Tiempo id ta w el sistema ficado id ta w el sistema ficado
0 – – – {P1 } P1 – – – {P1 } P1
3 P1 3 1.00 {P2 , P3 } P2 P1 3 1.00 {P2 , P3 } P3
5 P3 2 1.00 {P2 , P4 } P2
6 P2 4 1.33 {P3 , P4 } P3
8 P3 5 2.50 {P4 } P4 P2 6 2.00 {P4 } P4
13 P4 8 1.60 {P5 } P5 P4 8 1.60 {P5 } P5
16 P5 7 2.33 {} – P5 7 2.33 {} –

ta = 5.40 segundos ta = 5.20 segundos


w = 1.75 w = 1.59

El ejemplo 4.1 muestra que hay una gran disparidad en el servicio recibido por las solici-
tudes en la planificación FCFS. Con base en lo anterior, es posible concluir que las solicitudes
breves (los procesos P3 y P5) pueden experimentar altos giros ponderados, es decir, servicio
más deficiente en comparación con las demás solicitudes (proceso P4). En un sistema de pro-
cesamiento por lotes, las tareas en el lote pueden reordenarse para reducir los tiempos de giro y
los giros ponderados de tareas individuales. Sin embargo, esto podría no reducir la gama de los
tiempos de giro o incrementar el rendimiento.

Planificación de la siguiente solicitud más corta (SRN) El programador SRN siempre


planifica la más corta de las solicitudes que han llegado. Así, una solicitud permanece pendiente
hasta que se han atendido todas las solicitudes más breves.

05 MAQ. CAP. 04(F0694).indd 149 8/10/07 12:58:48 AM


150 CAPÍTULO 4 Planificación

Ejemplo 4.2 La mitad inferior de la figura 4.2 muestra las decisiones de planificación ejecutadas
por la política SRN para los procesos de la tabla 4.2. La mitad derecha de la tabla 4.3 resume el
desempeño del programador SRN. El tiempo de demora y el giro ponderado son mejores que en
planificación FCFS porque las solicitudes más breves tienden a recibir tiempos de giro y giros
ponderados menores que en planificación FCFS. Esto degrada el servicio en solicitudes largas
aunque sus giros ponderados no aumentan mucho porque sus tiempos de servicio son grandes.
El rendimiento es superior que en planificación FCFS, excepto al final del calendario, donde es
idéntico.

En la práctica resulta difícil implementar la política SRN, ya que los tiempos de servicio
de los procesos no se conocen de antemano. Muchos sistemas esperan que los usuarios pro-
porcionen estimaciones de los tiempos de servicio de los procesos. No obstante, los resultados
obtenidos al usar tales datos son erráticos si los usuarios carecen de experiencia suficiente en
la estimación de los tiempos de servicio. La dependencia en relación con las estimaciones del
usuario también deja vulnerable el sistema con respecto a abuso o manipulación, ya que qui-
zá los usuarios podrían intentar la obtención de un mejor servicio al especificar valores bajos
para los tiempos de servicio de sus procesos. Otro aspecto práctico en donde la planificación
SRN no funciona adecuadamente es en el servicio ofrecido a procesos largos. Un flujo estable de
procesos breves que llegan al sistema puede negar de manera indefinida el uso de CPU a proce-
sos largos. Esto se denomina inanición.

Planificación de la siguiente máxima relación de respuesta (HRN) La política HRN


calcula las relaciones de respuesta de todos los procesos en el sistema según la ecuación (4.1) y
elige el proceso que tiene la mayor relación de respuesta.

Tiempo transcurrido a Tiempo de servicio



partir de la llegada del proceso
Relación de respuesta   (4.1)
Tiempo de servicio del proceso

La relación de respuesta de un proceso recién llegado es 1. Se mantiene creciendo a razón


1兾tiempo de servicio mientras el proceso espera ser atendido; la relación de respuesta de un
proceso breve aumenta más rápido que la de uno largo, de modo que los procesos más breves
son favorecidos por la planificación. No obstante, la relación de respuesta de un proceso largo
puede volverse suficientemente grande para que ese proceso sea planificado. Esta característica
constituye un efecto semejante al de la técnica de envejecimiento que se analizó en la sección
4.1.3, de modo que los procesos largos no desaparecen por inanición. Esta propiedad se ilustra
con el siguiente ejemplo.

Ejemplo 4.3 En la figura 4.3 se resume la operación de la política de planificación HRN para los
cinco procesos P11-P15. Para cuando termina el proceso P11, los procesos P12 y P13 ya han llegado.
La relación de respuesta de P12 es mayor que la de P13, de modo que éste se programa a continua-
ción. Una vez que ha terminado P13, su relación de respuesta es mayor que antes; sin embargo,
P14, que llegó después que P13, posee una relación de respuesta aún mayor porque se trata de un
proceso más breve, razón por la cual es planificado. Cuando termina P14, la relación de respuesta
de P13 es mayor que la del proceso más breve, P15, porque ha estado bastante tiempo en espera,
mientras que P15 acaba de llegar. De modo que entonces se planifica a P13. Así, el proceso largo se
planifica antes que uno breve porque su tiempo de espera ha sido mayor.

05 MAQ. CAP. 04(F0694).indd 150 8/10/07 12:58:49 AM


4.3 Políticas de planificación priorizante 151

Proceso P11 P12 P13 P14 P15


Tiempo de llegada 0 2 3 4 8
Tiempo de servicio 3 3 5 2 3

Proceso terminado Relaciones de respuesta de los procesos


Tiempo id ta w P11 P12 P13 P14 P15 Planificado
0 − − − 1.00 P11
3 P11 3 1.00 1.33 1.00 P12
6 P12 4 1.33 1.60 2.00 P14
8 P14 4 2.00 2.00 1.00 P13
13 P13 10 2.00 2.67 P15
16 P15 8 2.67 –
ta = 5.8 segundos
w = 1.80

P11
P12
P13
P14
P15

0 5 10 15 tiempo →

Figura 4.3 Operación de la política de máxima relación de respuesta (HRN).

4.3 POLÍTICAS DE PLANIFICACIÓN PRIORIZANTE

En la planificación priorizante, el servidor puede cambiar al procesamiento de una nueva solici-


tud antes de terminar la solicitud presente. La solicitud priorizada se coloca otra vez en la lista
de solicitudes pendientes (consulte la figura 4.1). La forma en que fue atendida puede resumirse
una vez que se planifica nuevamente. Así, antes de terminar una solicitud puede ser necesario
planificarla varias veces. En el capítulo 2 se analizaron las políticas de planificación priorizante
utilizadas en multiprogramación y en sistemas operativos de tiempo compartido.
En esta sección se analizan cuatro políticas de planificación priorizante:

• Planificación round-robin con intervalos de tiempo (RR).


• Planificación del menos terminado (LCN) a continuación.
• Planificación del menor tiempo restante (STG).
• Planificación de la mínima relación de respuesta a continuación (HRN).

En la figura 4.4 se muestran las decisiones de planificación realizadas por estas políticas de
planificación priorizante cuando un SO ejecuta los procesos de la tabla 4.2 si las decisiones
de planificación se realizan cada segundo y si un proceso no lleva a cabo operaciones E/S. En la
tabla 4.4 se resume la operación de las políticas de planificación priorizante. En la tabla 4.5 se
resume el desempeño de estas políticas.

05 MAQ. CAP. 04(F0694).indd 151 8/10/07 12:58:49 AM


152 CAPÍTULO 4 Planificación

P1
Round-robin P2
P3
(RR) P4
P5

Planificación del P1
menos terminado P2
a continuación P3
(LCN) P4
P5

P1
Planificación del P2
menor tiempo P3
restante P4
(STG) P5

0 5 10 15

Figura 4.4 Planificación en que se utilizan políticas de planificación priorizante.

Planificación round-robin El objetivo de la planificación round-robin (RR) con intervalos


de tiempo es proporcionar un servicio equitativo a todas las solicitudes. Los intervalos de tiempo
se usan para limitar la cantidad de tiempo de CPU que puede usar un proceso cuando es plani-
ficado. Una solicitud se prioriza si transcurre el intervalo de tiempo. Esta política preserva los
giros ponderados de los procesos aproximadamente iguales al número de procesos activos que
hay en el sistema. Sólo pueden presentarse variaciones debido a la naturaleza de los procesos;
por ejemplo, un proceso ligado a E/S puede estar retrasado con respecto a procesos ligados a
CPU en cuanto al uso de éste. La política RR no funciona bien en términos de índices de desem-
peño del sistema como el rendimiento, ya que con esta política todos los procesos se tratan de la
misma manera y no se otorga un tratamiento preferencial a procesos breves. El desempeño de
la planificación RR se ilustra con el ejemplo 4.4.

Ejemplo 4.4 En la parte izquierda de la tabla 4.4 se resume la operación del programador RR con
  1 para los cinco procesos que se muestran en la tabla 4.2. El programador toma sus decisiones
cada segundo. En la columna Procesos se muestra la lista de los procesos existentes en el sistema.
El programador simplemente elige el primero que se va a planificar. El proceso actual es priorizado
cuando transcurre el intervalo de tiempo. Luego, es colocado al final de la cola. Se supone que un
nuevo proceso admitido en el sistema en el mismo instante se coloca en la cola antes que el proceso
priorizado.
Los tiempos de giro y los giros ponderados de los procesos son como se muestra en la parte
más a la izquierda de la tabla 4.5. En la columna C se presentan los tiempos de terminación. Los
tiempos de giro y los giros ponderados son inferiores en comparación con las políticas no priorizan-
tes. Esto es así porque el tiempo de CPU se divide entre muchos procesos en virtud de los intervalos
de tiempo. Puede observarse que los procesos P2, P3 y P4, que llegan más o menos al mismo tiem-
po, reciben giros ponderados aproximadamente iguales. P3 recibe el peor giro ponderado porque

05 MAQ. CAP. 04(F0694).indd 152 8/10/07 12:58:49 AM


4.3 Políticas de planificación priorizante 153

Tabla 4.4 Operación de las políticas de planificación priorizantes

Round-robin Menos terminado a continuación Menor tiempo restante


(RR) (LCN) (STG)
Plani- Plani- Plani-
Tiempo Procesos ficado Procesos ficado Procesos ficado
0 P1 P1 P1 :0 P1 P1 :3 P1
1 P1 P1 P1 :1 P1 P1 :2 P1
2 P2 , P1 P2 P1 :2, P2 :0 P2 P1 :1, P2 :3 P1
3 P1 , P3 , P2 P1 P1 :2, P2 :1, P3 :0 P3 P2 :3, P3 :2 P3
4 P3 , P2 P3 P1 :2, P2 :1, P3 :1 P2 P2 :3, P3 :1 P3
5 P2 , P4 , P3 P2 P1 :2, P2 :2, P3 :1, P4 :0 P4 P2 :3, P4 :5 P2
6 P4 , P3 , P2 P4 P1 :2, P2 :2, P3 :1, P4 :1 P3 P2 :2, P4 :5 P2
7 P3 , P2 , P4 P3 P1 :2, P2 :2, P4 :1 P4 P2 :1, P4 :5 P2
8 P2 , P4 P2 P1 :2, P2 :2, P4 :2 P1 P4 :5 P4
9 P4 , P5 P4 P2 :2, P4 :2, P5 :0 P5 P4 :4, P5 :3 P5
10 P5 , P4 P5 P2 :2, P4 :2, P5 :1 P5 P4 :4, P5 :2 P5
11 P4 , P5 P4 P2 :2, P4 :2, P5 :2 P2 P4 :4, P5 :1 P5
12 P5 , P4 P5 P4 :2, P5 :2 P4 P4 :4 P4
13 P4 , P5 P4 P4 :3, P5 :2 P5 P4 :3 P4
14 P5 , P4 P5 P4 :3 P4 P4 :2 P4
15 P4 P4 P4 :4 P4 P4 :1 P4
16 – – – – – –

en el sistema existen tres procesos casi durante toda su duración. P1 recibe el mejor giro ponderado
porque en el sistema no hay ningún otro proceso durante la primera parte de la ejecución de P1. Así,
los giros ponderados dependen de la carga que hay en el sistema.

La eficacia de la planificación RR depende de dos factores: la elección de , el intervalo


de tiempo y la naturaleza de los procesos en el sistema. Como se analizó en el capítulo 2, si un
sistema contiene n procesos y cada solicitud de un proceso consume exactamente  segundos,
entonces el tiempo de respuesta (rt) para una solicitud es

rt  n  (  ) (4.2)

donde  es la carga general de planificación por decisión de planificación. Debido a que no


todos los procesos pueden estar activos todo el tiempo, ya que algunos pueden estar bloqueados
por operaciones de E/S u otras solicitudes, el tiempo de respuesta es regido más por un número
de procesos activos que por n. Otros dos factores que pueden afectar a rt son la variación en el
tiempo de CPU requerido por varias solicitudes y la relación entre  y el tiempo de CPU reque-
rido por una solicitud. En la ecuación (4.2) se supone que cada solicitud consume exactamente
 y que produce una respuesta. Si una solicitud requiere más tiempo de CPU que , entonces es
necesario planificarla más de una vez antes de que pueda producir una respuesta. Por tanto, en
ciertas regiones de valores de , rt para una solicitud puede aumentar, aun cuando  disminuya.
Este hecho se ilustra con el ejemplo 4.5.

05 MAQ. CAP. 04(F0694).indd 153 8/10/07 12:58:49 AM


154 CAPÍTULO 4 Planificación

Tabla 4.5 Desempeño de las políticas de planificación priorizante (C: Tiempo de terminación del proceso)

Máxima relación
Round-robin Menos terminado a Menor tiempo de respuesta a
(RR) continuación (LCN) restante (STG) continuación (HRN)
Proceso C ta w C ta w C ta w C ta w
P1 4 4 1.33 9 9 3.00 3 3 1.00 5 5 1.67
P2 9 7 2.33 12 10 3.33 8 6 2.00 11 9 3.00
P3 8 5 2.50 7 4 2.00 5 2 1.00 8 5 2.50
P4 16 11 2.20 16 11 2.20 16 11 2.20 16 11 2.20
P5 15 6 2.00 14 5 1.67 12 3 1.00 15 6 2.00

ta = 6.6 segundos ta = 7.8 segundos ta = 5.0 segundos ta = 7.2 segundos


w = 2.07 w = 2.40 w = 1.44 w = 2.27

Ejemplo 4.5 Un SO contiene 10 procesos idénticos que empezaron al mismo tiempo. Cada uno
contiene 15 solicitudes idénticas y cada solicitud consume 20 mseg de tiempo de CPU. Una soli-
citud es seguida de una operación de E/S que consume 10 mseg. El sistema consume 2 mseg en
planificación de CPU. Para   20 mseg, la primera solicitud del primer proceso recibe un tiempo
de respuesta de 22 mseg y la primera solicitud del último recibe un tiempo de respuesta de 220
mseg, de modo que el tiempo de respuesta medio es igual a 121 mseg. Una solicitud posterior de
cualquier proceso recibe un tiempo de respuesta de 10  (2  20) 10 mseg  210 mseg, ya que
el proceso utiliza 10 mseg en una espera de E/S antes de hacer la siguiente solicitud. Para   10
mseg, una solicitud puede ser priorizada al cabo de 10 mseg. Una vez que se vuelve a planificar,
debe ejecutarse durante 10 mseg y entonces producir resultados, de modo que el tiempo de respues-
ta para el primer proceso es

 10  (2  10)  (2  10)  132 mseg

y para el último es

 10  (2  10)  10  (2  10)  240 mseg.

Una solicitud posterior de cualquier proceso recibe un tiempo de respuesta de 10  (2  10) 


10  (2  10) 10  230 mseg. La figura 4.5 ilustra la variación del tiempo de respuesta medio
para las solicitudes segunda y posteriores para diferentes valores de . En la tabla 4.6 se resume el
desempeño del sistema para valores diferentes de . Como era de esperar, la sobrecarga es mayor
para valores menores de .

Políticas que utilizan información del consumo de recursos

El objetivo de las políticas que utilizan información del consumo de recursos es eliminar al-
gunos problemas de las políticas priorizantes analizadas hasta ahora, por ejemplo, giros pon-
derados deficientes de procesos e inanición de procesos largos. A continuación se analizan tres
políticas de planificación:
1. Planificación del menos terminado (LCN) a continuación.
2. Planificación del menor tiempo restante (STG).
3. Planificación de relación de respuesta.

05 MAQ. CAP. 04(F0694).indd 154 8/10/07 12:58:50 AM


4.3 Políticas de planificación priorizante 155

0.3
Tiempo de •
respuesta
(segundos) • •

0.2

0.1

5 10 15 20 25 Intervalo de tiempo (mseg) →

Figura 4.5 Variación del tiempo de respuesta promedio con intervalo de tiempo.

Tabla 4.6 Desempeño de la planificación RR para valores distintos de 

Intervalo de tiempo 5 mseg 10 mseg 15 mseg 20 mseg


rt promedio para la primera solicitud (mseg) 248.5 186 208.5 121
rt promedio para la solicitud posterior (mseg) 270 230 230 210
Número de decisiones de planificación 600 300 300 150
Longitud de la planificación (mseg) 4 200 3 600 3 600 3 300
Sobrecarga (porcentual) 29 17 17 9

Menos terminado a continuación (LCN) Esta política programa el proceso que ha consu-
mido la menor cantidad de tiempo de CPU. Así, la naturaleza de un proceso, ligado al CPU o a
E/S, y el requerimiento de tiempo de CPU de un proceso no afectan su avance en el sistema. To-
dos los procesos avanzan aproximadamente igual en términos del tiempo de CPU que consumen,
de modo que se garantiza que los procesos breves terminan antes que los procesos largos. No
obstante, esta política posee la conocida desventaja de que los procesos largos padecen inanición
con respecto al CPU. También ignora a los procesos existentes si al sistema continúan llegando
nuevos procesos. Así, incluso procesos no tan largos tienden a sufrir inanición o tiempos de giro
mayores.

Ejemplo 4.6 La operación de la política de planificación LCN para los cinco procesos que se
muestran en la tabla 4.2 se resume en la parte central de la tabla 4.4. La información de la planifi-
cación usada por esta política consta de un par de procesos (identificación del proceso, tiempo de
CPU consumido). Aquí se utiliza la notación Pi:tj, donde Pi es la identificación de un proceso y tj es
el tiempo de CPU consumido por el mismo, para denotar esta información en la columna Procesos.
El programador analiza esta información y elige el proceso que ha consumido la menor cantidad
de tiempo de CPU. En caso de haber un empate, elige aquel que no ha sido atendido durante un
intervalo de tiempo mayor.
Los tiempos de giro y los giros ponderados de los procesos se muestran en la segunda parte de
la tabla 4.5. El procesamiento de P1, P2 y P4 se posterga porque al sistema llegan nuevos procesos

05 MAQ. CAP. 04(F0694).indd 155 8/10/07 12:58:50 AM


156 CAPÍTULO 4 Planificación

y obtienen servicio de CPU antes de que aquéllos puedan avanzar más. El proceso P4 los atrapa
para darles servicio durante la segunda mitad de su existencia en el sistema porque no llega ningún
nuevo proceso. La política de planificación LCN proporciona tiempos de giro y giros ponderados
más deficientes que los proporcionados por las políticas RR y STG (consulte los ejemplos 4.4 y
4.7) porque favorece nuevos procesos que llegan sobre los procesos existentes en el sistema; por
ejemplo, favorece a P3 sobre P1 y P2, y a P5 sobre P4.

Planificación del menor tiempo restante (STG) Esta política es una versión priorizan-
te de la política SRN. Un proceso es planificado cuando sus requerimientos de procesamiento
restantes son los más pequeños en el sistema. La política STG favorece un proceso que está
próximo a su terminación, sin tomar en cuenta el tiempo de CPU que ya ha consumido. Así,
un proceso largo que está próximo a su terminación puede ser favorecido sobre procesos breves
que llegan al sistema. Los procesos largos deben terminar primero, mejorando así su giro pon-
derado, aunque esto puede afectar los tiempos de giro y los giros ponderados de varios procesos
breves en el sistema. Por otra parte, los procesos largos tienen problemas en la recepción de
servicio en fases tempranas de su operación, de modo que el servicio favorecido para procesos
largos próximos a su terminación puede no evitar la inanición de los procesos largos.

Ejemplo 4.7 En la parte derecha de la tabla 4.4 se resume el desempeño de la política de planifica-
ción STG para los cinco procesos que se muestran en la tabla 4.2. La información de planificación
que usa la política consta de un par (identificación del proceso y el tiempo de CPU necesario para
terminación). Aquí se utiliza la notación Pi:tj, donde Pi es la identificación de un proceso y tj es el
tiempo de CPU necesario para la terminación del proceso, para registrar esta información en la co-
lumna Procesos. El programador usa esta información para elegir el proceso que requiere la menor
cantidad de tiempo de CPU a fin de ser terminado. En caso de haber un empate, elige un proceso
que no ha sido atendido durante un intervalo de tiempo mayor.
En la tercera parte de la tabla 4.5 se muestran los tiempos de giro y los giros ponderados de los
procesos. Observe que los procesos P1, P3 y P5 obtienen tiempos de giro y giros ponderados acep-
tables. De hecho, los tiempos de giro y los giros ponderados de todos los procesos, salvo P4, son
mejores que los proporcionados por la política LCN (consulte el ejemplo 4.6). Esto se debe a que
sus tiempos de servicio son menores que los de P4. Por tanto, el mejor servicio que han recibido es
a costa de ignorar a P4, cuya ejecución ni siquiera empieza sino hasta que se ha terminado P5. El
hecho de ignorar los procesos largos puede apreciarse con mayor detalle si otro proceso P6 cuyo
requerimiento de tiempo de CPU de 6 segundos fuese a llegar en t  1 s. Su ejecución comenzará
sólo después de la terminación de P4; su tiempo de demora y su giro ponderado serán iguales a 21
segundos y 3.5, respectivamente.

4.4 LA PLANIFICACIÓN EN LA PRÁCTICA

4.4.1 Planificación a corto, mediano y largo plazos

Un sistema operativo debe proporcionar una combinación idónea de características centradas en


el usuario y en el sistema. También debe adaptarse a la naturaleza y cantidad de solicitudes de
los usuarios que se espera surjan en su entorno, así como a la disponibilidad de recursos. Un solo
programador y una sola política de planificación no son capaces de manipular todos sus asuntos.

05 MAQ. CAP. 04(F0694).indd 156 8/10/07 12:58:50 AM


4.4 La planificación en la práctica 157

Por consiguiente, un SO utiliza una disposición que consta de tres programadores denominados
programador a largo plazo, programador a mediano plazo y programador a corto plazo encar-
gados de atender diversas cuestiones centradas en el usuario y en el sistema.

Tabla 4.7 Planificación a largo, mediano y corto plazos

Planificación a Decide cuándo admitir un proceso recién llegado para su procesamiento con base
largo plazo en su naturaleza, ya sea limitado por el CPU o ligado a E/S, así como la disponi-
bilidad de recursos, como estructuras de datos del kernel, terminales del usuario y
espacio de disco para intercambio.
Planificación a Mueve los procesos entre la memoria y el disco a fin de optimizar el uso de la pri-
mediano plazo mera. Mantiene una cantidad suficiente de procesos listos en la memoria.
Planificación a Decide cuáles procesos listos deben ejecutarse a continuación y durante cuánto
corto plazo tiempo.

Interrupción

Manejo de la
interrupción

Listas PCB Crear/ Manejador de Suspender/


terminar resumir Manejadores
Listas ECB un proceso la memoria un proceso de eventos

Programador Programador a
a largo plazo mediano plazo
Programadores
Programador a
corto plazo
Flujo de control
Flujo de datos
Despachador

Figura 4.6 Manejo y planificación de eventos.

En la figura 4.6 se muestra una visión general de la planificación y acciones relacionadas.


Como se analizó en las secciones 2.1.2 y 3.3.2, el kernel opera a manera de interrupción. Cada
evento que requiere su atención provoca una interrupción. El manejo de la interrupción ejecuta

05 MAQ. CAP. 04(F0694).indd 157 8/10/07 12:58:50 AM


158 CAPÍTULO 4 Planificación

una función de guardar el contexto e invoca un manejo de eventos. Éste procesa el evento y
modifica el estado del proceso afectado por el evento. Luego invoca al programador a largo,
mediano y corto plazos según sea conveniente. Por ejemplo, el manejador de eventos que crea
un nuevo proceso invoca a un programador de largo plazo, y el programador a mediano plazo
es invocado cuando es necesario suspender o resumir un proceso. Por último, el programador a
corto plazo obtiene el control y selecciona un proceso para su ejecución.

Planificación a largo plazo El programador a largo plazo decide cuándo empezar a


considerar una solicitud para su planificación a mediano y corto plazos. Este hecho se deno-
mina admisión de una solicitud. El programador a largo plazo puede postergar la admisión de
una solicitud por dos razones. Puede no estar preparado para asignar recursos suficientes, como
estructuras de datos del kernel o dispositivos de E/S, a una petición cuando ésta llega, o puede
encontrar que la admisión de una solicitud podría afectar de alguna manera el desempeño del
sistema. Por ejemplo, si el sistema contiene actualmente un gran número de solicitudes ligadas
al CPU, podría diferir una nueva solicitud ligada a éste, aunque podría admitir de inmediato una
nueva ligada a E/S.
La planificación a largo plazo no es relevante si toda petición que llega puede ser admi-
tida de inmediato para su procesamiento, por ejemplo, en un SO de tiempo compartido capaz
de crear recursos virtuales cuando es necesario. No obstante, la planificación a largo plazo se
utilizó en las décadas de los sesenta y setenta para planificación de tareas porque el equipo de
cómputo era costoso y los sistemas de computadoras tenían recursos limitados. Sigue siendo
importante en sistemas operativos cuyos recursos son limitados. Su empleo es inevitable si las
solicitudes tienen tiempos límite o si un conjunto de solicitudes se repite con una periodicidad
conocida.

Planificación a mediano plazo El programador a mediano plazo transforma la gran can-


tidad de solicitudes que han sido admitidas al sistema en un número relativamente menor de
solicitudes que pueden caber en la memoria del sistema en cualquier momento. Así, el programa-
dor se centra en la suspensión o reactivación de procesos mediante la ejecución de operaciones
de suspensión o de activación, de modo que el programador a corto plazo encuentre una cantidad
suficiente de procesos listos. El programador a mediano plazo decide cuándo suspender un pro-
ceso y cuándo activarlo de vuelta en la memoria, modifica el estado del proceso en forma idónea
e introduce su PCB en la lista correcta de PCB. Las operaciones de reactivación y suspensión
actuales se ejecutan en el administrador de la memoria.
La decisión de suspender un proceso es relativamente fácil de tomar. Puede efectuarse cuan-
do un usuario solicita una suspensión, cuando el kernel se queda sin memoria libre o cuando se
encuentra que algún proceso presente en la memoria no tiene probabilidades de ser asignado
al CPU durante mucho tiempo. En sistemas de tiempo compartido, los procesos que se en-
cuentran en los estados bloqueado o listo son candidatos a ser suspendidos (consulte la figura
3.7). La decisión de reactivar un proceso es más complicada. El programador a mediano pla-
zo debe conjeturar cuándo un proceso tiene probabilidades de ser despachado a continuación,
y debe intercambiarlo con el proceso que sigue cronológicamente. El programador puede
sustentar su conjetura en la posición que ocupa un proceso en la lista de planificación. Las
decisiones de intercambio pueden tomarse en forma periódica o cuando ocurre un evento
relacionado.

05 MAQ. CAP. 04(F0694).indd 158 8/10/07 12:58:51 AM


4.4 La planificación en la práctica 159

Planificación a corto plazo Este tipo de planificación se ocupa del empleo eficiente del
CPU. Aquí se elige un proceso de una lista de procesos listos, se decide durante cuánto tiempo
debe ejecutarse el proceso y se hace lo necesario para producir un interruptor de tiempo en la
medida en que transcurre el tiempo. A continuación, el proceso elegido se entrega al mecanismo
de despacho.
En resumen, el programador a largo plazo selecciona los procesos que deben considerarse
para su programación por el programador a mediano plazo, que a su vez elige los procesos que
deben considerarse para su programación por el programador a corto plazo, y éste seleccio-
na procesos que deben ejecutarse en el CPU. Cada programador aplica sus propios criterios
concernientes al uso de recursos y a la calidad del servicio a fin de elegir los procesos para la
siguiente etapa de planificación. En las siguientes secciones se analizarán la naturaleza e impor-
tancia de las actividades de planificación a largo, mediano y corto plazos en diversos sistemas
operativos.

Planificación en el procesamiento por lotes, multiprogramación


y tiempo compartido

En un sistema de procesamiento por lotes, un lote de tareas se presenta para su procesamiento;


sin embargo, sólo se procesa una tarea a la vez en cualquier momento. El funcionamiento del
programador a largo plazo es trivial porque todos los recursos del sistema se dedican a una tarea
en cualquier instante y las tareas se procesan en orden FCFS: simplemente admite la siguiente
tarea del lote una vez que ha terminado la tarea precedente. El programador a corto plazo plani-
fica de inmediato la tarea admitida. La planificación a mediano plazo está ausente porque no se
lleva a cabo intercambio alguno. Una vez que se termina la tarea, el programador a largo plazo
admite la siguiente tarea del lote.
En un sistema de multiprogramación, la admisión de una tarea puede postergarse debido
al desempeño del sistema y a la carencia de recursos. El programador a largo plazo admite una
tarea cuando todos los recursos que ha solicitado pueden asignarse y la admisión no afecta la
mezcla en el sistema de tareas ligadas al CPU y tareas ligadas a E/S. La planificación a mediano
plazo está ausente porque no se lleva a cabo ningún intercambio en el sistema.
En la figura 4.7 se ilustra la planificación a largo, mediano y corto plazos en un sistema de
tiempo compartido. El programador a largo plazo admite un proceso cuando pueden asignársele
recursos del kernel —como los bloques de control— y otros recursos —como los dispositivos
de E/S. Asigna espacio de intercambio para los procesos en un disco, copia el código del proceso
en el espacio de intercambio y agrega el proceso a la lista de procesos intercambiados.
El programador a mediano plazo controla el intercambio de los procesos y los mueve entre
las listas intercambiado suspendido, bloqueado y listo. Siempre que el CPU está libre, el progra-
mador a corto plazo elige un proceso de la lista procesos listos para ejecutarlo. El mecanismo de
despacho inicia o resume la ejecución del proceso elegido en el CPU. Debido al intercambio, un
proceso puede moverse entre los programadores a mediano y corto plazos muchas veces.
Con base en este análisis, se observa que la planificación a largo plazo casi siempre está
ausente en los sistemas operativos modernos y que la planificación a mediano plazo suele estar
confinada al intercambio de los procesos. En las siguientes secciones se analizará la implemen-
tación de la planificación a corto plazo.

05 MAQ. CAP. 04(F0694).indd 159 8/10/07 12:58:51 AM


160 CAPÍTULO 4 Planificación

Lista de procesos
Procesos que
han llegado

Programador
a largo
plazo
Procesos listos
intercambiados,
procesos bloqueados
intercambiados
Suspen- Reac-
didos tivado
Programador
a mediano Procesos
plazo bloqueados

Procesos
listos
Programador
a corto
plazo

CPU

Figura 4.7 Planificación a largo, mediano y corto plazos en un sistema de tiempo compartido.

4.4.2 Planificación del proceso

A menudo, el programador a corto plazo suele denominarse programador del proceso. Usa una
lista de procesos listos y decide cuál de ellos ejecutar y durante cuánto tiempo.
En la figura 4.8 se muestra un esquema del programador de proceso. La lista de procesos
listos se mantiene como una lista de sus bloques de control de procesos. Otras listas BCP repre-
sentan procesos bloqueados y suspendidos. La organización y el uso de las listas BCP dependen
de la política de planificación. Cuando el programador del proceso recibe el control, elige un pro-
ceso para ejecutarlo. Luego invoca al mecanismo de despacho del sistema, que carga en el CPU
el contenido de dos campos BCP: los campos de registros PSW y CPU, para resumir la ejecución
del proceso elegido. Así, el mecanismo de despacho se enlaza con el módulo de política por un
lado y con el hardware por otro.
El mecanismo para guardar el contexto forma parte del manejo de la interrupción. Se invoca
cuando ocurre una interrupción para guardar los registros PSW y CPU del proceso interrumpido.
El cálculo de prioridad y el mecanismo de reordenamiento vuelven a calcular la prioridad de las
solicitudes y reordenan las listas BCP para reflejar las nuevas prioridades. Este mecanismo es
invocado explícitamente por el módulo de política cuando es conveniente o bien periódicamente.
Sus acciones exactas dependen de la política de planificación que esté en uso.
En las siguientes secciones se analizan los principios y la implementación de las políticas de
planificación del proceso que están en uso.

05 MAQ. CAP. 04(F0694).indd 160 8/10/07 12:58:51 AM


4.4 La planificación en la práctica 161

Política de Listas
planificación BCP

Mecanismos de Cálculo de
Despacho Guardar el prioridad y re-
planificación del proceso contexto ordenamiento

Hardware
Flujo de control
Flujo de datos

Figura 4.8 Mecanismo y módulos de la política de planificación del proceso.

4.4.3 Planificación basada en prioridades

Este tipo de planificación ofrece tiempos de respuesta aceptables a procesos de alta prioridad
y buen rendimiento. En la sección 2.5 se analizó la planificación basada en prioridades que
se utiliza en sistemas de multiprogramación. A continuación se presentan sus características
principales:
1. En el sistema existe una mezcla de procesos limitados por el CPU o ligados a E/S.
2. La prioridad de un proceso ligado a E/S es superior a la de uno limitado por el CPU.
3. Las prioridades del proceso son estáticas, es decir, no cambian con el tiempo.
4. La planificación del proceso es priorizante; un proceso en funcionamiento de baja prio-
ridad es priorizado si un proceso con prioridad más alta se convierte en listo (consulte el
ejemplo 2.8). En efecto, un proceso de baja prioridad no puede ser en funcionamiento si
en el estado listo existe algún proceso de prioridad más elevada.
Estas características se usan a fin de desarrollar un esquema para la planificación basada en
prioridades.
El programador puede mantener listas separadas de procesos listos y bloqueados, y elegir
siempre el proceso de prioridad más alta de la lista de procesos listos. No obstante, las prioridades
de los procesos son estáticas y la planificación es priorizante. Por tanto, un arreglo más simple
puede diseñarse como se indica a continuación: el programador puede mantener una simple lista
de BCP donde éstos se disponen en orden decreciente de prioridades. Puede explorar esta lista y
simplemente elegir el primer proceso listo que encuentre. Éste es el proceso listo de mayor priori-
dad que hay en el sistema. La planificación basada en prioridades se resume en la tabla 4.8.
Además de la lista BCP, el programador mantiene un indicador denominado apuntador al
proceso actualmente en ejecución (apuntador CRP). Este apuntador señala al BCP del proceso
que se encuentra en el estado en funcionamiento. Cuando ocurre una interrupción, el mecanismo
de guardar el contexto guarda los registros PSW y CPU en campos idóneos de esta BCP.

05 MAQ. CAP. 04(F0694).indd 161 8/10/07 12:58:52 AM


162 CAPÍTULO 4 Planificación

Tabla 4.8 Planificación sencilla basada en prioridades

1. Una sola lista de BCP se mantiene en el sistema.


2. Los BCP en la lista se organizan en orden decreciente de prioridades.
3. El BCP de un proceso de reciente creación entra en la lista de acuerdo con su prioridad.
4. Una vez que termina un proceso, su BCP se elimina de la lista.
5. El programador explora la lista de BCP desde el principio y planifica el primer proceso listo que
encuentra.

¿Qué debe hacer el programador si en el sistema no hay procesos listos? Sencillamente,


debe “congelar” el CPU, de modo que éste no ejecute ninguna instrucción, sino que permanezca
en un estado interrumpible; así, la ocurrencia de un evento puede ser procesada por el manejo de
eventos. Si la arquitectura carece de un estado “congelar” para el CPU, entonces el programador
puede obtener fácilmente un efecto equivalente definiendo un proceso falso que contenga un
ciclo infinito. (Éste es un proceso del sistema, en contrapartida de otros que son del usuario.)
Este proceso siempre se encuentra en el estado listo. Se le asigna la prioridad más baja, de modo
que es programado sólo cuando en el sistema hay procesos no listos. Una vez programado, este
proceso se ejecuta hasta que algún proceso con prioridad más alta se convierte en listo; entonces
es priorizado.

Proceso con Proceso con


la prioridad la prioridad Proceso
más alta más baja falso
Apuntador P1 P2 P3 Pn
de la lista
BCP en
bloqueado bloqueado bloqueado funcionamiento
a) Apuntador CRP
Apuntador P1 P2 P3 Pn
de la lista
BCP en
bloqueado funcionamiento bloqueado listo

Apuntador CRP
b)

Figura 4.9 Planificación basada en prioridades.

Ejemplo 4.8 En la figura 4.9a) se ilustra la situación en la que todos los procesos del usuario
están bloqueados. La única BCP que muestra un proceso en el estado listo es la correspondiente al
proceso falso. El programador elige a éste y lo despacha. En la figura 4.9b) se muestra la situación
después de que el proceso P2 se convierte en listo. La BCP de P2 es la primera BCP en la lista
BCP que muestra un proceso en el estado listo, de modo que P2 se planifica y el apuntador CRP se
establece para señalarlo. (El estado del proceso falso pudo haber cambiado a listo por el manejo de
la interrupción antes de llevarse a cabo la planificación.)

05 MAQ. CAP. 04(F0694).indd 162 8/10/07 12:58:52 AM


4.4 La planificación en la práctica 163

4.4.4 Planificación round-robin

Este tipo de planificación puede implementarse organizando la lista de procesos listos como
una cola. El programador siempre elige el primer proceso de la cola. Si el intervalo de tiempo
trascurre durante la ejecución de un proceso, éste se coloca al final de la cola. Un proceso que
inicia una operación de E/S se retira de la cola de procesos listos. Se agrega al final de la lista una
vez que termina la operación de E/S. Un proceso que se encuentra en la cola de procesos listos
avanza paulatinamente al inicio de la cola y es planificado.
La planificación round-robin se maneja mejor si se mantienen dos listas de BCP. Una
debe contener BCP de procesos listos, mientras que la otra debe contener BCP de procesos
bloqueados e intercambiados suspendidos. La lista de procesos listos debe organizarse como
una cola. Debido a que los procesos bloqueados e intercambiados suspendidos se ignoran para
efectos de la planificación, no es necesario mantener su lista BCP en algún orden específico.
Cuando cambia el estado de algún proceso, el programador cambia la BCP del proceso de una
lista BCP a otra. En la tabla 4.9 se resume la planificación round-robin.

Tabla 4.9 Planificación round-robin

1. El programador mantiene una cola de procesos listos y una lista de procesos bloqueados e inter-
cambiados suspendidos.
2. El BCP de un proceso de reciente creación se agrega al final de la cola de listos. El BCP de un
proceso que está terminando se elimina de las estructuras de datos de planificación.
3. El programador siempre elige el BCP que se encuentra a la cabeza de la lista de listos.
4. Cuando un proceso en funcionamiento termina su intervalo de tiempo, se mueve al final de la lista
de procesos listos.
5. El manejo de eventos realiza las siguientes acciones:
a) Cuando un proceso hace una solicitud de E/S o es intercambiado suspendido, su BCP se elimi-
na de la lista de procesos listos y pasa a la lista de bloqueados/intercambiados suspendidos.
b) Cuando termina la operación de E/S esperada por un proceso o el proceso es intercambiado
activado, su BCP se elimina de la lista bloqueados/intercambiados suspendidos y se agrega al
final de la cola de procesos listos.

Ejemplo 4.9 En la figura 4.10 se muestra la lista de procesos listos de un programador de tiempo
compartido en diferentes momentos durante la operación del sistema. En la figura 4.10a) se mues-
tra la lista de procesos listos cuando se está ejecutando el proceso P3. Si éste inicia una operación
de E/S, se desplaza a la cola de procesos bloqueados. Ahora la lista de procesos listos se ve como
se muestra en la figura 4.10b). Una vez que termina la operación de E/S, P3 se agrega al final de la
lista de procesos listos (consulte la figura 4.10c)). Mientras tanto, el proceso P2 ha terminado y se
ha creado uno nuevo, el proceso P7.

4.4.5 Planificación de multinivel

La eficacia y un servicio aceptable del usuario proyectan requerimientos contradictorios sobre


el programador, de modo que éste tiene que sacrificar tales características entre sí. La multi-
programación y el tiempo compartido representan posiciones extremas en este sacrificio. La

05 MAQ. CAP. 04(F0694).indd 163 8/10/07 12:58:53 AM


164 CAPÍTULO 4 Planificación

a) Lista de procesos listos P3 P2 P8 P9

b) P2 P8 P9

c) P8 P9 P7 P3

Figura 4.10 Listas de procesos listos en un sistema de tiempo compartido.

multiprogramación proporciona elevados niveles de eficacia, pero no es capaz de garantizar un


servicio del usuario aceptable, mientras el tiempo compartido proporciona buenos tiempos de
respuesta, aunque no es capaz de garantizar una eficacia elevada debido a su alta sobrecarga
de planificación. La planificación de multinivel ofrece una solución híbrida al problema de
garantizar la eficiencia y un buen servicio de usuario simultáneamente.
Un planificador multinivel mantiene un número de peticiones listas. Los procesos en peti-
ciones diferentes tienen prioridades y tiempos de intervalos de petición diversos. Los procesos
con una prioridad alta reciben tiempos de intervalos pequeños, de manera que obtienen tiem-
pos de respuesta buenos. En los procesos con baja prioridad se espera que mantengan el CPU
ocupado, de este modo proveen buena eficiencia, y reciben grandes tiempos de intervalos. La
tabla 4.10 resume las características de un planificador multinivel.

Tabla 4.10 Planificación de multinivel

1. El programador usa muchas listas de procesos listos.


2. Cada lista de procesos listos posee un par de atributos (intervalo de tiempo, prioridad en la plani-
ficación) asociados con ella. El intervalo de tiempo para una lista es inversamente proporcional a
la prioridad de la lista. Todo proceso en una lista de procesos listos recibe el intervalo de tiempo y
la prioridad en la planificación asociadas con la lista.
3. Los procesos en una lista de procesos listos son considerados para planificación sólo cuando todas
las listas de procesos listos con prioridad más alta están vacías.
4. En cada lista se lleva a cabo planificación round-robin.

Para explotar las características de la planificación de multinivel, el programador establece


la diferencia entre procesos: altamente interactivos, moderadamente interactivos y no interacti-
vos. El programador coloca los procesos altamente interactivos en la cola con prioridad más alta.
Para estos procesos es idóneo un pequeño intervalo de tiempo, por lo cual reciben muy buenos
tiempos de respuesta [consulte la ecuación (2.2)]. Los procesos moderadamente interactivos
también pueden colocarse en la misma cola, aunque pueden degradar los tiempos de respuesta
hasta procesos altamente interactivos y provocar una elevada sobrecarga de planificación debido
a un intercambio excesivo entre procesos, de modo que el programador los coloca en listas
de procesos listos con prioridades medias, donde reciben intervalos de tiempo más grandes.
Los procesos no interactivos se colocan en la lista de procesos listos de menor prioridad. Estos
procesos reciben el intervalo de tiempo más grande. Tal característica reduce la sobrecarga de

05 MAQ. CAP. 04(F0694).indd 164 8/10/07 12:58:53 AM


4.4 La planificación en la práctica 165

planificación en el sistema. Si se usan más de tres listas de procesos listos, otros procesos ocupan
niveles intermedios de planificación, dependiendo de cuán interactivos sean.

Ejemplo 4.10 En la figura 4.11 se ilustra un arreglo eficaz de listas de procesos listos en un
programador de multinivel. Para cada valor de prioridad se mantiene una lista por separado
de procesos listos. El encabezado de cada lista contiene un apuntador hacia el BCP del primer
proceso existente en la lista. También contiene un apuntador hacia el encabezado de la lista para
la siguiente prioridad más baja. El programador explora los encabezados en orden decreciente de
prioridad y elige el primer proceso que encuentra en la primera lista no vacía. Así, la sobrecarga
de planificación depende del número de prioridades distintas más que del número de procesos lis-
tos. El BCP de un proceso contiene un campo de nivel de planificación adicional. Siempre que un
proceso bloqueado se vuelve listo, el manejo de eventos usa este campo para identificar la lista
de procesos listos a la que debe agregarse.

P1 P4 P8 Lista con la prioridad más alta

Lista con prioridad inferior


P7 P5 a la prioridad más alta
..
.
P10 P3 Lista con la prioridad más baja

Figura 4.11 Listas de procesos listos en un programador de multinivel.

El modelo de planificación de multinivel hereda algunas desventajas del modelo de multi-


programación. Requiere que los procesos sean clasificados según su naturaleza ligada al CPU o
a E/S. Además, la clasificación es estática; por ejemplo, un proceso sólo es clasificado una vez
durante su existencia, por lo que una mala clasificación degradaría tanto el servicio del usuario
como el desempeño del sistema. El modelo de planificación tampoco es capaz de manejar nin-
gún cambio en el comportamiento computacional o de E/S de un proceso durante su existencia.
Como se vio en el ejemplo 4.10, los procesos que están en el nivel de prioridad más baja pueden
desaparecer por inanición.

Planificación adaptativa de multinivel (también denominada Planificación de multini-


vel con retroalimentación) Un programador adaptativo de multinivel intenta mantener un pro-
ceso en el nivel de planificación “correcto”, de modo que recibe una combinación idónea de
prioridad e intervalo de tiempo. El programador observa cómo el proceso ha utilizado reciente-
mente el CPU y E/S a fin de determinar el nivel de planificación correcto del proceso, para así
moverlo a dicho nivel. De esta forma, el programador se adapta a cambios en el comportamiento
computacional y de E/S de los procesos. De esta forma, un proceso puede estar ligado a E/S du-
rante una fase de su existencia y ligado al CPU durante otra, y aún así puede seguir recibiendo
una prioridad y un intervalo de tiempo idóneos. Esta característica elimina los problemas re-
lacionados con una asignación de antemano de las propiedades estáticas y garantiza tanto los
tiempos de respuesta como la eficacia del CPU.

CTSS El sistema de tiempo compartido compatible (compatible time sharing system) de


la IBM 7094 fue uno de los primeros sistemas de tiempo compartido. Usaba planificación adap-

05 MAQ. CAP. 04(F0694).indd 165 8/10/07 12:58:53 AM


166 CAPÍTULO 4 Planificación

tativa de multinivel con una estructura de prioridad de ocho niveles. Los niveles de prioridad
estaban numerados del 0 al 7. El nivel con el número n tenía asociado un intervalo de tiempo de
0.5  2n segundos de CPU. Durante la inicialización, cada proceso del usuario se colocaba en los
niveles 2 o 3, dependiendo de su requerimiento de memoria. La política de ascenso o descenso
era como se describe a continuación: si un proceso ha utilizado por completo el intervalo de
tiempo en su nivel de planificación actual (por ejemplo, por no haber iniciado ninguna operación
de E/S), es descendido al siguiente nivel con el número más alto; en caso contrario, permanece
en el mismo nivel. Un proceso es ascendido al siguiente nivel con el número más bajo si pasa
más de un minuto en el estado listo en su nivel actual sin haber obtenido ningún servicio de CPU.
Además, cualquier proceso que ejecuta operaciones E/S en la terminal del usuario es ascendido
al nivel 2. Posteriormente, debe migrar a su sitio “correcto” en la estructura de prioridades a
través de descensos posibles.

Ejemplo 4.11 En la figura 4.12 se muestran ascensos y descensos en la planificación adaptativa


de multinivel tipo CTSS. En la figura 4.12a) se muestra el proceso P3 en ejecución, ubicado en
la parte superior de la cola de procesos listos de más alta prioridad. Los procesos P5, P8 y P7 se
encuentran en listas con prioridad inferior. El proceso P3 usa por completo su intervalo de tiempo,
por lo que es descendido al nivel 2. Poco después, el proceso P7 es ascendido al nivel 2 porque ha
permanecido más de un minuto en el nivel 3. En la figura 4.12b) se muestran las listas de procesos
listos resultantes.

nivel 1 P3 P2 nivel 1 P2

nivel 2 P5 nivel 2 P5 P3 P7

nivel 3 P8 P7 nivel 3 P8
a) b)
Figura 4.12 Ejemplo de planificación adaptativa de multinivel.

4.4.6 Planificación de compartición equitativa


Una crítica común a todas las políticas de planificación que se han analizado hasta el momento
es que son ajenas a las relaciones que hay entre los procesos y los usuarios. Suponen que cada
proceso pertenece a un usuario distinto e intentan proporcionar un servicio equitativo a todos
los procesos. Si las aplicaciones iniciadas por los usuarios crean cantidades diferentes de pro-
cesos, entonces una aplicación que utiliza más procesos tiene probabilidades de recibir más
atención del CPU que una que utiliza menos procesos.
El concepto de compartición equitativa se encarga de esta cuestión. Una compartición
equitativa es la fracción de tiempo de CPU que debe dedicarse a la ejecución de un grupo de
procesos que pertenecen al mismo usuario o a la misma aplicación. El programador considera
un proceso de un grupo para planificarlo sólo si el grupo no ha utilizado su compartición equi-
tativa de tiempo de CPU, y fija el valor del intervalo de tiempo para el proceso de modo que
el grupo no exceda su compartición equitativa de tiempo de CPU al término del intervalo de
tiempo. Esta política asegura un uso equitativo del CPU de parte de los procesos que pertenecen
a usuarios o a aplicaciones diferentes.

05 MAQ. CAP. 04(F0694).indd 166 8/10/07 12:58:54 AM


4.4 La planificación en la práctica 167

Observe que la compartición actual del tiempo de CPU recibido por un grupo de procesos
puede diferir de la compartición equitativa del grupo debido a la falta de actividad en sus pro-
cesos o en procesos de otros grupos. Por ejemplo, considere dos grupos G1 y G2 de procesos,
cada uno de los cuales posee una compartición de 50 por ciento del tiempo de CPU. Si todos los
procesos en G1 están dormidos, entonces a los procesos en G2 debe asignárseles 100 por ciento
del tiempo de CPU disponible a fin de no desperdiciar el tiempo de CPU. ¿Qué debe hacer
el programador cuando los procesos en G1 se activen después de haber estado dormidos un
lapso prolongado? ¿Se les debe asignar sólo 50 por ciento del tiempo de CPU luego de que
despierten, debido a que ésta es su compartición equitativa de tiempo de CPU, o el progra-
mador debe asignarles casi todo el tiempo de CPU disponible hasta que su consumo actual de
CPU desde su inicio sea igual a 50 por ciento?
La planificación de loterías es una técnica reciente propuesta para compartir un recurso de
manera probabilísticamente equitativa. Los “billetes” de lotería se distribuyen entre todos los
procesos (o aplicaciones) que comparten un recurso, de modo que un proceso obtiene tan-
tos billetes como su compartición equitativa del recurso. Por ejemplo, a un proceso se le asignarán
cinco billetes de un total de 100 si su compartición equitativa del recurso es igual a 5 por ciento.
Cuando va a asignarse el recurso, se lleva a cabo una lotería para elegir aleatoriamente un billete
ganador de entre todos los repartidos entre los procesos que de manera activa buscan el recurso.
Luego, al proceso poseedor del billete ganador se le asigna el recurso. La compartición actual
de los recursos asignados al proceso depende de la disputa por el recurso. La planificación de
loterías puede usarse para la compartición equitativa de la planificación de CPU como se des-
cribe a continuación: los billetes pueden emitirse para las aplicaciones (o para los usuarios)
con base en su compartición equitativa del tiempo de CPU. Una aplicación puede compartir sus
billetes entre sus procesos de cualquier forma en que lo disponga. Para asignar un intervalo de
tiempo del CPU, el programador lleva a cabo una lotería en la que sólo participan billetes
de procesos listos. Cuando el intervalo de tiempo es de unos cuantos milisegundos, este método de
planificación proporciona imparcialidad incluso a fracciones de segundo si todos los grupos
de procesos están activos.

4.4.7 Administración de energía

En la sección 4.4.3 se vio cómo el kernel coloca el CPU en un ciclo infinito que no hace nada
cuando no existe ningún proceso listo. Esta solución desperdicia energía en la ejecución de
instrucciones inservibles. En sistemas carentes de energía, como los sistemas incrustados y mó-
viles, resulta esencial evitar este desperdicio de energía.
A fin de abordar este requerimiento, las computadoras cuentan con un modo especial en
el CPU. Cuando la computadora funciona en este modo, el CPU no ejecuta instrucciones, con
lo cual se conserva la energía; no obstante, el CPU puede aceptar interrupciones y reanudar la
operación normal cuando se presenta una interrupción. Se usará la expresión modo dormido del
CPU para designar de manera genérica tales modos.
Algunas computadoras cuentan con varios modos dormido. En el modo dormido “ligero”,
el CPU sencillamente deja de ejecutar instrucciones. En un modo dormido “pesado”, el CPU no
sólo deja de ejecutar instrucciones sino que también realiza otros pasos que reducen su consumo
de energía; por ejemplo, al hacer más lento el reloj y desconectar el CPU del bus del sistema. De
forma ideal, el kernel debe colocar el CPU en el modo dormido más profundo posible cuando
el sistema no tiene procesos en el estado listo. No obstante, un CPU consume más tiempo para

05 MAQ. CAP. 04(F0694).indd 167 8/10/07 12:58:54 AM


168 CAPÍTULO 4 Planificación

“despertar” de un modo dormido pesado del que consumiría para “despertar” de un modo dor-
mido ligero, de modo que el kernel está obligado a negociar en este caso. Empieza colocando
el CPU en el modo dormido ligero. Si durante algún tiempo ningún proceso pasa al estado listo,
entonces establece el CPU en un modo dormido más pesado, y así sucesivamente. De esta forma,
sólo conserva la energía que puede sin sacrificar demasiado los tiempos de respuesta.
Sistemas operativos como Unix y Windows cuentan con administración de energía gene-
ralizada para incluir a todos los dispositivos. Comúnmente, un dispositivo es colocado en un
estado de consumo de energía inferior como si hubiera estado inactivo en su estado de con-
sumo de energía presente durante algún tiempo. A los usuarios también se les proporcionan
servicios con los cuales pueden configurar el esquema de administración de energía utilizado
por el SO.

4.5 PLANIFICACIÓN EN TIEMPO REAL

Las aplicaciones en tiempo real a menudo imponen algunas restricciones especiales para la pla-
nificación, además de la conocida necesidad de satisfacer tiempos límite. En primer lugar, los
procesos dentro de una aplicación en tiempo real son interactivos y entre ellos pueden tener prio-
ridades determinadas por la naturaleza de la aplicación; en segundo lugar, los procesos pueden
ser periódicos. Estas restricciones se ilustran en el ejemplo 4.12.

Ejemplo 4.12 Considere la aplicación en tiempo real de descarga de datos del ejemplo 3.1. Los
procesos copy_sample y disk_write interactúan para utilizar la memoria intermedia. Muestras de
datos llegan en intervalos de 100 microsegundos; es importante que sea posible copiar una muestra
antes de que llegue la muestra siguiente. Para lograr lo anterior, a copy_sample se le asigna una
prioridad más alta que a los demás procesos de la aplicación. Este proceso también debe ejecutarse
con una periodicidad de 100 microsegundos.

Ninguna de las políticas de planificación analizadas hasta el momento toma en cuenta estos
tiempos límite o estas restricciones, de modo que un sistema operativo en tiempo real requiere
políticas de planificación especiales.

4.5.1 Precedencia de procesos y planificaciones factibles

Los procesos de una aplicación en tiempo real interactúan entre ellos a fin de asegurar que
realizan sus acciones en el orden deseado. Aquí se establece la hipótesis de simplificación de
que esta interacción se lleva a cabo sólo al principio o al final de un proceso. Esto provoca de-
pendencia entre los procesos, lo cual debe tomarse en cuenta al determinar los tiempos límite
y al llevar a cabo la planificación. Se utiliza una PPG para representar tales dependencias entre
procesos.
Se dice que el proceso Pi precede al proceso Pj si la ejecución de Pi debe terminar antes
de que Pj pueda iniciar su ejecución. La notación Pi → Pj indica que el proceso Pi precede
directamente al proceso Pj. La relación de precedencia es transitiva; por ejemplo, Pi → Pj y
∗ P se usa para indicar que el proceso P
Pj → Pk implican que Pi precede a Pk. La notación Pi → k i
precede directa o indirectamente a Pk.

05 MAQ. CAP. 04(F0694).indd 168 8/10/07 12:58:54 AM


4.5 Planificación en tiempo real 169

Una gráfica de precedencia de procesos es una gráfica dirigida G ⬅ (N, E) tal que Pi 僐 N
representa un proceso, y una arista (Pi, Pj) 僐 E implica Pi → Pj. Así, una ruta Pi . . . Pk en PPG
∗ P . Un proceso P es descendiente de P si P → ∗ P.
implica Pi → k k i i k
En la sección 2.7 se definió un sistema en tiempo real duro como un sistema capaz de
satisfacer de manera garantizada el requerimiento de tiempo de respuesta de una aplicación en
tiempo real, incluso cuando se requieran acciones de tolerancia predeterminadas. Esta condición
implica que el tiempo requerido por el SO para terminar la operación de todos los procesos en la
aplicación no excedan el requerimiento de respuesta de la aplicación. Por otra parte, un sistema en
tiempo real blando cumple el requerimiento de respuesta de una aplicación sólo de manera pro-
babilística, y no necesariamente todas las veces. El concepto de planificación factible ayuda a
diferenciar entre estas situaciones.

Definición 4.1 (Planificación factible) Una planificación factible para procesos de una
aplicación es una sucesión de decisiones de planificación que permite a los procesos operar
según sus precedencias y cumplir el requerimiento de respuesta de la aplicación.

La planificación en tiempo real se centra en la determinación e implementación de una pla-


nificación factible para una aplicación, en caso de existir. Considere una aplicación para actuali-
zar cada 15 segundos los horarios de salida de vuelos en las pantallas de información al público.
Esta aplicación consta de los procesos independientes siguientes, donde el proceso P3 manipula
una situación excepcional que ocurre muy rara vez.

Proceso P1 P2 P3 P4 P5
Tiempo de servicio 3 3 2 4 5

No existe una planificación factible para terminar en 15 segundos los cinco procesos, por lo que
debe ocurrir un rebase del tiempo límite. No obstante, cuando el proceso P5 no está activo son
posibles varias planificaciones. El programador en un sistema en tiempo real blando puede en-
contrar cualquiera de ellas y usarla.
En la tabla 4.11 se resumen tres métodos fundamentales para planificación en tiempo real. A
continuación se analizan las características y propiedades de estos métodos de planificación.

Planificación estática Como indica su denominación, antes de poner en marcha el sistema


se prepara una planificación. Ésta consta de las precedencias, periodicidades, restricciones de
recursos y posibilidades de traslapar operaciones de E/S en un proceso que tiene cálculos en otro
proceso. Esta planificación se representa en forma de tabla, cuyos renglones indican el momento
de inicio de la ejecución de procesos diferentes. Durante la operación del sistema no se realiza
decisión alguna de planificación. El SO en tiempo real simplemente consulta la tabla y empie-
za la ejecución de los procesos según está indicado ahí.
El tamaño de la tabla de planificación depende de la periodicidad de los procesos. En caso
de que éstos no sean periódicos, o si todos tienen la misma periodicidad, entonces la tabla de
planificación sólo posee tantos renglones como el número de procesos haya en la aplicación.
Esta planificación se utiliza de manera repetida durante la operación del sistema. Si las periodi-
cidades de los procesos son diferentes, entonces la longitud de la planificación que es necesario

05 MAQ. CAP. 04(F0694).indd 169 8/10/07 12:58:54 AM


170 CAPÍTULO 4 Planificación

Tabla 4.11 Planificación en tiempo real

Planificación Antes de empezar la ejecución de la aplicación, se prepara una planificación.


estática Durante la elaboración de la planificación se toman en consideración las in-
teracciones, periodicidades, restricciones de recursos y tiempos límite de los
procesos.
Planificación basada La aplicación en tiempo real se analiza para asignar prioridades apropiadas a
en prioridades los procesos que preceden. Durante la operación de la aplicación se usa plani-
ficación convencional basada en prioridades.
Planificación La planificación se lleva a cabo una vez que se ejecuta una petición para crear
dinámica el proceso. La creación del proceso tiene éxito sólo si es posible garantizar el
cumplimiento de los requerimientos de respuesta del proceso.

representar en la tabla de planificación es el mínimo común múltiplo de todos los procesos


existentes en la aplicación.
La planificación estática conduce a sobrecarga de planificación despreciable durante la ope-
ración del sistema. Sin embargo, es inflexible e incapaz de manipular cuestiones como la to-
lerancia a fallos.

Planificación basada en prioridades Un análisis del sistema considera dos cosas mien-
tras asigna prioridades a los procesos: el carácter crítico de los procesos según se analizó en
el ejemplo 4.12 y la periodicidad de los procesos. Un proceso con menor periodicidad requiere
ejecutarse más a menudo que uno con mayor periodicidad. Por tanto, la periodicidad de un pro-
ceso debe depender inversamente de su periodicidad.
Durante la operación del sistema, las prioridades de los procesos se usan para tomar deci-
siones de planificación. La planificación basada en prioridades proporciona más flexibilidad que
la planificación estática; sin embargo, durante la operación, el sistema incurre en sobrecarga de
planificación. La planificación basada en prioridades es capaz de manipular en forma natural
algunas formas de fallos, ya que los procesos de alta prioridad siguen obteniendo un tratamiento
favorable en la medida en que haya disponibilidad de los recursos necesarios.

Planificación dinámica En los sistemas que utilizan el método de planificación dinámica,


la planificación se lleva a cabo durante la operación del sistema. Comúnmente, una decisión de
planificación se toma cuando llega un proceso. Los sistemas multimedia, como video sobre
demanda, utilizan un método de planificación dinámica. Una solicitud para iniciar un proceso
contiene información, como el requerimiento de recursos del proceso, el tiempo de servicio y
un tiempo límite o alguna especificación de la calidad del servicio. Al recibir una solicitud de
inicio de un proceso, el programador verifica si es posible asignar los recursos necesarios por el
proceso y asegura un tiempo límite o alguna calidad de servicio esperada. Éste acepta el proceso
sólo si su verificación es exitosa.
Otro enfoque de la planificación dinámica consiste en admitir con optimismo procesos para
su ejecución. Con este planteamiento no hay ninguna garantía de que pueda cumplirse el tiempo
límite o la calidad del servicio deseada por un proceso. Los sistemas en tiempo real blando a
menudo obedecen a este enfoque.

05 MAQ. CAP. 04(F0694).indd 170 8/10/07 12:58:55 AM


4.5 Planificación en tiempo real 171

4.5.2 Planificación con tiempo límite


Para cada proceso es posible definir dos tipos de tiempos límite: una de inicio, o el último ins-
tante en el que debe empezar la ejecución del proceso; y una de terminación, o el momento en el
que la ejecución del proceso debe estar terminada.

Estimación del tiempo límite Un análisis a profundidad de una aplicación en tiempo real
y sus requerimientos de respuesta se lleva a cabo durante su desarrollo. Los tiempos límite de los
procesos individuales pueden determinarse al considerar procedencias de procesos y, trabajando
hacia atrás, a partir del requerimiento de respuesta de la aplicación. Por consiguiente, el tiempo
límite de un proceso Pi es
Di  Daplicación
k僐descendiente(i) xk (4.3)
donde Daplicación es al tiempo límite de la aplicación, xk es el tiempo de servicio del proceso Pk
y descendiente (i) es el conjunto de descendientes de Pi en el PPG, es decir, el conjunto de todos
los procesos que están en alguna ruta entre Pi y el nodo de salida del PPG. Así, el tiempo límite
para un proceso Pi es tal que si se cumple, todos los procesos que directa o indirectamente depen-
den de Pi también pueden terminar antes de que se venza al tiempo límite global de la aplicación.
Este método se ilustra en el ejemplo 4.13.

2 P1 6 P5

P2 3 5 P3

P4 4

P6 5

Figura 4.13 PPG para un sistema sencillo en tiempo real.

Ejemplo 4.13 En la figura 4.13 se muestra el PPG de una aplicación en tiempo real que contiene 6
procesos. Cada círculo es un nodo de la gráfica y representa un proceso. El número en el círculo indi-
ca el tiempo de servicio de un proceso. Una arista en el PPG corresponde a una restricción de prece-
dencia. Así, el proceso P2 puede iniciarse sólo cuando se termina el proceso P1, el proceso P4 puede
iniciarse sólo cuando se terminan los procesos P2 y P3, y así sucesivamente. Se supone que cada
proceso es limitado por el CPU y que es ejecutado de manera no priorizante. El total de los tiempos
de servicio de los procesos es igual a 25 segundos. Si la aplicación debe producir una respuesta en 25
segundos, entonces las tiempos límite de los procesos serán como se muestra a continuación:

Proceso P1 P2 P3 P4 P5 P6
Tiempo límite 8 16 16 20 20 25

Un método práctico para estimar tiempos límite consiste en incorporar también otras restric-
ciones. Por ejemplo, los procesos pueden ejecutar E/S. Si una operación E/S de un proceso puede

05 MAQ. CAP. 04(F0694).indd 171 8/10/07 12:58:55 AM


172 CAPÍTULO 4 Planificación

traslaparse con la ejecución de algún proceso independiente, entonces el tiempo límite de sus
predecesores (y ancestros) en el PPG puede relajarse en la cantidad del traslape E/S. Por ejem-
plo, los procesos P2 y P3 en la figura 4.13 son independientes entre sí. Si el tiempo de servicio
de P2 incluye 1 segundo de tiempo de E/S, entonces es posible hacer que el tiempo límite de
P1 sea igual a 9 segundos en vez de 8 si la operación E/S de P2 puede traslaparse con el pro-
cesamiento de P3. No obstante, la ejecución traslapada de procesos también debe considerar la
asignación de recursos. Por tanto, la determinación de los tiempos límite es mucho más compli-
cada de lo que se ha descrito aquí.

Planificación del tiempo límite más cercano EDF (Earliest deadline first) Como sugiere
su nombre, esta política siempre elige el proceso con el primer tiempo límite. Considere un
conjunto de procesos en tiempo real que no realizan operaciones E/S. Si seq es la secuencia en
la que los procesos son atendidos por una política de tiempo límite y pos(Pi) es la posición del
proceso Pi en seq, entonces un rebase del tiempo límite ocurre para el proceso Pi sólo si la suma
de su propio tiempo de servicio y los tiempos de servicio de todos los procesos que lo preceden
en seq no exceden su propio tiempo límite; es decir,


k:pos(Pk) pos(Pi) xk Di (4.4)

donde xk es el tiempo de servicio del proceso Pk y Di es al tiempo límite del proceso Pi. Si esta
condición no se cumple, entonces ocurre un rebase del tiempo límite para el proceso Pi.

Tabla 4.12 Operación de la planificación EDF

Proceso Rebase de Procesos en Procesos


Tiempo terminado tiempo límite el sistema programados
0 – 0 P1 : 8 , P2 : 16 , P3 : 16 , P4 : 20 , P5 : 20 , P6 : 25 P1
2 P1 0 P2 : 16 , P3 : 16 , P4 : 20 , P5 : 20 , P6 : 25 P2
5 P2 0 P3 : 16 , P4 : 20 , P5 : 20 , P6 : 25 P3
10 P3 0 P4 : 20 , P5 : 20 , P6 : 25 P4
14 P4 0 P5 : 20 , P6 : 25 P5
20 P5 0 P6 : 25 P6
25 P2 0 – –

Cuando existe un calendario factible, puede demostrarse que la condición 4.4 se cumple
para todos los procesos; es decir, para ningún proceso ocurre un rebase de tiempo límite. En la
tabla 4.12 se ilustra la operación de la política EDF para los tiempos límite del ejemplo 4.13.
La notación P4:20 en la columna Procesos en el sistema indica que el proceso P4 tiene el tiempo
límite 20. Los procesos P2, P3 y P5, P6 poseen tiempos límite idénticos, de modo que usando
la planificación EDF son posibles tres planificaciones distintas a las que se muestran en la tabla
4.12; sin embargo, con ninguno de ellos se incurrirá en rebases de tiempo límite.
Las ventajas más importantes de la planificación EDF son su sencillez y naturaleza no prio-
rizante, con lo cual se reduce la sobrecarga de programación. La planificación EDF constituye

05 MAQ. CAP. 04(F0694).indd 172 8/10/07 12:58:55 AM


4.5 Planificación en tiempo real 173

una política aceptable para la planificación estática porque la existencia de un calendario factible
puede determinarse de antemano, y la ausencia de acciones de planificación durante la operación
implica que es posible obtener 100 por ciento de utilización del CPU si los procesos no realizan
operaciones de E/S o si sus operaciones de E/S pueden traslaparse con cálculos de otros proce-
sos. También es una buena política de planificación dinámica para utilizar en sistemas en tiempo
real blando donde la información del proceso puede no estar disponible de antemano, ya que son
aceptables sobrecargas de planificación ocasionales.
Sin embargo, la planificación EDF no considera los tiempos de servicio de los procesos
mientras prepara un calendario, por lo que puede no desempeñarse bien cuando no existe una
planificación factible. En el ejemplo siguiente se ilustra este aspecto de la planificación EDF.

Ejemplo 4.14 Considere el PPG de la figura 4.13 sin la arista (P5, P6). Contiene dos aplicaciones
independientes, una de las cuales contiene los procesos P1, P4 y P6, mientras que la otra sólo con-
tiene a P5. Si todos los procesos deben terminar en 19 segundos, entonces no existe una planifica-
ción factible. Así, los tiempos límite de los procesos, determinados usando la ecuación (4.3), son
los siguientes:

Proceso P1 P2 P3 P4 P5 P6
Tiempo límite 2 10 10 14 19 19

La planificación EDF puede programar los procesos en la secuencia P1, P2, P3, P4, P5, P6, que
es la misma que en la tabla 4.12, o en la secuencia P1, P2, P3, P4, P6, P5. Los procesos P5 y P6 no
cumplen sus tiempos límite en la primera secuencia, mientras que en la segunda sólo el proceso P5
no la cumple. Sin embargo, no se tiene ningún control respecto a cuál secuencia será elegida por
una implementación de planificación EDF. Así, el número de procesos que pueden experimentar
sobrecargas de planificación en un sistema en tiempo real blando puede no ser óptimo.

4.5.3 Planificación monotónica de tasas

Cuando los procesos en una aplicación son periódicos aunque sus periodicidades sean diferentes,
la existencia de una planificación factible puede determinarse en una forma interesante. Consi-
dere tres procesos independientes que no realizan operaciones E/S:

Proceso P1 P2 P3
Intervalo de tiempo (mseg) 10 15 30
Tiempo de servicio (mseg) 3 5 9

El proceso P1 se repite cada 10 mseg y requiere 3 mseg de tiempo de CPU. Así, la fracción
de tiempo de CPU que usa es 3/10; es decir, 0.30. En forma semejante, las fracciones de tiempo
de CPU que usan P2 y P3 son 5/15 y 9/30; es decir, 0.33 y 0.30. Suman 0.93, de modo que si la
sobrecarga de CPU de la operación del SO es 0, entonces es factible atender estos tres procesos
cuando operan con estas periodicidades. El tiempo de servicio del proceso Pi se denota por xi

05 MAQ. CAP. 04(F0694).indd 173 8/10/07 12:58:56 AM


174 CAPÍTULO 4 Planificación

y para el intervalo de tiempo de Pi se usa la notación tpi. En general, un conjunto de procesos


periódicos P1 ..Pn puede ser atendido por un sistema en tiempo real duro que tenga una sobre-
carga despreciable si

xi
Σ i= 1... n ≤ 1.
tp i

Sigue siendo necesario planificar estos procesos de modo que todos sean capaces de ejecu-
tarse con las periodicidades idóneas. La política de planificación monotónica (RM) de tasas hace
lo anterior como sigue: determina la tasa a la que un proceso debe repetirse; es decir, el número
de repeticiones por segundo, y asigna la tasa en sí como la prioridad del proceso. De esta forma,
un proceso cuya periodicidad sea superior posee una mayor prioridad, con lo que podría operar
más a menudo. Luego emplea una técnica de planificación basada en prioridades para llevar a
cabo la planificación.
En el ejemplo anterior, las prioridades de los procesos P1, P2 y P3 deben ser 1/0.010, 1/0.015
y 1/0.025; es decir, 100, 67 y 45, respectivamente. En la figura 4.14 se muestra cómo operarán
estos procesos. Primero debe planificarse el proceso P1. Se ejecutará una vez y luego permane-
cerá inactivo durante 3 mseg, ya que x1  3 mseg. Luego se programará P2, que se terminará al
cabo de 5 mseg. A continuación se programará P3, aunque será priorizado después de 2 mseg
porque P1 pasa al estado listo por segunda ocasión y así sucesivamente. Como se muestra en la
figura 4.14, el proceso P3 debe terminar en 28 mseg. En ese tiempo, P1 se ha ejecutado tres veces
y P2 se ha ejecutado dos.

P1 3 3 3
P2 5 5
P3 2 2 5

0 10 20 30 tiempo (mseg) →

Figura 4.14 Operación de procesos en tiempo real que usan planificación monotónica de tasas.

No se garantiza que la tasa de la planificación monotónica encuentre una planificación fac-


tible en todas las situaciones. Por ejemplo, si el proceso P3 tuviese un periodo de 27 mseg, su
prioridad sería diferente; sin embargo, las prioridades relativas de los procesos permanecerían
sin cambios. Así, entonces P3 experimentará una sobrecarga de planificación de 1 mseg. Se hu-
biese obtenido una planificación factible si P3 se hubiera planificado en 20 mseg y P1 lo hubiera
hecho en 25 mseg; sin embargo, esto no es posible con planificación RM porque asigna priori-
dades estáticas. Liu y Layland (1973) han demostrado que en la planificación RM no ocurren
rebases del tiempo límite si la fracción de tiempo de CPU usada por procesos en tiempo real no
excede de m(21兾m 1), donde m es el número de procesos. Recuerde que la planificación RM
evitará rebases del tiempo límite en la medida en que para los procesos en consideración exista
una planificación factible.

05 MAQ. CAP. 04(F0694).indd 174 8/10/07 12:58:56 AM


4.6 Planificación en Unix 175

4.6 PLANIFICACIÓN EN UNIX

En la sección 3.5.1 se describieron los estados y las transiciones de los procesos usados en Unix.
Un proceso Unix se encuentra en uno de los tres siguientes modos en cualquier instante:

1. Modo no interrumpible de kernel.


2. Modo interrumpible de kernel.
3. Modo de usuario.

Los procesos que están en el modo no interrumpible de kernel poseen las prioridades más al-
tas, mientras los que se encuentran en el modo de usuario tienen las prioridades más bajas. A
continuación se describe la lógica existente detrás de esta estructura de prioridades: un proceso
en el modo de kernel tiene asignados muchos recursos del SO. Si se permite su ejecución a una
prioridad elevada, es el que deja más pronto tales recursos. Los procesos en el modo de kernel
que no tienen tantos recursos del SO se colocan en el modo interrumpible de kernel.

Direcciones de los eventos De un proceso que está bloqueado sobre un evento se dice que
está dormido en éste. Unix utiliza una disposición interesante para activar los procesos dormidos
en un evento. En vez de usar ECB (consulte la sección 3.3.6), utiliza el concepto de dirección
de un evento. Para este efecto, en el kernel se reserva un conjunto de direcciones. Cada evento
se transforma en una de estas direcciones. Cuando un proceso desea dormir en un evento, su di-
rección se calcula usando un procedimiento especial. El estado del proceso cambia a bloqueado
y la dirección del evento se coloca en la estructura del proceso. Esta dirección sirve como
la descripción del evento esperado por el proceso. Cuando ocurre un evento, el kernel calcula la
dirección del evento y activa todos los procesos que están durmiendo ahí.
Esta disposición tiene una desventaja: en algunas situaciones incurre innecesariamente en
sobrecarga. Varios procesos pueden dormir en el mismo evento. El kernel los activa a todos
una vez que ocurre el evento. Los procesos por sí mismos deciden si todos deben reanudar su
ejecución o si sólo deben hacerlo unos cuantos. Por ejemplo, cuando se activan varios proce-
sos dormidos debido a la sincronización de acceso a los datos, sólo un proceso obtiene acceso a
ellos y los demás procesos activados deben seguir dormidos. El método de mandar eventos a di-
recciones se suma a este problema. Para llevar a cabo esta transformación se utiliza un esquema
de búsqueda, de modo que puede ocurrir que dos o más eventos sean enviados a la misma direc-
ción del evento. Luego, la ocurrencia de cualquiera de estos eventos activa todos los procesos
que están durmiendo en todos estos eventos. Sólo algunos procesos que duermen en el evento
correcto reanudan su ejecución. Todos los demás deben continuar dormidos.

Prioridades de los procesos Unix es un sistema operativo de tiempo compartido puro, por
lo que utiliza la política de planificación round-robin. Sin embargo, en una variante de esta po-
lítica de planificación, modifica dinámicamente las prioridades de los procesos y lleva a cabo
planificación round-robin sólo para procesos con la misma prioridad. Así, esencialmente, uti-
liza planificación adaptativa de multinivel. A continuación se explica el porqué de la variación
dinámica de las prioridades de los procesos priorizantes.
Un proceso del usuario se ejecuta en el modo del usuario cuando ejecuta su propio código.
Se instala en el modo de kernel cuando empieza a ejecutar el código de kernel debido a una

05 MAQ. CAP. 04(F0694).indd 175 8/10/07 12:58:56 AM


176 CAPÍTULO 4 Planificación

interrupción o a una llamada del sistema. Un proceso que está ejecutando una llamada del sis-
tema puede bloquearse para un recurso o un evento. Un proceso así debe tener ciertos recursos
del kernel; cuando se vuelve activo de nuevo, debe planificarse lo más pronto posible, de modo
que pueda liberar recursos del kernel y volver al modo del usuario. Para facilitar lo anterior, a
todos los procesos que están en el modo del kernel se les asignan prioridades más altas que
a todos los procesos que están en el modo del usuario. Cuando un proceso se bloquea en el modo
del kernel, la razón del bloqueo se utiliza para determinar qué prioridad debe tener una vez que
se vuelva a activar.
A los procesos Unix se les asignan prioridades numéricas, donde un mayor valor numérico
implica una prioridad efectiva inferior. En el BSD 4.3 de Unix, las prioridades varían de 0 a 127.
Los procesos en el modo del usuario tienen prioridades entre 50 y 127, mientras los que están en
el modo del kernel tienen prioridades entre 0 y 49. Cuando un proceso llega a estar bloqueado
en una llamada del sistema, su prioridad cambia a un valor en el intervalo 0-49, dependiendo de
la causa del bloqueo. Una vez que se vuelve activo nuevamente, ejecuta el resto de la llama-
da del sistema con esta prioridad. Cuando sale del modo del kernel, su prioridad regresa a su
valor previo, que estaba en el intervalo 50-127.
La segunda razón para explicar la variación de las prioridades de un proceso es que la políti-
ca round-robin no proporciona una atención equitativa del CPU a todos los procesos. Un proceso
ligado a E/S no utiliza por completo un intervalo de tiempo, de modo que el uso que hace del
CPU siempre queda atrás con respecto al uso que los procesos limitados por el CPU hacen de
éste. El programador Unix proporciona una prioridad superior a los procesos que no han recibi-
do mucha atención del CPU en el pasado reciente. Vuelve a calcular las prioridades del proceso
cada segundo según la fórmula siguiente:

Prioridad del proceso  prioridad base para procesos de los usuarios


 f (tiempo de CPU utilizado)

donde todos los procesos del usuario tienen la misma prioridad base.
El programador mantiene el tiempo de CPU utilizado por cada proceso en su entrada co-
rrespondiente en la tabla del proceso. El reloj en tiempo real origina una interrupción 60 veces
por segundo, es decir, una vez cada 16.67 mseg. El manejador del reloj incrementa el conteo en
el campo de uso del CPU del proceso en ejecución. Al inicio, el campo de uso del CPU es 0, por
lo que un proceso inicia con la prioridad base para los procesos del usuario. A medida que recibe
atención del CPU, su prioridad efectiva se reduce. Si dos procesos tienen la misma prioridad, se
planifican de manera round-robin.
Si para calcular la prioridad del proceso se emplea el uso total de CPU que ocupó un proce-
so, entonces la política de planificación sería parecida a la política LCN, que no funciona bien
en la práctica (consulte la sección 4.1.1). Por consiguiente, Unix sólo considera al uso de CPU
más reciente, en vez del uso total del CPU desde que inició un proceso. A fin de implementar esta
política, el programador aplica un “decaimiento” a la influencia del tiempo de CPU utilizado por
un proceso. Cada segundo, antes de volver a calcular las prioridades del proceso, los valores en
los campos de uso del CPU de todos los procesos se dividen a la mitad y vuelven a almacenarse.
El nuevo valor en el campo de uso del CPU de un proceso se utiliza como f (tiempo de CPU
utilizado). De esta forma, la influencia del tiempo de CPU utilizado por un proceso se reduce a
medida que el proceso espera utilizar el CPU.

05 MAQ. CAP. 04(F0694).indd 176 8/10/07 12:58:57 AM


4.6 Planificación en Unix 177

Una característica interesante en Unix es que un usuario puede controlar la prioridad de


un proceso. Esto se logra por medio de la llamada del sistema denominada nice( priority
value ); que establece el nice value del proceso de un usuario. Entonces la prioridad efectiva
del proceso se calcula como sigue:

Prioridad del proceso  prioridad base para procesos del usuario


 f (tiempo de CPU utilizado)  nice value (4.5)

Se solicita que un usuario utilice un valor cero o positivo en la llamada nice. Así, un usuario
no puede incrementar la prioridad efectiva de un proceso, aunque sí disminuirla. (Esto se hace
comúnmente cuando se sabe que un proceso ha ingresado en una fase limitada por el CPU.)

Ejemplo 4.15 En la tabla 4.13 se resume la operación de una política de planificación semejante
a la de Unix para los procesos de la tabla 4.2. Se supone que el proceso P3 está ligado a E/S, que
inicia una operación E/S que dura 0.5 segundos antes de ser ejecutado en el CPU durante 0.1
segundos, y ninguno de los demás procesos realiza E/S. El campo T indica el tiempo de CPU
consumido por un proceso y el campo P contiene su prioridad. El programador actualiza el campo
T de un proceso 60 veces por segundo y vuelve a calcular las prioridades del proceso una vez
por segundo. El intervalo de tiempo es igual a 1 segundo, y la prioridad base de los procesos del
usuario es de 60. En la primera línea de la tabla 4.13 se observa que en t  0 sólo existe P1 en
el sistema. Su campo T contiene 0, por lo que su prioridad es 60. Se muestran dos renglones para
t  1.0. La primera línea muestra los campos T de todos los procesos en t  1, mientras que
en la segunda línea se observan los campos P y T después de que el cálculo de prioridades actúa en
t  1.0. Al término del intervalo de tiempo, los contenidos del campo T de P1 son 60. La acción de
decaimiento por dividir el tiempo de CPU a la mitad reduce lo anterior a 30, por lo que la priori-
dad de P1 se convierte en 90. En t  2, la prioridad efectiva de P1 es menor que la de P2 porque su
campo T contiene 45 y 0, respectivamente, por lo que se planifica P2. En forma semejante, P3 se
planifica en t  2 segundos.
El proceso P3 usa el CPU sólo durante 0.1 segundos antes de iniciar una operación E/S, por
lo que su prioridad es mayor que P2 cuando su planificación se lleva a cabo en t  4 segundos y
es planificado antes que el proceso P2. De nuevo es planificado en t  6 segundos. Estas acciones de
planificación corrigen el sesgo contra E/S mostrado por el programador RR.

4.6.1 Planificación equitativa en Unix

Los programadores en Unix logran planificación equitativa al agregar un término adicional a la


ecuación (4.5) como sigue:

Prioridad del proceso  prioridad base para procesos del usuario


 f (tiempo de CPU utilizado por el proceso)
 f (tiempo de CPU utilizado por grupo de procesos)
 valor agradable

donde f es la misma función que se utilizó en la ecuación (4.5). Luego, el SO mantiene la pista
del tiempo de CPU utilizado por cada proceso y por cada grupo de procesos. La prioridad de un
proceso depende del tiempo reciente de CPU utilizado por este proceso y por otros procesos en

05 MAQ. CAP. 04(F0694).indd 177 8/10/07 12:58:57 AM


178 CAPÍTULO 4 Planificación

Tabla 4.13 Operación de una política de planificación semejante a la de Unix


cuando el proceso ejecuta operaciones de E/S

P1 P2 P3 P4 P5 Plani-
Tiempo P T P T P T P T P T ficado
0.0 60 0 P1
1.0 60
90 30 P1
2.0 90 0
105 45 60 0 P2
3.0 45 60
82 22 90 30 60 0 P3
3.1 82 22 90 30 60 6 P1
4.0 76 30 6
98 38 75 15 63 3 P3
4.1 98 38 75 15 63 9 P2
5.0 38 69 9 0
79 19 94 34 64 4 60 0 P4
6.0 19 34 4 60
69 9 77 17 62 2 90 30 P3

el grupo. Debido a que la prioridad efectiva es el inverso del valor de prioridad calculado con
la ecuación anterior, la prioridad de un proceso se reduce aún más cuando otros procesos de su
grupo reciben tiempo de CPU. En el ejemplo 4.16 se ilustra la operación de un programador de
compartición equitativa.

Ejemplo 4.16 En la tabla 4.14 se presenta la planificación de los procesos de la tabla 4.2 realizada
por un programador de compartición equitativa semejante al de Unix. Los campos P, T y G contie-
nen prioridad del proceso, tiempo de CPU consumido por un proceso y tiempo de CPU consumido
por un grupo de procesos, respectivamente. Existen dos grupos de procesos. El primero contiene
los procesos P1, P2, P3 y P5, mientras que el segundo grupo contiene todo el proceso P4. Como es
de esperarse, éste recibe un tratamiento preferencial cuando es comparado con los demás proce-
sos. De hecho, en el periodo que va de t  5 a t  15, recibe todo intervalo de tiempo alternativo.
Los procesos P2, P3 y P5 sufren porque pertenecen al mismo grupo de procesos. A su vez, estos
hechos se reflejan en los tiempos de demora y en los de demora promedio de los procesos, que se
muestran en la tabla 4.15.

4.7 PLANIFICACIÓN EN LINUX

Linux lleva a cabo aplicaciones tanto en tiempo real como en tiempo no real. En consecuencia,
posee dos clases de procesos. Los procesos en tiempo real poseen prioridades estáticas entre 0
y 100, donde la prioridad más alta es 0. Los procesos en tiempo real pueden planificarse en dos
formas: FIFO o round-robin dentro de cada nivel de prioridad. El kernel asocia un comentario a
cada proceso para indicar cómo debe planificarse.
Los procesos en tiempo no real tienen prioridades más bajas que todos los procesos en tiem-
po real; sus prioridades son dinámicas y tienen valores numéricos que varían entre 20 y 19,
donde 20 es la prioridad máxima. De manera efectiva, el kernel posee (100  40) niveles de

05 MAQ. CAP. 04(F0694).indd 178 8/10/07 12:58:57 AM


4.7 Planificación en Linux 179

Tabla 4.14 Operación de una política de planificación de compartición equitativa

P1 P2 P3 P4 P5 Plani-
Tiempo P C G P C G P C G P C G P C G ficado
0 60 0 0 0 0 0 0 P1
1 120 30 30 30 30 0 30 P1
2 150 45 45 105 0 45 45 0 45 P2
3 134 22 52 142 30 52 112 0 52 0 52 P3
4 127 11 56 131 15 56 146 30 56 0 56 P1
5 58 125 7 58 133 15 58 60 0 0 58 P4
6 29 92 3 29 96 7 29 120 30 30 29 P2
7 44 135 31 44 107 3 44 90 15 15 44 P4
8 22 97 15 22 83 1 22 134 37 37 82 0 22 P5
9 41 108 7 41 101 0 41 96 18 18 131 30 41 P4
10 20 83 3 20 80 0 20 138 39 39 95 15 20 P3
11 40 101 1 40 40 98 19 19 107 7 40 P4
12 20 80 0 20 20 138 39 39 83 3 20 P2
13 40 40 40 98 19 19 101 1 40 P4
14 20 20 20 39 80 0 20 P5
15 40 40 40 19 130 30 40 P5
16

Tabla 4.15 Desempeño de una planificación de compartición equitativa

Proceso P1 P2 P3 P4 P5
Tiempo de terminación 5 13 11 14 16
Tiempo de demora 5 11 8 9 7
Tiempo de demora ponderado 1.67 3.67 4.00 1.80 2.33

Tiempo de demora promedio ( ta ) = 8.0 segundos


Tiempo de demora ponderado promedio (w) = 2.69 segundos

prioridad. Para empezar, la prioridad de todo proceso en tiempo no real es 0. La prioridad puede
ser modificada por el propio proceso mediante las llamadas del sistema nice o setpriority. Sin
embargo, se requieren privilegios especiales para incrementar la prioridad mediante la llamada
del sistema nice, por lo que los procesos comúnmente la usan para disminuir sus prioridades
cuando desean ser agradables con otros procesos. Además de esta variación de la prioridad, el
kernel modifica la prioridad de un proceso a fin de reflejar su naturaleza ligada a E/S o limitada
por el CPU. Para implementar lo anterior, el kernel mantiene información sobre cuánto tiempo
de CPU ha utilizado recientemente el proceso y durante cuánto permaneció en el estado blo-
queado, y agrega un bono entre 5 y 5 al valor “nice” del proceso. Así, un proceso altamente
interactivo tendrá una prioridad efectiva de nice 5, mientras uno limitado por el CPU tendrá
una prioridad efectiva de nice 5.

05 MAQ. CAP. 04(F0694).indd 179 8/10/07 12:58:58 AM


180 CAPÍTULO 4 Planificación

Debido a la estructura de prioridad de multinivel, el kernel de Linux organiza sus datos de


planificación como se muestra en la figura 4.11 de la sección 4.4.5. Así, cada nivel de prioridad
tiene asociada una lista de procesos listos. Para limitar la sobrecarga de planificación, Linux uti-
liza un esquema programador semejante al que se muestra en la figura 3.10. Así, la planificación
no se realiza después de cada acción de manejo de eventos. Se lleva a cabo cuando el proceso
que se está ejecutando en ese momento debe bloquearse debido a una llamada del sistema, o
cuando el comentario need_resched ha sido establecido por una acción de manejo de eventos.
Esto se efectúa mientras se manipula el vencimiento del intervalo de tiempo o mientras se ma-
neja un evento que activa un proceso de prioridad más alta que el que se está ejecutando en ese
momento.
Los procesos en tiempo no real se planifican usando el concepto de intervalo de tiempo;
sin embargo, este concepto en Linux es diferente del que se describió en capítulos anteriores.
El intervalo de tiempo en Linux es en realidad un cuanto de tiempo que un proceso puede usar
durante un intervalo de tiempo según su prioridad. Linux utiliza intervalos de tiempo en el in-
tervalo que va de 10 a 200 mseg. Al contrario de las descripciones proporcionadas en capítulos
anteriores, un proceso de alta prioridad posee un intervalo de tiempo más grande. Esto no afecta
los tiempos de respuesta en Linux porque, como ya se describió, la naturaleza de los procesos
con altas prioridades es interactiva.
El programador Linux utiliza dos listas de procesos: una lista activa y una lista agotada.
Ambas están ordenadas según las prioridades de los procesos y usan la estructura de datos
antes descrita. El programador planifica un proceso de la lista activa, que de vez en cuando
usa su intervalo de tiempo. Una vez que se agota el intervalo de tiempo, se coloca en la lista
agotada. Los programadores del kernel 2.5 de Linux y kernel anteriores ejecutaban un ciclo
de recómputo de prioridades cuando la lista activa se encontraba vacía. El ciclo calculaba un
nuevo intervalo de tiempo para cada proceso con base en su prioridad dinámica. Al término
del ciclo, todos los procesos se transferían a la lista activa y se reanudaba la operación normal de
planificación.
El kernel 2.6 de Linux utiliza un nuevo programador que incurre en menos sobrecarga y
escala mejor con el número de procesos y los CPU. El programador distribuye la sobrecarga del
recómputo de prioridades a lo largo de toda la operación del programador, más que agruparla en
el ciclo de recómputo. Logra lo anterior al volver a calcular la prioridad de un proceso cuando
éste agota su intervalo de tiempo y se desplaza a la lista agotada. Una vez que ésta se vacía, el
programador simplemente intercambia las listas activa y agotada.
La escalabilidad del programador se asegura de dos formas. El programador tiene un men-
saje para indicar si la lista de los procesos de un nivel de prioridad está vacía. Cuando se invoca,
el programador prueba los mensajes de las listas de procesos en orden decreciente de prioridad
y elige el primer proceso en la primera lista de procesos ocupada que encuentra. Este procedi-
miento incurre en una sobrecarga de planificación que no depende del número de procesos listos;
sólo del número de niveles de planificación porque está acotado por una constante. Esta plani-
ficación se denomina O(1), es decir, orden 1, planificación. Los programadores en kernel más
antiguos de Linux usaban un candado de sincronización en la lista activa de procesos a fin de
evitar condiciones de carrera cuando se admitían muchos CPU. El kernel 2.6 de Linux mantiene
listas activas sobre una base por CPU, lo cual elimina el candado de sincronización y los retrasos
asociados. Esta disposición también asegura que un proceso sea ejecutado por el mismo CPU
cada vez que es planificado, lo que ayuda a asegurar mejores relaciones de impacto.

05 MAQ. CAP. 04(F0694).indd 180 8/10/07 12:58:58 AM


4.9 Análisis de desempeño de las políticas de planificación 181

4.8 PLANIFICACIÓN EN WINDOWS

La planificación en Windows está orientada a proporcionar tiempos de respuesta aceptables a


hilos interactivos y en tiempo real. La planificación es basada en prioridades y es priorizante. La
planificación en un nivel de prioridad se realiza usando una política round-robin con intervalos
de tiempo. Las propiedades de los hilos no en tiempo real varían dinámicamente para favorecer
a los hilos interactivos. Este aspecto es semejante a la planificación adaptativa de multinivel
(consulte la sección 4.4.5).
Los hilos se dividen en dos clases: hilos en tiempo real y otros hilos. A los primeros se asig-
nan prioridades que varían de 16 a 31. Éstas permanecen sin cambio durante la operación del
hilo. Otros hilos tienen prioridades en el intervalo de 1 a 15, y pueden variar durante su existen-
cia, por lo que esta clase de hilos también se denomina clase de prioridad variable. La prioridad
efectiva de un hilo en esta clase en cualquier momento es una combinación de tres factores: la
prioridad base del proceso al que pertenece el hilo, la prioridad base del hilo y la componente
dinámica asignada por el programador. Un valor numérico superior de la prioridad implica una
prioridad efectiva más alta.
La prioridad base de los procesos y los hilos se especifica en el momento en que son creados.
La prioridad base de un hilo se sitúa en el intervalo 2 a 2. La prioridad inicial de un hilo es la
suma de la prioridad base del proceso en que es creado y su propia prioridad base. El programa-
dor varía dinámicamente la prioridad de un hilo. La prioridad efectiva de un hilo puede variar
entre prioridad base del proceso 2 y 15. Así, puede alcanzar el valor de prioridad más alto para
la clase de prioridad variable; sin embargo, no puede caer más de 2 niveles debajo de la prioridad
base del proceso al que pertenece. La variación de prioridades se implementa como sigue: si un
hilo gasta su intervalo de tiempo durante su ejecución, su prioridad se reduce en una unidad.
Cuando un hilo que está bloqueado en un evento despierta, se le proporciona un incremento en
prioridad basado en la naturaleza del evento. Si el hilo estaba bloqueado a la entrada desde los
teclados, entonces su prioridad aumenta en 6. Esta política favorece a los hilos interactivos sobre
otros hilos.
El sistema se protege contra inanición al aumentar temporalmente la prioridad de un hilo
listo que no ha recibido CPU durante más de 3 segundos. La prioridad de un hilo así aumenta a
15 y se le proporciona un arranque de CPU que es el doble de su arranque normal. Luego de este
arranque, su prioridad y arranque de CPU regresan a sus valores anteriores.

4.9 ANÁLISIS DE DESEMPEÑO DE LAS POLÍTICAS


DE PLANIFICACIÓN

El análisis de desempeño de las políticas de planificación puede usarse para dos objetivos:
comparar el desempeño de políticas de planificación alternativas y determinar “buenos” valores
de parámetros clave del sistema, como el intervalo de tiempo y el número de usuarios activos.
El desempeño es sensible a la carga de trabajo de solicitudes dirigidas al programador, por lo
que resulta esencial realizar el análisis de desempeño en el entorno en el que deberá utilizarse un
programador. Aquí se consideran métodos diferentes para el análisis de desempeño y se estudian
sus ventajas y desventajas.
Una dificultad común en el análisis de desempeño está relacionada con una caracterización
precisa de la carga de trabajo común. Hay varias razones para explicar esta dificultad. Como

05 MAQ. CAP. 04(F0694).indd 181 8/10/07 12:58:58 AM


182 CAPÍTULO 4 Planificación

ya se mencionó en el contexto de la política SRN, las estimaciones del usuario de los tiempos
de servicio no son confiables, ya sea porque el usuario carece de experiencia para proporcionar
buenos estimadores del tiempo de servicio o porque los usuarios con experiencia pueden propor-
cionar estimadores erróneos para obtener un servicio preferencial del sistema. Algunos usuarios
incluso pueden recurrir a cambios en sus solicitudes a fin de obtener un mejor servicio: si un
usuario sabe que se está usando la política SRN, es capaz de separar una tarea de larga ejecución
en varias tareas con tiempos de servicio menores. Todos estos factores distorsionan la carga de
trabajo, por lo que debe tenerse extremo cuidado al desarrollar una caracterización de una carga
de trabajo común.
El desempeño de una política de planificación en un entorno computacional específico puede
estudiarse mediante su implementación en un SO y sometiendo a éste a una carga de trabajo
de solicitudes comunes encontradas en el entorno. Sin embargo, este método no es factible de-
bido a su complejidad, costo y retrasos implicados en la implementación de la política de plani-
ficación requerida por un SO.
Dos métodos prácticos para el análisis de desempeño de las políticas de planificación son la
simulación y la modelación matemática. Un simulador imita las decisiones de un programador
y las acciones relevantes de un SO, y determina los tiempos de terminación de las solicitudes en
una carga de trabajo común. Esto se logra codificando como un programa —el programa simu-
lador— la política de planificación y las funciones relevantes del SO y usando como su entrada
una carga de trabajo común. La carga de trabajo es un registro de la carga de trabajo real diri-
gida al SO durante un periodo muestra. El análisis puede repetirse con muchas cargas de trabajo
para eliminar el efecto de variaciones a través de las cargas de trabajo. Para eliminar la distor-
sión de las cargas de trabajo, ¡debe tenerse cuidado de registrar las cargas de trabajo sin que los
usuarios lo sepan!
Un modelo matemático consta de dos componentes: un modelo del servidor y un modelo
de la carga de trabajo que se está procesando. El modelo proporciona un conjunto de expresio-
nes matemáticas de características de desempeño importantes, como los tiempos de servicio de
las solicitudes y la sobrecarga. Estas expresiones aportan conocimiento sobre la influencia
de varios parámetros en el desempeño del sistema. El modelo de la carga de trabajo difiere de las
cargas de trabajo utilizadas en simulaciones en el sentido de que no es un registro de la carga de
trabajo actual en ningún intervalo de tiempo específico. Se trata de una abstracción matemática
denominada distribución, que constituye una buena aproximación a la carga de trabajo actual
observada durante cualquier periodo.

Teoría de colas El uso tan vasto de los modelos matemáticos para analizar el desempeño
de varios sistemas condujo al desarrollo de una rama por separado de las matemáticas denomi-
nada teoría de colas. El análisis de desempeño que utiliza la teoría de colas se denomina análisis
de colas. La primera aplicación bien conocida de la modelación matemática es la de Erlang
(1909) para evaluar el desempeño de una comunicación telefónica con el número de líneas tron-
cales como parámetro de control.
El modelo fundamental de la teoría de colas de un sistema es idéntico al sencillo modelo
programador que se analizó al principio de este capítulo (consulte la figura 4.1). Lo anterior se
conoce como single-server model. Las solicitudes que llegan al sistema entran en una cola. El
servidor elige las solicitudes de esta cola con el propósito de planificarlas. Una solicitud sale
del sistema una vez terminada. Si el servidor es priorizable, entonces una solicitud priorizada

05 MAQ. CAP. 04(F0694).indd 182 8/10/07 12:58:58 AM


4.9 Análisis de desempeño de las políticas de planificación 183

se devuelve a la lista de planificación y debe esperar su reprogramación para reanudar su eje-


cución. Esto se ilustra con la flecha discontinua de la figura 4.1. El análisis de colas se usa para
desarrollar expresiones matemáticas para la eficacia del servidor, la longitud media de la cola y
el tiempo de espera medio.
Una solicitud que llega en el instante Ai con tiempo de servicio Xi se termina en el instante
Ci. El tiempo transcurrido (Ci Ai) depende de dos factores: de los tiempos de llegada y los
tiempos de servicio de las solicitudes que se encuentran en ejecución o en la cola de planificación
en algún momento durante el intervalo (Ci Ai), y de la política de planificación utilizada por
el servidor. Es razonable suponer que los tiempos de llegada y de servicio de las solicitudes que
ingresan al sistema se desconocen de antemano; es decir, estas características de las solicitudes
son de naturaleza no determinística.
El entorno de planificación es caracterizado por dos parámetros: el patrón de llegada de
las solicitudes y su patrón de servicio. Estos parámetros rigen los tiempos de llegada y los
de servicio de las solicitudes, respectivamente. A pesar de que se desconocen las característi-
cas de las solicitudes individuales, suele suponerse que se apegan a ciertas distribuciones esta-
dísticas. A continuación se proporciona una breve introducción a las distribuciones estadísticas
y su uso en la modelación matemática utilizando la siguiente notación:

 : Razón de llegada media (solicitudes por segundo)


 : Razón de ejecución media (solicitudes por segundo)
 : 兾

 se denomina factor de utilización del servidor. Cuando  1, la tarea que está dirigiéndo-
se al sistema excede su capacidad. En este caso, el número de solicitudes en el sistema aumenta
de manera indefinida. La evaluación del desempeño de un sistema de esta naturaleza es de poca
importancia práctica porque los tiempos de demora pueden ser arbitrariamente grandes. Cuando
 1, la capacidad del sistema excede a todo el trabajo dirigido hacia el sistema. Sin embar-
go, esto sólo es cierto como un promedio a largo plazo; puede no cumplirse en un intervalo de
tiempo arbitrario. Por tanto, el servidor puede estar ocioso de vez en cuando, y unas cuantas
solicitudes pueden existir en la cola en ciertos instantes.
La mayor parte de los sistemas prácticos satisfacen  1. Aun cuando se considera un
servidor lento,  no excede de 1 porque la naturaleza de la mayor parte de los sistemas prácticos
es de autorregulación: el número de usuarios es finito y la razón de llegada de las solicitudes
se reduce cuando la longitud de la cola es grande porque ¡casi todas las solicitudes del usuario
tienen candados en la cola!
Un sistema llega a un estado estable cuando se extinguen todas las corrientes transitorias
en el sistema inducidas debido a este inicio abrupto en el instante t  0. En el estado estable,
los valores de las longitudes medias de la cola, los tiempos de espera medios y los de demora
promedios reflejan el desempeño de la política de planificación. Para obtener estos valores, se
empieza por suponer ciertas distribuciones para la llegada y para el servicio de las solicitudes
en el sistema.

Tiempos de llegada El tiempo que transcurre entre la llegada de dos solicitudes consecuti-
vas se denomina tiempo de interllegadas. Debido a que  es la razón de llegadas, entonces el
tiempo medio de interllegadas es 1Ⲑ. Una distribución con esta razón media de interllegadas y
que se ajuste de manera razonable a los datos empíricos puede usarse como la caracterización

05 MAQ. CAP. 04(F0694).indd 183 8/10/07 12:58:58 AM


184 CAPÍTULO 4 Planificación

de la carga de trabajo para el análisis de colas. La llegada de las solicitudes al sistema puede
considerarse como eventos aleatorios totalmente independientes entre sí. Luego se hacen dos
suposiciones que llevan a una distribución de Poisson de las llegadas. Primero, el número de lle-
gadas en un intervalo que va de t a t  dt depende sólo del valor de dt y no de la historia pasada
del sistema durante el intervalo (0, t). Segundo, para valores pequeños de dt, la probabilidad de
más de una llegada en el intervalo que va de t a (t  dt) es despreciable. La primera suposición se
conoce como la propiedad sin memoria de la distribución de los tiempos de llegada. Una función
de distribución exponencial que proporciona la probabilidad de una llegada en el intervalo de 0
a t para cualquier t es de la forma

F(t)  1 e .t

Esta distribución posee el tiempo de interllegadas medio 1Ⲑ, ya que 兰0∞ t.dF (t)  1Ⲑ. Se en-
cuentra que la función de distribución exponencial ajusta razonablemente bien los tiempos de
interllegadas en datos empíricos. [Sin embargo, se encuentra que la distribución hiperexponen-
cial con la misma media de 1Ⲑ es una mejor aproximación para los datos experimentales (Fife,
1965).]

Tiempos de servicio La función S(t) proporciona la probabilidad de que el tiempo de ser-


vicio de una solicitud sea menor que o igual a t.

S(t)  1 e .t

Al igual que en el caso de los tiempos de llegada, se hacen dos suposiciones que llevan a una
distribución de Poisson de tiempos de servicio. Por tanto, la probabilidad de que una solicitud
que ya haya consumido t unidades de tiempo de servicio termine en los dt segundos siguientes
sólo depende del valor de dt y no de t. En planificación priorizante, esto se aplica cada vez que
se programa la ejecución de una solicitud luego de una interrupción.
La propiedad sin memoria de los tiempos de servicio implica que un algoritmo de plani-
ficación es incapaz de hacer cualesquiera predicciones con base en la historia pasada de una
solicitud en el sistema. Así, una política de planificación priorizante que requiere conocer el
comportamiento futuro de la solicitud debe depender de estimaciones de los tiempos de servicio
proporcionados por un programador. El desempeño de la planificación depende entonces fun-
damentalmente del comportamiento del usuario y puede ser manipulado por los usuarios. En
una situación práctica, un sistema debe esforzarse para obtener el efecto opuesto; es decir, el
desempeño del sistema debe ser inmune a las especificaciones de los usuarios de un tiempo de
servicio de una solicitud. Esta característica parece apuntar hacia la planificación round-robin
con intervalo de tiempo como una política de planificación práctica.

Análisis de desempeño La relación entre L, la longitud media de la cola, y W, el tiempo de


espera medio para una petición antes de su servicio, está dada por la fórmula de Little; a saber,

LW (4.6)

Esta relación se deduce del hecho de que mientras una solicitud espera en la cola,   W, nuevas
solicitudes se integran a ella.
Cuando llega una nueva solicitud, se agrega a la cola de solicitudes. En planificación no
priorizante, la nueva solicitud es considerada sólo después de que el servidor termina la solicitud

05 MAQ. CAP. 04(F0694).indd 184 8/10/07 12:58:59 AM


4.9 Análisis de desempeño de las políticas de planificación 185

que está atendiendo. Sea W0 el tiempo esperado para terminar la solicitud que está siendo aten-
dida. Naturalmente, W0 es independiente de la política de planificación. W 0 = α2 . 兰0∞ t 2 dF (t),
y posee el valor ωα2 para una distribución exponencial F (t) = 1– e –α .t . W, el tiempo de espera
medio para una solicitud cuando se utiliza una política de planificación específica se calcula
usando W0 y características de la política de planificación. A continuación se presenta un esbozo
de cómo se deducen los tiempos medios de espera para las políticas FCFS y SRN. Las deduc-
ciones para HRN y round-robin son más complicadas, aunque es posible consultarlas en el libro
de Brinch Hansen (1973). En la tabla 4.16 se resume el tiempo de espera medio de una solicitud
cuyo tiempo de servicio es t cuando se utilizan políticas de planificación diferentes.

Tabla 4.16 Resumen del análisis de desempeño

Política de planificación Tiempo de espera medio de una solicitud con tiempo de servicio = t
W0
FCFS 1− ρ

, donde ρ t = 兰o α.x.dS (x)


W0 t
SRN 1− ρ t
ρ2
HRN para t pequeña: W 0 + 1− ρ × t
2
W0
(No priorizante) para t grande: 2 .W0
(1− ρ)( 1− ρ+ t
)
Round-robin n
ω (1− P0 )
− 1
α, donde P0 = 1
Σ nj = 0 ( n−n ! j )! × (α ) j

(P0 es la probabilidad de que ninguna terminal espere una respuesta)

W, el tiempo de espera de alguna solicitud r, es la cantidad de tiempo que r permanece en


la cola antes de que empiece su tiempo de servicio. Por tanto, en planificación FCFS

W  W0 
i (Xi)

donde la solicitud i está antes que la solicitud r en la cola de la planificación. El sistema se en-
cuentra en el estado estable, por lo que es posible sustituir el término
i por n × ω1 , donde n es el
número de solicitudes que están antes de ry ω1 es el tiempo de servicio medio. Debido a que n es
la longitud media de la cola, n    W a partir de la fórmula de Little. Así,

W = W0 + α × W × 1
ω
= W0 + ρ × W .

W0
En consecuencia, W = 1− ρ
. Por tanto, el tiempo de espera medio en planificación FCFS aumen-
ta pronunciadamente para valores altos de .
En planificación SRN, las solicitudes cuyos tiempos de respuesta Xr, donde Xr es el
tiempo de respuesta de r, se atienden antes que la solicitud r. Así, el tiempo de espera de la
solicitud r es

W = W0 + Σ i (X i ), donde X i < X r
, donde ρr = 兰0 α.x.dS (x).
W0 r
= 1− ρ r

05 MAQ. CAP. 04(F0694).indd 185 8/10/07 12:58:59 AM


186 CAPÍTULO 4 Planificación

Planeación de la capacidad El análisis de desempeño puede usarse para planeación de


la capacidad. Por ejemplo, las fórmulas que se muestran en la tabla 4.16 pueden aplicarse para
determinar los valores de parámetros importantes, como los tamaños de colas de los procesos
utilizados por el kernel.
Como ejemplo, considere un SO donde la razón de llegada media de las solicitudes es de 5
solicitudes por segundo y el tiempo de respuesta medio por solicitud es 3 segundos. La longitud
media de la cola se calcula aplicando la fórmula de Little [ecuación (4.6)] como 5  3  15.
Observe que algunas veces las colas excederán esta longitud. El ejemplo 4.17 proporciona una
base para decidir la capacidad de la cola de procesos listos.

Ejemplo 4.17 El kernel de un SO permite hasta n elementos en la lista de solicitudes de procesos


listos. Si la cola está llena cuando llega una nueva solicitud, ésta es rechazada y abandona el SO.
Puede demostrarse que Pi, la probabilidad de que la cola de procesos listos contenga i procesos en
cualquier momento, es

ρ i × (1 — ρ)
Pi = (4.7)
1 — ρ n+ 1

Para ρ = 0.5 y n = 3, P0 = 158 , P1 = 15


4
, P2 = 152 y P3 = 15
1
. Así, se pierde 6.7 por ciento
de las solicitudes. En caso de que deban perderse menos solicitudes, es necesario usar un valor
superior de n.

EJERCICIO 4
1. Proporcione ejemplos de contradicciones de planificación entre los enfoques centrados en el usuario y
centrados en el sistema.
2. Estudie el desempeño de políticas de planificación priorizante y no priorizante en los procesos descritos
en la tabla 4.2 si sus tiempos de llegada son 0, 1, 3, 7 y 10 segundos, respectivamente. Elabore diagramas
semejantes a las figuras 4.2 y 4.4 para mostrar la operación de estas políticas.
3. Comente sobre la veracidad de las siguientes afirmaciones:
a) “Si un sistema que utiliza la política de planificación SRN termina la ejecución de las solicitudes en
la secuencia r1, r2 . . . rn, entonces tiempo de demora ponderado de ri tiempo de demora ponde-
rado de rj si i j.”
b) “La política de planificación LCN proporciona mejores tiempos de demora para solicitudes ligadas
a E/S que los tiempos de demora proporcionados por la planificación RR.”
4. Demuestre que la política de planificación SRN proporciona el tiempo de demora promedio mínimo
para un conjunto de solicitudes que llegan en el mismo instante.
5. Si la política de planificación de máxima relación de respuesta a continuación (HRN) se aplica en for-
ma priorizante, compárela y contrástela con las siguientes políticas:
a) STG.
b) LCN.
c) RR.
(Sugerencia: Considere el servicio proporcionado a procesos cortos y largos.)

05 MAQ. CAP. 04(F0694).indd 186 8/10/07 12:59:00 AM


Ejercicio 4 187

6. Un SO implementa la política HRN como sigue: cada t segundos se calculan las relaciones de respuesta
de todos los procesos. Esto es seguido por la planificación, que selecciona el proceso con la mayor
relación de respuesta. Comente sobre el desempeño y la sobrecarga de la política de planificación para
valores grandes y pequeños de t.
7. Un programa contiene un solo ciclo que se ejecuta 50 veces. El ciclo contiene un cálculo que dura
50 mseg seguido por una operación de E/S que consume 200 mseg. Este programa es ejecutado en un
sistema de tiempo compartido con otros 9 programas idénticos. Todos los programas empiezan su eje-
cución al mismo tiempo. Calcule el tiempo de respuesta en la primera repetición y en las repeticiones
siguientes si el intervalo de tiempo es igual a
a) 50 mseg.
b) 20 mseg.
8. Describa las acciones del kernel cuando transcurre un intervalo de tiempo.
9. ¿Es posible pronosticar el tiempo de respuesta medio experimentado por un proceso en el nivel de
planificación i de CTSS si en el nivel i hay ni procesos?
10. Houston Automatic SPooling system (HASP) era un subsistema de planificación utilizado en la
IBM/360. HASP asigna alta prioridad a procesos ligados a E/S y baja prioridad a procesos limitados
por el CPU. Un proceso se clasifica como ligado a E/S o limitado por el CPU con base en su compor-
tamiento reciente con respecto al intervalo de tiempo: un proceso es limitado por el CPU si usa todo
su intervalo de tiempo al ser planificado; en caso contrario, se trata de un proceso ligado a E/S. Para
obtener un rendimiento aceptable, HASP requiere que un porcentaje fijo de procesos en la cola de
planificación sean procesos ligados a E/S. Periódicamente, HASP ajusta el intervalo de tiempo a fin
de satisfacer este requerimiento: el intervalo de tiempo se reduce si más procesos de los pensados se
consideran limitados por el CPU, y se incrementa si un número menor de procesos son limitados por
el CPU. Explique el propósito de ajustar el intervalo de tiempo. Describa la operación de HASP si la
mayor parte de los procesos en el sistema son a) limitados por el CPU y b) ligados a E/S.
11. Comente las semejanzas y diferencias entre las planificaciones
a) LCN y Unix.
b) HASP y adaptativa de multinivel.
12. Determine los tiempos límite iniciales de los procesos del ejemplo 4.13.
13. Comente sobre la validez de la siguiente afirmación:
“La política de planificación Unix favorece a los procesos interactivos sobre los procesos no interac-
tivos.”
14. gi es un grupo de procesos en un sistema que utiliza planificación equitativa. Cuando de gi se elige un
proceso Pi para ser planificado, se dice “Pi es una selección de gi”. Demuestre que si el proceso no
efectúa operaciones de E/S, entonces no es posible que dos selecciones consecutivas de gi sean para el
mismo proceso.
15. Un SO que usa una política de planificación selectiva aplica prioridades que cambian dinámicamente.
La prioridad de un proceso cambia a razones diferentes en su estado como sigue:
 : Razón de cambio de la prioridad cuando un proceso está en funcionamiento
 : Razón de cambio de la prioridad cuando un proceso está listo
 : Razón de cambio de la prioridad cuando un proceso está ejecutando E/S
Observe que la razón de cambio de la prioridad puede ser positiva, negativa o cero. Cuando se crea un
proceso, su prioridad es 0. Se considera que un proceso con valor numérico de prioridad más alto tiene
mayor prioridad para ser planificado.

05 MAQ. CAP. 04(F0694).indd 187 8/10/07 12:59:00 AM


188 CAPÍTULO 4 Planificación

Comente sobre las políticas de planificación resultantes si


a)  0,   0,   0.
b)   0,  0,   0.
c)     0,  0.
d)  0,   0,   0.
El comportamiento de las políticas de planificación, ¿cambia si la prioridad de un proceso se establece
en 0 cada vez que es planificado?
16. Conteste sí o no a las siguientes preguntas:
a) Un proceso ligado a E/S se ejecuta dos veces; una en un sistema que utiliza planificación round-
robin y otra en un sistema que usa planificación adaptativa de multinivel. La cantidad de veces que
es planificado por el programador round-robin y por el programador de multinivel es la misma.
b) Si los procesos no realizan E/S, la planificación round-robin se parece a la planificación STG.
c) Si los procesos no realizan E/S, la política de planificación Unix degenera en la política de planifi-
cación round-robin convencional.
17. Explique cómo se evita la inanición en los sistemas Unix y Windows.
18. Un sistema usa la política de planificación FCFS. Al sistema llegan solicitudes computacionalmente
idénticas a razón de 20 solicitudes por segundo. Se desea que el tiempo medio de espera en el sistema
no exceda de 2 segundos. Calcule el tamaño de cada solicitud en segundos de CPU.
19. Solicitudes idénticas, cada una de las cuales requiere 0.05 segundo de CPU, llegan a un SO a razón
de 10 solicitudes por segundo. El kernel usa una cola de procesos listos de tamaño fijo. Si la cola no
está llena, ésta acepta una nueva solicitud; en caso contrario, la solicitud es eliminada. ¿Cuál debe
ser el tamaño de la cola de procesos listos si es necesario eliminar menos de 1 por ciento de las soli-
citudes?
20. La razón de llegada media de las solicitudes en un sistema en que se utiliza planificación FCFS es de 5
solicitudes por segundo. El tiempo de espera medio de una solicitud es igual a 3 segundos. Encuentre
la razón de ejecución media.
21. Una “solicitud pequeña” se define como una solicitud cuyo tiempo de servicio es inferior a 5 por ciento
de ω1 . Calcule el tiempo de demora promedio de una solicitud pequeña en un sistema que utiliza la po-
lítica de planificación no priorizante HRN cuando   5 y   8.

BIBLIOGRAFÍA
Corbato et al. (1962) analizan el uso de las colas de retroalimentación de multinivel en el sistema opera-
tivo CTSS. Coffman y Denning (1973) reportan estudios relacionados con la planificación de multinivel. El
programador de compartición equitativa está descrito en la obra de Kay y Lauder (1988) y la planificación
de loterías, en la obra de Waldspurger y Weihl (1994). Liu y Layland (1973), Zhao (1989), Khanna et al.
(1992) y Liu (2000) analizan la planificación en tiempo real. La conservación de energía constituye un nue-
vo elemento crucial en la planificación. La energía puede conservarse ejecutando el CPU a velocidades más
bajas. Zhu et al. (2004) analizan algoritmos de planificación especulativos que ahorran energía al variar la
velocidad del CPU y reducir el número de cambios de velocidad a la vez que se asegura que una aplicación
cumpla sus restricciones de tiempo.
Bach (1986), McKusick et al. (1996) y Vahalia (1996) estudian la planificación en Unix; Bovet y Ce-
sati (2003), O’Gorman (2003) y Love (2005) analizan la planificación en Linux; Mauro y McDougall

05 MAQ. CAP. 04(F0694).indd 188 8/10/07 12:59:00 AM


Bibliografía 189

(2001) estudian la planificación en Solares, mientras Russinovich y Solomon (2005) analizan la planifica-
ción en Windows.
La teoría de colas se utiliza en planificación y evaluación de desempeño. La primera aplicación de
la teoría de colas fue hecha por Erlang en 1909, quien la aplicó en la evaluación de desempeño de una
comunicación telefónica. Trivedi (1982) proporciona una fuente de información excelente sobre todos los
aspectos de la teoría de colas. Algunos trabajos anteriores son los de Kleinrock (1975, 1976) y Coffman
(1976). Brinch Hansen (1973) introduce el contexto necesario de la teoría de colas para el análisis de la
planificación. Hellerman y Conroy (1975) usan la teoría de colas en la evaluación de desempeño.

1. Bach, M.J. (1986): The Design of the Unix Operating System, Prentice-Hall, Englewood Cliffs.
2. Bovet, D.P. y M. Cesati (2003): Understanding the Linux Kernel, O’Reilly, Sebastopol.
3. Brinch Hansen, P. (1973): Operating System Principles, Prentice-Hall, Englewood Cliffs.
4. Bruno, J., E.G. Coffman y R. Sethi (1974): “Scheduling independent tasks to reduce mean finis-
hing time”, Communications of the ACM, 17 (7), 382-387.
5. Coffman, E.G. (Ed.) (1976): Computer and Job Shop Scheduling, Wiley, Nueva York.
6. Coffman, E.G. y P.J. Denning (1973): Operating Systems Theory, Prentice-Hall, Englewood
Cliffs.
7. Conway, R.W., W.L. Maxwell y L.W. Miller (1967): Theory of Scheduling, Addison-Wesley,
Reading.
8. Corbato, F.J., M. Merwin-Daggett y R.C. Daley (1962): “An experimental timesharing system”,
Proceedings of the AFIPS Fall Joint Computer Conference, 335-344.
9. Hellerman, H. y T.F. Conroy (1975): Computer System Performance, McGraw-Hill Kogakusha,
Tokio.
10. Kay, J. y P. Lauder (1988): “A fair share scheduler”, Communications of the ACM, 31 (1),
44-55.
11. Khanna, S., M. Sebree y J. Zolnowsky (1992): “Real time scheduling in SunOS 5.0”, Proceedings
of the Winter 1992 USENIX Conference, San Francisco, enero 1992, 375-390.
12. Kleinrock, L. (1975-1976): Queuing Systems, vols. I y II, Wiley, Nueva York.
13. Love, R. (2005): Linux Kernel Development, 2a. ed., Novell Press.
14. Liu, C.L. y J.W. Layland (1973): “Scheduling algorithms for multiprogramming in a hard real-
time environment”, Communications of the ACM, 20, 1, 46-61.
15. Liu, J.W.S. (2000): Real-Time Systems, Pearson Education.
16. Mauro, J. y R. McDougall (2001): Solaris Internals—Core Kernel Architecture, Prentice-Hall.
17. McKusick, M.K., K. Bostic, M.J. Karels y J.S. Quarterman (1996): The Design and Implementa-
tion of the 4.4BSD Operating System, AddisonWesley, Reading.
18. O’Gorman, J. (2003): Linux Process Manager: The Internals of Scheduling, Interrupts and
Signals,Wiley and Sons.
19. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.
20. Trivedi, K.S. (1982): Probability and Statistics with Reliability—Queuing and Computer Science
Applications, Prentice-Hall, Englewood Cliffs.
21. Vahalia, U. (1996): Unix Internals: The New Frontiers, Prentice Hall, Englewood Cliffs.

05 MAQ. CAP. 04(F0694).indd 189 8/10/07 12:59:01 AM


190 CAPÍTULO 4 Planificación

22. Waldspurger, C.A. y W.E.Weihl (1994): “Lottery scheduling”, Proceedings of the First USENIX
Symposium on Operating System Design and Implementation (OSDI), 1-11.
23. Zhao, W. (1989): Special issue on real-time operating systems, Operating System Review, 23, 7.
24. Zhu, D., D. Mosse y R. Melhem (2004): “Power-aware scheduling for AND/OR graphs in real-
time systems”, IEEE Transactions on Parallel and Distributed Systems, 15 (9), 849-864.

05 MAQ. CAP. 04(F0694).indd 190 8/10/07 12:59:01 AM


Capítulo
5
Administración de
la memoria

Como se vio en el capítulo 2, la jerarquía de la memoria incluye el caché, la unidad de admi-


nistración de la memoria (MMU), la memoria de acceso aleatorio o memoria de acceso directo
(RAM), que en este capítulo simplemente se denomina memoria, y un disco. La administración
de la memoria que realiza el SO se analiza en dos partes: en este capítulo se abordarán las téc-
nicas para obtener un uso eficaz de ella, mientras que en el capítulo siguiente se estudiará la
administración de la memoria virtual, que forma parte de la jerarquía de la memoria que consta
de la memoria y el disco.
Se empieza por analizar los fundamentos de las asignaciones estática y dinámica de la me-
moria. Luego se introduce el modelo utilizado para la asignación de la memoria a un proceso y
se muestra cómo el modelo se ajusta a las componentes estática y dinámica.
Para asegurar el uso eficaz de la memoria, el kernel vuelve a utilizar la memoria asignada
a un proceso cuando éste termina. La fragmentación de la memoria es un problema que vuelve
inutilizables algunas áreas de la memoria, lo cual conduce a un uso ineficaz de ésta. Se analizan
técnicas prácticas que se utilizan en la fragmentación de la memoria, especialmente asignación
de memoria no contigua utilizando paginamiento y segmentación. El kernel usa parte de la me-
moria para llevar a cabo sus propias actividades: para bloques de control como los PCB y los
ECB. Los tamaños de estos datos se conocen de antemano, de modo que el kernel utiliza técni-
cas especiales que aprovechan este conocimiento para lograr asignación/retiro de asignaciones
rápidas de los bloques de control y un uso eficaz de la memoria. En la última sección se analizan
ligamiento, relocalización y propiedades de formas de programas. Esta sección es de utilidad
para lectores que se están iniciando en el estudio de estos temas.

5.1 ADMINISTRACIÓN DE LA JERARQUÍA DE LA MEMORIA

Como ya se analizó en el capítulo 2, la jerarquía de la memoria es un arreglo de varias unidades


de memoria con velocidades y tamaños variables que crea una ilusión de una memoria rápida y
grande a bajo costo. El CPU recurre a la memoria más rápida, el caché, cuando requiere acceder
a una instrucción o a datos. Si éstos no están disponibles en el caché, se trae del siguiente nivel
inferior en la jerarquía de la memoria, que puede ser un caché más lento o la memoria de acceso

06 MAQ. CAP. 05(F0694).indd 191 8/10/07 12:59:40 AM


192 CAPÍTULO 5 Administración de la memoria

aleatorio (RAM), que en este libro simplemente se denomina memoria. Si la instrucción o los
datos requeridos tampoco están disponibles en el siguiente nivel inferior de memoria, se lleva
ahí desde un nivel aún más bajo, y así sucesivamente. El desempeño de la jerarquía de la me-
moria depende de la relación de impactos en varios niveles de la jerarquía, donde la relación de
impactos en un nivel indica qué fracción de los bytes de las instrucciones o los datos que se bus-
caban en ese nivel en realidad estaba ahí. La ecuación (2.1) del capítulo 2 indica cómo el tiempo
de acceso efectivo a la memoria depende de una relación de impactos.
En la figura 5.1 se ilustra la jerarquía de la memoria y se describe su operación. Está inte-
grada por memorias caché, como los cachés L1 y L2, la unidad de administración de la memoria,
la memoria y un disco. Los cachés L1 y L2 se manejan en el hardware, de modo que el kernel
y los programas del usuario deben emplear técnicas especiales para obtener altas relaciones de
impactos en los cachés. Por ejemplo, el kernel elimina el espacio de direcciones de un proceso
priorizado o bloqueado de un caché a fin de asegurar protección de la memoria. Esta acción
conduce a una deficiente relación de impactos para un proceso cuando se inicia su operación o
cuando vuelve a reanudarse luego de una pausa. El kernel responde a este efecto al intercambiar
entre hilos del mismo proceso siempre que es posible, así como a través de la planificación
con afinidad en un sistema de multiprocesador (consulte la sección 13.5). En la sección 5.10 se
analizarán técnicas especiales de diseño usadas por el kernel para asegurar un desempeño acep-
table del caché mientras se accede a estructuras de datos del kernel.
Éste asigna memoria para los procesos del usuario. La preocupación más importante sobre
el desempeño en esta función es alojar más procesos del usuario en la memoria para mejorar
tanto el desempeño del sistema como el servicio del usuario. El kernel satisface esta preocupa-
ción mediante la reutilización eficaz de la memoria cuando termina un proceso, lo cual reduce
la cantidad de memoria no utilizada en el sistema en cualquier momento. Durante su operación,
un proceso crea estructuras de datos dentro de la memoria ya asignada al proceso por el kernel.
Esta función la lleva a cabo en realidad la biblioteca en tiempo de ejecución (run-time) del len-
guaje de programación en que está escrito el código del proceso. La biblioteca utiliza técnicas
que de manera eficaz reutilizan la memoria cuando un proceso crea y destruye estructuras de
datos durante su operación. Así, algunos de los intereses y técnicas empleadas por el kernel y las
bibliotecas run-time son semejantes.
Como una secuela del interés del kernel por alojar un gran número de procesos en la me-
moria, aquél puede decidir preservar en ésta sólo una parte de cada espacio de direcciones de
un proceso. Esto se logra usando la parte de la jerarquía de la memoria denominada memoria
virtual, que incluye la memoria y un disco (consulte el recuadro discontinuo en la figura 5.1). Las
partes de un espacio de direcciones de un proceso que no están en la memoria se cargan desde
el disco cuando se requieren durante la ejecución del proceso. En este arreglo, la relación
de impactos de un proceso en la memoria determina su desempeño. Por tanto, el kernel utiliza
un conjunto de técnicas para asegurar una elevada relación de impactos para los procesos. El
disco en la memoria virtual es administrado totalmente por el kernel; éste almacena en el dis-
co diferentes partes de cada espacio de direcciones del proceso, de modo que sea posible acce-
der de manera eficaz a ellas, lo que contribuye a un desempeño aceptable de la ejecución de los
procesos en una memoria virtual.
El análisis de la jerarquía de la memoria en un sistema operativo se realiza en dos partes.
Este capítulo se centra en la administración de la memoria y se enfoca en las técnicas utilizadas
para obtener un uso eficaz de la misma, y de su asignación y retiro de asignación rápidas. Des-
pués se analizará la forma en que la unidad de administración de la memoria (MMU) simpli-
fica estas dos funciones. En el capítulo 6 se abordará la administración de la memoria virtual,

06 MAQ. CAP. 05(F0694).indd 192 8/10/07 12:59:40 AM


5.2 Asignaciones estática y dinámica de la memoria 193

CPU

Caché L1

MMU

Caché L2

Memoria

Memoria
virtual
Disco

Características del
Nivel Cómo se administra desempeño
Caché L1 La asignación y el uso son adminis- Asegurar altas relaciones de im-
trados por el hardware pacto
Caché L2 La asignación y el uso son adminis- Asegurar altas relaciones de im-
trados por el hardware pacto
Memoria La asignación es administrada por el 1) Alojar más procesos en la me-
kernel y el uso de la memoria asig- moria, 2) asegurar altas relaciones
nada es administrado por las biblio- de impacto
tecas run-time
Disco La asignación y el uso son adminis- Carga y almacenamiento rápidos
trados por el kernel de partes de los espacios de direc-
ciones de los procesos

Figura 5.1 Administración de la jerarquía de la memoria.

especialmente las técnicas utilizadas por el kernel para asegurar altas relaciones de impacto en la
memoria y limitar la que se dedica a cada proceso.

5.2 ASIGNACIONES ESTÁTICA Y DINÁMICA


DE LA MEMORIA
La asignación de la memoria a un proceso implica especificar las direcciones de la memoria a
sus instrucciones y datos. Constituye también un aspecto de una acción más general denominada
unión. Otros dos aspectos relacionados con la ejecución de un programa, a saber, ligamiento y

06 MAQ. CAP. 05(F0694).indd 193 8/10/07 12:59:41 AM


194 CAPÍTULO 5 Administración de la memoria

carga, también son parte de la unión. Este capítulo empieza con una rápida revisión general de
dos métodos fundamentales para ejecutar la unión, sus propiedades fundamentales y sus impli-
caciones para la asignación de la memoria, el ligamiento y la carga de programas.
Una entidad posee varios atributos y cada uno tiene un valor. Por ejemplo, una variable
en un programa tiene atributos como tipo, dimensionalidad, alcance y dirección de la memoria.
La unión es el acto de especificar el valor de un atributo. La asignación de la memoria es el acto
de especificar el atributo de dirección de la memoria de una entidad.
Las uniones deben realizarse para los atributos de una entidad antes de que la entidad sea
utilizada durante la operación de un proceso o de un sistema de software. Las uniones estática y
dinámica constituyen dos métodos fundamentales para llevar a cabo la unión.

Definición 5.1 (Unión estática y dinámica) La unión estática es una unión realizada antes
del inicio de la operación de un programa (o de un sistema de software), mientras que la
unión dinámica es una unión realizada durante su operación.

Durante la ejecución de un programa puede estar disponible más información relacionada


con una entidad que antes del inicio de su ejecución. Usando esta información, pueden llevarse a
cabo uniones de mejor calidad. Por ejemplo, la unión dinámica puede obtener un uso más eficaz
de recursos, como la memoria.

Asignaciones estática y dinámica de memoria La asignación estática de memoria pue-


de realizarse con un compilador, un ligador o cargador mientras se prepara la ejecución de un
programa. La asignación dinámica de memoria se lleva a cabo de manera posterior. Es decir,
la memoria se asigna a una entidad durante la ejecución de un programa justo antes de usar la
entidad por primera vez.
La asignación estática de memoria es posible sólo si antes de iniciar la ejecución de un pro-
grama se conocen los tamaños de los datos. Si no se conocen, es necesario conjeturarlos, lo cual
puede conducir a desperdicio de memoria y a falta de flexibilidad. Por ejemplo, considere un
arreglo cuyo tamaño se desconoce durante la compilación. Se desperdicia memoria si su tamaño
conjeturado es mayor que el real, mientras que un programa no puede ejecutarse correctamente
si su tamaño real es mayor que el conjeturado. La asignación dinámica puede evitar estos proble-
mas, ya que el tamaño real del arreglo debe conocerse en el instante de realizar la asignación.
La asignación estática de memoria no requiere acciones de asignación de memoria durante
la ejecución de un programa. En contraste, la asignación dinámica incurre en sobrecarga de ac-
ciones de asignación de memoria realizadas durante la ejecución de un programa. Incluso, algu-
nas de estas acciones se repiten varias veces durante dicha ejecución. En la tabla 5.1 se resumen
características clave de las asignaciones estática y dinámica de memoria.
Los sistemas operativos aprovechan las características de las asignaciones estática y dinámi-
ca de memoria para obtener la mejor combinación de eficacia y flexibilidad de la ejecución. Sin
considerar si la flexibilidad no es importante o necesaria, el SO lleva a cabo en forma estática
decisiones de asignación de la memoria. Este método proporciona eficacia de ejecución. Cuando
la flexibilidad es necesaria y su costo es justificable, el SO lleva a cabo en forma dinámica de-
cisiones de asignación de la memoria. Por ejemplo, aplica asignación estática de memoria para
algunos atributos de estructuras de datos del kernel porque conoce características de datos de
éste (consulte la sección 5.10), mientras puede realizar asignación dinámica de memoria para

06 MAQ. CAP. 05(F0694).indd 194 8/10/07 12:59:41 AM


5.2 Asignaciones estática y dinámica de la memoria 195

Tabla 5.1 Características de las asignaciones estática y dinámica de memoria

Tipo de asignación Características clave


Asignación estática • La asignación se realiza antes del inicio
de la ejecución de un programa.
• Antes de iniciar la ejecución es necesario
conocer el tamaño de los datos, ya que
puede desperdiciarse memoria asignada
o un proceso puede quedarse sin memo-
ria durante su operación.
• Ninguna acción de asignación durante la
ejecución de un programa.
Asignación dinámica • La asignación se realiza durante la eje-
cución de un programa.
• La asignación es exactamente igual al
tamaño de los datos; no hay desperdicio
de memoria.
• Sobrecarga de asignación durante la eje-
cución de un programa.

programas del usuario porque no conoce mucho sobre éstos. También puede realizar asignación
dinámica de memoria a diversas partes de un programa a fin de reducir el desperdicio de memo-
ria y mejorar el desempeño del sistema.

Ligamiento/carga estática y dinámica La diferencia entre los términos ligamiento y


carga se ha vuelto algo difusa. Sin embargo, un ligador liga módulos entre sí para integrar un
programa ejecutable. Un cargador carga en la memoria un programa o una parte de él para su
ejecución.
Un ligador estático liga todos los módulos de un programa antes de que empiece su eje-
cución. Si varios programas usan el mismo módulo de una biblioteca, entonces cada uno debe
poseer una copia privada del módulo y al mismo tiempo puede haber varias copias de éste en
la memoria. El ligamiento dinámico de un módulo se realiza cuando debe ejecutarse alguna re-
ferencia. Proporciona una amplia gama de posibilidades relacionadas con el uso, compartición
y actualización de los módulos de una biblioteca. Los módulos que no son invocados durante
la ejecución de un programa no necesitan estar ligados en absoluto al programa. Si el módulo
referido por un programa ya ha sido ligado a otro que igualmente está en ejecución, enton-
ces también es posible ligar la misma copia a este programa. El ligamiento dinámico consti-
tuye también una ventaja interesante cuando se actualiza una biblioteca de módulos: ¡cualquier
programa que invoca a un módulo nuevo automáticamente empieza a usar la nueva versión del
módulo! Las bibliotecas ligadas dinámicamente (DLL) aprovechan algunas de estas caracte-
rísticas.
El ligamiento dinámico requiere carga dinámica. Sin embargo, ésta también puede usarse
con ligamiento estático. Su ventaja es que no es necesario en absoluto cargar los módulos que
no han sido invocados. Otra forma para conservar memoria consiste en sobrescribir un nuevo
módulo en uno ya existente en la memoria. Esta idea se aplica en la memoria virtual, que se
analizará en el capítulo siguiente.

06 MAQ. CAP. 05(F0694).indd 195 8/10/07 12:59:41 AM


196 CAPÍTULO 5 Administración de la memoria

5.3 ASIGNACIÓN DE MEMORIA A UN PROCESO

5.3.1 Pilas y montículos

El compilador de un lenguaje de programación genera un código para un programa y asigna sus


datos estáticos. Crea un módulo objeto para el programa (consulte la sección 5.11) que contiene
el código, los datos estáticos e información sobre su tamaño. El ligador vincula el programa con
funciones de biblioteca y con el soporte run-time del lenguaje de programación, prepara una
forma listo-para-ejecución de los programas y la almacena en un archivo. La información sobre
el tamaño del programa se registra en el elemento del directorio del archivo.
El soporte run-time asigna dos tipos de datos durante la ejecución de un programa. El pri-
mero incluye variables cuyo alcance está asociado con funciones, procedimientos o bloques en
un programa. Los datos son asignados cuando se ingresa una función, un procedimiento o un
bloque, y se retira su asignación una vez que salen. Debido a la naturaleza último en entrar-pri-
mero en salir de su asignación/retiro de asignación, estos datos se asignan a la pila. El segundo
tipo de datos son aquéllos creados dinámicamente por un programa que utiliza características
de lenguaje, como la nueva declaración de Pascal, C o Java, o las declaraciones malloc,
calloc de C. Éstos se denominan datos dinámicos controlados por programa (datos PCD), y se
asignan utilizando una estructura de datos denominada montículo.

Pila En una pila, las asignaciones/retiro de asignaciones se realizan según la manera último
en entrar-primero en salir (LIFO) en respuesta a las operaciones push (apilar) y pop (desapilar o
retirar), respectivamente. Se supone que cada elemento en la pila posee algún tamaño estándar;
por ejemplo, l bytes. Sólo el último elemento de la pila es accesible en cualquier instante. Para
la pila se reserva un área contigua de la memoria. Un apuntador denominado primer objeto
apilado (SB) apunta hacia el primer elemento de la pila, mientras un apuntador denominado
último objeto apilado (TOS) lo hace hacia el último elemento asignado a la pila. Se establece así
el convenio de que una pila crece hacia la parte inferior de la memoria; en las figuras se describe
a medida que crece hacia arriba.
Durante la ejecución de un programa, para admitir llamadas de funciones se utiliza una pila.
El grupo de elementos en la pila que pertenecen a una llamada de funciones se denomina registro
de activación en terminología de compilación. Un registro de activación se apila cada vez que se
llama a una función. Para empezar, el registro de activación contiene direcciones o valores de los
parámetros de la función y la dirección de retorno, es decir, la dirección de la instrucción a la que
debe regresar el control luego de terminar la ejecución de la función. Durante la ejecución de la
función, el soporte run-time del lenguaje de programación en el que está codificado el programa
crea datos locales de la función dentro del registro de activación. Al final de la ejecución de
la función todo el registro de activación es retirado de la pila y la dirección de retorno se usa para
devolver el control al programa que está llamando.
Para facilitar el uso de los registros de activación se toman en cuenta dos aspectos: el primer
elemento en un registro de activación es un apuntador que señala hacia el registro de activación
previo de la pila. Este elemento facilita el desapilamiento de un registro de activación. Un apun-
tador adicional denominado registro base (FB) se utiliza para apuntar hacia el inicio del registro
de activación más alto en la pila. Es de utilidad para acceder a diversos elementos de la pila en
el registro de activación. En el ejemplo 5.1 se ilustra cómo se usa la pila para implementar lla-
madas de funciones.

06 MAQ. CAP. 05(F0694).indd 196 8/10/07 12:59:41 AM


5.3 Asignación de memoria a un proceso 197

Ejemplo 5.1 En la figura 5.2 se muestra la pila durante la ejecución de un programa que contie-
ne llamadas de funciones anidadas. En la figura 5.2a) se muestra la pila después de que main, la
función primaria del programa, ha hecho una llamada de función sample(x, y, i). Un registro de
activación se apiló cuando se hizo la llamada. El primer elemento del registro de activación contie-
ne un apuntador que apunta hacia el registro de activación previo en la pila. El segundo elemento
es ret_ad(main), que es la dirección de retorno hacia la función main. Los tres siguientes elemen-
tos pertenecen a los parámetros x, y e i, mientras que los elementos que los suceden pertenecen
a datos locales de la función sample. El apuntador del registro base apunta al primer elemento
en el registro de activación. El del último objeto apilado lo hace hacia los últimos datos locales en
el registro de activación. El código para la función sample accede a la dirección de retorno, a infor-
mación sobre los parámetros y a sus datos locales usando desplazamientos con respecto al registro
base: en el supuesto de que cada elemento en la pila sea igual a 4 bytes, la dirección de retorno se
encuentra a un desplazamiento de 4 con respecto al registro base, el primer parámetro está a un
desplazamiento de 8 con respecto al registro base, etcétera.
En la figura 5.2b) se muestra la pila después de que la función sample ha hecho una llamada
de función calc(a, b, sum). Se ha apilado un nuevo registro de activación, el valor del registro base se
ha guardado en el primer elemento de este registro de activación, el registro base se ha dirigido a un
punto al inicio del nuevo registro de activación y la parte superior del apuntador de pila entonces
apunta al último elemento en el nuevo registro de activación. Al término de la función, el apuntador
del último objeto apilado debe dirigirse hacia el elemento de la pila que precede al elemento indi-
cado por el registro base, y éste debe cargarse con la dirección contenida en el elemento de la pila
al que estaba apuntando. Estas acciones extraen de manera eficaz el registro de activación de calc
y establecen el registro base de modo que apunte hacia el inicio del registro base para sample. La
pila resultante debe ser idéntica a la que había antes que la función sample llamara a calc.

Último
objeto Registro de
Datos locales
apilado
de calc activación
(TOS) sum para
b llamar a
a calc
Último Registro ret ad(sample)
base FB previo
objeto (FB)
Datos locales Datos locales Registro de
apilado de sample Registro de de sample activación
(TOS) i activación i para
y para y llamar a
x llamar a x sample
Registro ret ad(main) sample ret ad(main)
base FB previo FB previo
(FB)
a) b)

Figura 5.2 Pila después de que a) main llama a sample, b) sample llama a calc.

Montículo Un montículo permite asignación y retiro de asignación de memoria en orden


aleatorio. Una solicitud de asignación hecha por un proceso regresa con un apuntador hacia el
área de memoria asignada en el montículo, y el proceso accede al área de memoria asignada
mediante este apuntador. Una solicitud de retiro de asignación debe presentar un apuntador hacia

06 MAQ. CAP. 05(F0694).indd 197 8/10/07 12:59:42 AM


198 CAPÍTULO 5 Administración de la memoria

el área de memoria cuya asignación será retirada. En el siguiente ejemplo se ilustra el uso de un
montículo para administrar los datos PCD de un proceso. Como se muestra ahí, en la asignación
de memoria se desarrollan huecos, como estructuras de datos, según se crean y liberan. El asig-
nador de montículos debe volver a utilizar estas áreas libres de la memoria mientras satisface
futuras demandas de memoria.

Ejemplo 5.2 En la figura 5.3 se muestra el estatus de un montículo después de ejecutar el siguiente
programa C:

float *floatptr1, *floatptr2;


int *intptr;
floatptr1 = (float *) calloc(5, sizeof(float));
floatptr2 = (float *) calloc(4, sizeof(float));
intptr = (int *) calloc(10, sizeof(int));
free(floatptr2);

La rutina calloc se utiliza para hacer una solicitud de memoria. La primera llamada solicita me-
moria suficiente para alojar 5 números de punto flotante. El asignador de montículos asigna un
área de memoria y devuelve el apuntador a ésta. Este apuntador se almacena en floatptr1. Se
supone que los primeros bytes de cada área de memoria asignada contienen un campo length. Éste
se utiliza durante el retiro de asignación cuando la rutina free es llamada con un apuntador a un
área de memoria asignada. En la figura 5.3a) se muestra el montículo después del procesamiento
de todas las llamadas calloc. En la figura 5.3b) se le muestra después de la llamada free call;
free ha liberado el área de memoria a la que está indicando floatptr2. Esta acción origina un
“hueco” en la asignación.

floatptr1 20 floatptr1 20
floatptr2 floatptr2 –
intptr 16 intptr
40 40
campo
length

a) b)

Figura 5.3 a) Un montículo, b) un “hueco” en la asignación cuando se retira la asignación de la memoria.

5.3.2 El modelo de asignación de memoria

La memoria asignada a un proceso contiene lo siguiente:


• Código y datos estáticos del programa que se va a ejecutar.
• Pila.
• Datos dinámicos controlados por programa (datos PCD).
El compilador de un lenguaje de programación genera el código para un programa y asigna
sus datos estáticos. El ligador liga lo anterior con el código de los módulos de la biblioteca que

06 MAQ. CAP. 05(F0694).indd 198 8/10/07 12:59:42 AM


5.3 Asignación de memoria a un proceso 199

requiere para preparar una versión lista para ejecutar el programa y el cargador carga esta versión
en la memoria (consulte la sección 5.11 para ver un repaso del ligamiento y la carga). La pila
contiene algunos datos del programa y datos creados y usados específicamente para controlar
su ejecución; por ejemplo, parámetros de procedimientos o funciones que han sido llamadas,
pero de las cuales no se ha salido, y dirección de retorno que se van a utilizar mientras se sale
de ellas.
Dos tipos de datos son asignados dinámicamente por el soporte run-time de un lenguaje de
programación. El primero incluye variables cuyos alcances están asociados con funciones, pro-
cedimientos o bloques en un programa. Los datos son asignados cuando se ingresa una función,
un procedimiento o un bloque y se retira su asignación cuando se sale de ellos. Debido a la na-
turaleza LIFO de su asignación/retiro de asignación, estos datos se asignan a la pila. El segundo
tipo de datos son aquéllos creados dinámicamente por un programa que utiliza características de
lenguaje, como la nueva declaración de Pascal, C o Java, o las declaraciones malloc, calloc
de C. Estos datos se denominan datos dinámicos controlados por programa (datos PCD), y se
asignan utilizando una estructura de datos denominada montículo (consulte la sección 5.3.1).
Los tamaños del código y las componentes de los datos estadísticos en un programa se
conocen en el momento de la compilación. El compilador coloca esta información en la for-
ma compilada de un programa (llamada módulo objeto: consulte la sección 5.11). Cuando la
forma ejecutable de un programa se almacena en un archivo, el elemento del directorio del archi-
vo contiene la información del tamaño.
Los tamaños de la pila y los datos PCD varían durante la ejecución de un programa. Así,
¿cómo sabe el kernel cuánta memoria asignar para la ejecución de un programa? En gene-
ral, no lo sabe. Puede conjeturar tamaños de estas componentes dinámicas y asignarles cierta
cantidad de memoria. Sin embargo, esto supone asignación estática y, por ende, falta de fle-
xibilidad. Como se analizó en la sección 5.2, la memoria asignada puede desperdiciarse o un
programa puede quedarse sin espacio durante su ejecución.

Extremo bajo
de la
memoria asignada
Código

Datos
estáticos

Datos PCD dirección de


crecimiento
espacio
libre
dirección de
Pila crecimiento
Extremo alto
de la
memoria asignada
Figura 5.4 Modelo de asignación de memoria para un proceso.

06 MAQ. CAP. 05(F0694).indd 199 8/10/07 12:59:42 AM


200 CAPÍTULO 5 Administración de la memoria

A fin de no tener que enfrentar individualmente estos problemas para estas dos componen-
tes, los sistemas operativos utilizan un modelo de asignación de memoria que se muestra en la
figura 5.4. El código y las componentes de los datos estáticos en el programa son áreas de memo-
ria asignadas que corresponden exactamente a sus tamaños. Los datos PCD en la pila comparten
una sola área grande de memoria, pero crecen en direcciones opuestas cuando la memoria se
asigna a nuevas entidades. Los datos PCD se asignan empezando en el extremo bajo de esta área,
mientras la pila se asigna empezando en el extremo alto de la misma. La memoria entre estas dos
componentes es libre. Puede usarse para crear nuevas entidades en cualquier componente. En
este modelo, las componentes de la pila y de los datos PCD no tienen restricciones individuales
de tamaño.
Una vez que se inicia la ejecución de un programa, el kernel le asigna un área de la memoria
y carga su código y datos estáticos. La memoria restante es libre: se utiliza para los datos PCD y
para la pila según se describió antes. A medida que se llevan a cabo el procedimiento y las
llamadas de funciones, en la pila se crean nuevos elementos, mientras que en el área PCD se
crean cuando el programa solicita memoria para sus datos controlados. Éstos son aspectos de la
asignación dinámica de memoria, de modo que, según están descritos en la tabla 5.1, atraen
penalizaciones sobre el tiempo de ejecución debido a acciones de asignación o retiro de asig-
nación.
Durante su ejecución, un programa crea o destruye datos PCD al llamar rutinas idóneas de
la biblioteca run-time del lenguaje de programación en el que está codificado. Las rutinas de la
biblioteca llevan a cabo asignaciones/retiro de asignaciones en el área de datos PCD asignada
a la ejecución del programa. Así, el kernel no está implicado en este tipo de administración de
memoria. De hecho, es ajeno a ella.

5.3.3 Localización y ejecución de un programa

Un programa suele estar codificado (o compilado) de modo que sea posible ejecutarlo sólo en un
área específica de la memoria. Ésta puede no estar disponible cuando se va a ejecutar un programa,
de modo que el mismo debe ejecutarse en el área de la memoria para la cual está preparado, o bien
es necesario cambiar su código, de modo que el programa puede ser ejecutado correctamente
desde alguna otra área de la memoria. La acción realizada en el segundo caso se denomina
relocalización de un programa. Se lleva a cabo mediante un cargador de relocalización. El uso
del cargador de relocalización va acompañado por algunos costos de procesamiento y memoria
que se describirán más tarde, en la sección 5.11. En algunas arquitecturas de computadora se
utiliza un esquema ingenioso para facilitar la ejecución de un programa desde cualquier área de
la memoria sin incurrir en estos costos.

Registro de relocalización Un registro de relocalización es un registro especial en el CPU


que ayuda a la relocalización de un programa. Contiene un número entero. El CPU lo suma a
toda dirección generada durante la ejecución de un programa. El resultado es otra dirección de la
memoria, que se utiliza para hacer una referencia de ella. Así,

Dirección de la memoria efectiva  Dirección utilizada en una instrucción


 contenido del registro de relocalización.

En el ejemplo 5.3 se ilustra cómo puede usarse el registro de relocalización para lograr la relo-
calización de un programa.

06 MAQ. CAP. 05(F0694).indd 200 8/10/07 12:59:43 AM


5.3 Asignación de memoria a un proceso 201

Programa CPU Memoria


50000
55000 Sumar 65784 PSW 75000
Registro de 70000
relocalización 20000
65784 75000 Sumar 65784

85784

a) b)

Figura 5.5 Relocalización de un programa usando un registro de relocalización:


a) programa, b) ejecución.

Ejemplo 5.3 Se ha preparado un programa para su ejecución en un área de la memoria que empie-
za en la dirección 50000. Ésta se denomina dirección de memoria inicial supuesta. Considere que el
área de la memoria asignada a la ejecución del programa tiene la dirección inicial 70000 (consulte
la figura 5.5). La relocalización del programa se logra simplemente cargando un valor idóneo en el
registro de relocalización, lo cual se calcula como sigue:

Valor que debe ser cargado en el registro de relocalización


 dirección inicial de la memoria asignada  dirección inicial supuesta
 70000  50000  20000.

Considere la ejecución de la instrucción Add en el programa. Existe en el byte de la memoria con la


dirección 55000 en el programa, y accede al byte de la memoria con dirección 65784. Esta instruc-
ción debe cargarse en la localización con dirección 75000. Durante su ejecución, debe accederse al
byte de la memoria con la dirección 65784  20000  85784.

5.3.4 Protección de la memoria


Para asegurar que los procesos no interfieran entre sí con sus códigos o datos, cada dirección
de la memoria utilizada por el proceso debe comprobarse para ver si está dentro del área o las
áreas de la memoria asignadas al proceso. Por razones evidentes, esta función no puede ser rea-
lizada por el software, de modo que su implementación requiere soporte de una arquitectura de
máquina. Este soporte se presenta en dos formas: registros acotados por la memoria y llaves
de protección de la memoria asociadas con áreas de ella.
Como se analizó en la sección 2.1.1, la protección de la memoria mediante la utilización de
registros acotados por ella se implementa usando el registro de límite inferior (LBR) y el registro
de límite superior (UBR) en el CPU. Éstos contienen las direcciones inicial y final, respectiva-
mente, del área de la memoria asignada a un proceso (consulte la figura 5.6), y se almacenan
en el campo información de protección de la memoria (MPI) del PSW. El kernel carga valores
idóneos en el LBR y el UBR mientras programa un proceso para su ejecución. El proceso de un
usuario no debe poder manipular los valores en estos registros, de modo que las instrucciones
para cargar y salvarlos se convierten en instrucciones privilegiadas.

06 MAQ. CAP. 05(F0694).indd 201 8/10/07 12:59:43 AM


202 CAPÍTULO 5 Administración de la memoria

Interrupción Memoria
por violación a 0K
la protección Kernel
de la memoria 50K
Load 85252 p1
CPU
80K
LBR 50K ? p2
UBR 80K

dirección p3
85252

Figura 5.6 Protección de la memoria utilizando registros acotados por la memoria.

El hardware de protección de la memoria compara cada dirección de la memoria utilizada


por el proceso con el contenido de los registros acotados por la memoria. Se genera una interrup-
ción por violación a la protección de la memoria si la dirección es más pequeña que la dirección
en el LBR o mayor que la dirección en el UBR. Al procesar esta interrupción, el kernel termina
el proceso de error.
Cuando se utiliza un registro de relocalización (consulte la sección 5.3.3), la dirección de
la memoria efectiva debe compararse con las direcciones contenidas en el LBR y en el UBR.
La verificación de la protección de la memoria se hace más sencilla si todo programa posee la
dirección inicial supuesta de “0000”. Entonces, tanto el registro de relocalización como el LBR
contienen la misma dirección. Así, es posible eliminar el LBR. Además, ya no es necesario com-
probar si una dirección efectiva es menor que la contenida en el registro de relocalización.

5.4 REÚSO DE LA MEMORIA

Dos cuestiones fundamentales en el diseño de un asignador de memoria son la velocidad de su


asignación y su uso eficaz. Este uso contempla dos facetas.

• Sobrecarga de memoria del asignador: La sobrecarga de memoria incluye la memoria


usada por el asignador de memoria para su propia operación, así como la utilizada por un
proceso solicitante a fin de mantener el rastro de la memoria asignada.
• Reúso de la memoria liberada por los procesos: Debe ser posible volver a usar la memo-
ria liberada por un proceso mientras se hacen nuevas asignaciones de memoria.

En una pila, la sobrecarga de memoria consta de los apuntadores SB y TOS. El reúso de


la memoria es automático, ya que la memoria liberada cuando un registro es desapilado, se
emplea cuando en la pila se crea un nuevo registro. En un montículo, la sobrecarga de memoria
consta de apuntadores hacia áreas asignadas. El reúso de la memoria no es automático; el asig-
nador de memoria debe intentar usar nuevamente un área libre mientras se hacen nuevas asigna-
ciones de memoria. El uso eficaz de la memoria se convierte aquí en una cuestión importante
porque el tamaño de una nueva solicitud de memoria rara vez equivale al de cualquier área de
memoria liberada, de modo que siempre existe la posibilidad de que pueda desperdiciarse algo
de memoria cuando se vuelve a usar un área de memoria.

06 MAQ. CAP. 05(F0694).indd 202 8/10/07 12:59:43 AM


5.4 Reúso de la memoria 203

El asignador de memoria mantiene una lista libre para conservar información concernien-
te a todas las áreas libres de memoria que hay en el sistema. La lista se elabora usando partes
de las áreas libres. De esta forma, su existencia no impone una sobrecarga. En la figura 5.7a)
se muestra una lista libre con liga sencilla en un montículo que contiene cinco áreas indicadas
por a-e en uso activo y tres áreas libres x-z. Los primeros bytes en cada área libre contienen el
tamaño del área. Los siguientes contienen un apuntador hacia la siguiente área libre en la lista.
En la figura 5.7b) se muestra una lista libre doblemente ligada. Con esta organización se facilita
la adición/borrado de nuevas áreas de memoria a/de la lista. En ambos casos, los elementos
pueden disponerse en orden creciente de tamaño, de modo que la “mejor” área en satisfacer una
solicitud de memoria pueda identificarse fácilmente.

-
a) Encabezado
de la lista a x b y c d z e
libre

- -
b) Encabezado
de la lista
libre a x b y c d z e

Figura 5.7 Administración de áreas libres: a) lista libre con liga sencilla, b) lista libre doblemente ligada.

Cómo hacer nuevas asignaciones usando una lista libre


Para hacer una asignación nueva a partir de una lista libre es posible aplicar tres técnicas:

• Técnica del primer ajuste.


• Técnica del mejor ajuste.
• Técnica del siguiente ajuste.

Para atender una solicitud de n bytes de memoria, la técnica del primer ajuste utiliza la
primera área libre que puede encontrar cuyo tamaño sea  n bytes. A la solicitud se asignan n
bytes, y lo que queda del área se devuelve a la lista libre. Esta técnica adolece del siguiente pro-
blema: las áreas de memoria libres pueden separarse varias veces, de modo que pueden hacerse
cada vez más pequeñas. La técnica del mejor ajuste usa el área libre más pequeña de tamaño
 n. Esto evita la separación innecesaria de áreas grandes; sin embargo, tiende a generar peque-
ñas áreas libres debido a las separaciones. Por tanto, a largo plazo, también puede experimentar
el problema de numerosas áreas libres pequeñas. Igualmente incurre en mayor costo de asig-
nación porque tiene que procesar toda la lista libre en cada asignación o mantenerla en orden
creciente de tamaño. La siguiente técnica de ajuste es una solución intermedia entre las dos
anteriores. Recuerda el elemento a partir del que se hizo la última asignación. Mientras tanto,
realiza una nueva asignación, busca la lista libre empezando a partir del siguiente elemento y
lleva a cabo la asignación usando la primera área libre de tamaño  n bytes que pueda encontrar.

06 MAQ. CAP. 05(F0694).indd 203 8/10/07 12:59:43 AM


204 CAPÍTULO 5 Administración de la memoria

Así evita separar de manera repetida la misma área libre como en la técnica del primer ajuste y
también la sobrecarga de asignación de la técnica del mejor ajuste.

a) Encabezado
de la lista libre 200 170 500

b) 100 50 400

50 170 100

c) 100 50 400

200 20 100

d) 100 50 400

100 120 100

Figura 5.8 a) Lista libre, b)-d) asignación usando las técnicas de primer ajuste, mejor ajuste y siguiente ajuste.

Ejemplo 5.4 Como se muestra en la figura 5.8a), una lista libre contiene tres áreas libres de ta-
maños 200, 170 y 500 bytes, respectivamente. Los procesos realizan solicitudes de asignación por
100, 50 y 400 bytes. La técnica del primer ajuste asigna 100 y 500 bytes de la primera área libre,
dejando un área libre de 50 bytes. Asigna 400 bytes de la tercera área libre. La técnica del mejor
ajuste asigna 100 y 50 bytes de la segunda área libre, dejando un área libre de 20 bytes. La técnica
del siguiente ajuste asigna 100, 50 y 400 bytes de las tres áreas libres.

Knuth (1973) presenta datos experimentales y concluye que, en la práctica, el primer ajuste
es superior al mejor ajuste. Tanto el primero como el siguiente se desempeñan mejor que el
mejor ajuste. Sin embargo, el siguiente ajuste tiende a separar todas las áreas libres si el sistema
ha estado en operación lo suficiente, mientras que el primer ajuste puede no separar las últimas
áreas libres. Esta característica facilita la asignación de grandes áreas de memoria cuando se
utiliza la técnica del primer ajuste.

Fragmentación de la memoria

Definición 5.2 (Fragmentación de la memoria) La fragmentación de la memoria es la exis-


tencia de áreas inutilizables en la memoria de un sistema de computación.

En la tabla 5.2 se describen dos aspectos de la fragmentación de la memoria. La fragmen-


tación externa ocurre si un área de la memoria permanece sin usarse debido a que no puede ser
asignada. La fragmentación interna ocurre si a un proceso se le asigna más memoria de la que
requiere. El resto de la memoria permanece sin usarse. En la figura 5.8c), la asignación del mejor
ajuste crea un área libre de 20 bytes, lo cual es demasiado pequeño para ser asignado. Éste es un
ejemplo de fragmentación externa. Sería deseable contar con fragmentación interna en caso de
que un asignador deba asignar 70 bytes de memoria cuando un proceso solicita 50 bytes.

06 MAQ. CAP. 05(F0694).indd 204 8/10/07 12:59:44 AM


5.4 Reúso de la memoria 205

Tabla 5.2 Formas de fragmentación de la memoria

Forma de
fragmentación Descripción
Fragmentación externa Algún área de la memoria es demasiado pequeña para ser asignada.
Fragmentación interna Se asigna más memoria que la solicitada por un proceso. Por tanto, algo de
la memoria asignada permanece sin utilizarse.

La fragmentación de la memoria da por resultado su utilización deficiente. En esta sección


y en el resto del capítulo se analizarán varias técnicas para evitar o minimizar la fragmentación
de la memoria.

Fusión de áreas libres

La fragmentación externa puede encontrarse fusionando áreas libres para formar áreas de este
tipo más grandes. La fusión puede intentarse cada vez que un área se agrega a la lista libre. Un
método sencillo sería buscar la lista libre para comprobar si cualquier área que se adjunta a la
nueva ya está en la lista libre. En caso afirmativo, puede eliminarse de la lista libre, fusionarse
con la nueva área y ésta puede agregarse a la lista. Sin embargo, tal método es costoso porque
implica la búsqueda de la lista libre cada vez que a ésta se considera agregar una nueva área.
A continuación se describen dos técnicas genéricas que realizan la fusión de manera más efi-
caz. En la sección 5.4.1 se aborda un asignador de memoria que utiliza una técnica de fusión
especial.

Etiquetas de frontera Una etiqueta es un descriptor de estado para un área de memo-


ria. Consta de un par ordenado (estado de asignación, tamaño). Por cada área de memoria se
usan dos etiquetas que contienen información idéntica. Éstas se almacenan al inicio y al final
del área, es decir, en los primeros y en los últimos bytes del área. Así, toda área asignada o
libre de la memoria contiene etiquetas cerca de sus fronteras. Si un área es libre, entonces el
apuntador de la lista libre sigue la etiqueta en su frontera inicial. Este arreglo se muestra en la
figura 5.9.
Cuando un área se convierte en libre, se comprueban sus etiquetas de frontera de sus áreas
vecinas. Éstas se encuentran fácilmente porque preceden inmediatamente a las fronteras de la
nueva área liberada. Si cualesquiera de los vecinos está libre, se fusiona con esta nueva área. En
la figura 5.10 se muestran las tres posibilidades que hay en la fusión. Si sólo el vecino izquierdo
está libre, la nueva área liberada se fusiona con él. Luego, las etiquetas de frontera se establecen
para la nueva área. El vecino izquierdo ya existía en la lista libre (consulte la figura 5.10b)), de
modo que basta simplemente cambiar el tamaño de su campo. Si sólo el vecino derecho está
libre, la nueva área liberada se fusiona con él y las etiquetas de frontera se establecen para el
área fusionada. Después, es necesario modificar la lista libre a fin de eliminar el elemento para
el vecino derecho y agregar un elemento para el área fusionada (consulte la figura 5.20c)). Si
ambos vecinos están libres, la nueva área liberada se fusiona con ellos para formar una sola
área libre. El campo de tamaño del elemento del vecino izquierdo en la lista libre se modifica
para reflejar la fusión. El vecino derecho también posee un elemento en la lista libre. Ésta se

06 MAQ. CAP. 05(F0694).indd 205 8/10/07 12:59:44 AM


206 CAPÍTULO 5 Administración de la memoria

etiqueta de frontera etiqueta de frontera


del vecino del vecino
área asignada/libre

apuntador de
la lista libre estado de estado de
asignación tamaño asignación tamaño
etiqueta de etiqueta de
frontera frontera
Figura 5.9 Etiquetas de frontera y apuntador del área libre.

modifica para simplemente eliminar este elemento (consulte la figura 5.10d)). Mantener la lista
libre como una lista doblemente ligada debe permitir que esta operación se lleve a cabo de
manera eficaz.

a) Encabezado 30 F
30 40 40 40 40 20
F O X O O Y O F
20 45
F O Z 45
O F
30 30
F
de la lista libre

70 70 40 40 20 20 45
b) F F O Y O F F O Z 45
O F
30 30
F

30 30 40 40 60 60 45
c) F F O X O F F O Z 45
O F
30 30
F

d) 30 30 40 40 40 40 95 95
F F O X O O Y O F F

Valores de las banderas de estado: O: ocupado, F: libre


Figura 5.10 Fusión usando etiquetas: a) lista libre, b)-d ) liberación de las áreas X, Y y Z.

Una relación denominada regla del cincuenta por ciento se cumple cuando se utiliza este
método de fusión. Si se libera un área de la memoria, el número total de áreas libres en el sistema
aumenta en 1, disminuye en 1 o permanece igual, dependiendo de si los vecinos del área que se
está liberando son cero áreas libres, dos áreas libres o un área libre. Estas áreas se muestran como
las áreas tipo C, B y A, respectivamente, a continuación:

A B C B A B B A

Cuando se realiza una asignación, el número de áreas libres se reduce en 1 si el tamaño


solicitado es igual al de alguna otra área; en caso contrario, permanece sin cambio, ya que el

06 MAQ. CAP. 05(F0694).indd 206 8/10/07 12:59:44 AM


5.4 Reúso de la memoria 207

área de memoria restante debe regresar a la lista libre. El segundo caso es mucho más probable
que el primero. Suponiendo una gran memoria de modo que sea posible ignorar la situación en
ambos extremos de la memoria, y suponiendo que cada área tiene la misma probabilidad de ser
liberada, se tiene

Número de áreas asignadas, n  #A  #B  #C


Número de áreas libres, m  12- (2  #A  #B)

donde #A es el número de áreas libres del tipo A, etc. En el estado estable #A  #C, de modo que
m  12- n. Esta relación se denomina regla del cincuenta por ciento.
La regla del cincuenta por ciento es de utilidad para la estimación del tamaño de la lista libre
y del esfuerzo implicado en un método de asignación como el del mejor ajuste, que requiere el
procesamiento de toda la lista libre. También constituye un método para estimar el área libre en
la memoria en cualquier instante. Si sf es el tamaño promedio de las áreas libres de la memoria,
entonces la memoria libre total es sf  n-2 .

Compactación de memoria En este método, las uniones de la memoria se cambian de


modo que todas las áreas libres puedan fusionarse para formar una sola área libre. Como sugiere
su denominación, esto se logra “compactando” todas las áreas asignadas hacia un extremo de la
memoria. En la figura 5.11 se ilustra el uso de la compactación para fusionar áreas libres.

a) Encabezado a b c d e
de la lista libre

b) a b c d e

Figura 5.11 Compactación de memoria.

La compactación es más importante de lo que se sugiere en este análisis porque implica el


movimiento de códigos y datos en la memoria. Si el área b en la figura 5.11 contiene un proceso,
éste requiere ser relocalizado para su ejecución correcta desde la nueva área de memoria. Esto
implicaría la modificación de direcciones del operando en sus instrucciones. Si el sistema de
cómputo cuenta con un registro de relocalización, ésta puede lograrse simplemente cambiando
la dirección en el registro de relocalización (consulte la sección 5.3). En caso contrario, la relo-
calización debe ejecutarse a través de medios del software. Esto no es práctico porque todas las
direcciones usadas por un proceso, incluidas las direcciones de datos asignados a un montículo y
las direcciones contenidas en registros CPU, tendrían que ser modificadas. Así, la compactación
sólo se lleva a cabo si el sistema de cómputo cuenta con un registro de relocalización o con un
arreglo equivalente.

5.4.1 Sistema acompañante y asignadores de potencias de 2

El sistema acompañante y los asignadores de potencias de 2 realizan la asignación de la me-


moria en bloques de unos cuantos tamaños estándar: el tamaño de cada bloque de la memoria
es una potencia de 2. Esta restricción reduce el esfuerzo implicado en la asignación y fusión de

06 MAQ. CAP. 05(F0694).indd 207 8/10/07 12:59:45 AM


208 CAPÍTULO 5 Administración de la memoria

bloques, y da por resultado asignación y retiro de asignación rápidas. Sin embargo, conduce a
fragmentación interna, a menos que un proceso solicite un área de la memoria cuyo tamaño sea
una potencia de dos.

Asignador de sistema acompañante Un sistema acompañante separa y recombina un


bloque de la memoria de manera predeterminada durante la asignación y el retiro de asignación.
Los bloques creados mediante la separación de un bloque se denominan bloques acompañantes.
Bloques acompañantes libres se fusionan a fin de formar el bloque que fue separado para crear-
los. Esta operación se denomina coalescencia. Bajo este sistema, al adjuntar bloques libres que
no son acompañantes se obtienen bloques acompañantes que no son coalescentes. El sistema
acompañante binario, que se describe aquí, separa un bloque en dos bloques acompañantes del
mismo tamaño. Así, cada bloque b cuenta con un solo bloque acompañante que precede o sucede
a b en la memoria. Los tamaños de los bloques de la memoria son 2n para valores diferentes
de n  t, donde t es algún valor de umbral. Esta restricción asegura que el tamaño de los blo-
ques de la memoria no sea insignificante.
El asignador de sistema acompañante asocia una etiqueta de 1 bit a cada bloque para in-
dicar si el bloque está asignado o libre. La etiqueta de un bloque puede localizarse en éste o
puede estar almacenada por separado. El asignador mantiene muchas listas de bloques libres;
cada una se mantiene como una lista doblemente ligada y consta de bloques libres del mismo
tamaño; es decir, bloques de tamaño 2k para alguna k  t. La operación del asignador empieza
con un solo bloque libre de memoria de tamaño 2z para alguna z  t. Es ingresado en la lista li-
bre para bloques de tamaño 2z. Las acciones siguientes se realizan cuando un proceso solicita
un bloque de memoria de tamaño m. El sistema encuentra la menor potencia de 2 que es  m,
tal que ésta sea igual a 2i. Si la lista de bloques de tamaño 2i no está vacía, asigna el primer
bloque de la lista al proceso y cambia la etiqueta del bloque, de libre a asignado. Si está vacía,
comprueba la lista de bloques de tamaño 2i1. Entonces, saca un bloque de esta lista y lo separa
en dos bloques de tamaño 2i. Estos bloques se vuelven acompañantes. Pone uno de sus bloques en
la lista libre de los bloques de tamaño 2i y usa el otro para satisfacer la solicitud. En caso de
que no haya disponible ningún bloque de tamaño 2i1, busca en la lista bloques de tamaño 2i2.
Después de la separación, uno de ellos debe colocarse en la lista libre de los bloques de tamaño
2i1 y el otro debe separarse aún más para su asignación según se describió antes. En caso de
que no haya disponible ningún bloque de tamaño 2i2, busca en la lista bloques de tamaño 2i3,
y así sucesivamente. Por tanto, antes de poder satisfacer una solicitud puede necesitarse llevar a
cabo varias separaciones.
Cuando un proceso libera un bloque de memoria de tamaño 2i, el sistema acompañante
cambia la etiqueta del bloque a libre y comprueba la etiqueta de su bloque acompañante para ver
si los bloques acompañantes también son libres. En caso de serlo, fusiona estos dos bloques en
uno solo de tamaño 2i1. Luego repite la comprobación de coalescencia en forma transitiva, es
decir, comprueba si el acompañante de este nuevo bloque de tamaño 2i1 es libre, y así sucesi-
vamente. Ingresa un bloque en una lista libre sólo cuando encuentra que su bloque acompañante
no es libre.
Ejemplo 5.5 En la figura 5.12 se ilustra la operación de un sistema acompañante binario. Los in-
cisos a) y b) de la figura muestran el estado del sistema antes y después de que el bloque marcado
con el símbolo de flecha hacia abajo ‘⇓’ es liberado por un proceso. Para facilitar las cosas, en cada
parte se muestran dos vistas del sistema. La mitad superior muestra la lista libre, mientras que en la
inferior se observa la disposición de la memoria. Bloques correspondientes en las dos mitades están
identificados con los mismos números a fin de hacer más fácil la referencia. El tamaño del bloque

06 MAQ. CAP. 05(F0694).indd 208 8/10/07 12:59:45 AM


5.4 Reúso de la memoria 209

tamaño encabezado tamaño encabezado


del de la bloques de del de la bloques de
bloque lista libre memoria libre bloque lista libre memoria libre
16 1 16 −

32 2 32 −

64 − 64 4

128 128
3 3

Disposición de
la memoria
1⇓ 2 3 4 3

Disposición de los
bloques acompañantes
1
2
4
3 3
a) b)
Figura 5.12 Operación del sistema acompañante cuando se libera un bloque.

que se está liberando es igual a 16 bytes. Su acompañante es el bloque libre identificado con el
número 1 en la figura 5.12a); de esta manera, el asignador de sistema acompañante fusiona estos dos
bloques para formar uno nuevo. El acompañante de éste es el bloque 2; entonces el nuevo bloque y
el bloque 2 son fusionados para formar un nuevo bloque cuyo tamaño es 64 bytes. Este bloque libre
está identificado con el número 4 en la figura 5.12b). Luego se ingresa en la lista libre idónea.

La comprobación de la etiqueta de un acompañante puede hacerse de manera eficaz


porque los tamaños de los bloques son potencias de 2. Considere que el tamaño del bloque que
se está liberando es igual a 16 bytes. Debido a que 16 es 24, su dirección es de la forma ...y0000,
donde después de y hay cuatro ceros, y y es 0 o 1. La dirección de su bloque acompañante es
...z0000, donde z  1 y. Esta dirección puede obtenerse simplemente llevando a cabo una ope-
ración o una excluyente con un número ...10000; es decir, con 24. Por ejemplo, si la dirección de
un bloque es 101010000, entonces la dirección de su acompañante es 101000000. En general, la
dirección del acompañante de un bloque de tamaño 2n bytes puede encontrarse realizando una
excluyente o con 2n.

Asignador de potencias de 2 Como en el sistema acompañante, los tamaños de los bloques


de la memoria son potencias de 2, y listas libres por separado son mantenidas por bloques de
tamaños distintos. Sin embargo, aquí termina la semejanza con el sistema acompañante. Cada

06 MAQ. CAP. 05(F0694).indd 209 8/10/07 12:59:45 AM


210 CAPÍTULO 5 Administración de la memoria

bloque contiene un encabezado o título que se utiliza para dos cosas. Contiene una bandera de
estado para indicar si actualmente el bloque está asignado o libre. Si un bloque está libre, otro
campo en el encabezado contiene el tamaño del bloque. Si está asignado, el otro campo en el
encabezado contiene la dirección de la lista libre a la que debe agregarse el bloque una vez que
esté libre (consulte la figura 5.13).

estado tamaño/dirección
libre o tamaño del bloque o
asignado dirección en la lista libre

Figura 5.13 Elemento del encabezado en el asignador de potencias de 2.

Cuando se hace una solicitud por n bytes, el asignador encuentra el menor bloque libre que
es suficientemente grande para contener n bytes. Primero comprueba la lista libre que contiene
bloques cuyo tamaño es el valor más pequeño de x tal que 2x  n. Si esta lista libre se encuentra
vacía, comprueba la lista que contiene bloques cuyo tamaño es la siguiente potencia de 2, y así
sucesivamente. A una solicitud se asigna todo un bloque; es decir, no se lleva a cabo ninguna
separación de bloques. Tampoco se hace ningún esfuerzo para alinear bloques adjuntos a fin de
formar bloques más grandes; una vez liberado, un bloque simplemente regresa a la lista libre.
La operación del sistema empieza con la formación de bloques del tamaño deseado que son
ingresados en las listas libres idóneas. Nuevos bloques pueden crearse dinámicamente siempre
que el asignador se quede sin bloques de un tamaño dado, o cuando no sea posible asignar algún
bloque a una solicitud.

Comparación de asignadores de memoria Los asignadores de memoria pueden compa-


rarse con base en la velocidad de asignación y en el uso eficaz de la memoria. Los asignadores de
sistema acompañante y de potencias de 2 son superiores a los asignadores del primer ajuste,
del mejor ajuste y del siguiente ajuste en términos de la velocidad de asignación porque evitan
búsquedas en las listas libres. El asignador de potencias de 2 es más rápido que el asignador de
sistema acompañante porque no requiere ejecutar separaciones ni fusiones.
La utilización de la memoria puede compararse al calcular un factor de utilización de la
memoria como se muestra a continuación
memoria en uso
Factor de utilización de la memoria  
memoria total comprometida
donde memoria en uso es la cantidad de memoria en uso por procesos con solicitudes, y memoria
total comprometida incluye la memoria asignada, la memoria libre que existe con el asignador
de memoria y la memoria ocupada por sus propias estructuras de datos. El mayor valor del fac-
tor de utilización representa el mejor desempeño de caso de un sistema, y el menor valor repre-
senta el peor desempeño de caso. Puede verse que los asignadores de sistema acompañante y de
potencias de 2 no se comportan muy bien en términos del factor de utilización porque asignan
bloques cuyos tamaños son potencias de 2. Se obtiene fragmentación interna a menos que las
solicitudes de memoria correspondan a los tamaños de los bloques. Estos asignadores también
usan adición de memoria para almacenar los encabezados de las listas. El asignador de sistema
acompañante también requiere memoria para almacenar etiquetas.

06 MAQ. CAP. 05(F0694).indd 210 8/10/07 12:59:46 AM


5.5 Asignación de memoria contigua 211

Un asignador de potencias de 2 fracasa en satisfacer una solicitud en caso de que no exista


un bloque libre suficientemente grande. Debido a que no fusiona bloques libres en bloques más
grandes, esto puede ocurrir incluso cuando bloques libres contiguos de menor tamaño hayan
podido ser combinados para satisfacer la solicitud. En un sistema acompañante esto ocurrirá sólo
si bloques libres contiguos no son acompañantes. Esto es raro en la práctica. De hecho, Knuth
(1973) reporta que en estudios de simulación un asignador de sistema acompañante fue capaz de
alcanzar 95 por ciento de utilización de la memoria antes de fracasar en dar satisfacción a una
solicitud.
Los asignadores de potencias de 2 poseen otra desventaja. Mientras el tamaño del bloque
sea una potencia de 2, el elemento del encabezado no puede ser usado por un proceso al que esté
asignado el bloque. Así, la porción útil de un bloque es algo más pequeña que una potencia de 2.
Si una solicitud de memoria es destinada para un área que sea exactamente una potencia de 2, este
método utiliza hasta por lo menos dos veces esa cantidad de memoria. Los asignadores que usan
las técnicas del primer ajuste o del mejor ajuste proporcionan una mejor utilización de la memoria
porque no se desperdicia ninguna parte de un bloque asignado. Sin embargo, los asignadores del
primer ajuste, del mejor ajuste o del siguiente ajuste sufren de fragmentación externa porque los
bloques libres pueden ser demasiado pequeños para satisfacer cualquier solicitud.

5.5 ASIGNACIÓN DE MEMORIA CONTIGUA

La asignación de memoria contigua es el modelo clásico de asignación de memoria en el que


cada proceso es asignado en una sola área contigua en la memoria. En los primeros sistemas
de computadoras, la decisión de asignación de memoria se realizaba estadísticamente, es decir,
antes de que empezara la ejecución de un proceso. El SO determinaba la memoria requerida para
ejecutar un proceso y asignaba suficiente memoria.
Algunas cuestiones prácticas en la asignación de memoria contigua son las siguientes:

1. Protección de la memoria.
2. Relocalización estática y dinámica de un programa que se va a ejecutar desde el área de
memoria que se le ha asignado.
3. Medidas para evitar fragmentación de la memoria.

De lo anterior, la protección de la memoria y la relocalización estática ya se analizaron en las


secciones 5.3.4 y 5.3.3. En esta sección la atención se centrará en técnicas prácticas de asigna-
ción de memoria contigua que abordan el problema de fragmentación de la memoria.

5.5.1 Manejo de la fragmentación de la memoria

En la fragmentación de la memoria hay dos aspectos.

• La fragmentación externa, que surge cuando las áreas de memoria libres que existen en un
sistema son demasiado pequeñas para ser asignadas a procesos. El kernel está al tanto de
la fragmentación externa y puede ser capaz de emprender algunas acciones para aliviarla.
• La fragmentación interna, que existe cuando la memoria asignada a un proceso no es
completamente utilizada por éste. Ésta se presenta si el kernel asigna un área de la me-
moria de tamaño estándar a un proceso, independientemente de su solicitud.

06 MAQ. CAP. 05(F0694).indd 211 8/10/07 12:59:46 AM


212 CAPÍTULO 5 Administración de la memoria

Se analizan dos técnicas utilizadas para superar el problema de fragmentación externa-compac-


tación de memoria y reúso de fragmentos de memoria.

Compactación de memoria El kernel puede realizar periódicamente compactación de me-


moria para eliminar fragmentación externa. Esta acción produce una sola área sin usar en la
memoria, que puede ser suficientemente grande para albergar uno o más procesos nuevos, inclu-
so en casos en que áreas libres individuales antes de la compactación sean muy pequeñas para
este propósito. La compactación de memoria se ilustra en el ejemplo 5.6.

Ejemplo 5.6 En la memoria existen los procesos A, B, C y D (consulte la figura 5.14a)). Cuando
B termina, hay dos áreas de memoria libres; sin embargo, ninguna es suficientemente grande para
dar cupo a otros procesos (consulte la figura 5.14b)). El kernel lleva a cabo compactación para crear
una sola área e iniciar el proceso E en esta área (consulte la figura 5.14c)).

Kernel Kernel Kernel


A A A
2M
B C
3M
C C D

D D E

a) b) c)

Figura 5.14 Compactación de memoria.

La compactación implica el movimiento de procesos en la memoria durante su ejecución.


Esta acción supone una relocalización dinámica de un programa. Puede lograrse de manera bas-
tante simple en sistemas de computadora que cuentan con un registro de relocalización (consulte
la sección 5.3.3). Considere el proceso C de la figura 5.14a). Si la dirección inicial supuesta de
este programa era 0, entonces el registro de relocalización debe contener la dirección 3 M bytes
cuando C esté en ejecución. Durante la compactación, C se mueve hacia el área de la memoria
con dirección inicial 2 M bytes. A fin de implementar esta relocalización dinámica, el registro de
relocalización debe cargarse con la dirección 2 M siempre que el programa C se programe como
en la figura 5.14c). La relocalización dinámica no es práctica si el sistema de cómputo no cuenta
con un registro de relocalización. En tales casos, el kernel debe recurrir al reúso de áreas de
memoria libres.

Reúso de áreas de memoria El reúso de áreas de memoria libres evita la sobrecarga de


relocalización del programa y no requiere prestaciones especiales de hardware como un registro
de relocalización. Sin embargo, puede provocar retrasos en el inicio de la ejecución de los pro-
gramas. En el ejemplo 5.6, la asignación de memoria mediante el reúso podría retrasar el inicio
del proceso E hasta que la memoria contenga un área libre suficientemente grande para dar cupo
al proceso.

06 MAQ. CAP. 05(F0694).indd 212 8/10/07 12:59:46 AM


5.6 Asignación de memoria no contigua 213

5.5.2 Intercambio

En la sección 2.6.3 se describieron la motivación y el mecanismo básico del intercambio. Un


sistema de tiempo compartido intercambia un proceso que no se encuentra en el estado de fun-
cionamiento a fin de hacer espacio para otro proceso. Mientras intercambia el proceso, su código
y espacio de datos se escriben en un área de intercambio en el disco. El proceso de intercambio
se devuelve a la memoria antes de que esté listo para reanudar su ejecución.
Una cuestión fundamental mientras se intercambia un proceso es la siguiente: ¿el proceso
debe ser asignado a la misma área de memoria que ocupaba antes de ser intercambiado? En
caso afirmativo, su intercambio depende del intercambio de algún otro proceso que entre tanto
hubiera podido ser asignado a esa área de la memoria. La capacidad de colocar el proceso inter-
cambiado en cualquier otro sitio en la memoria será de utilidad, aunque requiere relocalización
del proceso que se va a ejecutar desde una nueva área de la memoria. Como se mencionó en la
sección 5.5.1, sólo los sistemas de computadoras que cuentan con un registro de relocalización
pueden lograr fácilmente lo anterior.

5.6 ASIGNACIÓN DE MEMORIA NO CONTIGUA

En el modelo de asignación de memoria no contigua, varias áreas de memoria no adyacentes son


asignadas a un proceso. Ninguna de éstas es suficientemente grande para admitirlo todo, por lo
que una parte del proceso (incluidos sus datos y su pila) es cargado en cada una de estas áreas.
Cada una de estas partes se denomina componente de un proceso.
El modelo de asignación de memoria no contigua proporciona otras dos ventajas importan-
tes. Un área de memoria que no es suficientemente grande para llevar a cabo un proceso comple-
to aún puede ser utilizada, de modo que resulta menos fragmentación externa. (De hecho, como
se analizará más tarde, cuando se utiliza paginamiento, no ocurre fragmentación externa.) Esta
característica reduce la fragmentación externa y mejora la utilización de la memoria; en conse-
cuencia, puede ser innecesario llevar a cabo fusión de áreas de memoria libres o compactación.
Este modelo se ilustra en el ejemplo 5.7.

Ejemplo 5.7 En la memoria hay cuatro áreas de memoria no asignadas de 50 K, 30 K, 80 K y 60 K


bytes, como se muestra en la figura 5.15a). Se iniciará un proceso P de tamaño 140 K bytes. El pro-
ceso se separa en tres componentes denominadas P-1, P-2 y P-3 que se cargan en tres de las áreas
libres como sigue (consulte la figura 5.15b)):

componente del proceso tamaño dirección inicial de la memoria


P-1 50 K 100 K
P-2 30 K 300 K
P-3 60 K 450 K

Para facilitar las cosas, se supone que 1 K es igual a 1 000 bytes. Entonces existen dos áreas de
memoria libres de tamaños 20 K y 60 K bytes después de la componente P-3 y del proceso D, res-
pectivamente. Estas áreas pueden utilizarse para iniciar otro proceso de tamaño  80 K bytes.

No basta cargar un proceso en áreas de memoria no contigua: debe poder ejecutarse correc-
tamente. El programa del proceso P del ejemplo 5.7 hubiera sido compilado y ligado asumiendo
el modelo clásico de asignación de memoria contigua (consulte la figura 5.4). Así, ¿cómo puede

06 MAQ. CAP. 05(F0694).indd 213 8/10/07 12:59:46 AM


214 CAPÍTULO 5 Administración de la memoria

Memoria Memoria
Kernel Kernel
100 K 100 K
50 K P-1
F F
300 K 300 K
30 K 307 488 P-2
450 K
C Proceso P 450 K
C
80 K 0K P-3
xyz 20 K
D 51 488 D
600 K 40 K 600 K 40 K
140 K
a) b) c)

Figura 5.15 Carga no contigua del proceso P.

ejecutarse cuando se lleva a cabo asignación de memoria no contigua? Esta cuestión se analizará
usando el concepto de organización lógica y física.

Organización lógica y física En la sección 1.1 se mencionó que la vista abstracta de una
entidad se denomina vista lógica, y que el arreglo y relación entre las componentes de la entidad
es llamada organización lógica. La vista real de una entidad se denomina vista física y el arreglo
representado en ella es llamado organización física. En la figura 5.15 se ilustran las vistas lógica
y física del proceso P del ejemplo 5.7. En la vista lógica, P es una entidad contigua con el inicio
de la dirección 0 K. En la vista física, P está realmente cargado en 3 áreas no adyacentes con las
direcciones iniciales 100 K, 300 K y 450 K bytes, respectivamente.

Ejemplo 5.8 En el ejemplo 5.7, el espacio de direcciones lógicas de P va de 0 a 140 K, mientras


el de direcciones físicas va de 0 K a 640 K. El área de datos xyz en el programa del proceso P tiene
la dirección 51 488 (consulte la figura 5.15b)). Ésta es la dirección lógica de xyz. La componente
P-1 del proceso en la figura 5.15 tiene un tamaño de 50 K bytes; es decir, 51 200 bytes, de modo
que xyz está situado en la componente P-2 en un desplazamiento de 288 bytes. Debido a que P-2
está cargada en el área de memoria con la dirección inicial 300 K bytes; es decir, 307 200 bytes, la
dirección física de xyz es 307 488 (consulte la figura 5.15c)).

El esquema de la figura 5.16 muestra cómo el CPU obtiene la dirección física que corres-
ponde a una dirección lógica. El kernel almacena en una tabla información sobre las áreas de la
memoria asignadas al proceso P, que pone a disposición de la unidad de administración de
la memoria (MMU). En el ejemplo 5.7, esta información consistirá de los tamaños y las direc-
ciones iniciales de la memoria de P-1, P-2 y P-3. El CPU envía a la MMU la dirección lógica
de cada dato o instrucción utilizados en el proceso, y la MMU utiliza la información de asigna-
ción de memoria almacenada en la tabla para calcular la dirección física correspondiente. Esta
dirección se denomina dirección de memoria efectiva de los datos o de la instrucción. El pro-
cedimiento para calcular la dirección de memoria efectiva desde una dirección lógica es llamado
traducción de la dirección.

Direcciones lógicas, direcciones físicas y traducción de la dirección Una dirección ló-


gica es la dirección de una instrucción o bytes de datos según se utilizan en un proceso. (Esta

06 MAQ. CAP. 05(F0694).indd 214 8/10/07 12:59:47 AM


5.6 Asignación de memoria no contigua 215

Memoria Información de
asignación
Área del de memoria
kernel de P
Instrucción que
está ejecutándose
Unidad de
administración
de la memoria
(MMU) Áreas de memoria asignadas
al proceso P

Figura 5.16 Esquema de traducción de la dirección en asignación de memoria no contigua.

dirección puede obtenerse utilizando un índice, una base o registros de segmentos.) El conjunto
de direcciones lógicas usadas por un proceso constituyen el espacio de direcciones lógicas del
proceso. Una dirección física es la dirección de memoria efectiva de una instrucción o bytes
de datos. El conjunto de direcciones físicas en el sistema constituye el espacio de direccio-
nes físicas del sistema.
Se considera que una dirección lógica consta de dos partes: la identificación de la compo-
nente del proceso que contiene la dirección y la identificación del byte dentro de la componente.
Cada dirección se representa por un par de la forma

(compi, bytei).

Con la siguiente fórmula, la MMU calcula las direcciones donde un byte (compi, bytei) existe en
la memoria.

Dirección de memoria efectiva de (compi, bytei)


 dirección inicial del área de la memoria asignada a compi (5.1)
 compensación de bytei dentro de compi

Para facilitar la traducción de la dirección por la MMU, al programar al proceso P el kernel


proporciona a la primera la información de asignación de memoria concerniente al proceso P. En
el ejemplo 5.7, esta información consistirá en los tamaños y direcciones iniciales de la memoria
de P-1, P-2 y P-3.

Implementación de la asignación de memoria no contigua Para lograr esto se utilizan


dos métodos:

• Paginamiento.
• Segmentación.
En el paginamiento, cada proceso consta de componentes de tamaño fijo denominadas
páginas. El tamaño de una página se especifica en la arquitectura del sistema de cómputo. La

06 MAQ. CAP. 05(F0694).indd 215 8/10/07 12:59:47 AM


216 CAPÍTULO 5 Administración de la memoria

memoria puede alojar un número entero de páginas. La asignación de memoria se lleva a cabo
con una página como unidad: un área de la memoria cuyo tamaño es el mismo que el de la página
al que se asigna. Debido a que todas las páginas son del mismo tamaño, ningún área de memo-
ria no asignada puede ser más pequeña que el tamaño de una página. En consecuencia, en el
sistema no se presenta fragmentación externa.
En la segmentación, un programador identifica en un proceso componentes denominadas
segmentos. Un segmento es una entidad lógica en un programa, por ejemplo, una función, una
estructura de datos o un objeto. Este arreglo facilita la compartición de un código, de datos y
de módulos del programa. Los segmentos pueden ser de distintos tamaños, de modo que la
administración de la memoria es engorrosa y es posible que haya fragmentación externa.
El paginamiento y la segmentación se analizan en las secciones 5.7 y 5.8, respectivamente.

Protección de la memoria Ningún área de la memoria asignada a un proceso requiere ser


protegida contra la interferencia de otros procesos. Esto puede lograrse usando los esquemas
de protección de la memoria descritos en la sección 5.3.4. Con una modificación irrelevante,
puede usarse el esquema basado en las llaves de protección de la memoria: siempre que una
componente de un proceso esté cargada en un área de la memoria, la llave de protección de
todos los bloques en esa área de la memoria deben establecerse en la APK del proceso. Mientras
ejecuta el proceso, el CPU debe detectar una violación de protección de la memoria si la APK del
proceso no corresponde a la llave de protección de un byte de memoria al que accede.
La utilización del esquema de registros acotados para protección de la memoria requiere un
arreglo elaborado. El esquema debe aplicarse de manera individual para cada área de la memoria
asignada a un proceso, de modo que es complementado por la MMU. Mientras lleva a cabo la
traducción de la dirección para una dirección lógica (compi, bytei), la MMU comprueba si compi
existe en el programa del proceso y si bytei existe en compi. Se presenta una interrupción por
violación de la protección si fracasa cualesquiera de estas comprobaciones. En paginamiento es
posible simplificar la verificación de límites porque una dirección lógica tiene justamente los
bits necesarios para alojar la compensación del último byte en una página. Así, no es necesario
comprobar si bytei existe en compi.
El esquema de verificación de límites de protección de la memoria resulta atractivo porque
permite que los procesos tengan diferentes tipos de privilegios de acceso a una componente
compartida. Por ejemplo, un proceso puede contar con un privilegio de lectura a un segmento
de datos, mientras otro tiene un privilegio de lectura/escritura al segmento. Esta característica
es especialmente importante en segmentación porque cada segmento es una unidad lógica en un
programa.

5.6.1 Comparación de asignación de memoria contigua y no contigua

En la tabla 5.3 se resumen características clave de la asignación de memoria contigua y no con-


tigua. En la asignación de memoria contigua, una sola área de la memoria se asigna a un proceso
usando el método del primer ajuste, del mejor ajuste o del siguiente ajuste. En la asignación
de memoria no contigua, la asignación de memoria se realiza para cada parte de un proceso.
En paginamiento, todas las partes del proceso son del mismo tamaño, por lo que la memoria
puede partirse en áreas del mismo tamaño y utilizarse una estrategia de asignación basada en
recursos en común. Este método reduce la sobrecarga de asignación. También elimina la frag-
mentación externa de la memoria; sin embargo, en la última página de un proceso puede haber

06 MAQ. CAP. 05(F0694).indd 216 8/10/07 12:59:48 AM


5.7 Paginamiento 217

fragmentación interna. Los sistemas que utilizan segmentación comparten algunas desventajas
de asignación contigua. Los segmentos no son del mismo tamaño, por lo que no es posible evitar
fragmentación externa.
El intercambio es más eficaz en asignación de memoria no contigua porque la traducción de
la dirección permite la ejecución de un proceso intercambiado desde cualquier parte de la me-
moria. La protección también es más efectiva porque los procesos pueden tener diferentes tipos
de privilegios de acceso a una componente compartida.

Tabla 5.3 Comparación de asignación de memoria contigua y no contigua

Característica Asignación contigua Asignación no contigua


Sobrecarga No hay sobrecarga durante la ejecución La traducción de la dirección se lleva
de un programa. a cabo durante la ejecución de un pro-
grama.
Asignación Asigna una sola área de la memoria. Asigna varias áreas de la memoria: un
área de la memoria para cada compo-
nente de un proceso.
Reúso de En asignación particionada hay frag- En paginamiento: no hay fragmentación
la memoria mentación interna. Hay fragmentación externa, aunque sí hay interna. En seg-
externa en la asignación con el método mentación: hay fragmentación externa,
del primer ajuste, del mejor ajuste y del pero no hay interna.
siguiente ajuste.
Intercambio A menos que el sistema de cómputo En cualquier área de la memoria puede
cuente con un registro de relocalización, instalarse un proceso de intercambio.
es necesario colocar un proceso de in-
tercambio en su área asignada original-
mente.

5.7 PAGINAMIENTO
En un sistema en el que se utilice paginamiento, un proceso es considerado como una entidad
contigua que contiene instrucciones y datos. En la vista lógica, un proceso consta de un arre-
glo lineal de páginas. Cada una contiene s bytes, donde s es una potencia de 2. El valor de s se
especifica en la arquitectura del sistema de cómputo. Los procesos utilizan direcciones lógicas
numéricas. El hardware de la computadora descompone una dirección lógica en un par (pi, bi),
donde pi es el número de página y bi es un desplazamientoen pi, 0  bi  s. La vista física consta
de dos áreas de memoria no adyacentes asignadas a páginas del proceso.
En la figura 5.7 se ilustra el arreglo utilizado para ejecutar los procesos P y R en un sistema
que usa paginamiento. El tamaño de P es de 5 500 bytes. El de página es 1 K byte, de modo que
P tiene 6 páginas. Estas páginas están numeradas del 0 al 5 y los bytes en una página están nu-
merados de 0 a 1 023. La última página sólo contiene 380 bytes. Si un elemento de datos sample
tiene la dirección 5 248, entonces el hardware de la computadora ve esta dirección como el par
(5, 128). El proceso R tiene 3 páginas numeradas del 0 al 2.
El kernel parte la memoria en áreas denominadas marcos de página . Cada uno es del mismo
tamaño que la página; es decir, 1 K byte. En la figura 5.17, la computadora tiene una memoria de

06 MAQ. CAP. 05(F0694).indd 217 8/10/07 12:59:48 AM


218 CAPÍTULO 5 Administración de la memoria

Marco de
página #
0 0 1 Marco de
1 1 3
2 2 9 página #
3 3 6 0 0 0 4
4 4 7 1 1 2
5 5 8 2 2 5 Lista de
marcos libres
Proceso P Tabla de Proceso R Tabla de
página página
de P de R

Figura 5.17 Procesos en paginamiento.

10 K bytes, por lo que los marcos de página están numerados del 0 al 9. En cualquier momento,
algunos marcos de página se asignan a páginas del programa y otros quedan libres. El kernel
mantiene una lista denominada lista de marcos libres para notar las identificaciones de los mar-
cos de página libres. Por el momento, sólo el marco de página 4 es libre.
A la vez que carga el proceso P para su ejecución, el kernel consulta la tabla de marcos y
asigna un marco de página libre a cada página de los procesos. A fin de facilitar la traducción de
la dirección, se elabora una tabla de página (PT) para el proceso. Cada elemento de la tabla
de página indica el número de marco asignado a una página del proceso. Esta tabla está identi-
ficada con un número de página. Durante la ejecución del proceso, la MMU consulta la tabla de
página para realizar la traducción de la dirección.
En la figura 5.17, la tabla de marco indica que seis marcos de página están ocupados por
el proceso P, tres por un proceso R y uno está libre. La tabla de página P indica los números de
marco asignados a las páginas de P. La dirección lógica (5, 128) debe traducirse a la dirección
física 8 320 utilizando el elemento para la página 5 en la tabla de página.

Traducción de la dirección Se utiliza la siguiente notación:

s : Tamaño de una página


lt : Longitud de una dirección lógica (es decir, el número de bits que contiene)
lh : Longitud de una dirección física
nb : Número de bits necesarios para acceder al último byte de una página
np : Número de bits usados para alojar el número de página en una dirección lógica
nf : Número de bits usados para alojar el número de página en una dirección física

El tamaño de una página, s, es una potencia de 2; por ejemplo, s  2nb. Por tanto, los bits
menos significativos nb en una dirección lógica proporcionan bi. Los bits restantes en una direc-
ción lógica forman a pi. Los valores de pi y bi pueden obtenerse simplemente agrupando los bits
de una dirección lógica como sigue:

np nb
pi bi

donde np  ll  nb. El uso de una potencia de 2 como tamaño de página simplifica de manera
semejante la elaboración de la dirección de la memoria efectiva. Considere que a la página pi

06 MAQ. CAP. 05(F0694).indd 218 8/10/07 12:59:49 AM


5.8 Segmentación 219

se ha asignado el marco de página qi. Debido a que el tamaño de las páginas y el de los marcos
de página es el mismo, también se requieren nb bits para direccionar los bytes en un marco de
página. Sea n f  l p  n b. La dirección física del byte “0” del marco de página qi es

nf nb
qi 0 0

Por tanto, la dirección física del byte bi en el marco de página qi está dada por

nf nb
qi bi

La MMU puede obtener esta dirección simplemente al concatenar qi y bi a fin de obtener un


número de bit lh. La traducción de la dirección se ilustra en el ejemplo 5.9.

Ejemplo 5.9 Un sistema de cómputo utiliza direcciones lógicas de 32 bits y un tamaño de página
de 4 K bytes. Para direccionar los bytes en una página bastan 12 bits. Así, los 20 bits de orden su-
perior en una dirección lógica representan a pi y los 12 bits de orden inferior representan a bi. Para
un tamaño de memoria de 256 M bytes, lp  28. De esta forma, los 16 bits de orden superior en una
dirección física representan a qi. Si la página 130 se encuentra en el marco de página 48, entonces
pi  130 y qi  48. Si bi  600, las direcciones lógica y física se ven como:

Dirección lógica Dirección física


20 12 16 12
0 010000010 001001011000 0 00110000 001001011000

Durante la traducción de la dirección, la MMU obtiene a pi y bi simplemente agrupando los bits


como se mostró antes. Luego se accede al elemento número 130 de la tabla de página para obtener
qi, que es igual a 48. Este número se concatena con bi para formar la dirección física.

5.8 SEGMENTACIÓN

Un segmento es una entidad lógica en un programa; por ejemplo, una función, una estructura
de datos o un objeto. Por tanto, resulta importante administrar un segmento como si fuese una
unidad: cargarlo en la memoria para su ejecución o compartirlo con otros programas. En la vis-
ta lógica, un proceso consta de un conjunto de segmentos. La vista física consta de áreas no
adyacentes de memoria asignadas a segmentos.
Un proceso Q consta de cuatro unidades lógicas con los nombres simbólicos main, databa-
se, search y retrieve. Mientras codifica el programa, el programador declara estas unidades
lógicas como segmentos en Q. El compilador/ensamblador genera direcciones lógicas mientras
traduce el programa. Cada dirección lógica utilizada en Q tiene la forma (si, bi), donde si y bi
son las identificaciones de un segmento y un byte dentro de un segmento. Por ejemplo, la
instrucción correspondiente a una declaración call get_sample, donde get_sample es un
procedimiento en el segmento retrieve, puede utilizar la dirección de operando (retrieve,
get_sample), o usar una representación numérica para si y bi.

06 MAQ. CAP. 05(F0694).indd 219 8/10/07 12:59:49 AM


220 CAPÍTULO 5 Administración de la memoria

principal
actualizar
búsqueda Nombre Tamaño Dirección
main 476 23500
database 20240 32012
base de datos search 378 76248
pila update 642 91376
stack 500 54500
Tabla de segmento de Q
Proceso Q

Figura 5.18 Un proceso Q en segmentación.

En la figura 5.18 se muestra la forma en que el kernel maneja al proceso Q. La mitad iz-
quierda de la figura muestra la vista lógica del proceso Q. A fin de facilitar la traducción de la
dirección, el kernel elabora una tabla de segmento para Q. Cada elemento en esta tabla muestra
el tamaño de un segmento de Q y direcciones del área de la memoria que se le han asignado.
La MMU utiliza la tabla de segmento para llevar a cabo la traducción de la dirección. Los
segmentos no tienen tamaños estándares, de modo que no es aplicable la simplificación de la
concatenación de bits usada en el paginamiento. En consecuencia, el cálculo de la dirección
de la memoria efectiva implica la adición de bi a la dirección inicial de si, según la ecuación (5.1),
por lo que la traducción de la dirección es más lenta que el paginamento. En la figura 5.18, si
get_sample tiene la compensación 232 en el segmento retrieve, entonces la traducción de la
dirección de (retrieve, get_sample) debe producir la dirección 91376  232  91608.
La asignación de memoria para cada segmento se lleva a cabo como en el modelo de asigna-
ción de memoria no contigua. El kernel mantiene una lista libre de áreas de la memoria. Mientras
carga un proceso, busca en esta lista para realizar asignación del primer ajuste o del mejor ajuste
a cada segmento del proceso. Una vez que termina un proceso, las áreas de la memoria asigna-
das a sus segmentos se agregan a la lista libre. Hay fragmentación externa porque el tamaño de
los segmentos varía.
La tarea de escribir cada dirección lógica en la forma (si, bi) se realiza mediante un com-
pilador o ensamblador. Mientras compila una referencia a un símbolo xyz, debe decidir a qué
segmento pertenece xyz.

5.9 SEGMENTACIÓN CON PAGINAMIENTO

En este método, cada segmento en un programa se pagina por separado. En consecuencia, a cada
segmento se asigna un número entero de páginas. Este método simplifica y acelera la asigna-
ción de memoria, y también evita la fragmentación externa. Para cada segmento se elabora una
tabla de página, y en el elemento del segmento en la tabla de segmentos se mantiene un apunta-
dor hacia la tabla de página. Luego, la traducción de la dirección para una dirección lógica (si, bi)
se realiza en dos etapas. En la primera, el elemento de si se localiza en la tabla de segmentos, y se
obtiene la dirección de su tabla de página. Luego, el número de byte bi se separa en un par (psi,
bpi), donde psi es el número de página en el segmento si, y bpi es el número de byte en la página

06 MAQ. CAP. 05(F0694).indd 220 8/10/07 12:59:49 AM


5.10 Asignación de memoria por el kernel 221

pi. Después, el cálculo de la dirección efectiva se termina como en paginamiento; es decir, se ob-
tiene el número de marco de psi y bpi se concatena con éste para obtener la dirección efectiva.

principal Dirección
actualizar de la tabla
búsqueda Nombre Tamaño de página
main 476
database 20240
base de datos search 378
pila update 642
stack 500
Tabla de segmento de Q
Proceso Q

Figura 5.19 Un proceso Q en segmentación y paginamiento.

En la figura 5.19 se muestra el proceso Q de la figura 5.18 en un sistema que utiliza seg-
mentación con paginamiento. Cada segmento se pagina de forma independiente, por lo que en
la última página de cada segmento hay fragmentación interna. Entonces, cada elemento de la
tabla de segmentos contiene un apuntador hacia la tabla de página del segmento. El campo
de tamaño en un elemento del segmento se utiliza para facilitar una comprobación de límites
para protección de la memoria.

5.10 ASIGNACIÓN DE MEMORIA POR EL KERNEL

Durante su operación, el kernel crea y destruye muchas estructuras de datos, que casi siempre
son bloques de control que se utilizan para controlar la asignación y uso de los recursos del
sistema. Algunos ejemplos de bloques de control son: el bloque de control de procesos (PCB)
creado para todo proceso, el bloque de control de eventos (ECB) creado siempre que se anticipa
la ocurrencia de un evento, el bloque de control de E/S (IOCB) creado para una operación de E/S
y el bloque de control de archivos (FCB) creado para todo archivo abierto. El tiempo de memo-
ria y de CPU utilizado por el kernel constituyen sobrecarga. Por tanto, la creación y la destruc-
ción de estructuras de datos llevadas a cabo por el kernel deben ser rápidas, y éste también debe
utilizar eficazmente la memoria.
Las duraciones de las estructuras de datos del kernel están ligadas a las duraciones de en-
tidades relacionadas, como los procesos, o actividades relacionadas, como operaciones de E/S,
por lo que no tienen ninguna relación pronosticable entre sí. Esta característica excluye el uso
de la pila del kernel para crear tales estructuras de datos. El kernel debe utilizar un montículo.
Los tamaños de los bloques de control se conocen mientras se diseña el SO. El kernel utiliza
esta característica para hacer que la asignación de memoria sea sencilla y eficaz: la memoria
liberada cuando se destruye un bloque de control puede asignarse para crear un bloque de con-
trol semejante en el futuro. Para cada tipo de bloque de control puede preservarse una lista libre
por separado a fin de obtener esta ventaja.

06 MAQ. CAP. 05(F0694).indd 221 8/10/07 12:59:50 AM


222 CAPÍTULO 5 Administración de la memoria

Asignadores de memoria de kernel en Unix y Solaris


Unix y Solaris utilizan asignación de memoria no contigua con paginación, de modo que los
asignadores de memoria usan un número entero de páginas y realizan esfuerzos especiales para
utilizar eficazmente cada página. En esta sección se analizarán tres asignadores de memoria de
kernel:

• asignador McKusick-Karels,
• asignador acompañante perezoso y
• asignador de losa

Los asignadores McKusick-Karels y acompañante perezoso asignan áreas de memoria cuyo


tamaño es una potencia de 2. Estos asignadores, y otros de potencias de 2, enfrentan un pro-
blema peculiar relacionado con el desempeño del caché. Una vez que se accede a un objeto, se
carga en el caché del procesador. Aparece un problema de desempeño porque a algunas partes
del objeto se accede más frecuentemente que a otras. Debido al alineamiento de las direccio-
nes a lo largo de una frontera que es una potencia de 2, las partes de los objetos a las que se acce-
de con frecuencia son mapeadas en las mismas áreas que el caché. Por tanto, algunas partes del
caché se enfrentan a bastante disputa, mientras otras no. Esta torcida disputa del caché hace que
tenga un desempeño deficiente. El asignador de losa utiliza una técnica interesante para evitar
este problema en el desempeño del caché.
A continuación se describen estos tres asignadores. En aras de la consistencia con análisis
previos, aquí se utiliza una terminología ligeramente distinta a la que se usa en la literatura en la
que se abordan estos asignadores.

Asignador McKusick-Karels Este asignador modificado de potencias de 2 se utiliza en


Unix 4.4 BSD. El asignador utiliza un número entero de páginas. El principio de operación
básico consiste en dividir cada página en bloques del mismo tamaño y almacenar la infor-
mación de tamaño contra la dirección lógica de una página. Este principio ayuda a eliminar
el elemento del encabezado que se utiliza en los asignadores de potencias de 2 para alma-
cenar el tamaño de un bloque o la dirección de una lista libre (consulte la figura 5.13). Esto
puede explicarse como sigue: debido a que todos los bloques en una página son del mismo
tamaño, el de un bloque puede encontrarse al determinar la dirección de la página en la que
está localizado. Así, no es necesario almacenar el tamaño en cada bloque libre. Mientras se
libera un bloque, la lista libre a la que debe agregarse el bloque también puede encontrarse
al determinar la dirección de la página en la que está localizado. Por tanto, la dirección de la
lista libre no necesita ser almacenada en cada bloque asignado. Como una consecuencia de
la eliminación del elemento del encabezado, la asignación es superior a la de los asignado-
res de potencias de 2 cuando una solicitud de memoria es para un área cuyo tamaño es una
potencia exacta de 2. Un bloque del mismo tamaño puede ser asignado para satisfacer la
solicitud, mientras un asignador de potencias de 2 hubiera asignado un bloque cuyo tamaño
es la siguiente potencia de 2.
El asignador solicita una página libre cuando no encuentra un bloque del tamaño que está
buscando. Esta página se divide en bloques del tamaño deseado. Uno de éstos se asigna al pro-
ceso que ha hecho la solicitud actual y los bloques restantes se ingresan en la lista libre idónea.
En caso de que no exista una página libre con el asignador, solicita al sistema de paginamiento

06 MAQ. CAP. 05(F0694).indd 222 8/10/07 12:59:50 AM


5.10 Asignación de memoria por el kernel 223

una nueva página a la cual asignarlo. Para asegurar que no consuma un mayor número de pági-
nas que el necesario, el asignador marca una página como libre cuando todos los bloques de las
páginas están libres.
El asignador McKusick-Karels logra un factor de utilización de la memoria superior al de
los asignadores de potencias de 2 porque el elemento del encabezado no está almacenado en cada
bloque. Sin embargo, a diferencia del sistema acompañante, no alinea bloques libres adyacentes.
En vez de lo anterior, marca una página como libre cuando todos los bloques en la página se
vuelven libres. También carece de la característica de devolver páginas libres al sistema de pagi-
namiento. Así, el número total de páginas asignadas al asignador es el mayor número de páginas
que ha utilizado en cualquier instante de su duración. Esta característica puede conducir a un
bajo factor de utilización de la memoria.

Asignador acompañante perezoso El sistema acompañante puede realizar una o más


separaciones en cada asignación y una o más acciones de coalescencia en cada liberación.
Algunas de estas acciones pueden ser innecesarias porque un bloque alineado puede separarse
en el futuro. El principio de diseño básico del asignador acompañante perezoso es retrasar las
acciones de coalescencia siempre que es posible. Esto se hace con la expectativa de que en el
futuro pueda crearse una estructura de datos que requiera la misma cantidad de memoria que
el bloque liberado. Un bloque de esta naturaleza puede asignarse sin separación; por tanto,
retrasar la decisión de alinear bloques puede evitar la sobrecarga de separación en ciertas
condiciones.
El asignador acompañante perezoso utilizado en Unix 5.4 trabaja como sigue: se considera
que los bloques de control del mismo tamaño constituyen una clase de bloques. Las decisiones
de coalescencia para una clase se toman con base en las razones por las que las estructuras de
datos de la clase se crean y destruyen. El asignador caracteriza el comportamiento del SO con
respecto a una clase de bloques en tres estados denominados perezoso, recuperable y acelerado.
Para facilitar las cosas, lo anterior se denomina estados de una clase de bloques.
En el estado perezoso, las asignaciones y liberaciones de los bloques de una clase ocu-
rren con frecuencias coincidentes. Por tanto, los bloques libres alineados pueden separarse
pronto. Tanto la coalescencia como la separación pueden evitarse retrasando la primera.
En el estado recuperable, las liberaciones ocurren a un ritmo más rápido que la asignación,
de modo que es una buena idea llevar a cabo coalescencia en cada liberación. En el estado
acelerado, las liberaciones ocurren más rápido que las asignaciones, por lo que es conve-
niente fusionar a un ritmo más rápido. El asignador debe intentar fusionar un bloque que está
siendo liberado y, además, también debe intentar hacerlo con otros bloques que ya han sido
liberados.
El asignador acompañante perezoso mantiene la lista libre como una lista doblemente liga-
da. De esta forma, es posible acceder al inicio y al final de la lista casi con la misma facilidad.
Se mantiene un mapa de bits para indicar el estado de asignación de los bloques. En el estado
perezoso, el asignador no lleva a cabo ninguna coalescencia. Un bloque que está siendo libera-
do simplemente se agrega a la cabeza de la lista libre. Se dice que este bloque está localmente
libre. Ya que se encuentra al principio de la lista, este bloque es asignado antes que cualquier otro
en la lista. Su asignación es eficaz y rápida porque no es necesario actualizar el mapa de bits: éste
sigue señalando que el bloque está asignado.
En los estados recuperable y acelerado, un bloque es agregado a la lista libre y marcado
como libre en el mapa de bits. Se dice que este bloque está globalmente libre. Los bloques

06 MAQ. CAP. 05(F0694).indd 223 8/10/07 12:59:50 AM


224 CAPÍTULO 5 Administración de la memoria

globalmente libres se agregan al final de la lista libre. En el estado recuperable, el asignador in-
tenta fusionar de modo transitivo un bloque globalmente libre con su acompañante. Por último,
un bloque es agregado a alguna lista libre: a una lista libre a la que hubiera pertenecido el bloque
que está siendo liberado o a la que contiene bloques de mayor tamaño. Observe que el blo-
que que se está agregando a una lista libre podrá ser un bloque local o globalmente libre, de-
pendiendo del estado del SO con respecto a esa clase de bloques. En el estado acelerado, el
asignador intenta fusionar el bloque que está siendo liberado, igual que en el estado recuperable.
Además, también intenta fusionar otro bloque localmente libre —el bloque que se encontraba al
inicio de la lista libre— con su acompañante.
El estado de una clase de bloques se caracteriza como sigue: sean A, L y G el número de
bloques asignados, el número de bloques localmente libres y el número de bloques globalmente
libres, de manera respectiva. El número total de bloques de una clase está dado por N  A  L
 G. Un parámetro denominado slack se calcula como sigue:

slack  N  2  L  G

Se dice que una clase está en el estado perezoso, recuperable o acelerado si el valor de slack es
 2, 1 o 0, respectivamente. (El asignador asegura que slack nunca es 0.) La sobrecarga de
coalescencia es distinta en estos tres estados. En el estado perezoso no hay sobrecarga. Por
tanto, la asignación y liberación de bloques debe hacerse rápido y los procesos deben experi-
mentar retrasos mínimos en su operación debido a la asignación y liberación de estructuras de
datos. En el estado recuperable, la sobrecarga debe ser comparable a la del sistema acompañante,
mientras en el estado acelerado debe ser más pesada que en el sistema acompañante. Se ha de-
mostrado que retrasos promedio al usar el asignador acompañante perezoso son de 10 a 32 por
ciento más bajos que en el caso del asignador acompañante.
La implementación del algoritmo del acompañante perezoso en Unix 5.4 utiliza dos tipos
de bloques. El tamaño de los bloques pequeños varía entre 8 y 256 bytes. El de los bloques
grandes, entre 512 y 16 K bytes. El asignador obtiene memoria del sistema de paginamiento en
términos de áreas de 4 K bytes. Alguna parte del área se usa para mantener el mapa de bits de
los bloques en esa área. De manera colectiva, los bloques en el área se denominan recursos en
común. Cuando todos los bloques en los recursos en común están libres, los recursos en común
regresan al sistema archivador. Así se supera la desventaja observada en el caso del asignador
McKusick-Karels.

Asignador de losa El asignador de losa del sistema Solaris 2.4 posee dos características
especiales:

• Utiliza objetos inicializados, lo que mejora la eficacia de reúso del objeto.


• La asignación de memoria está dirigida a obtener mejor comportamiento del caché.

Cada objeto es una estructura de datos del kernel. El asignador de losa asigna todos los
objetos juntos del kernel de la misma clase a los recursos en común. Para objetos pequeños,
los recursos en común constan de muchas losas, donde cada una contiene muchos objetos. (Aquí
no se estudiará el caso de objetos grandes.) Una losa se organiza en un área de tamaño estándar

06 MAQ. CAP. 05(F0694).indd 224 8/10/07 12:59:51 AM


5.10 Asignación de memoria por el kernel 225

asignada por el sistema de paginamiento. Es posible crear una nueva losa mediante la obtención
de un área de memoria adicional del sistema de paginamiento, y una losa sin utilizar puede de-
volverse al sistema de paginamiento. Las losas en los recursos en común se ingresan en una lista
doblemente ligada para facilitar la adición y la eliminación de losas. Una losa puede estar llena,
parcialmente vacía o vacía, dependiendo del número de objetos activos existentes ahí.
Para facilitar las búsquedas para una losa vacía, la lista doblemente ligada que contiene
las losas en los recursos en común se clasifica según el estado de una losa: todas las losas llenas
están al principio de la lista; las parcialmente vacías están a la mitad y las vacías, al final. Cada
losa contiene una lista libre desde la cual es posible asignar objetos vacíos. Cada uno de los
recursos en común contiene un apuntador dirigido hacia la primera losa que contiene un objeto
vacío. Este arreglo hace eficaz la asignación. Cuando un asignador se queda sin objetos vacíos
de un tipo, obtiene un área adicional del sistema de paginamiento, construye una nueva losa y la
introduce en la lista doblemente ligada de losas.

área de área sin


coloreado utilizar
objetos descriptor

libre activa libre libre activa

apuntadores a la lista libre

Figura 5.20 Formato de una losa.

Una losa contiene objetos de un solo tipo. En la figura 5.20 se muestra el formato de una.
Cuando el asignador obtiene un área de memoria del sistema de paginamiento, forma una losa
mediante el formateo del área a fin de que contenga un número entero de objetos, una lista libre
que contenga a todos los objetos y un campo descriptor que contiene la cuenta de los objetos
activos y el encabezado de la lista libre. Cada objeto es inicializado. Esta acción implica la ini-
cialización de diferentes campos en el objeto para información específica de éste, como cadenas
fijas de valores constantes. Una vez asignado, el objeto puede utilizarse de manera directa. En
el momento del retiro de la asignación, el objeto regresa al estado en que se encontraba cuando
estaba asignado. Debido a que algunos campos del objeto jamás cambian, o lo hacen de tal forma
que sus valores en el momento del retiro de la asignación son los mismos que sus valores en el
momento de la asignación, este método elimina sobrecarga repetitiva de formación de objetos
experimentada por otros asignadores. Sin embargo, el uso de objetos inicializados tiene algunas
implicaciones para el factor de utilización de la memoria. Cada objeto debe tener asociado un
apuntador de campo, que se usa para ingresarlo en la lista libre. Debido a que un objeto está
inicializado, este campo indicador existe de manera externa a aquél, incluso cuando el objeto es
libre (consulte la figura 5.20).
El asignador de losa proporciona un comportamiento mejorado del caché al evitar el pro-
blema de desempeño del caché que enfrentan los asignadores de potencias de 2 y sus variantes,
descritos al inicio de esta sección. Cada losa contiene en su inicio un área reservada denominada

06 MAQ. CAP. 05(F0694).indd 225 8/10/07 12:59:51 AM


226 CAPÍTULO 5 Administración de la memoria

área de coloreado (consulte la figura 5.20). El asignador hace diferente el tamaño de esta área
de coloreado en losas distintas en los recursos en común. En consecuencia, los objetos en los
mismos recursos en común poseen alineaciones distintas con respecto a los múltiplos más pró-
ximos de una potencia de 2. Esta característica se utiliza para asegurar que estos objetos sean
mapeados en áreas diferentes del caché del procesador, evitando así excesiva disputa del caché
y mejorando el desempeño de éste.
El asignador también brinda un mejor factor de utilización de memoria porque asigna úni-
camente la memoria requerida para cada objeto. No obstante, a diferencia de los asignadores
McKusick-Karels y acompañante perezoso, no existe fragmentación interna por objeto; sola-
mente existe fragmentación externa en la forma del área sin usar de cada fragmento. Se ha des-
cubierto que la fragmentación representa sólo el 14 por ciento del asignador de losa, contra el 45
o 46 por ciento en los asignadores McKusick-Karels y acompañante perezoso, respectivamente.
El promedio de los tiempos de asignación también son mejores que en otros asignadores.

5.11 REPASO DE RELOCALIZACIÓN, LIGAMIENTO


Y FORMAS DEL PROGRAMA
Un programa P escrito en algún lenguaje de programación L experimenta varias transformacio-
nes antes de ser ejecutado. La figura 5.21 contiene un esquema de estas transformaciones. El pro-
grama P es traducido por un traductor para L (que puede ser un compilador o un ensamblador)
para producir una forma de programa denominada módulo objeto. El módulo objeto contiene
las instrucciones y los datos de P, así como información requerida para su relocalización y liga-
miento. El ligador procesa el módulo objeto de P para obtener una forma de programa lista para
ejecutar, llamada programa binario. Si P utiliza algunas funciones estándar, entonces el ligador
incluye sus módulos objeto desde una biblioteca. Almacena el programa binario generado en una
biblioteca. El cargador lo carga en el área de memoria asignada a P, lo prepara para su ejecución
en esta área de la memoria y pasa el control para su ejecución.

Biblioteca
Datos

Programa Programa
fuente Traductor Ligador Cargador Resultados
binario

Módulos Programas Flujo de datos


objeto binarios Flujo del control

Figura 5.21 Esquema de la ejecución de un programa.

Direcciones traducidas, ligadas y tiempo de carga El origen de un programa es la direc-


ción inicial del área de la memoria donde se espera ejecutarlo. Mientras compila un programa,
a un traductor se le proporciona una especificación de origen (en caso contrario, asume un valor
predeterminado, que suele ser 0). Esto se denomina origen traducido del programa. El traduc-
tor utiliza el valor del origen traducido para asignar direcciones a sus instrucciones y datos. Lo

06 MAQ. CAP. 05(F0694).indd 226 8/10/07 12:59:51 AM


5.11 Repaso de relocalización, ligamiento y formas del programa 227

anterior se denomina direcciones del tiempo de traducción. La dirección inicial de ejecución,


o simplemente la dirección inicial de un programa, es la dirección de la instrucción con que
empieza su ejecución. La dirección inicial asignada por el traductor es la dirección inicial tra-
ducida del programa. Todo objeto módulo contiene el origen traducido y la dirección inicial
traducida de un programa, y utiliza sus direcciones de tiempo de traducción.
Puede ser necesario tener que cambiar el origen de un programa por medio del ligador o
del cargador. Muchos objetos módulo pueden usar el mismo origen y las mismas direcciones de
tiempo de traducción. Cuando tales módulos objeto deben incluirse en el mismo programa bi-
nario, surgen conflictos de dirección. Para resolverlos, el ligador cambia el origen especificado
en algunos módulos objeto. El origen del programa binario generado por el ligador se denomina
su origen ligado. La dirección del área de la memoria donde se va a cargar un programa binario
para su ejecución se denomina su origen de carga. El cargador debe modificar el origen de un
programa si el origen ligado de éste es diferente de su origen de carga. Un cambio de origen
conduce a cambios en la dirección inicial de ejecución y en las direcciones asignadas a las ins-
trucciones y a los datos.
En esta sección se analizarán diferentes formas de un programa, sus propiedades, su pro-
cesamiento mediante el ligador y el cargador, y las ventajas de usarlos en un sistema operativo.
Para ilustrar los conceptos de relocalización y ligamiento se utilizan programas escritos en un
lenguaje ensamblador hipotéticamente sencillo.

Un lenguaje ensamblador sencillo Una declaración en lenguaje ensamblador tiene el si-


guiente formato:

[Label] <Opcode> <operand spec>,<operand spec>

El primer operando siempre es un registro CPU: AREG, BREG, CREG o DREG. El segundo
operando se refiere a un byte de la memoria que usa un nombre simbólico. Códigos de opera-
ciones (opcode) autoexplicativos, como ADD y MULT, se usan para designar operaciones arit-
méticas. La instrucción MOVER mueve un valor del operando de la memoria al operando del
registro mientras la instrucción MOVEM hace lo opuesto. Todas las operaciones aritméticas
se llevan a cabo en un registro y establecen un código de condición. Éste puede probarse
mediante una instrucción Branch on Condition (BC). La declaración ensambladora correspon-
diente tiene el formato

BC condition code spec>, <memory address

donde condition code spec es una cadena de caracteres cuyo significado es evidente; por
ejemplo, GT, EQ, etc. La instrucción BC transfiere el control a la instrucción con dirección me-
mory address si el valor actual del código de condición equivale a condition code spec. Para
facilitar las cosas, todas las direcciones y constantes están en decimal, y todas las instrucciones
ocupan 4 bytes. El opcode, el operando de registro y el operando de memoria de una instruc-
ción ocupan 2, 1 y 3 dígitos, respectivamente. El signo no forma parte de ninguna instrucción.

5.11.1 Relocalización

En la figura 5.22 se muestra el programa P, un programa ensamblador y su código generado.


La declaración STAR 500 indica que el origen traducido del programa debe ser 500. Por con-

06 MAQ. CAP. 05(F0694).indd 227 8/10/07 12:59:52 AM


228 CAPÍTULO 5 Administración de la memoria

siguiente, la dirección del tiempo de traducción de LOOP es 504. La dirección de A es 540. Las
instrucciones en bytes cuyas direcciones son 532 y 500 utilizan estas direcciones para referirse
a LOOP y A, respectivamente. Estas direcciones dependen de manera evidente del origen del
programa. Las instrucciones que usan estas direcciones se denominan instrucciones sensibles a
la dirección. Un programa que contiene instrucciones sensibles a la dirección puede ejecutarse
correctamente sólo si se carga en un área de la memoria cuya dirección inicial coincida con el
origen del programa. Para poderlo ejecutar desde otras áreas de la memoria, las direcciones en
instrucciones sensibles a la dirección deben modificarse según sea necesario. Este proceso se
denomina relocalización del programa.

Declaración Dirección Código


START 500
ENTRY TOTAL
EXTRN MAX, ALPHA
READ A 500) + 09 0 540
LOOP 501)

MOVER AREG, ALPHA 518) + 04 1 000


BC ANY, MAX 519) + 06 6 000

BC LT, LOOP 538) + 06 1 501


STOP 539) + 00 0 000
A DS 1 540)
TOTAL DS 1 541)
END

Figura 5.22 Programa ensamblador P y su código generado.

Si origen ligado
origen traducido, entonces el ligador debe llevar a cabo relocalización.
Si origen cargado
origen ligado, entonces el cargador debe llevar a cabo relocalización. En
general, un ligador siempre lleva a cabo relocalización, mientras algunos cargadores no. Un car-
gador es un cargador absoluto si no es capaz de manejar la situación origen cargado
origen
ligado. La relocalización requiere el conocimiento de los orígenes traducido y de origen, así
como información sobre instrucciones sensibles a la dirección. En el ejemplo 5.10 se ilustra la
relocalización de P.

Ejemplo 5.10 El origen traducido del programa P en la figura 5.22 es 500. La dirección del tiempo
de traducción del símbolo A es 540. La instrucción correspondiente a la declaración READ A es una
instrucción sensible a la dirección. Si el origen ligado es 900, A tendrá la dirección del tiempo de
ligamiento 940, por lo que la dirección en la instrucción READ debe corregirse a 940. De manera
semejante, la instrucción en el byte 532 de la memoria traducida contiene 504, la dirección de
LOOP, que debe corregirse a 901. (Observe que las direcciones de operando en las instrucciones con
direcciones 516 y 520 también deben “corregirse”. Éste es un caso de ligamiento, que se analizará
en la sección 5.11.2.)

5.11.2 Ligamiento
Las declaraciones MOVER y BC en el programa P utilizan los operandos ALPHA y MAX (consulte
la figura 5.22). Éstos son bytes de datos e instrucciones localizados en otro programa o en un

06 MAQ. CAP. 05(F0694).indd 228 8/10/07 12:59:52 AM


5.11 Repaso de relocalización, ligamiento y formas del programa 229

módulo de biblioteca. El ligador obtiene sus direcciones y las coloca en las instrucciones corres-
pondientes a las declaraciones MOVER y BC. El ligamiento es el proceso por el cual se une una
referencia externa con la dirección del tiempo de ligamiento correcta.
Una definición pública es un símbolo definido en una unidad de traducción a la que pueda
hacerse referencia en otras unidades de traducción. Una referencia externa es una referencia a un
símbolo que no está definido en la unidad de traducción. Las declaraciones ENTRY y EXTRN en
una lista de un programa ensamblador enumeran sus definiciones públicas y referencias externas,
respectivamente. El traductor coloca en un módulo objeto información sobre las declaraciones
ENTRY y EXTRN para su uso por el ligador. El ligamiento se ilustra en el ejemplo 5.11.

Ejemplo 5.11 En el programa P de la figura 5.22, la declaración ENTRY TOTAL indica que en el pro-
grama existe una definición pública de TOTAL. Observe que LOOP y A no son definiciones públicas,
aunque están definidas en el programa. La declaración EXTRN MAX, ALPHA indica que el programa
contiene referencias externas a MAX y ALPHA. El ensamblador no conoce la dirección de un símbolo
externo, por lo que escribe ceros en los campos de dirección de instrucciones en las que se usen
estos símbolos. Ahora considere el programa Q, descrito a continuación:

Declaración Dirección Código


START 200
ENTRY ALPHA
- -
ALPHA DS 25 232) + 00 0 025
END

El programa P contiene una referencia externa al símbolo ALPHA que es una definición pública en Q
con la dirección del tiempo de traducción 232. Sea 900 el origen ligado de P. Su tamaño es 42 bytes.
Por consiguiente, el origen ligado de Q es 942, y la dirección del tiempo de ligamiento de ALPHA
es 974. El ligamiento se lleva a cabo colocando la dirección del tiempo de ligamiento de ALPHA en
la instrucción de P que utiliza ALPHA; es decir, colocando la dirección 974 en la instrucción con
dirección del tiempo de traducción 516 en P.

Ligamiento estático y dinámico El ligador que se muestra en la figura 5.21 lleva a cabo
ligamiento estático utilizando el esquema que se ilustra en el ejemplo 5.11. Genera un programa
binario que no contiene ninguna referencia externa no resuelta. El ligamiento dinámico se realiza
cuando un programa binario contiene referencias no resueltas a símbolos externos y una de estas
referencias se encuentra durante la ejecución de un programa binario. Este tipo de ligamien-
to resuelve la referencia externa usando el esquema que se ilustra en el ejemplo 5.11.
El ligamiento dinámico se implementa usando el siguiente arreglo: si una referencia a un
símbolo externo va a resolverse dinámicamente, el ligador estático lo liga a un módulo estándar
cuyo sólo propósito es llamar al ligador dinámico para resolver la referencia externa. El ligador
dinámico es activado cuando tal referencia externa se encuentra durante la ejecución del pro-
grama. Este ligamiento busca bibliotecas de módulos objeto para localizar un módulo objeto
que contenga el símbolo requerido como una definición pública. El módulo objeto es ligado con
el programa binario utilizando el esquema que se ilustra en el ejemplo 5.11. Debido a que un
módulo objeto puede contener una referencia externa a un símbolo que es una definición pública
del programa binario, el ligador dinámico mantiene información sobre definiciones públicas a lo
largo de toda la ejecución de un programa binario.

06 MAQ. CAP. 05(F0694).indd 229 8/10/07 12:59:52 AM


230 CAPÍTULO 5 Administración de la memoria

El ligamiento dinámico posee las ventajas mencionadas en la sección 5.2. Sin embargo,
conduce a una complicación: el modelo de asignación de memoria de la figura 5.4 no es aplicable
porque las componentes de código y datos de un módulo ligado dinámicamente son memoria
asignada sólo después de que ha iniciado la ejecución de un programa. Para ese entonces, algunos
datos de programa controlados dinámicamente (datos PCD) ya deben haber sido asignados en el
montículo (consulte el ejemplo 5.12). Esta situación complica las acciones de administración
de montículos, especialmente el reúso de la memoria.

Código (A) Código (A) Código (A)


Datos estáticos (A) Datos estáticos (A) Datos estáticos (A)
Código (B)
Datos estáticos (B) Datos PCD (A) Datos PCD (A)
Código(C) Código (B)
Datos estáticos (C) Datos estáticos (B)
Datos PCD (B)
Datos PCD

Pila Pila Pila

a) b) c)

Figura 5.23 Ligamiento estático y ligamiento dinámico.

Ejemplo 5.12 Un programa consta de tres objetos módulo X, Y y Z. En la figura 5.23a) se ilustran
las componentes del programa en una memoria al inicio de la ejecución si se lleva a cabo ligamien-
to estático. En la figura 5.23b) se muestra esta situación usando ligamiento dinámico cuando está
en ejecución algún procedimiento del módulo X. En la figura 5.23c) se ilustra la situación cuando
un procedimiento del módulo X invoca un procedimiento del módulo Y. Luego, los datos PCD de
X y Y son separados por los datos de código y estáticos de Y.

5.11.3 Formas de programa para usar en sistemas operativos

Para que un SO ejecute un programa, éste debe tener tres características importantes:

• ¿Cuánta memoria requiere el programa?


• ¿Es posible ejecutarlo desde cualquier área de la memoria, o debe ejecutarse desde un
área específica de ésta?
• ¿El código del programa puede ser utilizado en forma simultánea por varios usuarios?

El tamaño de un programa y su capacidad de ejecución desde cualquier área de la memoria


son importantes para su tiempo de demora porque el programa puede ser ejecutado sólo cuan-
do existe disponible un área de la memoria suficientemente grande para dar cupo al programa.
Para ejecutar el programa en esa área de la memoria, el programa debe estar disponible como
un programa binario cuyo origen de carga coincide con la dirección inicial del área, o bien debe
ser relocalizado para satisfacer esta condición. La primera opción sería la mejor. Sin embargo,

06 MAQ. CAP. 05(F0694).indd 230 8/10/07 12:59:52 AM


5.11 Repaso de relocalización, ligamiento y formas del programa 231

implica que varias copias del programa, cada una con diferente origen de carga, deben estar
preparadas y almacenadas en un disco. Así, esta opción requiere que grandes áreas de disco sean
comprometidas a cada programa. La segunda opción evita este requerimiento, pero supone la
realización de ligamiento y carga cada vez que se ejecuta el programa. La capacidad de compar-
tición de un programa es importante si éste será utilizado por varios usuarios al mismo tiempo. Si
un programa no es compartible, entonces en la memoria debe haber varias copias del programa
al mismo tiempo.
Algunas de las consideraciones mencionadas no son importantes en sistemas de cómputo
que cuentan con grandes memorias virtuales. Sin embargo, es de utilidad conocer diversas for-
mas de programa y sus características analizadas aquí.

Tabla 5.4 Formas de programa utilizadas en sistemas operativos

Forma de programa Características


Módulo objeto Contiene instrucciones y datos de un programa e información para su reloca-
lización y ligamiento.
Programa binario Forma listo-para-ejecutar de un programa.
Programa ligado El ligamiento se realiza de manera perezosa; es decir, un módulo objeto que
dinámicamente define a un símbolo es ligado a un programa cuando se hace referencia a
ese símbolo durante su ejecución. Los módulos objeto que definen símbolos
usados en un programa, aunque no se haga ninguna referencia a ellos durante
una ejecución, no requieren ser ligados a ésta en absoluto.
Programa de El programa puede relocalizarse a sí mismo para su ejecución desde cual-
autoubicación quier área de la memoria.
Programa reentrante El programa puede ejecutarse de manera simultánea sobre varios conjuntos
de datos.

En la tabla 5.4 se resumen características de varias formas de programa. Un programa liga-


do de manera dinámica reduce potencialmente el requerimiento de memoria para un programa.
La estructura de capas ayuda a reducir el requerimiento de memoria para un programa. La for-
ma del programa de autoubicación elimina la necesidad de tener varias copias de un programa
en un disco, cada uno con origen de carga distinto. La forma del programa de autoubicación
no es importante cuando se utiliza asignación de memoria no contigua, y tanto los programas
con estructura de capas y los de autoubicación son innecesarios en un sistema de cómputo que
utiliza memoria virtual. La forma del programa reentrante evita la necesidad de tener varias
copias de él en la memoria.

5.11.3.1 Programas de autoubicación


Un programa de autoubicación lleva a cabo relocalización de sus propias instrucciones sensibles
a la dirección. En consecuencia, puede ser ejecutado desde cualquier área de la memoria. En un
programa de autoubicación se requieren las siguientes estipulaciones:
1. Debe conocer su origen traducido y su dirección inicial de ejecución, así como las direc-
ciones de sus instrucciones sensibles a la dirección.

06 MAQ. CAP. 05(F0694).indd 231 8/10/07 12:59:53 AM


232 CAPÍTULO 5 Administración de la memoria

2. Debe contar con una lógica de relocalización, es decir, un código para efectuar su propia
relocalización.
La dirección inicial de la lógica de relocalización se especifica como la dirección inicial
de ejecución del programa. Así, la lógica de relocalización gana control cuando el programa es
cargado para su ejecución, y utiliza la información en el punto 1 para efectuar su propia reloca-
lización. Por razones evidentes, la autoubicación es más rápida que la relocalización realizada
con un ligador.

5.11.3.2 Compartición de programas


Los programas pueden compartirse de manera tanto estática como dinámica. Considere dos pro-
gramas A y B que usan un programa común C. La compartición estática de C se realiza usando
ligamiento estático. Así, C está incluido tanto en A como en B y la identidad de C se pierde en
los programas binarios producidos por el ligador. Si los programas A y B se inician simultánea-
mente, entonces en la memoria hay dos copias de C (consulte la figura 5.24a)). Por tanto, la com-
partición estática de un programa es fácil de implementar, aunque desperdicia memoria durante
la ejecución de los programas que la comparten.

Programa Programa
C
A A

Programa
Programa B
C
B Programa
C
a) b)
Figura 5.24 Compartición de un programa: a) compartición estática, b) compartición dinámica.

La compartición dinámica implica que el código de un programa es compartido por otros


programas durante su ejecución. Se implementa utilizando ligamiento dinámico. Cuando el pro-
grama B necesita usar el programa C en un modo compartido, el SO lo liga a aquél. En la figura
5.24b) este hecho se representa al trazar una flecha de B a C. El SO también observa el hecho de
que el programa C se utilizará en el modo compartido. Cuando el programa A necesita usar el
programa C, el kernel comprueba si en la memoria ya existe una copia de C. Si éste es el caso,
el kernel liga la copia existente de C con A. Así, sólo existe una copia de C incluso cuando es
usado por más de un programa. La compartición dinámica ahorra memoria, aunque su imple-
mentación es complicada. El kernel debe mantener la pista de los programas compartidos en
la memoria y realizar ligamiento dinámico. El programa compartido debe codificarse como un
programa reentrante a fin de evitar interferencia mutua por los programas que lo comparten.

Programas reentrantes Cuando el programa C es compartido dinámicamente por los pro-


gramas A y B, los datos usados por C en representación de A deben protegerse de interferencia
por su ejecución en representación de B. Esto se logra asignando copias por separado del espacio
de datos de C para su uso por A y B. El truco consiste en asignar dinámicamente cada área de
datos y preservar su dirección en un registro CPU. Los contenidos de los registros CPU se guar-

06 MAQ. CAP. 05(F0694).indd 232 8/10/07 12:59:53 AM


Ejercicio 5 233

dan como parte del estado CPU cuando un programa es priorizado, y se devuelven a los registros
CPU cuando el programa es programado de nuevo. Estas acciones deben asegurar que diferentes
invocaciones de C no interfieran con los datos entre sí.

Datos (CB)

Datos (CA) Datos (CA)


Registro 1

C C C

a) b) c)
Figura 5.25 Programa reentrante: a) estructura del programa C, b)-c) invocaciones por A y B.

En la figura 5.25 se ilustra este arreglo. El programa C se codifica de modo que asuma que
el registro 1 apunte al inicio de su área de datos (consulte la figura 5.25a)). Es posible acceder
a los datos en esta área usando diferentes compensaciones de la dirección contenida en el regis-
tro 1. Cuando A llama a C, para esta invocación se asigna un área de datos. Esto se representa
como Datos (CA) (consulte la figura 5.25b)). El programa A puede asignar esta área como parte
de sus datos PCD y cargar su dirección en el registro 1 mientras llama a C. Alternativamente, C
mismo puede asignar esta área como el inicio de su ejecución en representación de A. Cuando
se prioriza la ejecución de A, el contenido del registro 1 debe almacenarse en los datos PCB de
A. Cuando C es llamado por B, un área de datos Datos (CB) se asigna de manera semejante y el
registro 1 se establece de modo que apunte al inicio de esta área (consulte la figura 5.25c)). Así,
la ejecución del programa A no interfiere con la ejecución del programa B.

EJERCICIO 5
1. Explique por qué los datos de un programa controlado dinámicamente (datos PCD) no pueden asignar-
se a una pila.
2. Un programa P contiene grandes arreglos cuyos límites de dimensión están especificados como cons-
tantes; por ejemplo, A(100000). Comente sobre la validez de la siguiente afirmación: “Los requeri-
mientos de memoria y los tiempos de ejecución de P deben ser idénticos sin tomar en cuenta si P utiliza
asignación estática de la memoria o asignación dinámica de la memoria.”
3. Dos versiones de un programa P, denominadas Ps y Pd se desarrollan usando asignación estática y
dinámica de la memoria, respectivamente. Cuando se hace un esfuerzo para ejecutar Ps, un SO envía
el mensaje “Memoria insuficiente: no es posible ejecutar el programa.” Sin embargo, el mismo SO
ejecuta el programa Pd sin ninguna dificultad. Explique por qué ocurre esto.
4. Un asignador worst fit siempre separa la mayor área de memoria libre mientras lleva a cabo una asig-
nación. Compare sus ventajas y desventajas con los asignadores del primer ajuste y del mejor ajuste.
5. Explique por qué las listas libres en un sistema acompañante están doblemente ligadas.
6. Una vez que se libera un bloque de memoria, un asignador de memoria hace un esfuerzo por fusionarlo
con uno o con sus dos vecinos. Comente sobre la validez de la siguiente afirmación en este contexto:
“Si se conocen los tamaños de bloques vecinos, es adecuado tener una etiqueta en sólo una frontera de

06 MAQ. CAP. 05(F0694).indd 233 8/10/07 12:59:53 AM


234 CAPÍTULO 5 Administración de la memoria

cada bloque; sin embargo, si no se conocen los tamaños de bloques vecinos, es esencial tener etiquetas
en ambas fronteras de cada bloque.”
7. Analice la fragmentación de la memoria en el sistema acompañante y los asignadores de potencias
de 2.
8. Las etiquetas de frontera se utilizan como etiquetas en un sistema acompañante. Analice la eficacia de
ejecución y la eficacia de utilización de la memoria de este método.
9. Las etiquetas en un sistema acompañante se almacenan en una tabla hash (tabla de búsqueda). Para
cada bloque libre con dirección a y tamaño s, en la tabla de búsqueda se almacena un par (a, s). Evalúe
la eficacia de este método.
10. A un asignador de sistema acompañante se asigna un área de 64 K bytes. Bloques de tamaño 2 K, 11 K,
120 bytes y 20 K son asignados en ese orden.
a) Muestre el estado de asignación y las listas libres del asignador. ¿Cuántas separaciones se realiza-
ron?
b) Muestre el estado de asignación y las listas libres del asignador después de que se libera el bloque
de 120 bytes. ¿Cuántas operaciones de coalescencia se realizaron?
11. a) Justifique la afirmación: “Cuando se libera un bloque en un sistema acompañante, el número de
bloques libres en el sistema puede aumentar en 1, permanecer sin cambio o puede disminuir en un
número entre 1 y n, inclusive, donde n depende de la memoria disponible en el sistema.”
b) Determine el valor de n si el tamaño mínimo de bloque en el sistema acompañante del problema 10
es 16 bytes.
12. Un sistema acompañante de Fibonacci utiliza bloques cuyos tamaños son múltiplos de los términos de
la serie de Fibonacci; por ejemplo, 16, 32, 48, 80, 128, ... Por tanto, el tamaño de un bloque es la suma
de los tamaños de los dos bloques inmediatos más pequeños.
Compare la eficacia de ejecución, la de la memoria y la del sistema acompañante de Fibonacci con el
sistema acompañante binario.
13. Un asignador de memoria trabaja como sigue: áreas de memoria pequeñas se asignan utilizan-
do un sistema acompañante. Áreas de memoria grandes se asignan utilizando una lista libre y un
asignador de primer ajuste. Comente sobre la eficacia y la utilización de la memoria obtenidas por
este asignador.
14. ¿La regla del cincuenta por ciento es válida para los siguientes asignadores?
a) Sistema acompañante.
b) Asignador de potencias de 2.
c) Asignador de losa.
15. El kernel de un SO recibe solicitudes para asignación de memoria a un ritmo elevado. Se ha en-
contrado que una gran fracción de solicitudes son para áreas de memoria de tamaño 100, 300 y 400
bytes (estos tamaños se denominan “estándares”). Otras solicitudes son para áreas de otros tamaños.
Diseñe un esquema de asignación de memoria en el que no se presente fragmentación mientras se
asignan áreas de tamaño estándar y no presente fragmentación interna mientras se asignan áreas de
otros tamaños.
16. Calcule el slack para cada clase de memoria intermedia (buffer) si se utiliza un asignador acompañante
perezoso en vez del asignador acompañante del problema 10.
17. Un asignador de potencias de 2 utiliza un tamaño de bloque mínimo de 16 bytes y un tamaño de bloque
máximo de 32 K bytes. Inicia su operación con por lo menos un bloque libre de cada tamaño. Compare
su operación con el sistema acompañante si procesa las mismas solicitudes que en el problema 10.
18. Comente sobre las siguientes afirmaciones:

06 MAQ. CAP. 05(F0694).indd 234 8/10/07 12:59:54 AM


Bibliografía 235

a) Los programas de autoubicación son menos eficaces que los programas relocalizables.
b) No habría necesidad de los asignadores si todos los programas se codifican como programas de
autoubicación.
19. Un programa de autoubicación necesita conocer su propia dirección de carga para usarla en la lógica
de relocalización. Un programa puede obtener su propia dirección de carga haciendo un novedoso
uso de la instrucción “branch to subroutine” (BSUB): esta instrucción transfiere el control a una
subrutina y carga la dirección de regreso en un registro CPU. El programa puede utilizar la dirección
de regreso para calcular su propia dirección de carga. Escriba un programa de autoubicación que use
esta técnica para determinar su propia dirección de carga.

BIBLIOGRAFÍA
Los ligadores y cargadores están descritos en la obra de Dhamdhere (1999).
Knuth (1973) es el punto de partida clásico para el estudio de administración de memoria contigua.
Hoare (1973) y Mckeag (1971) analizan varias técnicas de administración de la memoria. Randell (1969)
escribe un artículo pionero sobre la motivación de sistemas de memoria virtual. Denning (1970) describe
los fundamentos de los sistemas de memoria virtual.
Vahalia (1996) describe los distintos asignadores de memoria de kernel utilizados en sistemas Unix.
McKusick y Karels (1988) lo hacen con respecto el asignador de memoria McKusick-Karels. Lee y Barkley
(1989) describen el asignador acompañante perezoso. Estos dos asignadores se utilizan en Unix. Bonwick
(1994) y Bonwick y Adams (2001) describen el asignador de losa. Mauro y McDougall (2003) lo hacen en
relación con el uso del asignador de losa en Solaris, mientras Beck et al. (2002), y Bovet y Cesati (2003)
describen su implementación en Linux. El kernel de Windows utiliza varias políticas de asignación de
memoria para sus propios requerimientos de memoria. Implementa un sistema de asignación que semeja al
acompañante para bloques de tamaño mediano y asignación basada en montículos para bloques de tamaño
pequeño. Russinovich y Solomon (2005) describen asignación de memoria de kernel en Windows.

1. Beck, M., H. Bohme, M. Dziadzka, U. Kunitz, R. Magnus, C. Schroter y D. Verworner (2002):


Linux Kernel Programming, 3a. ed., Pearson Education.
2. Bonwick, J. (1994): “The slab allocator: An object-caching kernel memory allocator”, Procee-
dings of the Summer 1994 Usenix Technical Conference, 87-98.
3. Bonwick, J. y J. Adams (2001): “Extending the slab alloctor to many CPUs and arbitrary resour-
ces”, Proceedings of the 2001 Usenix Annual Technical Conference, 15-34.
4. Bovet, D.P. y M. Cesati (2003): Understanding the Linux Kernel, O’Reilly, Sebastopol.
5. Denning, P.J. (1970): “Virtual Memory”, Computing Surveys, 2 (3), 153-189.
6. Dhamdhere, D.M. (1999): Systems Programming and Operating Systems, 2a. ed. revisada, Tata
McGraw Hill, Nueva Delhi.
7. Hoare, C.A.R. y R.M. Mckeag (1971): “A survey of store management techniques”, en Operating
Systems Techniques, por C.A.R. Hoare y R.H. Perrott (eds.), Academic Press, Londres.
8. Knuth, D.E. (1973): The Art of Computer Programming, 2a. ed., vol. I: Fundamental Algorithms,
Addison-Wesley, Reading.
9. Kuck, D.J. y D.H. Lowrie (1970): “The use and performance of memory hierarchies”, en Software
Engineering, 1, J.T. Tou (ed.), Academic Press, Nueva York.
10. Lee, T.P. y R.E. Barkley (1989): “A watermark-based lazy buddy system for kernel memory allo-
cation”, Proceedings of the Summer 1989 USENIX Technical Conference, 1-13.

06 MAQ. CAP. 05(F0694).indd 235 8/10/07 12:59:54 AM


236 CAPÍTULO 5 Administración de la memoria

11. Mauro, J. y R. McDougall (2001): Solaris Internals—Core Kernel Architecture, Prentice-Hall.


12. McKusick, M.K. y M.J. Karels (1988): “Design of a general-purpose memory allocator for the 4.3
BSD Unix kernel”, Proceedings of the Summer 1988 USENIX Technical Conference, 295-303.
13. Peterson, J.L. y T.A. Norman (1977): “Buddy systems”, Communications of the ACM, 20 (6),
421-431.
14. Randell, B.(1969): “A note on storage fragmentation and program segmentation”, Communications
of the ACM, 12 (7), 365-369.
15. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.
16. Vahalia, U. (1996): Unix Internals—The New Frontiers, Prentice-Hall, Englewood Cliffs.

06 MAQ. CAP. 05(F0694).indd 236 8/10/07 12:59:54 AM


Capítulo
6
Memoria virtual

La memoria virtual es una ilusión de que un sistema de cómputo posee más memoria de la que
realmente tiene, lo que permite que un proceso sea independiente del tamaño de la memoria real
y que un gran número de procesos comparta un sistema de cómputo sin restringirse mutuamente.
La memoria virtual se implementa a través de la parte de la jerarquía de la memoria que consta
de una memoria y un disco: el código y los datos de un proceso se almacenan en un disco
y partes de aquéllos se cargan en la memoria cuando son necesarios durante la ejecución del
proceso. Utiliza el modelo de asignación de memoria no contigua y contiene componentes tanto
del hardware como del software.
El desempeño de la memoria virtual depende del ritmo al que deben cargarse las partes
de un proceso en la memoria desde un disco. El principio de localidad de referencia mantiene
la promesa de que este ritmo debe ser bajo si a un proceso se le asigna una cantidad idónea de
memoria. El aspecto práctico de la memoria virtual depende entonces del control de la cantidad
de memoria asignada a un proceso y de la decisión sobre qué partes de un proceso deben
preservarse en la memoria. Estas dos tareas las lleva a cabo la componente del software de la
memoria virtual.
Se empieza por analizar el principio de localidad de referencia y las técnicas que se utilizan
para decidir qué partes de un proceso deben preservarse en la memoria. Luego se abordan las
técnicas para controlar la cantidad de memoria asignada a un proceso. También se analizan las ca-
racterísticas del hardware para acelerar la operación de los procesos en la memoria virtual y para
auxiliar al software de la memoria virtual.

6.1 FUNDAMENTOS DE LA MEMORIA VIRTUAL

Los usuarios siempre quieren más de un sistema de cómputo: más recursos y más servicios. La
necesidad de más recursos se satisface obteniendo un uso más eficaz de los recursos o creando
la ilusión de que en el sistema hay más recursos. Una memoria virtual es lo que indica su nom-
bre: una ilusión de que en el sistema de cómputo hay una memoria más grande que la real, es
decir, que la RAM. Como se analizó en la sección 1.1, esta ilusión forma parte de una vista

07 MAQ. CAP. 06(F0694).indd 237 8/10/07 1:01:17 AM


238 CAPÍTULO 6 Memoria virtual

abstracta del usuario de la memoria. Así, un usuario o su proceso sólo ve la memoria virtual. El
kernel implementa la ilusión utilizando una combinación de medios de hardware y software. La
componente del software de la memoria virtual se denomina manejador de la memoria virtual.
La base de la memoria virtual es el modelo de asignación de memoria no contigua (consulte
la sección 5.6). Se supone que cada proceso consta de dos partes denominadas componentes del
proceso. Éstas pueden cargarse para su ejecución en áreas de memoria no adyacentes. La unidad
de administración de la memoria (MMU) traduce la dirección de cada operando o instrucción
utilizado mediante un proceso en la dirección del byte de memoria donde reside en realidad
el operando o la instrucción. El uso del modelo de asignación de memoria no contigua reduce el
problema de fragmentación de la memoria porque un área libre de memoria puede volver a
usarse incluso si no es suficientemente grande para admitir todo un proceso. De esta forma, es
posible alojar más procesos en la memoria, lo cual redunda en beneficio tanto de los usuarios
como del SO.
La ilusión de una gran memoria es creada al permitir la ejecución de un proceso cuyo ta-
maño excede al de la memoria. Esto se logra manteniendo un proceso en un disco y cargando
en la memoria en cualquier instante sólo sus porciones requeridas. El kernel utiliza esta idea
para reducir la asignación de memoria a procesos en general, es decir, incluso los procesos que
pueden caber en la memoria no se cargan totalmente en ella. Esta estrategia incrementa aún más
el número de procesos que pueden alojarse en la memoria.

Memoria

Proceso Disco

Información
de asignación de
memoria
Figura 6.1 Visión general de la memoria virtual.

En la figura 6.1 se muestra un esquema de la memoria virtual. Un proceso contiene cinco


componentes. Tres de éstas se encuentran en ese momento en la memoria. La información sobre
las áreas de la memoria donde existen las componentes se mantiene en una estructura de datos
del manejador de la memoria virtual. La MMU utiliza esta información durante la traducción de
la dirección. Cuando una instrucción en el proceso se refiere a una componente del proceso que
no está en la memoria, ésta se carga desde el disco. Ocasionalmente, el manejador de la memoria
virtual elimina algunas componentes del proceso de la memoria para tener espacio y poder car-
gar otras. Ahora ya es posible definir la memoria virtual.

Definición 6.1 (Memoria virtual) La memoria virtual es una jerarquía de la memoria que
consta de la memoria y el disco de un sistema de cómputo, y que permite la operación de un
proceso sólo con algunas porciones de su espacio de direcciones que hay en la memoria.

07 MAQ. CAP. 06(F0694).indd 238 8/10/07 1:01:17 AM


6.1 Fundamentos de la memoria virtual 239

Dos métodos fundamentales para implementar la memoria virtual son:

• Paginamiento.
• Segmentación.

Estos métodos difieren en la manera como se determinan las fronteras y tamaños de las com-
ponentes de los procesos. En el paginamiento, cada componente de un proceso se denomina
página. Todas las páginas son del mismo tamaño. El tamaño de página es determinado por la
arquitectura del sistema de cómputo y ésta lleva a cabo de manera implícita la demarcación
de las páginas en un proceso. En la segmentación, cada componente de un proceso es un
segmento. Un programador declara como segmentos algunas entidades lógicas importantes
en un proceso con el objetivo de implementar la memoria virtual. Así, la identificación de las
componentes de un proceso la realiza el programador, y los segmentos pueden tener tamaños
diferentes. Como se verá en secciones posteriores, el paginamiento y la segmentación tienen
implicaciones diferentes para la utilización de la memoria y para la compartición de progra-
mas y datos.
Los sistemas de memoria virtual que utilizan paginamiento y segmentación se denominan
sistemas de memoria virtual con paginamiento y sistemas de memoria virtual segmentados.
Algunos sistemas utilizan un método combinado de segmentación y paginamiento para obtener
ventajas de ambos. Este capítulo se iniciará con un repaso general de la operación de un sistema
de memoria virtual.

6.1.1 Carga por demanda de las componentes de un proceso

La memoria virtual utiliza carga por demanda de las componentes de un proceso a fin de
dar la ilusión de una gran memoria. Cuando va a iniciarse la ejecución de un proceso, el mane-
jador de la memoria virtual carga en la memoria sólo una de sus componentes. Ésta contiene
su primera instrucción. Las demás se cargan según sea necesario. De esta forma, la memoria
asignada a un proceso puede ser menor que el tamaño de éste. Para mantener reducido el
compromiso de memoria, el manejador de la memoria virtual elimina de la memoria una com-
ponente de un proceso si ésa pudiera no ser necesaria durante algún tiempo para la ejecución
de un proceso.
El desempeño de un proceso en un sistema de memoria virtual depende del ritmo al que
es necesario cargar en la memoria las componentes de un proceso. Si este ritmo es bajo, se
obtiene un desempeño aceptable. El manejador de la memoria virtual aplica una técnica espe-
cial para lograr lo anterior, misma que aprovecha el principio de localidad de referencia, que
se analizará en la sección 6.2.2.1. Un programador también puede contribuir a la obtención de
un buen desempeño mediante la codificación de un proceso, de modo que no requiera muchas
de sus componentes en ningún momento durante su ejecución (consulte el problema 7 en el
ejercicio 6).

6.1.2 Un ejemplo de operación de la memoria virtual

En la figura 6.2 se muestra la ejecución del proceso A en una memoria virtual. El proceso cons-
ta de cuatro componentes, 1-4. Por conveniencia, éstas se denominan A-1, A-2, A-3 y A-4.

07 MAQ. CAP. 06(F0694).indd 239 8/10/07 1:01:18 AM


240 CAPÍTULO 6 Memoria virtual

Memoria
0

Proceso A
0 MMU
A-1
A-2 Add ·· (3, 349)
A-2 A-1 47000
3 349 A-2 15000
A-3
A-3 38000
A-4 A-3 A-4 –
16999 38000 349
Espacio de Información
direcciones lógicas A-1 de asignación de
49999 38349 la memoria
Espacio de direcciones físicas

Figura 6.2 Espacio de direcciones lógicas, espacio de direcciones físicas y traducción de la dirección.

La dirección inicial lógica, el tamaño y la dirección inicial de la memoria asignada a cada una de
estas componentes son como se muestra a continuación:

Componente del proceso A-1 A-2 A-3 A-4


Dirección inicial lógica 0 3000 9000 13000
Tamaño 3000 6000 4000 4000
Dirección inicial del área de 47000 15000 38000 –
la memoria

El espacio de direcciones lógicas de A consta de las direcciones 0 . . . 16999. El sistema de


cómputo tiene una memoria de 50 K bytes, por lo que el espacio de direcciones físicas consta
de las direcciones 0 . . . 50 K-1. Alguna parte del espacio de direcciones físicas está ocupada por
componentes del proceso A, mientras que el resto del espacio puede estar ocupado por compo-
nentes de otros procesos en el sistema. Observe que en la memoria sólo existen las componentes
A-1, A-2 y A-3; la componente A-4 no está presente en la memoria.
Una vez que se despacha A, a la MMU se le proporciona información sobre las direccio-
nes iniciales de las áreas de la memoria asignadas a las componentes de A. Cuando se ejecuta
la instrucción Add ·· (3, 348) de la componente A-32, la MMU obtiene la dirección de la compo-
nente número 3, es decir, 38000. Siguiendo la ecuación (5.1), se calcula 38000348 para obtener
la dirección de la memoria efectiva del byte 348 en esta componente. Luego se lleva a cabo un
acceso a la ubicación de la memoria con dirección 38348. Si se hace referencia a alguna compo-
nente en la dirección 4, es decir, (4, 228), entonces el manejador de la memoria virtual debe car-
gar la componente A-4 en la memoria y dar a conocer su dirección inicial a la MMU.

6.2 PAGINAMIENTO POR DEMANDA


6.2.1 Visión general del paginamiento
Se entiende que un proceso consta de páginas, numeradas desde 0 hacia delante. El tamaño de
cada página es s bytes. Se considera que la memoria del sistema de cómputo consta de mar-
cos de página, donde un marco de página es un área de la memoria del mismo tamaño de una

07 MAQ. CAP. 06(F0694).indd 240 8/10/07 1:01:18 AM


6.2 Paginamiento por demanda 241

página. Los marcos de página están numerados de 0 a nf 1, de modo que nf  s es el tamaño de
la memoria. El espacio de direcciones físicas consta de las direcciones que van de 0 a nf  s 1.
En cualquier instante, un marco de página puede estar libre o contener una página de algún pro-
ceso. Cada dirección lógica que se usa en un proceso se considera como un par (pi, bi), donde pi
es un número de página y bi es un desplazamiento en pi, 0  bi  s. El tamaño de una página (y
por tanto el de un marco de página) se elige como una potencia de 2. Esta elección simplifica la
traducción de la dirección y también la hace más eficaz (consulte la sección 5.7).

0 4
1 Tabla de
2 1 página de P1
Memoria 3
MMU Marco de
0 página #
pi bi
1 1 0
2 2 480 2 1 5 Tabla de
2 7
3 3 página de P2
4 3 4
7 480
5 Add 2 480 qi bi
6 0
7 1 0 6
2 Tabla de
4 3 2 página de P3 Lista de
4 3 marcos
5 libres

Figura 6.3 Traducción de la dirección en un sistema de memoria virtual con paginamiento.

En la figura 6.3 se muestra una vista general de un sistema de memoria virtual con pagi-
namiento, donde se supone que una página contiene 1 K byte. Tres procesos P1, P2 y P3 tienen
algunas de sus páginas en la memoria. La memoria contiene 8 marcos de página numerados de
0 a 7. La información de asignación de la memoria para un proceso se almacena en una tabla
de página. Cada entrada en la tabla de página contiene información de asignación de la memoria
para una página de un proceso y el número del marco de página en que reside una página. El
proceso P2 tiene sus páginas 1 y 2 en la memoria, que ocupan los marcos 5 y 7, respectivamente.
El proceso P1 tiene sus páginas 0 y 2 en los marcos de página 4 y 1, respectivamente, mientras
que el proceso P3 tiene sus páginas 1, 3 y 4 en los marcos de página 0, 2 y 3, respectivamente.
La lista de marcos libres contiene una lista de marcos de páginas libres. En ese momento, sólo la
página de marco 6 está libre.
El proceso P2 está ejecutando entonces la instrucción “Add ·· 2528”, de modo que la MMU
utiliza la tabla de página de P2 para la traducción de la dirección. La MMU ve la dirección
de operando 2528 como el par (2, 480). Luego ingresa la entrada para la página 2 en la tabla de
página de P2. Esta entrada contiene el número de marco 7, de modo que la MMU forma la di-
rección 7  1 024  480 y la utiliza para hacer un acceso a la memoria. En efecto, el byte con
el desplazamiento 480 ingresa en el marco de página 7.

07 MAQ. CAP. 06(F0694).indd 241 8/10/07 1:01:18 AM


242 CAPÍTULO 6 Memoria virtual

6.2.2 Preliminares del paginamiento por demanda

En el paginamiento por demanda, una página se carga en la memoria cuando se requiere, es decir,
cuando una dirección lógica generada por un proceso apunta a una página que no se encuentra
en la memoria. Para facilitar el paginamiento por demanda, todo el espacio de direcciones lógi-
cas de un proceso se mantiene en un dispositivo de almacenamiento secundario, como un disco
rápido. Este disco se denomina dispositivo de paginamiento. Mientras se inicia la ejecución
de un proceso, un área se asigna al dispositivo de paginamiento para su espacio de direcciones
lógicas, y su código y sus datos se copian en este espacio. Este espacio se denomina espacio
de intercambio del proceso. Una página se carga desde esta área hacia la memoria cuando es
necesario. Si el manejador de la memoria virtual decide eliminar una página de la memoria, la
página se copia de vuelta en el espacio de intercambio si fue modificada desde la última vez
que fue cargada en la memoria. De esta forma, el espacio de intercambio contiene una copia
actualizada de cada página que no se encuentra en la memoria.
El paginamiento por demanda implica la interacción entre componentes del hardware y del
software de la memoria virtual, es decir, entre la MMU y el manejador de la memoria virtual.
Tres conceptos son importantes para comprender la operación del paginamiento por demanda.
Éstos son:

• Fallo de página.
• Operaciones de página adentro y página afuera.
• Reemplazo de página.

A las entradas de la tabla de página se agregan nuevos campos para facilitar la implementación
de estos conceptos. El formato de una entrada de una tabla de página es como se muestra en la
figura 6.4. El campo de bit válido contiene un valor booleano para indicar si la página existe en
la memoria; por ejemplo, 1 para indicar “residente en la memoria” y 0 para indicar “no residente
en la memoria”. El campo misc info (información miscelánea) contiene información útil para
las operaciones de página adentro y página afuera, así como de reemplazo de página. Se divide
en cuatro subcampos. La información en el campo prot info se utiliza para proteger la página.
ref info contiene información relacionada con referencias hechas a la página mientras está en la
memoria. Como se analizará más tarde, esta información se utiliza para decisiones de reemplazo
de página. El campo modified indica si la página ha sido modificada, es decir, si es sucia. El
campo other info contiene otra información concerniente a la página; por ejemplo, la dirección
del disco en el espacio de intercambio donde se mantiene una copia de la página.
El procedimiento de traducción de la dirección se describe en la tabla 6.1. Éste origina
un fallo de página si la página no se encuentra en la memoria. El fallo de página conduce a
operaciones de página adentro, página afuera y reemplazo de página para cargar la página en
la memoria. A continuación se describen detalles de estas operaciones.

Fallos de página Mientras realiza la traducción de la dirección para una dirección lógica
(pi, bi), la MMU comprueba el bit válido de la entrada de la tabla de página de pi (consulte el
paso 2 de la tabla 6.1). Si indica que pi no está presente en la memoria, el manejador de la me-
moria virtual origina una interrupción denominada fallo de página o interrupción por omisión de
página (missing page interrupt). La acción de interrupción (consulte la sección 2.1.1) transfiere
el control al manejador de interrupción, que invoca al manejador de la memoria virtual cuando

07 MAQ. CAP. 06(F0694).indd 242 8/10/07 1:01:19 AM


6.2 Paginamiento por demanda 243

Misc
info

Bit Marco de Prot Ref Modi- Otra


válido página # info info ficado info

Campo Descripción
Bit válido Indica si la página descrita por la entrada existe en ese momento
en la memoria. Este bit también se denomina bit de presencia.
Marco de página # Contiene el número de marco de página ocupado por la página.
Prot info Información de protección (si los procesos pueden leer la página
o escribir en ella).
Ref info Información relacionada con las referencias hechas a la página
mientras está en la memoria.
Modificado Indica si la página ha sido modificada mientras está en la memo-
ria, es decir, si es sucia. Este bit también se denomina bit sucio.
Otra info Otra información útil concerniente a la página; por ejemplo, su
posición en el espacio de intercambio.

Figura 6.4 Campos en una entrada de una tabla de página.

Tabla 6.1 Pasos en la traducción de la dirección

1. Una dirección lógica se considera como un par (pi, wi), donde wi consta de los bits de orden inferior
sw de la dirección y pi consta de los bits de orden superior sp .
2. pi se utiliza para indicar la tabla de página. Una falla de página se eleva al campo bit válido si la
tabla de página contiene un 0.
3. El campo marco de página # contiene un número marco representado como un bit sb. Éste está
concatenado con wi para obtener la dirección de memoria efectiva. Ello es la dirección fisica de la
dirección de la palabra.
4. El acceso a la memoria se hace con la dirección de memoria efectiva.

encuentra que la interrupción es un fallo de página. El manejador de interrupción pasa el número


de página que provocó la interrupción, es decir, pi, al manejador de la memoria virtual. El mane-
jador de la memoria virtual carga la página pi en la memoria.
La figura 6.5 contiene una visión general de las acciones del manejador de la memoria
virtual cuando el proceso P2 está en ejecución. Mientras traduce la dirección lógica (3, 682), la
MMU provoca un fallo de página porque el bit válido de la entrada de la página 3 es 0. Cuando
el manejador de la memoria virtual adquiere el control, sabe que una referencia a la página 3
provocó el fallo de página. El campo Misc info de la entrada de la tabla de página 3 cuenta con
la dirección del bloque de disco que contiene a la página 3. El manejador de la memoria virtual

07 MAQ. CAP. 06(F0694).indd 243 8/10/07 1:01:19 AM


244 CAPÍTULO 6 Memoria virtual

obtiene esta dirección. Luego consulta la lista de marcos libres y encuentra que el marco de
la página 6 está libre en ese momento. Asigna este marco de página a la página 3 e inicia una
operación de E/S para cargar la página 3 en el marco de la página 6. Una vez que la termina,
actualiza la entrada de la página 3 en la tabla de página al establecer el bit válido en 1 y colocar 6
en el campo de marco de página #. La ejecución de la instrucción “Sub ·· (3, 682)”, que provocó
el fallo de página, se reanuda a continuación. La dirección lógica (3, 682) debe traducirse a la
dirección física 6s682, que es la dirección del byte con desplazamiento 682 en el marco de
página 6.

Espacio de
intercambio de P2
Manejador
de la
memoria
virtual

Memoria
MMU
0 Tabla de página
pi bi
1 1 0
2 3 682 1 1 5
2 2 1 7 P2
3 3 0
4 4
5 Sub 3 682 qi bi
6 Bit Marco Misc 6
válido de página info
7 Lista de
#
marcos libres

Figura 6.5 Carga por demanda de páginas.

Operaciones de página adentro, página afuera y reemplazo de página Una página se


carga en la memoria cuando ocurre un fallo de página. Esto se denomina operación de página
adentro. En la figura 6.5 existía un marco de página cuando ocurrió un fallo de página. Éste
puede no ser el caso en todo fallo de página. Por tanto, el manejador de memoria virtual puede
tener que eliminar una página de la memoria a fin de crear espacio libre para cargar una página
requerida. Si la página que está eliminándose ha sido modificada después de la última vez que
se cargó en la memoria, el espacio de intercambio no contiene su copia actualizada. Esta página
debe copiarse de la memoria al bloque de disco que tiene asignado en el espacio de intercam-
bio del proceso. Esta operación se denomina página afuera. El hecho de cargar una nueva página
en un marco de página que previamente contenía otra página se denomina operación de reem-
plazo de página. Puede implicar una operación de página afuera si la página previa que ocupaba

07 MAQ. CAP. 06(F0694).indd 244 8/10/07 1:01:19 AM


6.2 Paginamiento por demanda 245

el marco de página fue modificado mientras estaba en la memoria, e implica una operación de
página adentro para cargar la nueva página.
Las operaciones de página adentro y página afuera requeridas para implementar pagina-
miento por demanda constituyen páginas de E/S. La expresión tráfico de página se utiliza para
describir el movimiento de páginas afuera y adentro de la memoria. Observe que la página de
E/S es distinta de las operaciones de E/S realizadas por las páginas, lo cual se denomina E/S del
programa. Un proceso que encuentra un fallo de página se convierte en bloqueado hasta que
la página requerida se carga en la memoria, por lo que el desempeño de ejecución del proceso
se ve afectado. El CPU puede intercambiarse para la ejecución de otro proceso; sin embargo,
la eficacia del sistema se afectará si todos los procesos en el sistema están bloqueados debido a
fallos de página.

Tiempo de acceso a la memoria efectiva Para calcular el tiempo de acceso a la memoria


efectiva se utiliza la siguiente notación en paginamiento por demanda:

pr1 probabilidad de que en la memoria exista una página


ta tiempo de acceso a la memoria
tpfh sobrecarga de tiempo del manejo de un fallo de página

donde pr1 se denomina relación de impactos en la memoria. tpfh incluye el tiempo consumido
por las operaciones de página adentro, página afuera y reemplazo de página antes descritas. Es
alrededor de dos órdenes de magnitud más grande que ta.
En la memoria existe una tabla de página de proceso cuando éste se encuentra en operación.
Por tanto, si una página a la que se está haciendo referencia también existe en la memoria, in-
troducir un operando con la dirección lógica (pi, bi) consume dos ciclos de memoria: uno para
ingresar la entrada de pi en la tabla de página de proceso para traducción de la memoria y otro
para ingresar el operando desde la memoria utilizando una dirección de memoria efectiva de
(pi, bi). En caso de que la página no esté presente en la memoria, se origina un fallo de página
después de haber referido la tabla de página, es decir, después de un ciclo de memoria. Luego, la
página requerida es cargada en la memoria y su entrada en la tabla de página se actualiza para re-
gistrar el número de marco del marco de página donde se carga. tpfh incluye el tiempo consumido
por el acceso inicial a la tabla de página que originó el fallo de página y el tiempo consumido por
la operación de página adentro o de reemplazo de página. Se ignora la sobrecarga de intercambio
de proceso y se supone que el proceso se programa inmediatamente después de que terminan
las operaciones de página adentro o de reemplazo de página. El tiempo de acceso a la memoria
efectiva se calcula como sigue:

Tiempo de acceso a la memoria efectiva  pr1  2  ta  (1  pr1)  (ta  tpfh  2  ta)


(6.1)

El tiempo de acceso a la memoria efectiva puede mejorarse si se reduce el número de fallos


de página. Cargar las páginas antes de que sean requeridas por un proceso puede reducir el nú-
mero de fallos de página. El sistema operativo Windows NT realiza precarga especulativamente:
cuando ocurre un fallo de página, carga la página requerida y también unas cuantas páginas
adjuntas del proceso. Esta acción no logra una mejora en el tiempo de acceso a la memoria si
la página precargada no es referenciada por el proceso. El sistema operativo Linux permite que

07 MAQ. CAP. 06(F0694).indd 245 8/10/07 1:01:19 AM


246 CAPÍTULO 6 Memoria virtual

un proceso especifique cuáles páginas deben precargarse. Un programador puede utilizar este
servicio para mejorar el tiempo de acceso a la memoria efectiva.

6.2.2.1 Reemplazo de páginas

El reemplazo de páginas se vuelve necesario cuando ocurre un fallo de página y en la memoria


no existen marcos de página libres. En principio, el manejador de la memoria virtual puede ele-
gir al azar un marco de página y reemplazar la página ahí contenida. Sin embargo, podría ocurrir
otro fallo de página cuando la página reemplazada vuelve a ser referenciada, por lo que resulta
importante reemplazar una página que no tenga probabilidades de ser referenciada en el fu-
turo inmediato. El principio de localidad de referencia proporciona pistas invaluables para iden-
tificar estas páginas.

Localidad de referencia La localidad de referencia puede plantearse como sigue:

Una dirección lógica generada mientras se ejecuta una instrucción en un proceso tiene
la probabilidad de encontrarse en la cercanía de las direcciones lógicas generadas
durante las instrucciones previamente ejecutadas del proceso.

Los procesos muestran buena localidad por dos razones. La naturaleza de la ejecución de un
programa es mayoritariamente secuencial, ya que sólo entre 10 y 20 por ciento de las instruccio-
nes son de ramificación. Así, la siguiente instrucción que se va a ejecutar suele ir a continuación
de las instrucciones previamente ejecutadas en el espacio de direcciones lógicas. Las referen-
cias a datos no escalares, es decir, arreglos, también tienden a estar en la proximidad de refe-
rencias previas porque los procesos tienden a realizar operaciones semejantes sobre varios
elementos de un arreglo.
Considere que la región de proximidad de una dirección lógica ai contiene a todas las direc-
ciones lógicas que están en la cercanía de ai. Para facilitar las cosas, se supone que la región de
proximidad de ai está totalmente dentro de la página que contiene a ai, por ejemplo la página pi,
es decir, una dirección lógica en la región de proximidad de ai está ubicada dentro de la página
pi misma.
La localidad actual de un proceso se define como el conjunto de páginas referenciadas
en sus instrucciones previas. El principio de localidad indica que la dirección lógica utilizada en
una instrucción tiene la probabilidad de referir a una página que está en su localidad actual.
Dada esta probabilidad, es de esperar que puedan ocurrir demasiados fallos de página durante la
operación de un proceso si las páginas en su localidad actual están presentes en la memoria. Así,
resulta previsible que los sistemas de memoria virtual con paginamiento por demanda operen
con niveles razonables de eficacia.
Observe que la localidad de referencia no implica ausencia de fallos de página. Éstos ocu-
rren por dos razones: primero, la región de proximidad de una dirección lógica puede no caber
en una página, por lo que un acceso en su región de proximidad puede referirse a una página que
no está incluida en la localidad actual del proceso. Segundo, una instrucción o datos referidos por
un proceso pueden no existir en su localidad actual. Esta situación se denomina desplazamiento
en la localidad de un proceso y suele ocurrir cuando un proceso realiza una transición de una
acción en su lógica a otra.

07 MAQ. CAP. 06(F0694).indd 246 8/10/07 1:01:20 AM


6.2 Paginamiento por demanda 247

Ejemplo 6.1 En la figura 6.6, los asteriscos indican las últimas direcciones lógicas usadas duran-
te la ejecución de un proceso P. Los recuadros con líneas discontinuas muestran las regiones de
proximidad de estas direcciones lógicas. Observe que las regiones de proximidad de las direcciones
lógicas referenciadas en la página 4 se traslapan entre sí y se extienden más allá de las fronteras de
la página; de manera semejante, ocurre esto con las direcciones lógicas referenciadas en la página
6. Así, las regiones de proximidad están localizadas en las páginas 0, 1, 3, 4, 5, 6 y 7; sin embargo,
la localidad actual de P es el conjunto de páginas {0, 1, 4, 6}.

Página Proceso P
número ................................ Dirección lógica
................................................ a la que se
Una página en ∗0 ................................ ha accedido
su localidad ∗1 ................................................................
actual ................................................ Región de
2 proximidad
de la dirección
3 lógica
................................................
∗4 ................................................................
................................................................
................
5 ................................................
∗6 ................................................................
................................................................
................................
7
8

Figura 6.6 Regiones de proximidad de referencias previas y localidad actual de un proceso.

El principio de localidad ayuda a decidir qué página debe reemplazarse cuando ocurre un
fallo de página. Se supondrá que el número de marcos de página asignados a un proceso P es una
constante, de modo que es necesario reemplazar una de las páginas de P existentes en la memo-
ria. Sean t1 y t2 los intervalos de tiempo durante los cuales no se ha hecho referencia a las páginas
p1 y p2 durante la ejecución de P. Sea t1  t2, lo que implica que algún byte de la página p2 ha sido
referido o ejecutado (como una instrucción) más recientemente que cualquier byte de la página
p1. Por tanto, la página p2 tiene más probabilidad de formar parte de la localidad actual del
proceso que la página p1, es decir, es más probable referir o ejecutar un byte de la página p2 que
uno de la página p1. Este argumento se utiliza para elegir a la página p1 para reemplazo cuando
ocurra un fallo de página. Si en la memoria hay muchas páginas de P, es posible clasificarlas
según las últimas referencias que se han hecho a éstas y reemplazar la página a la que se haya
hecho la última referencia.
En la figura 6.7 se muestra cómo puede variar la razón de fallo de página de un proceso
con la cantidad de memoria que se le ha asignado al proceso. Lo anterior se denomina caracte-
rística de fallo de página deseable y es una gráfica de la razón de fallo de página de un proceso,
es decir, del número de fallos de página por tiempo unitario de ejecución contra el número de
marcos de página asignados al proceso. La razón de fallo de página decrece de manera monótona
con el número de marcos de página, o lo que es lo mismo, la razón de fallo de página es menor
si a un proceso se asigna una mayor cantidad de memoria. Como se analizará más tarde, esta

07 MAQ. CAP. 06(F0694).indd 247 8/10/07 1:01:20 AM


248 CAPÍTULO 6 Memoria virtual

propiedad es útil para el diseño de acciones del manejador de la memoria virtual a fin de res-
ponder a un desempeño deficiente del sistema. Observe que la pendiente de la curva es mayor
cuando la asignación de memoria es modesta. Esto implica que la razón de fallo de página
aumenta pronunciadamente si se reduce la asignación de memoria existente hasta ese momento,
o decrece rápidamente si la asignación es pequeña y se aumenta. La curva es más plana en la
región de alta asignación de memoria. En esta región, un cambio en la asignación de memoria
posee un impacto relativamente menor sobre la razón de fallo de página.


Zona de
Razón operación
de fallo de Región de aconsejable Región
página fallo de de fallo de
página página
elevado bajo

0
Número de marcos de página →
asignados a un proceso

Figura 6.7 Variación aconsejable de la razón de fallo de página con asignación de memoria.

¿Cuánta memoria debe asignar un SO a un proceso? Dos factores opuestos afectan esta
decisión. Con base en la figura 6.7, se observa que un exceso de compromiso de la memoria
implicará un fallo de página bajo y, por ende, un desempeño aceptable del proceso. Sin embargo,
un exceso de compromiso de la memoria significará que menos procesos cabrán en la memoria.
Esta situación provocará que el CPU esté ocioso, así como un desempeño deficiente del sistema.
Un defecto de compromiso de la memoria originará un fallo de página elevado, lo cual conducirá
a un desempeño deficiente del sistema. La zona de operación aconsejable indicada en la figu-
ra 6.7 evita las regiones de asignación de memoria baja y alta.

Hiperpaginación Considere un proceso que está operando a la izquierda de la zona de


operación aconsejable de la figura 6.7. Este proceso opera en la región de razón de fallo
de página elevado. Si todos los procesos en el sistema operan en estas regiones, el CPU estará
esencialmente ocupado realizando tráfico de páginas e intercambio de procesos. La eficacia del
CPU será baja y el desempeño del sistema, medido en términos de tiempo de respuesta promedio
o de rendimiento, será deficiente. Esta situación se denomina hiperpaginación.

Definición 6.2 (Hiperpaginación) Hiperpaginación es la coincidencia de tráfico de página


alto y baja eficacia del CPU.

Observe que una baja eficacia del CPU podrá ser resultado de otras causas, como un bajo
grado de multiprogramación; sin embargo, en estas situaciones no existirá alto tráfico de páginas.

07 MAQ. CAP. 06(F0694).indd 248 8/10/07 1:01:20 AM


6.2 Paginamiento por demanda 249

Con base en la figura 6.7, puede observarse que la causa de la hiperpaginación es un bajo compro-
miso de la memoria con los procesos. El remedio consiste en aumentar la asignación de memoria
para cada proceso. Esto puede lograrse eliminando algunos procesos de la memoria, es decir,
reduciendo el grado de multiprogramación.
Observe que este razonamiento es de naturaleza cualitativa. No ayuda a decidir cuánta me-
moria, es decir, cuántos marcos de página son necesarios asignar a cada proceso. El problema
más importante para decidir la asignación de memoria para un proceso es que la característica de
fallo de página, es decir, la pendiente de la curva y la razón del fallo de página en la figura 6.7,
varía con los procesos. De hecho, incluso para el mismo proceso es probable que la característica
sea diferente para datos distintos. Por tanto, es razonable suponer que la cantidad de memoria
óptima para asignar a un proceso debe determinarse dinámicamente considerando el comporta-
miento de la ejecución de un proceso. Esta cuestión se analizará en la sección 6.4.

6.2.2.2 Tamaño óptimo de página

El tamaño de página se define en la arquitectura de un sistema de cómputo. Determina el número


de bits requeridos para representar el desplazamiento del byte en una página. El hardware de
paginamiento usa implícitamente esta información mientras descompone una dirección lógica
en un par (pi, bi). El tamaño de página también determina

1. El desperdicio de memoria debido a fragmentación interna.


2. El tamaño de la tabla de página para un proceso.
3. Las razones de fallo de página cuando se asigna una cantidad de memoria fija a un pro-
ceso.

Considere un proceso P de tamaño igual a z bytes. Un tamaño de página de s bytes implica


que el proceso tiene las páginas 0, . . . , n 1, de modo que n  关z冫s兴, donde 关z冫s兴 indica que
el valor de z/s se redondea hacia arriba. La fragmentación interna media es s/2 bytes porque la
última página debe estar semivacía en promedio. El número de entradas en la tabla de página
es n. Así, la fragmentación interna varía directamente con el tamaño de página, mientras que el
tamaño de la tabla de página varía en razón inversa a dicho número.
Resulta interesante observar que la razón de fallo de página varía directamente con el tama-
ño de página, mientras que el tamaño de la tabla de página varía inversamente en relación con
dicha razón. Esto puede explicarse como sigue: el número de páginas de P en la memoria varía
inversamente al tamaño de página. En la memoria habrá el doble de páginas que hay en P si el
tamaño de página es igual a s冫2. Ahora suponga que la región de proximidad de una instrucción
según se definió en la sección 6.2 es pequeña en comparación con s冫2, de modo que las regiones
de proximidad de las últimas direcciones lógicas generadas por un proceso caben completamente
en las páginas que las contienen. Así, cuando el tamaño de página es s冫2, la memoria contiene
el doble de regiones de proximidad de direcciones lógicas recientes que cuando el tamaño
de página era igual a s bytes. Con base en la característica de fallo de la figura 6.7, las razones de
fallo de página deben ser más bajas para menores tamaños de página.
Puede calcularse el tamaño de página que minimice la penalización de memoria debido a
los dos primeros factores. Si s z y cada
√ entrada de la tabla de página ocupa un byte de me-
moria, entonces el valor óptimo de s es 2z. De esta forma, el tamaño óptimo de página es 400
bytes para un proceso de tamaño 80 K bytes, y sólo 800 bytes para un proceso de 320 K bytes.

07 MAQ. CAP. 06(F0694).indd 249 8/10/07 1:01:20 AM


250 CAPÍTULO 6 Memoria virtual

Sin embargo, los sistemas de cómputo tienden a usar tamaños de página más grandes (por ejem-
plo, Pentium y MIPS usan tamaños de página de 4 K bytes o más, Sun Ultrasparc usa tamaños
de página de 8 K bytes o más y la Powerpc usa un tamaño de página de 4 K bytes) debido a las
siguientes razones:
1. Las entradas de la tabla de página tienden a ocupar más de un byte.
2. Los costos de hardware son más altos para tamaños de página más pequeños. Por ejem-
plo, el costo de traducción de la dirección aumenta si para representar un número de
página se usa un número más grande de bytes.
3. Los discos rápidos que se utilizan como dispositivos de paginamiento tienden a operar
de manera menos eficaz para tamaños más pequeños de bloques de disco.
La decisión de utilizar tamaños de página más grandes que el valor óptimo implica de algu-
na manera razones de fallo de página más altas para un proceso. Esta característica representa
una solución intermedia entre el costo de hardware y la eficacia del proceso.

6.2.3 Hardware de paginamiento

En la sección 6.2.1 se analizó la provisión fundamental para traducción de la dirección (consul-


te la figura 6.3). El hardware de paginamiento realiza las funciones adicionales enumeradas en
la tabla 6.2 para acelerar la traducción de la dirección y admitir las funciones del maneja-
dor de la memoria virtual. A continuación se describen algunas técnicas utilizadas para im-
plementar estas funciones. Al final de la sección se incluyen estudios de caso de hardware de
paginamiento en unos cuantos sistemas.

Tabla 6.2 Funciones del hardware de paginamiento

• Traducción de la dirección y generación de fallos de página: El hardware de paginamiento


contiene características para acelerar la traducción. También admite paginamiento en un sistema
multiprogramado al mantener las tablas de página para varios programas y usar la correcta para la
traducción de una dirección.
• Protección de la memoria: Esta función evita interferencia mutua entre los procesos del usuario.
Es necesario utilizar técnicas especiales debido a la naturaleza no contigua de asignación de me-
moria.
• Suministro de soporte para reemplazo de página: El hardware reúne información relacionada con
referencias hechas a las páginas de un programa. El manejador de la memoria virtual usa esta in-
formación para decidir qué página reemplazar cuando ocurre un fallo de página.

6.2.3.1 Traducción de la dirección y generación de fallo de página

Memoria intermedia para traducción de la dirección Para una dirección lógica (pi, bi),
la MMU agrega pi  lPT_entry, donde lPT_entry es la longitud de una entrada de la tabla de página
a la dirección inicial de la tabla de página. Esto proporciona la dirección de la entrada de la tabla
de página de la página pi. Luego se accede a ella para realizar la traducción de la dirección. El
formato de la tabla de página es como se muestra en la figura 6.4. Si lPT_entry es una potencia de 2,
pi  lPT_entry puede calcularse de manera eficaz al desplazar el valor de pi por estos cuantos bits.

07 MAQ. CAP. 06(F0694).indd 250 8/10/07 1:01:21 AM


6.2 Paginamiento por demanda 251

Si las tablas de página se encuentran en la memoria, entonces cada acceso a la memoria


consumirá dos ciclos de memoria: uno para acceder a la tabla de página y otro para el acceso a
la memoria real. Para acelerar la traducción de la memoria se utiliza una memoria intermedia
para traducción de la dirección (consulte la figura 6.8). La memoria intermedia (buffer) es una
memoria pequeña y totalmente asociativa que contiene información relacionada con algunas pá-
ginas del proceso que está ejecutándose en ese momento. Cada entrada en la memoria intermedia
es un par de la forma (página #, marco de página #) para alguna página que existe en la memoria.
La memoria intermedia es buscada de manera basada en contenido utilizando un número de
página como llave, es decir, el número de página se compara simultáneamente con el campo
de página # de todas las entradas en la memoria intermedia. La búsqueda regresa la entrada de
la página o termina en un fracaso. Para una dirección lógica (pi, bi), la MMU accede primero a la
memoria intermedia (consulte las flechas marcadas como 2 y 3 en la figura 6.8). Si la entrada
de la página no se encuentra en la memoria intermedia, la traducción de la dirección se reali-
za utilizando la tabla de página. Esto hace rápida la traducción de la dirección si en la memoria
intermedia hay información sobre la página requerida. La memoria intermedia de traducción de
la dirección se denomina almacenamiento temporal de visión lateral de traducción (translation
look-aside buffer: TLB) debido a la manera en que se utiliza.

Página Marco de
# página #

2 7 Almacenamiento
temporal de
1 5 visión lateral de
2 traducción (TLB)
Memoria 3
MMU
0
p i bi
1 1 0
2 2 479 2 1 1 5
2 1 7
3 3 Tabla de
4 4 página de P2
7 479 3
5 Add 2479 q i bi
6
7 Bit Marco Misc
4 válido de página info
#

Figura 6.8 Almacenamiento temporal de visión lateral de traducción.

Las memorias asociativas son costosas, de modo que el TLB sólo contiene unas cuantas
entradas. El hardware de paginamiento mantiene información sobre las páginas más recientes a
las que se ha hecho referencia mediante un proceso en el TLB. Siempre que el TLB busca fallos
para una página, el hardware forma un par (página #, marco de página #) que coloca en el TLB.
Este par desplaza algún par existente en el TLB.
Para ver cómo el TLB acelera la traducción de la dirección, se calcula el tiempo de acceso a
la memoria efectiva utilizando la siguiente notación:

07 MAQ. CAP. 06(F0694).indd 251 8/10/07 1:01:21 AM


252 CAPÍTULO 6 Memoria virtual

pr1 probabilidad de que en la memoria haya una página


pr2 probabilidad de que en el TLB haya una entrada de página
ta tiempo de acceso a la memoria
tt tiempo de acceso del TLB
tpfh sobrecarga de tiempo del manejo de fallo de página

Comúnmente, tt es por lo menos un orden de magnitud más pequeño que ta, que es aproxima-
damente dos órdenes de magnitud más pequeño que tpfh. pr2 se denomina relación de impactos
en el TLB.
Cuando no se utiliza el TLB, el tiempo de acceso a la memoria efectiva está dado por
la ecuación (6.1). Cuando se usa el TLB, pr2 es la probabilidad de que una entrada de la página
requerida exista en el TLB. La probabilidad de que una referencia de una tabla de página sea
necesaria y suficiente para la traducción de la dirección es (pr1  pr2). El tiempo consumido por
cada una de tales referencias es (tt  2  ta), ya que una búsqueda infructuosa TLB precede a la
búsqueda de la tabla de página. Un fallo de página puede ocurrir en cualquier otro momento. Por
tanto, el tiempo de acceso a la memoria efectiva es

Tiempo de acceso a la memoria efectiva  pr2  (tt  ta)  (pr1  pr2)  (tt  2  ta)
 (1  pr1)  (tt  ta  tpfh  tt  2  ta)
(6.2)

Obtener (pi , w)i


de la dirección
lógica

Sí ¿El elemento
pi está en el
TLB? Fallo de página

No
¿Se requiere No
¿pi está en No página
la memoria? afuera?
Cargar la
Se presenta un Sí página pi
Sí fallo de página Eliminar de la
Introducir (pi fi ) memoria la
página pj Actualizar la
en la dirección entrada PT
lógica de pi
Actualizar la
entrada, TLB
Formar la de pj Invocar al programador
dirección física
utilizando f i

Acciones de la ATU Acciones del manejador de la memoria virtual

Figura 6.9 Resumen de las acciones en el paginamiento por demanda.

En la figura 6.9 se resumen las acciones de software y hardware implicadas en la traducción


de la dirección y en el manejo de fallo de página para una dirección lógica (pi, bi). La MMU
primero lleva a cabo una búsqueda TLB para pi. Si encuentra un par (pi, fi), completa la traduc-

07 MAQ. CAP. 06(F0694).indd 252 8/10/07 1:01:21 AM


6.2 Paginamiento por demanda 253

ción de la memoria utilizando a fi. Si fracasa la búsqueda TLB, la MMU hace referencia a la en-
trada de la tabla de página de pi para comprobar si pi está en la memoria. Si se encuentra en la
página fi, la MMU hace una entrada (pi, fi) en el TLB y termina la traducción de la dirección
utilizando a fi. Si pi no está en la memoria, entonces la MMU genera un fallo de página. Todas
estas acciones las realiza el hardware.
El manejador de la memoria virtual es activado por fallo de página. Verifica si un marco
de página vacío está disponible para cargar la página; en caso contrario, inicia una operación de
página afuera para alguna página pj a fin de liberar el marco de página fj ocupado por el marco
de página. La entrada pj de la tabla de página se actualiza para indicar que ya no se encuentra en
la memoria. Si pj tiene una entrada en el TLB, entonces el manejador de la memoria virtual la
borra mediante la ejecución de una instrucción “erase TLB entry” a fin de evitar la posibilidad
de una traducción de la dirección incorrecta en la siguiente referencia a pj. Luego se realiza
una operación de página adentro para cargar pj en el marco de página fj, y la entrada pi de la
tabla de página se actualiza cuando se termina la operación de página adentro. La ejecución
de la instrucción que originó el fallo de página debe repetirse cuando el proceso se progra-
ma de nuevo. Esta vez se encuentra que pi está en la memoria, de modo que la MMU utiliza la
información en esta tabla de página para terminar la traducción de la dirección. También hace
una entrada (pi, fj) en el TLB.

Superpáginas El tamaño de las memorias y procesos de las computadoras ha crecido rá-


pidamente desde la década de los noventa. Sin embargo, los tamaños del TLB no han seguido el
ritmo de estos incrementos porque la naturaleza completamente asociativa de los TLB los hace
costosos. En consecuencia, TLB reach, que es el producto del tamaño de página y el número de
entradas en un TLB, ha crecido marginalmente, aunque su relación con el tamaño de memoria
se ha reducido por un factor de más de 1 000. Por consiguiente, las relaciones de impactos del
TLB son deficientes en comparación y los tiempos medios de acceso a la memoria son más altos
[consulte la ecuación (6.2)]. Los cachés del procesador también se han vuelto más grandes que el
TLB reach. Esto afecta el desempeño del caché porque puede ser necesario hacer más lento
el acceso a instrucciones o datos en un caché debido a fallas y búsquedas del TLB a través de las
tablas de página. Una forma de contrarrestar estos problemas es utilizando un tamaño de página
más grande, de modo que la búsqueda TLB se vuelva también más grande. Sin embargo, esto
conduce a mayor fragmentación interna y a más páginas de E/S.
El concepto de superpáginas surgió para aminorar el problema creado por una baja búsque-
da TLB. Una superpágina es como una página de un proceso, excepto porque su tamaño es una
potencia de 2 múltiplos del tamaño de página, y su dirección inicial en el espacio de direcciones
lógicas y en el espacio de direcciones físicas está alineada con respecto a un múltiplo de su ta-
maño. La mayor parte de las arquitecturas modernas permiten unos cuantos tamaños estándares
de superpáginas y que la entrada TLB sea utilizada por una página o por una superpágina. Esta
característica incrementa la búsqueda TLB sin aumentar el tamaño del TLB y ayuda a obtener
una mayor relación de impactos del TLB.
El manejador de la memoria virtual aprovecha el concepto de superpáginas mediante la
adaptación del tamaño y el número de superpáginas en un proceso a sus características de eje-
cución. Puede combinar algunas páginas de un proceso en una superpágina de tamaño idóneo si
a estas páginas se accede con frecuencia, y satisfacer el requerimiento de contigüidad y alinea-
miento con respecto a la dirección en el espacio de direcciones lógicas. Esta acción se denomina
promoción. Puede ser necesario que el manejador de la memoria virtual tenga que relocalizar las

07 MAQ. CAP. 06(F0694).indd 253 8/10/07 1:01:21 AM


254 CAPÍTULO 6 Memoria virtual

páginas en la memoria a fin de satisfacer contigüidad y alineamiento con respecto a la dirección


en la memoria. Una promoción incrementa la búsqueda TLB y libera a algunas de las entradas
del TLB que fueron asignadas a páginas individuales de la nueva superpágina.
Si el manejador de la memoria virtual encuentra que a algunas páginas en una superpágina
no se accede a menudo, puede decidir descomponer la superpágina en sus páginas individuales.
Este paso, denominado degradación, libera algo de memoria que puede utilizarse para cargar
otras páginas. Así, tiene el potencial de reducir la frecuencia de fallo de página.

Traducción de la dirección en un sistema multiprogramado En la figura 6.10 se ilustra


la traducción de la dirección en un sistema multiprogramado. En la memoria existen tablas de
página para muchos procesos. La MMU contiene un registro especial denominado registro
de la dirección de la tabla de página (PTAR) para indicar el inicio de la tabla de página. La
MMU utiliza el contenido de esta tabla de página para la traducción de la dirección. Para una
dirección lógica (pi, bi), la MMU calcula PTAR  pi  lPT _entry, donde lPT _entry es la longitud
de una entrada de la tabla de página, para obtener la dirección de la entrada de la tabla de pági-
na de la página pi.

Tabla de
Memoria página de P1
MMU
PTAR
2
Sumar +
1
pi bi Tabla de
1 fi
>? página de P2
Tamaño 3
del
PT
1 fi bi
4
Tabla de
página de P3

Excepción de protección de la memoria

Figura 6.10 Traducción de la memoria en un sistema multiprogramado.

El PTAR debe cargarse con la dirección correcta siempre que se programe un proceso. Para
facilitar esto, el kernel puede almacenar la dirección de la tabla de página de cada proceso en
su PCB. Debido a que todos los procesos en el sistema usan el TLB, el kernel debe borrar su
contenido cada vez que se programa un nuevo proceso.

6.2.3.2 Protección de la memoria

En un sistema multiprogramado con memoria virtual y paginamiento, las excepciones a la pro-


tección pueden presentarse sólo en las dos formas siguientes:

07 MAQ. CAP. 06(F0694).indd 254 8/10/07 1:01:22 AM


6.2 Paginamiento por demanda 255

• Una dirección está fuera del espacio de direcciones lógicas de un proceso: Un proceso
puede utilizar una dirección lógica (pi, bi) que exceda el tamaño de su espacio de direc-
ciones lógicas. Debido a que el kernel considera que un proceso contiene un número
entero de páginas, esto sólo puede ocurrir si pi es mayor que el número de la última
página en el kernel. En este caso, la MMU debe cancelar la traducción de la dirección
y presentar una excepción de protección de la memoria. No hacer lo anterior puede ser
desastroso, ¡ya que un número de página fuera de rango puede apuntar hacia una entrada
en la tabla de página de algún otro proceso!
• Un proceso excede sus privilegios de acceso: Un proceso puede intentar acceder a una
página de manera inválida, por ejemplo, puede tratar de modificar una página para la que
sólo tiene un privilegio de lectura. Esto puede ocurrir en un sistema que permite compar-
tición de páginas.

Los pasos en la tabla 6.3 implementan la protección de la memoria. Un registro, denomi-


nado PT size register, se proporciona en la MMU para este objeto (consulte la figura 6.10). Este
registro se carga con el número de página de la última página del proceso que está ejecutándose
actualmente. La MMU verifica el número de página de cada dirección lógica contra este registro
antes de acceder a la tabla de página (consulte el paso 2 en la tabla 6.3). Provoca una interrup-
ción de protección de la memoria si el número de página excede el tamaño de la tabla de página.
La información del tamaño de tabla de página se preserva en el PCB de un proceso. Se carga en
la MMU cuando se programa el proceso.

Tabla 6.3 Pasos en la implementación de la protección en el espacio de direcciones lógicas

1. Considere una dirección lógica como un par (pi, bi).


2. Presente una excepción de protección de la memoria si pi excede el contenido del registro de ta-
maño PT (consulte la flecha marcada con 1 en la figura 6.10). Calcule PTAR  pi  lPT _entry
para acceder a la entrada de la tabla de página para pi.
3. Compruebe el tipo de acceso que está realizándose con los privilegios de acceso almacenados en el
campo misc info de la entrada pi de la tabla de página. En caso de conflicto, presente una excepción
de protección de la memoria.

Los privilegios de acceso de un proceso a una página pueden almacenarse en el campo misc
info de su entrada en la tabla de página. Durante la traducción de la dirección, la MMU puede ve-
rificar el tipo de acceso que está realizándose a una página confrontándola con esta información
(consulte el paso 3 en la tabla 6.3). Los privilegios de acceso pueden ser codificados como bits
para un acceso eficaz. Cada bit en el campo debe corresponder a un tipo de acceso (por ejemplo,
read, write, etc.). Se establece en “on” si el proceso posee el privilegio de acceso correspondiente
a la página.

6.2.3.3 Soporte para el reemplazo de página


El manejador de la memoria virtual requiere dos tipos de información para tomar decisiones
relacionadas con el reemplazo de página que minimicen los fallos de página y el número de
operaciones de página adentro y página afuera:

07 MAQ. CAP. 06(F0694).indd 255 8/10/07 1:01:22 AM


256 CAPÍTULO 6 Memoria virtual

1. Hora en que la página fue utilizada por última vez.


2. Si una página es sucia, es decir, si en cualquier byte de la página se ha realizado una
operación de escritura. (Una página es limpia si no es sucia.)
La hora de uso último indica cuán recientemente se ha utilizado la página en el proceso.
Esta información es útil para decidir si la página puede formar parte de la localidad actual de
un proceso. Como se verá en la sección 6.3 cuando se analicen las políticas de reemplazo
de página, esta información también puede usarse para establecer la diferencia entre páginas
para el propósito de reemplazo de página. La información sobre si una página es limpia o sucia
se usa para decidir si durante el reemplazo de página es necesario realizar una operación de
página afuera. Si una página es limpia, entonces en el espacio de intercambio del proceso ya
hay una copia actualizada. Por tanto, no se requiere ninguna operación de página afuera; su
copia en la memoria puede simplemente sobrescribirse llevando a cabo una operación de
página adentro para cargar la página. Para una página sucia, es necesario efectuar una opera-
ción de página afuera porque su copia en el espacio de intercambio no está actualizada. Una
operación de página adentro para la nueva página que se va a cargar puede iniciarse sólo des-
pués de terminar la operación de página afuera. Para indicar si una página es limpia o sucia es
suficiente un solo bit, mientras que para registrar la hora del último uso pueden ser necesarios
varios bits.

6.2.4 Operaciones de E/S en un entorno con paginamiento

Una operación de E/S en un proceso especifica el número de bytes que se van a transferir y la
dirección lógica del área de datos, que es el área de la memoria que participa en la transferencia
de datos. El área de datos puede generar varias páginas del proceso. A fin de evitar la disrup-
ción de la operación de E/S, todas las páginas del área de datos deben estar en la memoria a
todo lo largo de la operación, de modo que el kernel carga todas las páginas del área de datos en
la memoria y pone un E/S fix en cada página antes de iniciar la operación. El manejador de la
memoria virtual no reemplaza ninguna de estas páginas hasta que se retira el E/S fix al final de
la operación de E/S. Una forma sencilla de implementar fijación de páginas de E/S es agregar un
bit E/S fix al campo de misc info de cada entrada de la tabla de página.
El subsistema de E/S no contiene ninguna MMU, de modo que la E/S debe efectuarse uti-
lizando direcciones físicas. El manejador de E/S utiliza la información de la tabla de página del
proceso para reemplazar la dirección lógica del área de datos por su dirección física.
Una cuestión clave en la implementación de una operación de E/S es que las páginas que
contienen un área de datos pueden no ser asignadas a direcciones físicas contiguas. Para abordar
esta cuestión puede utilizarse la característica dispersar y recoger con que cuentan casi todos los
subsistemas de E/S. Una operación “scatter read” puede depositar parte de sus datos en áreas
de memoria no contiguas. Por ejemplo, puede leer los primeros bytes de un registro de E/S en
un marco de página situado en una parte de la memoria y los bytes restantes en otro localizado
en una parte diferente de la memoria. De manera semejante, un “gather write” puede retirar sus
datos de áreas de memoria no contiguas y escribirlos en un dispositivo de E/S. En el ejemplo 6.2
se ilustra cómo se usa una operación scatter read para implementar una operación de E/S que
genera dos páginas en un proceso.
Si un subsistema de E/S no cuenta con la característica de dispersar y recoger, el kernel pue-
de manejar esta situación en dos formas. Puede colocar de forma contigua en la memoria física
páginas que contienen el área de datos, o primero puede leer los datos hacia un área del kernel

07 MAQ. CAP. 06(F0694).indd 256 8/10/07 1:01:22 AM


6.2 Paginamiento por demanda 257

que tenga direcciones físicas contiguas y luego copiarlos hacia el área de datos en el proceso.
Provisiones semejantes pueden hacerse para admitir una operación de escritura.

Espacio de direcciones Espacio de direcciones


lógicas Memoria lógicas Memoria

8 leer (i1 ,20), 8 leer 14020,


i2 leer (i1 ,20), i2 leer (i1 ,20),
10
i1 i1
i1 +1 i1 +1
14 14
15

Bit Marco de Misc Bit Marco de Misc


válido página # info válido página # info

i1 1 14 I/O fix i1 1 14 I/O fix


i1 +1 1 10 I/O fix i1 +1 1 15 I/O fix

i2 1 8 i2 1 8
PT PT
a) b)
Figura 6.11 Operaciones de E/S en sistemas con memoria virtual.

Ejemplo 6.2 La página i2 de un proceso P contiene un sistema denominado ‘perf _io (read, 827,
(i1, 520))’, donde 827 es el conteo de los bytes de datos a leer e (i1, 520) es la dirección lógica del
principio del área de datos. En la figura 6.11 se ilustra la forma en que se implementa la operación
de E/S. El tamaño de la página es 1 K byte, de modo que el área de datos está situada en las páginas
i1 e i1  1 del proceso. Antes de iniciar la operación de E/S, el manejador de la memoria virtual
ha invocado cargar las páginas i1 e i1  1 en la memoria. Estas páginas se cargan en los marcos
de página 14 y 10 de la memoria. El manejador de la memoria virtual coloca un E/S fix en estas
páginas al establecer bits en el campo de misc info de sus entradas de la tabla de página. Estas pá-
ginas no se reemplazan sino hasta que se retira el E/S fix al final de la operación de E/S. Luego, el
manejador de E/S genera una operación scatter-read para leer los primeros bytes, empezando en
el byte de desplazamiento 520 en el marco de página 14, y los bytes restantes empezando en el byte
de desplazamiento 0 en el marco de página 15. El E/S fix sobre las páginas 14 y 15 se retira una vez
que termina la operación de E/S.

6.2.5 El manejador de la memoria virtual

El manejador de la memoria virtual utiliza dos estructuras de datos. La tabla de página, cuyo
formato de entradas se muestra en la figura 6.4, y la lista de marcos libres. Con pocas excepcio-
nes, en especial en la arquitectura IBM/370, los campos ref info y modified son establecidos por

07 MAQ. CAP. 06(F0694).indd 257 8/10/07 1:01:22 AM


258 CAPÍTULO 6 Memoria virtual

el hardware de paginamiento. Todos los demás campos son establecidos por el manejador de la
memoria virtual.
En la tabla 6.4 se resumen las funciones efectuadas por el manejador de la memoria virtual.
En esta sección se analizan las cuatro primeras funciones. Las otras, a saber, reemplazo de pá-
gina, asignación de memoria física a los procesos e implementación de páginas compartidas, se
analizan en las siguientes secciones.

Tabla 6.4 Funciones realizadas por el manejador de la memoria virtual

1. Administra el espacio de direcciones lógicas de un programa: Organiza el espacio de direcciones


lógicas en el dispositivo de paginamiento, mantiene la tabla de página del programa, realiza ope-
raciones de página adentro y página afuera.
2. Administra la memoria física: Preserva la pista de marcos de página ocupados y libres en la me-
moria.
3. Implementa protección de la memoria: Mantiene la información necesaria para protección de la
memoria.
4. Reúne información para reemplazo de página: El hardware de paginamiento proporciona infor-
mación relacionada con referencias a páginas. Esta información se mantiene en estructuras de da-
tos idóneas para ser utilizadas por el algoritmo de reemplazo de página.
5. Lleva a cabo reemplazo de página: Lleva a cabo el reemplazo de una página cuando se presenta un
fallo de página y todos los marcos de página en la memoria están ocupados.
6. Asigna memoria física a los programas: Decide cuánta memoria debe asignar a un programa y
revisa esta decisión de vez en cuando para ajustar las necesidades del programa y el SO.
7. Implementa la compartición de páginas: Arregla la compartición de páginas entre programas.

Administración del espacio de direcciones lógicas de un proceso Para este efecto, el


manejador de la memoria virtual emplea las siguientes subfunciones:
1. Organiza una copia de las instrucciones y datos del proceso en el dispositivo de pagi-
namiento.
2. Mantiene la tabla de página.
3. Realiza operaciones de página adentro y página afuera.
4. Lleva a cabo la iniciación de procesos.
Como ya se mencionó en la sección 6.2, el espacio de direcciones lógicas se organiza en
el espacio de intercambio del proceso una vez que se inicia un proceso. Cuando una referencia
a un proceso conduce a un fallo de página, la página se carga desde el espacio de intercambio
utilizando una operación de página adentro. Cuando una página sucia debe eliminarse de la
memoria, una operación de página afuera la copia desde la memoria hacia el bloque de disco
en el espacio de intercambio. Así, el espacio de intercambio contiene una copia actualizada de
toda página de proceso que no está en la memoria física y de todas las que se encuentran en la
memoria pero no han sido modificadas desde que fueron cargadas por última vez. Para otras
páginas, la copia en la memoria es actual y el espacio de intercambio contiene una copia pasada
(es decir, no actualizada).
Una cuestión en la administración del espacio de intercambio es el tamaño del espacio de
intercambio para un proceso. La mayor parte de los sistemas con memoria virtual permiten que

07 MAQ. CAP. 06(F0694).indd 258 8/10/07 1:01:23 AM


6.2 Paginamiento por demanda 259

el espacio de direcciones lógicas de un proceso crezca dinámicamente durante su ejecución.


Esto puede ocurrir por varias razones. El tamaño de la pila o de las áreas de datos PCD pueden
aumentar (consulte la sección 5.3.2), el proceso puede ligar dinámicamente más módulos o efec-
tuar mapeo de memoria de archivos (consulte la sección 6.6). Un método evidente para manejar
el crecimiento dinámico de espacios de direcciones es asignar dinámicamente y de manera no
contigua el espacio de intercambio; no obstante, este método enfrenta el problema de que el
manejador de la memoria virtual puede quedarse sin espacio de intercambio durante la ejecución
de un proceso.
Para iniciar la ejecución de un proceso, sólo es necesario cargar en la memoria la página que
contiene la primera instrucción del proceso. Las otras páginas deben traerse por demanda. En
las secciones 6.2.1 y 6.2 ya se han descrito detalles de la tabla de página y de las operaciones de
página adentro y página afuera.

Administración de la memoria física La lista de marcos libres se mantiene durante todo


el tiempo. Un marco de página se saca de la lista para cargar una página nueva, y un marco se
agrega a ésta cuando se lleva a cabo una operación de página afuera. Todos los marcos de página
asignados a un proceso se agregan a la lista una vez que termina el proceso.

Protección La protección de la información, que consiste en privilegios de acceso del pro-


ceso a sus páginas, se almacena en la tabla de página en el momento de iniciación del proceso.
El hardware de protección se inicializa simplemente cargando la dirección inicial de la tabla
de página y la información sobre el tamaño de página en registros idóneos MMU mientras se
programa un proceso. Como ya se vio, esto se logra al colocar estos puntos de información en
el PCB de un proceso. Luego, esta información se transfiere a los registros MMU como parte de
la acción de despacho.

Recolección de información para reemplazo de página El campo ref info de una entrada
en la tabla de página indica la última vez que se hizo referencia a una página, y el campo modi-
fied indica si la página ha sido modificada desde que fue cargada en la memoria. La información
sobre la referencia a la página es de utilidad sólo en la medida en que una página existe en la
memoria física; se reinicializa la siguiente vez que para la página se realiza una operación de
página adentro.
La mayor parte de las arquitecturas cuentan con un solo bit en el campo ref info para re-
colectar la información sobre la referencia a la página. Esta información no es adecuada para
elegir el mejor candidato para el reemplazo de página, de modo que el manejador de la memoria
virtual reestablece periódicamente el bit utilizado para almacenar esta información. Este aspecto
se analizará en la sección 6.3.1.

Ejemplo 6.3 Un sistema con memoria virtual cuenta con una memoria física que consta de 8 mar-
cos de página numerados de 0 a 7. En el sistema hay tres procesos: P1, P2 y P3. En la figura 6.12 se
muestra la tabla de página del proceso P1. P1 está en ejecución. Consta de cinco páginas numeradas
de 0 a 4. Los marcos de página 2, 7 y 4 han sido asignados a las páginas 1, 2 y 3, respectivamente.
Las otras páginas de P1 no existen en ese momento en la memoria. Los marcos de página 1 y 5 han
sido asignados a las páginas 8 y 4 del proceso P2, respectivamente, y los marcos de página 0, 3 y 6
lo han sido a las páginas 4, 1 y 3 del proceso P3, respectivamente. Así, todos los marcos de página
de la memoria física han sido asignados a procesos y en el sistema no hay ninguna página libre.
+
En la figura 6.12a) se ilustra la situación en el sistema en el instante t11 . En la figura sólo
se muestra el marco de página de P1 porque el proceso P1 está en ejecución. El contenido de los

07 MAQ. CAP. 06(F0694).indd 259 8/10/07 1:01:23 AM


260 CAPÍTULO 6 Memoria virtual

Marco Marco
Bit de Misc Bit de Misc
válido página # info válido página # info
0 0 0 0
1 1 2 m, t4 1 0
2 1 7 t11 2 1 7 t11
Memoria t9 Memoria t9
3 1 4 3 1 4
0 4 0 0 4 1 2 t12
1 1
PT PT
2 2
3 Página 3 Página
4 Estado identificación 4 Estado identificación
0 1 (P3 , 4) 0 1 (P3 , 4)
5 1 1 (P2 , 8) 5 1 1 (P2 , 8)
6 2 1 (P1 , 1) 6 2 1 (P1 , 4)
7 3 1 (P3 , 1) 7 3 1 (P3 , 1)
4 1 (P1 , 3) 4 1 (P1 , 3)
5 1 (P2 , 4) 5 1 (P2 , 4)
6 1 (P3 , 3) 6 1 (P3 , 3)
7 1 (P1 , 2) 7 1 (P1 , 2)
FT FT
a) b)
Figura 6.12 Operación del manejador de la memoria virtual.

campos ref info y modified se muestran en el campo misc info. Las páginas 1, 2 y 3 fueron referi-
das por última vez en los instantes t4, t11 y t9, respectivamente. La página 1 fue modificada poco
después de ser cargada, de modo que el campo misc info de su entrada de tabla de página contiene
la información m,t4.
En el instante t12, el proceso P1 provocó un fallo de página para la página 4. Debido a que
todos los marcos de página en la memoria física están ocupados, el manejador de la memoria virtual
decide reemplazar la página 1 del proceso. La página ha sido modificada desde que fue cargada,
por lo que es necesario efectuar una operación de página afuera. El campo marco de página # de la
entrada de la tabla de página de la página 1 indica que la página existe en el marco 2. El maneja-
dor de la memoria virtual efectúa entonces una operación de página afuera para escribir el conte-
nido del marco 2 en el área de intercambio reservada para la página 1 de P1. Luego se inicia una
operación de página adentro para la página 4 de P1. Al término de la operación, la entrada de la tabla
de página de la página 4 se modifica para indicar que existe en la memoria en el marco de página 2
y se reanuda la ejecución de P1. P1 inmediatamente hace una referencia a la página 4, por lo que
la información de referencia de página de la página 4 indica que la última vez que se hizo referen-
cia a ella fue en t12. En la figura 6.12b) se indican las estructuras de datos del manejador de la me-
+
moria virtual en el instante t12 .

6.2.6 Organizaciones prácticas de la tabla de página


Tablas de página invertidas Las estructuras de datos del manejador de la memoria virtual
constituyen un buen ejemplo de la negociación espacio-tiempo en los programas de sistemas.
Grandes procesos cuentan con grandes tablas de página, de modo que las estructuras de datos
del manejador de la memoria virtual ocupan bastante memoria. Para tener una idea de los reque-
rimientos de memoria de una tabla de página, considere un sistema de cómputo contemporáneo

07 MAQ. CAP. 06(F0694).indd 260 8/10/07 1:01:23 AM


6.2 Paginamiento por demanda 261

que utiliza direcciones lógicas que contienen 32 bits o más. El tamaño del espacio de direcciones
lógicas es 4 G bytes o más. Si el tamaño de una página es 1 K byte, entonces en un proceso pue-
de haber 4 millones de páginas. Cada entrada de una tabla de página mide unos cuantos bytes de
longitud, de modo que la tabla de página de un proceso puede ocupar varios M bytes.
A fin de conservar memoria, algunos sistemas prescinden por completo de tablas de página.
La tabla de marco, que también se denomina tabla de página invertida (IPT), se utiliza también
para traducción de la dirección. Este método ahorra una cantidad de memoria considerable, ya
que el tamaño de la IPT está regido sólo por el tamaño de la memoria física; es independiente del
número y el tamaño de los procesos que se están ejecutando. Sin embargo, el uso de la IPT hace
más lentas la traducción de la memoria y las funciones del manejador de la memoria virtual. Las
tablas de página invertida se utilizan en muchos sistemas, incluido el IBM RS 6000 y el AS 400.
En la IPT se almacena información útil para las decisiones de reemplazo de página.

MMU

Identi- Fallo de IPT


ficación página Identi-
Memoria P del ficación
proceso de la Ref
pi bi página info
1 2 3
P pi
fi (P, pi )
fi bi 4
Sumar
5

a)
Identi-
ficación
de la Marco Ref
P pi página # info Apuntador

(Q, pk ) fk
h (P, pi ) fi
v
(R, pl ) fl −

Tabla de búsqueda IPT


b)
Figura 6.13 Tablas de página invertida: a) concepto, b) implementación utilizando una tabla de búsqueda.

07 MAQ. CAP. 06(F0694).indd 261 8/10/07 1:01:23 AM


262 CAPÍTULO 6 Memoria virtual

En la figura 6.13a) se ilustra el uso de la IPT en la traducción de la dirección. Cada entrada


de la IPT contiene un par (identificación del proceso, número de página). Mientras se programa
un proceso, el programador copia la identificación del proceso desde su PCB hacia un registro
de la MMU. Sea P esta identificación. La traducción de la dirección para una dirección lógica en
el proceso P consta de las siguientes acciones:
1. El par (pi, bi) se extrae de una dirección lógica.
2. Utilizando la identificación del proceso P, se forma el par (P, pi).
3. El par (P, pi) se busca en la IPT. Se origina un fallo de página si la página no está en la
IPT.
4. Si el par existe en la entrada fi de la IPT, entonces el número del marco de página fi se
copia para su uso en la traducción de la dirección.
5. La traducción de la dirección se termina usando fi y bi.
Estos pasos se muestran con los números con círculo del 1 al 5 en la figura 6.13a).
La búsqueda de (P, pi) en la IPT hace más lenta la traducción de la dirección. Una solución
costosa para este problema consiste en almacenar la IPT en una memoria asociativa que pueda
ubicar la entrada de (P, pi) mediante una búsqueda asociativa. Una solución más práctica es
utilizar una tabla de búsqueda para acelerar la búsqueda.
En la figura 6.13b) se muestra una tabla de página invertida que utiliza una tabla de búsque-
da. Un par que consta de un identificación del proceso y un número de página se almacena en el
campo identificación de la tabla (page id) y el número de marco asignado a la página se alma-
cena en el campo marco # de la tabla de página invertida. La tabla de búsqueda se utiliza para
localizar de manera eficaz la entrada de un par requerido (P, pi) en la tabla de página inverti-
da durante la traducción de la dirección. La organización de la tabla de página invertida se
presenta en tres pasos. Primero, se analiza la organización de una simple tabla de búsqueda.
Luego se analiza la forma en que el manejador de la memoria virtual construye la tabla de página
invertida. Finalmente, en el ejemplo 6.4 se analiza la forma en que la MMU utiliza la tabla de
página invertida durante la traducción de la dirección.
Para buscar un par (P, pi), primero se concatenan las cadenas de bits que representan a P y
pi a fin de obtener una cadena de bits más larga. Luego, esta cadena de bits se interpreta como un
número entero x y se le aplica la siguiente función de búsqueda h:

h(x) = residuo ( ax )

donde a es el tamaño de la tabla de búsqueda, que suele ser algún número primo  número de
marcos, el número de marcos de página que hay en la memoria. h(x), que está en el intervalo
0. . . a  1, es el número de entrada en la tabla de búsqueda. Sea v este valor. Debido a que el
número total de páginas de todos los procesos que hay en la memoria es mucho mayor que
número de marcos, la búsqueda de muchos pares identificación del proceso-identificación
de la página puede producir el mismo valor v. Para incorporar esta posibilidad, el par (P, pi) no
se ingresa en la v-ésima entrada de la tabla de búsqueda. En vez de lo anterior, se almacena en
una entrada de la tabla de página invertida, y todas las entradas en la tabla de página invertida
que están ocupadas por tales pares identificación del proceso-identificación de la página que
buscan el valor de v se ingresan en una lista ligada. La v-ésima entrada de la tabla de búsqueda
apunta a la primera entrada en esta lista ligada. De manera semejante, los pares identificación
del proceso-identificación de la página que buscan en alguna otra entrada de la lista de búsqueda,

07 MAQ. CAP. 06(F0694).indd 262 8/10/07 1:01:24 AM


6.2 Paginamiento por demanda 263

por ejemplo, la w-ésima entrada, forman una lista ligada por separado a la que apunta la w-ésima
entrada de la tabla de búsqueda.
El manejador de la memoria virtual construye y mantiene la tabla de página invertida como
sigue: cuando la página pi del proceso P se carga en el marco de página fi en la memoria, el
manejador de la memoria virtual construye el par (P, pi) para ella. Busca este par a fin de obtener
el número de una entrada; por ejemplo, v. Luego, el manejador de la memoria virtual elige una
entrada libre en la tabla de página invertida e introduce el par (P, pi) en el campo identificación
de página y el número de marco fi en el campo marco # de esta entrada. Luego agrega esta
entrada a la lista ligada empezando en la v-ésima entrada de la tabla de búsqueda como sigue:
copia la v-ésima entrada de la tabla de búsqueda en el campo indicador de la entrada de la tabla
de página invertida recién formada e ingresa el número de entrada de la entrada de la tabla de
búsqueda recién formada en la v-ésima entrada de la tabla de búsqueda. Una vez que esta página
se elimina de la memoria, el manejador de la memoria virtual borra su entrada de la lista ligada
empezando en la v-ésima entrada de la tabla de búsqueda. En la figura 6.13b), las tres páginas
(R, pl), (P, pi) y (Q, pk), que fueron cargadas en los marcos de página fl, fi y fk, respectivamente,
se ingresan en la misma lista ligada porque todos ellos fueron buscados en la v-ésima entrada de
la tabla de búsqueda. En el ejemplo 6.4 se describe la forma en que la MMU utiliza la tabla
de página invertida durante la traducción de la dirección.

Ejemplo 6.4 La traducción de la dirección utilizando la IPT que se ilustra en la figura 6.13b) se
implementa como sigue: sea (pi, bi) la dirección lógica. Se busca el par (P, pi) para obtener un
número de entrada v en la tabla de búsqueda. Se busca la lista ligada empezando en esta entrada. El
par (P, pi) no corresponde con el par (Q, pk) que se encontró en la primera entrada de la lista, por
lo que a la siguiente entrada de la lista se accede usando el campo apuntador. Entonces se detecta
una correspondencia y se forma la dirección lógica (fi, bi) utilizando la identificación del marco fi
que se encontró en la entrada. Si la búsqueda de un par (S, pj) formado para una dirección lógica
(pj, wj) del proceso S también proporciona el mismo número de entrada v en la tabla de búsqueda,
se generará un fallo de página después de buscar todas las entradas en la lista ligada empezando en
la v-ésima entrada de la tabla de búsqueda.

Tablas de página de dos niveles Hasta el momento se ha supuesto que toda la tabla de
página de un proceso siempre está en la memoria. Esto es impráctico para tablas de página
grandes. Por ejemplo, en un sistema que utiliza direcciones lógicas de 32 bits y un tamaño de
página de 1 K byte, un proceso podrá tener 4 millones de páginas. Si el tamaño de la entrada
de una página es 4 bytes, una tabla puede contener 256 entradas de la tabla de página, ¡por lo que
la tabla de página podrá contener 16 000 páginas! Los requerimientos de memoria de una tabla
de página pueden reducirse al paginar la tabla de página en sí y cargar sus páginas por demanda,
justo como las páginas de un proceso. Este método origina un arreglo de dos niveles donde la
tabla de página del nivel superior contiene entradas que apuntan a páginas de la tabla de página y
la tabla de página contiene entradas que apuntan a las páginas de un proceso. Este arreglo reduce
el compromiso de la memoria a una tabla de página, ya que sólo algunas de sus partes están en
la memoria en cualquier instante.
En la figura 6.14 se ilustra el concepto de tabla de página de dos niveles. La memoria con-
tiene dos tipos de páginas: las páginas de proceso y las páginas de la tabla de página, es decir,
páginas PT, o páginas de la tabla de página. Para la traducción de la memoria de una dirección
lógica (pi, bi) en un proceso P, la página pi del proceso P debe estar en la memoria. También
la página de la tabla de página de P, que contiene la entrada para la página pi, debe existir en la

07 MAQ. CAP. 06(F0694).indd 263 8/10/07 1:01:24 AM


264 CAPÍTULO 6 Memoria virtual

Tabla de página
de P
Página 0
Páginas de
la tabla de Página 1
página de P Páginas
Página 2 de P

Byte con
la dirección (pi , bi )
Figura 6.14 Concepto de tabla de página de dos niveles.

memoria. En la figura 6.14, ésta es la página 1 de la tabla de página de P. Durante la traducción


de la dirección, la MMU debe determinar la identificación de esta página PT y asegurar su pre-
sencia en la memoria.
Como se mencionó en la sección 6.2.1, el número de página y los bits de desplazamiento
de una dirección lógica (pi, bi) están representados por np y nb bits. La longitud de una dirección
lógica, es decir, ll, es np  nb. Si el número de páginas ocupadas por la entrada de cada tabla de
página es una potencia de 2, entonces el número de entradas de la tabla de página que pue-
de caber en una página también debe ser una potencia de 2. Considere que cada entrada de la
tabla de página ocupa 2e bytes; entonces el número de entradas de tabla de página en una página
es 2nb /2e , es decir, 2nb –e. Por tanto, la identificación de la página PT que contiene la entrada de la
tabla de página para la página pi de un proceso está dada por 2npb i−e , donde indica un valor
entero truncado. Este número está contenido en np  (nb  e) bits de orden superior en pi. Los
nb  e bits de orden inferior indican cuál entrada en esta página contiene información concer-
niente a la página pi.
La traducción de la dirección requiere dos accesos a la memoria para acceder a la ta-
bla de página de orden superior y a la tabla de página del proceso. En la figura 6.15 se ilustra la
traducción de la dirección para una dirección lógica de la dirección (pi, bi). Consta de los pasos
siguientes:

1. La dirección (pi, bi) se reordena en tres campos:


n p − (nb − e) nb − e nb
p1i p2i bi

Los contenidos de estos tres campos son p1i , p2i y bi, respectivamente.
2. p1i es un número de página en la tabla de nivel superior. Esta página contiene la entrada pi
en la tabla de página. La MMU verifica si esta página existe en la memoria y en caso de
no estar ahí provoca un fallo de página. El fallo de página es atendido por el manejador
de la memoria virtual para cargar la página en la memoria.
3. p2i es el número de entrada para pi en esta página. La MMU usa la información en esta
entrada para comprobar si la página pi existe en la memoria y presenta un fallo de página
si la página no se encuentra en la memoria. El manejador de la memoria virtual atiende
el fallo de página y carga la página pi en la memoria.

07 MAQ. CAP. 06(F0694).indd 264 8/10/07 1:01:24 AM


6.2 Paginamiento por demanda 265

Página del
proceso P

PT

Tabla de
página
de nivel
superior
de P

p1i

p2i Página pi

bi
Palabra con
la dirección (pi , bi )

p1i p2i bi

pi
Figura 6.15 Organización de la tabla de página de dos niveles.

4. El contenido de la entrada de la tabla de página de pi se utiliza para llevar a cabo la tra-


ducción de la dirección.
Este paginamiento se utiliza en la arquitectura Intel 80386. La tabla de página de nivel supe-
rior se denomina directorio de página. Una referencia de página se implementa utilizando una en-
trada en el directorio de página y una entrada en la tabla de página. El hardware enciende los bits
a los que ha accedido en estas entradas. Si la referencia es una referencia de escritura, entonces de
manera adicional el hardware enciende el bit sucio en la entrada de la tabla de página.

Tablas de página de multinivel Las organizaciones de tabla de página de multinivel se


utilizan cuando el tamaño de la tabla de página de nivel superior en una organización de tabla
de página de dos niveles es grande en sí mismo. Como acaba de verse, en un sistema que utiliza
direcciones lógicas de 32 bits, un tamaño de página de 1 K byte y entradas de tabla de página
de 4 bytes, la página debe contener 16 000 páginas. El tamaño de la tabla de página de nivel
superior debe ser 64 K bytes. A fin de reducir aún más el compromiso de la memoria para tablas
de página, la tabla de página de nivel superior también puede ser paginada. Este arreglo da por
resultado una estructura de tabla de página de tres niveles.

07 MAQ. CAP. 06(F0694).indd 265 8/10/07 1:01:25 AM


266 CAPÍTULO 6 Memoria virtual

La traducción de la dirección en este entorno la realiza una extensión evidente de traduc-


ción de la dirección en tablas de página de dos niveles. Una dirección lógica (pi, bi) se separa en
cuatro componentes p1i , p2i , p3i y bi, y las tres primeras componentes se utilizan para direccionar
tres niveles de la tabla de página. Así, la traducción de la dirección requiere hasta tres accesos a
la memoria. En sistemas de cómputo que usan direcciones de 64 bits, incluso la tabla de página
de nivel más alto en una organización de tabla de página de tres niveles puede volverse dema-
siado grande. Las tablas de página de cuatro niveles se utilizan para superar este problema. En
las arquitecturas Sun Sparc y Motorota 68030 se han utilizado tablas de página de tres y cuatro
niveles, respectivamente. Estas dos arquitecturas usan direcciones lógicas de 32 bits.

6.3 POLÍTICAS DE REEMPLAZO DE PÁGINA

Una operación de reemplazo de página es necesaria si un marco de página libre no existe cuando
ocurre un fallo de página durante la ejecución de algún proceso proci. Una decisión de reemplazo
de página posee dos aspectos importantes:
1. Si una página que pertenece al proceso proci debe reemplazarse o si debe incrementarse
el número de marcos de página asignados al proceso proci.
2. Qué criterios deben usarse para elegir la página a reemplazar.
Como se analizará más tarde en esta sección, el manejador de la memoria virtual aborda por se-
parado estos aspectos. Así, cuando ocurre un fallo de página, el manejador de la memoria virtual
reemplaza una página del mismo proceso si todos los marcos de página asignados al proceso
están ocupados. La decisión de aumentar o disminuir la asignación de memoria a un proceso se
toma de manera independiente.
El reemplazo de página es una política de decisión basada en la información de referencia
de página disponible en la tabla de página. Se implementa mediante el uso de las operaciones de
página adentro y página afuera como mecanismos. En la figura 6.16 se representa el arreglo de la
política y los módulos del mecanismo del manejador de la memoria virtual. Los mecanismos
de página adentro y página afuera interactúan con el hardware de paginamiento a fin de implemen-
tar su cometido. También actualizan la página y los marcos de página para reflejar sus acciones.

Política de Tablas del manejador


paginamiento de la memoria virtual

Página Página Mecanismos


adentro afuera de paginamiento

Flujo de datos
Flujo de control
Hardware de paginamiento
Figura 6.16 Módulos del manejador de la memoria virtual en un sistema con memoria virtual y paginamiento.

A continuación se evalúan las tres siguientes políticas de reemplazo para ver cuán bien con-
sideran la localidad actual de un proceso mientras toman decisiones de reemplazo de página:

07 MAQ. CAP. 06(F0694).indd 266 8/10/07 1:01:26 AM


6.3 Políticas de reemplazo de página 267

• Política de reemplazo óptimo de página.


• Política de reemplazo FIFO.
• Política de reemplazo LRU.
En este análisis se usa la siguiente notación:

alloci : Número de marcos de página asignados al proceso proci

Cadena de referencia de página Una cadena de referencia de página de un proceso es una


secuencia de números de página que aparece en direcciones lógicas generadas por un proceso.
Cuando un proceso está a punto de ser iniciado, se crea una secuencia vacía de números de pá-
gina. Para toda dirección lógica utilizada durante la ejecución del proceso, el número de página
en la dirección lógica se agrega al final de la secuencia. Estas acciones implican una sobrecar-
ga sustancial del CPU, de modo que las cadenas de referencia de página sólo se construyen
para procesos que se utilizan para estudiar el desempeño de las políticas de reemplazo de página.
Observe que la ejecución de un proceso con datos diferentes puede conducir a diferentes cadenas
de referencia de página.
Se introduce el concepto de instante de tiempo lógico como ayuda para aludir a una referen-
cia de página específica en una cadena de referencia de página. Un instante de tiempo lógico es
el tiempo en un reloj lógico del proceso, es decir, un reloj que avanza sólo cuando el proceso se
encuentra en el estado de ejecución (running state). Los instantes de tiempo lógico se designan
como t1, t2, . . . Un instante de tiempo lógico se utiliza como índice en una cadena de referen-
cia de página. Para facilitar su uso, los instantes de tiempo lógico se muestran como una cadena
asociada con la cadena de referencia de página. Esta cadena se denomina cadena de referencia
de tiempo. En el ejemplo 6.5 se ilustra la cadena de referencia de página y la cadena de referen-
cia de tiempo para un proceso.

Ejemplo 6.5 Un sistema de cómputo proporciona instrucciones de longitud 4 bytes cada una y uti-
liza un tamaño de página de 1 K byte. Ejecuta el siguiente programa sin sentido en el que se supone
que A y B existen en las páginas 2 y 5, respectivamente:

START 2040
READ B
LOOP MOVER AREG, A
SUB AREG, B
BC LT, LOOP
...
STOP
A DS 2500

B DS 1
END

La cadena de referencia de página y la cadena de referencia de tiempo para el proceso son como
sigue:
cadena de referencia de página : 1, 5, 1, 2, 2, 5, 2, 1, . . .
cadena de referencia de tiempo : t1, t2, t3, t4, t5, t6, t7, t8 . . .

La dirección lógica de la primera instrucción es 2040, de modo que está en la página 1. En con-
secuencia, la primera referencia de página en la cadena es 1. Esto ocurre en el instante de tiempo

07 MAQ. CAP. 06(F0694).indd 267 8/10/07 1:01:26 AM


268 CAPÍTULO 6 Memoria virtual

lógico t1. B, el operando de la instrucción, se encuentra en la página 5, por lo que la segun-


da referencia de página en la cadena es 5. La siguiente instrucción está en la página 1 y hace refe-
rencia a A, que se encuentra en la página 2, de modo que las dos siguientes referencias de página
son a las páginas 1 y 2. Las dos siguientes instrucciones están en la página 2 y la instrucción con
etiqueta LOOP se encuentra en la página 1, por lo que las cuatro siguientes referencias de página
son a las páginas 2, 5, 2 y 1, respectivamente.

Reemplazo óptimo de página El reemplazo óptimo de página implica tomar decisiones de


reemplazo de página de modo que el número total de fallos de página durante la ejecución
de un proceso sea el mínimo posible, es decir, que ninguna otra decisión de reemplazo de página
conduzca a un menor número de fallos de página. Para obtener un reemplazo óptimo de pági-
na, en cada fallo de página la política de reemplazo de página debe considerar todas las decisio-
nes alternativas de reemplazo de página, analizar sus implicaciones para futuros fallos de página
y luego seleccionar la mejor alternativa. Belady (1966) demostró que esto puede lograrse sim-
plemente utilizando la regla siguiente: en un fallo de página, reemplazar la página cuya siguiente
referencia es la más lejana en la cadena de referencia de página.
El reemplazo óptimo de página no es factible porque el manejador de la memoria virtual
ignora el comportamiento futuro del proceso. Sin embargo, constituye una base útil para evaluar
el desempeño de otras políticas de reemplazo de página.

Reemplazo de página FIFO En cada fallo de página, la política de reemplazo de página


FIFO reemplaza la página que fue cargada en la memoria antes que cualquiera otra página del
proceso. Para facilitar la política de reemplazo de página FIFO, la entrada PIT de una página se
utiliza para registrar el instante en el que la página fue cargada por última vez en la memoria.
Cuando ocurre un fallo de página, esta información se usa para determinar pearliest, la página que
fue cargada antes que cualquiera otra página del proceso. Esta página se reemplaza por la página
requerida.

Reemplazo de página LRU La política LRU utiliza el principio de localidad de referencia


como base para sus decisiones de reemplazo. Su operación puede describirse como sigue: en
cada fallo de página, la página usada menos recientemente (LRU: least recently used) se reem-
plaza por una nueva página. La entrada de la tabla de página de una página registra el instante en
el que se hizo referencia por última vez a la página. Esta información es inicializada cuando se
carga una página, y remodificada cada vez que se hace referencia a la página. Cuando ocurre un
fallo de página, PIT es buscado para localizar la página plru cuya última referencia es anterior a
la de cualquier otra página. Esta página se reemplaza con una nueva página.

Ejemplo 6.6 A continuación se proporcionan una cadena de referencia de página y una cadena de
referencia de tiempo para un proceso P:

cadena de referencia de página : 0, 1, 0, 2, 0, 1, 2, . . . (6.3)


cadena de referencia de tiempo : t1, t2, t3, t4, t5, t6, t7 . . . (6.4)

En la figura 6.17 se ilustra la operación de las políticas de reemplazo FIFO y LRU para esta
cadena de referencia de página con alloc  2. Por conveniencia, sólo se muestran dos campos de
la tabla de página, a saber, valid bit y misc info, y se supone que la información de referencia
de página está almacenada en el campo misc info.

07 MAQ. CAP. 06(F0694).indd 268 8/10/07 1:01:26 AM


6.3 Políticas de reemplazo de página 269

En la columna izquierda se muestra información del reemplazo óptimo de página. La informa-


ción de referencia de página no se muestra en la tabla de página porque la información relacionada
con referencias pasadas no es necesaria para el reemplazo óptimo de página. En el instante de tiempo
lógico t4 ocurre un fallo de página, cuando se está haciendo referencia a la página 2. La página 1 se
reemplaza debido a que su siguiente referencia está más lejos en la cadena de referencia de página
que la referencia de la página 0. En el instante t6, la página 1 reemplaza a la página 0 porque la si-
guiente referencia de la página 0 está más lejos que la referencia de la página 2.

Óptimo FIFO LRU


Instante Referencia Bit Misc Reem- Bit Misc Reem- Bit Misc Reem-
de tiempo de página válido info plazo válido info plazo válido info plazo
0 1 0 1 t1 0 1 t1
t1 0 1 0 − 1 0 − 1 0 −
2 0 2 0 2 0

0 1 0 1 t1 0 1 t1
t2 1 1 1 − 1 1 t2 − 1 1 t2 −
2 0 2 0 2 0

0 1 0 1 t1 0 1 t3
t3 0 1 1 − 1 1 t2 − 1 1 t2 −
2 0 2 0 2 0

0 1 0 0 0 1 t3
t4 2 1 0 1 por 2 1 1 t2 0 por 2 1 0 1 por 2
2 1 2 1 t4 2 1 t4

0 1 0 1 t5 0 1 t5
t5 0 1 0 − 1 0 1 por 0 1 0 −
2 1 2 1 t4 2 1 t4

0 0 0 1 t5 0 1 t5
t6 1 1 1 0 por 1 1 1 t6 2 por 1 1 1 t6 2 por 1
2 1 2 0 2 0

0 0 0 0 0 0
t7 2 1 1 − 1 1 t6 0 por 2 1 1 t6 0 por 2
2 1 2 1 t7 2 1 t7

Figura 6.17 Comparación de las políticas de reemplazo de página con alloc  2.

La columna de en medio de la figura 6.17 ilustra la operación de la política de reemplazo


FIFO. Cuando se está haciendo referencia a la página 2, en el instante t4 ocurre un fallo de página.
El campo misc info muestra que la página 0 fue cargada antes que la página 1, de modo que la
página 0 se reemplaza por la página 2.
La última columna de la figura 6.17 ilustra la operación de la política de reemplazo LRU. El
campo misc info de la tabla de página indica la última vez que se hizo referencia a una página. En

07 MAQ. CAP. 06(F0694).indd 269 8/10/07 1:01:26 AM


270 CAPÍTULO 6 Memoria virtual

el instante t4, la página 1 se reemplaza por la página 2 porque la última referencia de la página 1 es
posterior a la última referencia de la página 0. El número total de fallos de página experimentados
por las políticas óptimo, FIFO y LRU son 4, 6 y 5, respectivamente.

Cuando se analiza por qué el desempeño de LRU es mejor que el de FIFO en el ejemplo 6.6,
se encuentra que FIFO eliminó la página 0 en el instante t4, aunque LRU no lo hizo así porque se
había hecho referencia a la página 0 después que a la página 1. Esta decisión es consistente con
el principio de localidad, que indica que debido a que a la página 0 se hizo referencia más recien-
temente que a la página 1, aquélla tenía una mayor probabilidad de haber sido referenciada que
la página 1. Así, LRU no interfiere con el principio de localidad de un proceso, mientras FIFO
sí lo hace.
Resulta interesante considerar si la política LRU posee la característica aconsejable de fallo
de página de la figura 6.7, es decir, si la política LRU es capaz de garantizar que la razón de
fallo de página no sea superior si el proceso fuese ejecutado con más memoria asignada a él. Para
analizar este asunto se utiliza la siguiente notación.

{pi }kn : Conjunto de páginas en la memoria en el instante t k+ si alloci


 n durante toda la ejecución del proceso proci (tk+ implica
un tiempo después del instante de tiempo tk pero antes de tk+ 1 ).

Definición 6.3 (Propiedad de pila) Una política de reemplazo de página posee la propiedad
de pila si
{pi }kn ⊆ {pi }km si n < m.

Considere dos ejecuciones del proceso proci, una con alloci  n durante toda su ejecución
y otra con alloci  m, de modo que n  m. Si una política de reemplazo de página posee la
propiedad de pila, entonces en puntos idénticos durante estas ejecuciones de proci (es decir, en
instantes de tiempo idénticos) todas las páginas que estaban en la memoria cuando alloci  n
también están en la memoria cuando alloci  m.
Puede demostrarse que si una política de reemplazo de página posee la propiedad de pila,
entonces su característica de fallo de página es semejante a la característica de fallo de página
aconsejable que se analizó en la sección 6.2.2. Considere un instante de tiempo lógico tg durante
las ejecuciones de proci con n y m páginas, respectivamente. Por brevedad, estas ejecuciones se
denominan “ejecución n” y “ejecución m”. Si la política de reemplazo de página posee la propie-
dad de pila, todas las páginas n que están en la memoria cuando alloci  n también están en la
memoria cuando alloci  m. Además, la memoria también contiene otras m  n páginas del pro-
ceso. Si se hace referencia a cualesquiera de estas páginas en las siguientes referencias de página
de proci, entonces ¡durante la ejecución n ocurren fallos de página pero no durante la ejecución
m! Así, la razón de fallos de página en la ejecución n debe ser mayor que en la ejecución m. Por
tanto, se cumple la característica de fallo de página de la figura 6.7. Las razones de fallo de
página deben ser idénticas si a estas páginas no se hace referencia en las siguientes referencias
de página; sin embargo, en ningún caso la razón de fallo de página aumenta cuando se incremen-
ta la asignación de memoria para un proceso.
Si una política de reemplazo de página no posee la propiedad de pila, entonces {p i }km no
contiene ninguna(s) página(s) contenida(s) en {pi }kn. Las referencias a estas páginas dan por

07 MAQ. CAP. 06(F0694).indd 270 8/10/07 1:01:27 AM


6.3 Políticas de reemplazo de página 271

resultado fallos de página, de modo que es posible que la ejecución m tenga un mayor número
de fallo de página que la ejecución n.
La política de reeemplazo de página FIFO no cuenta con la propiedad de pila, pero la polí-
tica LRU sí la tiene. Estos hechos se ilustran en el ejemplo 6.7.

Ejemplo 6.7 Considere las siguientes cadenas de referencia de página y de referencia de tiempo
para un proceso:

cadena de referencia de página : 5, 4, 3, 2, 1, 4, 3, 5, 4, 3, 2, 1, 5, . . . (6.5)


cadena de referencia de tiempo : t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13 . . . (6.6)

FIFO alloci = 3 3 3 3 4 4 4 4 4 2 2 2
4 4 4 1 1 1 5 5 5 5 5 5
5 5 5 2 2 2 3 3 3 3 3 1 1
5 4* 3* 2* 1* 4* 3* 5* 4 3 2* 1* 5
alloci = 4 3 3 3 3
2 2 2 2 2 2
3 3 3 3 3 3 4 4 4 4 5
4 4 4 4 4 4 5 5 5 5 1 1
5 5 5 5 1 1 1 1 1 1 2 2 2
5 4* 3* 2* 1* 4 3 5* 4* 3* 2* 1* 5*
LRU alloci = 3 3 3 3 4 4 4 4 4 4 1 1
4 4 4 1 1 1 5 5 5 2 2 2
5 5 5 2 2 2 3 3 3 3 3 3 5
5 4* 3* 2* 1* 4* 3* 5* 4 3 2* 1* 5*
alloci = 4 2 2 2 2 5 5 5 5 1 1
3 3 3 3 3 3 3 3 3 3 3
4 4 4 4 4 4 4 4 4 4 4 5
5 5 5 5 1 1 1 1 1 1 2 2 2
5 4* 3* 2* 1* 4 3 5* 4 3 2* 1* 5*
Figura 6.18 Desempeño de los reemplazos de página FIFO y LRU.

En la figura 6.18 se muestra el comportamiento de las políticas de reemplazo de página FIFO y


LRU. Cada columna de recuadros muestra los marcos de página asignados al proceso. Los núme-
ros en los recuadros indican páginas en la memoria después de ejecutar la referencia a la memoria
marcada bajo la columna. Las referencias de página marcadas con (*) provocan fallos de página y
dan por resultado reemplazo de página.
Se tiene {pi }12
4 = {2, 1, 4, 3}, mientras {pi }3 = {1, 5, 2} para reemplazo de página FIFO.
12

Así, el reemplazo de página FIFO no posee la propiedad de pila. Esto conduce a un fallo de página
en t13 cuando alloci  4, pero no cuando alloci  3. Por tanto, en 13 instantes de tiempo se pre-
senta un total de 10 fallos de página cuando alloci  4, mientras que se presentan 9 fallos de pá-
gina cuando alloci  3. Para LRU, se observa que {pi }3 ⊂ {pi }4 en todos los instantes de tiempo
lógicos.

En la figura 6.19 se ilustra la característica de fallo de página del reemplazo de página FIFO
y LRU para una cadena de referencia de página (6.5). Para facilitar las cosas, el eje vertical

07 MAQ. CAP. 06(F0694).indd 271 8/10/07 1:01:30 AM


272 CAPÍTULO 6 Memoria virtual

muestra el número total de fallo de página, más que la frecuencia de fallo de página. En la figura
6.19a) se ilustra un aspecto sorprendente del reemplazo de página FIFO: la frecuencia de fallo
de página de un proceso aumenta a medida que se incrementa su asignación de memoria. Este
comportamiento anómalo fue reportado por primera vez por Belady, por lo que se denomina
anomalía de Belady. El manejador de la memoria virtual no es capaz de usar reemplazo de pá-
gina FIFO porque aumentar la asignación a un proceso puede incrementar su frecuencia de fallo
de página. Esta característica podrá hacer imposible abordar la hiperpaginación en el sistema.
La gráfica para los reemplazos de página LRU muestran que el número de fallos de página es
una función no creciente de alloc. Por tanto, resulta imposible combatir la hiperpaginación in-
crementando el valor de alloc.

14 14
↑ 12 ↑ 12
10 10
fallos fallos
8 8
de página de página
6 6
4 4
2 2

0 1 2 3 4 5 0 1 2 3 4 5
alloc → alloc →
FIFO LRU

Figura 6.19 a) Anomalía de Belady en reemplazo de página FIFO, b) reemplazo de página LRU.

6.3.1 Políticas prácticas de reemplazo de página

LRU debe ser una opción automática para la implementación de un manejador de la memoria
virtual, ya que posee la propiedad de pila. Sin embargo, el reemplazo de página LRU no es fac-
tible porque no cuenta con suficientes bits en las entradas PIT para almacenar el tiempo de la
última referencia. En consecuencia, los manejadores de la memoria virtual deben utilizar al-
goritmos que puedan implementarse utilizando el escaso soporte de reemplazo de página pro-
porcionado por un sistema de cómputo. Estos algoritmos constituyen aproximaciones toscas al
reemplazo de página LRU o FIFO.

Aproximaciones LRU Muchos sistemas de cómputo proporcionan un solo bit de referen-


cia para recolectar información de referencia de página. Mientras toma una decisión de re-
emplazo de página, el manejador de la memoria virtual puede usar esta información para
encontrar una página a la que no se haya hecho referencia durante algún tiempo. Esta página
se reemplaza. Si el manejador de la memoria virtual encuentra que todas las páginas tienen sus
bits de referencia 1, restablece los bits de todas las páginas y arbitrariamente elige una página
para su reemplazo. Ésta es una aproximación burda al reemplazo de página LRU. Con este
método son posibles algunas mejoras evidentes. El bit de referencia no proporciona verdadera

07 MAQ. CAP. 06(F0694).indd 272 8/10/07 1:01:30 AM


6.3 Políticas de reemplazo de página 273

información LRU, de modo que el manejador de la memoria virtual no puede distinguir entre
páginas cuyo bit de referencia es 0. Para reducir el costo de reemplazo, el manejador de la me-
moria virtual puede verificar los bits modificados de todas las páginas cuyos bits de referencia
sean 0 y elegir una página que no haya sido modificada. En el estudio de caso del manejador
de la memoria virtual Unix en la sección 6.7 se describen algunas otras aproximaciones LRU
usadas en la práctica.

Aproximaciones FIFO En el reemplazo de página FIFO no es crucial el soporte del hard-


ware de paginamiento porque el manejador de la memoria virtual en sí puede mantener el orde-
namiento FIFO de las páginas. Puede mantener una cola donde las páginas aparezcan en el orden
en que fueron cargadas por última vez en la memoria física. Cuando ocurre un fallo de página,
la primera página en la cola se elimina de la memoria y su entrada se elimina de la cola. Al final
de la cola se agrega la identificación de una nueva página cargada.
En algunos manejadores de la memoria virtual se utiliza un refinamiento denominado al-
goritmo de segunda oportunidad. En este algoritmo se hace un esfuerzo tosco para distinguir
entre páginas a las que se ha accedido con frecuencia y páginas a las que no se ha accedido con
frecuencia, utilizando un solo bit de referencia. El bit de referencia de una página es restablecido
cuando la página se carga en la memoria. Se restablece cada vez que se accede a la página. En
un fallo de página, la página que encabeza la cola no se reemplaza si su bit de referencia está
establecido. En vez de lo anterior, su bit de referencia se restablece y su entrada se desplaza al
final de la cola. En efecto, se permite que la página permanezca en la memoria física, pero en
el futuro se le dará el mismo tratamiento que recibiría si se hubiera cargado en la memoria en el
instante de tiempo presente. La página que encabeza la cola modificada se considera entonces de
manera semejante para su reemplazo.
Así, las páginas a las que se hace referencia a menudo siguen recibiendo una nueva inyec-
ción de vida en la memoria física hasta que dejan de ser referidas con frecuencia. El manejador
de la memoria virtual concluye lo último cuando la página llega al primer lugar de la cola y su
bit de referencia es 0. Para implementar esta aproximación resulta conveniente utilizar una cola
circular. Un apuntador denominado head se dirige hacia el encabezado actual de la cola. Si
la página está localizada en la cabeza de la cola, se considera que se accede a ella con frecuencia,
su bit de referencia se establece y head simplemente avanza para indicar la siguiente página en
la cola; en caso contrario, la página en la cabeza de la cola se elimina de la memoria y se hace
avanzar al apuntador. Este algoritmo a veces se denomina algoritmo del reloj por razones evi-
dentes. (En el manejador de la memoria virtual Unix se utilizan refinamientos del algoritmo del
reloj. Consulte la sección 6.7.)

Ejemplo 6.8 En la figura 6.20 se ilustra la operación de los algoritmos FIFO y de segunda oportu-
nidad cuando alloc  3 para la cadena de referencia de página

cadena de referencia de página : 5, 4, 3, 2, 1, 4, 3, 5, 4, 3, 4, 1, 4, . . . (6.7)


cadena de referencia de tiempo : t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13 . . . (6.8)

Para implementar la política de segunda oportunidad se mantiene una cola circular de pági-
nas. El símbolo “ ” indica el encabezado de la cola. Un “.” después de un número de página
en la cola implica que el bit de referencia de la página es 1. La ejecución del proceso se inicia

07 MAQ. CAP. 06(F0694).indd 273 8/10/07 1:01:31 AM


274 CAPÍTULO 6 Memoria virtual

después de que la página 5 se carga en la memoria. Todas las referencias de página en el in-
tervalo de tiempo t2-t8 originan fallos de página. Hasta el instante de tiempo t3, en la memoria
hay marcos de página asignados al proceso, por lo que las nuevas páginas se cargan directamente.
Después de t3 un fallo de página conduce al reemplazo de la página que está en el encabezado de la
cola. Cuando se carga una página, su bit de referencia se inicializa en 0.
En t9, la referencia a la página 4 no conduce a un fallo de página porque ya está en la memoria.
Su bit de referencia se establece en 1. Las dos siguientes referencias, que son para las páginas 3 y
4, también tienen un efecto semejante. El apuntador de la cola no avanza porque el reemplazo de
página no se lleva a cabo. En t12, la referencia a la página 1 conduce a un fallo de página. Las pági-
nas 4 y 3, que aparecen en el encabezado de la cola, no se reemplazan porque sus bits de referencia
son 1. En vez de de ello, sus bits de referencia se establecen en 0 y el apuntador de la cola avanza.
El apuntador apunta entonces a la página 5, cuyo bit de referencia es 0. Por tanto, la página 5 se
reemplaza por la página 1. La página 4 está en la memoria cuando se hace referencia a ella en t13.
Así, se experimenta un fallo de página menos que en el caso del reemplazo de página FIFO.

FIFO 3 3 3 4 4 4 4 4 4 1 1
4 4 4 1 1 1 5 5 5 5 5 5
5 5 5 2 2 2 3 3 3 3 3 3 4
Referencia
de página → 5 4∗ 3∗ 2∗ 1∗ 4∗ 3∗ 5∗ 4 3 4 1∗ 4∗

Segunda Cola 3 3 3 4 4 4 4· 4· 4· 4 4·
oportunidad circular 4 4 4 1 1 1 5 5 5 5 1 1
5 5 5 2 2 2 3 3 3 3· 3· 3 3
Referencia
de página → 5 4∗ 3∗ 2∗ 1∗ 4∗ 3∗ 5∗ 4 3 4 1∗ 4

Figura 6.20 a) Desempeño del reemplazo de página FIFO y de segunda oportunidad.

Variaciones del algoritmo de segunda oportunidad El concepto de “segunda oportuni-


dad” puede utilizarse en cualquier escenario donde un manejador de la memoria virtual manten-
ga una lista de candidatos que se van a reemplazar. Un candidato a reemplazar es una página de
la que puede prescindirse debido a que no se ha hecho referencia a ella durante mucho tiempo.
Su entrada en la tabla de página de su proceso se cambia por “no está en la memoria”. Sin em-
bargo, no se elimina de la memoria: permanece ahí hasta que se sobrescribe en una nueva página.
Cuando ocurre un fallo de página, el manejador de la memoria virtual verifica si la página re-
querida está en la lista de candidatos a reemplazar. En caso afirmativo, la página es simplemente
“reconectada” al proceso y se elimina de la lista de candidatos. Esta acción evita una operación
de página adentro. Si la página requerida no está en la lista de candidatos, entonces el maneja-
dor de la memoria virtual la carga en el marco de página ocupado por la página que se encuentra
en el encabezado de la lista de candidatos.
El reemplazo de una página modificada requiere que una operación de página afuera pre-
ceda a una operación de página adentro para cargar la nueva página. Esto incurre en mayor
sobrecarga del reemplazo de página. También puede provocar un retraso en la carga de la nueva
página. Estos efectos pueden contrarrestarse utilizando el siguiente arreglo:

• El manejador de la memoria virtual siempre favorece a una página candidato que no ha


sido modificada. Elige una página candidato modificada sólo en caso de que no exista
una página candidato no modificada.

07 MAQ. CAP. 06(F0694).indd 274 8/10/07 1:01:31 AM


6.4 Asignación de memoria a un proceso 275

• Mientras realiza el reemplazo de páginas no modificadas, el manejador de la memoria


virtual también inicia operaciones de página afuera sobre las páginas candidato modifi-
cadas. Una vez que termina la operación de página afuera sobre una página modificada,
ésta se marca como “no modificada”. Debe ser considerada para reemplazo en el siguien-
te fallo de página.

Debido a la primera provisión, durante una operación de reemplazo de página es necesario efec-
tuar una operación de página afuera sólo si el manejador de la memoria virtual se ha quedado
sin páginas candidatos que no se hayan modificado. La segunda provisión intenta convertir una
página candidato modificada en una página candidato sin modificar antes de ser elegida para su
reemplazo. Así, las dos provisiones juntas reducen los retrasos provocados por operaciones de
página afuera que deben efectuarse durante el reemplazo de página. En el mejor de los casos,
estos retrasos deben ser eliminados por completo.

6.4 ASIGNACIÓN DE MEMORIA A UN PROCESO

En la sección 6.2 se describió cómo un exceso o un defecto de compromiso de memoria con los
procesos puede afectar de manera adversa el desempeño de un sistema. Un exceso de compro-
miso de memoria con los procesos conduce a un desempeño deficiente del proceso. Sin embargo,
el grado de multiprogramación en el sistema debe ser bajo, de modo que el traslape de E/S del
CPU debe ser deficiente y el desempeño del sistema debe ser afectado por ello. Un defecto de
compromiso de memoria con los procesos conduce a un desempeño deficiente de cada proceso,
lo cual da por resultado elevadas razones de fallo de página y un tráfico de página pesado en
el sistema. Esto se denomina hiperpaginación (consulte la definición 6.2). En esta situación se
observa un incremento en el paginamiento y sobrecarga de programación, elevadas páginas de
E/S y baja eficacia del CPU.
La zona de operación aconsejable de un proceso, que se muestra en la figura 6.7, evita el ex-
ceso o el defecto de compromiso de memoria con un proceso. Mantener cada proceso en la zona
de operación aconsejable protege tanto el buen desempeño del proceso como el buen desem-
peño del sistema. Sin embargo, no resulta claro cómo el manejador de la memoria virtual decide
el número correcto de marcos de página que debe asignar a cada proceso, es decir, el valor co-
rrecto de alloc para cada proceso.
Así, las cuestiones clave en la asignación de la memoria en un sistema con memoria virtual
son si se debe variar la asignación a un proceso y, en caso afirmativo, cómo hacerlo. A continua-
ción se analizan tres métodos representativos para determinar la asignación de memoria para los
procesos:

• Asignación fija, reemplazo local.


• Asignación variable, reemplazo global.
• Asignación variable, reemplazo local.

En el reemplazo local, un fallo de página es atendido mediante el reemplazo de una página


del mismo proceso, mientras en el reemplazo global la página a reemplazar puede pertenecer
a cualquier proceso en el sistema. Cuando un reemplazo es local, el desempeño de un proceso

07 MAQ. CAP. 06(F0694).indd 275 8/10/07 1:01:31 AM


276 CAPÍTULO 6 Memoria virtual

es independiente del comportamiento de otros procesos en el sistema. Esto no es así cuando el


reemplazo es global.
En asignación fija que utiliza reemplazo local, las decisiones de asignación de la memoria se
realizan estadísticamente. La memoria que se va a asignar a un proceso es determinada por algu-
nos criterios una vez que se inicia el proceso. En una política sencilla, la memoria asignada a un
proceso puede ser una fracción fija de su tamaño. El reemplazo de página siempre se lleva a cabo
localmente. El método es fácil de implementar. El costo del reemplazo de página es moderado,
ya que en una decisión de reemplazo de página sólo participan páginas del proceso en ejecución.
Sin embargo, el método adolece de todos los problemas relacionados con una decisión estática.
Un proceso puede experimentar defecto o exceso de compromiso de memoria. Este hecho podrá
afectar su propio desempeño y el del sistema. Éste puede encontrar hiperpaginación.
En asignación variable que utiliza reemplazo global, la política de reemplazo de página usa
la información de referencia de página para todos los procesos en el sistema a fin de elegir un
candidato para reemplazar. La asignación para el proceso que está ejecutándose actualmente se
incrementa si se reemplaza una página que pertenece a otro proceso; en caso contrario, permanece
sin cambio. Esta política de asignación enfrenta dos dificultades. La asignación para el proceso
que está ejecutándose puede crecer demasiado. Por ejemplo, si se utiliza la política de reemplazo
LRU, entonces el manejador de la memoria virtual debe reemplazar páginas de otros procesos
casi todo el tiempo porque sus últimas referencias deben preceder a las referencias de páginas
del proceso en ejecución. Esto puede conducir a un exceso de compromiso de la memoria con el
proceso en ejecución. Un proceso bloqueado perderá los marcos de página que tiene asignados,
con el resultado de que podrá enfrentar altas razones de fallo de página una vez que se programa
de nuevo. Sin embargo, la razón de fallo de página podrá disminuir en la medida en que se
ejecuta el proceso.
El método de asignación variable con reemplazo local varía la asignación de un proceso
para evitar tanto un exceso como un defecto de compromiso de la memoria. Con este método se
evita la hiperpaginación, así como una situación en la que un proceso bloqueado podría perder
sus marcos de página, de modo que un proceso no tendría que enfrentar elevadas razones de
fallo de página cada vez que se programa el proceso. Sin embargo, dicho método requiere un
manejador de la memoria virtual para determinar el valor correcto de alloc para un proceso en
cualquier momento. A continuación se describe un método para determinar un valor práctico
de alloc.

Modelo del conjunto de trabajo El concepto de conjunto de trabajo ayuda al manejador


de la memoria virtual a decidir cuántas y cuáles páginas de un proceso deben estar en la memoria
para obtener un desempeño aceptable del proceso. De un manejador de la memoria virtual que
usa el modelo del conjunto de trabajo se dice que utiliza un asignador de memoria de conjunto
de trabajo.

Definición 6.4 (Conjunto de trabajo) El conjunto de trabajo de un proceso es el conjunto


de páginas del proceso a las que se ha hecho referencia en las instrucciones previas del
proceso, donde es un parámetro del sistema.

Se dice que las instrucciones previas constituyen la ventana del conjunto de trabajo. Para
efectos de este análisis se introduce la siguiente notación:

07 MAQ. CAP. 06(F0694).indd 276 8/10/07 1:01:31 AM


6.4 Asignación de memoria a un proceso 277

WSi(t, ∆) : Conjunto de trabajo para el proceso proci en el instante t para el


tamaño de ventana
WSSi(t, ∆) : Tamaño del conjunto de trabajo para el proceso proci, es decir,
el número de páginas en WSi(t, ).

Observe que WSSi(t, )  porque a una página puede hacerse referencia más de una vez en
una ventana del conjunto de trabajo. (t, ) se omite cuando t y carecen de importancia o son
evidentes según el contexto.
Un asignador de memoria de un conjunto de trabajo mantiene siempre en la memoria el
conjunto de trabajo de un proceso. Así, en todo instante t, las páginas de proci que están inclui-
das en WSi(t, ) se encuentran en la memoria, y alloci  WSSi(t, ). Si lo anterior no es posible,
entonces el asignador establece alloci  0 y suspende proci. Hay dos razones por las cuales se
espera que este método proporcione un buen desempeño de un proceso. Primero, a partir del
principio de localidad de referencia, hay una alta probabilidad de que las páginas referidas por
un proceso ya estén en la memoria. Segundo, si el valor de se elige cuidadosamente, no hay
peligro de un defecto de compromiso de memoria a un proceso. Esta característica también evita
hiperpaginación en el sistema.
El tamaño del conjunto de trabajo de un proceso cambia dinámicamente, por lo que la
asignación de memoria para los procesos también cambia dinámicamente. Así, el asignador de
memoria del conjunto de trabajo debe modificar el número de procesos que hay en la memoria.
Por ejemplo, el grado de multiprogramación debe disminuirse si


kWSSk(t, )  sm

donde sm es el número total de marcos en la memoria y {prock} es el conjunto de procesos en


la memoria. El asignador de memoria del conjunto de trabajo elimina algunos procesos de la
unidad de memoria hasta que
kWSSk(t, )  sm.
El grado de multiprogramación debe aumentarse si
kWSSk(t, )  sm y existe un proceso
procg tal que

WSSg(t, )  (sm 
k WSSk (t, )).

después, a procg deben asignarse WSSg(t, ) marcos de página y su ejecución debe iniciarse o
reanudarse.
Las modificaciones en el grado de multiprogramación se implementan como sigue: el ma-
nejador de la memoria virtual mantiene dos puntos de información para cada proceso: alloci y
WSSi. Cuando es necesario reducir el grado de multiprogramación, el manejador de la memo-
ria virtual decide cuál proceso debe suspenderse. Considere que este proceso es proci. Luego,
el manejador de la memoria virtual efectúa una operación de página afuera para cada página
modificada de proci y cambia a free el estado de todos los marcos de página que ha asignado.
Después, alloci se establece en 0, aunque el valor de WSSi permanece sin cambio. Cuando es ne-
cesario incrementar el grado de multiprogramación y el manejador de la memoria virtual decide
reanudar la ejecución de proci, establece alloci  WSSi y asigna el número de marcos de página
indicado por WSSi. Entonces carga una página de proci. Ésta es la que contiene la siguiente ins-
trucción que se va a ejecutar. Las otras páginas se cargan cuando ocurre un fallo de página. Una

07 MAQ. CAP. 06(F0694).indd 277 8/10/07 1:01:32 AM


278 CAPÍTULO 6 Memoria virtual

alternativa sería cargar todas las páginas de WSi mientras se reanuda la ejecución de proci. Sin
embargo, este método podría conducir a una carga de páginas redundante porque tal vez ya no se
vuelva a hacer referencia a algunas páginas en WSi.
El desempeño de un asignador de memoria del conjunto de trabajo es sensible al valor de
. Si es demasiado grande, la memoria podrá contener algunas páginas sin probabilidad
de ser referidas. Esto podrá dar como resultado un exceso de compromiso de la memoria con
los procesos, así como forzar a que el manejador de la memoria virtual reduzca el grado de mul-
tiprogramación, afectando el desempeño del sistema. Si es demasiado pequeño, existe el peli-
gro de un defecto en el compromiso de la memoria con los procesos, llevando a un aumento en
la frecuencia en el fallo de página y a la posibilidad de hiperpaginación.

Implementación del asignador de memoria del conjunto de trabajo El uso de un asig-


nador de memoria del conjunto de trabajo adolece de una dificultad práctica. Resulta costoso
determinar WSi(t, ) y alloci en todo instante de tiempo t. Para resolver esta dificultad, un mane-
jador de la memoria virtual que utilice un asignador de memoria del conjunto de trabajo puede
determinar los conjuntos de trabajo de todos los procesos periódicamente, en vez de hacerlo en
cada instante. Los conjuntos de trabajo determinados al final de un intervalo se utilizan para
decidir los valores de alloc que se van a utilizar durante el siguiente intervalo de tiempo. Este
método se ilustra en el ejemplo 6.9.

Ejemplo 6.9 Un manejador de la memoria virtual dispone de 60 marcos de página para asignar a
procesos del usuario. Los conjuntos de trabajo de todos los procesos vuelven a calcularse en los ins-
tantes t j 100 , j 1, 2 . . . Luego del cálculo de los conjuntos de trabajo, el manejador de la memoria
virtual maneja cada proceso proci como sigue: establece alloci  WSSi si puede asignarle WSSi
marcos de página; en caso contrario, establece alloci  0 y elimina todas las páginas de proci que
están en la memoria. Para cada proceso, el valor de alloc asignado a t j 100 se mantiene constante
hasta que t j 1 100. El proceso de calcular los conjuntos de trabajo y determinar alloci para todos
los procesos se repite en t j 1 100 .
En la figura 6.21 se ilustra la operación del sistema. Muestra valores de alloci y WSSi para
todos los procesos proci en los instantes de tiempo t100 , t200 , t300 y t400 . En t100 Σi 1 3 WSSi = 52,
WSS4  10 y alloc4  0. Esto implica que 8 marcos de página están libres, aunque se ha suspendido
la ejecución de proc4 porque el tamaño de su conjunto de trabajo es 10 marcos de página. En t 200 ,
vuelven a calcularse los valores de WSSi, i  1, . . . , 3. El valor de WSSi se lleva desde t100 , ya que
proc4 no se ha ejecutado en el intervalo t100-t200 alloci, i  1, . . . , 3 entonces se les asignan nuevos
valores. Todavía no es posible intercambiar proc4 debido a falta de memoria, ya que cinco marcos de
página están libres y WSS4  10. En t300, proc4, se intercambia, aunque vuelve a intercambiarse
de nuevo en t400. Observe que la menor asignación para proc2 es 11 marcos de página y que la ma-
yor asignación es 25 marcos de página durante el intervalo t100-t400. Esta variación se lleva a cabo
para ajustar su asignación de memoria a su comportamiento reciente.
La dilatación y la contracción de alloc se llevan a cabo como sigue: en t200, el manejador de
la memoria virtual decide reducir alloc1 de 14 a 12 marcos de página. Debe aplicar una política
semejante a la política LRU para eliminar dos páginas de proc1. En t300, incrementa alloc1 hasta 14
marcos de página. Debe asignar dos marcos de página más a alloc1. Estos marcos de página deben
utilizarse cuando se presente un fallo de página durante la ejecución del proceso.

El manejador de la memoria virtual puede usar los bits de referencia proporcionados por el
hardware de paginamiento para determinar los conjuntos de trabajo. Los bits de referencia en
todas las páginas en la memoria pueden apagarse una vez que se determinan los conjuntos de

07 MAQ. CAP. 06(F0694).indd 278 8/10/07 1:01:32 AM


6.5 Páginas compartidas 279

t100 t200 t300 t400


WSS alloc WSS alloc WSS alloc WSS alloc
proc1 14 14 12 12 14 14 13 13
proc2 20 20 24 24 11 11 25 25
proc3 18 18 19 19 20 20 18 18
proc4 10 0 10 0 10 10 12 0

Figura 6.21 Operación de un asignador de memoria de un conjunto de trabajo.

trabajo. Esos bits se encienden de nuevo en la medida en que durante el siguiente intervalo se
haga referencia a estas páginas. Mientras lleva a cabo el reemplazo de página, el manejador de
la memoria virtual puede mantener la pista de las páginas reemplazadas cuyos bits de referencia
estaban encendidos. El conjunto de trabajo al final del siguiente intervalo consta de estas páginas
y de todas las páginas en la memoria cuyos bits de referencia están encendidos.
La implementación de los conjuntos de trabajo de esta forma enfrenta un problema. El
restablecimiento de los bits de referencia al final del intervalo puede interferir con las decisio-
nes de reemplazo de página. Si ocurre un fallo de página en un proceso poco después de que se
determinan los conjuntos de trabajo, la mayor parte de las páginas del proceso en la memoria
tendrán apagados sus bits de referencia, de modo que el manejador de la memoria virtual no
podrá distinguir entre estas páginas para efectos de reemplazo de página. Si algunos permanecen
bloqueados o no obtienen la oportunidad de ejecutarse a lo largo de todo un intervalo, entonces
sus asignaciones se reducirán innecesariamente. Este efecto hace difícil decidir sobre el tamaño
correcto de la ventana del conjunto de trabajo.
Una alternativa consiste en utilizar de manera individual una ventana del conjunto de tra-
bajo para cada proceso; sin embargo, así se complicará al manejador de la memoria virtual y
se aumentará su sobrecarga. Lo anterior tampoco resolverá la cuestión de interferencia con las
decisiones de reemplazo de página. Debido a estas razones, en realidad pocos SO utilizan asig-
nadores de memoria del conjunto de trabajo. No obstante, el concepto de conjunto de trabajo es
importante para comprender el comportamiento del fallo de página de los procesos en un sistema
con memoria virtual.

6.5 PÁGINAS COMPARTIDAS

Los programas compartidos se analizaron en la sección 5.11.3.2. La compartición estática resul-


ta de la unión estática realizada por un ligador o cargador antes de que inicie la ejecución de un
programa (consulte la sección 5.11.3.2). Con la unión estática, si dos procesos A y B comparten
estáticamente el programa C, entonces C se incluye en el código tanto de A como de B. Sea la
0ésima página de C que se transforma en la página i del proceso A (consulte la figura 6.22a)).
Si la instrucción sumar en la página 1 del programa C tiene un operando en la página 4 de C,
entonces la instrucción debe relocalizarse para utilizar una dirección ubicada en la página i 
4ésima del proceso A. Si la página 0ésima de C se vuelve la página j en el proceso B, entonces la
instrucción sumar debe relocalizarse a fin de utilizar una dirección ubicada en la página j  4ésima
del proceso B. Así, cada página de un programa tiene dos copias en los espacios de dirección de
A y B. Estas copias pueden existir en la memoria al mismo tiempo si los procesos A y B están en
operación de manera simultánea.

07 MAQ. CAP. 06(F0694).indd 279 8/10/07 1:01:32 AM


280 CAPÍTULO 6 Memoria virtual

Página Proceso A Página Proceso A


#0 #0
Programa i
i+1 Add (i+4,12)
C
Página Programa C
Página Proceso B Página Proceso B #0
#0 #0
Programa j
j+1 Add ( j+4,12)
C

a) b)

Figura 6.22 Compartición del programa C por los procesos A y B: a) unión estática y b) unión dinámica.

La unión dinámica (consulte la sección 5.2) puede utilizarse para conservar memoria me-
diante la unión de la misma copia de un programa o datos a varios procesos. En este caso, el
programa o datos que se van a compartir deben retener su identidad (consulte la figura 6.22b))
y ligarse dinámicamente a varios programas por medio de un ligador dinámico invocado por
el manejador de la memoria virtual. Esto se logra como sigue: el proceso A hace una llamada del
sistema para unir el programa C (o algunos datos) a una dirección lógica específica en su espacio
de direcciones lógicas. Considere que esta dirección está alineada sobre el inicio de la página i.
Luego, el kernel invoca al manejador de la memoria virtual, que crea entradas en la tabla de pá-
gina de A para las páginas del programa C y establece una bandera en cada entrada de la tabla de
página para indicar que se trata de una página compartida. Después invoca al ligador dinámico,
que cambia la instrucción Add del programa C a Add (i+4, 12). Cuando falla una referencia a
una dirección en el programa C, el manejador de la memoria virtual verifica si la página reque-
rida de C ya se ha cargado en la memoria. En caso afirmativo, coloca el número del marco de
página de la página en la entrada relevante de la tabla de página de A. Acciones semejantes se
realizan cuando el proceso B une al programa C la dirección inicial de la página i. En la figura
6.23 se muestra el arreglo establecido por estas uniones.
Para que funcione la unión dinámica de programas deben cumplirse dos condiciones. El
programa que se va a compartir debe estar codificado como un programa reentrante, de modo
que varios programas puedan invocarlo al mismo tiempo (consulte la sección 5.11.3.2). El pro-
grama también debe estar limitado a direcciones lógicas idénticas en todo programa que lo ha
compartido. Debe asegurarse que una instrucción como Add (i+4, 12) en la página i  1 de la
figura 6.23 funcione correctamente en cada uno de los procesos. Estas condiciones son inne-
cesarias cuando los datos están limitados dinámicamente a varios procesos; sin embargo, los
procesos compartidos deben sincronizar sus accesos a los datos compartidos a fin de evitar con-
diciones de competencia.
Cuando la compartición de páginas se implementa al hacer que las entradas de las tablas de
página de los procesos compartidos apunten hacia el mismo marco de página, la información
de referencia de página para páginas compartidas se dispersa a través de muchas tablas de página.
El algoritmo de reemplazo de página debe reunir toda esta información a fin de obtener una
representación correcta sobre las referencias de páginas compartidas. Esto es más bien engorro-

07 MAQ. CAP. 06(F0694).indd 280 8/10/07 1:01:33 AM


6.5 Páginas compartidas 281

Tabla de
Página Proceso A página de A
# Memoria

Páginas del i i
programa C i+1 i+1

Tabla de
Página Proceso B página de B Add (i+4,12)
#
Páginas del i i
programa C i+1 i+1

Figura 6.23 Compartición dinámica del programa C por los procesos A y B.

so. Un mejor método será mantener la información concerniente a las páginas compartidas en
una tabla de páginas compartidas por separado y recolectar información sobre la referencia de
páginas para páginas compartidas en las entradas de página en esta tabla. Este arreglo también
permite aplicar un criterio de reemplazo de página diferente al que se utiliza para mantener pági-
nas compartidas. En la sección 6.9 se describe una técnica relacionada que se usa en los sistemas
operativos Windows.

6.5.1 Copia durante la escritura

La característica copia durante la escritura se utiliza para conservar memoria cuando los datos en
páginas compartidas pueden modificarse, aunque los valores modificados deben ser privativos
de un proceso. Cuando los procesos A y B unen dinámicamente tales datos, el manejador de la
memoria virtual establece el arreglo que se muestra en la figura 6.24a), que es semejante al arre-
glo de la figura 6.23, excepto porque las entradas de la tabla de página de las páginas de datos
contienen banderas de bits “c” para indicar que la característica copia durante la escritura debe
utilizarse cuando se modifica cualesquiera de las páginas. Si después el proceso A intenta modi-
ficar la página k, entonces la MMU provoca un fallo de página al observar que la página k es una
página de copia durante la escritura. Luego, el manejador de la memoria virtual hace una copia
privada de la página k para el proceso A, modifica el número de marco de página almacenado
en la entrada de la página k en la tabla de página de A como corresponde y también apaga el bit
de la copia durante la escritura en esta entrada (figura 6.24b)). Otros procesos que comparten la
página k continúan utilizando la copia original de la página k en la memoria; cada una de ellas
también obtiene una copia privada de la página en caso de modificarla.
En sistemas Unix, un proceso hijo empieza con el código y los datos del proceso padre; sin
embargo, puede modificar los datos, y los valores modificados son de su exclusividad. El uso de
la característica de copia durante la escritura para los espacios de direcciones completos de los
procesos padre e hijo evita copiar las páginas de código porque no están modificadas; sólo las
páginas de datos pueden copiarse si lo están.

07 MAQ. CAP. 06(F0694).indd 281 8/10/07 1:01:33 AM


282 CAPÍTULO 6 Memoria virtual

Tabla de Tabla de
página de A Memoria página de A Memoria

k c k
k+1 c k+1 c

Tabla de Tabla de
página de B página de B

k c k c
k+1 c k+1 c

a) b)

Figura 6.24 Implementación de copia durante la escritura: a) antes y b) después de que el proceso A modifica la página k.

6.6 ARCHIVOS MAPEADOS EN LA MEMORIA

El mapeo en la memoria de un archivo por un proceso une ese archivo con una parte del espa-
cio de direcciones lógicas del proceso. Esta unión se lleva a cabo cuando el proceso hace una
llamada de sistema memory map (mapeo en la memoria); lo anterior es semejante a la unión
dinámica de programas y datos que se analizó antes en la sección 6.5. Después del mapeo en
la memoria de un archivo, el proceso se refiere a los datos en el archivo como si fuesen datos
localizados en páginas de su propio espacio de direcciones, y el manejador de la memoria virtual
se coordina con el sistema de archivos para cargar por demanda en la memoria partes del archivo
del tamaño de una página. Cuando el proceso actualiza los datos contenidos en tales páginas, los
bits modificados de las páginas se establecen en on, pero los datos no se escriben de inmediato en
el archivo; las páginas de datos sucias se escriben en el archivo cuando van a liberarse los marcos
de página que las contienen. Cuando el proceso hace una llamada memory unmap, el maneja-
dor de la memoria virtual borra el archivo del espacio de direcciones lógicas del proceso. En este
instante se escriben las otras páginas sucias que aún contengan los datos del archivo.
En la figura 6.25 se muestra el arreglo utilizado para mapeo en la memoria del archivo info
por el proceso A. Observe que las operaciones de página adentro y de página afuera sobre estas
páginas del proceso A que no pertenecen al archivo info implican el espacio de intercambio
del proceso y se llevan a cabo por el manejador de la memoria virtual. La lectura y escritura de
datos del archivo info se realizan por medio del sistema de archivos del sistema junto con el
manejador de la memoria virtual. Si varios procesos mapean en la memoria el mismo archivo,
se tiene un arreglo semejante al que se muestra en la figura 6.23; estos procesos comparten efec-
tivamente el archivo mapeado en la memoria.
En la tabla 6.5 se resumen las ventajas del mapeo de archivos en la memoria. El mapeo en
la memoria hace accesibles los registros de los archivos utilizando el hardware de la memoria
virtual. Esto es inherentemente más eficaz. Un proceso puede utilizar mapeo en la memoria para
reducir el número de operaciones de copia de memoria a memoria como sigue: cuando un pro-
ceso accede a algunos datos en un archivo de entrada que no se ha mapeado en la memoria, el

07 MAQ. CAP. 06(F0694).indd 282 8/10/07 1:01:33 AM


6.6 Archivos mapeados en la memoria 283

Tabla de
Página Proceso A página de A
# Memoria
Archivo
info i i Espacio de
mapeado i+1 i+1
intercambio de A
en la
memoria
Archivo
info
Sistema de
archivos

Figura 6.25 Mapeo en la memoria del archivo info por el proceso A.

Tabla 6.5 Ventajas de los archivos mapeados en la memoria

Ventaja Descripción
Archivos de datos El acceso a archivos de datos se busca como acceso a páginas,
como páginas lo cual es inherentemente más eficaz debido al hardware de la
memoria virtual.
Menos copiado de Los archivos de datos son una parte del espacio de direcciones
memoria a memoria del proceso. El proceso puede aprovechar esta característica me-
diante el acceso in situ a los datos, es decir, donde existe en el
espacio de direcciones lógicas, más que mediante su copiado en
otra parte de su espacio de direcciones, como se hace durante el
procesamiento normal de archivos.
Menos operaciones Los archivos de datos se leen o escriben página por página, en
de escritura/lectura vez de en cada operación del archivo, y así una sola operación de
lectura/escritura puede ser suficiente para realizar varias opera-
ciones de archivos.
Prebúsqueda de Para lecturas secuenciales, los datos ya estarán en la memoria si
archivos la página que contiene los datos fue leída durante una operación
previa de archivo.
Eficaz acceso a los Los archivos de datos pueden accederse de manera eficaz sin to-
datos mar en cuenta la organización del archivo.

sistema de archivos copia primero el registro en un área de la memoria utilizada como memoria
intermedia o caché de disco (consulte el capítulo 12). Luego, el proceso copia los datos de la me-
moria intermedia o del caché de disco en su propio espacio de direcciones (es decir, en algunas
variables) para acceder a ellos. Así, se efectúan una operación de copia del disco a la memoria
y otra de la memoria a la memoria. Cuando un archivo se mapea en la memoria, la operación de
copia de la memoria a la memoria efectuada de la memoria intermedia al espacio de direcciones
del proceso ya no es necesaria porque los datos ya forman parte del espacio de direcciones del
proceso. De manera semejante, cuando se modifican los datos del archivo se realizan menos

07 MAQ. CAP. 06(F0694).indd 283 8/10/07 1:01:34 AM


284 CAPÍTULO 6 Memoria virtual

operaciones de copia. Los datos localizados en una página que fue leída durante una operación
de archivo previa puede accederse sin E/S de disco; de esta forma, el mapeo en la memoria redu-
ce el número de operaciones de E/S que se realizan durante el procesamiento de archivos.
La última ventaja, el acceso eficaz a los datos en un archivo independientemente de su
organización, surge del hecho de que a los datos en un archivo se accede utilizando el hardware
de la memoria virtual. Por tanto, es posible acceder a cualquier parte de los datos en forma igual-
mente eficaz. Si es necesario acceder a algunos datos en la parte de en medio de un gran archivo
secuencial, sólo se carga y accede a la página que contiene los datos.

6.7 MEMORIA VIRTUAL UNIX

Unix se ha utilizado en sistemas de cómputo con diversos diseños de hardware; de ahí que se
ha usado una gama de esquemas ingeniosos para aprovechar las características de hardware de
paginamiento de una máquina huésped. En esta sección se describirán algunas características
comunes de la memoria virtual Unix, así como técnicas interesantes utilizadas en diferentes
versiones Unix. Su objetivo es proporcionar una visión de las cuestiones prácticas en implemen-
taciones de memoria virtual, más que estudiar en detalle el manejador de la memoria virtual de
cualquier versión Unix. Siempre que fue posible, la terminología Unix se sustituyó por termino-
logía utilizada en secciones previas de este capítulo.

Espacio de direcciones lógicas y espacio de intercambio La tabla de página de un proce-


so distingue tres tipos de páginas: residente, no accedida e intercambiada. Una página residente
existe en la memoria; debe haber sido cargada por demanda en algún fallo de página. A una
página no accedida no se ha accedido ni siquiera una vez durante la ejecución del proceso; por
tanto, jamás ha sido cargada en la memoria. Puede cargarse cuando su uso en alguna instrucción
conduce a un fallo de página. Como se describirá más tarde, las acciones para manejar el fallo
de página para esta página dependen de si se trata de una página de texto o de una página de
datos. Una página intercambiada existe en el espacio de intercambio. Hacer una referencia a ella
producirá un fallo de página, por lo que se cargará de vuelta en la memoria desde su ubicación
en el espacio de intercambio.
Una página no accedida puede ser de texto o de datos. Una página de texto se carga desde un
archivo ejecutable existente en el sistema de archivos. Localizar tal página en el sistema de ar-
chivos puede requerir la lectura de varios bloques de disco en el ínodo y en la tabla de asignación
de archivos. Para evitar lo anterior, el manejador de la memoria virtual mantiene informa-
ción sobre tales páginas en una tabla por separado y usa esta información cuando es necesario
cargar una página. Como se describirá más tarde, el manejador de la memoria virtual 4.3BSD
mantiene esta información en la entrada de la tabla de página en sí. Esta información se sobres-
cribe por el número del marco de página una vez que se carga la página, de modo que no está
disponible si ésta se elimina de la memoria, y debe volver a cargarse. Una página de texto puede
eliminarse de la memoria si no se utiliza durante algún tiempo y puede volver a cargarse en un
fallo de página subsecuente, por lo que el Unix 4.3BSD escribe una página de texto en el espacio
de intercambio cuando se elimina de la memoria por primera vez, y la carga desde el espacio de
intercambio por demanda. Una página de datos se denomina página de región cero; se llena con
ceros cuando su primera utilización conduce a un fallo de página. A partir de ese momento, se
convierte en una página residente o en una página intercambiada.

07 MAQ. CAP. 06(F0694).indd 284 8/10/07 1:01:35 AM


6.7 Memoria virtual Unix 285

Una página de texto existe en la memoria aun cuando esté marcada como no residente en
su entrada de tabla de página. Esta situación se presenta si algún otro proceso está utilizando
la página (o la ha utilizado). Una optimización evidente es posible en este caso cuando ocurre
un fallo de página para una página de texto, de modo que el manejador de la memoria virtual
primero comprueba si la página ya está en la memoria. En caso afirmativo, simplemente colo-
ca la información del marco de página en la entrada de la tabla de página de la página y marca
a ésta como residente. Esta acción evita una operación de página adentro y también conserva
memoria.
Para conservar espacio de disco, se hace un intento por asignar tan poco espacio de in-
tercambio como sea posible. Para empezar, suficiente espacio de intercambio se asigna para
dar cabida a la pila del usuario y al área de datos. A partir de entonces, el espacio de inter-
cambio se asigna en trozos más grandes siempre que la pila o el área de datos aumenten de
tamaño. Este método adolece del problema de que el espacio de intercambio en el sistema
puede agotarse cuando crece el área de datos de un proceso. Un proceso así debe suspenderse
o cancelarse durante su ejecución. Sin embargo, esta situación no puede surgir en un punto
arbitrario en la ejecución de un proceso; sólo puede aparecer cuando crece el espacio de di-
recciones de un proceso.

Copia durante la escritura El manejador de la memoria virtual Unix utiliza el principio


de copia durante la escritura para conservar memoria y espacio de intercambio cuando un
proceso crea un proceso hijo a través de la llamada fork. La semántica de fork requiere que
el proceso hijo obtenga una copia del espacio de direcciones del proceso padre. Esta semántica
puede implementarse asignando distintas áreas de memoria y espacio de intercambio al proce-
so hijo. Sin embargo, los procesos hijo suelen descartar la copia del espacio de direcciones de
su proceso padre utilizando la llamada exec para cargar algún otro programa para su ejecución.
En cualquier caso, un proceso hijo puede no querer modificar mucho de los datos del padre, de
modo que tanto la memoria como el espacio de intercambio pueden optimizarse al reproducir
de manera selectiva partes del espacio de datos, más que todo el espacio entero de datos. El
principio de copia durante la escritura obliga a la creación de una copia distinta de la página
de datos para su uso por el proceso hijo sólo cuando éste intenta modificar alguna parte de la
página.
La copia durante la escritura se implementa como sigue: cuando un proceso es bifurcado,
la cuenta de referencia de todas las páginas de datos en el espacio de direcciones del proceso
padre se incrementa en 1. Los bits en el acceso que privilegian al campo de la entrada de la
tabla de página de una página de datos se establecen de modo que hagan a la página sólo de
lectura. Cualquier intento por modificar la página provoca un fallo de protección. El maneja-
dor de la memoria virtual percibe que esta situación es un intento por modificar una página de
datos compartida por un proceso y su hijo. Luego reduce la cuenta de referencia de la página,
hace una copia de esta página y asigna los privilegios de lectura y escritura a esta copia al esta-
blecer los bits idóneos en su entrada de la tabla de página. Estas copias sólo se hacen a partir de
páginas de datos modificadas.

Uso eficaz de la tabla de página y del hardware de paginamiento Vivimos en un mun-


do imperfecto, aunque tratamos de aprovecharlo al máximo. Lo anterior es más evidente en el
caso del software de la memoria virtual. La mayor parte de los sistemas de cómputo propor-
cionan un soporte inadecuado para una administración aceptable de la memoria virtual y se
deja que el manejador de la memoria virtual haga impráctica y rentable la memoria virtual. A

07 MAQ. CAP. 06(F0694).indd 285 8/10/07 1:01:35 AM


286 CAPÍTULO 6 Memoria virtual

continuación se analizan algunas técnicas interesantes que se usan en implementaciones de la


memoria virtual en Unix para superar las deficiencias en el soporte de hardware para reempla-
zo de página.
Si una página no existe en la memoria, entonces el bit válido de su entrada de la tabla de
página está “off”. Los bits en otros campos de tal entrada, como el campo reference o el cam-
po page frame, no contienen ninguna información útil. Así, estos bits pueden utilizarse para
otros propósitos. La Unix 4.3BSD usa estos bits para guardar direcciones del bloque de disco en
el sistema de archivos que contiene la página siguiente. VAX 11 no proporciona un bit de refe-
rencia para reunir información de referencia de página. Su ausencia es compensada mediante el
uso del bit válido de manera interesante. Periódicamente, el bit válido de una página se apaga,
incluso si ésta existe en la memoria. La siguiente referencia a la página provoca un fallo de
página. Sin embargo, el manejador de la memoria virtual sabe que éste no es un fallo de página
genuino, de modo que restablece el bit como válido y regresa a la ejecución del proceso. En
efecto, el bit válido se usa como bit de referencia.
En sistemas de cómputo que no proporcionan suficiente información relacionada con la úl-
tima utilización de una página, el bit de referencia se manipula para lograr un efecto equivalente.
Este enfoque, denominado método de la no utilizada recientemente, es como sigue: el mane-
jador de la memoria virtual apaga los bits de referencia de las páginas. Tiempo después, el bit
de referencia de la página vuelve a revisarse. Debe encontrarse que es 1 sólo si a la página se hizo
referencia después de que se apagó su bit de referencia, es decir, sólo si se ha hecho referencia re-
ciente a la página. A una página cuyo bit de referencia sigue apagado no se le ha hecho referencia
desde que el bit fue apagado. Una página así es un candidato para reemplazo.
Variantes de este tema se han utilizado en diferentes versiones de Unix. Como se describirá
más tarde, el manejador de la memoria virtual Unix mantiene una lista libre de páginas e in-
tenta mantener cierto número de páginas inactivas siempre en la lista libre. Cuando requiere
cargar una página, sobrescribe la primera página en la lista libre con la nueva página. Cuando
necesita agregar más páginas a la lista libre, usa el bit de referencia para decidir cuál página está
inactiva. El manejador de la memoria virtual explora todas las páginas en la memoria utilizando
uno o dos apuntadores. Estos algoritmos se denominan algoritmos del reloj debido a la forma en
que utilizan los apuntadores. La página a la que se dirige un apuntador se examina para efectuar
una acción apropiada y el apuntador avanza para orientarse hacia la página siguiente. Después
de examinar la última página, el apuntador se establece para dirigirse nuevamente a la primera
página. De esta forma, el apuntador se mueve sobre las páginas de la misma manera en que el
minutero o el segundero de un reloj se desplazan sobre todas las posiciones marcadas en la ca-
rátula de un reloj.
En el algoritmo del reloj con una manecilla, una exploración consta de dos partes. En el
primer paso, el manejador de la memoria virtual simplemente establece el bit de referencia de
la página a la que está apuntando el apuntador. En el segundo paso, agrega páginas cuyos bits
de referencia siguen estando apagados para la lista libre. En el algoritmo del reloj con dos ma-
necillas se mantienen dos apuntadores. Uno se utiliza para restablecer los bits de referencia y
el otro para verificarlos. Ambos apuntadores se incrementan de manera simultánea. La página
a la que apunta el apuntador de verificación se agrega a la lista libre si su bit de referencia está
apagado.

Daemon de pageout Para facilitar la ejecución de operaciones rápidas de página adentro,


el manejador de la memoria virtual Unix mantiene una lista de marcos de página libres e intenta

07 MAQ. CAP. 06(F0694).indd 286 8/10/07 1:01:35 AM


6.7 Memoria virtual Unix 287

mantener por lo menos 5 por ciento del total de marcos de página en esta lista durante todo el
tiempo. Para este efecto se crea un daemon denominado daemon de pageout (proceso 2). Éste
es activado en cualquier momento en que el número de marcos de página libres cae por abajo de
5 por ciento. El daemon intenta añadir páginas a la lista libre y se instala a sí mismo en estado
dormido cuando la lista libre contiene más de 5 por ciento de marcos de página libres. Algunas
versiones en Unix utilizan dos umbrales: uno alto y uno bajo, en vez de un solo umbral a 5 por
ciento. El daemon pasa al estado dormido cuando encuentra que el número de páginas en la lista
libre excede el umbral alto. Es activado cuando este número desciende por abajo del umbral
bajo. Este arreglo evita la activación y desactivación frecuente del daemon.
Las páginas en la memoria pueden dividirse en dos grandes categorías: las que están fijas
en la memoria y las que no lo están. Un proceso solicita la fijación de algunas páginas en la
memoria para reducir las razones de fallo de página y mejorar su desempeño de ejecución. El
sistema permite que un proceso fije sólo ciertas fracciones de sus páginas de esta manera. Éstas
no pueden eliminarse de la unidad de memoria hasta que quedan no fijas por el proceso. De ma-
nera interesante, en Unix no hay fijación de páginas E/S porque las operaciones se realizan entre
un bloque de disco y un bloque en el caché de la memoria intermedia, en vez de hacerlo entre un
bloque de disco y el espacio de direcciones de un proceso.
El manejador de la memoria virtual divide las páginas que no están fijas en la memoria en
páginas activas —es decir, páginas que están en uso activo por un proceso— y páginas inactivas
—es decir, páginas a las que no se ha hecho referencia en el pasado reciente—. El manejador
de la memoria virtual mantiene dos listas: la activa y la inactiva. Ambas son operadas como
colas. Una página se agrega a la lista activa cuando se vuelve activa, y a la inactiva cuando
es considerada para volverse inactiva. Así, la página menos activada recientemente encabeza
la lista activa y la página inactiva más antigua encabeza la lista inactiva. Una página se mue-
ve de la lista inactiva a la lista activa cuando se hace referencia a ella. El daemon de pageout
intenta mantener en la lista inactiva cierto número de páginas, calculadas como una fracción
del total de páginas residentes. Si llega al final de la lista inactiva mientras agrega marcos de
página a la lista activa, verifica si el número total de páginas en la lista inactiva es menor que
el esperado. En caso afirmativo, transfiere un número suficiente de páginas de la lista activa a
la lista inactiva.
El daemon de pageout es activado cuando el número de marcos de páginas libres cae por
abajo del umbral bajo mientras maneja un fallo de página. El daemon libera marcos de página
en el orden siguiente: marcos de página que contienen páginas de procesos inactivos, marcos
de página que contienen páginas de procesos activos y marcos de página que contienen páginas
activas de procesos activos. El daemon encuentra procesos inactivos, en caso de haberlos, y
los intercambia. Vuelve a dormir si el número de marcos de página libres excede entonces el
umbral alto.
Si el número de marcos de páginas libres después del intercambio de procesos inactivos
sigue estando por abajo del umbral bajo, el daemon de pageout explora la lista inactiva y decide si
debe añadir marcos de página ocupados por páginas inactivas a la lista libre y cuándo hacerlo.
Un marco de página que contiene una página inactiva se agrega a la lista libre directamente si
a la página no se ha hecho referencia y no es sucia. Si es sucia y no ha sido intercambiada, enton-
ces el daemon de pageout inicia una operación de página afuera sobre la página y procede a exa-
minar la siguiente página inactiva. Si una página ha sido intercambiada, el daemon simplemente
la omite. El bit modify es restablecido una vez que termina su operación de página afuera. Los
marcos de página que contienen estas páginas deben agregarse a la lista libre en algún instante

07 MAQ. CAP. 06(F0694).indd 287 8/10/07 1:01:35 AM


288 CAPÍTULO 6 Memoria virtual

futuro cuando el daemon los examine en un paso subsecuente y encuentre que su operación de
página afuera ha terminado. El daemon activa al intercambiador si no es capaz de agregar a la
lista libre un número suficiente de marcos de página. El intercambiador intercambia uno o más
procesos activos para liberar un número suficiente de marcos de página.
A fin de agilizar el tráfico de páginas, el manejador de la memoria virtual escribe páginas
sucias en el espacio de intercambio en grupos. Cuando el daemon de pageout encuentra una
página sucia durante su exploración, examina páginas adyacentes para verificar si son sucias.
En caso afirmativo, un grupo de páginas sucias se escribe fuera del disco en una sola operación
de E/S. Otra optimización concierne a operaciones redundantes de página adentro. Cuando un
marco de página fi ocupado por alguna página limpia pi se agrega a la lista libre, el bit válido de
la entrada de la página de pi se establece en 0. Sin embargo, en la página no se sobrescribe
de inmediato al cargar otra página en el marco de página. Esto podrá ocurrir en un momento
futuro cuando su entrada encabece la lista libre y se asigne a algún proceso. La siguiente re-
ferencia a pi podrá provocar un fallo de página, ya que el bit válido en su entrada de tabla de
página se ha establecido en 0. Si todavía existe en fi, es decir, si fi sigue estando en la lista libre,
entonces simplemente puede ser sacado de ella y ser “reconectado” en el espacio de direcciones
lógicas del proceso. Esto ahorra una operación de página adentro y retrasos subsecuentes del
proceso de fallo de página.

Intercambio El manejador de la memoria virtual Unix no utiliza un asignador de me-


moria del conjunto de trabajo debido a una elevada sobrecarga de un asignador así. En vez
de lo anterior, se enfoca en mantener en la memoria las páginas necesarias. Un proceso se
intercambia si ninguna de sus páginas necesarias puede mantenerse en la memoria y si en el
sistema existen condiciones semejantes a la hiperpaginación. Un proceso inactivo, es decir,
un proceso que ha estado bloqueado durante mucho tiempo, también puede ser intercambiado
a fin de mantener un número suficiente de marcos de página libres. Cuando se presenta esta
situación y se hace necesario un intercambio, se activa el intercambiador, que siempre es el
proceso 0 en el sistema. El intercambiador encuentra e intercambia procesos inactivos. Si con
esto no se libera suficiente memoria, entonces es activado de nuevo por el daemon de pageout.
Esta vez intercambia los procesos que han sido residentes la mayor parte del tiempo. Cuando
en el sistema hay un proceso de intercambio, el intercambiador verifica de manera periódica
si hay suficiente memoria para intercambiar algunos procesos. Una prioridad del intercambio
—que es una función de cuando fue intercambiado el proceso— se utiliza para estos fines.
Esta función asegura que ningún proceso permanezca intercambiado indefinidamente. En el
4.3BSD, un proceso es intercambiado sólo si puede asignarse tanta memoria como la que
tenía cuando fue intercambiado. En el 4.4BSD se ha relajado este requerimiento; un proceso
se intercambia si es posible asignarle suficiente memoria para que quepa en su estructura de
usuario y pila de kernel.

6.8 MEMORIA VIRTUAL LINUX

Linux utiliza un tamaño de página de 4 K bytes. En arquitecturas de 64 bits, usa una tabla de
página de tres niveles (consulte la sección 6.2.6): el directorio global de la página, el directorio

07 MAQ. CAP. 06(F0694).indd 288 8/10/07 1:01:35 AM


6.8 Memoria virtual Linux 289

de en medio y la tabla de página. En consecuencia, una dirección lógica consta de cuatro partes,
tres de las cuales son para los tres niveles y la cuarta es el número de byte dentro de una página.
Linux utiliza un arreglo interesante para eliminar operaciones de página adentro para pági-
nas que previamente fueron cargadas en la memoria, aunque fueron marcadas para su elimina-
ción. Esto se logra utilizando los siguientes estados para marcos de página: un marco de página
libre es uno que no ha sido asignado a un proceso, mientras un marco de página activa es uno que
está en uso por un proceso al que ha sido asignado. Un marco de página sucia inactiva fue mo-
dificado por el proceso al que fue asignado aunque ya no está en uso por el proceso. Una página
inactiva lavada es una que era sucia inactiva y que por tanto está siendo escrita fuera del disco.
Una página inactiva lavada se convierte en inactiva limpia cuando su contenido se copia en el
disco. Si una página de un proceso falla por una página que está en un marco de página marcada
como inactiva lavada, el marco de página vuelve a asignarse al proceso y la página simplemente
se marca como presente en la memoria. Si la página se encuentra en un marco de página marcada
como inactiva lavada, estas acciones se llevan a cabo cuando termina su operación del disco.
Además de ahorrar operaciones de disco, este arreglo también evita el acceso a una copia pasa-
da de una página. Una página inactiva limpia también puede ser asignada directamente a otro
proceso.
El reemplazo de página en Linux se basa en el algoritmo del reloj. El kernel intenta mante-
ner un número suficiente de marcos de página libres todo el tiempo, de modo que los fallos de
página puedan ser atendidos rápidamente utilizando uno de los tres marcos de página. Usa dos
listas denominadas lista activa y lista inactiva, y mantiene el tamaño de la lista activa hasta
dos tercios del tamaño de la lista inactiva. Cuando el número de marcos de página libres des-
ciende por debajo de un umbral inferior, ejecuta un ciclo hasta que se liberan algunos marcos
de página. En este ciclo, examina el marco de página al final de la lista inactiva. Si se establece
su bit de referencia, restablece el bit y mueve el marco de página al principio de la lista; en caso
contrario, libera el marco de página. Cuando es necesario mantener el balance entre las listas ac-
tiva e inactiva, procesa unos cuantos marcos de página desde el final de la lista activa de manera
semejante y los mueve al principio de la lista activa o al inicio de la lista inactiva con sus bits de
referencia encendidos. Un marco de página es desplazado de la lista inactiva a la lista activa si
un proceso ha hecho referencia a dicho marco de página.
Linux utiliza un asignador acompañante para asignar marcos de página a los procesos (con-
sulte la sección 5.4.1). Este método facilita llevar a cabo operaciones de E/S a través de buses
DMA más antiguos en lugar de usar direcciones físicas, ya que tales operaciones de E/S requie-
ren que la memoria sea asignada de manera contigua (consulte la sección 6.2.4).
El espacio de direcciones lógicas de un proceso puede constar de varias regiones de me-
moria virtual; cada una puede poseer características diferentes y se maneja utilizando políticas
por separado para carga y reemplazo de páginas. Una página en una región de memoria cero
llena se llena de ceros en su primera utilización. Una región respaldada con archivos facilita el
mapeo en la memoria de archivos. Las entradas en la tabla de página de sus páginas apuntan a las
memorias intermedias de disco utilizadas por el sistema de archivos. De esta manera, cualquier
actualización en una página de dicha región se refleja de inmediato en el archivo y es visible para
usuarios simultáneos del archivo. Una región de memoria privada se maneja en forma diferente.
Cuando un nuevo proceso se bifurca, al proceso hijo se le proporciona una copia de la tabla de
página del padre. En ese instante, a las páginas de una memoria privada se les proporciona un
estado de copia durante la escritura. Cuando un proceso modifica esta página, se le hace una
copia de la página.

07 MAQ. CAP. 06(F0694).indd 289 8/10/07 1:01:35 AM


290 CAPÍTULO 6 Memoria virtual

6.9 MEMORIA VIRTUAL EN WINDOWS

Windows opera en diferentes arquitecturas. Admite direcciones lógicas de 32 y 64 bits. El espa-


cio de direcciones de un proceso es 2 o 3 G bytes. El resto del espacio de direcciones lógicas se
reserva para uso del SO. El kernel es mapeado en esta parte de todo espacio de direcciones del
proceso. El tamaño de página es 4 K bytes.
En una arquitectura X-86, Windows utiliza una organización de tabla de página de dos nive-
les, semejante a la que se muestra en la figura 6.15. La tabla de página de nivel superior se deno-
mina directorio de página (PD). PD contiene 1 024 entradas de 4 bytes cada una. Cada entrada
en PD apunta a una tabla de página (PT). Cada tabla de página contiene 1 024 entradas de tabla
de página de 4 bytes cada una. Cada dirección lógica de 32 bits se separa en tres componentes,
como se muestra a continuación:

10 bits 10 bits 12 bits


Índice PD Índice PT Índice de bytes

Para resolver una dirección lógica, el campo índice PD se utiliza para localizar una tabla de pá-
gina. El campo índice PT se usa para seleccionar la entrada de una página. Esta entrada apunta
a un marco de página. El índice de bytes se encadena con la dirección del marco de página para
obtener la dirección física efectiva. Cada entrada de una tabla de página contiene una dirección
de 20 bits del marco de página que contiene una página. Los 12 bits restantes se usan para los
siguientes propósitos: cinco bits contienen el campo de protección, cuatro indican el archivo
que contiene una copia del archivo y tres especifican el estado de la página. Si la página no está
en la memoria, los 20 bits especifican el desplazamiento hacia el archivo de paginamiento.
Esta dirección puede usarse para cargar la página en la memoria. Si la página contiene un có-
digo, una copia de éste existe en un archivo de código. Por tanto, la página no requiere ser
incluida en un archivo de paginamiento antes de ser cargada por primera vez. En este caso,
un bit indica la protección de la página y 28 bits apuntan a una estructura de datos del sistema
que indica la posición de la página en un archivo que contiene un código. En otras estructuras,
Windows usa tablas de página de tres o cuatro niveles y diferentes formatos para las entradas
de la tabla de página.
Un marco de página puede estar en uno de ocho estados. Algunos de éstos son: valid: la
página está en uso activo; free: la página no está en uso activo; zeroed: la página está limpia y
disponible para su uso inmediato; standby: la página ha sido eliminada del conjunto de trabajo
del proceso al que fue asignada, aunque es posible “reconectarla” al proceso si vuelve a ser refe-
rida de nuevo; modified: la página es sucia y todavía no se ha escrito afuera, y bad: no es posible
acceder a la página debido a un problema de hardware.
Para manejar páginas compartidas se hacen dos provisiones. Una sección objeto representa
una sección de la memoria que puede compartirse. Todo proceso que comparte la sección objeto
posee su propia vista del objeto; una vista controla la parte del objeto que es visible para el pro-
ceso. Un proceso mapea una vista de una sección en su propio espacio de direcciones haciendo
una llamada del kernel con sus parámetros que indican la parte de la sección objeto que va a
mapearse, es decir, una desplazamiento y el número de bytes que se va a mapear, así como la

07 MAQ. CAP. 06(F0694).indd 290 8/10/07 1:01:36 AM


6.10 Memoria virtual usando segmentación 291

dirección lógica en el espacio de direcciones del proceso donde va a mapearse el objeto. Cuando
se accede por primera vez a una vista, el kernel asigna memoria a la parte de la sección que está
cubierta por la vista, a menos que la memoria ya esté asignada a ésta. Si la memoria de la sección
tiene el atributo based, entonces la memoria compartida posee la misma dirección virtual en el
espacio de direcciones lógicas de cada proceso compartido.
Una característica copia durante la escritura se usa para compartir las páginas. Esto implica
que todos los procesos compartidos comparten la misma copia de la página hasta que ésta es mo-
dificada. Si un proceso modifica una página, entonces es creada una copia privada de la página
para el proceso. Durante la escritura la copia se implementa al establecer el campo de protección
de una página en read only (sólo lectura). Una excepción de protección se presenta cuando un
proceso intenta modificarlo. El administrador de la memoria virtual hace después una copia pri-
vada de la página para su uso en el proceso.
La segunda provisión para la compartición concierne al nivel de indirección para acceder
a las entradas de la tabla de página para páginas compartidas. En ausencia de tal indirección,
la página tendría entradas en tablas de página de todos los procesos compartidos y todas estas
copias tendrían que modificarse cuando una página es cargada o eliminada de la memoria. Para
evitar esto, en las entradas PT de la página en cada tabla de página del proceso compartido se
establece un bit de indirección. La entrada de la tabla de página entonces apunta a una entrada
de página prototipo, que indica hacia el marco de página actual que contiene a la página. Sólo es
necesario modificar la entrada de la página prototipo cuando una página es cargada o eliminada
de la memoria.

6.10 MEMORIA VIRTUAL USANDO SEGMENTACIÓN

En una memoria virtual segmentada, un proceso es una colección de segmentos. Cada uno es
una entidad lógica importante en un proceso. En términos de programación, un segmento suele
constar de un conjunto de procedimientos o datos y forma un módulo de un sistema de software.
Así, agrupa procedimientos y datos que poseen atributos en común para compartir con otros
procedimientos. La segmentación es de utilidad mientras se construyan grandes sistemas de
software que comparten módulos con otros sistemas de software.
Una dirección lógica en un proceso segmentado se considera como un par (si, bi), donde
si y bi son el número de segmento y el byte de desplazamiento, respectivamente. Durante la
ejecución, la MMU convierte esta referencia en una dirección de la memoria efectiva usando
el esquema de la figura 6.26. Pueden observarse varias semejanzas con la memoria virtual con
paginamiento. Un registro especial de hardware denominado registro de direcciones de la tabla
de segmentos (STAR) apunta a la tabla de segmentos de un proceso. A ésta puede accederse con
si como un índice. Si el segmento está presente en la memoria, la traducción de la dirección se
termina usando la dirección inicial de la memoria encontrada en su entrada de la tabla de seg-
mento; en caso contrario, se provoca un fallo de “segmento omitido”.
En un sentido importante difiere la traducción de la dirección en un sistema con memoria
virtual de la traducción de la dirección en un sistema de memoria virtual con paginamiento. A
diferencia de las páginas, los segmentos poseen diferentes longitudes, de modo que la memoria
física no puede asignarse en unidades de un tamaño fijo. En consecuencia, cada entrada de una
tabla de segmento contiene una dirección completa de la memoria física, más que simplemente
un número de marco como en un sistema de memoria virtual con paginamiento. El número de

07 MAQ. CAP. 06(F0694).indd 291 8/10/07 1:01:36 AM


292 CAPÍTULO 6 Memoria virtual

byte bi se agrega a esta dirección para calcular la dirección física efectiva. Este paso implica un
ciclo de adición, en vez de una mera concatenación como ocurre en paginamiento.

Memoria
ATU
Bit Direc- Misc
STAR válido ción info
+
Add si wi 2
1
si wi 1 ai
3

ai + wi
Tabla de segmento
(ST)
4

Figura 6.26 Implementación de la memoria virtual usando segmentación.

En cuanto a la manera en que están indicados si y bi en una instrucción, hay variantes. Un


método consiste en usar identificadores numéricos para cada uno de éstos. Así, la dirección lógica
consta de un número de segmento y un byte de desplazamiento, y la traducción de la dirección
se lleva a cabo como ya se describió. De manera alternativa, si y bi pueden especificarse de
manera simbólica, es decir, como nombres. Una dirección lógica típica en este caso sería (al-
pha, beta), donde alpha es el nombre de un segmento y beta es el de un byte en el segmento.
Durante la traducción de la dirección, la MMU debe buscar y localizar la entrada de alpha en
la tabla de segmento para obtener su dirección inicial en la memoria. Para cada segmento es
necesario mantener una tabla que muestre identificaciones y sus desplazamientos en el seg-
mento. Ésta se denomina tabla de enlaces de segmentos (segment linking table: SLT) y usa el
nombre del segmento como subíndice. Así, SLTalpha es la tabla de enlaces de segmentos para
alpha. SLTalpha se busca para encontrar el desplazamiento de beta en el segmento alpha.
Este desplazamiento se agrega a la dirección inicial de alpha para completar la traducción de
la dirección.

Ejemplo 6.10 En la figura 6.17 se ilustra el cálculo de la dirección efectiva para la dirección lógica
(alpha, beta). En la parte a) de la figura se muestra el segmento alpha; beta y gamma son las dos
identificaciones que podrían usarse en direcciones lógicas. Estas identificaciones están asociadas
con bytes en el segmento cuyos desplazamientos son 232 y 478, respectivamente. La tabla de enla-
ces de segmentos SLTalpha contiene entradas para beta y gamma, mostrando sus desplazamientos.
La tabla de enlaces de segmentos de alpha indica que existe en el área de la memoria con dirección
inicial 23480. El desplazamiento de beta es 232, por lo que la dirección efectiva de (alpha, beta)
debe calcularse como 23480232  23712.

07 MAQ. CAP. 06(F0694).indd 292 8/10/07 1:01:36 AM


6.10 Memoria virtual usando segmentación 293

Segmento Bit Direc- Misc Despla-


alpha Nombre válido ción info Nombre zamiento

beta :
beta 232
alpha 1 23480 gamma 478
gamma :

Tabla de segmento Tabla de enlaces de


(ST) segmentos (SLTalpha )

a) b)

Figura 6.27 Uso de un segmento simbólico y sus palabras de identificación.

En sistemas prácticos segmentados con memoria virtual se han utilizado identificaciones


numéricas y simbólicas. El sistema MULTICS usa identificadores simbólicos. Para facilitar las
cosas, en esta sección se supondrá el uso de identificadores numéricos. El espacio de direcciones
lógicas en un sistema segmentado con memoria virtual es inherentemente bidimensional por
naturaleza. Una dirección lógica lll se especifica como un par (si, bi). La manera en que (si, bi)
se representa determina el número máximo de un segmento. Si para representar a si se usan n1
bits y para representar a b se usan n2 bits, entonces un proceso puede contener 2n1 segmentos y
el tamaño máximo de un segmento es 2n2 bytes. Considere un sistema segmentado con memoria
virtual que usa identificación numérica para los segmentos y byte de desplazamiento, y n2  15.
El tamaño máximo de un segmento es 32768. Si el tamaño del segmento si es 2000 bytes, las
direcciones lógicas (si, 2000), (si, 2001) . . . (si, 32767) no existen en el proceso; sin embargo,
la dirección (si  1, 0) existirá si el segmento si  1 existe en el proceso. Incluso si si tuviese el
tamaño máximo, es decir, 32768, las direcciones (si, 32767) y (si  1, 0000) no son direcciones
“adjuntas” en ningún sentido porque pertenecen a segmentos diferentes del proceso.
Compare lo anterior con un sistema de memoria virtual con paginamiento, donde la direc-
ción lógica lll está especificada por un solo número. Sabiendo el número de bits usado para re-
presentar el número de página y el byte de desplazamiento, la MMU extrae automáticamente a pi
y bi de lll. Así, el espacio de direcciones lógicas es unidimensional. Si un registro CPU contiene
la dirección del último byte de una página, al sumar 1 a la dirección ¡se produce un “derrame”
hacia la página siguiente! Esto no ocurre en un sistema segmentado con memoria virtual porque
el último byte de un segmento y el primero del siguiente segmento no son bytes adjuntos en el
proceso. Esta diferencia tiene implicaciones importantes para la asignación de memoria, como
se verá en la sección 6.10.1.

6.10.1 Administración de la memoria física

Entre la administración de la memoria y la memoria virtual con paginamiento hay algunas seme-
janzas. Una falla de segmento indica que un segmento requerido no se encuentra en la memoria.
Una operación de segmentación se realiza para cargar el segmento. Si no se dispone de suficiente
memoria libre, quizá sea necesario que alguna(s) operación(es) de segmento afuera deba(n) pre-
ceder a la carga del segmento. La asignación de memoria para un proceso puede controlarse

07 MAQ. CAP. 06(F0694).indd 293 8/10/07 1:01:36 AM


294 CAPÍTULO 6 Memoria virtual

usando el concepto de conjunto de trabajo de segmentos. Los segmentos deben reemplazarse con
base en un LRU mientras se atienden los fallos de segmento.
Los segmentos no tienen un tamaño fijo. Esta propiedad conduce a muchas diferencias con
la administración de la memoria en sistemas con memoria virtual con paginamiento. Cuando se
elimina un segmento, la memoria liberada de la memoria puede no ser suficiente para cargar otro
segmento, de modo que puede ser necesario eliminar muchos antes de cargar un nuevo segmen-
to. Las diferencias en los tamaños de los segmentos también provoca fragmentación externa,
que puede abordarse usando técnicas de reúso de la memoria, a través de compactación o apli-
cando las estrategias del primer ajuste o del mejor ajuste. La compactación es auxiliada por la
presencia de la MMU: sólo es necesario modificar el campo de direcciones de la entrada de
la tabla de segmento cuando un segmento se desplaza en la memoria. Por supuesto, es necesario
tener cuidado para asegurar que los segmentos que están moviéndose no participen en opera-
ciones de E/S. La naturaleza bidimensional de la memoria virtual segmentada permite que un
segmento crezca o se reduzca dinámicamente en tamaño. El crecimiento dinámico puede ma-
nejarse mediante la asignación de un área de memoria más grande a un segmento y liberando
el área de la memoria que tenía asignada antes. Es posible dejar que un segmento crezca en su
ubicación actual en la memoria si la memoria adjunta está libre.

6.10.2 Protección y compartición

En la protección y compartición de segmentos hay dos cuestiones importantes:


1. Protección contra el hecho de exceder el tamaño de un segmento.
2. Compartición estática y dinámica de segmentos.
Mientras se traduce una dirección lógica (si, bi), es esencial asegurar que bi esté dentro del
segmento si. La MMU logra esto al comparar bi con el tamaño del segmento si, que se almacena
en un campo adicional de cada entrada de la tabla de segmento.
Un segmento es una unidad conveniente para compartir porque es una entidad lógica en un
proceso. Si las identificaciones de los segmentos son numéricas, entonces los segmentos deben
ocupar posiciones idénticas en los espacios de direcciones lógicas de procesos compartidos. Esta
restricción es semejante a la que concierne a páginas compartidas en un sistema de memoria virtual
con paginamiento (consulte la sección 6.5 y la figura 6.23). Esta restricción no es necesaria si las
identificaciones de los segmentos son simbólicas. La protección en los espacios de direcciones
lógicas y físicas es semejante a la protección en memoria virtual con paginamiento.

6.10.3 Segmentación con paginamiento

Como se mencionó en la sección 6.10.1, los sistemas segmentados con memoria virtual adolecen
del problema de fragmentación externa porque los tamaños de los segmentos son diferentes. Este
problema puede abordarse superponiendo paginamiento en un mecanismo de direccionamiento
orientado a segmento. Un sistema que usa este método preserva la ventaja fundamental de me-
moria virtual segmentada: el espacio de direcciones lógicas es bidimensional, lo cual permite
cambios dinámicos en el tamaño de un segmento, a la vez que se evita la fragmentación externa.
Cada segmento contiene un número entero de páginas y la administración de la memoria se lleva
a cabo en términos de páginas. Los fallos de página se atienden como en un sistema de memoria
virtual con paginamiento. Los conjuntos de trabajo se mantienen en términos de páginas, más

07 MAQ. CAP. 06(F0694).indd 294 8/10/07 1:01:37 AM


Ejercicio 6 295

que de segmentos. Este arreglo puede lograr un uso más eficaz de la memoria porque en ésta
sólo debe haber en cualquier instante páginas requeridas de un segmento. Sin embargo, el pagi-
namiento introduce fragmentación interna.
Una dirección lógica generalizada en un sistema así tiene la forma (si, pi, bi). Cada segmento
consta de un número de páginas, de modo que para cada segmento existe una tabla de página. La
entrada de un segmento en la tabla de segmento apunta al inicio de la tabla de página para ese
segmento. En la figura 6.28 se ilustra este arreglo. (El campo name de la tabla de segmento se
requiere sólo si se usan identificaciones de segmento simbólicas.) La traducción de la memoria
implica entonces dos niveles de indirección, primero a través de la tabla de segmento y luego a
través de la tabla de página del segmento. Requiere dos referencias de la memoria si el segmento
y las tablas de página van a preservarse en la memoria. Para acelerar la traducción de la direc-
ción, es necesario usar las memorias intermedias de traducción de la dirección para el segmento
y las referencias a las tablas de página. Una simple extensión del esquema antes descrito en la
sección 6.2.3 puede usarse para este fin. De manera alternativa, puede usarse un solo conjunto de
memorias intermedias de traducción de la dirección, donde cada memoria intermedia contenga
un par (si, pi) y el número de marco de página correspondiente.

Bit Dirección Misc


Nombre válido PT info
ST
Memoria
ATU

si pi wi Bit Marco de Misc


válido página info
Add si pi wi
ai PT
ai wi

Figura 6.28 Traducción de la memoria en segmentación con paginamiento.

La protección de la memoria puede realizarse en el nivel de segmentos. Puede implemen-


tarse a través de la tabla de segmento colocando la información de protección en cada entrada de
la tabla de segmento. Las memorias intermedias de traducción de la dirección pueden contener
información de validación de acceso según se ha copiado de las entradas de la tabla de segmento.
Una vez que la validación de acceso se ha realizado al nivel de segmento, la validación de acceso
a la página no es necesaria.

EJERCICIO 6
1. El tamaño de la memoria física asignada a un proceso en un sistema de memoria virtual con pagina-
miento se mantiene constante y el tamaño de página es variable. (Con esta acción se hace variar el

07 MAQ. CAP. 06(F0694).indd 295 8/10/07 1:01:37 AM


296 CAPÍTULO 6 Memoria virtual

número de páginas del proceso en la memoria.) Elabore un diagrama de tamaño de página contra razón
de fallos de página esperados.
2. El grado de multiprogramación en un sistema de memoria virtual con paginamiento se hace variar
cambiando los procesos de asignación de memoria. Elabore un diagrama de multiprogramación contra
eficacia del CPU. Explique la naturaleza de la gráfica en la región de alto grado de multiprograma-
ción.
3. Comente sobre la posible pérdida de protección si el contenido del almacenamiento temporal de visión
lateral de traducción (translation look-aside buffer: TLB) no se cambia cuando se lleva a cabo la pro-
gramación del proceso. Explique cómo puede evitarse lo anterior.
4. Las tablas de página se almacenan en la memoria física, cuyo tiempo de acceso es de 100 nanosegun-
dos. El almacenamiento temporal de visión lateral de traducción puede alojar 8 entradas de tablas de
página y tiene un tiempo de acceso de 10 nanosegundos. Durante la ejecución de un proceso se en-
cuentra que 85 por ciento del tiempo de una entrada de una página requerida existe en el TLB y sólo
2 por ciento de las referencias conduce a fallos de página. El tiempo medio por reemplazo de página es
de 2 milisegundos. Calcule el tiempo medio de acceso a la memoria.
5. Usando las aceleraciones de acceso y las relaciones de impacto mencionados en el problema 4, calcule
el tiempo medio de acceso a la memoria en organizaciones de tablas de dos, tres y cuatro niveles.
6. Tres métodos para paginamiento del kernel en un sistema de memoria virtual son los siguientes:
a) Hacer que el kernel sea residente permanente en la memoria.
b) Paginar el kernel de manera semejante al paginamiento de los procesos del usuario.
c) Hacer del kernel una parte obligatoria del espacio de direcciones lógicas de todo proceso en el
sistema y administrar sus páginas como páginas compartidas.
¿Cuál método recomendaría usted? Justifique su respuesta.
7. El desempeño de un proceso en un sistema de memoria virtual con paginamiento depende de la lo-
calidad de referencia mostrada durante su ejecución. Desarrolle un conjunto de líneas directrices que
debe seguir un programador para obtener un desempeño aceptable de un proceso. Describa las razones
que subyacen en cada directriz. (Sugerencia: ¡Considere que los arreglos de las referencias ocurren en
ciclos anidados!)
8. Se observa que cuando un proceso se ejecuta con alloc  5, produce más fallos de página cuando se
usa la política de reemplazo de página LRU que cuando se utiliza la política de reemplazo óptimo de
página. Proporcione una cadena de referencia de página muestra para tal proceso.
9. ¿La política de reemplazo de página FIFO puede desempeñarse mejor que el algoritmo de segunda
oportunidad para un proceso? En caso afirmativo, describa las condiciones en que esto puede ocurrir y
elabore una cadena de referencia de página para la cual la política FIFO se desempeñe mejor.
10. Un proceso hace r referencias de página durante su ejecución. La cadena de referencia de página del
proceso contiene d números de página distintos. El tamaño del proceso es de p páginas y a lo largo de
toda su ejecución se le han asignado f marcos de página.
a) ¿Cuál es el número mínimo de fallos de página que pueden ocurrir durante la ejecución del pro-
ceso?
b) ¿Cuál es el número máximo de fallos de página que pueden ocurrir durante la ejecución del pro-
ceso?
11. Demuestre la validez de la siguiente declaración si en la política de reemplazo de página se utiliza una
asignación de memoria fija y reemplazo local de página: “Si un proceso no modifica ninguna de sus
páginas, entonces resulta óptimo reemplazar la página cuya siguiente referencia está más lejos en la
cadena de referencia de página.”
Demuestre que esta política puede no conducir al mínimo de operaciones de página adentro y
página afuera si el proceso modifica sus páginas.

07 MAQ. CAP. 06(F0694).indd 296 8/10/07 1:01:37 AM


Ejercicio 6 297

12. ¿En qué consiste la anomalía de Belady? Demuestre que un algoritmo de reemplazo de página que
cuenta con la propiedad de pila no puede presentar la anomalía de Belady.
13. Demuestre que la política de reemplazo de página LRU posee la propiedad de pila.
14. El reemplazo óptimo de página, ¿posee la propiedad de pila?
15. Se utiliza un asignador de conjunto de trabajo para una cadena de referencia de página con dos valores
de , 1  2. pfr1 y pfr2 son razones de fallo de página cuando se usan 1 y 2. ¿Es cierto que pfr1
pfr2 si los conjuntos de trabajo vuelven a calcularse a) después de cada instrucción, b) después de cada
n instrucciones para alguna n?
16. Describa acciones del manejador de la memoria virtual utilizando un asignador de conjunto de trabajo
cuando decide reducir el grado de multiprogramación. Indique claramente cómo usa y manipula sus
estructuras de datos para este fin.
17. Para la cadena de referencia de página (6.5):
a) Muestre el conjunto de trabajo en cada instante de tiempo si el tamaño de la ventana del conjunto
de trabajo es i) tres instrucciones, ii) cuatro instrucciones.
b) Compare la operación y el desempeño del asignador del conjunto de trabajo con asignadores FIFO
y LRU.
18. Explique, con ayuda de ejemplos, por qué el tamaño del conjunto de trabajo de un proceso puede au-
mentar o disminuir durante la ejecución del proceso.
19. Un manejador de la memoria virtual utiliza la siguiente política de reemplazo de página: cuando se ob-
serva una combinación de una elevada razón de fallo de página y baja eficacia del CPU, reducir la asigna-
ción de cada proceso y cargar/activar la ejecución de un proceso más. Comente acerca de la eficacia
de esta política.
20. Justifique la siguiente afirmación: “En un sistema de memoria virtual con paginamiento que usa un
asignador de memoria del conjunto de trabajo puede haber hiperpaginación; sin embargo, no puede
durar mucho.”
21. Explique por qué el algoritmo del reloj con dos manecillas para reemplazo de página es superior al
algoritmo del reloj con una manecilla (consulte la sección 6.7).
22. Un manejador de memoria virtual utiliza competición dinámica de páginas. Describa las acciones do-
mésticas realizadas en las siguientes situaciones:
a) Cuando ocurre un fallo de página.
b) Cuando una página compartida abandona el conjunto de trabajo de uno de los procesos de compar-
tición.
23. En el contexto de administración de páginas compartidas, analice las ventajas y desventajas de:
a) Protección en el espacio de direcciones lógicas.
b) Protección en el espacio de direcciones físicas.
24. Un asignador de memoria utiliza el concepto de “instrucciones en el pasado” durante la ejecución de
un proceso. Se dice que la instrucción más recientemente ejecutada es “1 instrucción en el pasado” del
proceso, de la instrucción anterior se dice que es “2 instrucciones en el pasado”, y así sucesivamente.
Se refiere a la referencia de página en la instrucción que es i instrucciones en el pasado como la refe-
rencia de página i. Usa un parámetro w y aplica las reglas siguientes en el orden a)-d) para asignación
de la memoria y reemplazo de página:
a) No hacer nada si la siguiente referencia de página coincide con la referencia de página w.
b) Si la siguiente referencia de página coincide con la referencia de página i para alguna i  w, hacer
lo siguiente: si la referencia de página w no coincide con la referencia de página j para alguna j  w,
entonces reducir la asignación de memoria para el proceso por un marco de página y eliminar la
página más recientemente utilizada; en caso contrario, no hacer nada.

07 MAQ. CAP. 06(F0694).indd 297 8/10/07 1:01:37 AM


298 CAPÍTULO 6 Memoria virtual

c) Si la siguiente referencia de página provoca un fallo de página y la referencia de página w no


coincide con la referencia de página en la instrucción j para alguna j  w, entonces realizar un
reemplazo de página usando la política de reemplazo de página LRU.
d) Incrementar la asignación de memoria para el proceso por 1 marco de página y cargar la página
contenida en la siguiente referencia de página.
Demuestre que las acciones del asignador de la memoria son equivalentes a las acciones del asig-
nador del conjunto de trabajo con  w.
Un asignador del conjunto de trabajo se utiliza para una cadena de referencia de página con
dos valores de , 1  2. pfr1 y pfr2 son razones de fallo de página cuando se usan 1 y 2. Use la
equivalencia de estas reglas con el comportamiento de un asignador del conjunto de trabajo para de-
mostrar que pfr1 pfr2.
25. Escriba una nota breve sobre las ventajas y desventajas de utilizar identificaciones de segmento simbó-
licas e identificaciones de bytes en una memoria virtual segmentada.
26. Compare las siguientes proposiciones de administración de la memoria en un sistema de memoria
virtual usando segmentación con paginamiento:
a) Usar la política LRU dentro de un proceso.
b) Usar la política LRU dentro de un segmento.
27. Comente sobre la validez de la siguiente afirmación: “En un sistema de memoria virtual segmentado
que usa segmentación y paginamiento, el papel de la segmentación está limitado a la compartición. No
desempeña ningún papel en la administración de la memoria.”
28. Una operación de E/S consiste en la ejecución de una secuencia de comandos de E/S. Una operación de
E/S de autodescripción es una operación de E/S, de la cual algunos comandos de E/S se leen por medio
de un comando de E/S previo de la misma operación de E/S. Por ejemplo, considere la operación de
E/S

1. Read d, 6, aaa
2. Read d, count, bbb.

donde d es la identificación del dispositivo de E/S. El primer comando de E/S lee 6 bytes en el área de
la memoria con dirección aaa. Sea ésta el área donde se almacenan los campos que contienen count (2
bytes) y bbb (4 bytes) del segundo comando de E/S. Sean n y ccc los valores que son leídos hacia los
campos count y bbb, respectivamente, por el primer comando de E/S. Después de que termina la E/S
para el primer comando de E/S, el segundo comando de E/S lee n bytes hacia el área de la memoria con
dirección ccc. Los datos para esta operación de E/S deben ser
n, ccc,
n bytes de datos

Los métodos para realizar E/S en un sistema de memoria virtual con paginamiento descritos en la
sección 6.2.3, ¿pueden manejar correctamente las operaciones de E/S de autodescripción? Justifique
claramente su respuesta.
En una forma simplificada de E/S de autodescripción, los primeros comandos de E/S leen sólo 2
bytes y los almacenan en el campo count. Los métodos descritos en la sección 6.2.3, ¿pueden manejar
correctamente estas operaciones de E/S?
29. El siguiente método se sugiere para realizar operaciones de E/S en un entorno con paginamiento: mien-
tras se lleva a cabo una lectura, los datos se leen primero en un área temporal. Luego se mueven al área
en que se supone que debieron leerse. Mientras se efectúa una escritura, los datos se mueven primero
hacia un área temporal. Luego se escriben en un dispositivo de E/S.

07 MAQ. CAP. 06(F0694).indd 298 8/10/07 1:01:38 AM


Bibliografía 299

Explique cuáles características de las operaciones de E/S descritas en la sección 6.2.3 deben pre-
servarse para su uso en este método y cuáles pueden descartarse. Explique las ventajas y las desventajas
de este método.
30. Mientras se inicia un proceso, el manejador de la memoria virtual en un sistema de memoria virtual
con paginamiento copia el código del proceso en el espacio de intercambio reservado para el proceso.
Desde el espacio de intercambio, los códigos de página se cargan en la memoria cuando son necesarios.
Los códigos de algunas páginas pueden no utilizarse durante una ejecución, por lo que es redundante
copiarlos en el espacio de intercambio.
Para evitar el copiado redundante, algunos manejadores de la memoria virtual copian un código de
página en el espacio de intercambio cuando se usa por primera vez. Describa cómo los sistemas Unix
y Windows implementan esta optimización. Analice las ventajas y las desventajas de la optimización.
31. El desempeño de una memoria virtual está determinado por la interacción de tres factores: la velocidad
del CPU, el tamaño de la memoria y el rendimiento pico del dispositivo de paginamiento. Algunas
causas posibles de baja o alta eficacia del CPU y del disco de paginamiento pueden resumirse como
sigue:

Alta eficacia Baja eficacia

Los programas están limitados por Pocos programas están limitados por
CPU
el CPU o el CPU es lento el CPU o hay hiperpaginación
Disco de Hay hiperpaginación o el disco es Exceso de compromiso de la memoria
paginamiento lento con los programas

El desempeño de un sistema de memoria virtual puede mejorar si se hacen uno o varios de los cambios
siguientes: el CPU se sustituye por un CPU más rápido; el disco de paginamiento se sustituye por un
disco más rápido; se incrementa la memoria o el grado de multiprogramación. En cada uno de los
casos siguientes, ¿cuál de los cambios anteriores recomendaría usted para mejorar el desempeño del
sistema?
a) Baja eficacia del CPU y baja eficacia del disco.
b) Baja eficacia del CPU y alta eficacia del disco.
c) Alta eficacia del CPU y baja eficacia del disco.
d) Alta eficacia del CPU y alta eficacia del disco.

BIBLIOGRAFÍA
Randell (1969) escribió un artículo reciente sobre la motivación de los sistemas con memoria virtual. Gha-
nem (1975) analiza la partición de la memoria en sistemas con memoria virtual para multiprogramación.
Denning (1970) hizo un artículo de estudio sobre la memoria virtual. Hatfield (1971) analiza aspectos del
desempeño del programa en un sistema con memoria virtual.
Belady (1966) analiza la anomalía que lleva su nombre. Mattson et al. (1970) estudian la propiedad
de pila de los algoritmos de reemplazo de página. Denning (1968a, 1968b) analiza la hiperpaginación
e introducen el modelo fundamental del conjunto de trabajo. Denning (1980) realizó un análisis exhaustivo
sobre conjuntos de trabajo. Smith (1978) preparó una bibliografía sobre el paginamiento y temas relaciona-
dos. Wilson et al. (1995) analizan la asignación de la memoria en entornos con memoria virtual. Johnstone
y Wilson (1998) estudian el problema de fragmentación de la memoria.

07 MAQ. CAP. 06(F0694).indd 299 8/10/07 1:01:38 AM


300 CAPÍTULO 6 Memoria virtual

Chang y Mergen (1988) describen la tabla de página invertida, mientras Tanenbaum (2001) analiza
las tablas de página de dos niveles usadas en Intel 30386. Jacob y Mudge (1998) comparan características
de la memoria virtual en arquitecturas MIPS, Pentium y PowerPC. Swanson et al. (1998) y Navarro et al.
(2002) describen las superpáginas.
Car y Hennessy (1981) analizan el algoritmo del reloj. Bach (1986) y Vahalia (1996) describen la me-
moria virtual de Unix, Beck et al. (2002), Bovet y Cesati (2002), Gorman (2004) y Love (2005) analizan
la memoria virtual de Linux; Mauro y McDougall (2001) estudian la memoria virtual en Solaris, mientras
Russinovich y Solomon (2005) analizan la memoria virtual de Windows.
Organick (1972 describe la memoria virtual segmentada en MULTICS.

1. Aho, A.V., P.J. Denning y J.D. Ullman (1971): “Principles of optimal page replacement”, Journal
of ACM, 18 (1), 80-93.
2. Bach, M.J. (1986): The Design of the Unix Operating System, Prentice-Hall, Englewood Cliffs.
3. Belady, L.A. (1966): “A study of replacement algorithms for virtual storage computers”, IBM
Systems Journal, 5 (2), 78-101.
4. Bensoussen, A., C.T. Clingen y R.C. Daley (1972): “The MULTICS virtual memory—concepts
and design”, Communications of the ACM, 15 (5), 308-318.
5. Bryant, P. (1975): “Predicting working set sizes”, IBM Journal of R and D, 19 (5), 221-229.
6. Beck, M., H. Bohme, M. Dziadzka, U. Kunitz, R. Magnus, C. Schroter y D. Verworner (2002):
Linux Kernel Progreamming, 3a. ed., Pearson Education.
7. Bovet, D.P. y M. Cesati (2002): Understanding the Linux Kernel, O’reilly, Sebastopol.
8. Carr,W.R. y J.L. Hennessy (1981): “WSClock—a simple and effective algorithm for virtual
memory management”, Proceedings of the ACM Symposium on Operating Systems Principles,
87-95.
9. Chang, A. y M. Mergen (1988): “801 storage: architecture and programming”, ACM Transactions
on Computer Systems, 6, 28-50.
10. Daley, R.C. y J.B. Dennis (1968): “Virtual memory, processes and sharing in MULTICS”, Com-
munications of the ACM, 11 (5), 305-322.
11. Denning, P.J. (1968a): “The working set model for program behavior”, Communications of the
ACM, 11 (5), 323-333.
12. Denning, P.J. (1968b): “Thrashing: Its causes and prevention”, Proceedings of AFIPS FJCC, 33,
915-922.
13. Denning, P.J. (1970): “Virtual Memory”, Computing Surveys, 2 (3), 153-189.
14. Denning, P.J. (1980): “Working sets past and present”, IEEE Transactions on Software Enginee-
ring, 6 (1), 64-84.
15. Ghanem, M.Z. (1975): “Study of memory partitioning for multiprogramming systems with virtual
memory”, IBM Journal of R y D, 19, 451–457.
16. Gorman, M. (2004): Understanding the Linux Virtual Memory Manager, Prentice Hall PTR.
17. Guertin, R.L. (1972): “Programming in a paging environment”, Datamation, 18 (2), 48-55.
18. Hatfield, D.J. y J. Gerald (1971): “Program restructuring for virtual memory”, IBM Systems Jour-
nal, 10 (3), 169-192.
19. Jacob, B. y T. Mudge (1998): “Virtual memory in contemporary microprocessors”, IEEE Micro
Magazine, 18, 60-75.
20. Johnstone, M.S. y P.R. Wilson (1998): “The memory fragmentation problem: solved?”, Procee-
dings of the First International Symposium on Memory Management, 26-36.

07 MAQ. CAP. 06(F0694).indd 300 8/10/07 1:01:38 AM


Bibliografía 301

21. Love, R. (2005): Linux Kernel Development, 2a. ed., Novell Press.
22. Mauro, J. y R. McDougall (2001): “Solaris Internals—Core Kernel Architecture”, Sun Microsys-
tems, Palo Alto.
23. Mattson, R.L., J. Gecsei, D.R. Slutz e I.L. Traiger (1970): “Evaluation techniques for storage
hierarchies”, IBM Systems Journal, 9 (2), 78-117.
24. Navarro, J., S. Iyer, P. Druschel y A. Cox (2002): “Practical, transparent operating system support
for superpages”, ACM SIGOPS Operating Systems Review, 36, issue SI, 89-104.
25. Organick, E.I. (1972): The MULTICS System, MIT Press, Mass.
26. Randell, B. (1969): “A note on storage fragmentation and program segmentation”, Communica-
tions of the ACM, 12 (7), 365-369.
27. Rosell, J.R. y J.P. Dupuy (1973): “The design, implementation and evaluation of a working set
dispatcher”, Communications of the ACM, 16, 247-253.
28. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.
29. Smith, A.J. (1978): “Bibliography on paging and related topics”, Operating Systems Review, 12
(4), 39-56.
30. Swanson, M., L. Stoller y J. Carter (1998): “Increasing TLB reach using superpages backed by
shadow memory”, Proceedings of the 25 th International Symposium on Computer Architecture,
204-213.
31. Tanenbaum, A.S. (2001): Modern Operating Systems, 2a. ed., Prentice-Hall, Englewood Cliffs.
32. Vahalia, U. (1996): Unix Internals—The New Frontiers, Prentice-Hall, Englewood Cliffs.
33. Wilson, P.R., M.S. Johnstone, M. Neely y D. Boles (1995): “Dynamic storage allocation: a sur-
vey and critical review”, Proceedings of the International Workshop on Memory Management,
1-116.

07 MAQ. CAP. 06(F0694).indd 301 8/10/07 1:01:38 AM


Capítulo
7
Sistema de archivos

Los usuarios de computadora almacenan datos en archivos de modo que puedan usarlos
convenientemente y de manera repetida. Un usuario tiene muchas expectativas de un sistema de
archivos. Las más evidentes son las siguientes:

• Acceso conveniente y fácil a los archivos.


• Almacenamiento confiable de los archivos.
• Poder compartir de manera controlada los archivos con otros usuarios del sistema.

Los recursos utilizados para este propósito son dispositivos de E/S: su capacidad para almacenar
datos y sus velocidades para transferirlos. Como otros recursos, el SO debe asegurar la utilización
eficaz de los dispositivos de E/S.
En muchos sistemas operativos, las funciones mencionadas están organizadas en dos com-
ponentes denominadas sistema de archivos y sistema de control de entrada salida (IOCS). El
sistema de archivos proporciona servicios que permiten al usuario la creación de archivos, asig-
narles nombres con sentido, manipularlos y especificar la manera en que serán compartidos con
otros usuarios del sistema. El IOCS implementa la organización eficaz y el acceso a los datos
en los archivos. Así, el uso del sistema de archivos y del IOCS separa de manera conveniente lo
relacionado con el nivel de archivo a partir de cuestiones relativas a E/S.
En este capítulo se analizará el sistema de archivos. La implementación de las opera-
ciones de archivos que utilizan los servicios proporcionados por el IOCS se analizarán en el
capítulo 12.

7.1 SISTEMA DE ARCHIVOS E IOCS

El sistema de archivos y los módulos IOCS constituyen la jerarquía de las capas que se muestran
en la figura 7.1. Cada capa contiene la política y los módulos del mecanismo. Los mecanismos
de una capa se implementan utilizando la política y los módulos del mecanismo. La estructura
sobre la capa IOCS, así como el número de capas IOCS, varía a través de los sistemas operativos.
En el capítulo 12 se analizará una estructura convencional del IOCS.

08 MAQ. CAP. 07(F0694).indd 302 8/10/07 1:02:55 AM


7.1 Sistema de archivos e IOCS 303

Programa de aplicación

M P Sistema de archivos

M P Capas IOCS

M Kernel

Hardware
M : Módulo de mecanismo
P : Módulo de política

Figura 7.1 Sistema de archivos y capas IOCS.

Como se analizó en las secciones 1.1 y 14.4, la jerarquía del sistema de archivos y las ca-
pas IOCS proporcionan una jerarquía de abstracciones. Este capítulo empieza con un repaso de
las funciones realizadas por las capas de la figura 7.1.
El kernel interactúa con el hardware de E/S y proporciona facilidades para manejar el inicio
y término de E/S. Las capas IOCS invocan los servicios del kernel a través de llamadas del sis-
tema. Utilizando los mecanismos IOCS, es posible efectuar E/S sin conocer los vericuetos de los
dispositivos de E/S. Los módulos de la política IOCS aseguran un uso eficaz del subsistema E/S
y un buen desempeño de los programas de procesamiento de archivos. Éstos invocan los módu-
los del mecanismo para implementar acciones de E/S. La capa del sistema de archivos utiliza
servicios proporcionados por la capa IOCS para implementar sus funciones. Este arreglo oculta
todos los detalles de la organización de E/S y las interfaces del módulo IOCS del programa de
aplicación; el programa de aplicación sólo interactúa con el sistema de archivos.

Sistema de archivos y servicios del IOCS El sistema de archivos considera un archivo


como una entidad que es propiedad del usuario, que puede ser compartida por un conjunto de
usuarios autorizados y que debe ser almacenada de manera confiable durante un intervalo
de tiempo largo. Como un aspecto de la propiedad, proporciona libertad de nombres de los ar-
chivos, de modo que un usuario puede asignar un nombre deseado a un archivo sin preocuparse
si otros usuarios han creado nombres de archivo idénticos, y proporciona privacidad al proteger
contra interferencia de otros usuarios. El IOCS considera un archivo como un conjunto de re-
gistros a los que es necesario acceder rápidamente y almacenar en un dispositivo de E/S que
requiere ser utilizado eficazmente.
En la tabla 7.1 se resumen los servicios proporcionados por el sistema de archivos y el
IOCS. El sistema de archivos provee las estructuras de directorio que permiten que un usuario
organice sus datos en grupos lógicos de archivos. Por ejemplo, un usuario podrá preferir separar
datos personales de datos profesionales y estructurar los datos profesionales según las activida-
des. El sistema de archivos proporciona protección contra acceso ilegal a los archivos y reglas
para compartirlos concurrentemente. También asegura que los datos se almacenen de manera
confiable, es decir, que ningún dato se pierda cuando ocurra una caída del sistema. El IOCS
proporciona mecanismos para efectuar operaciones de E/S y para asegurar el uso eficaz de los
dispositivos de E/S. También provee un conjunto de módulos de biblioteca que permiten que un
programa procese de manera eficaz un archivo.

08 MAQ. CAP. 07(F0694).indd 303 8/10/07 1:02:55 AM


304 CAPÍTULO 7 Sistema de archivos

Tabla 7.1 Servicios proporcionados por el sistema de archivos y el IOCS

Sistema de archivos
• Estructuras del directorio para la agrupación conveniente de los archivos.
• Protección de los archivos contra accesos ilegales.
• Semántica para compartir archivos.
• Almacenamiento confiable de los archivos.
IOCS
• Operación eficaz de los dispositivos de E/S.
• Acceso eficaz a los registros en un archivo.

Estructura del directorio

Proceso
pi leer
leer
beta beta pi Proceso
pk
llave=“..”
Proceso leer
pj

Registros Registros
de beta de pi

Figura 7.2 Organización lógica en el sistema de archivos.

Organización lógica en un sistema de archivos En la figura 7.2 se muestra la organi-


zación lógica en un sistema de archivos. La estructura del directorio contiene información re-
lacionada con los nombres, la organización y la ubicación de archivos. El arreglo de datos en
un archivo es determinado por su organización. Cuando un proceso desea manipular un archivo,
éste se localiza utilizando su estructura de datos. A sus datos se accede usando comandos que son
consistentes con su organización.
En el sistema existen dos archivos llamados beta. Los procesos Pi y Pj acceden a uno de
estos archivos. A cuál de los dos beta se accede es determinado por la estructura del directorio
y por las identidades de los usuarios que iniciaron los procesos Pi y Pj. La naturaleza de beta
para compartir es determinada por la semántica para compartir del archivo. Los archivo beta y
pi tienen organizaciones diferentes (beta es un archivo secuencial, mientras pi es uno directo:
consulte la sección 7.3), de modo que los comandos que se utilizan para acceder a ellos son
distintos.

08 MAQ. CAP. 07(F0694).indd 304 8/10/07 1:02:55 AM


7.2 Archivos y operación de archivos 305

Acceso a archivos en un programa La expresión procesamiento de archivos se usa para


referirse a la lectura o escritura de información en un archivo. En la figura 7.3 se ilustra el arreglo
usado para implementar el procesamiento en un programa de aplicación. El sistema de archi-
vos y el IOCS proporcionan bibliotecas de módulos estándar. Un programa de aplicación con-
tiene declaraciones de los archivos utilizados por el programa, que especifican valores de los
atributos de los archivos que describen la estructura y organización de los datos en un archivo.
Mientras compila el programa de aplicación, el compilador elige el sistema de archivos idóneo
y los módulos IOCS con base en los atributos de un archivo. Estos módulos se ligan con el
programa de aplicación. Las acciones de procesamiento de archivos en el programa de aplica-
ción se compilan como llamadas a los módulos del sistema de archivos y al IOCS. Los módulos
del sistema de archivos invocan a los módulos del IOCS, que a su vez invocan al kernel para
implementar la operación. Los programadores con conocimientos avanzados del IOCS pueden
escribir el programa de aplicación que comunica directamente con el IOCS (consulte la figura
7.1). En este capítulo no se abordarán tales utilizaciones de los módulos del IOCS.

{Declaración
de archivos}

open ... call ... call ...

read ... call ... call ...

Programa que El compilador sustituye


contiene la el procesamiento de Módulos del
declaración y uso archivos con llamadas a los sistema de
archivos
del archivo módulos del sistema de
archivos/IOCS
Módulos
IOCS

El programa llama
a los módulos del
sistema de
archivos y a los
módulos IOCS
durante su ejecución

Figura 7.3 Procesamiento de archivos en un programa.

7.2 ARCHIVOS Y OPERACIÓN DE ARCHIVOS

Tipos de archivos Un sistema de archivos contiene diferentes tipos de archivos; por ejem-
plo, archivos que contienen datos, programas ejecutables, módulos objeto, información textual,
documentos, hojas de cálculo, fotos y video clips. Cada uno de estos archivos tiene su propio
formato. Estos tipos de archivos pueden clasificarse en dos clases:

08 MAQ. CAP. 07(F0694).indd 305 8/10/07 1:02:56 AM


306 CAPÍTULO 7 Sistema de archivos

• Archivos estructurados.
• Archivos de flujo de bytes.

Un archivo estructurado es una vista clásica de un archivo que consta de registros y campos.
En esta vista, un archivo se denomina colección de registros. Un registro es una colección sig-
nificativa de campos relacionados, y un campo contiene un solo dato. Un registro también es una
unidad significativa para el procesamiento de datos. Se supone que cada registro en un archivo
contiene un campo llave. El contenido de los campos llave de todos los registros en un archivo es
único. Muchos tipos de archivos antes mencionados son archivos estructurados. Los tipos de
archivo usados por software del sistema estándar, como compiladores y ligadores, poseen una
estructura determinada por el diseñador del SO. La estructura de un tipo de archivo utilizado por
una aplicación como un programa de hojas de cálculo es determinada por la aplicación misma.
La estructura de un archivo de datos es determinada por el programa que lo crea.
Un archivo de flujo de bytes es “plano”. No contiene campos ni registros; los procesos
que lo utilizan lo consideran como una secuencia de bytes. Unix usa este tipo de archivos para
almacenar datos y programas.

Ejemplo 7.1 En la figura 7.4 se muestra un archivo employee_info. Cada registro en el archivo
contiene información sobre un empleado. Un registro contiene cuatro campos: la identificación
del empleado, su nombre, su nombramiento y su edad. El campo que contiene la identificación del
empleado es el campo llave.

employee info report


abscd18735

Empleado #

51
Anita Ingle
Ejecutiva
33 años
a) b)
Figura 7.4 Vistas lógicas de a) un archivo estructurado employee_info, b) un archivo de flujo de bytes report.

Atributos de los archivos Los atributos de los archivos son características de un archivo
que son importantes para sus usuarios o para el SO. Los atributos comunes de un archivo son
los siguientes: tipo, organización, tamaño, ubicación en el sistema, información de control de
acceso que indica la manera en que los diferentes usuarios pueden acceder al archivo, nombre
del propietario y hora de la última vez que se usó.

Operaciones de los archivos En la tabla 7.2 se describen las operaciones realizadas sobre
los archivos. Como ya se mencionó, el SO es responsable de crear y mantener un archivo, para
asegurar que a él acceden los usuarios sólo conforme a los privilegios de acceso especificados
para el archivo, y para eliminar el archivo cuando así los solicite su propietario. Estas funciones
son realizadas mediante el empleo de la interfaz del sistema de archivos. El verdadero acceso a
los archivos, es decir, la lectura o escritura de registros, se implementa utilizando el IOCS.

08 MAQ. CAP. 07(F0694).indd 306 8/10/07 1:02:56 AM


7.3 Organizaciones fundamentales de archivos 307

Tabla 7.2 Operaciones de archivos efectuadas por los procesos

Operación Descripción
Apertura de archivos Un proceso ejecuta una declaración open antes de realizar el procesa-
miento de un archivo. El sistema de archivos localiza el archivo y verifica
si el usuario que está ejecutando el proceso cuenta con los privilegios
de acceso necesarios. También lleva a cabo algunas acciones domésticas
para iniciar el procesamiento del archivo.
Lectura o escritura El sistema emite un comando idóneo para leer o escribir un registro. El
de un registro sistema de archivos considera la organización del archivo (consulte la
sección 7.3) e implementa la operación de lectura/escritura de manera
apropiada.
Cierre de un archivo La ejecución de una declaración close indica al sistema de archivos que
se ha terminado el procesamiento del archivo. El sistema de archivos ac-
tualiza en sus estructuras de datos la información concerniente al tamaño
del archivo, es decir, al número de registros que contiene.
Creación de un Un archivo se crea haciendo una copia de un archivo existente o escribiendo
archivo registros en un nuevo archivo. El sistema de archivos almacena en sus es-
tructuras de datos la información concerniente al tamaño del archivo. Tam-
bién almacena información relacionada con los privilegios de acceso para el
archivo.
Borrado de un El archivo se borra de la estructura del directorio del sistema de archi-
archivo vos. El medio de almacenamiento secundario ocupado por este archivo
se libera.
Volver a nombrar El sistema de archivos recuerda el nuevo nombre del archivo en su estruc-
un archivo tura del directorio.
Especificación de El usuario puede especificar o modificar los privilegios de acceso de
los privilegios un archivo creado por su proceso en cualquier momento de la existencia
de acceso del archivo.

En la siguiente sección se describen varias formas para organizar los datos en un archivo es-
tructurado. En las secciones posteriores se analizan los preliminares del acceso a archivos reque-
ridos para asegurar que un proceso accede a un archivo sólo en concordancia con sus privilegios
de acceso.

7.3 ORGANIZACIONES FUNDAMENTALES DE ARCHIVOS

La expresión “patrón de acceso a un registro” se usa de manera informal para describir el orden
en que un proceso accede a los registros de un archivo. Dos patrones de acceso a un registro
fundamentales son el acceso secuencial, en el que se accede a los registros en el mismo orden en
que existen en un archivo (o en orden inverso), y el acceso aleatorio, en el que se accede a los
registros en algún orden distinto al secuencial. Un programa se ejecuta de manera eficaz si su
patrón de acceso a un registro puede implementarse de manera eficaz en el sistema de archivos
mientras se procesa un archivo.
Una organización de archivos define dos cuestiones relacionadas con un archivo: el arreglo
de los registros en el archivo y el procedimiento que se va a utilizar para acceder a los registros.

08 MAQ. CAP. 07(F0694).indd 307 8/10/07 1:02:56 AM


308 CAPÍTULO 7 Sistema de archivos

Su uso proporciona un acceso eficaz a los registros para un patrón de acceso a un registro especí-
fico. La organización de archivos determina cuán eficazmente puede utilizarse el medio de E/S.
Un sistema de archivos proporciona varias organizaciones de archivos, de modo que el programa
puede elegir una organización de archivos que se ajuste mejor a sus necesidades.
Mientras se analiza la actividad de procesamiento de archivos en un proceso se usa la
siguiente notación:

tp : tiempo de CPU requerido para procesar la información en un registro.


tw : tiempo de espera por registro, es decir, tiempo que transcurre desde
que un proceso hace la solicitud para un registro hasta aquél en el que
el registro se vuelve disponible para su procesamiento.

La eficacia de procesamiento de un archivo depende del valor de tw. Una organización de archi-
vos aprovecha las características de un dispositivo de E/S para suministrar una eficacia de pro-
cesamiento de archivos aceptable para un patrón de acceso específico. Por ejemplo, un registro
de disco posee una dirección única y en cualquier registro de disco puede realizarse una opera-
ción de lectura/escritura cuando se especifica su dirección. Este hecho puede usarse para imple-
mentar de manera eficaz el patrón de acceso aleatorio.
En esta sección se describen tres organizaciones fundamentales de archivos. Otras usadas
en la práctica son variaciones de estas organizaciones fundamentales o son organizaciones con
un propósito especial que se ajustan a dispositivos de E/S de uso menos común. Los accesos a
los archivos que utilizan organizaciones de archivos específicas se implementan por medio de
un módulo IOCS denominado método de acceso. Las funciones efectuadas por los métodos
de acceso se analizan después de estudiar las organizaciones fundamentales de archivos.

7.3.1 Organización secuencial de archivos

En la organización secuencial de archivos, el campo llave almacena los registros en una se-
cuencia ascendente o descendente. Se espera que el patrón de acceso de una aplicación sea una
subsecuencia de esta secuencia. Por consiguiente, un archivo secuencial admite dos tipos de ope-
raciones: leer el siguiente registro (o el previo) y omitir el siguiente registro (o el previo). En una
aplicación se utiliza un archivo secuencial si sus datos pueden preclasificarse convenientemente
en orden creciente o decreciente.
A la mayor parte de los dispositivos de E/S puede accederse de manera secuencial, de modo
que los archivos secuenciales no dependen crucialmente de las características del dispositivo.
En consecuencia, un archivo secuencial puede migrarse fácilmente a un tipo de dispositivo di-
ferente. La organización secuencial de archivos también se utiliza para archivos de flujo de
bytes.

Ejemplo 7.2 Un archivo maestro de datos de empleados se organiza como un archivo secuencial.
El número de empleado es el campo llave del registro de un empleado y los registros están dis-
puestos en orden creciente por número de empleado (consulte la figura 7.5a)). Cada registro en
el archivo maestro contiene el número de cuenta bancaria del empleado en la que se depositarán
todos los pagos. Cuando debe procesarse algún pago especial para una clase específica de emplea-
dos, sus números de empleado se clasifican en orden ascendente. Para manejar los pagos especiales,
un proceso lee el número de un empleado, obtiene su registro del archivo maestro para ese emplea-
do y procesa el pago a la cuenta bancaria del empleado.

08 MAQ. CAP. 07(F0694).indd 308 8/10/07 1:02:56 AM


7.3 Organizaciones fundamentales de archivos 309

Debido a que los números del empleado están preclasificados en orden ascendente, este pro-
cedimiento puede realizarse al leer u omitir el siguiente registro.

empleado # registros falsos

1 2 4 10 12 . . . 1 2 3 4 5 . . . 10

a) b)
Figura 7.5 Registros en a) archivo secuencial, b) archivo directo.

7.3.2 Organización de archivos de acceso directo

Esta organización proporciona comodidad y eficacia para el procesamiento de archivos cuando


a los registros se accede en orden aleatorio. Para acceder a un registro, un comando de lectu-
ra/escritura sólo necesita mencionar su llave; por tanto, el acceso a un registro es independiente
de a cuál registro se accedió antes. Esto contrasta con la organización secuencial de archivos.
Si un proceso desea acceder al registro del empleado con el número 125, y si el último registro
que se leyó del archivo fue el del empleado con el número 36, éste tendrá que omitir de manera
explícita los registros que intervienen si se utiliza la organización secuencial de archivos. Estas
acciones se evitan en una organización de archivos de acceso directo, lo cual la hace tanto con-
veniente como eficaz.
Los archivos directos se registran en discos. Cuando un proceso proporciona un valor llave,
el método de acceso para la organización de archivos de acceso directo aplica una transforma-
ción al valor llave a fin de generar una dirección (track no, record no). Las cabezas del disco
ahora están posicionadas en la pista track no antes de emitir un comando de lectura/escritura en
record no. Considere el archivo maestro de la información del empleado usada en el ejemplo 7.2,
esta vez organizada como un archivo directo. Considere que en una pista del disco se han escrito
p registros. Suponiendo que los números del empleado, la pista y los números del registro del
archivo maestro empiezan desde 1, la dirección del número n de registro del empleado es (track
number(tn), record number (rn)) donde
n
tn = (7.1)
p
rn = n – (tn – 1) × p (7.2)

y indica un valor entero redondeado.


La organización de archivos de acceso directo proporciona eficacia de acceso cuando los
registros se procesan de manera aleatoria; sin embargo, posee dos desventajas en comparación
con un archivo secuencial:

• El cálculo de la dirección del registro consume tiempo de CPU.


• Una consecuencia de la necesidad de registros falsos es una utilización deficiente del
medio de E/S. Este aspecto se ilustra en el ejemplo 7.3.

Por tanto, el procesamiento secuencial de los registros en un archivo directo es menos eficaz que
el procesamiento de discos en un archivo secuencial.

08 MAQ. CAP. 07(F0694).indd 309 8/10/07 1:02:57 AM


310 CAPÍTULO 7 Sistema de archivos

Ejemplo 7.3 En la figura 7.5 se muestra el arreglo de los registros de los empleados en organi-
zaciones de archivos secuencial y directa. Los empleados con el número de empleado 3, 5 a 9 y
11 han abandonado la organización. Sin embargo, el archivo directo requiere contener un registro
para cada uno de estos empleados a fin de satisfacer las fórmulas (7.1)-(7.2) para el cálculo de
la dirección. Este requerimiento conduce a la necesidad de contar con registros falsos en el archivo
directo.

Otro problema práctico en el uso de archivos directos es la dependencia excesiva con res-
pecto al dispositivo. Las características de un dispositivo de E/S se suponen de manera explícita
y se utilizan en las fórmulas (7.1)-(7.2) para el cálculo de dirección. Volver a escribir el archivo
en otro dispositivo con características diferentes, por ejemplo, con capacidad de disco diferente,
implica modificar las fórmulas para el cálculo de la dirección.

7.3.3 Organización de archivo secuencial con índice

Un índice ayuda a determinar la ubicación de un registro a partir de su valor llave. En una or-
ganización de archivo indexada, el índice contiene entradas en la forma (key, disk address) para
todos los valores llave que hay en un archivo. Para acceder a un disco con llave k, la entrada del
índice que contiene a k se encuentra al buscar en el índice, y la dirección de disco mencionada
en la entrada se utiliza para acceder al registro. Si un índice es menor que un archivo, entonces
este arreglo proporciona una elevada eficacia de acceso, ya que buscar en el índice es más eficaz
que hacerlo en el archivo.
La organización de archivo secuencial con índice es una organización híbrida que utiliza
elementos de las organizaciones de archivos indexada y secuencial para combinar algunas de
sus ventajas y evitar algunas de sus desventajas. Usa un índice para identificar una sección
de la superficie del disco que puede contener un registro deseado. Los registros ubicados en esta
sección del disco se buscan secuencialmente para encontrar el disco. La búsqueda es exitosa si
el registro se encuentra en el archivo; en caso contrario, da por resultado un fracaso. Este arreglo
requiere un índice mucho más pequeño que en un archivo puramente indexado porque ningún
valor llave existe en el índice. También proporciona mejor eficacia de acceso que una organiza-
ción secuencial de archivos, a la vez que asegura una eficacia comparable de la utilización de
medios de E/S.
Para un gran archivo, el índice debe contener un gran número de entradas, de modo que
el tiempo requerido para buscar a través del índice debe ser grande. Para reducir el tiempo de
búsqueda puede usarse un índice de nivel superior. Una entrada en el nivel superior apunta a
una sección del índice. Ésta se busca para localizar la sección del disco que pudiera contener un
registro deseado. Este arreglo se ilustra en el ejemplo 7.4.

Ejemplo 7.4 En la figura 7.6 se ilustra un archivo maestro de información de empleados organi-
zado como un archivo secuencial con índice. El campo llave almacena los registros en orden ascen-
dente. Se elaboran dos índices para facilitar la rapidez de la búsqueda. El índice de la pista indica
los valores llave más pequeño y más grande localizados en cada pista (consulte los campos identifi-
cados como Bajo y Alto en la figura 7.6). El índice de nivel superior contiene entradas para grupos
de pistas que contienen 3 pistas cada una. Para localizar el registro con llave k, primero se busca el
índice de nivel superior a fin de ubicar el grupo de pistas que pudieran contener el registro deseado.
Luego se busca el índice de pista para las pistas del grupo a fin de localizar la pista que pudiera con-
tener el registro deseado, y la pista seleccionada se busca secuencialmente para encontrar el registro
con llave k. La búsqueda termina infructuosamente si no encuentra el registro en la pista.

08 MAQ. CAP. 07(F0694).indd 310 8/10/07 1:02:57 AM


7.4 Estructuras de directorio 311

Grupo
de Pista
pista Bajo Alto Pista Bajo Alto #
1 1 43 1 1 13 1 1 2 4 10 12 13
2 45 96 2 16 31 2 16 17 18 21 24 31
3 32 43
Índice de nivel 3 32 33 36 37 40 43
superior
Índice de pista

Figura 7.6 Índice de pista e índice de nivel superior en un archivo secuencia.

7.3.4 Métodos de acceso

Un método de acceso es un módulo del IOCS, que implementa el acceso a una clase de ar-
chivos utilizando una organización de archivos específica. El procedimiento que se debe usar
para acceder a registros en un archivo, ya sea con una búsqueda secuencial o por cálculo
de la dirección, es determinado por la organización de los archivos. El método de acceso utiliza
este procedimiento para acceder a los registros. También emplea algunas técnicas avanzadas en
programación E/S para hacer más eficaz el procesamiento de archivos. Dos de estas técnicas son
la memoria intermedia (buffer) para los registros y el bloqueo de los registros.

Memoria intermedia (buffer) para los registros Los registros de un archivo de entrada
se leen antes del momento en que los requiere un proceso. Los métodos de acceso mantienen
estos registros en áreas de la memoria denominadas memoria intermedia (buffers) hasta que
son requeridos por el proceso. El propósito de la memoria intermedia es reducir o eliminar a tw;
el proceso enfrenta una espera sólo cuando el registro requerido ya no existe en una memoria
intermedia.
Las acciones conversas se realizan para un archivo de salida. Cuando el proceso realiza
una operación de escritura, el valor que se va a escribir en el archivo se copia en una memo-
ria intermedia. Tiempo después se escribe en el dispositivo de E/S y la memoria intermedia se
libera para su reúso. El proceso enfrenta una espera sólo si no está disponible una memoria in-
termedia cuando realiza una operación de escritura.

Bloqueo de registros Un gran bloque de datos siempre se lee desde, o se escribe hacia, el
medio de E/S. El tamaño de este bloque excede el tamaño de un registro en el archivo. Este arre-
glo reduce el número total de operaciones de E/S requeridas por el procesamiento de un archivo,
con lo cual se mejora la eficacia del procesamiento de archivos. El bloqueo también mejora la
utilización de un medio de E/S y el rendimiento de un dispositivo.
Las técnicas de memoria intermedia y bloqueo de registros se analizan en el capítulo 12.

7.4 ESTRUCTURAS DE DIRECTORIO

Un sistema de archivos contiene archivos que son propiedad de varios usuarios. En este contexto
son importantes dos características:

08 MAQ. CAP. 07(F0694).indd 311 8/10/07 1:02:57 AM


312 CAPÍTULO 7 Sistema de archivos

• Libertad de nombrado: Capacidad del usuario para dar cualquier nombre a un archivo,
sin estar restringido por los nombres de los archivos utilizados por otros usuarios.
• Compartir archivos: Capacidad del usuario para acceder a archivos creados por otros
usuarios, y de permitir a otros usuarios el acceso a sus archivos.

Un sistema de archivos utiliza directorios para proporcionar estas dos características. Un di-
rectorio contiene información sobre un grupo de archivos relacionados. Cada entrada en el
directorio contiene información relacionada con un archivo: su ubicación, tipo y manera en que
otros usuarios del sistema pueden acceder a él. Cuando un proceso emite un comando para abrir
un archivo, el sistema de archivos encuentra la entrada del archivo en un directorio y obtiene su
localización.
En la figura 7.7 se muestran campos en una entrada de directorio típica. El campo flags se
utiliza para distinguir entre diferentes tipos de entradas de directorio. El valor “D” en este campo
se pone para indicar que un archivo es un directorio, “L” para indicar que se trata de una liga
y “M” para indicar que se trata de un sistema de archivos montado. Estos usos se describen en
secciones posteriores. El campo misc info contiene información de tipo: propietario, momento
de creación y momento de la última modificación.

Información Información
Nombre de Tipo/ de de Misc
archivo tamaño localización protección Banderas info

Figura 7.7 Entrada de directorio típica.

Un sistema de archivos contiene varios directorios. La estructura del directorio del sistema
de archivos conecta un directorio con otros en el sistema. Rige la manera en que los archivos
pueden ser compartidos por un grupo de usuarios. Se utiliza la convención pictórica de que un
directorio se representa por un rectángulo, mientras un archivo se representa por un círculo. En la
figura 7.8 se muestra una simple estructura del directorio que incluye a dos directorios. Un user
directory (UD) contiene información sobre los archivos que son propiedad de un usuario; cada
archivo se describe por medio de una entrada en el directorio. El master directory (MD) contiene
información sobre las UD de todos los usuarios registrados por el sistema. Cada entrada en el MD
contiene un par (identificación del usuario, apuntador UD). Los usuarios A y B crearon, ambos, un
archivo denominado alpha. Estos archivos tienen entradas en los UD respectivos. La estructura
del directorio que se muestra en la figura 7.8 se denomina estructura del directorio de dos niveles.
La utilización de los UD proporciona libertad de nombrado. Cuando un proceso iniciado por
el usuario A lleva a cabo la llamada open (alpha, . . . ), el sistema de archivos busca el MD para
dar cupo a las A del UD, y busca ahí a alpha. Si la llamada open (alpha, . . . ) fue realizada por
algún proceso ejecutado por B, entonces el sistema de archivos tendrá que buscar las B de UD
para alpha. Este arreglo asegura que se accederá al archivo correcto incluso si en el sistema hay
muchos archivos con nombres idénticos.
El uso de los UD presenta una desventaja: prohíbe que los usuarios compartan sus archivos
con otros usuarios. Puede proporcionarse una sintaxis especial para permitir que un usuario haga
referencia al archivo de otro usuario. Por ejemplo, un proceso iniciado por el usuario C pue-
de realizar la llamada open (A → alpha, . . . ) para abrir el archivo alpha de A. El sistema de

08 MAQ. CAP. 07(F0694).indd 312 8/10/07 1:02:58 AM


7.4 Estructuras de directorio 313

Directorio
maestro

Directorios
del usuario A B C

alpha beta gamma alpha calendar

Figura 7.8 Directorios maestro y del usuario.

archivos puede implementar lo anterior simplemente al utilizar la UD de A, en vez de la C de


UD, para buscar y localizar el archivo alpha. Para implementar la protección de archivos, el
sistema de archivos debe determinar si al usuario C puede permitírsele que abra el archivo al-
pha de A. Para este efecto comprueba el campo información de protección del directorio alpha.
Los detalles de la protección de archivos se analizarán en la sección 7.5.
La estructura del directorio de dos niveles de la figura 7.8 puede generalizarse de muchas
formas interesantes para proporcionar más flexibilidad a los usuarios. En la tabla 7.3 se resumen
tres generalizaciones importantes que se describen a continuación.

Tabla 7.3 Generalizaciones del concepto de estructura del directorio de dos niveles

Generalización Ventajas
Estructura de multinivel Múltiples niveles de directorios permiten que un usuario estructure sus
archivos en niveles y subniveles relacionados de manera funcional.
Directorio como archivo Un usuario puede crear archivos y directorios dentro de un directorio.
También puede proporcionar un nombre deseado a un directorio. Efecti-
vamente, un usuario puede personalizar la estructura del directorio.
Sintaxis generalizada La sintaxis generalizada permite acceder a cualquier archivo en el sis-
para el acceso a archivos tema de archivos, sujeto a restricciones impuestas por la protección de
archivos.

La primera generalización concierne al número de niveles en la estructura del directorio. El


sistema de archivos puede proporcionar una estructura del directorio de multinivel donde cada
usuario tiene un UD que contiene unos cuantos directorios, y algunos de éstos contienen a otros
directorios. Un usuario puede utilizar esta característica para agrupar archivos conforme a algún
criterio significativo, como la naturaleza de las actividades a las que pertenecen. Sin embargo, a
este método le falta flexibilidad, ya que proporciona un número fijo de niveles en la jerarquía y
un número fijo de directorios en cada nivel.
La segunda generalización proporciona más flexibilidad: un directorio es un archivo y pue-
de ser creado de la misma forma en que se crea un archivo. Es posible poner una “D” en el campo
flag de la entrada de un archivo para indicar que se trata de un archivo directorio. El sistema de

08 MAQ. CAP. 07(F0694).indd 313 8/10/07 1:02:58 AM


314 CAPÍTULO 7 Sistema de archivos

archivos proporciona un directorio denominado root que contiene información sobre las UD de
todos los usuarios. Un usuario crea directorios de archivos y archivos de datos para esta infor-
mación según sea necesario. En la figura 7.9 se muestra el árbol de directorio para el usuario A.
El usuario ha creado un archivo denominado alpha y directorios denominados admin y pro-
jects en el UD proporcionado por el sistema de archivos. El directorio projects contiene un
directorio real_time, que contiene un archivo main_pgm. Los árboles de directorio de todos
los usuarios juntos constituyen el árbol directorio del sistema de archivos. La raíz de este árbol
es el directorio root de la raíz del sistema de archivos.

root

A B

admin projects
alpha

real time
beta

main pgm

Figura 7.9 Archivos del usuario A.

En cualquier instante, se dice que un usuario está “in” en algún directorio específico. Este
directorio se denomina directorio actual del usuario. Cuando el usuario desea abrir un archivo,
el nombre del archivo es buscado en este directorio. Mientras se registra un usuario en el SO,
algún directorio en la jerarquía del directorio del sistema de archivos se especifica como direc-
torio raíz. Cada vez que el usuario entra, el SO lo coloca en ese directorio. Esta acción hace
que el directorio raíz sea el directorio del usuario en ese momento. Un usuario puede cambiar
el directorio actual a algún otro directorio a través de un comando change directory. Para fa-
cilitar esto, cada directorio almacena información sobre su directorio raíz en la estructura del
directorio.
La tercera generalización concierne a la sintaxis para acceder a los archivos. Debido a que
el nombre de un archivo puede no ser único en el sistema de archivos, para acceder a un archivo,
un usuario o un proceso debe identificarlo sin ninguna ambigüedad. Una trayectoria de acceso
es una trayectoria en la jerarquía de directorio, que proporciona un método sin ambigüedades
para designar a un archivo. Un usuario o un proceso utiliza un nombre de la trayectoria para
indicar a cuál archivo se accederá. Un nombre de la trayectoria es una secuencia de una o más
trayectorias componentes separadas por “/”, donde cada trayectoria componente es una referen-
cia a través de un directorio y la última puede ser el nombre de un archivo.

08 MAQ. CAP. 07(F0694).indd 314 8/10/07 1:02:58 AM


7.4 Estructuras de directorio 315

La tabla 7.4 contiene ejemplos de nombres de la trayectoria. El primer nombre de la tra-


yectoria contiene una sola trayectoria componente que es el nombre de un archivo. Este nombre
debe buscarse en el directorio actual. En la tercera trayectoria componente la notación ~xyz
significa el directorio raíz del usuario xyz.

Tabla 7.4 Ejemplos de nombres de la trayectoria

Nombre de la
trayectoria Explicación
alpha el archivo alpha está en el directorio actual
projects/beta el archivo beta en el directorio projects contenido en el directorio actual
~xyz/alpha el archivo alpha en el directorio raíz del usuario xyz
../personal/tax el archivo tax en el directorio personal, que existe en la raíz del directorio
actual

Los nombres de la trayectoria que empiezan en el directorio actual se denominan nombre


relativo de la trayectoria, y son a menudo breves y cómodos de usar; sin embargo, pueden
ser confusos porque un archivo puede tener un nombre relativo de la trayectoria para directorios
diferentes. Por ejemplo, en la figura 7.9, el archivo alpha tiene el nombre relativo de la trayec-
toria alpha del directorio A, mientras tiene los nombres relativos de la trayectoria ../alpha
y ../../alpha de los directorios projects y real_time, respectivamente.
Un nombre absoluto de la trayectoria empieza en el directorio raíz de la jerarquía del direc-
torio del sistema de archivos. Se usará la convención de que la primera trayectoria componente
en una trayectoria absoluta es un símbolo nulo. Así, en la figura 7.9, el nombre absoluto del
archivo alpha es /A/alpha. Archivos con el mismo nombre en directorios diferentes se distin-
guen en sus nombres absolutos de la trayectoria.

7.4.1 Estructuras de directorio de árbol y grafos

La estructura del directorio que se ilustra en la figura 7.9 es un árbol. En esta estructura, cada
archivo, excepto el directorio root (observe que el directorio también es un archivo), tiene
exactamente un directorio raíz. La ventaja de la estructura de árbol es que proporciona una
separación total de los archivos de usuarios diferentes, proporcionando así completa libertad
de nombre a los usuarios. Sin embargo, hace que el compartir archivos sea más bien engorroso.
Un usuario que desea acceder a los archivos de otro usuario tiene que hacerlo a través de dos o
más directorios. Por ejemplo, en la figura 7.9, el usuario B puede acceder al archivo beta utili-
zando el nombre de la trayectoria ../A/projects/beta o ~A/projects/beta.
El uso de la estructura de árbol conduce a una asimetría fundamental en la forma en que
usuarios diferentes pueden acceder a un archivo compartido. El archivo podrá existir en algún
directorio perteneciente a uno de los usuarios, que puede acceder al archivo con un nombre
más corto de la trayectoria que otros usuarios. Este problema puede resolverse organizando
los directorios en una estructura de grafo acíclica. En esta estructura, un archivo puede tener
muchos directorios raíz, y así un archivo compartido puede ser apuntado por los directorios de
todos los usuarios que tienen acceso al archivo. Para construir estructuras de gráfica acíclicas
pueden utilizarse ligas.

08 MAQ. CAP. 07(F0694).indd 315 8/10/07 1:02:58 AM


316 CAPÍTULO 7 Sistema de archivos

Ligas Una liga es una conexión dirigida entre dos archivos existentes en la estructura del di-
rectorio. Puede escribirse como una tripleta (from_filename, to_filename, link_name)
donde from_filename es un directorio de archivos y to_filename puede ser un directo-
rio o un archivo de datos. Una vez que se establece la liga puede accederse al to_filename
como si fuese un archivo denominado el link_name en el directorio el from_filename. El
hecho de que el link_name es una liga en el directorio el from_filename se indica ponien-
do el valor “L” en su campo de flags. En el ejemplo 7.5 se ilustra cómo se establece una liga.

Ejemplo 7.5 En la figura 7.10 se muestra la estructura del directorio después de que el usuario B
crea una liga usando el comando (~B, ~A/projects/beta, s_ware). El nombre de la liga es
s_ware. La liga se hace en el directorio ~B y apunta al archivo ~A/projects/beta. La liga per-
mite el acceso de ~A/projects/beta por medio del nombre ~B/s_ware. Por supuesto, el usuario
B debe tener los privilegios de acceso necesarios a beta a fin de establecer esta liga.

root

A B

admin projects
alpha

beta

Figura 7.10 Una liga en la estructura del directorio.

Para facilitar el borrado de archivos, que se describirá más adelante, el sistema de archivos
mantiene un conteo indicando el número de ligas que apuntan hacia un archivo. Un comando de
desligar borra una liga y disminuye el conteo. En consecuencia, la implementación de los co-
mandos ligar y desligar implica la manipulación de los directorios que contienen a los archivos
from_filename y to_filename. Mientras se implementan los comandos ligar y desligar,
pueden presentarse bloqueos mutuos si varios procesos emiten los comandos de manera simul-
tánea. El sistema de archivos puede aplicar alguna política de prevención de bloqueos mutuos a
fin de asegurar su ausencia (consulte el capítulo 11).

Operaciones en directorios Algunas operaciones comunes en directorios son operaciones


de mantenimiento, como la creación y el borrado de archivos, la actualización de entradas de
archivos cuando un proceso realiza una operación de cierre, enlistar el directorio y borrar el di-
rectorio. La mayor parte de estas operaciones requiere modificar el directorio.
La operación de borrado se hace complicada cuando las estructuras del directorio semejan
gráficas porque un archivo puede tener varias raíces. El sistema de archivos debe comprobar si

08 MAQ. CAP. 07(F0694).indd 316 8/10/07 1:02:59 AM


7.4 Estructuras de directorio 317

el archivo que se va a borrar tiene una sola raíz. En caso afirmativo, se borra el archivo y su en-
trada se elimina de la raíz. En caso contrario, el archivo no se borra porque de hacerlo se llegará
a apuntadores suspendidos; sin embargo, su entrada se elimina del directorio raíz implicado en
la trayectoria de acceso proporcionada en el comando de borrado.
Resulta engorroso comprobar si un archivo tiene varios directorios raíz. Esta tarea se sim-
plifica al mantener un conteo de referencia en cada archivo. El conteo se establece en 1 cuando
se crea el archivo, y se incrementa en 1 siempre que una liga se establece de modo que apunte
al archivo. Cuando se hace un intento por borrar un archivo, su conteo de referencia disminuye
en 1 y la entrada del archivo se borra del directorio raíz implicado en su trayectoria de acceso
proporcionada en el comando de borrado. El archivo en sí es borrado si el nuevo valor de su
conteo de referencia es 0.
Esta simple estrategia no es adecuada si la estructura del directorio contiene ciclos. Los ci-
clos se desarrollan cuando se establece una liga de un directorio hacia uno de sus directorios
ancestros; por ejemplo, si se estableciera una liga del directorio real_time de la figura 7.9 al
directorio A. La eliminación de A del directorio root llevará sólo a la eliminación de la entrada
de A en root porque la nueva cuenta de referencia de A es 1. Sin embargo, no hay ninguna
razón para retener el directorio A y los archivos alcanzables desde ahí, ¡ya que A no es accesible
desde el directorio raíz de cualquier usuario! Este problema puede resolverse utilizando una
técnica para detectar ciclos no alcanzables desde ninguno de los directorios raíz, lo cual puede
ser costoso, o evitando la aparición de ciclos en la estructura del directorio, lo que es igual
de costoso.

7.4.2 Montaje de sistemas de archivos

Un sistema de archivos se constituye a partir de un dispositivo lógico, es decir, de una partición


del disco. A los archivos contenidos en un sistema de archivos sólo es posible acceder una vez
que está montado el sistema de archivos. Esta operación “conecta” el sistema de archivos con
la estructura del directorio del sistema. Una operación de desmontaje desconecta un sistema
de archivos. Las operaciones de montaje y desmontaje son realizadas por el administrador del
sistema. Esta característica proporciona un elemento de protección. El montaje de sistemas de
archivos es útil cuando en el sistema hay más de un sistema de archivos (consulte la sección
7.12) o cuando un usuario de un sistema distribuido desea acceder a archivos localizados en una
máquina remota (consulte el capítulo 19).
Un sistema de archivos montado suele considerarse como un archivo en el directorio raíz del
sistema de archivos huésped. Sin embargo, algunos sistemas operativos generalizan el concepto
de montaje y permiten que un sistema de archivos sea montado en cualquier punto en la estruc-
tura del directorio de otro sistema de archivos. Este montaje proporciona un efecto semejante al
proporcionado por una liga. La diferencia es que el montaje no modifica de manera permanente
la estructura del directorio. Su efecto dura hasta que el sistema de archivo se desmonta o hasta
que el sistema vuelve a arrancar de nuevo.
El montaje se lleva a cabo como sigue: ciertos archivos en la jerarquía del sistema de ar-
chivos se designan puntos de montaje. Un sistema de archivos puede montarse en un punto de
montaje emitiendo el comando (FS_name, mount_point_name), donde FS_name y
mount_point_name son, ambos, nombres de la trayectoria, y designan la raíz del sistema
de archivos que va a ser montado y el punto de montaje, respectivamente. Una vez que se ha

08 MAQ. CAP. 07(F0694).indd 317 8/10/07 1:02:59 AM


318 CAPÍTULO 7 Sistema de archivos

realizado la operación de montaje, es posible acceder a cualquier archivo con el nombre relativo
de la trayectoria api en el directorio FS_name con el nombre de la trayectoria mount_po-
int_name/api. En el ejemplo 7.6 se ilustra el efecto de ejecutar el comando mount.

Ejemplo 7.6 En la figura 7.11b) se muestra el efecto del comando mount (meeting, ~A/admin),
donde las jerarquías del sistema de archivos en meeting y admin son como se muestra en la figura
7.11a). Entonces ya es posible acceder al archivo items como ~A/admin/agenda/items.

˜A meeting ˜A

admin agenda admin


time

agenda
items time

items
a) b)

Figura 7.11 Montaje de un sistema de archivos.

El efecto de una operación de montaje es anulado con un comando (FS_name, mount_


point_name). La operación unmount tiene éxito sólo si en el sistema de archivos montados
no hay archivos abiertos en ese momento. Para verificar fácilmente esta condición, el sistema
de archivos mantiene un conteo en la raíz del sistema de archivos montados para indicar cuántos
archivos han sido abiertos.

7.5 PROTECCIÓN DE ARCHIVOS

El propietario de un archivo puede especificar la forma en que otros usuarios pueden acceder
a su archivo. Mientras se crea un archivo se especifica información de protección, que puede
modificar el propietario del archivo en cualquier momento durante la existencia del archivo.
Se almacena en el campo protection info en la entrada del directorio de un archivo (consulte la
figura 7.7). El sistema de archivos usa esta información a fin de proporcionar formas controladas
para compartir archivos.
Resulta conveniente almacenar la información de protección en la forma de una access
control list (ACL). Cada elemento de esta lista es un par de control de acceso (user_name,
list_of_access_privileges). Cuando un proceso iniciado por algún usuario X intenta realizar
una operación opn en el archivo alpha, el sistema de archivos encuentra el par de control de
acceso con user_name  X y comprueba si opn está contenido en list_of_access_pri-
vileges. El intento por acceder a alpha fracasa si no es éste el caso. Por ejemplo, un intento de
escritura hecho por X fracasará si la entrada para el usuario X en la lista de control de acceso es
(X, read), o si en la lista ACL no existe ninguna entrada para X.

08 MAQ. CAP. 07(F0694).indd 318 8/10/07 1:02:59 AM


7.6 Interfaz entre el sistema de archivos y el IOCS 319

El tamaño de la lista de control de acceso de un archivo depende del número de usuarios y


de privilegios de acceso definidos en el sistema. La mayor parte de sistemas de archivos utili-
zan tres tipos de privilegios de acceso: read, write y execute (leer, escribir y ejecutar). Los dos
primeros indican si el archivo puede ser leído o modificado por un usuario. Un privilegio write
permite modificar los datos existentes en el archivo, y también agregar nuevos datos. Es posi-
ble distinguir entre estos dos privilegios si se define un nuevo privilegio de acceso denominado
append, aunque así se incrementará el tamaño de protección de la información. El privilegio
execute permite que un usuario ejecute el programa contenido en un archivo.
Los privilegios de acceso poseen distintos significados para los archivos del directorio. El
privilegio read para un archivo del directorio implica que es posible obtener un listado del direc-
torio, mientras el privilegio write para un directorio implica que es posible crear nuevos archivos
en el directorio. El privilegio execute para un directorio permite hacer un acceso a través del
directorio, es decir, permite el acceso a un archivo que existe en el directorio. Un usuario puede
hacer que el privilegio execute de los directorios haga visible para otros usuarios una parte de su
jerarquía de archivos.
Si un sistema contiene un gran número de usuarios, no es factible usar un par de control de
acceso para cada uno. Para reducir el tamaño de la información de protección, los usuarios pue-
den clasificarse de alguna manera conveniente y para cada clase de usuario es posible especificar
un par de control de acceso, en vez de hacerlo para cada usuario en particular. Luego, una lista de
control de acceso cuenta con tantos pares como el número de clases de usuarios. En el ejemplo
7.7 se describe la lista de control de acceso utilizada en Unix. En el capítulo 8 se analizará la
protección de archivos con más detalle.

Ejemplo 7.7 El sistema operativo Unix limita el tamaño de la lista de control de acceso de un
archivo alpha al dividir a todos los usuarios del sistema en las tres clases siguientes:

Clase 1 : Propietario del archivo alpha


Clase 2 : Usuarios del mismo grupo que el propietario del archivo alpha
Clase 3 : Todos los demás usuarios del sistema

Se definen tres privilegios de acceso; a saber, read, write y execute. La entrada del diccionario de
alpha contiene la identificación de su propietario así como los privilegios de acceso asignados a
cada clase de usuarios. Por tanto, en cada lista de control de acceso sólo hay tres pares de control
de acceso.

7.6 INTERFAZ ENTRE EL SISTEMA DE ARCHIVOS Y EL IOCS

El sistema utiliza mecanismos del IOCS para implementar operaciones de E/S. Estos mecanis-
mos acuden a la programación de E/S para manejar detalles en el nivel de dispositivos para el
inicio de E/S y manejo de la interrupción. Este arreglo protege al sistema de archivos respecto de
características dependientes de la máquina. La interfaz entre el sistema de archivos y el IOCS
consta del bloque de control de archivos y de funciones que efectúan operaciones de E/S.
Un bloque de control de archivos (FCB) contiene toda la información concerniente a una
actividad de procesamiento de archivos (consulte la tabla 7.5). La información en el FCB se
deriva de una variedad de fuentes. La información relacionada con la organización de un archivo
proviene de la declaración de archivo contenida en un programa de aplicación. Mientras compila
el programa, el compilador crea el FCB en su código objeto y registra esta información en el
FCB.

08 MAQ. CAP. 07(F0694).indd 319 8/10/07 1:02:59 AM


320 CAPÍTULO 7 Sistema de archivos

La información del directorio se vuelve disponible a través de acciones conjuntas del


sistema de archivos y el IOCS. El sistema de archivos decide la ubicación de un archivo en
el sistema cuando se crea el archivo y almacena esta información en la entrada del directorio del
archivo. El IOCS copia esta información en el FCB cuando un archivo se abre para su lectura.
Información concerniente al estado actual del procesamiento se escriben en el IOCS y el FCB.
Esta información se actualiza de manera continua durante el procesamiento de un archivo.

Tabla 7.5 Campos en el bloque de control de archivos (FCB)

Categoría Campos
Organización de Nombre del archivo
los archivos Tipo de archivo, organización y método de acceso
Tipo de dispositivo y dirección
Tamaño de un registro
Tamaño de un bloque
Número de memorias intermedias
Nombre/dirección del módulo IOCS/método de acceso
Información del Dirección del FCB del directorio raíz
directorio Dirección de la tabla del mapa de archivos (FMT) (o la tabla del mapa de archivos
misma)
Estado actual del Dirección del siguiente registro que será procesado
procesamiento Direcciones de las memorias intermedias

El sistema de archivos admite las siguientes operaciones:

• open (fcb_address, processing_mode);


• close (fcb_address);
• read/write (fcb_address, record_info, I/O_area addr).

Cada operación toma una dirección del FCB como su primer operando. La operación open
asume el modo de procesamiento, ya sea entrada, salida o agregar, como parámetro opcional.
Las operaciones read/write asumen el parámetro record_info, que indica la identidad de
registro que se va a leer o a escribir. Este parámetro se requiere en todas las organizaciones
de archivos, excepto en la organización secuencial de archivos (consulte la sección 7.3). El pará-
metro I/O_area addr indica la dirección del área de la memoria donde serán leídos los datos
del registro o de la memoria que contiene los datos que van a escribirse en el registro.
Cada operación del sistema de archivos extrae información relevante del FCB y la estructura
del directorio, e invoca una operación apropiada del IOCS. La operación open extrae el nom-
bre del archivo del FCB, se refiere a la jerarquía del directorio y ubica la entrada del directorio
para el archivo. Pasa al IOCS la dirección del FCB del directorio raíz y sus propios parámetros.
El IOCS copia información de la entrada del directorio del archivo hacia el FCB. La operación
close pasa la dirección del FCB del directorio raíz y otros parámetros al IOCS para actualizar
la entrada del directorio del archivo. Una operación read/write simplemente pasa todos sus
parámetros al IOCS.

08 MAQ. CAP. 07(F0694).indd 320 8/10/07 1:03:00 AM


7.6 Interfaz entre el sistema de archivos y el IOCS 321

La interfaz IOCS admite las siguientes operaciones:

• iocs-open (fcb_address ,directory_entry_address, processing_mode);


• iocs-close (fcb_address ,directory_entry_address);
• iocs-read/write (fcb_address, record_info, I/O_area addr).

Las operaciones iocs-open e iocs-close son operaciones de lectura y escritura especiali-


zadas que copian la información en el FCB de la entrada del directorio o del FCB hacia la entra-
da del directorio. Las operaciones iocs-read/write usan información concerniente al estado
actual del procesamiento de archivos encontrado en el FCB para implementar una operación de
lectura/escritura. Cuando una operación de escritura requiere más espacio de disco, iocs-write
debe invocar una función del sistema de archivos para efectuar asignación de espacio de disco
(consulte la sección 7.7).

Directorio alpha
˜U

<fi le declaration> fcbalpha 3 8

1 2
open (alpha, open (Ad(fcbalpha ),
‘read’) ‘read’)
read (alpha, read (Ad(fcbalpha ), 4 5
<record info>, <record info>, FS IOCS
Ad(xyz)) Ad(xyz))
6 7
close (alpha) close (Ad(fcbalpha ))

Programa fuente Programa compilado Acciones del sistema de archivos


y del IOCS
Figura 7.12 Visión general de operaciones con archivos.

En la figura 7.12 se muestra un esquema del procesamiento del archivo alpha en un proceso
iniciado por algún usuario U. El programa fuente contiene una declaración para el archivo alpha.
En la versión compilada de este programa, el compilador crea un FCB para el archivo al-
pha, que se denota por fcbalpha. El compilador también sustituye las declaraciones open, read y
alpha en el programa fuente por llamadas a operaciones en el sistema de archivos open, read
y alpha, respectivamente. El primer parámetro en todas estas llamadas es la dirección de fcbalpha
en vez del nombre del archivo alpha. Algunos pasos significativos en la ejecución de este progra-
ma se muestran con las flechas numeradas en la figura 7.12 y se describen a continuación.
1. El proceso que representa la ejecución de este programa realiza la llamada open
(Ad(fcbalpha), ‘read’).

08 MAQ. CAP. 07(F0694).indd 321 8/10/07 1:03:00 AM


322 CAPÍTULO 7 Sistema de archivos

2. La operación open extrae el nombre del archivo alpha de fcbalpha, localiza la entrada
del directorio alpha y almacena la dirección en fcbalpha para su uso mientras cierra el
archivo. Luego hace una llamada iocs-open con Ad(fcbalpha) y la dirección de la entrada
del directorio alpha como parámetros.
3. El IOCS copia información concerniente al tamaño y ubicación del archivo, a saber,
direcciones del primer y último bloque de bytes, de la entrada del directorio en fcbalpha.
4. Cuando el proceso requiere leer un registro de alpha hacia el área xyz, invoca la ope-
ración read del sistema de archivos con Ad(fcbalpha), record_info y Ad(xyz) como
parámetros.
5. La información de localización de alpha entonces ya está disponible en fcbalpha, de
modo que no es necesario hacer referencia al directorio de entrada de alpha para im-
plementar una operación read/write; estas operaciones pueden invocar directamente a
las operaciones iocs-read/write. De hecho, el proceso puede invocar de manera di-
recta a iocs-read/write.
6. El proceso invoca la operación close con Ad(fcbalpha) como parámetro.
7. El sistema de archivos hace una llamada iocs-close con Ad(fcbalpha) como parámetro.
8. El IOCS copia información concerniente al tamaño y ubicación del archivo, a saber, di-
recciones del primer y último bloque de bytes, de fcbalpha hacia la entrada del directorio
de alpha.

7.7 ASIGNACIÓN DE ESPACIO DE DISCO

En la sección 7.6 se mencionó que la asignación de espacio de disco la lleva a cabo el sistema de
archivos. Mientras se crea o actualiza un archivo, el IOCS espera que un módulo del sistema
de archivos proporcione la dirección de un bloque de disco en donde debe escribirse un registro.
Por razones de sencillez, los primeros sistemas de archivos adoptaban el modelo de asignación
de memoria contigua (consulte la sección 5.5) mediante la asignación de una sola área de me-
moria contigua a un archivo. Para facilitar lo anterior, se requería que un proceso proporcionara
un estimado del archivo a la vez que creaba un nuevo archivo. Este método condujo a fragmen-
tación tanto interna como externa del espacio de disco.
La asignación contigua de espacio de disco también requería arreglos complicados a fin de
evitar el mal uso de los bloques de disco. El sistema de archivos debía identificar malos bloques
de disco mientras daba formato al disco y elaboraba una tabla que mostraba las direcciones de
los bloques malos y sus sustitutos. Durante una operación read/write, el IOCS debía com-
probar si el bloque de disco al que iba a accederse era un mal bloque. En caso de serlo, obtenía
direcciones del bloque de disco sustituto y accedía a éste.
Los sistemas contemporáneos evitan estos problemas al adaptar el modelo de asignación
de memoria no contigua (consulte la sección 5.6) a la asignación de espacio de disco. Con este
método se evita la fragmentación externa. Bloques de disco de tamaño fijo se asignan por
demanda mientras se crea o actualiza un archivo. Así se reduce la fragmentación promedio
por archivo a la mitad del tamaño del bloque de disco. Ahora, para acceder a los datos se requiere
un equivalente de la “traducción de la dirección” (consulte la figura 5.16). Para este efecto se
mantienen las tablas que almacenan información relacionada con los bloques de disco asignados
a un archivo.

08 MAQ. CAP. 07(F0694).indd 322 8/10/07 1:03:00 AM


7.7 Asignación de espacio de disco 323

A continuación se analizan dos métodos de asignación no contigua de espacio de disco.


Continuando con la sección 7.4, se supone que la información concerniente a los bloques de
discos asignados a un archivo pueden obtenerse del campo Loc info de su entrada del directorio.

Nombre Location
del archivo info apuntador de la lista libre
alpha Datos
beta 1 - 2 Datos de control
3 4
5 6
7 - - 8
Directorio
Figura 7.13 Asignación ligada de espacio de disco.

Asignación ligada En la figura 7.13 se ilustra la asignación ligada. Un archivo se represen-


ta por una lista ligada de bloques de disco. Cada uno de éstos contiene dos campos: data (datos)
y control info (información de control). El campo datos contiene los datos escritos en el archivo,
mientras información de control contiene la dirección del siguiente bloque de discos asignado al
archivo. El campo Loc info (información local) de la entrada del directorio de un archivo apunta
hacia el primer bloque de disco del archivo. A los otros bloques se accede siguiendo los apunta-
dores en la lista de los bloques de disco. El espacio libre en el disco se representa por medio de
una free list (lista libre). Cuando un bloque de disco se requiere para escribir un nuevo registro
en un archivo, de la lista libre se saca un bloque que se agrega a la lista del archivo de los blo-
ques de disco. Para borrar un archivo, la lista del archivo de los bloques de disco simplemente se
agrega a la lista libre. Esta acción ahorra bastante tiempo de procesamiento durante el borrado
de un archivo.
La asignación ligada es fácil de implementar, e incurre en una baja sobrecarga de asigna-
ción/retiro de asignación. También admite de manera bastante eficaz archivos secuenciales. Sin
embargo, no es posible acceder de manera eficaz a los archivos con organizaciones no secuen-
ciales. La confiabilidad también es deficiente porque la corrupción del campo de información de
control en un bloque de disco puede conducir a la pérdida de datos en todo el archivo. De manera
semejante, la operación del sistema de archivos puede interrumpirse si un apuntador en la lista
libre está corrompido. Estos asuntos se analizan en la sección 7.10.

Tabla de asignación de archivos (FAT) MS-DOS utiliza una variante de asignación liga-
da que almacena los datos de control en forma separada de los datos del archivo. Una tabla de
asignación de archivos (FAT) de un disco es un arreglo que tiene un elemento correspondiente
a todo bloque del disco en el disco. Para un bloque de disco que está asignado a un archivo,
el elemento correspondiente de la FAT contiene la dirección del siguiente bloque de disco. Así, el
bloque de disco y su elemento FAT juntos constituyen un par que contiene la misma información
que el bloque de disco en un esquema clásico de asignación ligada.
La entrada del directorio de un archivo contiene la dirección de su primer bloque de disco.
El elemento FAT correspondiente a este bloque de disco contiene la dirección del segundo blo-
que de disco y así sucesivamente. El elemento FAT correspondiente al último bloque de disco
contiene un código especial para indicar el final del archivo. En la figura 7.14 se ilustra el FAT
para el disco de la figura 7.13. El archivo alpha consta de los bloques de disco 3 y 2. Por

08 MAQ. CAP. 07(F0694).indd 323 8/10/07 1:03:00 AM


324 CAPÍTULO 7 Sistema de archivos

tanto, la entrada del directorio de alpha contiene al 3. La entrada de FAT para el bloque de disco
3 contiene al 2 y la entrada FAT para el bloque de disco 2 indica que es el último bloque del
archivo. El archivo beta consta de los bloques 4, 5 y 7.

Nombre Location
del archivo info 1 free
alpha 2 end
3 3 2
1 2
beta 4 4 5 3 4
5 7
6 free 5 6
7 end 7 8
8 free

Directorio Tabla de asignación


de archivos
Figura 7.14 Tabla de asignación de archivos (FAT).

Una FAT también puede utilizarse para almacenar información del espacio libre. La lista de
los bloques de disco libres puede almacenarse como si fuera un archivo, y la dirección del primer
bloque de disco libre puede mantenerse en un apuntador de lista libre. De manera alternativa,
algún código especial puede almacenarse en el elemento de la FAT correspondiente a un bloque
de disco libre, por ejemplo, el código “free” en la figura 7.14.
El uso de la FAT en vez de la asignación ligada clásica implica una penalización en el
desempeño, ya que es necesario acceder a la FAT para obtener la dirección del siguiente blo-
que de disco. Para superar este problema, la FAT se mantiene en la memoria durante el procesa-
miento del archivo. El uso de la FAT proporciona mayor confiabilidad que la asignación ligada
clásica porque la corrupción de un bloque de disco que contiene datos del archivo conduce a un
daño limitado. Sin embargo, la corrupción de un bloque de disco utilizado para almacenar una
FAT es desastrosa.

Asignación indexada En la asignación indexada, un índice denominado tabla del mapa


de archivos (FMT) se mantiene para anotar las direcciones de los bloques de disco asignados a
un archivo. En su forma más simple, la FMT puede ser un arreglo que contiene direcciones de
bloques de disco. Cada bloque de disco contiene un solo campo: el campo de datos. El campo
loc info de la entrada de un directorio apunta a la FMT para un archivo (consulte la figura 7.15).
En el siguiente análisis, la FMT del archivo alpha se denota por fmtalpha.

Nombre Location
del archivo info
alpha
beta
fmtalpha

Directorio
fmtbeta
Figura 7.15 Asignación indexada del espacio de disco.

08 MAQ. CAP. 07(F0694).indd 324 8/10/07 1:03:01 AM


7.7 Asignación de espacio de disco 325

Una tabla denominada mapa de estado del disco (MED) se utiliza para indicar el estado
de los bloques de disco. El MED posee una entrada para cada bloque de disco que indica si el
bloque de disco es libre o ya ha sido asignado a un archivo. Esta información puede mantenerse
en un solo bit. En la figura 7.16 se ilustra un MED. Un “1” en una entrada indica que el blo-
que de disco correspondiente está asignado. El MED se consulta cada vez que un nuevo bloque
de disco debe ser asignado a un archivo. Una alternativa al uso del MED es emplear una lista
libre de bloques de disco como ya se describió.

011100101

El bloque
de disco
está asignado
El bloque
de disco
está libre

Figura 7.16 Mapa de estado del disco (MED).

La asignación de espacio de disco a un archivo denominado alpha se realiza por demanda


cuando alpha es creado o actualizado. El MED es buscado para localizar un bloque libre, y la
dirección del bloque se agrega a fmtalpha. El retiro de asignación se lleva a cabo una vez que se
borra alpha. Todos los bloques de disco a los que apunta fmtalpha se marcan como libres antes
de que se borren fmtalpha y la entrada del directorio de alpha.
El problema de confiabilidad es menos grave en asignación indexada que en asignación li-
gada. Esto se debe al hecho de que la corrupción de una entrada de una FMT o un MED conduce
a un daño limitado. En comparación con la asignación ligada, el acceso a archivos secuenciales
es menos eficaz porque es necesario acceder a la FMT de un archivo para obtener la dirección
del siguiente bloque de disco. Sin embargo, el acceso a los registros en un archivo directo es
más eficaz, ya que la dirección del bloque de disco que contiene un registro específico puede
obtenerse directamente de la FMT.
Para un archivo pequeño, la FMT puede almacenarse en la entrada del directorio del archi-
vo. Esto es conveniente y eficaz. Para un medio o un archivo grande, la FMT podrá no caber en
la entrada del directorio. La asignación indexada de multinivel que se representa en la figura 7.17
suele utilizarse para tales FMT. El directorio aún contiene una parte de la FMT. Las primeras
entradas en la FMT, por ejemplo n entradas, apuntan a bloques de datos como en la asignación
indexada convencional. Otras entradas apuntan a bloques especiales denominados bloques de ín-
dice. Un bloque de índice no contiene datos, sino varios apuntadores hacia los bloques de datos.
Es necesario acceder a estos bloques de datos a través de dos niveles de indirección. El primer
nivel de indirección apunta a un bloque de índice. El segundo, a un bloque de datos. La ventaja
de su arreglo es que archivos pequeños que contienen n o menos bloques de datos siguen siendo
accesibles de manera muy eficaz en tanto sus FMT no contengan bloques de índice. Los archivos
medios y grandes adolecen de degradación marginal en cuanto a su desempeño de acceso debido
a múltiples niveles de indirección.

08 MAQ. CAP. 07(F0694).indd 325 8/10/07 1:03:02 AM


326 CAPÍTULO 7 Sistema de archivos

1 Bloques
de datos

Bloques
m de datos
FMT

Bloques
de índice
Figura 7.17 Asignación indexada de multinivel.

7.8 IMPLEMENTACIÓN DEL ACCESO A ARCHIVOS

El uso de la estructura del directorio y el bloque de control de archivos (FCB) en la implementa-


ción de un acceso a un archivo ya se analizó en la sección 7.6. El esquema que se analizó utiliza
un FCB para seguir la pista del estado actual de una actividad de procesamiento de un archivo.
La dirección de un FCB se pasa como un parámetro en toda llamada a una operación del sistema
de archivos realizada por un proceso y en toda llamada de una operación del IOCS hecha por
el sistema de archivos. Una debilidad de este esquema es que un FCB forma parte del espacio
de direcciones de un proceso, lo cual origina una preocupación sobre la confiabilidad debido
a que el proceso puede falsear información en el FCB, afectando así la operación del sistema de
archivos. Este asunto puede abordarse mediante la construcción de FCB en el área del sistema.
El kernel crea una FCB en su propio espacio de direcciones cuando un proceso abre un archivo
y pasa su dirección al proceso. El proceso no puede falsear la información del FCB debido a la
protección de la memoria.
Una estructura de datos denominada tabla de archivos activos (active files table: AFT) se
utiliza para contener los FCB de todos los archivos abiertos. Cuando se abre un archivo, el siste-
ma de archivos almacena su FCB en una entrada de la AFT. El desplazamiento de esta entrada
en la AFT se denomina identificación interna del archivo. La identificación interna se devuelve
al proceso, que la utiliza como parámetro en todas las llamadas futuras del sistema. Este arreglo
se muestra en la figura 7.18. Cuando se abre un archivo alpha, al proceso se le devuelve internal
idalpha, que es 6.

7.8.1 Acciones del sistema de archivos en la apertura de archivos


El propósito de una llamada open (pathname ..), donde pathname es un nombre abso-
luto o relativo de la trayectoria para un archivo filename, es establecer el procesamiento del
archivo. open lleva a cabo las siguientes acciones:
1. En la AFT se crea un FCB para el archivo filename.
2. La identificación interna del archivo filename se devuelve al proceso para su uso en
el procesamiento del archivo.

08 MAQ. CAP. 07(F0694).indd 326 8/10/07 1:03:02 AM


7.8 Implementación del acceso a archivos 327

internal idalpha = 6

fcbalpha

fmtalpha
Tabla de archivos
activos (AFT)
Figura 7.18 Tabla de archivos activos (AFT).

3. Si el archivo filename está creándose o actualizándose, se toman provisiones para


actualizar la entrada de su directorio cuando el proceso haga una llamada close.
Para implementar la acción 3, el sistema de archivos establece un apuntador denominado apun-
tador FCB del directorio. Este apuntador señala al FCB del directorio, que contiene una entrada
para filename. Este directorio debe actualizarse una vez que se cierra el archivo, de modo que
el sistema de archivos almacena el apuntador FCB del directorio en el FCB de filename.
Estas acciones se implementan mediante un procedimiento denominado resolución del
nombre de la trayectoria, que atraviesa todas las trayectorias componentes en un nombre de la
trayectoria y comprueba la validez de cada componente. La resolución del nombre de la trayec-
toria consta de los pasos siguientes:
1. Si se utiliza un nombre absoluto de la trayectoria, localizar el FCB del directorio raíz del
sistema de archivos en la AFT; en caso contrario, localizar el FCB en el directorio actual.
(En este paso se supone que los FCB de estos directorios ya han sido creados en la AFT.
En caso contrario, deben crearse en este paso.) Se deja que el apuntador FCB del direc-
torio señale hacia este FCB.
2. a) Buscar la siguiente trayectoria componente en el nombre de la trayectoria en el di-
rectorio representado por el apuntador FCB del directorio. Indicar un error si la
componente no existe o si es inválida en este directorio.
b) Crear un FCB para el archivo descrito por la trayectoria componente. Almacenar este
FCB en una entrada libre de la AFT.
c) Establecer un apuntador denominado apuntador de archivos FCB que señale hacia
este FCB.
d) Si ésta no es la última componente en el nombre de la trayectoria, inicializar el FCB
de reciente creación utilizando la información de la entrada del directorio del archivo.
Establecer apuntador FCB del directorio  apuntador de archivos FCB y repetir el
paso 2.
3. a) Si el archivo ya existe, inicializar el FCB al que apunta el apuntador de archivos
FCB, utilizando la información de la entrada del directorio del archivo. Esta acción
incluye el copiado del apuntador a la FMT del archivo.
b) Si el archivo aún no existe, formatear la FMT del archivo. (Esta acción puede im-
plicar la asignación de un bloque de disco para la FMT y el almacenamiento de su
dirección en el FCB.)

08 MAQ. CAP. 07(F0694).indd 327 8/10/07 1:03:02 AM


328 CAPÍTULO 7 Sistema de archivos

4. Establecer internal id del archivo hacia el desplazamiento del apuntador de archivos


FCB en la FMT. Copiar el apuntador FCB del directorio hacia el FCB del archivo. De-
volver internal id al proceso.
Además de las acciones que acaban de describirse, el sistema de archivos puede efectuar
otras acciones en aras de la eficacia. Por ejemplo, mientras se abre un archivo existente, puede
copiar en la memoria parte o toda la FMT (consulte el paso 3a)). Esta acción asegura un acceso
eficaz a los datos en el archivo. También, durante el procesamiento sólo son necesarios los FCB
a los que apuntan el apuntador FCB del directorio y el apuntador de archivos FCB, de modo que
es posible destruir los otros FCB creados durante la resolución del nombre de la trayectoria.
En el ejemplo 7.8 se ilustran las estructuras de datos construidas por el sistema de archivos
cuando se abre un archivo.

Ejemplo 7.8 En la figura 7.19 se muestra el resultado de las acciones del sistema de archivos
después de ejecutar la llamada

open (/info/alpha, ..);

El nombre de la trayectoria mencionado en la llamada open es un nombre absoluto de la trayecto-


ria. El sistema de archivos busca el nombre info en el directorio raíz, y crea una FCB para info en
la AFT. Luego busca el nombre alpha en info y crea un FCB para alpha en la AFT. El apuntador
FCB del directorio apunta hacia fcbinfo y el apuntador de archivos FCB apunta a fcbalpha. Debido a
que alpha es un archivo existente, su apuntador de la FMT se copia en fcbalpha desde la entrada del
directorio de alpha. La llamada regresa con la identificación interna de alpha, que es 6.

Directorio alpha
info

Apuntador FCB
6
fcbinfo del directorio
fcbalpha
Apuntador de
archivos FCB
fmtalpha

AFT
Figura 7.19 Acciones del sistema de archivos en la apertura.

Acceso a archivos montados Un sistema de archivos se monta en un punto de montaje utili-


zando el comando mount (FS_name, mount_point_name) (consulte la sección 7.4). Una
forma sencilla de implementar el montaje es cambiar temporalmente la entrada del directorio de
mount_point_name en su directorio raíz de modo que apunte a la entrada del directorio
de FS_name.
El sistema de archivos debe prestar especial atención al cruce de un punto de montaje du-
rante la resolución del nombre de la trayectoria. Para este efecto, coloca el valor “M” en el

08 MAQ. CAP. 07(F0694).indd 328 8/10/07 1:03:03 AM


7.8 Implementación del acceso a archivos 329

campo flags de la entrada del directorio de FS_name y mantiene una mount table (tabla de
montaje) a fin de almacenar pares de la forma (FS_name, mount_point_name). Duran-
te la resolución de cada trayectoria, esta tabla se consulta cuando se encuentra un punto de
montaje mientras se recorre la jerarquía del directorio de padre a hijo (para el operador “/” en el
nombre de la trayectoria) o de hijo a padre (para el operador “..” en el nombre de la trayectoria).
El sistema de archivos también debe asegurar que la asignación de espacio de disco realizada
durante el procesamiento de un archivo montado debe estar en el sistema de archivos montados,
más que en el sistema de archivos huésped.

Ejemplo 7.9 Cuando se ejecuta la llamada mount (meeting, ~A/admin) de la sección 7.4, el
sistema de archivos cambia la entrada del directorio de admin de modo que apunte a meeting. La
jerarquía del directorio cambiado ahora semeja a la jerarquía que se muestra en la figura 7.11b).
La entrada del directorio de meeting contiene a “M” en su campo flags, y la tabla de montaje con-
tiene al par (meeting, ~A/admin). Esta información es adecuada para la resolución del nombre
de la trayectoria.

7.8.2 Acciones del sistema de archivos en la operación de un archivo

Una vez que se abre un archivo filename, un proceso iniciado por el usuario U realiza algunas
operaciones de lectura o escritura. Cada una de tales operaciones se traduce en una llamada

opn (internal id, record id, IO_area addr);

donde internal id es la identificación interna de filename devuelta por la llamada open.


(Observe que record id puede no estar en el caso de un archivo secuencial, ya que una operación
siempre se realiza en el siguiente registro.) El sistema de archivos lleva a cabo las siguientes
acciones para procesar esta llamada:
1. Localiza el FCB de filename en la AFT utilizando internal id.
2. Busca la lista de control de acceso de filename para el par (U,...). Proporciona un
error si opn no existe en la lista de privilegios de acceso de U. Este paso requiere una
referencia a la lista de control de acceso de filename. Esta referencia puede realizarse
usando el apuntador FCB del directorio. De manera alternativa, la lista de control de
acceso puede copiarse en el FCB una vez que se abre el archivo. De esta forma, no es
necesario acceder a la entrada del directorio del archivo para cada operación de éste.
3. Hace una llamada iocs-read o iocs-write con los parámetros internal id, record id y
IO_area addr.
El módulo IOCS iocs-read se llama para una operación read. Obtiene la FMT del FCB
del archivo y convierte record id en un par (disk block id, byte offset) utilizando la FMT. Si la
ejecución de la operación iocs-write requiere que en el archivo se escriba un nuevo registro,
entonces puede ser que el módulo IOCS requiera llamar a un módulo idóneo del sistema de ar-
chivos que pueda asignar un nuevo bloque de disco y agregar sus direcciones a la FMT.

Ejemplo 7.10 Siguiendo la llamada open del ejemplo 7.8, una declaración read (alpha, 25, . . .)
en el proceso, donde 25 es la record id, debe traducirse en iocs-read (6, 25). Si el tamaño de los
bloques de disco es de 1 000 bytes cada uno, y la longitud de un registro es de 100 bytes, entonces

08 MAQ. CAP. 07(F0694).indd 329 8/10/07 1:03:03 AM


330 CAPÍTULO 7 Sistema de archivos

IOCS debe convertir record id en un número de bloque de disco  3 y el número de registro en el


bloque de disco  5. Con esto se obtiene el byte de desplazamiento  400. La identificación
del bloque de disco del tercer bloque de disco asignado a alpha se obtiene a partir de la FMT y este
bloque se lee para obtener el registro deseado.

7.8.3 Acciones del sistema de archivos en el cierre de archivos

Cuando un proceso ejecuta la declaración close (internal id, . . .), el sistema de archivos realiza
las siguientes acciones.
1. Si el archivo ha sido creado o actualizado recientemente:
a) Si se trata de un archivo recientemente creado, usa el apuntador FCB del directorio
para localizar el FCB del directorio en el que debe estar el archivo. Crea una entra-
da para el archivo en este directorio. Copia la FMT del nuevo archivo o su apuntador,
según sea el caso, en esta entrada. Si la entrada del directorio contiene un apunta-
dor hacia la FMT en vez de la FMT en sí, entonces primero se escribe la FMT en
un bloque de disco y la dirección del bloque de disco es ingresada en la entrada del
directorio.
b) Si el archivo ha sido actualizado y su tamaño ha cambiado, entonces la entrada del
directorio se actualiza utilizando el apuntador FCB del directorio.
c) En caso de ser necesario, repite los pasos 1b)-1c) para actualizar otros directorios en
el nombre de la trayectoria después de establecer el apuntador de archivos FBC :
apuntador FCB del directorio y apuntador FCB del directorio : Dirección (FCB de
la raíz del directorio).
2. El FCB del archivo y los FCB de sus directorios raíz y antecesor se borran de la FMT.

info info

alpha alpha
pi

Apuntador
FCB del fcbinfo fmtpi
directorio fmtpi
Apuntador fcbpi
de archivos
FBC
AFT
a) b)
Figura 7.20 Acciones del sistema de archivos en el close.

Ejemplo 7.11 En la figura 7.20 se ilustran las acciones del sistema de archivos antes y después
de la ejecución del comando close/info/pi para un archivo pi recientemente creado. En el
directorio info se crea una entrada para pi y en el campo Loc info de esta entrada se coloca un

08 MAQ. CAP. 07(F0694).indd 330 8/10/07 1:03:03 AM


7.9 Semántica para compartir archivos 331

apuntador hacia fmtpi. Al agregar esta entrada a info se incrementa el tamaño de info, de modo
que quizá sea necesario asignar a info un bloque de disco adicional. Esto implica la actualización
de la FMT de info (consulte los pasos 1b) y 1c) de las acciones en close).

7.9 SEMÁNTICA PARA COMPARTIR ARCHIVOS

Como se analizó en la sección 7.5, el propietario de un archivo puede autorizar a otros usuarios
el acceso al archivo. Los usuarios autorizados pueden leer, escribir o ejecutar el archivo según
los privilegios que les hayan sido otorgados. Esencialmente, comparten los archivos a los que
tienen acceso.
Los modos en que se comparten archivos son de manera secuencial y concurrente (o si-
multánea). La primera ocurre cuando usuarios autorizados acceden a un archivo compartido
uno después de otro. Resulta evidente que las modificaciones hechas al archivo por un usuario,
en caso de haberlas, son visibles para los usuarios que acceden después al archivo. Compartir
archivos de manera concurrente ocurre cuando dos o más usuarios acceden a un archivo durante
el mismo lapso de tiempo. La semántica para compartir archivos determina la manera en que
los resultados de las manipulaciones de los archivos hechas por los usuarios simultáneos son
visibles para todos ellos.
La manera secuencial de compartir archivos puede implementarse agregando un campo de
candado a cada entrada del directorio. Este campo es un solo bit que contiene los valores “set”
o “reset”. La operación open en un archivo tiene éxito si el campo de candado en la entrada del
directorio del archivo tiene el valor “reset” y establece el reloj; en caso contrario, la operación
open fracasa y es necesario repetirla. Una operación close siempre restablece el reloj. Este
arreglo asegura que sólo un proceso puede utilizar el archivo en cualquier momento. La creación
y la destrucción de FCB se llevan a cabo según se analizó en la sección 7.8.
A continuación se considerarán dos procesos P1 y P2 que comparten de manera simultánea
un archivo secuencial alpha. Como se vio en la sección 7.6, la dirección del siguiente registro
al que accederá un proceso está contenida en un FCB del archivo. Por tanto, el primer reque-
rimiento para evitar la interferencia entre estos procesos es que el sistema debe crear un FCB
por separado para cada proceso. Este arreglo puede establecerse muy fácilmente. El sistema de
archivos puede simplemente seguir el procedimiento de la sección 7.8.1 cada vez que se abre
un archivo alpha. Tal procedimiento debe asegurar que para cada proceso que comparte el ar-
chivo se crea un FCB. El FCB de alpha creado para el proceso P1 se denota por fcbP1 alpha .
La manera concurrente de compartir un archivo puede implementarse en uno de los tres
modos siguientes:

• Compartir de manera concurrente usando archivos inmutables: Ningún proceso puede


modificar el archivo que está siendo compartido.
• Compartir de manera concurrente usando archivos mutables con imagen individual: Una
imagen es una vista de un archivo. Todos los procesos que comparten simultáneamente
un archivo “ven” la misma imagen del archivo. Así, las modificaciones hechas a un archi-
vo son visibles de inmediato para los otros procesos que están utilizando el archivo.
• Compartir de manera concurrente usando archivos mutables con imagen múltiple: Cada
proceso que accede al archivo posee su propia imagen del archivo. El sistema de archivos
mantiene muchas imágenes de un archivo o puede conciliarlas de alguna manera para

08 MAQ. CAP. 07(F0694).indd 331 8/10/07 1:03:03 AM


332 CAPÍTULO 7 Sistema de archivos

crear una imagen individual cuando los procesos cierran el archivo. De hecho, en cual-
quier momento pueden existir muchas versiones del archivo y las actualizaciones hechas
por un usuario pueden no ser visibles en algunos procesos simultáneos.

Estos modos de compartir tienen varias implicaciones para el sistema de archivos y para los
usuarios que comparten un archivo.

Compartir archivos inmutables Cuando el archivo alpha se comparte como un archivo


inmutable, ninguno de los procesos que lo comparten puede modificarlo. Esta forma de compar-
tir tiene la ventaja de que los procesos implicados son independientes entre sí: el orden en que
los registros de alpha son procesados por P1 no tienen ninguna importancia para la ejecución de
P2. La creación de un fcbalpha para cada proceso implicado es adecuada para implementar esta
forma de compartir archivos.
Cuando los archivos son mutables surgen dos cuestiones importantes, que son:

• Visibilidad de modificaciones en alpha realizadas por un proceso a otros procesos que


comparten alpha.
• Interferencia entre procesos que comparten alpha.
Compartir archivos mutables con imagen individual En los archivos mutables con ima-
gen individual una copia individual del archivo es compartida por los procesos que acceden a él,
por lo que los cambios hechos por un proceso son visibles de inmediato para los otros procesos.
A fin de implementar esta forma de compartir, es esencial que una copia individual de la FMT
sea utilizada por todos los procesos que comparten el archivo. Por tanto, es mejor mantener un
apuntador hacia la FMT, en vez de hacia la FMT en sí, como en un FCB.
En la figura 7.21 se muestra la manera concurrente de compartir el archivo alpha utilizando
P2
un arreglo así. Para alpha hay dos FCB denotados por fcbP1 alpha y fcbalpha , ambos apuntado a la
misma copia de fmtalpha. Cada FCB contiene la dirección del siguiente registro que será atendido
por un proceso. Si el conjunto de los registros procesados por P1 y P2 se traslapan, entonces sus
modificaciones deben ser visibles mutuamente. En tales situaciones pueden ocurrir condiciones
de carrera, y quizá se pierdan las modificaciones hechas por los procesos. Un sistema de archi-
vos típico no proporciona ninguna protección contra este problema; puede ser necesario que los
procesos que comparten el archivo tengan que hacer evolucionar sus propias convenciones de
sincronización para este efecto. El sistema de archivos Unix proporciona archivos mutables con
imagen individual. La semántica para compartir archivos Unix se analizará en la sección 7.12.2.

Compartir archivos mutables con imagen múltiple En los archivos mutables con imagen
múltiple, muchos procesos pueden actualizar alpha de manera simultánea. Cada proceso de
actualización crea una nueva versión de alpha, que es distinta de las versiones creadas por otros
procesos simultáneos. En este esquema, para cada FCB debe existir un distinto fmtalpha y debe
apuntar a una copia exclusiva del archivo. Este requerimiento se implementa mejor al hacer una
copia de alpha (y su FMT) para cada proceso que lo actualice de manera simultánea. alphaP1
representa la copia de alpha hecha por el proceso P1.
En la figura 7.22 se ilustra el arreglo para implementar archivos mutables con imagen múl-
tiple. Los procesos P1 y P2 están ocupados actualizando alpha. El procesamiento hecho por
P1 utiliza fcbP1 P1
alpha y fmt alpha para acceder a alpha , mientras el procesamiento hecho por P2
P1

utiliza fcbalpha y fmtalpha para acceder a alpha . alphaP1 y alphaP2 son de esta forma dos
P2 P2 P2

08 MAQ. CAP. 07(F0694).indd 332 8/10/07 1:03:04 AM


7.10 Confiabilidad del sistema de archivos 333

fcbP1
alpha

Bloque de datos
de alpha
fcbP2
alpha
fmtalpha

AFT

Figura 7.21 Compartir de manera concurrente un archivo mutable con imagen individual por los procesos P1 y P2.

fmtP1
alpha
Bloque de datos
de alpha P1 fcbP1
alpha

fcbP2
alpha
Bloque de datos
de alpha P2
fmtP2
alpha AFT

Figura 7.22 Compartir de manera concurrente un archivo mutable con imagen múltiple.

versiones de alpha. Para llegar a un esquema de implementación único, la semántica para com-
partir archivos debe especificar cómo los procesos que sólo quieren leer a alpha podrán acceder
a éste, es decir, a qué versión de alpha deben acceder.
Compartir archivos mutables con imagen múltiple es posible sólo en aplicaciones donde
tiene sentido la existencia de versiones múltiples debido a actualizaciones concurrentes. La se-
mántica para compartir archivos mutables con imagen múltiple es bastante difícil de comprender
e implementar. En la sección 19.3 se analizará la semántica de la sesión utilizada para archivos
mutables con imagen múltiple.

7.10 CONFIABILIDAD DEL SISTEMA DE ARCHIVOS

La confiabilidad del sistema de archivos concierne a la capacidad de un sistema de archivos


para funcionar correctamente a pesar de la ocurrencia de fallas en el sistema. Dos aspectos de la
confiabilidad del sistema son los siguientes:

• Asegurar que la creación, borrado y actualización de archivos sean correctos.


• Evitar la pérdida de datos en los archivos.

08 MAQ. CAP. 07(F0694).indd 333 8/10/07 1:03:04 AM


334 CAPÍTULO 7 Sistema de archivos

En la literatura sobre confiabilidad se distingue entre los términos fallo y fracaso. Un fallo es
un defecto en alguna parte del sistema. Un fracaso es un comportamiento del sistema que
es erróneo, o por lo menos diferente del esperado. La ocurrencia de un fallo provoca un fracaso.
Así, la corrupción de un bloque de disco debido a que la cabeza de un disco está dañada o debido
a un apagón eléctrico es un fallo, mientras la incapacidad del sistema de archivos para leer un
bloque de archivos es un fracaso. En este capítulo, tales términos se usarán de manera informal
y como sinónimos. En el capítulo 18 se usarán estos términos con precisión.
La corrupción de datos en los bloques de disco y en bloqueos del sistema debido a inte-
rrupciones de energía eléctrica suelen ser fallas comunes que conducen a problemas de con-
fiabilidad en sistema de archivos. La corrupción de datos provoca pérdida de datos en los
archivos o de datos de control del sistema de archivos almacenados en el disco. Un sistema
de archivos puede no ser capaz de continuar una operación significativa si los datos de con-
trol del sistema de archivos están perdidos o se vuelven inconsistentes. El daño provocado por la
pérdida de datos en un archivo debido a corrupción de datos es comparativamente menos grave,
ya que se limita a un solo archivo.

7.10.1 Pérdida de la integridad de los sistemas de archivos

La integridad de los sistemas de archivos implica la veracidad y consistencia de los datos de


control y de las operaciones en el sistema de archivos. La pérdida de integridad se presenta si
los datos de control del sistema de archivos se pierden o dañan. Resulta interesante ver por qué
ocurre esto. Para asegurar una operación eficaz, el sistema de archivos mantiene en la memoria
algo de sus datos de control. Esto incluye la tabla de archivos activos, que contiene bloques de
control de archivos de archivos abiertos, partes del mapa de estado del disco o listas libres
de bloques de disco, así como tablas del mapa de archivos de archivos abiertos. Partes de estos
datos, como la tabla del mapa de archivos, se escriben en un disco una vez que se cierra un ar-
chivo. Además, el sistema puede copiar periódicamente en el disco sus datos de control, a saber,
el mapa de estado del disco y las listas libres. Debido a este arreglo, las copias en el disco de los
datos de control pueden no contener información actualizada durante la operación del sistema,
de modo que los datos de control se pierden cuando falla la energía eléctrica. Los datos de con-
trol que no están en la memoria se pierden cuando un disco se bloquea.
Considere un proceso que actualiza un archivo alpha. Las siguientes estructuras de datos
deben existir en la memoria mientras se ejecuta el proceso: fcbalpha (que existe en la tabla de
archivos activos), parte de fmtalpha y parte del mapa de estado del disco. Estos datos se perderán
si el sistema se bloquea. Esta situación puede resultar en una o más de las siguientes fallas:
1. Algunos datos del archivo alpha pueden perderse.
2. Parte del archivo alpha puede volverse inaccesible.
3. El contenido de dos archivos puede mezclarse.
Resulta fácil visualizar una situación del primer tipo. Por ejemplo, considere que un fallo ocurre
después de que un nuevo bloque de disco se agrega al archivo alpha. La copia en el disco de
fmtalpha puede no contener esta identificación de disco, de modo que los datos en el bloque re-
cién agregado se pierden cuando ocurre un fallo. Situaciones del segundo y tercer tipos pueden
presentarse si el sistema de archivos utiliza el esquema de asignación ligada y ocurre un fallo
mientras un nuevo disco se está agregando a un archivo mediante el algoritmo 7.1.

08 MAQ. CAP. 07(F0694).indd 334 8/10/07 1:03:05 AM


7.10 Confiabilidad del sistema de archivos 335

Algoritmo 7.1 (Add block dj between blocks d1 and d2)

Input :
d1 , d2 , d j : record
next : ; { id of next block }
data : ;
end
1. d j .next := d1 .next;
2. d1 .next := address (d j );
3. Write d1 to disk.
4. Write d j to disk.

El algoritmo 7.1 agrega un nuevo bloque de disco dj entre los bloques d1 y d2 del archivo.
En la figura 7.23 se ilustra cómo partes del archivo alpha pueden volverse inaccesibles. En la
figura 7.23a) se muestra el archivo antes de la ejecución del algoritmo. Si ocurre un fallo entre
los pasos 3 y 4 del algoritmo 7.1, un nuevo contenido podrá escribirse en el bloque de disco d1,
pero no en el bloque de disco dj. Por tanto, d1.next apuntará hacia dj, mientras dj no contendrá
información de control correcta en su campo next (consulte la figura 7.23b)). Los bloques de
disco d2, d3, . . . ya no serán accesibles como partes del archivo.

d1 d2 d1 d2

dj

a) b)

Figura 7.23 Un fallo mientras se agrega un bloque de disco a un archivo conduce a pérdida de datos.

El contenido de dos archivos puede mezclarse si el sistema de archivos escribe datos de


control en el disco sólo cuando está cerrando un archivo, y no después de cada operación del
archivo. Considere la siguiente situación: un proceso P1 borra un bloque de disco dk de al-
gún archivo beta. dk se devolverá a la lista libre (o se marcará como libre en el mapa de estado
del archivo). Luego, otro proceso P2 agrega un nuevo registro al archivo alpha. El sistema de
archivos asigna un nuevo bloque de disco dj para este efecto y lo agrega antes que el bloque
de disco dm en el archivo alpha (consulte la figura 7.24a)). Después, considere la situación
cuando dj  dk y en el sistema ocurren los eventos siguientes:
1. Se cierra el archivo alpha.
2. El sistema de archivos actualiza la copia en el disco del archivo alpha y fcbalpha. Esto
implica agregar el bloque de disco dj a alpha.
3. Ocurre un fallo.
El disco contiene una copia antigua de beta, que contiene el bloque dk, y la nueva copia de
alpha, que contiene el bloque dj. Debido a que dj  dk, entonces alpha y beta comparten el

08 MAQ. CAP. 07(F0694).indd 335 8/10/07 1:03:05 AM


336 CAPÍTULO 7 Sistema de archivos

bloque de disco dj y todos los otros bloques accesibles a través de dj (consulte la figura 7.24b)).
Todos los bloques de disco del archivo beta previamente accesibles a través de dk ahora son in-
accesibles. En efecto, algunos datos son comunes a los archivos alpha y beta, mientras algunos
datos de beta se han perdido.

dk dl dl
beta
di dm di dj dm
alpha

a) b)
Figura 7.24 a) Archivos alpha y beta, b) cuando dj  dk y alpha se cierra.

7.10.2 Técnicas de confiabilidad del sistema de archivos

Los sistemas operativos utilizan dos técnicas para asegurarse de que los archivos del usuario
están almacenados de manera confiable durante un tiempo determinado. La recuperación es una
técnica clásica utilizada cuando se observa un fracaso. Restituye los datos en archivos y los datos
de control del sistema de archivos en algún estado consistente previo. Luego, el sistema de archi-
vos reanuda su operación a partir de ese estado. Así, hay desviaciones con respecto al comporta-
miento correcto, pero cuando se observan desviaciones se rectifica la operación del sistema.
La tolerancia de fallos es una técnica para protegerse contra la pérdida de integridad del
sistema de archivos cuando ocurre un fallo. Está dirigida a proporcionar operación del sistema
de archivos que sea ininterrumpida y correcta todo el tiempo.

7.10.2.1 Técnicas de recuperación


El estado del sistema de archivos en algún instante ti es la colección de todos los usuarios y datos
de control que hay en el sistema de archivos en ti. Un respaldo del sistema de archivos es una
grabación del estado del sistema de archivos. Para admitir la recuperación, el sistema de archivos
produce respaldos de manera periódica durante su operación. Sea tlb el instante en que se produjo
el último respaldo. En caso de un fracaso, por ejemplo, en el instante tf, el sistema de archivos
se restituye en el estado grabado en su último respaldo. Con esta acción se recuperan todas las
actualizaciones de los archivos antes de tlb. Sin embargo, las actualizaciones efectuadas antes de
tlb y tf se pierden, de modo que los procesos que llevan a cabo tales actualizaciones deben volver
a ejecutarse después de la recuperación.
Las acciones de recuperación en un sistema de archivos implican dos tipos de sobrecarga:
la originada por la creación de respaldos y la debida al reprocesamiento. La segunda es el costo
de volver a ejecutar un proceso cuyas actualizaciones se perdieron. Una forma interesante de re-
ducir la sobrecarga es utilizar una combinación de respaldos por incrementos y completos de
un sistema de archivos. Un respaldo por incrementos contiene copias de sólo aquellos archivos y
estructuras de datos que fueron modificados después de la creación del último respaldo completo
o por incrementos. El sistema de archivos crea respaldos completos a grandes intervalos de tiem-
po, por ejemplo, de unos días o una semana. Los respaldos por incrementos se crean a intervalos

08 MAQ. CAP. 07(F0694).indd 336 8/10/07 1:03:05 AM


7.10 Confiabilidad del sistema de archivos 337

más cortos, por ejemplo, en cada operación de cierre de archivo, y se descartan una vez que se
crea el siguiente respaldo completo.
Después de un bloqueo, el sistema se restaura a partir del último respaldo completo. Luego,
los respaldos por incrementos se procesan en el mismo orden en que fueron creados. Así, los ar-
chivos cuya modificación se terminó antes del fracaso deben recuperarse por completo. Los
archivos que estaban siendo modificados en el momento del fracaso no se restauran por com-
pleto. Puede incurrirse en algún costo de reprocesamiento por volver a ejecutar los procesos que
estaban en ejecución en el momento de fracaso del sistema. La sobrecarga por espacio también
podrá aumentar porque los respaldos completos y por incrementos coexisten y algunos archivos
pueden existir en más de un respaldo por incrementos.

Ejemplo 7.12 En la figura 7.15 se ilustra un sistema en el que se tomaron respaldos completos
en los instantes t1 y t4 y respaldos por incrementos en los instantes t2 y t3. Observe que los tamaños
de los respaldos por incrementos varían dependiendo del número de archivos actualizados desde
el último respaldo completo o por incrementos. Si después de t4 ocurre un fracaso, entonces el
sistema debe ser restaurado en el estado grabado en el respaldo tomado en t4. Si ocurre un fracaso
entre t3 y t4, el sistema debe restaurarse primero en el estado grabado en el respaldo tomado en t1.
Después de que se hace esto, los respaldos por incrementos tomados en t2 y t3 deben procesarse
en ese orden. Un método alternativo será procesar los respaldos por incrementos y completos en
orden inverso, es decir, procesar el respaldo por incrementos tomado en t3, seguido del respaldo por
incrementos tomado en t2, seguido del respaldo completo tomado en t1. Es necesario tener cuidado
de no restaurar un archivo que ya haya sido restaurado a partir de un respaldo posterior.

Respaldo por
incrementos
Respaldo completo

0 t1 t2 t3 t4

Figura 7.25 Respaldos completo y por incrementos para recuperación.

7.10.2.2 Técnicas de tolerancia de fallos


La confiabilidad del sistema de archivos puede mejorarse si se toman dos precauciones: evitar
la pérdida de datos debido a mal funcionamiento del dispositivo y evitar la inconsistencia de los
datos de control debido a fracasos. Estas precauciones se implementan aplicando las técnicas de
tolerancia de fallos de almacenamiento estable y acciones atómicas, respectivamente.

Almacenamiento estable La técnica de almacenamiento estable propuesta por Lampson


proporciona confiabilidad de un registro de datos en presencia de un fracaso simple. En un disco
se mantienen dos copias de un registro, denominadas copia primaria y copia secundaria. Una
operación de escritura actualiza ambas copias: la copia primaria se actualiza primero, seguida

08 MAQ. CAP. 07(F0694).indd 337 8/10/07 1:03:05 AM


338 CAPÍTULO 7 Sistema de archivos

de la copia secundaria. Para una operación de lectura, se accede al bloque de disco que contiene
a la copia primaria. Si es ilegible, se accede al bloque de disco que contiene la copia secundaria.
Debido a que se supone que sólo ocurren fracasos simples, es seguro que uno de los bloques
contiene datos legibles.
En la figura 7.26 se ilustra la operación de la técnica de almacenamiento estable si ocurren
fracasos en los instantes t1, t2, t3 o t4, respectivamente, mientras un proceso P está ejecutando
una operación de actualización en algunos datos D. En los incisos a)-d) se muestran diagramas
de asignación de tiempos y valores en las copias primaria y secundaria de D cuando ocurren
fracasos. En el inciso a), un fracaso ocurre en el instante t1, es decir, antes de que se actualice la
copia primaria, de modo que ésta, que contiene el valor antiguo de los datos, es accesible después
de un fracaso. En el inciso b), un fracaso ocurre mientras se está actualizando la copia primaria,
haciéndola ilegible. El valor antiguo de los datos es accesible desde la copia secundaria. En el
inciso c), un fracaso ocurre después de la actualización de la copia primaria pero antes de la ac-
tualización de la copia secundaria. Los nuevos datos son accesibles en la copia primaria después
del fracaso. En el inciso d), el fracaso ocurre después de que se han actualizado ambas copias, de
modo que permanecen accesibles.

La copia La copia
primaria se secundaria se Copia Copia
actualiza actualiza primaria secundaria
a)
antigua antigua
b)
ilegible antigua
c)
nueva antigua
d)
nueva nueva

t1 t2 t3 t4 tiempo →

Figura 7.26 Tolerancia de fallos utilizando la técnica de almacenamiento estable.

La técnica de almacenamiento estable puede aplicarse a archivos completos. Lampson de-


nominó a esta técnica efecto de espejo en un disco (aunque es diferente de la técnica de efecto
de espejo en un disco que se utiliza en RAID: consulte la sección 12.3). El efecto de espejo es
muy costoso para su uso general en un sistema de archivos; los procesos pueden utilizarlo se-
lectivamente para proteger sus datos. También, mientras el efecto de espejo garantiza que una
copia de datos sobrevivirá a un fracaso simple, no puede indicar si este valor es nuevo o antiguo
[consulte los incisos a) y d) de la figura 7.26], de modo que el usuario no sabe si volver a ejecu-
tar la operación de actualización en P cuando se restaure la operación del sistema. Una acción
atómica supera este problema.

Acciones atómicas Una acción puede implicar la manipulación de muchas estructuras de


datos. Las estructuras de datos pueden volverse inconsistentes si un fracaso interrumpe su ejecu-

08 MAQ. CAP. 07(F0694).indd 338 8/10/07 1:03:06 AM


7.10 Confiabilidad del sistema de archivos 339

ción. Por ejemplo, considere una aplicación bancaria que transfiere fondos de una cuenta a otra.
Si un fracaso interrumpe su ejecución, los fondos pueden haber sido adeudados a una cuenta
pero no acreditados a la otra cuenta o viceversa. Las acciones atómicas están orientadas a evitar
estos efectos perniciosos de los fracasos.

Definición 7.1 (Acción atómica) Una acción Ai que consta de un conjunto de subacciones
兵aij其 es una acción atómica si para toda ejecución de Ai ocurre una de las dos opciones si-
guientes:
1. Se llevan a cabo los efectos de todas las subacciones en 兵aij其, o bien
2. No se llevan a cabo los efectos de ninguna de las subacciones.

Una acción atómica Ai posee una propiedad de todo o nada, que evita la inconsistencia de
datos cuando ocurre algún fracaso. En la figura 7.27 se muestra el algoritmo 7.1 codificado como
una acción atómica denominada add a block. Difiere del algoritmo 7.1 sólo en el uso de las decla-
raciones begin atomic action y end atomic action. La ejecución de una acción atómica comienza
con la declaración begin atomic action. Puede terminar en dos formas: fracasar o tener éxito. Una
acción atómica fracasa si se ejecuta una declaración abort o si ocurre un fracaso antes de que se
ejecute la declaración end atomic action. Si fracasa, el estado de cada archivo y cada variable
usados por la acción atómica debe ser el que era antes de la ejecución de la declaración begin
atomic action. Una acción atómica tiene éxito cuando ejecuta la declaración end atomic action.
Se dice que la acción atómica se comete en este punto. Se garantiza que todas las actualizaciones
realizadas por la acción atómica sobreviven a cualquier fracaso una vez que se comete.

begin atomic action add a block;


d j .next := d1 .next;
d1 .next := address d j ;
write d1 ;
write d j ;
end atomic action add a block;

Figura 7.27 Acción atómica add a block.

Por tanto, se tiene la garantía de que la ejecución de la acción atómica add a block de la
figura 7.27 conduce a una de las dos siguientes posibilidades. Si se comete la acción atómica, el
bloque de disco dj se agrega al archivo alpha, que ahora consta de los bloques de disco . . . d1, dj,
d2, . . . Si la acción atómica falla, el bloque de disco dj no se agrega al archivo alpha, es decir,
alpha continúa consistiendo en los bloques de disco . . . d1, d2, . . . La consistencia de los datos
de control del sistema de archivos puede preservarse si se actualizan las estructuras de datos del
sistema de archivos utilizando acciones atómicas. Los sistemas de bases de datos usan acciones
atómicas para asegurar también algunas otras propiedades; este análisis está restringido sólo a la
confiabilidad del sistema de archivos.
La implementación de las acciones atómicas puede hacerse de varias formas. En un método
de implementación, los archivos no se actualizan durante la ejecución de la acción atómica. En
vez de ello, los detalles de las actualizaciones que se van a realizar se anotan en una lista que se
denomina lista de intenciones (intentions list). Esta lista contiene pares de la forma (disk block
id, new_contents) indicando que new_contents debe escribirse en el bloque de disco

08 MAQ. CAP. 07(F0694).indd 339 8/10/07 1:03:06 AM


340 CAPÍTULO 7 Sistema de archivos

con la identificación disk block id. La información en la lista de intenciones se utiliza para
actualizar los archivos cuando se comete la acción atómica. Esto se denomina procesamiento de
comisión.
Este arreglo automáticamente tolera fallos que ocurren cuando se comete una acción
atómica, ya que en los archivos no se habrían podido efectuar actualizaciones. Así, implementa
la parte “nada” de la propiedad todo o nada. Mientras se realizan las actualizaciones es necesario
asegurar que todas éstas se terminen incluso si durante el procesamiento de comisión ocurren
fallas. Esta característica del procesamiento de comisión implementará la parte “todo” de la
propiedad todo o nada.
Con cada acción atómica está asociada una bandera de comisión. Ésta contiene dos campos:
identificación de la transacción y valor. Dicha bandera se crea cuando se ejecuta la declaración
begin atomic action de una acción atómica Ai y sus campos se inicializan en Ai y en “not com-
mitted”. La bandera de comisión se cambia a “committed” cuando se ejecuta end atomic action.
La bandera se destruye después de que se han llevado a cabo todas las actualizaciones.
Tanto la lista de intenciones como la bandera de comisión se mantienen en almacenamiento
estable para su protección en contra de corrupción de datos y pérdida debido a fallos. Cuando un
sistema se recupera después de un fallo, verifica la presencia de banderas de comisión. Si para
Ai existe una bandera de comisión que tiene el valor “not committed”, simplemente se destruye
y la acción atómica Ai se ejecuta de nuevo empezando con la declaración begin atomic action.
La existencia de una bandera de comisión para Ai con el valor “committed” implica que un
procesamiento de comisión de Ai estaba llevándose a cabo cuando ocurrió el fallo. Debido a
que no se sabe si alguna de las entradas de la lista de intenciones ya estaba procesada antes
del fallo, entonces se repite todo el procesamiento de comisión. Observe que en este arreglo
es posible hacer más de una vez una actualización si durante el procesamiento de comisión
ocurre un fallo.
Para asegurar que el procesamiento repetido de una lista de intenciones no plantea ningún
problema de consistencia de datos, una operación de actualización debe ser idempotente. Es decir,
la ejecución de la operación de actualización más de una vez debe dar el mismo resultado que si
se hubiera ejecutado una sola vez. Si éste no es el caso, entonces los archivos pueden contener
diferentes valores si una operación de actualización se repite debido a un fallo ocurrido durante
el procesamiento de comisión. (¡Imagine que la edad de alguien se incrementa por más de 1 el
31 de diciembre!) Escribir new contents en el bloque de disco con la identificación disk
block id constituye una operación idempotente, de modo que los problemas concernientes a
la consistencia de datos no se presentan, incluso si los fallos ocurren durante el procesamiento de
comisión. En el algoritmo 7.2 se resumen todas estas acciones relacionadas con la implementa-
ción de una acción atómica.

Algoritmo 7.2 (Implementación de una acción atómica)

1. Ejecución de una acción atómica:


a) Efectuar las siguientes acciones cuando se ejecute la declaración begin atomic
action de la acción atómica Ai:
commit flag : (Ai, ‘not committed’);
intentions list : ‘empty’;
Tanto commit flag como intentions list se mantienen en almacenamiento estable.

08 MAQ. CAP. 07(F0694).indd 340 8/10/07 1:03:06 AM


7.11 Sistema de archivos virtuales 341

b) Para toda actualización de un archivo hecha por una subacción, agregar un par (d, v)
a la lista de intenciones, donde d es la identificación de un bloque de disco y v es su
nuevo contenido.
c) Cuando se ejecute la declaración end atomic action, establecer el valor del valor de
la commit flag de Ai en “committed” y efectuar el paso 2.
2. Procesamiento de comisión:
a) Para todo par (d, v) en la lista de intenciones, escribir v en el bloque de disco con la
identificación d.
b) Borrar la bandera de comisión y la lista de intenciones.
3. Para recuperación después de un fallo:
Si para la acción atómica Ai existe la bandera de comisión,
a) Si el valor en la bandera de comisión es “not committed”: Borrar la bandera de co-
misión y la lista de intenciones. Volver a ejecutar la acción atómica Ai.
b) Hacer el paso 2 si el valor en la bandera de comisión es “committed”.

Bloque Nuevo
de disco contenido
dj
Identificación de
d1 la transacción Valor d1 d1
d2 add a block NC d2
dj
Bandera de comisión Lista de intenciones
a) b)
Figura 7.28 a) antes, b) después del procesamiento de comisión (nota: NC significa not committed).

Ejemplo 7.13 En la figura 7.28a) se ilustran el archivo alpha, la bandera de comisión y la lista de
intenciones cuando el algoritmo 7.2 se aplica a la acción atómica de la figura 7.27. El nuevo conte-
nido de los bloques de disco dj y d1 se mantienen en la lista de intenciones hasta el procesamiento
de comisión. La atomicidad de la acción se asegura como sigue: si durante el paso del algoritmo
ocurre un fallo, ninguna de las actualizaciones de archivos se refleja en el disco. Por tanto, el
archivo contiene la secuencia original de los bloques de disco d1, d2, . . . Un fallo en el paso 2 podrá
corromper algunos datos; no obstante, la lista de intenciones y la bandera de comisión no se ven
afectadas porque existen en la tabla de almacenamiento. Un fallo en el paso 2 conduce a un proce-
samiento de comisión repetido. Esto no interfiere con la consistencia de los datos, ya que el nue-
vo contenido simplemente se escribe en bloques de disco durante el procesamiento de comisión.
Así, como se muestra en la figura 7.28b), el archivo contiene la secuencia de bloques de disco
d1, dj, d2, . . . al final del procesamiento de comisión.

7.11 SISTEMA DE ARCHIVOS VIRTUALES

Los usuarios tienen distintos requerimientos de un sistema de archivos, como conveniencia, alta
confiabilidad, respuesta rápida y acceso a los archivos en otros sistemas de cómputo. Un solo
sistema de archivos no puede proporcionar todas estas características, de modo que un sistema

08 MAQ. CAP. 07(F0694).indd 341 8/10/07 1:03:07 AM


342 CAPÍTULO 7 Sistema de archivos

operativo proporciona un sistema de archivos virtuales (VFS) que facilita la operación simul-
tánea de varios sistemas de archivos. De esta forma, cada usuario puede utilizar el sistema de
archivos de su preferencia.
Un sistema de archivos virtuales (VFS) es una abstracción que admite un modelo de archivo
genérico. La abstracción es implementada por una capa VFS que está situada entre un proceso
y un sistema de archivos (consulte la figura 7.29). La capa VFS posee dos interfaces: una con
los sistemas de archivos y otra con los procesos. Cualquier sistema de archivos que se ajusta a
la especificación de la interfaz VFS-sistema de archivos puede instalarse para trabajar según la
especificación. Esta característica hace fácil agregar un nuevo sistema de archivos. La interfaz
VFS-proceso proporciona funciones para ejecutar operaciones genéricas de apertura, cierre, lec-
tura y escritura en los archivos, así como operaciones de montaje y desmontaje en los sistemas
de archivos. Estas funciones se invocan a través de llamadas del sistema. Los VFS determinan
a qué sistema de archivos pertenece realmente un archivo e invocan las funciones de apertura,
cierre, lectura y escritura del sistema de archivos específico a través de la interfaz VFS-sistema
de archivos. También invocan funciones del sistema de archivos específico para implementar las
operaciones de montaje y desmontaje.

Procesos

Sistema de archivos virtuales


Metadatos
(VFS)

Metadatos Datos del Metadatos Datos del Metadatos Datos del


archivo archivo archivo

Sistemas de archivos tipo X Sistemas de archivos tipo Y Sistemas de archivos tipo Z


Figura 7.29 Sistema de archivos virtuales.

Todos los sistemas de archivos que operan bajo VFS están disponibles para su uso simultáneo.
En el sistema de la figura 7.29, un proceso puede utilizar un sistema de archivos de tipo X, mien-
tras otro simultáneamente usa un sistema de archivos de tipo Y. El sistema de archivos virtuales
también puede usarse para integrar un sistema de archivos heterogéneo. Por ejemplo, un usuario
puede montar un sistema de archivos de tipo X en un directorio de un sistema de archivos de tipo
Y. Esta característica es útil con medios removibles como los CD; permite que un usuario monte el
sistema de archivos existente en un CD en su directorio actual y acceda a sus archivos sin ninguna
preocupación por el hecho de que los datos del archivo están grabados en un formato distinto. Esta
característica también es útil en un entorno distribuido para montar un sistema de archivos remoto
en un sistema de archivos de tipo diferente. Esto se describirá en la sección 19.6.1.
Como se muestra en el esquema de la figura 7.29, el sistema de archivos virtuales no con-
tiene datos de archivo. Simplemente incluye estructuras que constituyen los metadatos del VFS.
Cada sistema de archivos contiene sus propios metadatos y sus datos de archivo. La estructura
de datos llave utilizada por el sistema de archivos virtuales es el nodo virtual, conocido popu-

08 MAQ. CAP. 07(F0694).indd 342 8/10/07 1:03:07 AM


7.12 Sistema de archivos de Unix 343

larmente como nodov, que es una representación de un archivo en el kernel. Puede considerarse
como un archivo objeto con las tres partes siguientes:

• Datos independientes del sistema de archivos, como una identificación del archivo que es
única dentro del dominio del VFS, que puede ser el sistema de cómputo individual o una
red; el tipo de archivo, por ejemplo, directorio, archivo de datos o un archivo especial; y
otros campos, como un conteo abierto, candado y banderas.
• Datos específicos del sistema de archivos, como la tabla del mapa de archivos.
• Direcciones de funciones en el sistema de archivos que contienen este archivo. Estas
funciones implementan las operaciones de apertura, lectura y escritura sobre archivos de
este tipo de archivo.

Los sistemas operativos han proporcionado sistemas de archivos virtuales desde la década
de los noventa. Sun OS, Unix System version 4, Unix 4.2 BSD y Linux proporcionan un sis-
tema de archivos virtuales.

7.12 SISTEMA DE ARCHIVOS DE UNIX

Las versiones de Unix difieren del sistema de archivos en características. En esta sección se des-
cribirán características importantes comunes a muchas versiones Unix. El sistema de archivos
de Unix está bastante influido por el sistema de archivos Multics. La estructura del directorio de
Unix es semejante a la de directorio que se analizó en la sección 7.4. Las jerarquías de directorio
se forman al tratar a los directorios en sí como archivos. Para efectos de protección, se definen
tres grupos de usuarios como se analizó en el ejemplo 7.7. Unix admite sólo archivos de flujo
de bytes, es decir, archivos sin ninguna estructura. Los archivos se consideran como flujos de
caracteres y a ellos se accede secuencialmente. El arreglo genérico concerniente al procesamien-
to de archivos descrito en las secciones 7.4 y 7.6 centra el uso de entradas de directorio, FCB
e identificaciones internas. El arreglo utilizado en Unix se centra alrededor de las siguientes
estructuras de datos:

• Ínodos (abreviación de index nodes),


• Descriptores de archivos,
• Estructuras de archivos.

7.12.1 Ínodos, descriptores de archivos y estructuras de archivos

La información en la entrada del directorio de la sección 7.4 se separa entre la entrada del di-
rectorio y el ínodo del archivo. Una entrada del directorio contiene sólo el nombre del archivo.
El volumen de la información concerniente al archivo está contenido en el ínodo. El directorio
en el sistema V contiene entradas de 16 bytes cada una. Los dos primeros bytes contienen el
número de ínodo, mientras los bytes restantes contienen el nombre del archivo, que puede ser
hasta de 14 bytes de longitud. En la versión 4.2 de Unix, el nombre del archivo puede ser hasta
de 255 bytes de longitud. La estructura del archivo contiene dos campos: la posición actual en
un archivo abierto, que está en la forma de un desplazamiento desde el principio del archivo,
y un apuntador hacia el ínodo para el archivo. Un descriptor del archivo apunta a una estructura
de archivo. Su uso semeja el de la identificación interna de un archivo en el arreglo genérico de

08 MAQ. CAP. 07(F0694).indd 343 8/10/07 1:03:08 AM


344 CAPÍTULO 7 Sistema de archivos

las secciones 7.4 y 7.6. Un caché de búsqueda del directorio mantiene información concerniente
a unos cuantos archivos sobre una base LRU. Este caché se busca en el instante de apertura de
un archivo. Una búsqueda exitosa evita búsquedas costosas en el directorio.
La estructura de datos del ínodo se mantiene en el disco. Algunos de sus campos contienen
la siguiente información:

• Tipo de archivo: directorio, liga, archivo especial, etcétera.


• Número de ligas del archivo.
• Tamaño del archivo.
• Identificación del dispositivo en el que está almacenado el archivo.
• Número de serie del ínodo.
• Identificación de usuario y de grupo del propietario.
• Permisos de acceso.
• Información de asignación.

La información de asignación es semejante a la FMT descrita en la sección 7.7. Observe la se-


mejanza entre los campos del ínodo y los del FCB (consulte la tabla 7.5). El administrador del
sistema puede especificar una cuota de disco para cada usuario a fin de evitar que un usuario
ocupe mucho espacio de disco.

Desplazamiento
apuntador del ínodo
descriptor estructura Bloque de
de archivos del archivo disco
de
alpha
ínodo para
alpha
Figura 7.30 Estructuras de datos Unix.

En la figura 7.30 se ilustra el arreglo del descriptor de archivos, la estructura del archivo
y el ínodo en la memoria durante el procesamiento de un archivo. Cuando un proceso abre un
archivo, para éste se crean un descriptor de archivos y una estructura del archivo, y el descriptor
de archivos se establece de modo que apunte hacia la estructura del archivo. Ésta contiene dos
campos: desplazamiento del siguiente byte en el archivo y el apuntador del ínodo. El ínodo del
archivo se copia en la memoria, a menos que ésta ya contenga tal copia, y se hace que la estruc-
tura del archivo apunte hacia el ínodo. Así, el ínodo y la estructura del archivo juntos contienen
toda la información necesaria para acceder a un archivo.
Los descriptores de archivos se almacenan en una tabla de archivos abiertos. Esta tabla
semeja la de archivos activos (AFT) descrita en secciones anteriores, con una diferencia. Se
trata de una tabla por proceso, más que global. El descriptor de archivos apunta hacia la estruc-
tura del archivo. Cuando se abre un archivo, el descriptor de archivos se transfiere al proceso
que lo abrió. Si un proceso crea un proceso hijo, para éste se crea una tabla de descriptores y los
descriptores de archivos de los procesos padre se copian en el proceso hijo. Así, muchos descrip-

08 MAQ. CAP. 07(F0694).indd 344 8/10/07 1:03:08 AM


7.12 Sistema de archivos de Unix 345

tores de archivos pueden compartir la misma estructura del archivo. Los procesos que poseen a
los descriptores comparten el desplazamiento del archivo.

7.12.2 Semántica para compartir archivos

Unix proporciona una semántica de archivos mutables con imagen individual para compartir
archivos de manera concurrente. Como se muestra en la figura 7.30, cada proceso que abre un
archivo apunta hacia la copia de su ínodo a través del descriptor de archivos y de la estructura
de archivos. Así, todos los procesos que comparten un archivo usan la misma copia de éste; los
cambios realizados por un proceso son visibles de inmediato para otros procesos que compar-
ten el archivo. A fin de evitar condiciones de carrera mientras se accede a un ínodo, en la copia en
la memoria de un ínodo se proporciona un campo de candado. Un proceso que intente acceder a
un ínodo debe dormir si el candado es establecido por otros procesos. Los procesos que utilizan
de manera simultánea un archivo deben hacer sus propios arreglos a fin de evitar condiciones de
carrera en los datos contenidos en el archivo.

7.12.3 Asignación de espacio de disco

Unix utiliza asignación indexada de espacio de disco, con un bloque de disco de tamaño igual a 4
K bytes. Cada archivo posee una tabla de asignación de archivos (FAT) semejante a la FMT, que
se mantiene en su ínodo. La tabla de asignación contiene 15 entradas (consulte la figura 7.31).
Doce de éstas apuntan directamente hacia los bloques de datos del archivo. La siguiente entrada
en la tabla de asignación apunta hacia un bloque indirecto, es decir, un bloque que por sí mismo
contiene apuntadores hacia los bloques de datos. Las dos entradas siguientes apuntan a bloques
indirectos dobles y triples. De esta forma, el tamaño total del archivo puede ser hasta de 242
bytes. Sin embargo, la información del tamaño del archivo se almacena en una palabra de 32 bits
del ínodo, por lo que el tamaño del archivo está limitado a 232  1 bytes, para el cual son idóneos
los bloques directo y sencillo, así como los bloques indirectos dobles de la tabla de asignación.

12 Indirección
sencilla
13
14
Indirección
15 doble

Indirección
triple

Figura 7.31 Tabla de asignación de archivos Unix.

Para tamaños de archivos menores que 48 K bytes, este arreglo es tan eficaz como el arreglo
plano FMT que se analizó en la sección 7.7. Estos archivos también cuentan con una pequeña
tabla de asignación que cabe en el ínodo en sí. Los bloques indirectos permiten que los archivos

08 MAQ. CAP. 07(F0694).indd 345 8/10/07 1:03:08 AM


346 CAPÍTULO 7 Sistema de archivos

crezcan a tamaños muy grandes, aunque sus accesos impliquen atravesar la indirección en la
tabla de asignación de archivos.
El sistema de archivos mantiene una lista libre de bloques de disco. Para almacenar la lista
libre se utiliza una técnica interesante. En su forma más simple, una lista libre deberá almacenarse
utilizando un arreglo semejante a la asignación ligada: la lista constará de un conjunto de bloques
de disco libres, con cada bloque apuntando hacia el siguiente bloque en la lista. Sin embargo,
Unix utiliza un esquema de asignación indexada, de modo que cada bloque de disco que fue
asignado a un archivo borrado debe estar ligado de manera individual a la lista libre. Para evitar
esto, la lista libre de Unix consta de una lista de bloques donde cada bloque es semejante a un
bloque indirecto en la FMT. Así, cada bloque en la lista libre contiene direcciones de los bloques
de disco libres, y la identificación del siguiente bloque en la lista libre. Este arreglo minimiza la
sobrecarga que implica agregar bloques de disco a la lista libre cuando se borra un archivo. Para
archivos cuyo tamaño es menor que 48 K bytes sólo se requiere procesamiento marginal.
Un campo candado se asocia con la lista libre para evitar condiciones de carrera cuando
a la lista se agregan o borran bloques de disco. Para formar una lista libre cuando se crea un
nuevo sistema de archivos, se utiliza un programa del sistema de archivos denominado mkfs.
mkfs enumera los bloques libres en orden creciente por número de bloque mientras elabora
la lista libre. Este ordenamiento se pierde a medida que a la lista libre se agregan o borran
bloques de disco durante la operación del sistema de archivos. El sistema de archivos no hace
nada por restaurar este orden. Así, los bloques asignados a un archivo pueden ser distribuidos
descuidadamente en un disco, lo cual reduce la eficacia de acceso de un archivo. Para abordar
esta cuestión, Unix BSD utiliza el concepto de grupo de cilindros, que es un conjunto de cilindros
consecutivos en un disco. Para minimizar el movimiento de la cabeza del disco, el sistema de
archivos asegura que todos los bloques de disco asignados a un archivo pertenezcan al mismo
grupo de cilindros.

7.12.4 Sistemas de archivos múltiples

En aras de la eficacia, Unix preserva la raíz de todo sistema de archivos, denominada superbloque,
en la memoria principal. Los ínodos de todos los archivos abiertos también se copian en la
memoria. El superbloque contiene el tamaño del sistema de archivos, la lista libre y el tamaño
de la lista del ínodo. El superbloque se copia periódicamente en el disco. Parte del estado del
sistema de archivos se pierde si el sistema se bloquea después de que se modifica el superbloque
pero antes de que se copie la información en el disco. El sistema de archivos puede reconstruir
parte de la información de estado perdida, por ejemplo, la lista libre, mediante el análisis del
estado del disco. Esto se hace como parte del procedimiento de carga del sistema.
En un sistema Unix pueden existir muchos sistemas de archivos. Cada uno consta de un
superbloque, una lista del ínodo y bloques de datos. En un dispositivo de disco lógico sencillo
existe un sistema de archivos, de modo que los archivos no pueden desplazarse a través de discos
lógicos diferentes. Un disco lógico contiene exactamente un sistema de archivos. Un disco físico
puede partirse en muchos discos lógicos y en cada uno de éstos es posible construir un sistema
de archivos. Esta partición proporciona algo de protección y también evita que un sistema de
archivos ocupe demasiado espacio de disco. Antes de acceder a un sistema de archivos, es
necesario montarlo. Sólo un superusuario, comúnmente el administrador del sistema, puede
montar un sistema de archivos.

08 MAQ. CAP. 07(F0694).indd 346 8/10/07 1:03:08 AM


7.12 Sistema de archivos de Unix 347

A continuación se describe cómo funciona el montaje y el desmontaje de sistemas de


archivos. A un disco lógico que contiene un sistema de archivo se le proporciona un nombre
de archivo especial de dispositivo. Un sistema de archivos puede montarse en un directorio al
especificar su nombre de la trayectoria en un comando mount; por ejemplo,

mount (<FS_name>, <mount_point_name>, . . .);

donde FS_name es el nombre de archivo especial de dispositivo del sistema de archivos que
se va a montar, y mount_point_name es el nombre de la trayectoria del directorio en que se
montará el sistema de archivos. Una vez montado, la raíz del sistema de archivo lleva el nombre
proporcionado por el nombre de la trayectoria especificado por mount_point_name. En la
sección 7.4 se describirán otros detalles de montaje. Cuando se monta un sistema de archivo, el
superbloque del sistema de archivos montado se carga en la memoria. Luego, la asignación de
bloques de disco para un archivo en el sistema de archivos montado debe efectuarse dentro del
dispositivo de disco lógico en el que existe el sistema de archivos. El acceso a los archivos de un
sistema de archivos montado es como se describe en la sección 7.8.1.
Una llamada de apertura de un archivo en Unix especifica tres parámetros: nombre de
la trayectoria, banderas y modo. Las banderas indican el tipo de operaciones para las que se
está abriendo el archivo. Los valores posibles de esta bandera son read, write o read/write. El
parámetro de modo se proporciona cuando se está creando un nuevo archivo. Éste especifica los
privilegios de acceso que deben asociarse a un archivo. Dicha información suele copiarse a partir
de la máscara de creación del archivo del usuario. El propietario de un archivo puede modificar
la información de protección en cualquier momento a través del comando chmod.

7.12.5 Otras características

Dos tipos de ligas son admitidas en Unix. Según se describió en la sección 7.4, las ligas se
denominan ligas duras. El sistema de archivos mantiene un conteo de referencia con cada archivo
para indicar el número de ligas que apuntan hacia el archivo. Un archivo puede borrarse sólo si su
conteo de referencia se vuelve 0. Por tanto, si un archivo tiene muchas ligas que apuntan hacia
él, no es posible borrarlo incluso si el propietario realiza una operación de borrado. De hecho,
el archivo podrá incluirse en la cuota del propietario y ¡el propietario tendrá que seguir pagan-
do por el espacio de disco que está ocupando! Una liga simbólica es un archivo que contiene
un nombre de la trayectoria de otro archivo. Por tanto, si se crea un archivo alpha como una
liga simbólica hacia el archivo beta, se crea el archivo alpha y el nombre de la trayectoria de
beta proporcionado en el comando de liga se almacena en alpha. La entrada del directorio
de alpha se indica como liga simbólica. De esta forma el sistema de archivos sabe cómo interpre-
tar su contenido. El conteo de referencia de beta no se incrementa cuando se establece una liga
simbólica. Así, la eliminación de beta permanece bajo control de su propietario. Sin embargo,
las ligas simbólicas pueden crear referencias pendientes una vez que se borran los archivos.
Las memorias intermedias no se asignan en el nivel de archivo o proceso. Todas las
memorias intermedias y sus contenidos se comparten a través de procesos. Este arreglo ayuda
a implementar semántica usando archivos mutables con imagen individual (consulte la sección
7.12.2). También reduce el número de accesos al disco cuando dos o más procesos procesan
simultáneamente un archivo (consulte la sección 12.10).

08 MAQ. CAP. 07(F0694).indd 347 8/10/07 1:03:08 AM


348 CAPÍTULO 7 Sistema de archivos

7.13 SISTEMA DE ARCHIVOS LINUX


Linux proporciona un sistema de archivos virtuales (VFS) que admite un modelo de archivos
comunes semejante al modelo Unix. El modelo de archivos se implementa utilizando estructuras
de datos semejantes a las de Unix como superbloques e ínodos. Cuando se abre un archivo, el
VFS transforma la entrada de su directorio en un objeto dentry. Este objeto se envía al caché, de
modo que la sobrecarga de construirlo a partir de la entrada del directorio se evita si el archivo
se abre repetidamente durante una sesión de computación. El sistema de archivos estándar de
Linux se denomina ext2. El sistema de archivos ext3 incorpora journaling (registro por diario),
que proporciona integridad de datos de archivo y metadatos, así como carga rápida después de
un apagado no limpio.
Ext2 proporciona una variedad de candados de archivo para sincronización del proceso.
Los candados de asesoramiento son aquellos que escucha el proceso a fin de asegurar exclusión
mutua; sin embargo, el sistema de archivo no hace cumplir su uso. Los candados de archivo de
Unix pertenecen a esta categoría de candados. Los candados obligatorios son aquellos compro-
bados por el sistema de archivos; si un proceso intenta acceder a datos protegidos por uno de
estos candados, el proceso es bloqueado hasta que el candado es restablecido por su poseedor.
Un arriendo es un tipo especial de candado de archivo que es válido durante un lapso específico
después de que otro proceso intenta acceder a los datos protegidos por este candado. Se imple-
menta como sigue: si un proceso accede a algunos datos protegidos por un arriendo, el titular
del arriendo es intimidado por el sistema de archivos. Entonces tiene un intervalo de tiempo
estipulado para terminar de acceder al archivo y liberar el arriendo. En caso de no proceder así,
su arriendo se rompe y es otorgado al proceso que intentó acceder a los datos protegidos por el
arriendo.
El diseño de ext2 fue influido por el sistema de archivos rápido de BSD. Ext2 utiliza el con-
cepto de grupo de bloques, que es un conjunto de bloques de disco consecutivos, para reducir el
movimiento de las cabezas de disco cuando se abre un archivo y se accede a sus datos. Utiliza un
mapa de bits para seguir la pista de los bloques de disco libres en un grupo de bloques. Cuando
se crea un archivo, intenta asignar espacio de disco para el ínodo del archivo dentro del mismo
grupo de bloques que contiene a su directorio raíz, y también da cabida a los datos del archivo
dentro del mismo grupo de bloques. Cada vez que un archivo se amplía mediante la adición de
nuevos datos, busca el mapa de bits del grupo de bloques para encontrar un bloque de disco libre
que esté próximo a un bloque de disco objetivo. Si se encuentra tal bloque de disco, comprueba
si algunos bloques de disco adjuntos también están libres y preasigna unos cuantos de éstos al
archivo. En caso de que no se encuentre tal bloque de disco libre, preasigna algunos bloques
de disco adjuntos localizados en otra parte del grupo de bloques. De esta forma, es posible leer
grandes secciones de datos sin tener que mover la cabeza del disco. Cuando se cierra el archivo,
se liberan los bloques de disco preasignados pero no utilizados. Esta estrategia de asignación de
espacio de disco asegura el uso de bloques de disco contiguos por secciones contiguas de datos
de archivos, aun cuando los archivos sean creados y borrados a gran ritmo; lo anterior contribuye
a un elevado desempeño de acceso a archivos.

7.14 SISTEMA DE ARCHIVOS WINDOWS

El sistema de archivos utilizado en Windows es NTFS, que está diseñado para satisfacer los
requerimientos del sistema de archivos para los servidores y las estaciones de trabajo, por lo que
proporciona soporte para aplicaciones de gama alta, como aplicaciones para grandes sistemas de

08 MAQ. CAP. 07(F0694).indd 348 8/10/07 1:03:09 AM


7.14 Sistema de archivos Windows 349

entidades corporativas y aplicaciones de servidor de clientes para servidores de archivos y bases


de datos. Una característica clave de NTFS es la recuperabilidad del sistema de archivos. Esta
característica se analizará en la sección 12.11.
La administración del espacio de disco realizada por NTFS está diseñada para ser
independiente de los tamaños de sector en discos diferentes. Utiliza el concepto de cluster
(grupo), que es una colección de sectores contiguos, para la asignación de espacio de disco.
El número de sectores en un grupo es una potencia de 2. Un volumen es una partición lógica
en un disco. Para indicar cuáles grupos en un volumen son asignados y cuáles son libres, se
utiliza un archivo de mapa de bits. Un archivo de grupos malos sigue la pista de los grupos que
son inutilizables debido a problemas de hardware. Grandes archivos que exceden la capacidad
de una partición son admitidos usando el concepto de conjunto de volumen. Un conjunto de
volumen puede contener hasta 32 volúmenes.
Un volumen NTFS contiene un sector de carga, una tabla de archivos maestros (MFT),
algunos archivos del sistema y archivos del usuario. La existencia del sector de carga hace que
cada volumen sea cargable. La MFT contiene información sobre todos los archivos y carpetas en
el volumen. También contiene información sobre áreas no utilizadas en el volumen. Así, la MFT
semeja la tabla de asignación de archivos (FAT) analizada en la sección 7.7.
Las entradas de la MFT son números de entrada de 16 bits. Cada archivo cuenta con un
número de archivo de 16 bits, que es simplemente el número de entrada de la entrada de la MFT
ocupada por el archivo. Un archivo también tiene un número de secuencia de 48 bits. Éste es un
conteo del número de veces que se ha utilizado una entrada de la MFT. El número de archivo
y el número de secuencia juntos constituyen un archivo de referencia que es único dentro del
volumen. El número de secuencia se utiliza para evitar mezclas entre dos archivos que hayan
usado la misma entrada de la MFT en instantes diferentes.
Cada archivo posee un conjunto de atributos. Cada atributo se considera como un flujo de
bytes independiente. Algunos atributos estándar están definidos para todos los archivos en el siste-
ma. Además, algunos archivos pueden tener atributos especiales. Los datos en un archivo también
se consideran como un atributo. Una entrada de la MFT contiene el archivo de referencia de un
archivo, el tamaño del archivo y la última vez que fue actualizado. También almacena los atribu-
tos del archivo. Si el tamaño de un atributo es grande, se almacena en un atributo no residente.
Los atributos no residentes se almacenan en alguna otra parte en una extensión del volumen y en
la entrada de la MFT se almacena un apuntador hacia la extensión. Este arreglo permite que los
datos en un archivo pequeños sean almacenados en la entrada de la MFT misma.
Una carpeta es un directorio. NTFS la implementa utilizando un archivo de índice. La
jerarquía del directorio se forma permitiendo que las carpetas contengan otras carpetas. Un
directorio se organiza como un árbol B con archivos como nodos hoja. La estructura de datos
del árbol B posee la propiedad de que la longitud de cada trayectoria en el árbol es la misma,
lo cual facilita la búsqueda eficaz de un archivo en un directorio.
NTFS adquiere robustez al salvaguardar consistencia de sus estructuras de datos en caso de
fallas en el sistema. Esto se logra al tratar cada modificación de las estructuras de datos como
una transacción atómica. Mientras se recupera de una falla, comprueba si una transacción estaba
llevándose a cabo en el instante en que ocurrió la falla. En caso afirmativo, termina la transacción
antes de reanudar la operación. Esta acción asegura que las estructuras de datos del sistema de
archivos sean consistentes siempre que el sistema esté en operación. Sin embargo, este método
de recuperación no se extiende a los archivos del usuario debido a la elevada sobrecarga que
implica utilizar transacciones atómicas, de modo que los archivos del usuario pueden perder
datos debido a fallas.

08 MAQ. CAP. 07(F0694).indd 349 8/10/07 1:03:09 AM


350 CAPÍTULO 7 Sistema de archivos

Las transacciones atómicas se implementan utilizando un archivo estructurado como bi-


tácora. Este método es semejante a la implementación de acciones atómicas analizada en la
sección 7.10.2. Para modificar sus propias estructuras de datos, NTFS escribe primero los pasos
invocados en la modificación, es decir, sus intenciones, en el archivo estructurado como bitáco-
ra. Luego, este archivo se protege en un disco para asegurar que los registros estructurados
como bitácora no se pierdan en caso de que ocurra un bloqueo. Luego de esto se lleva a cabo la
modificación requerida de las estructuras de datos. Entonces es posible descartar la bitácora. Si
ocurre un bloqueo en cualquier instante después de que la bitácora se vació en el disco, el archivo
estructurado como bitácora se usa para terminar la transacción.
Las transacciones atómicas no pueden evitar la pérdida de datos del sistema debido a un
bloqueo. Para evitar tal pérdida de datos, la bitácora no se descarta de inmediato luego de ter-
minar una actualización. En vez de ello, NFTS asume un punto de control cada 5 segundos
y descarta el archivo estructurado como bitácora en ese instante. En caso de un bloqueo, el sis-
tema de archivos puede restaurarse copiando el punto de control y procesando los registros, en
caso de haberlos, en el archivo estructurado como bitácora.

7.15 DESEMPEÑO DE LOS SISTEMAS DE ARCHIVOS

En la tabla 7.6 se resumen técnicas utilizadas para asegurar el buen desempeño de un sistema de
archivos. La mayor parte de estas técnicas conciernen al acceso rápido a los metadatos de un sis-
tema de archivos, como entradas de directorios, tablas de mapa de archivos y datos de archivos.
Otras técnicas se ocupan de la eficacia de las estructuras de datos y de los algoritmos utilizados
en el sistema de archivos. Para hacer más eficaces las búsquedas en directorios, se usan arre-
glos como tablas de búsqueda y árboles B.

Tabla 7.6 Puntos relacionados con el desempeño del sistema de archivos

Punto Técnicas utilizadas para manejar este punto


Acceso al directorio Caché para el directorio
Búsqueda en el directorio Tablas de búsqueda, árboles B
Acceso a la tabla del Caché de la tabla del mapa de archivos en la memoria
mapa de archivos
Acceso a un bloque Caché del bloque de disco en la memoria, programación de disco, grupos
de disco y extensiones de cilindro, caché del bloque de disco en el dispositivo
Acceso a los datos Almacenamiento temporal y bloqueo de los datos

Las técnicas de caché y almacenamiento temporal se utilizan para acelerar los accesos a
metadatos y archivo de datos. La formación de la memoria caché es la técnica fundamental para
acelerar el acceso a información en una jerarquía de la memoria (consulte la sección 2.1.1).
Implica el mantenimiento en la memoria de información a la que se ha accedido a fin de acele-
rar accesos repetidos a esa información. El almacenamiento temporal carga información en la
memoria en anticipación a futuras referencias. Por tanto, acelera el primer acceso a la informa-
ción. Accesos posteriores pueden ser acelerados por medio de la formación de la memoria caché.
Una acción de almacenamiento temporal, no obstante, puede desperdiciarse si a la información
almacenada temporalmente no se accede como estaba anticipado.

08 MAQ. CAP. 07(F0694).indd 350 8/10/07 1:03:09 AM


7.15 Desempeño de los sistemas de archivos 351

Los directorios están en la memoria caché cuando se accede a ellos por primera vez. Así, un
directorio utilizado para resolver el nombre de una trayectoria se retiene en la memoria caché
para acelerar futuras referencias a archivos ahí localizados. Esta memoria caché se denomina
caché de nombres del directorio. Una tabla de mapas de archivo se almacena temporalmente en
la memoria. Se carga ahí una vez que se abre un archivo. Esto se hace antes de acceder al archi-
vo. Puede estar en la memoria caché después de su primer acceso. El almacenamiento temporal
puede no ser factible si la FMT es grande. En ese caso, parte del archivo puede guardarse en la
memoria caché cuando se haga referencia a esta parte del archivo por primera vez.
Tres de las técnicas mencionadas en la tabla 7.6 se analizarán más tarde en el capítulo 12. La
planificación de discos se utiliza para reducir los movimientos de la cabeza del disco y el tiempo
promedio de espera para las operaciones de E/S. Un caché de disco almacena bloques de disco
en la memoria luego de haber sido usados por primera vez. Esto reduce el número de operaciones
de E/S en un disco. Es posible obtener relaciones de impacto de 0.9 o más en el caché de disco.
Un método de acceso utiliza las técnicas de memoria intermedia y bloqueo de datos de archivo
para reducir el tiempo de espera implicado en una operación de E/S.
A medida que avanza la tecnología, la tendencia es hacia acelerar el proceso para que las
técnicas que fueron desarrolladas en software sean implementadas en el hardware. La tecnología
moderna de E/S incorpora algunas de las técnicas mencionadas en la tabla 7.6. Así, los discos
SCSI proporcionan planificación de discos en el dispositivo mismo. Las unidades RAID contie-
nen una memoria intermedia de bloque de disco, que puede utilizarse tanto para los bloques de
disco de la memoria temporal como para el caché de bloques de disco. Estas dos tecnologías se
analizarán más tarde en el capítulo 12.

7.15.1 Sistema de archivos estructurado como bitácora


La formación de la memoria caché reduce el número de operaciones de lectura dirigidas hacia
el disco. Por tanto, la utilización del disco está dominada por el movimiento de la cabeza del
disco y las operaciones de escritura. El movimiento de la cabeza del disco puede reducirse por
medio de la programación de discos y a través del uso de grupos de cilindros en la asignación
de espacio de disco para archivos. Sin embargo, estas técnicas son menos efectivas cuando los
archivos ubicados en diferentes partes de un disco se procesan de manera simultánea, que es el
caso que se presenta más a menudo en un sistema de cómputo compartido. Por ejemplo, en un
sistema Unix, las operaciones de escritura en un disco consumen sólo aproximadamente 10 por
ciento del tiempo del disco; el resto se utiliza en movimiento de la cabeza del disco. Esto condu-
ce a un rendimiento deficiente de un disco.
Un sistema de archivos estructurado como bitácora reduce el movimiento de la cabeza del
disco por medio de una organización de archivo radicalmente diferente. Escribe datos de archi-
vos de todos los archivos juntos en una estructura secuencial simple que semeja un periódico.
Este archivo se denomina archivo de registro. Cuando sobre cualquier archivo se realiza una
operación de actualización o de lectura, los nuevos datos se agregan simplemente al final del
archivo de registro. Por tanto, en esta operación está implicado poco movimiento de la cabeza
del disco. El sistema de archivos escribe bloques de índice especiales en el archivo de registro
para alojar metadatos sobre la localización de cada archivo de datos en el archivo de registro.
Los bloques de índice se utilizan cuando los datos de un archivo deben leerse del disco. Así, para
leer datos que se escribieron recientemente en un archivo, se requiere poco movimiento de la
cabeza del disco; sin embargo, para datos más antiguos se requiere más movimiento de la cabeza
del disco. Estudios de desempeño sobre el sistema de archivos estructurado como bitácora Sprite

08 MAQ. CAP. 07(F0694).indd 351 8/10/07 1:03:09 AM


352 CAPÍTULO 7 Sistema de archivos

demostraron que el movimiento de la cabeza del disco explicaba sólo 30 por ciento del tiem-
po de disco consumido durante el procesamiento de archivos, y que su desempeño era superior
al sistema de archivos convencional para pequeños textos escritos frecuentemente. En el ejemplo
7.14 se ilustra la operación de un sistema de archivos estructurado como bitácora.

Bloque de índice

a) 1 2 3 Archivo de registro

b) 1 2 3 4 5 Archivo de registro

Figura 7.32 Actualización de un archivo en un sistema de archivos estructurado como bitácora.

Ejemplo 7.14 La figura 7.32a) es un esquema del arreglo utilizado en un sistema de archivos es-
tructurado como bitácora. Para facilitar las cosas, muestra los metadatos y los datos de un archivo
de un archivo simple en el archivo de registro. Los bloques de datos en el archivo de registro se han
numerado por conveniencia. La entrada del directorio de un archivo apunta a un bloque de índice
en el archivo de registro; se supone que el bloque de índice contiene la FMT del archivo. Cuando se
actualizan los datos del archivo que reside en el bloque 1, los nuevos valores se escriben en el blo-
que de disco 5 cuando se actualizan los datos en el bloque 3. Luego, el sistema de archivos escribe
un nuevo bloque de índice que contiene la FMT actualizada del archivo y establece el apuntador de
la FMT en el directorio del archivo de modo que señale hacia el nuevo bloque de índice. La nueva
FMT contiene apuntadores hacia los dos nuevos bloques de datos y hacia el bloque de datos 2 que
no se ha modificado (consulte la figura 7.32b)). El bloque de datos anterior y los bloques de disco
1 y 3 ahora son libres.

Debido a que el archivo de registro está escrito en forma de archivo con acceso secuencial,
el sistema de archivos debe asegurar que para escribir este archivo siempre debe haber disponi-
ble un área de disco suficientemente grande. Se logra lo anterior al mover bloques de datos alre-
dedor del disco a fin de hacer un área libre disponible para el archivo de registro. Esta operación
es semejante a la compactación de memoria (consulte la sección 5.5.1) e implica considerable
movimiento de la cabeza del disco que ahora domina el uso del disco; sin embargo, la compac-
tación se lleva a cabo como una actividad del entorno, de modo que así no retrasa las actividades
de procesamiento de archivos en los procesos.

EJERCICIO 7
1. Los usuarios de un sistema acceden frecuentemente a un archivo denominado data. Para simplificar el
acceso a data se proponen las siguientes alternativas:
a) Establecer ligas desde el directorio raíz de cada usuario hasta data.

08 MAQ. CAP. 07(F0694).indd 352 8/10/07 1:03:09 AM


Ejercicio 7 353

b) Copiar data en el directorio raíz de cada usuario.


Compare las ventajas y las desventajas de estos métodos.
2. Un archivo secuencial con índice contiene 10 000 registros. Su índice contiene 100 entradas. Cada en-
trada del índice describe un área del archivo que contiene 100 registros. Si la probabilidad de acceder
a todos los registros en el archivo es la misma, calcule el número medio de operaciones de disco im-
plicadas para acceder a un registro. Compare este resultado con el número de operaciones de disco
necesarias si los mismos registros estuvieran almacenados en un archivo secuencial.
3. Considere el archivo secuencial con índice de la figura 7.6. Un problema interesante se presenta cuando
un nuevo registro, por ejemplo, el del empleado con el número 8 (este registro se denomina regis-
tro 8) se agrega al archivo. No hay espacio para almacenar el nuevo registro, de modo que el método
de acceso saca de la pista el registro 13 y recorre los registros 10 y 12 a fin de hacer espacio para el
nuevo registro. Luego, el registro 13 es colocado en un área de desbordamiento. Un nuevo campo
denominado apuntador del área de desbordamiento se agrega a cada entrada en el índice de pista. Este
apuntador en la primera entrada del índice se establece de modo que apunte hacia el registro 13 en el
área de desbordamiento. Si más registros desbordan la primera pista, se colocan en una lista ligada y
el apuntador del área de desbordamiento de la primera entrada del índice apunta al encabezado de la
lista. Listas ligadas semejantes pueden formarse para varias pistas durante un intervalo de tiempo.
Si la probabilidad de acceder a todos los registros en el archivo secuencial con índice es la mis-
ma, demuestre que la eficacia de acceso y del archivo será afectada por la presencia de registros en
el área de desbordamiento. ¿Es posible restaurar la eficacia y volviendo a escribir el archivo como un
nuevo archivo que no contiene ninguno de los registros de desbordamiento?
4. Escriba una nota breve sobre las acciones que deben llevarse a cabo durante una operación de borrado
de un archivo si en la estructura del directorio existen ligas.
5. El sistema operativo “Amoeba” distribuido utiliza asignación contigua de espacio de disco. No permite
la actualización de archivos. Un efecto equivalente se logra escribiendo un archivo actualizado como
un nuevo archivo y borrando la copia anterior.
Comente sobre las ventajas y las desventajas de este método.
6. La asignación no contigua de espacio de disco, ¿afecta la factibilidad y eficacia de la organización
fundamental de archivos analizada en la sección 7.3?
7. Un sistema de archivos utiliza asignación de espacio de disco indexada de multinivel (consulte la figura
7.17). El tamaño de cada bloque de disco es 4 K bytes y la longitud de cada dirección del bloque de
disco es de 4 bytes. El tamaño de la FMT es un bloque de disco. Contiene 12 apuntadores hacia bloques
de datos. Los demás apuntadores están dirigidos hacia bloques de índice.
Un archivo secuencial info contiene 5 000 registros, cada uno de 4 K bytes. Las características
del disco y de un archivo info que accede a un proceso son como sigue:
Tiempo promedio para leer un bloque de disco  3 mseg
Tiempo promedio para procesar un registro  5 mseg
Calcule el tiempo transcurrido de un proceso que lee y procesa todos los registros en el archivo, en las
siguientes condiciones:
a) El sistema de archivos mantiene la FMT en la memoria, pero no mantiene ningún bloque de índice
en la memoria mientras procesa info.
b) El sistema de archivos mantiene en la memoria la FMT y un bloque de índice de info.
8. Al archivo info del problema 7 se piensa agregar un nuevo registro. Escriba un algoritmo para llevar
a cabo esta operación.
9. Un sistema de archivos utiliza asignación contigua de espacio de disco. El método de acceso secuencial
manipula los bloques malos en un disco como sigue: si ocurre un error durante la lectura/escritura de

08 MAQ. CAP. 07(F0694).indd 353 8/10/07 1:03:10 AM


354 CAPÍTULO 7 Sistema de archivos

un bloque, consulta la tabla de bloques malos, que de suyo está almacenada en el disco, y accede al
bloque de disco alterno asignado al bloque malo. Suponiendo que para acceder a todos los discos se
requieren tiempos de acceso idénticos, calcule la degradación en el desempeño de acceso a los archivos
si 2 por ciento de los bloques de disco asignados a un archivo son bloques malos. Sugiera un método
para mejorar el desempeño de acceso.
10. Para reducir la sobrecarga de la validación de acceso a un archivo (consulte el paso 2 de la sección
7.8.2), un diseñador de SO propone realizar la validación sólo en el archivo tiempo “abierto”. La decla-
ración open especifica el tipo de accesos que se harán al archivo; por ejemplo, open (abc, ‘read’).
¿Es adecuada una sola comprobación de validación de acceso en el archivo tiempo abierto? En
caso negativo, explique por qué. En cualquier caso, sugiera una directriz de implementación.
11. El paso 2 de la sección 7.8.1 crea un FCB para todo directorio que aparece en el nombre de una tra-
yectoria.
a) Este arreglo, ¿es adecuado cuando se utiliza un nombre relativo de la trayectoria?
b) El sistema de archivos Unix posee un campo adicional en cada directorio, que contiene la dirección
de su directorio raíz. ¿Es posible utilizar la información en este campo para reducir el número de
FCB en la memoria?
12. Comente acerca de la implementación de los puntos siguientes relacionados con el montaje de sistemas
de archivos:
a) Montajes en cascada: El directorio C contiene un archivo D. La jerarquía del sistema de archivos
arraigada en C se monta en el punto de montaje X/B. Después, la jerarquía del sistema de archivos
arraigada en X se monta en el directorio Y/A. ¿Es posible acceder al archivo D como ..Y/A/B/D?
b) Montajes múltiples: La jerarquía del sistema de archivos arraigada en C se monta de manera simul-
tánea en muchos puntos de montaje.
13. Comente acerca de la validez de la siguiente declaración: “Un archivo mapeado en la memoria propor-
ciona ventajas de archivos secuenciales y archivos directos.”
14. Un rastro de auditoría es una técnica utilizada para facilitar la recuperación de archivos luego de una
falla. Cada vez que se actualiza un archivo, en el rastro de intervención se escribe un registro que
contiene i) la identificación del registro del archivo actualizado y ii) el nuevo contenido del registro.
Indique cómo puede usarse el archivo de intervención junto con respaldo completo y por incrementos
para aumentar la confiabilidad de un sistema de archivos.
15. Analice cómo puede usarse la técnica de almacenamiento estable para evitar la pérdida de la integridad
del sistema de archivos.
16. Comente acerca de la validez de la siguiente declaración: “La mezcla en el contenido de archivos como
se muestra en la figura 7.23 no puede ocurrir cuando para los archivos se usa asignación indexada; no
obstante, si hay una falla puede ocurrir un bloque de disco en más de un archivo.”
17. El algoritmo 7.1 se replantea como sigue:

1. dj.next : d1.next;
2. d1.next : address (dj);
3. Write dj to disk.
4. Write d1 to disk.

Este algoritmo modificado, ¿evita la mezcla de archivos en caso que ocurra una falla?
18. Explique por qué no es posible tomar un respaldo completo de un sistema mientras se están llevando
a cabo las actividades de procesamiento de un archivo. Describa la forma en que debe tomarse un
respaldo por incrementos.

08 MAQ. CAP. 07(F0694).indd 354 8/10/07 1:03:10 AM


Bibliografía 355

19. Explique cómo el byte de desplazamiento en un archivo Unix puede convertirse en el par (identifica-
ción del bloque de disco, desplazamiento en el bloque).
20. De forma predeterminada, Unix asigna los archivos infile y outfile al teclado y a la terminal, respec-
tivamente. Para anular las asignaciones predeterminadas utiliza operadores de redirección ‘’ y ‘’,
usa otros archivos para entrada y salida. El operador ‘’ “redirect and append” agrega la salida
de un proceso al final de un archivo existente. Estas características pueden implementarse al asociar de
manera permanente FCB para infile y outfile con cada proceso.
a) Indique las acciones del sistema de archivos implicadas en la implementación de las asignaciones
predeterminadas para infile y outfile y los operadores de redirección ‘’ y ‘’.
b) Indique las acciones del sistema de archivos implicadas en la implementación del operador ‘’.
21. Los bloques de disco asignados a un archivo se agregan a la lista libre cuando se borra el archivo. Es-
criba un algoritmo para llevar a cabo esta operación en Unix.
22. El sistema de archivos Unix asocia un campo candado a la lista libre (consulte la sección 7.12). Co-
mente sobre la validez de la siguiente declaración: “Poner candados a la lista libre es necesario debido
a la naturaleza de los procesos Unix. Este aseguramiento es innecesario en un SO que utiliza el modelo
convencional de procesamiento.”

BIBLIOGRAFÍA
Históricamente, Organick (1972) es el artículo más importante sobre estructuras de directorios, ya que
la estructura de directorio MULTICS ha influido a la mayor parte de los sistemas de archivos contempo-
ráneos, como Unix, Linux, Solaris y Windows. USENIX (1992) contiene procedimientos de un taller de
sistema de archivos. Grosshans (1986), Weiderhold (1987) y Livadas (1990) analizan organizaciones
de archivos y sistemas de archivos.
McKusick et al. (1990) describen un sistema de archivos basado en la memoria, que proporciona
archivos mapeados en la memoria y estructuras de directorio implementadas en memoria paginable. Levy
y Silberschatz (1990) analizan la semántica para compartir el archivo. Lampson (1981) describe la técnica
de almacenamiento estable para confiabilidad de datos de disco, mientras Svobodova (1984) revisa cómo
se llevan a cabo las acciones atómicas en varios servidores de archivos. Florido (2000) analiza el diseño de
sistemas de archivos según registro por diario. Kleiman (1986) describe el diseño de sistema de archivos
virtuales para Sun Unix. Vahalia (1996) describe la interfaz Unix para sistemas de archivos virtuales. Ro-
senblum y Ousterhout (1992) analizan el diseño del sistema de archivos Sprite estructurados como bitácora,
mientras Matthews et al. (1997) analizan métodos adaptativos para mejorar el desempeño de sistemas de
archivos estructurados como bitácora. McKusick et al. (1996) analizan el sistema de archivos estructurados
como bitácora de Unix 4.4 BSD.
Bach (1986) y Vahalia (1996) describen el sistema de archivos Unix. Kowalski (1978) describe el
programa Unix utilizado para comprobar la integridad del sistema de archivos. Este programa busca a
través de todas las estructuras de datos del sistema de archivos en el disco. Bina y Emrath (1989) analizan
cómo pueden acelerarse las comprobaciones de integridad del sistema de archivos en el sistema de archivos
Unix. Beck et al. (2002) y Bovet y Cesati (2003) analizan el sistema de archivos ext2 de Linux. Mauro y
McDougall (2001) analizan el sistema de archivos Solaris. Nagar (1997) y Russinovich y Solomon (2005)
describen el sistema de archivos NTFS de Windows.

1. Bach, M.J. (1986): The Design of the Unix Operating System, Prentice-Hall, Englewood Cliffs.
2. Beck, M., H. Bohme, M. Dziadzka, U. Kunitz, R. Magnus, C. Schroter y D. Verworner (2002):
Linux Kernel Programming, Pearson Education,

08 MAQ. CAP. 07(F0694).indd 355 8/10/07 1:03:10 AM


356 CAPÍTULO 7 Sistema de archivos

3. Bina, E.J. y P.A. Emrath (1989): “A faster fsck for BSD UNIX”, Proceedings of the Winter 1989
USENIX Technical Conference, 173-185.
4. Bovet, D.P. y M. Cesati (2003): Understanding the Linux Kernel, O’Reilly, Sebastopol.
5. Burrows, M., C. Jerian, B. Lampson y T. Mann (1992): “On-line data compression in a logstruc-
tured file system”, ACM Sigplan Notices, 27, 9, 2-9.
6. Florido, J.I.S. (2000): “Journal file systems”, Linux Gazette, número 55.
7. Grosshans, D. (1986): File Systems: Design and Implementation, Prentice Hall, Englewood
Cliffs.
8. Kleiman, S.R. (1986): “Vnodes: an architecture for multiple file system types in Sun Unix”,
Proceedings of the Summer 1986 USENIX Technical Conference, 238-247.
9. Kowalski, T. (1978): “Fsck—the Unix system check program”, Bell Laboratory, Murray Hill.
10. Lampson, B.W. (1981): “Atomic transactions”, en Distributed systems—Architecture and Imple-
mentation: An Advanced Course, Goos, G., and J. Hartmanis (Eds), Springer Verlag, Berlin, 246-
265.
11. Levy, H.M. y A. Silberschatz (1990): “Distributed file systems: concepts and examples”, ACM
Computing Surveys, 22, 4, 321-374.
12. Livadas, P. (1990): File Structures: Theory and Practice, Prentice Hall, Englewood Cliffs.
13. Love, R. (2005): Linux Kernel Development, 2a. ed., Novell Press.
14. Matthews, J.N., D. Roselli, A.M. Costello, R.Y. Wang y T.E. Anderson (1997): “Improving the
performance of log-structured file systems with adaptive methods”, Proceedings of Sixteenth
Symposium on Operating Systems Principles, 238-251.
15. Mauro, J. y R. McDougall (2001): Solaris Internals—Core Kernel Architecture, Prentice-Hall.
16. McKusick, M.K., K. Bostic, M. Karels y J.S. Quarterman (1996): The Design and Implementation
of the 4.4BSD Operating System, AddisonWesley, Reading.
17. McKusick, M.K., M. Karels y K. Bostic (1990): “A pageable memory based filesystem”, Pro-
ceedings of the Summer 1990 USENIX Technical Conference, 137-144.
18. Nagar, R. (1997): Windows NT File System Internals, O’Reilly, Sebastopol.
19. Organick, E.I. (1972): The MULTICS System, MIT Press, Mass.
20. Rosenblum, M. y J.K. Ousterhout (1992): “The design and implementation of a log-structured file
system”, ACM Transactions on Computer Systems, 10, 2, 26-52.
21. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.
22. Svobodova, L. (1984): “File servers for network-based distributed systems”, ACM Computing
Surveys, 16, 4, 353-398.
23. USENIX (1992): Proceedings of the File Systems Workshop, Ann Arbor, mayo, 1992.
24. Vahalia, U. (1996): Unix Internals: The New Frontiers, Prentice Hall, Englewood Cliffs.
25. Weiderhold, G. (1987): File Organization for Database Design, McGraw-Hill, Nueva York.

08 MAQ. CAP. 07(F0694).indd 356 8/10/07 1:03:10 AM


Capítulo
8
Seguridad y protección

Las medidas de seguridad y protección evitan interferencia con el uso de recursos lógicos o
físicos en un sistema. Cuando estas medidas se aplican a información, aseguran que ésta sea
utilizada no sólo por usuarios autorizados y de la manera deseada, sino también que no se des-
truya ni dañe. La seguridad tiene que ver con amenazas a la información externas a un sistema
de cómputo, mientras que la protección está relacionada con amenazas internas.
La seguridad se implementa mediante la autentificación, utilizando contraseñas, y frustra
intentos realizados por entidades externas para enmascararse como usuarios de un sistema. Para
asegurar la confidencialidad de las contraseñas se utiliza la técnica de cifrado.
Un usuario necesita compartir con colaboradores datos y programas almacenados en archi-
vos. Un privilegio de acceso es una especificación de la manera en que un usuario puede acceder
a un archivo. El propietario de un archivo suministra al SO información concerniente a los pri-
vilegios de acceso a un archivo. La función de protección de un sistema operativo almacena esta
información y la utiliza para asegurar que todos los accesos al archivo coincidan estrictamente
con los privilegios de acceso.
Este capítulo empieza con un análisis de diferentes tipos de ataque a la seguridad y acerca
de cómo son perpetrados mediante el empleo de caballos de Troya, virus y gusanos. Luego se
presenta un análisis sobre técnicas de cifrado y su uso en la seguridad de las contraseñas. Más
adelante se describen tres conocidas estructuras de protección denominadas listas de control de
acceso, listas de capacidad y dominios de la protección, y se estudia el grado de control propor-
cionado por éstas con respecto a la manera de compartir archivos.

8.1 VISIÓN GENERAL DE SEGURIDAD Y PROTECCIÓN

La interferencia en el acceso a los recursos realizada por usuarios autorizados es una amenaza
grave en un SO. La naturaleza de la amenaza depende del carácter de un recurso y de la forma
en que se utiliza. En este capítulo se analizan amenazas al uso de la información almacenada en
archivos. Algunas técnicas que se usan para contrarrestar tales amenazas también son de utilidad
para otros recursos.

09 MAQ. CAP. 08(F0694).indd 357 8/10/07 1:03:52 AM


358 CAPÍTULO 8 Seguridad y protección

Los sistemas operativos utilizan dos conjuntos de técnicas para contrarrestar las amenazas
al uso de la información:

• La seguridad implica la protección de los datos y programas de un usuario en contra de


interferencia por entidades o personas externas a un sistema; por ejemplo, no usuarios.
• La protección implica proteger los datos y programas de un usuario en contra de interfe-
rencia por otros usuarios del sistema.

En la tabla 8.1 se describen dos métodos clave usados por los sistemas operativos para
implementar seguridad y protección. La autentificación es el método que se usa para comprobar
la identidad de una persona. La comprobación física de la identidad no es factible en entornos
contemporáneos de cómputo, de modo que la autentificación basada en computadoras se funda-
menta en un conjunto de suposiciones. Una suposición común es que tal persona es el usuario
que reclama serlo si sabe algo que sólo el usuario debería saber. Esto se denomina autentificación
por conocimiento. El otro método consiste en suponer que una persona es un usuario legítimo si
posee algo que se supone sólo puede estar en manos del usuario. Ejemplos de estos métodos son
la comprobación con base en las contraseñas y la autentificación biométrica, es decir, la auten-
tificación basada en ciertas características biológicas únicas e inalterables de un usuario, como
sus huellas digitales, su retina o su iris. La autorización es el acto que consiste en determinar
los privilegios de un usuario. Éstos se utilizan para implementar protección.

Tabla 8.1 Terminología utilizada en el contexto de protección de la información

Término Explicación
Autentificación Comprobar la identidad del usuario. Los sistemas operativos casi siempre realizan
la autentificación por conocimiento, es decir, a una persona que afirma ser un usua-
rio X se le solicita mostrar algún conocimiento compartido sólo entre el SO y el
usuario X, como una contraseña.
Autorización Comprobar el derecho de un usuario a acceder a un recurso en una manera espe-
cífica.

En la figura 8.1 se muestra un esquema genérico para implementar seguridad y protección


en un sistema operativo. La organización de seguridad consiste en el servicio de autentifica-
ción y la base de datos de autentificación. La organización de protección radica en el servicio de
autorización, base de datos de autorización y del administrador del servicio y los recursos. La
base de datos de la autentificación contiene un par de la forma (identificación login, validación
de información) para todo usuario registrado del sistema operativo. La validación de informa-
ción se utiliza para autentificar al usuario. A fin de demostrar su identidad, una persona presenta
su identificación de entrada y alguna información de autentificación esperada por el sistema,
como una contraseña. El servicio de autentificación transforma esta información en alguna ma-
nera estándar y la compara con la validación de información para el usuario. La persona es un
usuario registrado si ambos requisitos coinciden.
El servicio de autentificación genera un símbolo de autentificación después de comprobar la
identidad de un usuario y pasa este símbolo al servicio de autorización. Éste utiliza una base de
datos de autorización, que contiene un par de la forma (símbolo de autentificación, privilegios)

09 MAQ. CAP. 08(F0694).indd 358 8/10/07 1:03:53 AM


8.1 Visión general de seguridad y protección 359

Login e información
de autentificación
Usuario
+ kernel Servicio de
Símbolo de autentificación
autentificación
Base de datos de
autentificación
proceso
Solicitudes Organización
y respuestas de seguridad
Solicitudes
y respuestas Cambios en
los privilegios
Símbolo de
autentificación

Administrador
de servicios Servicio de
y recursos sí/no autorización

Sistema de Base de datos


protección de autorización

Figura 8.1 Organización genérica de los sistemas de seguridad y protección en un sistema operativo.

para todo usuario registrado del sistema. Entonces, consulta su base de datos para encontrar los
privilegios otorgados al usuario y pasa esta información al administrador de servicios y recursos.
Siempre que el usuario o su proceso presentan una solicitud de un servicio o recurso, el kernel
le asocia el símbolo de autentificación. El administrador de servicios y recursos comprueba si el
usuario ha sido autorizado para usar el servicio o el recurso, y concede la solicitud si es consis-
tente con los privilegios del usuario.
Por razones que serán analizadas en otra sección, en casi todos los sistemas operativos la
validación de información para un usuario consiste en una forma cifrada de su contraseña. El
símbolo de autentificación para un usuario es la identificación de un usuario asignada por el
sistema operativo mientras registra al usuario. El sistema operativo recuerda la identificación
de un usuario hasta que el usuario se sale del sistema. Utiliza esta información siempre que un
usuario o un proceso hacen una solicitud de un recurso o un servicio. A un usuario autentificado
se le permite usar todos los servicios del sistema, excepto porque puede usar un archivo sólo si
el propietario del archivo lo ha autorizado explícitamente. El sistema de archivos suele mantener
y usar esta información, de modo que la autorización no se realiza de manera explícita y no se
mantiene ninguna base de datos.
La diferencia entre protección y seguridad constituye una clara división de asuntos para el
SO. En un sistema operativo convencional, la cuestión de la seguridad está limitada a garanti-
zar que sólo los usuarios registrados pueden utilizar un SO. Cuando una persona entra, se lleva
a cabo una comprobación de seguridad para determinar si la persona es un usuario del SO y,
en caso de serlo, obtiene su identificación de usuario. Luego de esta comprobación, todas las
amenazas a la información almacenada en el sistema constituyen asuntos relacionados con la
protección; el usuario del SO utiliza la identificación de una persona para decidir si puede ac-

09 MAQ. CAP. 08(F0694).indd 359 8/10/07 1:03:53 AM


360 CAPÍTULO 8 Seguridad y protección

ceder a un archivo específico en el SO. En un sistema distribuido, sin embargo, las cuestiones
concernientes a la seguridad son más complicadas debido a la presencia de la componente de la
red (consulte el capítulo 20). El análisis en este capítulo se restringirá a los sistemas operativos
convencionales.

Mecanismos y políticas En la tabla 8.2 se describen los mecanismos y las políticas de


seguridad y protección. Las políticas de seguridad especifican si puede permitírsele a una per-
sona usar un sistema. Las políticas de protección especifican si debe permitírsele a un usuario
el acceso a un archivo específico. Estas políticas se reaplican fuera del dominio del SO. Un
administrador de un sistema decide si debe permitírsele a una persona que se convierta en
un usuario de un sistema. De manera semejante, mientras crea un nuevo archivo, un usuario
especifica el conjunto de usuarios a los que se ha permitido el acceso a tal archivo. Los mecanis-
mos de seguridad y protección se utilizan para implementar estas políticas haciendo comproba-
ciones específicas durante la operación del sistema.

Tabla 8.2 Políticas y mecanismos de seguridad y protección

Seguridad
• Política: Si una persona puede volverse usuario del sistema. El administrador del
sistema aplica la política mientras registra nuevos usuarios.
• Mecanismos: Agregar o quitar usuarios. Comprobar si una persona es un usuario re-
gistrado (es decir, lleva a cabo autentificación). Realiza cifrado para asegurar confi-
dencialidad de los datos.
Protección
• Política: El propietario del archivo especifica la política de autorización para un
archivo. Decide qué usuario puede acceder a un archivo y de qué manera.
• Mecanismos: Establece o cambia información de autorización para un archivo. Com-
prueba si una solicitud de procesamiento de un archivo se ajusta a los privilegios del
usuario.

Los mecanismos de seguridad agregan nuevos usuarios o comprueban si una persona es


un usuario autorizado del sistema. El segundo mecanismo se denomina autentificación, y se
invoca siempre que una persona desea entrar a un SO. Los mecanismos de protección estable-
cen información de protección para un archivo o para comprobar si puede permitírsele a un
usuario el acceso a un archivo. Son invocados cuando un proceso desea acceder a algún archivo
o cuando el propietario de un archivo desea modificar la lista de usuarios que pueden acceder
al archivo.

8.2 OBJETIVOS DE LA SEGURIDAD Y DE LA PROTECCIÓN

Los objetivos de la seguridad y de la protección son garantizar confidencialidad, privacidad,


autenticidad e integridad de la información. En la tabla 8.3 se proporcionan descripciones de
estos objetivos.
La confidencialidad constituye una cuestión de seguridad porque es amenazada por entida-
des fuera de un sistema operativo. Un SO aborda esta cuestión utilizando el servicio de autentifi-
cación. La privacidad es un asunto de protección. Un SO se encarga de ella a través del servicio

09 MAQ. CAP. 08(F0694).indd 360 8/10/07 1:03:54 AM


8.2 Objetivos de la seguridad y de la protección 361

Tabla 8.3 Objetivos de la seguridad y la protección en computación

Objetivo Descripción
Confidencialidad Sólo usuarios autorizados deben poder acceder a la
información.
Privacidad Establece o cambia información de autorización para
un archivo. Comprueba si una solicitud de procesa-
miento de un archivo se ajusta a los privilegios del
usuario.
Autenticidad Debe ser posible comprobar la fuente o el remitente de
la información, y también verificar que ésta se preser-
va en la forma en que fue creada o enviada.
Integridad No debe destruirse o corromperse información.

de autorización y del administrador de servicios y recursos. El servicio de autorización determi-


na los privilegios de un usuario, y el administrador de servicios y recursos rechaza solicitudes
que exceden los privilegios de un usuario. Corresponde a los usuarios asegurar privacidad de su
información utilizando esta organización. Un usuario que desea compartir sus programas con
otros usuarios debe establecer, según corresponda, la autorización para usar esta información.
Esto se denomina forma controlada de compartir la información y se basa en el principio de la
necesidad por conocer.
La confidencialidad, la autenticidad y la integridad son cuestiones relacionadas tanto con
la protección como con la seguridad. Estas cuestiones son fáciles de satisfacer en lo que corres-
ponde a la protección, ya que la identidad de un usuario ha sido comprobada, y la autorización
y validación de una solicitud forman parte de la organización de protección que se muestra
en la figura 8.1. Sin embargo, es necesario efectuar arreglos para satisfacer la confidenciali-
dad, la autenticidad y la integridad de cuestiones de seguridad. Estos temas se analizarán en
el capítulo 20.
Resulta interesante ver cómo surgen las amenazas a la protección y a la seguridad en un
SO. Primero se considerará un SO convencional. Este sistema utiliza autentificación a fin de
asegurar que sólo los usuarios autorizados puedan entrar al sistema e iniciar procesos. Por
tanto, sabe qué usuario ha iniciado un proceso específico y puede comprobar fácilmente si un
proceso está autorizado para utilizar ciertos recursos. Cuando los procesos se comunican con
otros procesos, las acciones del SO concernientes a la comunicación también están restringidas
al mismo nodo.
La situación es diferente cuando un sistema cuenta con una conexión en Internet y un usua-
rio descarga datos o programas de Internet. Una entidad externa al SO puede ser capaz de co-
rromper los datos y programas que se están descargando, y éstos convertirse en amenazas a la
seguridad.
Las amenazas a la seguridad pueden presentarse más fácilmente en un SO distribuido. Un
mensaje entre procesos puede cruzar los límites entre los nodos a medida que se desplaza entre
un emisor y un receptor. La comunicación entre nodos se lleva a cabo sobre ligas de comuni-
cación abiertas, incluidas ligas públicas. Así, es posible que una entidad externa manipule los
mensajes.

09 MAQ. CAP. 08(F0694).indd 361 8/10/07 1:03:54 AM


362 CAPÍTULO 8 Seguridad y protección

8.3 ATAQUES A LA SEGURIDAD

Los intentos de una persona o entidad por violar la seguridad de un sistema se llaman ataques a
la seguridad, y tal persona o entidad se denomina intruso o adversario. La comunicación es un
componente vulnerable de un entorno de cómputo, de modo que muchos ataques se lanzan a tra-
vés de la componente de comunicación. Dos ataques a la seguridad evidentes son la intercepción
de la comunicación (eavesdropping) y la manipulación. Estos ataques ocurren principalmente en
sistemas operativos distribuidos, que se analizarán en el capítulo 20.

Tabla 8.4 Clases de ataques a la seguridad

Ataque Descripción
Enmascaramiento Un intruso es capaz de hacerse pasar por un usuario regis-
trado del sistema.
Negación del Algún aspecto de la operación de un sistema operativo es
servicio alterado, de modo que no puede admitir algunos servicios
como era de esperar.

En la tabla 8.4 se describen dos formas comunes de ataques a la seguridad en sistemas no


distribuidos. En el ataque por enmascaramiento, un intruso puede acceder a los registros de
un usuario registrado del sistema o, lo que es peor, puede corromper o destruir información
perteneciente al usuario. La forma evidente de lanzar este tipo de ataque consiste en romper la
contraseña de un usuario y usar este conocimiento para pasar la prueba de autentificación en el
momento de entrar al sistema. Otro método consiste en un enmascaramiento más sutil a través
de programas que se importan desde un entorno de software. Este método se analizará en la
sección 8.3.1.
Un ataque por negación del servicio, también conocido como ataque DoS, es lanzado me-
diante el aprovechamiento de alguna vulnerabilidad en el diseño en la operación de un SO. Un
ataque DoS puede lanzarse a través de varios medios; algunos de éstos sólo pueden ser utilizados
por usuarios de un sistema, mientras otros pueden ser empleados por intrusos ubicados en otros
sistemas. Muchos ataques DoS pueden lanzarse a través de medios legítimos, lo cual facilita
lanzarlos y hacerlos difícil de detectar y de evitar por un SO.
Un ataque DoS puede lanzarse mediante la corrupción de un programa que ofrece algún
servicio o de la destrucción de alguna información de configuración dentro de un kernel; por
ejemplo, el uso de un dispositivo de E/S puede negarse cambiando su entrada en la tabla de
dispositivos físicos del kernel. Otra clase de ataques DoS pueden lanzarse mediante la sobre-
carga de un recurso a través de medios fantasma en tal medida que a los verdaderos usuarios
del recurso se les niega su uso. Si el kernel de un SO limita el número total de procesos que
pueden crearse debido a presión ejercida sobre las estructuras de datos del kernel, un usua-
rio puede crear un gran número de procesos de modo que ningún otro usuario pueda crear pro-
cesos. El uso de sockets en la red puede negarse de manera semejante abriendo un gran número
de ellos. Un ataque DoS a la red puede lanzarse inundándola con mensajes pretendidamente
enviados a un servidor particular de modo que el ancho de banda de la red se niegue a mensajes
genuinos, y el servidor se encuentre tan ocupado recibiendo mensajes que no tenga tiempo de

09 MAQ. CAP. 08(F0694).indd 362 8/10/07 1:03:54 AM


8.3 Ataques a la seguridad 363

responder a ninguno. Un ataque DoS distribuido es aquél lanzado por unos cuantos intrusos
ubicados en huéspedes diferentes en la red, y es aún más difícil de detectar y evitar.

8.3.1 Caballos de Troya, virus y gusanos

Los caballos de Troya, los virus y los gusanos constituyen formas novedosas para causar estra-
gos en un sistema de cómputo al colocar programas o códigos capaces de perpetrar una gama de
ataques a la seguridad. Sus características se resumen en la tabla 8.5.

Tabla 8.5 Amenazas a la seguridad a través de caballos de Troya, virus y gusanos

Amenaza Descripción
Caballo de Troya Programa que lleva a cabo una función legítima conocida por un SO o sus usua-
rios, pero que también posee una parte oculta que puede utilizarse para propósitos
infames, como ataques a la seguridad del mensaje o suplantación.
Virus Pieza de un código que por sí mismo es capaz de atacar a otros programas en
el sistema y dispersarse a otros sistemas cuando se copian o transfieren los pro-
gramas.
Gusano Programa que se difunde a otros sistemas de cómputo mediante la explotación
de huecos de seguridad, como debilidades en las instalaciones para creación de
procesos remotos.

En el caso de un caballo de Troya o de un virus, una amenaza al sistema de seguridad es co-


locada en un sistema de cómputo a través de un subterfugio. Ambos entran al sistema cuando un
usuario no sospechoso descarga un programa en el Internet o lo carga desde un CD. Por el con-
trario, un gusano no entra al sistema de cómputo a través de transferencias explícitas de progra-
mas. Un gusano que ya está en un sistema de cómputo se dispersa a otros sistemas de cómputo
por sí mismo. Una vez activado, el programa oculto en un caballo de Troya o el código en un
virus o el gusano provoca violaciones en la seguridad.
Un caballo de Troya es un programa escrito con la intención de causar estragos en un sis-
tema de cómputo. Por ejemplo, es capaz de borrar un disco duro en la computadora, lo cual
constituye una violación al requerimiento de seguridad, o hacer que un sistema se bloquee o
se vuelva más lento, lo cual supone negación del servicio. También puede monitorear el tráfico
entre el usuario y otros procesos a fin de reunir información para efectos de enmascaramiento,
o iniciar conversaciones espurias con la misma intención. Un ejemplo típico es un programa
spoof login que proporciona un mensaje con identificación falsa para engañar a un progra-
ma a fin de que revele información sobre alguna contraseña. Debido a que un caballo de Troya es
cargado de manera explícita por un usuario, no es difícil seguir la pista de su autor u origen.
Un virus es una pieza de un código que puede adjuntarse él mismo a otro programa en el
sistema y dispersarse a otros sistemas una vez que los programas se transfieren o copian. Mien-
tras se adjunta a otro programa, un virus escribe su propia dirección como la dirección inicial
de ejecución del programa. De esta forma adquiere el control cuando el programa es activado e
infecta algunos programas existentes en un disco dentro del sistema, al adjuntarse a tales progra-
mas. Después de eso, pasa el control al programa genuino para su ejecución. El paso de infección
no consume mucho tiempo de CPU, de modo que un usuario no puede saber que el programa

09 MAQ. CAP. 08(F0694).indd 363 8/10/07 1:03:54 AM


364 CAPÍTULO 8 Seguridad y protección

ejecutado transporta un virus. La forma en que un virus se introduce él solo a otro programa es
mucho más difícil de rastrear que en el caso de un caballo de Troya. Aparte de infectar a otros
programas, un virus comúnmente permanece latente hasta que algún evento, como una fecha o
un instante específico, lo despiertan. Entonces lanza uno de los ataques antes mencionados. Un
virus de correo electrónico entra en un sistema de cómputo a través de un correo electrónico y
envía correos ilegítimos a los usuarios cuyas direcciones electrónicas puedan encontrarse en
libros de direcciones en el sistema de cómputo. Puede saturar los buzones de los usuarios, pro-
vocando así negación del servicio.
Un virus no es capaz de duplicar o lanzar un ataque a la seguridad a menos que se ejecute
un programa infectado con un virus. Por tanto, los diseñadores de virus crearon una clase de
virus denominada virus del sector de arranque. Éstos se colocan ellos mismos en el sector
de arranque de un disco duro o de un disco extraíble; tienen oportunidad de ejecutarse cuando se
arranca el sistema y pueden duplicarse cuando se hace un nuevo disco.
Un gusano es un programa que se duplica a sí mismo al dispersarse a otros sistemas de
cómputo, aprovechando los huecos que hay en su organización. Se sabe que los gusanos se
duplican a ritmos inimaginablemente altos, recargando la red y consumiendo tiempo de CPU
durante la duplicación. Debido a su capacidad de autoduplicación, resulta mucho más difícil
rastrear a un gusano que a un virus.
Los ataques a la seguridad lanzados a través de caballos de Troya, virus o gusanos pueden
frustrarse llevando a cabo una o más de las siguientes acciones:

• Extremar las precauciones al cargar nuevos programas en una computadora.


• Usar programas antivirus.
• Tapar los huecos en el sistema de seguridad a medida que se descubren o reportan.

Cargar programas desde discos originales que son proporcionados por un vendedor puede eli-
minar una fuente primaria de caballos de Troya o virus. Este método es particularmente eficaz
desde la introducción de la tecnología del disco compacto (CD). Debido a que no es posible
modificar estos discos, un programa genuino no puede ser reemplazado por un caballo de Troya,
y un disco proporcionado por un vendedor no puede ser infectado por un virus.
Los programas antivirus analizan cada programa en un disco para ver si contienen algu-
na característica semejante a cualquiera de los virus conocidos. La característica principal que
buscan es si la dirección inicial de ejecución del programa ha sido modificada o si los primeros
bytes de un programa llevan a cabo acciones semejantes a la duplicación, por ejemplo, si adjun-
tan un código a los programas de un disco.
Los vendedores de SO colocan periódicamente en sus sitios de la red información sobre
vulnerabilidades en la seguridad de sus sistemas operativos y proporcionan parches de seguridad
para sellar tales huecos. Un usuario que utiliza una máquina para un solo usuario comprueba tal
información y aplica de manera periódica esos parches. De esta forma se frustran ataques a la
seguridad lanzados a través de gusanos.

8.4 ASPECTOS FORMALES Y PRÁCTICOS DE LA SEGURIDAD

Un intruso puede emplear una variedad de ataques ingeniosos para violar la seguridad, de modo
que es necesario probar formalmente la capacidad del sistema para resistir todas las formas de
ataque. Una prueba formal requiere de un modelo de seguridad que incluya políticas y meca-

09 MAQ. CAP. 08(F0694).indd 364 8/10/07 1:03:54 AM


8.4 Aspectos formales y prácticos de la seguridad 365

nismos de seguridad, una lista de amenazas, una lista de ataques fundamentales y una metodo-
logía de prueba. La lista de ataques debe ser completamente demostrable en el sentido de que
cualquier ataque concebible que suponga una amenaza en la lista de amenazas puede obtenerse
a través de una combinación de los ataques fundamentales. La metodología de prueba debe ser
capaz de determinar sin ninguna ambigüedad si el modelo de seguridad puede resistir ciertas
formas de ataque.
Siguiendo estas líneas, hace algún tiempo se elaboraron algunos trabajos sobre seguridad.
En el modelo tomar-conceder seguridad en computación (Landwehr, 1981), los procesos otor-
gaban privilegios a los objetos y a otros procesos. Un privilegio para un objeto permitía a su
poseedor acceder al objeto en forma específica. Un privilegio para otro proceso permitía a
su poseedor tomar un privilegio de acceso poseído por el otro proceso (una operación take,
tomar), o transferir un privilegio de acceso de sí mismo a otro proceso (una operación grant,
conceder). La prueba establecía si un proceso específico podía obtener un privilegio de acceso
específico para un objeto específico a través de una serie de operaciones de tomar y conceder.

Ejemplo 8.1 En una organización que utiliza un sistema de seguridad semejante al militar, todos los
documentos están clasificados en tres niveles de seguridad: no clasificado, confidencial y secreto.
A las personas que trabajan en la organización se les proporcionan autorizaciones de seguridad
denominadas U (no clasificado, unclasified), C (confidencial) y S (secreto) con la condición de que
una persona puede acceder a todos los documentos en su nivel de clasificación de seguridad y en
niveles inferiores de clasificación. Así, una persona con clasificación C puede acceder a documen-
tos confidenciales y no clasificados, pero no a documentos secretos.
La organización utiliza un sistema Unix y las personas en la organización usan las característi-
cas de Unix para acceder a archivos que contienen documentos. A fin de comprobar si la seguridad
de los documentos es infalible, todas las operaciones en el sistema se modelan y comprueban para
ver si una persona puede acceder a un documento que está en un nivel de clasificación superior al
de su autorización de seguridad. Se encontró que una utilización no restringida de la característica
setuid de Unix puede conducir a violaciones en la seguridad porque permite que un usuario ejecute
un programa con los privilegios de su propietario, en vez de hacerlo con sus propios privilegios
(consulte la sección 8.8.4).

En la práctica resulta muy difícil utilizar el método formal porque requiere una lista de ata-
ques fundamentales; no es posible desarrollar esta lista para sistemas operativos modernos. Este
método también requiere un planteamiento nítido de políticas de seguridad. Es difícil satisfacer
este requerimiento porque casi todas las políticas de seguridad constan de reglas que se plantean
de manera informal, de modo que todos puedan comprenderlas en una organización.

8.4.1 Aspectos prácticos de la seguridad

La componente de seguridad de un SO consta de un arreglo de mecanismos y políticas que per-


miten que un usuario autorizado realice operaciones, como compartir información e intercam-
biar mensajes, con otros usuarios autorizados del sistema. Este arreglo debe frustrar los ataques
de seguridad realizados por un extraño.
En la figura 8.2 se muestra un arreglo de políticas y mecanismos de seguridad. Ahí se uti-
lizan dos mecanismos básicos: autentificación y cifrado. La autentificación ya se describió. El
cifrado se utiliza para implementar la confidencialidad de la autentificación de la base de datos
y se analizará en la sección 8.5.

09 MAQ. CAP. 08(F0694).indd 365 8/10/07 1:03:55 AM


366 CAPÍTULO 8 Seguridad y protección

Políticas

Cifrado

Autentificación

Figura 8.2 Mecanismos y políticas de seguridad.

8.5 CIFRADO

El cifrado es una técnica para proteger la confidencialidad de los datos. Los mecanismos de
seguridad y protección lo utilizan para proteger información concerniente a los usuarios y sus
recursos. También puede usarse para guardar información perteneciente a los usuarios. La rama
de la ciencia que se encarga de las técnicas de cifrado se denomina criptografía. En la tabla 8.6
se resumen los términos y las definiciones clave que se usan en criptografía.
El cifrado se lleva a cabo mediante la aplicación de una transformación algorítmica de los
datos. La forma original de los textos se denomina forma de texto plano y su forma transformada
es llamada forma cifrada o de texto cifrado. Se usa la siguiente notación:

Pd : Forma de texto plano de los datos d


Cd : Forma de texto cifrado de los datos d

donde Pd ⬅ d. La confidencialidad de los datos se protege almacenando la información en for-


ma de texto cifrado, en vez de hacerlo como texto plano. El cifrado se lleva a cabo mediante la
aplicación de un algoritmo de cifrado E con un código de cifrado específico k a los datos. En
su forma de cifrado más sencilla, denominada cifrado simétrico, un texto cifrado se descifra
utilizando un algoritmo de descifrado D con la misma llave k para obtener su forma de tex-
to plano. En técnicas avanzadas de cifrado denominadas cifrado asimétrico, para descifrar un
texto cifrado se utiliza una llave diferente k´. En la figura 8.3 se ilustra el cifrado simétrico.

Llave de Llave de
cifrado (k) descifrado (k)

Algoritmo texto Algoritmo


de cifrado cifrado de descifrado
texto plano texto plano
(E) (D)

Figura 8.3 Cifrado y descifrado de datos.

El cifrado y el descifrado de datos se representan utilizando los algoritmos E y D con la llave


k como aplicaciones de las funciones Ek y Dk, respectivamente. Así,

Cd ⫽ Ek(d)
Pd ⫽ Dk(Cd)

09 MAQ. CAP. 08(F0694).indd 366 8/10/07 1:03:55 AM


8.5 Cifrado 367

Tabla 8.6 Términos y definiciones en criptografía

Término Descripción
Cifrado El cifrado es la aplicación de una transformación algorítmica Ek a los
datos, donde E es un algoritmo de cifrado y k es una llave de cifrado.
Se utiliza para proteger la confidencialidad de los datos. Los datos
originales se recuperan aplicando una transformación Dk⬘ donde k⬘
es una llave de descifrado. Un esquema en el que se utiliza k ⫽ k⬘ se
denomina cifrado simétrico, y uno en el que se usa k ⫽ k⬘ se llama
cifrado asimétrico.
Texto plano Datos a cifrar.
Texto cifrado Forma cifrada del texto plano.
Confusión El principio de confusión de Shannon requiere de que cambios pro-
vocados por un texto cifrado debido a un cambio en el texto plano no
deben ser fáciles de encontrar.
Difusión El principio de difusión de Shannon requiere que el efecto de una
pequeña subcadena en el texto plano debe estar ampliamente distri-
buido en el texto cifrado.
Ataques a Un ataque es una serie de intentos realizados por un intruso para en-
sistemas contrar una función de descifrado Dk. En un ataque único con texto
criptográficos cifrado, el intruso sólo puede examinar un conjunto de textos cifrados
para determinar Dk. En un ataque con texto plano conocido, el intruso
cuenta con una oportunidad para examinar las formas de texto plano
y texto cifrado de algunos datos, mientras que en un ataque con texto
plano seleccionado el intruso puede escoger un texto plano y obtener
su forma de texto cifrado para realizar el ataque.
Función de Una función, el cálculo de cuya inversa es suficientemente costoso
una sola vía para ser considerado impráctico. Su uso como una función de cifrado
hace difíciles los ataques criptográficos.
Código de Una técnica de código de bloque sustituye los bloques de tamaño fijo
bloque del texto plano por bloques de texto cifrado. Introduce algo de confu-
sión, pero no suficiente difusión.
Cifra de flujo Se considera que tanto un texto plano como la llave de cifrado son
flujos de bits. Unos cuantos bits en el texto plano se cifran utilizando
un número igual de bits en la llave de cifrado. Una cifra de flujo no
introduce confusión y sí limitada difusión; sin embargo, sus variantes
pueden introducir un alto nivel de difusión.
DES El estándar de cifrado de datos (Data Encryption Standard, DES) de
la Oficina Nacional de Estándares (National Bureau of Standards),
adoptado en 1976, utiliza una técnica de código de bloque y propor-
ciona encadenamiento de código de bloque como una opción. Contie-
ne 16 repeticiones que llevan a cabo transformaciones complejas en
el texto plano o en el texto cifrado intermedio.
AES El estándar avanzado de cifrado (Advanced Encryption Standard)
es una nueva norma adoptada por la Oficina Nacional de Estándares
(National Bureau of Standards) en 2001. Realiza entre 10 y 14 vueltas
de operaciones, de las cuales todas sólo implican sustituciones y per-
mutaciones, en bloques de texto plano de 128, 192 o 256 bits.

09 MAQ. CAP. 08(F0694).indd 367 8/10/07 1:03:55 AM


368 CAPÍTULO 8 Seguridad y protección

Resulta evidente que las funciones Ek y Dk deben satisfacer la relación

Dk(Ek(d)) ⫽ d, para toda d.

Así, un proceso debe ser capaz de hacer la transformación Dk para leer o manipular datos ci-
frados.
El uso de la técnica de cifrado se basa en la hipótesis de que resulta impráctico para un
intruso determinar al tanteo la llave de descifrado. (En una sección posterior se verá cómo esta
garantía se cumple sólo en sentido probabilístico y no en sentido absoluto.) Dada esta hipótesis,
puede verse que el cifrado frustra ataques dirigidos a la fuga del contenido de los mensajes a
través de la intercepción de la comunicación. También frustra intentos de manipulación de men-
sajes de la sigue manera: un mensaje contiene la forma de texto cifrado de la información que los
procesos están intercambiando. Un intruso podrá alterar un mensaje o elaborar nuevos mensajes,
ya que no hay protección por escrito para los mensajes en tránsito. Sin embargo, el descifrado
de un mensaje así producirá datos ininteligibles. Por tanto, el destinatario puede diferenciar
entre un mensaje genuino y uno manipulado. Se dice que el descifrado es infructuoso si produce
datos ininteligibles.

8.5.1 Ataques a los sistemas criptográficos

Un ataque a un sistema criptográfico consta de una serie de intentos por encontrar una función
de descifrado Dk. Debido a que Dk(Ek(d)) ⫽ d, Dk es la inversa de Ek. Por tanto, un ataque
implica encontrar la inversa de Ek. Si la calidad del cifrado se define como su capacidad para
resistir ataques, entonces el objetivo de una técnica de cifrado es proporcionar cifrado de alta
calidad a bajo costo. La calidad de cifrado es mejor si la función Ek es de una sola vía, es decir,
si el cálculo de su inversa a través de un ataque implica una cantidad impráctica de esfuerzo y
tiempo.
Un intruso, que puede ser una entidad interna o externa, puede lanzar una variedad de ata-
ques a un sistema criptográfico. La naturaleza de un ataque depende de la posición que puede
ocupar un intruso dentro del sistema. Si un intruso no es capaz de invocar la función de cifrado
y sólo puede examinar los datos en la forma de texto cifrado, está obligado a depender de con-
jeturas. Éste es un método al tanteo donde la función Dk se intenta adivinar repetidamente hasta
que su aplicación a un texto cifrado produce resultados inteligibles. Éste se denomina ataque
minucioso porque puede ser necesario intentar todas las posibilidades para Dk. Supone un gran
número de intentos. Los ataques que se describen a continuación implican menos intentos.

Ataque único con texto cifrado Para efectos de adivinar Dk un intruso utiliza alguna
información que es ajena a un texto cifrado. Por ejemplo, se conoce la frecuencia con la que
aparece cada letra del alfabeto en un texto en inglés. Si se sabe que Ek sustituye a cada letra
en un mensaje por otra letra del alfabeto (esto se denomina cifra de sustitución), un intruso
puede utilizar esta información para conjeturar Dk. Un ataque único con texto cifrado es más
eficaz que un ataque minucioso si es posible identificar una característica ajena idónea de texto
cifrado.

09 MAQ. CAP. 08(F0694).indd 368 8/10/07 1:03:55 AM


8.5 Cifrado 369

Ataque con texto plano conocido Un intruso conoce el texto plano correspondiente a un
texto cifrado. Este ataque es posible si un intruso puede ganar una posición dentro del SO desde
la cual pueda observar tanto un texto plano como el texto cifrado correspondiente. Reunir un
número suficiente de pares (texto plano, texto cifrado) facilita determinar Dk.

Ataque con texto plano seleccionado Un intruso es capaz de proporcionar un texto plano
y observar su forma cifrada. En efecto, es posible elegir una d y observar Ek(d). Esta posibilidad
permite que el intruso construya sistemáticamente una colección de pares (texto plano, texto
cifrado) para apoyar y refinar sus conjeturas durante el ataque.
Cuando se analice la contraseña de seguridad en la sección 8.6.1 se proporcionarán ejemplos
de estos ataques. Se cree que la calidad del cifrado mejora con un incremento en el número de
bits en la llave k. Por ejemplo, en un ataque minucioso se necesitarán 255 intentos para romper
un esquema de cifrado en el que se use una llave de 56 bits. Se creía que la gran cantidad de
intentos hacía computacionalmente seguro tal esquema contra ataques minuciosos. Sin embargo,
poderosas técnicas matemáticas, como el análisis diferencial, pueden aplicarse para conjeturar
Dk mucho más fácilmente que en un ataque minucioso. Por consiguiente, se estima que las llaves
necesitarán ser de varios miles de bits de longitud para asegurar que las funciones de cifrado son
de una sola vía.

8.5.2 Técnicas de cifrado

Las técnicas de cifrado difieren en la forma en que intentan derrotar los intentos de intrusos para
conjeturar Dk. El método fundamental es enmascarar las características de un texto plano, es
decir, asegurar que un texto cifrado no revele características del texto plano correspondiente, sin
incurrir en un costo alto de cifrado.
La técnica de cifrado más sencilla es la clásica cifra de sustitución, donde cada letra en un
texto plano se reemplaza por alguna otra letra del alfabeto. Esta técnica no enmascara ninguna
característica de los textos planos, por lo que es vulnerable a un ataque basado en el análisis del
texto cifrado. Por ejemplo, podría intentarse conjeturar el código del espacio que separa dos
palabras. Empezando con esta pista, quizá sea posible encontrar palabras de una sola letra. En
inglés sólo hay tres de estas palabras: a, i, o, de modo que será posible conjeturar los códigos
de estas tres letras. De hecho, puede usarse una comprobación más simple para obtener pistas
valiosas a fin de conjeturar Dk: las letras del alfabeto pueden disponerse en orden decreciente de
frecuencia de uso en un texto cifrado. Una comparación de esta lista con una lista semejante para
el idioma inglés puede usarse a fin de conjeturar Dk. Para derrotar tales intentos, las técnicas de
cifrado tratan de oscurecer las posiciones de las letras en un texto plano.
Shannon (1949) planteó dos principios para el diseño de técnicas de cifrado de alta calidad.
Éstos se denominan confusión y difusión. El principio de confusión defiende que los cambios
provocados en el texto cifrado debido a un cambio en el texto plano no deben ser fáciles de
encontrar. Este principio dificulta que un intruso encuentre correlaciones entre un texto plano
y el texto cifrado correspondiente. El principio de difusión indica que el efecto de una pequeña
subcadena en el texto plano debe distribuirse tanto como sea posible a través del texto cifrado.
Cuando hay un elevado nivel de difusión, un pequeño cambio en un texto plano modifica muchas
partes del texto cifrado. Esta característica hace difícil que un intruso encuentre patrones útiles

09 MAQ. CAP. 08(F0694).indd 369 8/10/07 1:03:56 AM


370 CAPÍTULO 8 Seguridad y protección

en un texto cifrado, de modo que se requieren más datos para llevar a cabo un ataque basado en
análisis de frecuencias. A continuación se abordarán tres esquemas de cifrado y se analizarán sus
propiedades de confusión y difusión.

Código de bloque El código de bloque es una extensión de la cifra de sustitución clásica.


Una técnica de código de bloque lleva a cabo la sustitución de bloques de tamaño fijo de un texto
plano por bloques de texto cifrado del mismo tamaño. Por ejemplo, un bloque que consta de, por
ejemplo, n bits, se cifra con una llave k para obtener un bloque de n bits del texto cifrado (consul-
te la figura 8.4). Estos bloques se ensamblan para obtener el texto cifrado. La técnica de código
de bloque es fácil de implementar. Introduce algo de confusión, aunque no suficiente difusión, de
modo que bloques idénticos en un texto plano producen bloques idénticos en el texto cifrado.
Esta característica la hace vulnerable a un ataque basado en análisis de frecuencias, así como a
ataques con texto plano conocido o con texto plano seleccionado. La gravedad de tales ataques
puede reducirse utilizando valores más grandes de n.

Llave de
cifrado (k)

Código
de bloque
texto plano texto cifrado

Figura 8.4 Código de bloque.

Cifra de flujo Una cifra de flujo considera que tanto un texto plano como la llave de cifrado
son flujos de bits. El cifrado se lleva a cabo aplicando una transformación que implica unos cuan-
tos bits del texto plano y un número igual de bits de la llave de cifrado. Una opción conocida de
la transformación es una transformación bit por bit del texto plano, que se realiza comúnmente
efectuando una operación como la del “o exclusivo” sobre un bit del texto plano y un bit de la
llave de cifrado.
Una cifra de flujo es más rápida que un código de bloque. No proporciona confusión o
difusión cuando se aplica una transformación de bit por bit. Sin embargo, puede utilizarse para
simular el cojín de una sola vez, famoso por su utilización en codificación durante la Segunda
Guerra Mundial. Esta cifra se denomina cifra de Vernam. Utiliza un flujo aleatorio de bits cuyo
tamaño coincide exactamente con el del texto plano como la llave de descifrado, de modo que
subcadenas idénticas en un texto plano no conducen a subcadenas en el texto cifrado. La llave
de cadena se usa para codificar sólo un texto plano. Tal cifra proporciona un elevado nivel de
seguridad.
Una variante de la cifra de flujo denominada indistintamente cifra de la autollave, cadena de
cifra asíncrona o cifra autosincronizada introduce difusión. Utiliza un generador de la llave
de cadena que usa una de las funciones de ésta y los últimos bits del flujo de texto cifrado
generado hasta ese momento (consulte la figura 8.5). Opera como sigue: la llave de cadena se

09 MAQ. CAP. 08(F0694).indd 370 8/10/07 1:03:56 AM


8.5 Cifrado 371

utiliza para cifrar los primeros bits del texto plano. El texto cifrado correspondiente a estos bits
del texto plano se usa luego como llave de cadena para cifrar los siguientes bits del texto plano y
así sucesivamente hasta que todo el texto plano está cifrado. Así, una subcadena en el texto plano
influye en el cifrado del resto del texto plano.

Llave de
cifrado (k)

Cifra de
texto plano flujo texto cifrado

Figura 8.5 Cifra de flujo.

DES El estándar de cifrado de datos (Data Encryption Standard) fue desarrollado por IBM
para la Oficina Nacional de Estándares (National Bureau of Standards). Utiliza una llave de 56
bits para cifrar bloques de datos de 64 bits. Así, se trata de un código de bloque. Sin embargo,
para superar el problema de difusión deficiente, el DES proporciona un modo de encadenamien-
to de bloque de cifra (CBC). En este modo, el primer bloque de texto plano se combina con un
vector inicial, aplicando una operación “o exclusivo” y después se cifra. Luego, el texto cifrado
se combina con el segundo bloque del texto plano, utilizando una operación “o exclusivo”, y así
sucesivamente.
DES contiene pasos explícitos que incorporan difusión y confusión. La difusión se intro-
duce usando permutaciones del texto plano. La confusión es suministrada por medio de una
sustitución de un número de m bits por un número de n bits al omitir selectivamente algunos
bits, y luego usando el número de n bits en el proceso de cifrado. Estos pasos oscurecen las
características de un texto plano y el proceso de cifrado, de modo que un intruso debe recurrir
a una variante del ataque minucioso para romper el cifrado. Un ataque minucioso requiere 255
intentos, de modo que es considerado poco práctico. (Sin embargo, un mensaje cifrado usando
DES fue decodificado por medio de una búsqueda al tanteo realizada de manera conjunta por
muchos usuarios. El número de intentos requeridos en este esfuerzo fue de sólo alrededor de 25
por ciento del máximo teórico.)
DES consta de tres pasos: uno inicial de permutación, el paso de la transformación y el final
de permutación. El paso de la transformación consta de 16 repeticiones. En cada una, la cade-
na de entrada a la repetición es sometida a una transformación compleja. El descifrado se lleva a
cabo aplicando los mismos pasos en orden inverso.
En la figura 8.6 se ilustran operaciones realizadas en cada repetición. En la primera, la
cadena de entrada es el texto plano. En todas las demás, la cadena de entrada es la salida de
la repetición previa. La cadena de entrada se separa en dos mitades de 32 bits cada una. La mitad
derecha se convierte en la mitad izquierda de la cadena resultante. La mitad derecha también es
sometida a una transformación usando una llave Ki que se obtiene al permutar la llave de cifra-
do k usando el número de repetición i. El resultado de esta operación se combina con la mitad
izquierda de la cadena de entrada, aplicando una operación “o exclusivo” para obtener la mi-
tad derecha de la cadena resultante.

09 MAQ. CAP. 08(F0694).indd 371 8/10/07 1:03:56 AM


372 CAPÍTULO 8 Seguridad y protección

Li 1 Ri−1 Cadena de entrada

Ki = Φ (k, i)
f

Li−1 + f (Ri−1 , Ki )

Li Ri Cadena resultante

Figura 8.6 Una repetición en DES.

La transformación de la mitad derecha de la cadena de entrada consta de los pasos siguien-


tes: primero, la mitad derecha se desarrolla hasta 48 bits al permutar sus bits y duplicar algunos
de ellos. La forma desarrollada se combina con la llave Ki aplicando una operación “o exclusivo”
(consulte la función f en la figura 8.6). El resultado de esta operación se separa en ocho grupos
de seis bits cada uno. Cada grupo de seis bits es la entrada de una caja S para su sustitución por
un grupo de cuatro bits. La caja S lleva a cabo una sustitución no lineal. Los resultados de la
sustitución se encadenan para obtener una cadena de 32 bits que se permuta a fin de obtener otra
cadena de 32 bits. Ésta se combina con la mitad izquierda de la cadena de entrada aplicando una
operación “o exclusivo” para obtener la mitad derecha de la cadena resultante.
Una crítica que se hacía al DES era que utilizaba una longitud de llave pequeña, lo cual lo
hacía vulnerable a ataques exitosos que usan tecnología contemporánea. En 1998, un mensaje
cifrado a través de DES fue decodificado en menos de tres días utilizando una computadora
diseñada especialmente. En 1990, otro fue descifrado en menos de un día utilizando 100 000
computadoras personales en Internet. Luego, el algoritmo triple DES fue endosado como una
norma interina hasta que se adoptó un nuevo estándar. Contenía tres repeticiones, donde cada
una aplicaba el algoritmo DES utilizando una llave distinta obtenida a partir de la llave de cifra-
do: las repeticiones primera y tercera llevaban a cabo el cifrado usando sus llaves, mientras la
segunda realizaba el cifrado usando su llave. En efecto, podía utilizar llaves hasta de 168 bits de
longitud, con lo cual se consideraba que era seguro contra ataques durante unos cuantos años.
El nuevo estándar, denominado estándar avanzado de cifrado (Advanced Encryption Standard:
AES) fue adoptado en 2001.

Estándar avanzado de cifrado (AES) AES es una variante de Rijndael, que es un algo-
ritmo de cifrado compacto y rápido que sólo utiliza sustituciones y permutaciones. Utiliza un
tamaño de bloque de 128 bits y llaves de 128, 192 o 256 bits, mientras que el de Rijndael puede
usar cualquier llave, y tamaños de bloque que varían de 128 a 256 bits, múltiplos de 32 bits. AES
utiliza un arreglo de 4 ⫻ 4 bytes, lo cual se denomina estado. Éste es un bloque de texto plano
en el cual se llevan a cabo varias vueltas de operaciones. El número de vueltas depende de la

09 MAQ. CAP. 08(F0694).indd 372 8/10/07 1:03:56 AM


8.6 Autentificación y seguridad de la contraseña 373

longitud de la llave: para llaves de 128 bits se hacen 10 vueltas; para 192 bits, 12 vueltas, y para
llaves de 256 bits se hacen 14. Cada vuelta consta de las operaciones siguientes:

1. Sustitución de bytes: Cada byte del estado se somete a una transformación no lineal apli-
cada por una caja S.
2. Desplazamiento de renglones: Los renglones en el estado se desplazan cíclicamente por
0, 1, 2 y 3 bytes, respectivamente.
3. Mezcla de columnas: Los cuatro bytes en una columna se sustituyen de modo que cada
byte del resultado es una función de los cuatro bytes en la columna.
4. Suma de llaves: Una subllave, cuyo tamaño es el mismo que el del estado, se obtiene a
partir de la llave de cifrado utilizando un programa de llave. La subllave y el estado se
consideran como cadenas de bits y se combinan aplicando una operación “o exclusivo”.
Si ésta es la última vuelta, el resultado de la operación “o exclusivo” es un bloque de tex-
to cifrado; en caso contrario, se usa como el estado para la siguiente vuelta de cifrado.

Para permitir tanto la realización de cifrado como de descifrado utilizando la misma secuencia
de pasos, antes de iniciar la primera vuelta se lleva a cabo la adición de una llave, y el paso de
mezcla de columnas se omite en la última vuelta.

8.6 AUTENTIFICACIÓN Y SEGURIDAD DE LA CONTRASEÑA

La autentificación por conocimiento frustra ataques por enmascaramiento en el supuesto de que


los usuarios autorizados no revelen la cuestión relevante de la información a otros y de
que esta información no puede ser conjeturada por una tercera parte implicada. La autentifica-
ción suele llevarse a cabo a través de contraseñas que utilizan el esquema mostrado en la figura
8.1. El sistema almacena información de validación de la forma (login id, <password_info> en
una tabla de contraseñas que actúa como la base de datos de autentificación, donde <password_
info ⫽ Ek(password). Cuando un usuario desea entrar al sistema, se le solicita proporcionar la
contraseña correcta. El sistema cifra la contraseña utilizando Ek y compara su resultado con la
cadena almacenada en la tabla de contraseñas. Se considera que el usuario es auténtico si ambas
coinciden.
Si un intruso tiene acceso a la tabla de contraseñas, puede lanzar uno de los ataques ya des-
critos en la sección 8.5.1 para determinar Ek. Alternativamente, el intruso puede lanzar un ataque
para romper la contraseña de un usuario individual. En el esquema antes descrito, si dos usuarios
tienen contraseñas idénticas, entonces las formas cifradas de sus contraseñas también lo son, lo
que facilitará el intento de un intruso por romper una contraseña si la tabla de contraseñas es visi-
ble para él. Por tanto, la función de cifrado E asume dos parámetros. Uno es la llave de cifrado
k y el otro es una cadena derivada de la identificación de entrada del usuario. Así, contraseñas
idénticas producen cadenas cifradas distintas.

Biometría En el futuro, los sistemas operativos podrán utilizar medios biométricos para
comprobar la identidad de un usuario. La clave de este método es utilizar una característica
biológica única e inalterable de un usuario para efectos de identificación. Algunos de los candi-
datos probables son las huellas digitales, la retina y el iris. El amplio uso de técnicas biométricas
dependerá, no obstante, de la disponibilidad de equipo económico y confiable para identificación
biométrica.

09 MAQ. CAP. 08(F0694).indd 373 8/10/07 1:03:56 AM


374 CAPÍTULO 8 Seguridad y protección

8.6.1 Seguridad de la contraseña

La seguridad de un sistema de cómputo puede ser violada mediante el rompimiento de una con-
traseña de alguna de sus cuentas. Los programas para romper contraseñas dependen del hecho
de que los usuarios pueden utilizar contraseñas basadas en nombres personales o de mascotas,
palabras del diccionario y números de placas de circulación de vehículos, o utilizar simples se-
cuencias de teclado como sus contraseñas. Aunque en Internet hay disponibles directrices para
elegir buenas contraseñas, los usuarios continúan usando contraseñas que no son difíciles de
adivinar. Algunas veces los usuarios usan contraseñas simples que son fáciles de recordar para
cuentas que se usan con poca frecuencia, siendo la copia común que no tienen muchos archivos
importantes en esa cuenta. Sin embargo, una contraseña suele ser el eslabón más débil en la ca-
dena de seguridad. Cualquier contraseña rota proporciona oportunidades a un intruso para lanzar
más ataques a la seguridad. Un gran número de problemas de seguridad están relacionados con
el uso de contraseñas deficientes.

Tabla 8.7 Técnicas del SO para derrotar ataques a las contraseñas

Técnica Descripción
Envejecimiento de Alienta u obliga a que los usuarios cambien sus contraseñas frecuente-
la contraseña mente, por lo menos una vez cada seis meses. Limita la exposición de una
contraseña a ataques de intrusos.
Cifrado de La forma cifrada de las contraseñas se almacena en un archivo del sistema.
contraseñas El archivo en sí puede ser visible para todos los usuarios del sistema. Sin
embargo, sólo es visible la forma de texto cifrado de las contraseñas. Un
intruso que es un usuario registrado puede utilizar el ataque elegido del
texto plano al cambiar su contraseña y ver su forma cifrada. Si las contra-
señas cifradas son visibles en Internet, lo cual no es probable, un intruso
que no sea usuario sólo puede usar ataques únicos con texto cifrado. O
bien, el intruso tendrá que llevar a cabo un ataque minucioso a través de
varios intentos para entrar al sistema.
Cifrar y ocultar El archivo cifrado no es visible para ninguna persona dentro o fuera del
información sobre sistema. Así, un intruso, que puede ser un usuario o un extraño, está obli-
la contraseña gado a utilizar un ataque minucioso a través de varios intentos para entrar
al sistema.

En la tabla 8.7 se resumen las técnicas utilizadas para derrotar ataques a las contraseñas. El
envejecimiento de la contraseña limita la exposición de las contraseñas a los intrusos, lo que las
hace más seguras. Otra forma de hacerlas más seguras es dejar que el administrador asigne “bue-
nas” contraseñas a los usuarios y evitar que éstos cambien sus contraseñas. Estas contraseñas no
pueden romperse con técnicas simples, como la búsqueda de partes de nombres en el diccionario
o palabras del diccionario en las contraseñas, de modo que un intruso está obligado a lanzar un
ataque minucioso que implique intentar toda cadena concebible como contraseña. El tiempo y el
esfuerzo implicados con este método lo hacen impráctico.
El cifrado es una técnica estándar para proteger la base de datos de autentificación. Un in-
truso tendrá que analizar el archivo de las contraseñas cifradas para romperlas. El intruso puede
usar uno de los ataques descritos en la sección 8.5.1. Un usuario registrado puede intentar un

09 MAQ. CAP. 08(F0694).indd 374 8/10/07 1:03:57 AM


8.7 Descriptores de acceso y matriz de control de acceso 375

ataque con texto plano seleccionado al cambiar su propia contraseña repetidamente y viendo su
forma cifrada. Un extraño tendría que efectuar un ataque minucioso intentando entrar al sistema
usando distintas contraseñas. Si el archivo de contraseñas cifradas no es visible para nadie más
que para la raíz, entonces cualquier intruso dentro o fuera del sistema estará obligado a efectuar
un ataque minucioso a través de intentos repetidos por entrar al sistema.
Unix y Linux llevan a cabo cifrado de contraseñas. El primero utiliza cifrado DES, y Linux
usa una técnica de mensajes resumidos, que es una función hash (función de búsqueda) de una
sola vía que genera un valor de búsqueda de 128 o 160 bits a partir de la contraseña. Esta técnica
tiene variantes denominadas MD2, MD4 y MD5. Linux utiliza MD5. Tanto Unix como Linux
proporcionan una opción de archivo de contraseñas de la sombra. Cuando se elige esta opción,
la forma de texto cifrado de las contraseñas se almacena en un archivo de la sombra que sólo es
accesible a la raíz. Como ya se mencionó, este arreglo obliga a que un intruso efectúe un ataque
minucioso.

8.7 DESCRIPTORES DE ACCESO Y MATRIZ


DE CONTROL DE ACCESO
A un usuario puede permitírsele el acceso a un conjunto de archivos y un archivo puede ser
accesible para un conjunto de usuarios. Una estructura de protección contiene información que
indica qué usuarios pueden acceder a qué archivos y de qué manera. Se trata del nombre clásico
para la base de datos de autorización que se analizó en la sección 8.1.
Un privilegio de acceso para un archivo es un derecho para hacer una forma de acceso
específica al archivo, por ejemplo, un acceso de lectura o de escritura. Un descriptor de ac-
ceso describe privilegios de acceso para un archivo. Se utiliza una notación evidente, como r, w
y x para representar privilegios de acceso para leer, escribir y ejecutar los datos o el programa en
un archivo. Un descriptor de acceso se representa como un conjunto; por ejemplo, el descriptor
{r, w} indica los privilegios para leer y escribir un archivo. La información de control de acceso
para un archivo es una colección de descriptores de acceso para privilegios de acceso que poseen
varios usuarios.
Una matriz de control de acceso (MCA) almacena información de protección que consta de
privilegios de acceso de los usuarios e información de control de acceso para los archivos. Un
renglón en la MCA describe los privilegios de acceso que detenta un usuario. Una columna des-
cribe la información de control de acceso para un archivo. Así, MCA(ui, fj) ⫽ aij implica que el
usuario ui puede acceder al archivo fj según los privilegios de acceso aij. En la figura 8.7 se mues-
tra una MCA. El usuario Jay tiene los privilegios de acceso {read, write} para beta pero sólo
el privilegio {read} para alpha. Cuando un proceso Pi intenta efectuar un acceso ak a un archivo
fj, el kernel obtiene la identificación del usuario que inició el proceso Pi. Sea ui este usuario. Lue-
go, el kernel utiliza ui y fj para obtener la entrada MCA(ui, fj). El acceso hecho por el proceso es
legal si ak se incluye en la lista de privilegios de acceso contenida en MCA(ui, fj).
Los descriptores de acceso pueden codificarse como bits para efectos de eficacia de la me-
moria y de acceso. Un bit en uno de estos descriptores de acceso indica la presencia o ausencia
de un derecho de acceso. En un SO que sólo utiliza tres derechos de acceso r, w y x, un descrip-
tor de acceso codificado como bits debe contener tres bits indicando la presencia o ausencia de
cada uno de los derechos de acceso. En una forma codificada como bits, el descriptor de acceso
para los privilegios de acceso {read, write} puede verse como la cadena 110…, donde los unos
indican que se han otorgado los privilegios de lectura y escritura, y los ceros indican que no se
ha otorgado un privilegio de ejecución.

09 MAQ. CAP. 08(F0694).indd 375 8/10/07 1:03:57 AM


376 CAPÍTULO 8 Seguridad y protección

Archivos →
alpha beta gamma
Usuarios Jay {r} {r,w}

Anita {r,w,x} {r}
Sheila {r}

Figura 8.7 Matriz de control de acceso, MCA.

Granularidad de la protección La granularidad de la protección significa el grado de


control sobre la protección de los archivos. En la tabla 8.8 se describen tres niveles de granu-
laridad. Una matriz de control de acceso posee granularidad de grano mediano y almacena pri-
vilegios de acceso para cada par (usuario, archivo). Así, los usuarios pueden poseer diferentes
privilegios de acceso para el mismo archivo. Existe granularidad de grano grueso si el propieta-
rio de un archivo es incapaz de especificar privilegios de acceso para cada usuario en el sistema.
Comúnmente esto ocurre cuando los usuarios se dividen en grupos de usuarios y los privilegios
de acceso se especifican para un grupo. La granularidad de grano fino existe si los privilegios de
acceso se especifican para procesos o fases de ejecución de procesos. De esta forma, diferentes
procesos creados por el mismo usuario pueden poseer diferentes privilegios de acceso para un
archivo, o el mismo proceso puede tener diferentes privilegios de acceso en instantes diferentes.
La granularidad de grano fino proporciona a los usuarios un poder de discriminación más impor-
tante que la protección de grano grueso o de grano mediano. En la sección 8.8.3 se analizará la
protección de grano fino.

Tabla 8.8 Granularidad de la protección

Grano grueso El propietario de un archivo especifica los privilegios de acceso para grupos de
usuarios. Cada usuario en un grupo posee los mismos privilegios de acceso al
archivo.
Grano mediano Los privilegios de acceso pueden especificarse individualmente para cada usuario
en el sistema.
Grano fino Los privilegios de acceso pueden especificarse para un proceso o para una fase de
ejecución de un proceso.

Desventajas de la matriz de control de acceso El uso de una MCA proporciona sencillez


y eficacia de acceso a la información de protección: los privilegios de acceso del usuario ui para
el archivo fi pueden obtenerse a partir de MCA(ui, f i ). Sin embargo, el tamaño de la MCA es
grande. Si un SO contiene nu usuarios y nf archivos, entonces el tamaño de la MCA es nu ⫻ nf .
Debido a que nu y nf pueden ser grandes, es necesario comprometer grandes áreas de la memoria
para dar cabida a la MCA, o a una parte de ésta, durante la operación del sistema. Un usuario co-
mún posee privilegios de acceso para pocos archivos, de modo que la mayor parte de las entradas
en la MCA contienen información nula. Así, la cantidad de información de control de acceso es
mucho menor que el tamaño de la MCA.
El tamaño de la información de control de acceso puede reducirse de dos formas: dismi-
nuyendo el número de renglones en la MCA o eliminando la información nula. El número de

09 MAQ. CAP. 08(F0694).indd 376 8/10/07 1:03:57 AM


8.8 Estructuras de protección 377

renglones se reduce asignando privilegios de acceso a grupos de usuarios, más que a usuarios
individuales. La MCA requiere contener sólo tantos renglones como el número de grupos de
usuarios; sin embargo, la reducción del número de renglones compromete la granularidad de la
protección.
El tamaño de la información de control de acceso puede reducirse eliminando la informa-
ción nula. Generalmente, la información se almacena en forma de listas, más que como una
matriz. Este método no afecta la granularidad de la protección, aunque reduce el tamaño de la
información de protección, ya que sólo es necesario que en la lista estén presentes las entradas
no nulas de una MCA. En la práctica se utilizan dos estructuras de listas:
1. Listas de control de acceso (ACL).
2. Listas de capacidad (listas C).
Una lista de control de acceso almacena la información nula de una columna de la MCA. Por
tanto, contiene información de control de acceso para un archivo en el sistema. Cuando un
usuario intenta utilizar un archivo, se busca la lista de control de acceso de ese archivo para
localizar un par que implique a ese usuario. Un acceso es inválido si en la lista no existe un par
que implique al usuario o si la forma de acceso intentada no es consistente con los privilegios
de acceso del usuario. Una lista de capacidad almacena la información nula de un renglón de
la MCA y describe los privilegios de acceso que detenta un usuario. La lista C de un usuario se
recorre cuando un usuario intenta acceder a un archivo.
Las listas de control de acceso se utilizan bastante para protección de archivos. Las listas
de capacidad pueden usarse para proteger archivos, así como los recursos, como programas u
objetos de datos en la memoria. Este uso de las listas C se analizará en la sección 8.9.

8.8 ESTRUCTURAS DE PROTECCIÓN

Una estructura de protección es un método para almacenar y utilizar información de control de


acceso. La naturaleza y el uso de la información determinan la granularidad de la protección. La
lista de control de acceso puede proporcionar protección de grano grueso o de grano mediano;
la lista de capacidad proporciona protección de grano mediano, mientras el dominio de la protec-
ción proporciona protección de grano fino.

8.8.1 Listas de control de acceso

La lista de control de acceso de un archivo indica cuáles usuarios pueden acceder a un archivo y
de qué manera. Suele almacenarse en la entrada del directorio del archivo. Siempre que un pro-
ceso quiere abrir un archivo, el SO encuentra la identificación del usuario que inició el proceso y
comprueba si los privilegios de acceso del usuario le permiten llevar a cabo el modo de acceso
intentado. Si no es éste el caso, el proceso es abortado. (En realidad, el sistema de archivos del
SO hace esta comprobación. Sin embargo, para facilitar las cosas, se supone que el SO lleva a
cabo todas las comprobaciones de protección.)
Cuando un usuario crea un archivo, registra la información de control de acceso al archivo
en el sistema. La lista de control de acceso para el archivo almacena esta información en la for-
ma de un conjunto de pares {(user_id, access_privileges), ..}. En la figura 8.8 se muestran listas
de control de acceso para tres archivos. La ACL para alpha es {(Jay, {read}, (Anita, {read,
write, execute})}, lo cual indica que el usuario Jay sólo puede leer el archivo alpha, mientras

09 MAQ. CAP. 08(F0694).indd 377 8/10/07 1:03:57 AM


378 CAPÍTULO 8 Seguridad y protección

Anita puede leer, escribir y ejecutar el archivo. A la usuaria Sheila no se le permite ningún tipo
de acceso a alpha, ya que la ACL de alpha no contiene una entrada para Sheila. En casi todos
los sistemas de archivos, el propietario obtiene ciertos privilegios de acceso en forma predeter-
minada. En Unix, éstos son controlados por la máscara del usuario.

Nombre Información de Información de


del archivo localización protección Banderas
alpha {(Jay, {r}),(Anita, {r,w,x})}
beta {(Jay, {r,w})}
gamma {(Anita, {r}),(Sheila, {r})}

Figura 8.8 Listas de control de acceso.

Los pasos implicados en el acceso al archivo gamma por la usuaria Sheila son como sigue:
1. La usuaria Sheila lleva a cabo su identificación en el sistema.
2. El sistema autentifica a Sheila al preguntarle su contraseña.
3. Un proceso iniciado por Sheila emite la llamada open(gamma, ‘write’) para modificar
el archivo gamma.
4. El SO localiza el par que implica a Sheila en la ACL del archivo gamma y comprueba si
contiene el privilegio de acceso ‘write’ para Sheila.
Observe que durante el acceso al archivo no es posible el enmascaramiento, ya que Sheila fue
autentificada por el sistema en el paso 2.
El uso de las listas de control de acceso enfrenta algunos problemas prácticos. La presencia
de un gran número de usuarios en un sistema conduce a grandes tamaños de las ACL y, por
tanto, a una gran sobrecarga de espacio en el sistema de archivos. La sobrecarga de tiempo
también es alta debido a que la ACL intenta validar el acceso a un archivo. Es posible conser-
var tanto la memoria como el tiempo de CPU a expensas de una protección de grano grueso al
especificar y almacenar información de protección para grupos de usuarios, en vez de hacerlo
para usuarios individuales. En la sección 8.10 se describirá cómo Unix almacena y busca una
ACL de manera eficaz.

8.8.2 Listas de capacidad (listas C)

Una capacidad representa privilegios de acceso de un usuario a un archivo. La información


concerniente a las capacidades con que cuenta un usuario se almacena en una lista de capacidad
(lista C). Por tanto, una lista C es un conjunto de pares {(file_id, access_privileges), ..}. En la
figura 8.9 se muestra la lista C {(alpha, {read, write, execute}), (gamma, {read})} para la usuaria
Anita. Ella puede leer, escribir o ejecutar el archivo alpha y leer el archivo gamma. Anita no
tiene acceso al archivo beta, ya que en la lista C no existe ninguna entrada para beta. Cuando
Anita desea acceder a algún archivo, el SO implementa el acceso sólo si la lista de capacidad
de Anita contiene el privilegio de acceso necesario para el archivo. Así, en el caso para las ACL,
no existen posibilidades de enmascaramiento porque un usuario es autentificado por el sistema
en el momento de identificarse y la identificación del usuario se utiliza para localizar la lista C

09 MAQ. CAP. 08(F0694).indd 378 8/10/07 1:03:58 AM


8.8 Estructuras de protección 379

correcta. El tamaño de las listas C suele ser pequeño. Esta característica limita la sobrecarga de
espacio y de tiempo al utilizar estas sobrecargas para controlar el acceso al archivo.

(alpha, {r, w, x})


(gamma, {r})

Figura 8.9 Lista de capacidad para la usuaria Anita.

8.8.3 Dominio de la protección

Como se mencionó en la sección 8.1, los sistemas operativos suelen manejar el aspecto de con-
fidencialidad de la protección y dejan el aspecto de la privacidad a los usuarios y sus procesos.
Resulta interesante ver por qué esto es así. El uso de una MCA, o sus variantes, como las ACL y
las listas C, confiere privilegios de acceso a los usuarios. Una peculiaridad de este arreglo es que
¡cada proceso creado por un usuario tiene los mismos privilegios de acceso! El arreglo sirve en el
asunto de confidencialidad en la protección porque sólo los usuarios autorizados pueden acceder
a un archivo; sin embargo, no aborda adecuadamente el de privacidad porque no distingue entre
diferentes procesos creados por un usuario.
Las violaciones del requerimiento de privacidad pueden presentarse como sigue: un privile-
gio de acceso se otorga a un usuario porque algún proceso iniciado por el usuario así lo requiere.
Sin embargo, cualquier proceso creado por el usuario puede usar el privilegio de acceso, de
modo que algunos procesos iniciados por el usuario pueden volver disponible la información
para una utilización no deseada o errónea. Un uso así viola el requerimiento de privacidad.
La posibilidad de una utilización no deseada de un archivo por los procesos da origen a una
cuestión fundamental que concierne a la confiabilidad, ya que la idoneidad de los datos depende
no sólo de la manipulación correcta de los procesos que se supone que acceden al archivo, ¡sino
también del carácter inofensivo de las acciones realizadas por los procesos que se supone que
no tienen acceso al archivo! En el ejemplo 8.2 se ilustra cómo es posible poner en peligro la
confidencialidad de la información.

Ejemplo 8.2 Un usuario ui tiene un privilegio de ejecución del programa invest cuyo propieta-
rio es otro usuario uj. Cuando ui ejecuta invest, éste se ejecuta como un proceso iniciado por el
usuario ui. Puede acceder a cualquier archivo del cual el usuario ui detenta un privilegio de acceso,
¡incluidos archivos que no tienen nada que ver con inversiones! Si uj así lo desea, puede hacer code
invest de modo que invest pueda acceder a archivos confidenciales de ui y copiarlos e incluso
modificarlos.

El concepto de dominio de la protección se ocupa de la privacidad. Un dominio de la


protección puede entenderse como un “entorno de ejecución” conceptual. Los privilegios de
acceso se otorgan a un dominio de la protección, más que a un usuario. Un proceso opera en un
dominio de la protección. De manera predeterminada, el dominio de la protección inicial de
un proceso no posee ningún privilegio de acceso. De esta forma, un proceso no puede acceder
a ningún recurso mientras se ejecute en su dominio, y ni siquiera a los recursos propiedad del
usuario que lo inició. Para acceder a un recurso específico, debe “ingresar” un dominio de la

09 MAQ. CAP. 08(F0694).indd 379 8/10/07 1:03:58 AM


380 CAPÍTULO 8 Seguridad y protección

protección que tenga privilegios de acceso para el recurso. El kernel cuenta con llamadas del
sistema por medio de las cuales un proceso puede solicitar su ingreso a un dominio de la protec-
ción. Es necesario definir un conjunto de condiciones de legalidad de tal solicitud. El kernel debe
aplicar las condiciones y satisfacer la solicitud de cambio de dominio de la protección o abortar
el proceso por haber hecho una solicitud ilegal.
El arreglo de protección que implica el uso de dominios de la protección facilita la imple-
mentación del principio de necesidad por conocer con una protección de grano fino. Sólo a los
procesos que requieren acceder a un recurso se les otorga el privilegio de hacerlo. En el ejemplo
8.3 se ilustra la forma en que este método proporciona privacidad de la información y en conse-
cuencia mejora la confiabilidad de los datos.

Archivos →
personal finance memos notes project
Dominios
D1 {r,w} {r,w}

D2 {r}
D3 {r,w} {r,w} {r}
Figura 8.10 Dominios de la protección.

Ejemplo 8.3 En la figura 8.10 se muestran tres dominios de la protección. El dominio D1 po-
see derechos de acceso de lectura y escritura para los archivos personal y finance, mientras
el dominio D2 posee sólo un derecho de lectura para finance. El dominio D3 posee los dere-
chos de acceso de lectura y escritura a los archivos memos y notes, y un derecho de lectura al
archivo project. Por tanto, los dominios D1 y D2 se traslapan, mientras el dominio D3 es ajeno
a los dominios D1 y D2. El usuario ui ejecuta tres cálculos denominados self, invest y job_re-
lated en los dominios D1, D2 y D3, respectivamente. Así, invest sólo puede acceder al archivo
finance, y sólo puede leerlo.
En un SO que no utiliza dominios de la protección, el usuario ui podrá necesitar derechos de
acceso de lectura y escritura para los archivos personal, finance, memos y notes, así como un
derecho de acceso al archivo project. Cuando el usuario ui ejecuta el programa invest que es
propiedad del usuario uj, ¡invest puede modificar muchos archivos accesibles a ui!

8.8.4 Cambio de dominio de la protección


Durante la ejecución de un proceso, a éste puede permitírsele cambiar su dominio de la protec-
ción. Este hecho puede utilizarse para hacer que ciertos recursos sean accesibles sólo durante
ciertas fases de ejecución de un proceso, mejorando así la privacidad de la información. A conti-
nuación se analizan dos ejemplos prácticos de cambio de dominio de la protección.
Unix Un proceso Unix posee dos estados distintos de funcionamiento: funcionamiento
del usuario y funcionamiento del kernel (consulte la sección 3.5.1). Mientras está en el esta-
do de funcionamiento, tiene acceso a su propio espacio de memoria, a archivos en el sistema de
archivos según la identificación del usuario que lo creó y a otros recursos ahí asignados. El
proceso efectúa una transición al estado de funcionamiento del kernel mediante una llamada del
sistema. En este estado, puede acceder a estructuras de datos del kernel y también al contenido
de toda la memoria. Regresa al estado de funcionamiento del usuario una vez que regresa de la
llamada del sistema. Luego, de nuevo sólo tiene los privilegios de acceso que ya tenía antes
de la llamada del sistema.

09 MAQ. CAP. 08(F0694).indd 380 8/10/07 1:03:58 AM


8.8 Estructuras de protección 381

La característica setuid (set user id) constituye otro método para cambiar dinámicamente
los dominios de la protección. Los privilegios de acceso de un proceso están determinados por
su uid (identificación del usuario). Cuando el kernel crea un proceso, establece uid del proceso
como la identificación del usuario que lo creó. La característica setuid constituye un método
para modificar temporalmente la uid de un proceso. setuid puede utilizarse como una llamada
del sistema por un proceso o usarse cuando un proceso lleva a cabo una orden exec para ejecutar
un programa. El proceso hace una llamada setuid del sistema con su propia identificación para
volver a su uid original.
Considere que un programa P está almacenado en un archivo denominado P. Si P va a ejecu-
tarse invocando la característica setuid, el bit setuid se establece en el ínodo del archivo P. Cuan-
do se ejecuta P, el kernel observa que el bit setuid del archivo denominado P se ha establecido y
cambia la uid del proceso a la uid del propietario de P, ejecutando temporalmente a P. Esta acción
coloca de manera efectiva al proceso en un dominio de la protección, cuyos privilegios de acceso
son idénticos a los de acceso del propietario de P. Utilizando esta característica, la situación que
se analizó en el ejemplo 8.2 puede evitarse como se indica a continuación: el usuario uj establece
el bit setuid del programa invest. El usuario ui proporciona a uj un acceso de lectura al archi-
vo finance antes de invocar invest. Luego, el programa invest puede acceder al archivo
finance de ui, pero a ningún otro archivo propiedad de ui.

MULTICS MULTICS proporciona 64 dominios de la protección organizados como anillos


concéntricos. Los anillos están numerados desde el más interior hasta el más exterior (consulte
la figura 8.11). Éstos proporcionan una jerarquía de los dominios de la protección, es decir, los
privilegios de acceso de un dominio incluyen privilegios de acceso de todos los dominios con
numeración superior. Además, puede poseer otros cuantos privilegios de acceso. Cada procedi-
miento de un programa se asigna a un dominio de la protección y sólo puede ser ejecutado por
un proceso que esté en el mismo dominio de la protección.

Compuertas Anillo 63

Anillo
0

Figura 8.11 Anillos de protección MULTICS.

La componente del código de un proceso puede consistir de procedimientos ubicados


en diferentes dominios de la protección. Surge una interrupción cuando un proceso que se está
ejecutando en el dominio de la protección Di invoca un procedimiento que está asignado al
dominio de la protección Dj, donde Dj ⫽ Di. Para ejecutar el procedimiento, el dominio de la
protección del proceso debe cambiarse a Dj. El kernel comprueba si esto es permisible por las
reglas para cambiar el dominio de la protección. Una vista simplificada de estas reglas es como

09 MAQ. CAP. 08(F0694).indd 381 8/10/07 1:03:58 AM


382 CAPÍTULO 8 Seguridad y protección

sigue: el cambio de dominio de la protección se permite si un proceso que se está ejecutando en


algún dominio Di invoca un procedimiento que existe en un dominio con numeración superior.
Sin embargo, para introducir un dominio de numeración inferior, un proceso debe invocar un
procedimiento designado especialmente llamado gate (compuerta). Un intento por invocar cual-
quier otro procedimiento en una capa con numeración inferior fracasa y el proceso es abortado.
Si una llamada satisface una de estas reglas, el dominio de la protección del proceso se cambia
temporalmente al dominio en que existe el procedimiento invocado. Éste se ejecuta en este do-
minio de la protección y accede a los recursos en concordancia con sus privilegios de acceso.
Al regreso, el dominio de la protección del proceso se restablece en su valor anterior, es decir,
en Di.
La estructura de protección MULTICS es complicada e incurre en sobrecarga de ejecución
sustancial debido a las comprobaciones realizadas en una llamada del procedimiento. Su natura-
leza jerárquica dicta que un privilegio de acceso perteneciente a un dominio de la protección in-
cluya privilegios de acceso de todos los dominios de la protección con numeración superior. Este
requerimiento no permite dominios de la protección cuyos privilegios de acceso sean ajenos. Por
ejemplo, los dominios D1, D2 y D3 de la figura 8.10 no pueden implementarse en MULTICS, ya
que el dominio D3 es ajeno a los dominios D1 y D2. Esta característica restringe la libertad de los
usuarios para especificar requerimientos de protección.

8.9 CAPACIDADES

El concepto de capacidad (Dennis, Van Horn, 1966) fue propuesto como un mecanismo general
para compartir la protección. Las capacidades en una lista C utilizadas para la protección de
archivos (consulte la sección 8.8.2) son una adaptación de este mecanismo general.

Definición 8.1 (Capacidad) Una capacidad es un símbolo que representa privilegios de ac-
ceso para un objeto.

Una capacidad contiene la identificación de un objeto y una lista de descriptores de acceso.


Un objeto es cualquier entidad del software o del hardware del sistema; por ejemplo, una im-
presora láser, un CPU, un archivo, un programa o una estructura de datos de un programa. Una
capacidad es propiedad de un programa. Proporciona al proceso el derecho de acceder al objeto
en una manera consistente con los privilegios de acceso.
Cuando algún proceso Pi crea un objeto Oi, el SO forma una capacidad para Oi que con-
tiene todo el conjunto de privilegios de acceso, y transmite esta capacidad a Pi. El proceso
Pi puede hacer copias de esta capacidad, o bien crear capacidades del subconjunto que con-
tienen menos privilegios de acceso, y pasan estas capacidades a otros procesos. Así, en el
sistema pueden existir muchas capacidades para Oi. El uso de éstas por los procesos conduce
a compartir Oi.
Cada proceso tiene capacidades para los objetos que posee y algunas capacidades que le
fueron pasadas por otros procesos. Todas las capacidades en una lista C se obtienen por medios
legales: ninguna puede ser robada o creada de manera fraudulenta por un proceso. Ésta es la ra-
zón por la cual una capacidad se describe a menudo como un símbolo no falsificable que confiere
privilegios de acceso a su propietario.

09 MAQ. CAP. 08(F0694).indd 382 8/10/07 1:03:59 AM


8.9 Capacidades 383

El formato de una capacidad se ilustra en la figura 8.12. La capacidad consta de dos campos:
identificación del objeto y privilegios de acceso. Cada objeto cuenta con una identificación de
objeto única en el sistema. El campo de los privilegios de acceso representa la presencia o au-
sencia de un privilegio de acceso específico.

Identificación Privilegios
del objeto de acceso

Figura 8.12 Formato de una capacidad.

La notación Capk(obji) se usa para hacer referencia a una capacidad de obji. El subíndice de
Cap se usa simplemente para distinguir entre capacidades diferentes de un objeto. No significa
ninguna otra cosa. Para facilitar las cosas, el subíndice se omite en contextos en que se implica
una sola capacidad de un objeto.

8.9.1 Sistemas de cómputo basados en capacidad


Un sistema de cómputo basado en capacidad es un sistema cuya arquitectura implementa direc-
cionamiento y protección para todos los objetos en el sistema. Los objetos incluyen objetos de
larga duración, como archivos, y objetos de corta duración, como estructuras de datos y copias
de programas en la memoria. Muchos sistemas basados en capacidad fueron elaborados para
investigación y experimentación. El Intel iapx-432 es un ejemplo de un procesador comercial
bastante conocido con arquitectura basada en capacidad.

p1 p2 p3

alpha {r}
alpha {r}
alpha {r,w}

C list1 C list2 C list3

Figura 8.13 Esquema de un sistema basado en capacidad.

En la figura 8.13 se muestra un esquema de un sistema basado en capacidad. Cada proceso


cuenta con una lista C que describe sus privilegios de acceso. Los procesos P2 y P3 contienen
capacidades idénticas de alpha que confieren el privilegio de lectura para alpha, mientras el
proceso P1 cuenta con una capacidad que confiere los privilegios de lectura y escritura para
alpha. Un sistema basado en capacidad difiere de un sistema de cómputo convencional en los
siguientes aspectos:
1. El sistema no asocia de manera explícita una “memoria” al proceso; asocia listas C a
procesos.
2. Las capacidades en una lista C pueden usarse para acceder a objetos existentes en cual-
quier parte del sistema (es decir, en la memoria o en un disco); la ubicación de un objeto
es irrelevante para un proceso.

09 MAQ. CAP. 08(F0694).indd 383 8/10/07 1:03:59 AM


384 CAPÍTULO 8 Seguridad y protección

3. A los objetos de larga duración, como los archivos, y a los objetos de corta duración,
como los datos y los programas, puede accederse de manera uniforme.
Estas diferencias se presentan a partir de la forma en que se accede a un objeto en un sistema
basado en capacidad.

p1 Identificación Dirección
del objeto del objeto
dcap(alpha)
alpha r, w alpha

C list1 alpha
Tabla de objetos
(OT)

Figura 8.14 Direccionamiento basado en capacidad.

Direccionamiento basado en capacidad En la figura 8.14 se muestra un esquema de di-


reccionamiento de objetos basado en capacidad. Cada objeto posee una identificación única. La
tabla de objetos (OT) es una tabla amplia del sistema que contiene información de localización
de todos los objetos en el sistema. El campo de dirección del objeto de la entrada de una OT
indica la dirección del objeto en la memoria primaria o secundaria de la computadora. El acceso
a un objeto se implementa como sigue: un proceso P1 lleva a cabo una operación <opi> sobre un
objeto utilizando una instrucción de la forma

< opi > dCap(obji) (8.1)

donde dCap(obji) es el desplazamiento de Cap(obji) en la lista C de P1. El sistema utiliza dCap(obji)


para localizar la capacidad en la lista C de P1. La identificación del objeto en la capacidad, a
saber alpha, se utiliza para ubicar la entrada de alpha en la OT. La dirección del objeto en la
entrada OT se usa para acceder a alpha para implementar <opi>. Para hacer más eficiente el ac-
ceso al objeto se utilizan técnicas semejantes a las memorias intermedias de dirección (consulte
la sección 6.2.3), a saber, registros de capacidad y memorias caché.
El direccionamiento basado en capacidad proporciona una flexibilidad crucial al SO. El SO
puede mover objetos en la memoria para una mejor administración de la memoria, o moverlos
entre la memoria y el disco para desempeño de acceso eficaz desde el punto de vista de costo,
sin afectar la manera en que un programa accede al objeto. Esta ventaja se denomina ventaja de
direccionamiento uniforme de las capacidades.

Operaciones con objetos y capacidades Un proceso Pk que posee Cap(obji) puede llevar
a cabo las operaciones enumeradas en la tabla 8.9 con obji y Cap(obji). Como ya se analizó,
las operaciones con obji están sujetas a los privilegios de acceso en la capacidad. En muchos
sistemas basados en capacidad, las operaciones en una capacidad también están sometidas a
los privilegios de acceso en la capacidad. Por ejemplo, un proceso puede ser capaz de crear una

09 MAQ. CAP. 08(F0694).indd 384 8/10/07 1:03:59 AM


8.9 Capacidades 385

capacidad subconjunto de Cap(obji) sólo si Cap(obji) contiene el privilegio de acceso “crear ca-
pacidad subconjunto”. Esta característica controla las operaciones que los procesos pueden efec-
tuar sobre las capacidades.

Tabla 8.9 Operaciones permisibles con los objetos y capacidades

Operaciones con los objetos


• Leer o modificar el objeto.
• Destruir el objeto.
• Copiar el objeto.
• Ejecutar el objeto.
Operaciones con las capacidades
• Hacer una copia de la capacidad.
• Crear una capacidad “subconjunto”.
• Utilizarla como parámetro en una llamada de
función/procedimiento.
• Pasar la capacidad para su uso por otro proceso.
• Borrar la capacidad.

8.9.2 Formas de compartir y proteger objetos


El acceso de un objeto en un sistema basado en capacidad procede como sigue:
1. Cuando el proceso Pi desea realizar una operación sobre un objeto Obji, ejecuta una ins-
trucción de la forma < opi > dCap(obji), donde < opi > es el código de la operación para la
operación deseada.
2. El CPU comprueba si la ejecución de < opi > es consistente con los privilegios de acceso
contenidos en Cap(obji). En caso afirmativo, realiza la operación; en caso contrario, ori-
gina una interrupción por violación a la protección.
3. El SO aborta el proceso si se presenta una interrupción por violación a la protección.
El CPU lleva a cabo las siguientes acciones adicionales si opi es la operación “crear
un nuevo objeto”: crea un nuevo objeto y crea una entrada para el objeto en la OT. Coloca
la identificación del objeto y la dirección del objeto de reciente creación en la entrada. Luego
crea una capacidad que contiene todo el conjunto de privilegios de acceso para el objeto y coloca
esta capacidad en la lista C. También coloca dCap(obji) en el registro de resultado de la operación
opi. El proceso Pi rescata este valor para su uso mientras se accede a opi en el futuro. Acciones
semejantes se llevan a cabo cuando un proceso hace una copia de un objeto.
Compartir objetos ocurre cuando un proceso pasa a otro proceso una capacidad para un ob-
jeto. El proceso receptor ingresa la capacidad en su propia lista C. Compartir está implícito en el
hecho de que ambas listas C contienen una capacidad para el objeto. La protección es implícita
en el hecho de que estas capacidades pueden conferir diferentes privilegios de acceso sobre el
proceso. El ejemplo 8.4 ilustra la manera de compartir y proteger objetos.

Ejemplo 8.4 Los siguientes eventos ocurren en un SO:


1. El proceso P1 crea un objeto obji. El SO inserta una capacidad Cap1(obji) en la lista C de
P1 y devuelve el desplazamiento de la capacidad a P1. Esta capacidad confiere el conjunto
de privilegios de acceso a su propietario, incluido el derecho de acceso “pasar”, lo cual
permite al proceso pasar la capacidad a otros procesos.

09 MAQ. CAP. 08(F0694).indd 385 8/10/07 1:04:00 AM


386 CAPÍTULO 8 Seguridad y protección

2. P1 crea una capacidad subconjunto de Cap1(obji) que sólo contiene el privilegio de lectura.
Sea Cap2(obji) esta llamada.
3. P1 pasa Cap2(obji) al proceso P2.
4. P2 acepta la capacidad. (Comúnmente, los pasos 2 y 3 se llevan a cabo usando un mecanis-
mo de regulación mutua de los intercambios.) La capacidad se ingresa en la lista C de P2
en el desplazamiento dCap2(obji).
5. Luego, P2 usa dCap2(obji) para llevar a cabo un acceso de lectura a obji.
En la figura 8.15 se ilustran las listas C resultantes de P1 y P2. Los procesos poseen diferentes
privilegios de acceso para obji.

p1 p2

obji {r, w, p}
obji {r}
obji {r}
C list1 C list2

obji

Tabla de objetos obji


(OT)

Figura 8.15 Compartir y proteger un objeto basado en capacidad.

Protección de capacidades La protección que utiliza capacidades se basa en la hipótesis


fundamental de que las capacidades no pueden falsificarse o manipularse. Esta hipótesis será
inválida si un proceso puede acceder a su lista C y modificar las capacidades ahí existentes. Por
ejemplo, el proceso P2 de la figura 8.15 podrá alterar el campo de privilegios de acceso de la
capacidad para obji y proporcionarse a sí mismo un privilegio de acceso de “escritura”. ¡Luego
podrá utilizar la capacidad modificada para alterar al objeto obji!
La manipulación y falsificación de las capacidades se evitan usando los dos métodos si-
guientes:

• Arquitecturas etiquetadas.
• Segmentos de capacidad.

Estos métodos son semejantes a los que se utilizan para proteger datos contra operaciones ilega-
les y para proteger programas contra modificación, respectivamente.

Arquitectura etiquetada La representación de tiempo de ejecución de un objeto consta de


dos campos: un campo etiqueta y un campo valor. El primero describe el tipo de objeto, mientras
el segundo contiene una representación del valor del objeto. El campo etiqueta sólo puede ser

09 MAQ. CAP. 08(F0694).indd 386 8/10/07 1:04:00 AM


8.9 Capacidades 387

modificado por una instrucción privilegiada, de modo que el programa de un usuario no pue-
de modificar el campo etiqueta de un objeto. Cuando una operación opi debe llevarse a cabo so-
bre un objeto objj, el CPU comprueba la compatibilidad de opi con la etiqueta de objj y realiza la
operación sólo si ambas son compatibles. Incluso el intento de ejecutar opi fracasa. Por ejemplo,
una operación de punto fijo falla si se aplica a un valor flotante.
Una capacidad se protege de la siguiente manera: una capacidad se considera como un ob-
jeto. Cuando se crea una capacidad, su campo etiqueta se establece en “cap” (consulte la figura
8.16). Este valor de etiqueta sólo es compatible con las operaciones sobre las capacidades defi-
nidas en la sección 8.9.1, por ejemplo, crear una copia de una capacidad o crear una capacidad
del subconjunto. Por tanto, un programa no puede manipular una capacidad, incluso si sabe
dónde está almacenada ella. Una capacidad no puede falsificarse porque un programa no puede
modificar el campo etiqueta de un objeto para hacerlo ver como una capacidad.

Etiqueta Valor
int −246
float
cap Cap (obji )

Figura 8.16 Protección de capacidad basada en etiqueta.

Segmentos de capacidad El direccionamiento basado en capacidad se ha utilizado en ar-


quitectura de computación para proteger programas contra modificación. En una arquitectura
que utiliza direccionamiento basado en capacidad, una dirección contiene una identificación de
segmento y una compensación dentro del segmento. Hay dos tipos de segmentos: los de datos y
los de programa. Para usar operandos situados en segmentos de datos se requieren instrucciones
de acceso y manipulación de datos, mientras para usar operandos situados en segmentos de pro-
grama se necesitan llamadas a instrucciones de ramificación y subrutinas. La violación de esta
disciplina conduce a una interrupción y a la cancelación del programa erróneo. Si una arquitectu-
ra utiliza un solo segmento de datos y un solo segmento de programa, no es necesario especificar
de manera explícita la identificación del segmento en el campo operando de una instrucción. El
CPU puede analizar el código de operación de la instrucción y decidir si su operando está situado
en el segmento de datos o en el de programa. Este arreglo evita la ejecución de una instrucción
store sobre un operando en un segmento de programa, con lo cual se impide la modifica-
ción accidental o maliciosa de los programas.
Este método se extiende para protección de capacidades mediante la introducción de un
tercer tipo de segmento: un segmento de capacidad. Las capacidades se insertan en un segmento
de capacidad mediante el kernel que utiliza información privilegiada. Ésta es la única instrucción
legal sobre las capacidades. El campo operando de una instrucción contiene dos campos: la iden-
tificación del segmento de capacidad y una compensación hacia este segmento. La capacidad
del objeto para tener acceso a éste se obtiene utilizando estos campos. Luego, la dirección de un
objeto se obtiene usando la OT como ya se describió. La protección de capacidades está implícita
en el hecho de que una operación store no puede llevarse a cabo en un segmento de capacidad.
Esta característica evita la manipulación y falsificación de capacidades.

09 MAQ. CAP. 08(F0694).indd 387 8/10/07 1:04:00 AM


388 CAPÍTULO 8 Seguridad y protección

8.9.3 Capacidades del software

El SO para una arquitectura basada no en capacidad puede implementar capacidades en el soft-


ware. El arreglo de objetos y capacidades puede ser semejante al que se muestra en la figura 8.15.
Sin embargo, la manipulación y la protección de objetos no pueden llevarse a cabo por el CPU
del sistema. Entonces se realiza mediante una componente del kernel denominada administrador
de objetos (OM).
Un programa indica sus requerimientos de manipulación de objetos al administrador de
objetos por medio de una llamada

OM (< opi >, Cap(obji))

Ésta tiene el mismo efecto que la instrucción (8.1). Antes de realizar <opi>, el administrador de
objetos comprueba que Cap(obji) contenga los privilegios de acceso necesarios.
Dos cuestiones importantes se presentan cuando las capacidades se implementan en el soft-
ware:

1. Un proceso puede ser capaz de desviar el arreglo de protección basada en capacidad


mientras accede a los objetos.
2. Un proceso puede ser capaz de manipular o fabricar capacidades.

¿Cómo puede evitarse que un proceso manipule objetos sin pasar por el administrador de obje-
tos? Una forma de lograr lo anterior es escondiendo los objetos de la vista de los procesos del
usuario, cifrando la tabla de objetos. Así, los procesos no conocerán la ubicación de los objetos,
por lo que tendrán que depender del administrador de objetos para llevar a cabo su manipulación.
La cuestión de evitar la manipulación de capacidades también puede abordarse utilizando cifra-
do. Como ejemplo, se describe una versión simplificada del esquema de protección de capacidad
que se usa en el sistema operativo “Amoeba”.

Identificación Privilegios
del objeto de acceso Número

Figura 8.17 Capacidad parecida a la del SO “Amoeba”.

Capacidades en el sistema operativo “Amoeba” En este sistema operativo, cuando se


crea un objeto obji se le asigna una llave de cifrado keyi. La llave de cifrado se almacena en la
entrada de la tabla de objetos de obji. El formato de una capacidad “Amoeba” se muestra en
la figura 8.17. El campo número contiene información que se usa para proteger la capacidad. Una
capacidad para obji se crea aplicando el siguiente procedimiento:

1. Los campos identificación del objeto y privilegios de acceso de la capacidad se estable-


cen apropiadamente.
2. La llave de cifrado keyi se obtiene a partir de la entrada de la tabla de objetos de obji. Las
cadenas privilegios de acceso y keyi se concatenan. Sea cat la cadena resultante de lo
anterior.

09 MAQ. CAP. 08(F0694).indd 388 8/10/07 1:04:00 AM


8.9 Capacidades 389

3. La cadena cat se cifra usando como llave a keyi. El resultado se coloca en el campo
número de la capacidad. Así, number ⫽ Ekeyi (access privileges, keyi), donde “.” denota
concatenación (consulte la sección 8.5 para detalles de cifrado).
Para manipular obji, un proceso debe presentar al administrador de objetos una capacidad
para obji. El administrador de objetos comprueba la validez de esta capacidad como sigue:

1. keyi se obtiene a partir de la entrada de la tabla de objetos de obji.


2. Se concatenan la cadena privilegios de acceso de la capacidad y la cadena keyi en la en-
trada de la tabla de objetos de obji. La cadena resultante se cifra utilizando como llave a
keyi.
3. El resultado del cifrado en el paso 2 se compara con el campo número en la capacidad.
La capacidad sólo es válida si ambos coinciden.

La comprobación en el paso 3 puede fallar si los campos identificación del objeto o pri-
vilegios de acceso de una capacidad han sido manipulados. El administrador de objetos debe
cancelar el proceso si ocurre esto.

Comparación con sistemas basados en capacidad La mayor fortaleza de las capacidades


del software, a saber, independencia del hardware subyacente, también es su mayor debilidad.
Muchas acciones realizadas por el hardware de un sistema basado en capacidad, por ejemplo,
la creación de capacidades del subconjunto, no requieren ser ejecutadas en el software. Cada
una de éstas implica una llamada del sistema para invocar al administrador de objetos. Además,
la prevención de manipulación requiere la validación de una capacidad antes de usarla. Estos
requerimientos conducen a una sobrecarga de tiempo sustancial.

8.9.4 Áreas problemáticas en el uso de capacidades

Además del alto costo de implementación de capacidades en el hardware o en el software, el


uso de las capacidades enfrenta algunas otras dificultades prácticas. Tres fundamentales son las
siguientes:

• Necesidad de recolección de basura: ¿Cuándo es posible destruir un objeto?


• Confinamiento de capacidades: ¿Cómo asegurar que los procesos no pasen capacidades
a otros procesos de manera indiscriminada?
• Revocación de capacidades: ¿Cómo cancelar una capacidad o retirar los privilegios de
acceso concedidos por las capacidades?

Recolección de basura El propietario de un objeto puede preparar capacidades del subcon-


junto para un objeto y pasarlas a otros procesos, de modo que puedan acceder al objeto. Antes
de destruir un objeto, el propietario debe saber que cada proceso al que se permitió el acceso al
objeto ha terminado su uso. Esta información puede adquirirse sólo a través de la sincroniza-
ción del propietario con todos los usuarios de un objeto. Este método es impráctico cuando se
están creando y usando objetos a gran ritmo o cuando se comparten objetos cuya duración es
larga. Pueden presentarse dos problemas si se destruyen objetos sin contar con esta información.

09 MAQ. CAP. 08(F0694).indd 389 8/10/07 1:04:01 AM


390 CAPÍTULO 8 Seguridad y protección

Pueden existir apuntadores pendientes, es decir, puede destruirse un objeto aunque sigan exis-
tiendo algunas capacidades para éste, o bien, un objeto puede existir mucho después de que
se han destruido sus capacidades. Impedir estas dos situaciones requiere el uso de técnicas de
recolección de basura costosas.

Confinamiento de capacidades. El confinamiento implica la restricción del uso de una


capacidad a un conjunto de procesos dado. El problema del confinamiento se presenta si un
proceso pasa de manera innecesaria una capacidad a otros procesos. Tales acciones provocan
una proliferación de capacidades, que complica la recolección de basura y prolonga la existencia
de un objeto. La proliferación también puede socavar la protección al violar el principio de la
necesidad por conocer. El confinamiento puede lograrse haciendo del traspaso de capacidades en
sí un derecho de acceso. Si el proceso Pi apaga el derecho de acceso de “pase” mientras pasa una
capacidad a Pj, entonces Pj no es capaz de pasar la capacidad a ningún otro proceso.

Revocación de capacidades La revocación de todas las capacidades de un objeto es el


problema más difícil en un sistema basado en capacidades porque no hay forma de saber
qué procesos tienen capacidades para el objeto. Las dificultades en la revocación también im-
plican que los privilegios de acceso no pueden otorgarse a un proceso por un intervalo de tiempo
limitado. De manera interesante, la revocación es posible en el caso de capacidades del software
que están protegidas por medio de cifrado. En el sistema operativo “Amoeba”, el cambio de la
llave otorgada a un objeto invalidaría de forma automática todas las capacidades existentes del
objeto. Para revocación selectiva, el propietario puede invalidar todas las capacidades y luego
emitir otras nuevas que estén cifradas, usando la nueva llave del objeto para ciertos procesos.
Sin embargo, esta operación es costosa y molesta: cada proceso que tenga una capacidad para el
objeto se ve afectado cuando se revoca cualquier capacidad del objeto.

8.10 SEGURIDAD UNIX

Como se mencionó en la sección 8.6.1, Unix utiliza cifrado para la seguridad de la contra-
seña. Como una opción, usa un archivo de contraseñas de la sombra que sólo es accesible a la
raíz, lo cual obliga a que un intruso lleve a cabo un ataque minucioso para romper las contrase-
ñas. Cada usuario de Unix posee una identificación distinta en el sistema. El administrador del
sistema crea grupos de usuarios que no se traslapan y a cada uno le asigna una identificación úni-
ca. La credencial de un usuario está integrada por su identificación de usuario y la identificación
del grupo. Se almacena en la tabla de contraseñas y se convierte en el símbolo de autentifica-
ción del usuario después de que se autentifica al usuario.
Unix define tres clases de usuarios: el propietario del archivo, el grupo del usuario y otros
usuarios, y proporciona sólo tres derechos de acceso: r, w y x (que representan read, write y
execute, respectivamente). Así, la ACL necesita registrar sólo la presencia de tres derechos de
acceso para cada una de las clases de usuarios. Se utiliza un descriptor de acceso codificado
con bits. Se almacena en un campo en la entrada del directorio de un archivo. La identidad del
propietario del archivo se almacena en otro campo en la entrada del directorio de un archivo.
En la figura 8.18 se muestran las ACL según se reportan en un listado del directorio. El archi-
vo sigma puede leerlo cualquier usuario del sistema, aunque el único que puede escribir en él es
su propietario. delta es un archivo de sólo lectura para todas las clases de usuarios, mientras pi
posee los privilegios de lectura, escritura y ejecución sólo para su propietario.

09 MAQ. CAP. 08(F0694).indd 390 8/10/07 1:04:01 AM


8.11 Seguridad Linux 391

rw-r--r-- sigma
r--r--r-- delta
rwx------ pi
Propie- Grupo Otros
tario del del usuarios
archivo usuario

Figura 8.18 Lista de control de acceso Unix.

Los privilegios de acceso de un proceso Unix están determinados por su uid. Cuando el
kernel crea un proceso, establece la uid del proceso en la identidad del usuario que creó el pro-
ceso. Un proceso tiene dos estados de funcionamiento distintos: funcionamiento del usuario y
funcionamiento del kernel (consulte la sección 3.5.1). Mientras está en el funcionamiento del
usuario, un proceso tiene acceso al espacio de la memoria y a otros recursos ahí asignados, así
como a archivos en el sistema de archivos según su uid. El proceso realiza una transición al
estado de funcionamiento del kernel mediante una llamada del sistema. En este estado, puede
acceder a estructuras de datos del kernel y también a todo el contenido de la memoria. Regresa al
estado de funcionamiento del usuario cuando vuelve de la llamada del sistema. Luego, de nuevo
sólo tiene acceso a aquellos privilegios de acceso que tenía antes de la llamada del sistema. Así,
en el dominio de la protección ocurre un cambio implícitamente cuando un proceso hace una
llamada del sistema y cuando regresa una llamada del sistema.
La característica setuid constituye un método para cambiar temporalmente la uid de un pro-
ceso. Puede usarse de dos formas: un proceso puede hacer una llamada del sistema < id > para
cambiar su uid a < id > , y otra llamada setuid del sistema con su propia identificación para volver
a su uid original. Alternativamente, es posible cambiar de manera implícita la uid cuando un pro-
ceso lleva a cabo una exec a fin de ejecutar un programa. Esta utilización se realiza como sigue:
sea P un programa almacenado en un archivo denominado P. Si P va a ejecutarse invocando la
característica setuid, entonces se establece el bit setuid en el ínodo del archivo P. Una vez que se
ejecuta P, el kernel observa que se ha establecido el bit setuid del archivo P y cambia temporal-
mente la uid del proceso que está ejecutando a P a la uid del propietario de P. Esta acción coloca
de manera efectiva al proceso en un dominio de la protección cuyos privilegios de acceso son
idénticos a los privilegios de acceso del propietario de P. Utilizando esta característica, la situa-
ción analizada en la sección 8.2 puede evitarse como sigue: el usuario uj establece el bit setuid
del programa invest. El usuario ui proporciona a uj un acceso de lectura al archivo finan-
ce antes de invocar a invest. Luego, el programa invest es ejecutado con la uid de uj. Así,
invest puede acceder al archivo finance del usuario ui, pero a ningún otro archivo propie-
dad de ui. La característica setgid proporciona de manera semejante un método para cambiar
temporalmente la identificación de grupo de un proceso.

8.11 SEGURIDAD LINUX

Linux autentifica a un usuario en el momento de entrar al sistema al agregar un valor “salt” a


su contraseña y al cifrar el resultado a través de MD5. Como una opción, utiliza un archivo de
contraseñas de la sombra que sólo es accesible a la raíz. Adicionalmente, Linux proporciona
módulos enchufables de la autentificación (PAM) a través de los cuales una aplicación puede
autentificar a un usuario en cualquier momento a través de una biblioteca dinámicamente carga-

09 MAQ. CAP. 08(F0694).indd 391 8/10/07 1:04:01 AM


392 CAPÍTULO 8 Seguridad y protección

ble de módulos de autentificación. Este arreglo proporciona flexibilidad porque el esquema de


autentificación usado en una aplicación puede cambiarse sin tener que recopilar la aplicación.
Los expertos en desarrollo de aplicaciones pueden utilizar los PAM para mejorar la seguridad
de la aplicación de varias maneras: emplear un esquema de cifrado de contraseñas a su elección;
establecer límites de recursos a usuarios, de modo que no puedan lanzar ataques por negación
del servicio, y permitir que usuarios específicos entren al sistema sólo en momentos específicos
desde sitios específicos.
El administrador del servicio mantiene un archivo de configuración PAM para cada apli-
cación que esté autorizada a emplear PAM. Cada archivo de configuración PAM especifica la
manera en que deben llevarse a cabo la autentificación y qué acciones, como el montaje de
directorios raíz o la identificación del evento de la autentificación, deben emprenderse una vez
que se ha autentificado. El archivo de configuración también denomina el mecanismo que debe
utilizarse siempre que un usuario desea cambiar su contraseña. PAM permite que varios módulos
de autentificación sean “apilados”; estos módulos son invocados uno después de otro. Una apli-
cación puede usar esta facilidad para autentificar a un usuario a través de varios medios, como
contraseñas e identificación biométrica, a fin de mejorar la seguridad.
Linux proporciona protección de acceso a archivos con base en la identificación del usuario
y de la identificación de grupo de un proceso. Cuando un servidor, como el sistema de archivos
de red (NFS), accede a un archivo en representación de un usuario, la protección de archi-
vos debe realizarse usando la identificación del usuario y la identificación del grupo del usuario,
en vez de las identificaciones del servidor. Para facilitar esto, Linux proporciona las llamadas
del sistema fsuid y fsgid mediante las cuales un servidor puede asumir temporalmente la
identidad de su cliente.
El kernel Linux admite módulos de kernel cargables. Esta característica se ha utilizado
para proporcionar controles de acceso mejorados a través de módulos de kernel cargables,
denominados módulos de seguridad Linux (LSM). El uso de los LSM permite que muchos
modelos de seguridad distintos sean admitidos. El esquema básico LSM es simple: el kernel
invoca una función de validación de acceso antes de acceder a un objeto. Un LSM proporciona
esta función, que puede permitir o negar el acceso en cuestión. El Security Enhanced Linux
(SELinux) de la Agencia de Seguridad de Estados Unidos (US National Security Agency) ha
construido mecanismos de control de acceso a través de LSM que proporcionan control de
acceso obligatorio.
El kernel Linux proporciona el parche de protección de ejecución que permite protección
contra la explotación de sobrecarga del almacenamiento temporal y la sobreescritura de estruc-
turas de datos para lanzar ataques a la seguridad.

8.12 SEGURIDAD WINDOWS

El modelo de seguridad de Windows cuenta con varios elementos de sistemas de clase C2 y B2,
según los Trusted Computer System Evaluation Criteria (TCSEC) del Departamento de Defensa
de Estados Unidos. Proporciona control de acceso discrecional, protección de reúso del objeto,
auditorías de eventos relacionados con seguridad, un monitor de referencia de seguridad (SRM)
que refuerza el control de acceso y una trayectoria confiada para autentificación que derrotaría
ataques de caballos de Troya por enmascaramiento. Entre otras características notables, propor-
ciona seguridad para la arquitectura cliente-servidor a través de símbolos de acceso, que son
semejantes a las capacidades (sección 8.9).

09 MAQ. CAP. 08(F0694).indd 392 8/10/07 1:04:01 AM


8.12 Seguridad Windows 393

La seguridad Windows se basa en el uso de identificadores de la seguridad (SID, security


identifiers); un identificador de la seguridad se asigna a un usuario, a una computadora o a un
dominio, que está integrado por varias computadoras. Los campos importantes en un SID son
una autoridad de identificador con valor de 48 bits, que identifica la computadora o dominio
que emitió el SID, y unos cuantos valores de subautoridad o identificador relativo (RID) de 32
bits, que principalmente se usan para generar SID únicos para entidades creadas por la misma
computadora o dominio.
Cada proceso e hilo poseen un símbolo de acceso que identifica su contexto de seguridad.
(Como en otras partes del texto, el término proceso se utiliza de manera genérica para indicar
tanto un programa como un hilo.) Un símbolo de acceso se genera cuando un usuario se identifi-
ca, y se asocia con el proceso inicial creado por el usuario. Un proceso puede crear más símbolos
de acceso mediante la función LogonUser. Un símbolo de acceso contiene una cuenta SID del
usuario y una cuenta SID de grupo. Estos campos son utilizados por el monitor de referencia
de seguridad para decidir si el proceso que detenta el símbolo de acceso puede efectuar ciertas
operaciones sobre un objeto. Un símbolo de acceso también contiene un arreglo de privilegios
que indica cualesquiera privilegios especiales que detenta el proceso, como un privilegio para
crear respaldos de archivos, suplantación de un cliente y para apagar una computadora. También
puede contener unos cuantos superprivilegios para cargar y descargar unidades de disco, apro-
piarse de objetos y crear nuevos símbolos de acceso.
Un objeto como un archivo tiene asociado un descriptor de la seguridad. Este descriptor
contiene la identificación del propietario del objeto, una lista de control de acceso discrecional
(DACL) y una lista de control de acceso al sistema (SACL). Tanto la DACL como la SACL son
listas de entradas de control de acceso (ACE). Cada ACE contiene un SID de un usuario. Una
ACE en una DACL permite o no un acceso al objeto por un usuario con un SID coincidente.
Este arreglo permite protección de grano mediano y aún así ayuda a hacer compacta la DACL;
sin embargo, es necesario procesar toda la DACL para determinar si a un usuario se le permite
el acceso al objeto de una manera específica. Un objeto que puede contener otros objetos, como
un directorio o una carpeta, se denomina objeto contenedor; los objetos contenidos en un objeto
contenedor se denominan objetos hijos. Una ACE en la DACL de un objeto contenedor con-
tiene banderas para indicar cómo la ACE va a aplicarse a un objeto hijo: idénticamente, en ab-
soluto o de alguna otra manera. Una opción importante es que la ACE puede ser heredada por
un objeto hijo que en sí mismo sea un objeto contenedor, aunque ya no puede ser heredada
por objetos que pueden ser creados dentro del objeto hijo. Esta característica ayuda a limitar la
propagación de privilegios de control de acceso.
La SACL se utiliza para generar un registro de la intervención. La ACE en la SACL indica
qué operaciones sobre el objeto por cuáles usuarios o grupos de usuarios deben intervenirse.
En el registro de la intervención se hace una entrada cuando se lleva a cabo cualquiera de estas
operaciones.
La característica de suplantación en el modelo de seguridad de Windows proporciona segu-
ridad en la arquitectura cliente-servidor. Cuando un servidor lleva a cabo algunas operaciones
sobre objetos en representación de un cliente, estas operaciones deben estar sometidas a los pri-
vilegios de acceso del cliente, en vez de a los privilegios de acceso del servidor; en caso contra-
rio, el cliente podrá efectuar operaciones sobre estos objetos que exceden sus propios privilegios
de acceso. De manera semejante, la información del registro de seguridad que se genera cuando
un servidor accede a un objeto en representación de un cliente debe contener la identidad del
cliente, más que la del servidor. Estos dos requerimientos se cumplen dejando que el servidor
asuma temporalmente la identidad del cliente a través de la suplantación.

09 MAQ. CAP. 08(F0694).indd 393 8/10/07 1:04:01 AM


394 CAPÍTULO 8 Seguridad y protección

Para la suplantación se utiliza el arreglo siguiente: cuando un cliente invoca a un servidor,


indica el tipo de suplantación que desea que haga el servidor: el servidor no puede llevar a cabo
la suplantación sin el consentimiento del cliente. Si se permite realizar la suplantación, desde el
símbolo del cliente se crea un símbolo de suplantación que se proporciona al servidor. El servi-
dor presenta el símbolo de suplantación, más que su propio símbolo de acceso, mientras lleva a
cabo operaciones sobre objetos. De manera efectiva, el símbolo de acceso y el de suplantación
actúan como las capacidades analizadas en la sección 8.9. Además, a fin de asegurar seguridad,
el servidor puede crear un símbolo restringido a partir de uno de suplantación. Un símbolo así
debe contener un subconjunto de los privilegios contenidos en el símbolo de suplantación: es
como una capacidad del subconjunto analizada en la sección 8.9.

EJERCICIO 8
1. Enumere los ataques a la seguridad que no es posible evitar por cifrado.
2. Analice si el cifrado puede asegurar confidencialidad, privacidad e integridad de los datos.
3. Escriba una regla de seguridad que elimine el defecto de seguridad del ejemplo 8.1.
4. Explique por qué un SO hace la comprobación Ek(contraseña) = cadena almacenada en la tabla de
contraseñas, donde E es una función de cifrado, en vez de la comprobación contraseña = Dk(cadena
almacenada en la tabla de contraseñas), donde D es una función de descifrado.
5. Describa por qué la autentificación es importante para la protección de archivos.
6. Describa las ventajas y las desventajas de llevar a cabo comprobaciones de protección de archivos en
a) el momento de apertura del archivo.
b) cada operación de lectura o escritura.
7. Comente la eficacia del siguiente esquema de protección de archivos: un archivo se cifra utilizando
una función de cifrado E y una llave k. El sistema de archivos no realiza ninguna otra comprobación de
protección. Si el usuario desea compartir el archivo con otro usuario, pone E y k a disposición del otro
usuario.
8. Algunos sistemas operativos antiguos asociaban contraseñas con archivos y permitían que cualquier
programa que presentase una contraseña válida pudiera acceder a los archivos. Compare este esquema
con el basado en el uso de capacidades.
9. La revisión de capacidad es el proceso mediante el cual un SO encuentra a todos los procesos que po-
seen una capacidad para un objeto específico obji. Describa cómo puede llevarse a cabo una operación
de revisión en un sistema que utiliza capacidades de hardware o de software.
10. Un SO realiza la validación de las capacidades del software como sigue: cuando se crea una nueva ca-
pacidad, el administrador de objetos almacena una copia de la capacidad para su propio uso. Cuando un
proceso desea llevar a cabo una operación, la capacidad que presenta se compara con las capacidades
almacenadas. La operación se permite sólo si existe una capacidad equiparable en el administrador de
objetos.
Este esquema, ¿es infalible? Utilizando este esquema, ¿es posible llevar a cabo revocación selec-
tiva de privilegios de acceso?
11. Explique cómo pueden usarse los registros de capacidad en el esquema de la figura 8.14 para hacer más
eficaz el acceso a los objetos.

09 MAQ. CAP. 08(F0694).indd 394 8/10/07 1:04:02 AM


Bibliografía 395

12. Nodos distintos de un sistema distribuido pueden crear simultáneamente nuevos objetos. Describa un
esquema que pueda asegurar unicidad de las identificaciones de los objetos en un SO.
13. Estudie y describa las provisiones en Unix para a) encontrar la identificación del usuario que posee un
archivo, b) decidir si un usuario pertenece al mismo grupo de usuarios que el propietario del archivo.

BIBLIOGRAFÍA
Ludwig (1998) describe diversas clases de virus, mientras Ludwig (2002) analiza virus que se propagan
por correo electrónico. Sppaford (1989) analiza el gusano Morris por Internet que causó estragos en 1988
y Berghel (2001) describe el gusano Code Red de 2001.
Landwher (1981) analiza modelos formales de seguridad para computadoras. Voydock y Kent (1983)
estudian cuestiones de seguridad en sistemas distribuidos y técnicas prácticas utilizadas para abordarlas.
Shannon (1949) es la obra clásica en seguridad para computadoras. Analiza las propiedades de difu-
sión y confusión de las cifras. Denning y Denning (1979) y Lempel (1979) contienen buenos panoramas
generales de seguridad de datos y criptología, respectivamente. Schneier (1996), y Ferguson y Schneier
(2003) prepararon textos sobre criptografía, mientras Pfleeger y Pfleeger (2003) hicieron un texto sobre
seguridad para computadoras. Stallings (2003) analiza la criptografía y seguridad en redes.
Naor y Yung (1989) analizan funciones de búsqueda unidireccionales. Rivest (1991) describe la fun-
ción de compendio de mensajes MD4. El objetivo de la función MD4 es hacer computacionalmente in-
factible la producción de dos mensajes con un compendio de mensajes idéntico, o la de un mensaje con
un compendio de mensajes dado. La función MD4 es extremadamente rápida y resiste exitosamente el
criptoanálisis. Rivest (1994) describe la función MD5, que es más conservadora y un poco más lenta que la
anterior. Preneel (1998) describe primitivas criptográficas para autentificación de información.
La protección basada en la matriz de acceso se analiza en Lampson (1971) y en Popek (1974). Orga-
nick (1972) analiza los anillos de protección MULTICS. La característica setuid de Unix se describe en la
mayor parte de los libros que tratan sobre Unix.
Denis y Van Horn (1966) escribieron un artículo de referencia bastante conocido sobre el concepto
de capacidades. Levy (1984) describe varios sistemas basados en capacidades. Mullender y Tanenbaum
(1986) y Tanenbaum (2001) describen las capacidades del software de “Amoeba”. Anderson et al. (1986)
analizan las capacidades del software con una provisión para la contención.
Los Trusted Computer System Evaluation Criteria (TCSEC) del Departamento de Defensa de Estados
Unidos ofrecen una clasificación de las características de seguridad de sistemas de cómputo. Éstas se des-
criben en DoD (1985).
Spafford et al. (2003) analizan la seguridad en Solaris, sistemas operativos Mac, Linux y sistemas
operativos FreeBSD. Wright et al. (2002) analizan los módulos de seguridad Linux. Russinovich y Solo-
mon (2005) analizan características de seguridad en Windows.

1. Anderson, M., R.D. Pose y C.S. Wallace (1986): “A password-capability system”, The Computer
Journal, 29 (1), 1-8.
2. Berghel, H. (2001): “The Code Red worm”, Communications of the ACM, 44 (12), 15-19.
3. Denning, D.E. y P.J. Denning (1979): “Data security,” Computing Surveys, 11 (4).
4. Dennis, J.B. y E.C. Van Horn (1966): “Programming semantics for multiprogrammed compu-
tations”, Communications of the ACM, 9 (3).
5. DoD (1985): Trusted Computer System Evaluation Criteria, US Department of Defense.
6. Ferguson, N. y B. Schneier (2003): Practical Cryptography, John Wiley & Sons.

09 MAQ. CAP. 08(F0694).indd 395 8/10/07 1:04:02 AM


396 CAPÍTULO 8 Seguridad y protección

7. Fluhrer, S., I. Mantin y A. Shamir (2001): “Weaknesses in the key scheduling algorithm of RC4”,
Proceedings of Eighth Annual Workshop on Selected Areas in Cryptography.
8. Lampson, B.W. (1971): “Protection”, Operating Systems Review, 8 (1), 18-24.
9. Landwehr, C.E. (1981): “Formal models for computer security”, Computing Surveys, 13 (3),
247-278.
10. Lempel, A. (1979): “Cryptology in transition”, Computing Surveys, 11 (4), 286-303.
11. Levy, H.M. (1984): Capability Based Computer Systems, Digital Press, Mass.
12. Ludwig, M.A. (1998): The giant black book of computer viruses, 2a. ed., American Eagle, Show
Low.
13. Ludwig, M.A. (2002): The Little Black Book of Email Viruses, American Eagle, Show Low.
14. Menezes, A., P. van Oorschot y S. Vanstone (1996): Handbook of Applied Cryptography, CRC
Press.
15. Mullender, S.P. y A. Tanenbaum (1986): “The design of a capability based distributed operating
system”, Computer Journal, 29 (4).
16. Nachenberg, C. (1997): “Computer virus-anti virus coevolution”, Communications of the ACM,
40, 46-51.
17. Naor, M. y M. Yung (1989): “Universal one-way hash functions and their cryptographic appli-
cations”, Proceedings of the Twenty First Annual ACM Symposium on Theory of Computing,
33-43.
18. Organick, E.I. (1972): The MULTICS System, MIT Press, Mass.
19. Oppliger, R. (1997): “Internet security: firewalls and beyond”, Communications of the ACM,
40 (5), 92-102.
20. Pfleeger, C.P. y S. Pfleeger (2003): Security in computing, Prentice Hall, N.J.
21. Popek, G.J. (1974): “ Protection structures”, Computer, 7 (6), 22-33.
22. Preneel, B. (1998): Cryptographic primitives for Information Authentication—State of the art in
applied cryptography, LNCS 1528, Springer Verlag, 1998.
23. Rivest, R. (1991): “The MD4 message digest algorithm”, Proceedings of Advances in Cryptolo-
gy—Crypto’90, Lecture Notes in Computer Science, vol. 537, Spinger-Verlag, 303-311.
24. Rivest, R. (1992): “TheMD5 Message digest algorithm”, Request for comments, RFC 1321.
25. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.
26. Schneier, B. (1996): Applied cryptography, 2a. ed., John Wiley.
27. Shannon, C.E. (1949): “Communication Theory of Secrecy Systems”, Bell Systems Journal, oc-
tubre 1949.
28. Spafford, E.H. (1989): “The internet worm: crisis and aftermath”, Communications of the ACM,
32 (6), 678-687.
29. Spafford, G., S. Garfinkel y A. Schwartz (2003): Practical UNIX and Internet Security, 3a. ed.,
Oreilly, Sebastopol.
30. Stallings, W. (2003): Cryptography and Network Security: Principles and Practice, 3a. ed., Pren-
tice Hall, N.J.
31. Stiegler, H.G. (1979): “A structure for access control lists”, Software—Practice and Experience,
9 (10), 813-819.
32. Tanenbaum, A.S. (2001): Modern Operating Systems, 2a. ed., Prentice-Hall, Englewood Cliffs.

09 MAQ. CAP. 08(F0694).indd 396 8/10/07 1:04:02 AM


Bibliografía 397

33. Voydock, V.L. y S.T. Kent (1983): “Security mechanisms in high level network protocols”,
Computing Surveys, 15 (2), 135-171.
34. Wofsey, M.M. (1983): Advances in Computer Security Management, John Wiley, Nueva York.
35. Wright, C., C. Cowan, S. Smalley, J. Morris y G. Kroah-hartman (2002): “Linux Security modu-
les: General security support for the Linux kernel”, Eleventh USENIX Security Symposium.

09 MAQ. CAP. 08(F0694).indd 397 8/10/07 1:04:02 AM


09 MAQ. CAP. 08(F0694).indd 398 8/10/07 1:04:02 AM
Parte II
Tópicos avanzados
En la parte I se analizaron conceptos fundamentales en un sistema operativo: cómo los siste-
mas operativos permiten que un programador elabore procesos en una aplicación, la manera en
que operan y son programados los procesos para su uso en el CPU, cómo se asignan a la me-
moria y cómo pueden llevar a cabo procesamiento de archivos. En la parte II se profundiza
en el tema de la implementación de diferentes actividades dentro de un proceso en un sistema
operativo; se consideran tanto actividades dentro de un proceso y actividades dentro del sis-
tema operativo en sí.
Los procesos dentro de una aplicación interactúan entre ellos a fin de realizar sus tareas de
manera armoniosa: interactúan para compartir datos y coordinar sus actividades, así como para
intercambiar información. La sincronización de procesos es el acto de implementar interaccio-
nes de procesos haciendo que éstos esperen las acciones de otros procesos. Un bloqueo mutuo
es una situación en la que algunos procesos esperan de manera indefinida a algún otro proceso
debido a una sincronización defectuosa. Un bloqueo mutuo afecta el desempeño de una aplica-
ción y del sistema operativo, de modo que un programador debe asegurar su ausencia en esta
aplicación y un sistema operativo debe asegurar ausencia de bloqueos mutuos durante acciones
como la asignación de recursos.
Los usuarios de computadoras y los administradores de sistemas tienen diferentes expectati-
vas de un sistema de archivos. Además de la conveniencia y de las características de protección
y confiabilidad analizadas en la parte I, un usuario de computadora espera que un sistema de
archivos implemente operaciones en los archivos de manera eficiente, y un administrador
de sistemas espera que asegure un uso suficiente de dispositivos de E/S. El sistema de archivos
utiliza un módulo denominado Sistema de control de entrada salida (IOCS) para lograr estas
dos funciones.
Durante la existencia de un SO ocurren varios cambios en la tecnología de computación y
en los requerimientos del usuario. El sistema operativo debe adaptarse a estos cambios. En con-
secuencia, la estructura de un SO debe facilitar cambios para implementar un sistema operativo
en un sistema de cómputo con una arquitectura diferente y proporcionar nuevas funcionalidades
requeridas por sus usuarios.
En esta parte se analizan las facilidades de sincronización proporcionadas en sistemas ope-
rativos, los métodos utilizados por los sistemas operativos para manipular los bloqueos mutuos,
las técnicas de eficacia usadas en un IOCS y las técnicas de diseño de un SO que facilitan la
modificación fácil de un SO para adaptarse a cambios en arquitectura de computadoras y en
requerimientos del usuario.

10 MAQ. PARTE 2.indd 399 8/10/07 1:04:38 AM


400 Parte II Tópicos avanzados

Diagrama de contenidos de la parte II

Introducción

Parte I: Conceptos fundamentales

Visión general
de los sistemas
operativos

Estructura de Administración
Procesos Sistemas
los sistemas de la memoria
e hilos de archivos
operativos

Protección
Sincronización Memoria
Planificación y
de procesos virtual
seguridad

Sincronización y programación Implementación


Pase de Bloqueos en sistemas operativos de las operaciones
mensajes mutuos de multiprocesador de archivos

Parte II: Tópicos avanzados

Capítulo 9: Sincronización de procesos


Los procesos de una aplicación trabajan en un objetivo común mediante el hecho de com-
partir algunos datos y la coordinación entre aquéllos. Los conceptos clave en la sincronización
de procesos son el uso de exclusión mutua a fin de salvaguardar la consistencia de los datos
compartidos y el uso de operaciones indivisibles en las actividades de coordinación de procesos.
En este capítulo se analizan algunos problemas clásicos en la sincronización de procesos y se
analiza cómo es posible satisfacer sus requerimientos de sincronización mediante el empleo de
características de sincronización, como los semáforos y los monitores proporcionados en lengua-
jes de programación y sistemas operativos.

Capítulo 10: Pase de mensajes


Los procesos intercambian información mediante el envío de mensajes interproceso. En
este capítulo se analiza la semántica del pase de mensajes, así como las responsabilidades del SO
en el almacenamiento temporal y la entrega de mensajes interproceso.

Capítulo 11: Bloqueos mutuos


Un bloqueo mutuo se presenta cuando los procesos esperan por algún otro de manera in-
definida debido al hecho de compartir o sincronizar recursos. En este capítulo se analiza cómo
pueden presentarse los bloqueos mutuos y cómo el SO lleva a cabo manejo del bloqueo mutuo

10 MAQ. PARTE 2.indd 400 8/10/07 1:04:39 AM


Parte II Tópicos avanzados 401

para asegurar su ausencia, a través de la detección y protección de los bloqueos mutuos o me-
diante políticas de asignación de recursos que llevan a cabo prevención del bloqueo mutuo o
cómo evitar el bloqueo mutuo.

Capítulo 12: Implementación de operaciones de archivos


En este capítulo se analiza la organización física utilizada en sistemas de archivos. Empieza
con una visión general de los dispositivos de E/S y sus características, y se abordan diversas
organizaciones RAID que proporcionan alta confiabilidad, acceso rápido y elevados ritmos de
transferencia de datos. Luego se analizan los arreglos usados para implementar dispositivos en
el nivel E/S, incluido el uso de cachés de dispositivo para acelerar las operaciones de E/S y el de
políticas de programación de discos para mejorar el rendimiento de los dispositivos de disco.
Este capítulo también discute las técnicas de colocación en memoria intermedia (buffering)
y bloqueo de datos en archivos para mejorar la eficiencia del procesamiento de archivos en un
proceso.

Capítulo 13: Sincronización y planificación en sistemas operativos de multiprocesador


Un sistema de cómputo de multiprocesador mantiene la promesa de obtener alto rendi-
miento y cálculos más rápidos mediante la programación de los procesos en todos sus CPU.
En este capítulo se analiza la forma en que se realiza esta promesa mediante el empleo de técni-
cas especiales de sincronización para reducir los retrasos de sincronización y técnicas especiales
de programación para obtener mayor rapidez computacional.

Capítulo 14: Estructura de los sistemas operativos


La estructura de un sistema operativo posee dos tipos de características: las que contribu-
yen a la sencillez de codificación y eficacia de operación, y las que contribuyen a la facilidad
con que es posible implementar un SO en diferentes sistemas de cómputo o la manera en que
puede mejorarse el SO a fin de incorporar nuevas funcionalidades. En este capítulo se anali-
zan tres métodos para estructurar un sistema operativo: la estructura por capas de los sistemas
operativos simplifica la codificación, la estructura basada en el kernel proporciona facilidad
de implementación en diferentes sistemas de cómputo y la estructura basada en el microkernel
permite mejorar características de un sistema operativo.

10 MAQ. PARTE 2.indd 401 8/10/07 1:04:39 AM


10 MAQ. PARTE 2.indd 402 8/10/07 1:04:39 AM
Capítulo
9
Sincronización
de procesos

Con el fin de cumplir con una meta común, los procesos interactivos necesitan compartir datos o
coordinar sus actividades entre sí. La sincronización para acceder a datos garantiza que aquellos
que se comparten no pierdan consistencia cuando son actualizados por varios procesos. Esto se
realiza asegurándose de que los accesos a datos compartidos sean efectuados de manera mutua-
mente exclusiva. La sincronización de controles asegura también que los procesos interactivos
realicen sus acciones en un orden deseado. Los sistemas de cómputo proporcionan instrucciones
indivisibles (también llamadas instrucciones atómicas) para apoyar el acceso a datos y la sincro-
nización de controles.
Empezaremos este capítulo con una discusión acerca de las secciones críticas, las cuales
se usan para acceder a datos compartidos de manera mutuamente exclusiva. Después introduci-
remos algunos problemas clásicos de la sincronización de procesos. Éstos son abstracciones de
problemas prácticos de sincronización que se enfrentan en varios dominios de aplicación. Ana-
lizaremos los requerimientos de sincronización de estos problemas y estudiaremos cuestiones
importantes involucradas en su puesta en práctica.
En el resto del capítulo discutiremos varias herramientas de sincronización que son pro-
porcionadas en lenguajes de programación y en sistemas operativos. Esto incluye a semá-
foros, regiones críticas condicionales y monitores. Finalmente, analizaremos su papel en el cum-
plimiento de los requerimientos de sincronización de procesos en los problemas clásicos.

9.1 LA SINCRONIZACIÓN DE ACCESO A DATOS


Y LA SINCRONIZACIÓN DE CONTROLES
En el capítulo 3 analizamos cómo la implementación de una aplicación mediante el uso de un
conjunto de procesos interactivos puede dar como resultado la aceleración de la ejecución y
el mejoramiento de los tiempos de respuesta. A fin de trabajar para lograr una meta común,
los procesos interactivos tienen que coordinar sus actividades entre sí. Para este propósito
hemos definido dos tipos de sincronización: sincronización de acceso a datos (véase la def. 3.6)
y sincronización de controles (véase la def. 3.7). La tabla 9.1 proporciona un resumen de sus
características principales.

11 MAQ. CAP. 09(F0694).indd 403 8/10/07 1:05:39 AM


404 CAPÍTULO 9 Sincronización de procesos

Tabla 9.1 Características de la sincronización de acceso a datos y de la sincronización de controles

Acceso a datos Las condiciones de ejecución (véase la def. 3.5) surgen si varios procesos
acceden a datos compartidos sin que exista coordinación. Las condiciones
de ejecución no son reproducibles y, por ende, la depuración es difícil. Se usa
la sincronización de acceso a datos para acceder a datos compartidos de ma-
nera mutuamente exclusiva. Esto evita las condiciones de ejecución y salvaguar-
da la consistencia de los datos compartidos.
Sincronización de La sincronización de controles es necesaria si un proceso ejecuta alguna acción
controles ai, sólo después de que algunos otros procesos han ejecutado una serie de ac-
ciones {aj} o sólo cuando se tiene una serie de condiciones {ck}.

En la sección 3.6.1 definimos una condición de ejecución en la siguiente forma (véase def.
3.5): que ai y aj sean operaciones con los datos compartidos ds implementadas por dos proce-
sos Pi y Pj. fi(ds) representa el valor de ds resultante de cambios, si los hubiere, causados por
la operación ai. fj(ds) se define en forma análoga. Una condición de ejecución surge si el resul-
tado de la ejecución de ai y aj en los procesos Pi y Pj es diferente de fi(fj(ds)) o fj(fi(ds)). En el
ejemplo 3.9 vimos cómo surge una condición de ejecución en el sistema de reservaciones de una
aerolínea cuando varios procesos actualizan el valor de nextseatno en forma no coordinada: ¡su
valor incrementó sólo en 1, aunque dos procesos le aumentaron 1!
También discutimos algunos ejemplos de sincronización de controles en la sección 3.6.2.
El sistema de tiempo real de la figura 3.3 usa tres procesos para copiar en un disco muestras
recibidas desde un satélite. Aquí el proceso principal espera hasta que se completen sus procesos
hijos antes de terminar él mismo. Los procesos hijos sincronizan sus actividades de tal forma que
sólo se copia una nueva muestra a una entrada de memoria intermedia cuando ésta se encuentra
vacía, y el contenido de una entrada de memoria intermedia es copiado al disco sólo cuando
aquélla contiene una nueva muestra.

Implementando la sincronización La técnica básica que se usa para realizar la sincroni-


zación consiste en bloquear un proceso hasta que una acción apropiada es ejecutada por otro, o
hasta que se cumpla una condición. Así, la sincronización de acceso a datos se realiza bloquean-
do un proceso hasta que otro termina su acceso a los datos compartidos. La sincronización de
controles se realiza bloqueando un proceso hasta que otro efectúe una acción específica.
Durante la implementación de la sincronización de procesos es importante observar que
no se puede estimar la velocidad efectiva de ejecución de un proceso debido a factores como
time slicing (división del tiempo en “rebanadas”), prioridades de proceso y actividades de E/S
en un proceso. De modo similar, es imposible conocer las velocidades de ejecución relativas
de procesos, por lo que un esquema de sincronización debe funcionar correctamente, de forma
independiente a la velocidad de ejecución relativa de los procesos.

9.2 SECCIONES CRÍTICAS

Las condiciones de ejecución en datos compartidos ds (véase la def. 3.5) surgen porque operacio-
nes en ds son implementadas simultáneamente por dos o más procesos. La noción de una sección
crítica (SC) es introducida para evitar condiciones de ejecución.

11 MAQ. CAP. 09(F0694).indd 404 8/10/07 1:05:40 AM


9.2 Secciones críticas 405

Definición 9.1 [Sección crítica (SC)] Una sección crítica para un ítem de dato ds es una
sección de código que no debe ser ejecutada consigo misma ni con otras secciones críticas
para ds.

Si algún proceso Pi está ejecutando una sección crítica para ds, otro proceso que desea
ejecutar una sección crítica para ds tendrá que esperar hasta que Pi termine la ejecución de su
sección crítica. De este modo, una SC para un ítem de dato ds es una región de exclusión mutua
con respecto a accesos a ds: a lo sumo, un proceso puede ejecutar una SC para ds en cualquier
momento dado.
Las condiciones de ejecución en un ítem de dato se evitan cuando se realizan todas sus ope-
raciones de actualización dentro de una SC para el ítem de dato. Además, para asegurar que los
procesos vean valores consistentes de un ítem de dato, todos sus usos también deberán ocurrir
dentro de una SC para el ítem de dato.
Señalamos una SC en una parte de código mediante un recuadro de líneas discontinuas.
Observe que los procesos podrán compartir una sola copia de código. En este caso, una sola SC
para ds podrá existir en una aplicación. En forma alternativa, el código para cada proceso podrá
contener una o varias SC para ds. La definición 9.1 incluye ambas situaciones. De un proceso
que ejecuta una SC se dice que está “en una SC”. También usamos los términos “entrar en una
SC” y “salir de una SC” para situaciones donde un proceso inicia y termina la ejecución de
una SC, respectivamente.

repetir para siempre repetir para siempre

Sección crítica
Sección crítica
Resto
Sección crítica
del ciclo
Sección crítica
{ Resto del ciclo }
final final
a) b)
Figura 9.1 a) Un proceso con muchas secciones críticas; b) una manera más simple de representar este proceso.

La figura 9.1a) muestra un proceso que contiene varias secciones críticas. Éstas se podrán
usar para acceder a los mismos o a distintos ítems de datos compartidos. De este modo, un pro-
ceso podrá contener varias secciones críticas para el mismo ítem de dato. El proceso contiene
un ciclo. En cada iteración entra en una sección crítica cuando necesita acceder a un ítem de
dato compartido. En otras ocasiones, ejecuta un código diferente en su lógica, lo que en conjunto
constituye el “resto del ciclo”. Cada vez que es posible, para describir un proceso usamos, por
motivos de simplicidad, el proceso sencillo que se representa en la figura 9.1b).
El ejemplo 9.1 ilustra el uso de una SC para evitar condiciones de ejecución en el sistema
de reservaciones de una aerolínea.

Ejemplo 9.1 La figura 9.2 muestra el uso de secciones críticas en el sistema de reservaciones de
aerolínea de la figura 3.22. Cada proceso contiene una SC en la cual accede a y actualiza la variable

11 MAQ. CAP. 09(F0694).indd 405 8/10/07 1:05:40 AM


406 CAPÍTULO 9 Sincronización de procesos

compartida nextseatno. La ausencia de condiciones de ejecución se puede mostrar de la siguien-


te manera: que fi(nextseatno) y fj(nextseatno) representen el valor de nextseatno que resulta de
cambios, si existen, causados por la ejecución de secciones críticas en Pi y Pj, respectivamente.
Que Pi y Pj intenten ejecutar sus secciones críticas en forma simultánea. Partiendo de la definición
de SC, se deduce que sólo uno de ellos puede ejecutar su SC en cualquier momento dado, así que
el valor resultante de nextseatno será fi(fj(nextseatno)) o fj(fi(nextseatno)). De la definición 3.5 no
surge ninguna condición de ejecución.

si nextseatno  capacidad si nextseatno  capacidad


entonces entonces
allotedno:=nextseatno; allotedno:=nextseatno;
nextseatno:=nextseatno+1; nextseatno:=nextseatno+1;
si no si no
visualiza “lo siento, no hay visualiza “lo siento, no hay
asientos disponibles”; asientos disponibles”;

proceso Pi proceso Pj

Figura 9.2 Uso de SC en la reservación de aerolíneas.

Si en una aplicación los procesos usan con frecuencia un ítem de dato ds, la ejecución
de una sección crítica para ds se podrá convertir en un cuello de botella permanente. Esto causa-
ría retrasos en la ejecución de los procesos y afectaría en forma desfavorable el rendimiento de
la aplicación. Se reduce la severidad de este problema si los procesos no pasan demasiado tiem-
po dentro de una SC. Tanto los procesos como el kernel deben cooperar para asegurar lo anterior.
Un proceso no deberá ejecutarse demasiado tiempo dentro de una SC. Mientras se encuentre
dentro de una SC, el proceso debe evitar llamadas al sistema que lo puedan poner en un estado de
bloqueo. El kernel no deberá adelantarse a un proceso que entra en la ejecución de una SC. Esta
condición es difícil de cumplir, pues requiere que el kernel sepa si un proceso está dentro de una
SC en algún momento dado. La condición no se puede cumplir si los procesos realizan secciones
críticas por su propia cuenta, es decir, sin involucrar al kernel. No obstante, en el presente capí-
tulo vamos a suponer que un proceso pasa sólo un tiempo breve dentro de una sección crítica.

9.2.1 Propiedades de una implementación de una SC

Una implementación de SC para un ítem de dato ds es como un planificador para un recurso.


Debe estar al corriente de todos los procesos que quieren entrar a una SC para ds y debe se-
leccionar un proceso para la entrada en una SC de acuerdo con las nociones de exclusión
mutua, eficiencia e imparcialidad. La tabla 9.2 resume las propiedades esenciales que posee la
implementación de una SC. A continuación analizaremos estas propiedades.
La exclusión mutua garantiza que no habrá más de un proceso en una SC para ds en un
momento dado. Además de lo correcto, una implementación de SC también deberá garantizar
que todo proceso que espera entrar en una SC no estará demorado indefinidamente; es decir,
no ocurrirá la inanición. Esta garantía está formada por dos partes y la proporcionan las otras
dos propiedades.

11 MAQ. CAP. 09(F0694).indd 406 8/10/07 1:05:41 AM


9.2 Secciones críticas 407

Tabla 9.2 Propiedades esenciales de una implementación de SC

Propiedad Descripción
Corrección En cualquier momento dado, a lo sumo un proceso podrá ejecutar
una SC para un ítem de dato ds.
Progreso Cuando una SC no está en uso, uno de los procesos que desean
entrar en ella recibirá permiso de entrar en la SC.
Espera limitada Después de que un proceso Pi haya indicado su deseo de entrar
en una SC para ds, la cantidad de veces que otros procesos pue-
dan obtener la entrada en una SC para ds antes de Pi está limitada
por un número entero finito.

La propiedad de progreso asegura que si algún proceso está interesado en entrar a una SC
para un ítem de dato ds, a uno de ellos se le concederá la entrada si ningún proceso se encuen-
tra en ese momento dentro de la SC; esto quiere decir que el privilegio para entrar en una SC
para ds no será reservado para algún proceso que actualmente no esté interesado en entrar en
una SC. Si esta propiedad no se cumple, los procesos que desean entrar en una SC podrían estar
demorados hasta que algún proceso específico Ps decide usar una SC. Puede ser que el proceso
Ps jamás use una SC para ds, así que la ausencia de esta propiedad puede demorar un pro-
ceso indefinidamente.
La propiedad de progreso asegura que la implementación de la SC necesariamente elija
a uno de los procesos de petición para entrar en una SC. Sin embargo, esto no es suficiente
para asegurar que un proceso de petición obtenga la entrada a una SC en tiempo finito, porque
una implementación de SC puede ignorar Pi mientras elige un proceso para la entrada en una SC.
La propiedad de espera limitada asegura que esto no suceda, limitando el número de veces que
otros procesos pueden ser preferidos a Pi. Puesto que la ejecución de una SC tarda poco tiempo,
esta propiedad garantiza que cada proceso de petición obtenga la entrada a su SC en tiempo
finito.

9.2.2 El problema de espera activa

Un proceso puede implementar una SC para un ítem de dato ds usando el siguiente código sen-
cillo:

mientras (algún proceso esté en una SC para ds )


{ no hagas nada }
Sección
crítica

En el bucle mientras, el proceso revisa si algún otro proceso está en una SC para el mismo ítem
de dato. En caso afirmativo, seguirá en el bucle hasta que el otro proceso salga de su SC.
Una espera activa es una situación en la que un proceso revisa de modo repetido si se
cumple con una condición que lo habilitaría para poder pasar un punto de sincronización. Sólo
termina cuando se cumple esta condición. ¡De esta manera, una espera activa mantiene al CPU

11 MAQ. CAP. 09(F0694).indd 407 8/10/07 1:05:41 AM


408 CAPÍTULO 9 Sincronización de procesos

ocupado en la ejecución de un proceso, aun cuando el proceso no haga nada! A los procesos de
menor prioridad se les niega el uso del CPU, así que sufren sus tiempos de respuesta. El rendi-
miento del sistema también lo padece.
Igualmente, una espera activa causa un problema curioso en un sistema de monoprocesa-
dor. Considere la siguiente situación: un proceso de alta prioridad Pi está bloqueado en una
operación E/S, y un proceso de baja prioridad Pj entra a una SC para el ítem de dato ds. Cuando
se completa la operación E/S de Pi, Pj está adelantado y Pi está en lista de espera. Si Pi intentara
en ese momento entrar en una SC para ds usando el bucle mientras que se describió líneas arri-
ba, enfrentaría una espera activa. Esa espera activa le niega el CPU a Pj y, por ende, no puede
completar su ejecución de la SC y salir. Esto impide que Pi entre a su SC. Entonces, los procesos
Pi y Pj esperan uno al otro indefinidamente. Esta situación se llama bloqueo mutuo. Debido a
que un proceso de alta prioridad espera a un proceso de baja prioridad, esta situación también se
llama inversión de prioridades. El problema de la inversión de prioridades se aborda usando el
protocolo de herencia de prioridad, donde un proceso de baja prioridad, que retiene un recurso,
temporalmente adquiere la prioridad del proceso con la prioridad más alta que necesita ese re-
curso. En nuestro ejemplo, el proceso Pj adquiriría temporalmente la prioridad del proceso Pi,
lo que lo habilitaría para ser programado y poder salir de su sección crítica. Sin embargo, el uso
del protocolo de herencia de prioridad en estas situaciones no es práctico porque requeriría que
el kernel tome en cuenta detalles minuciosos de la operación de procesos.
A fin de evitar esperas activas, un proceso que se encuentra esperando la entrada a una SC
se deberá poner en el estado bloqueado. Este estado se deberá cambiar a disponible sólo cuando se
pueda permitir que entre en su SC.

9.2.3 La historia de implementaciones de SC

Históricamente, la implementación de secciones críticas ha atravesado tres fases importantes:


planeamientos algorítmicos, primitivas de software y constructores de programación concu-
rrentes. Los planeamientos algorítmicos dependían de un complejo arreglo de controles para
asegurar la exclusión mutua entre procesos que usan una SC. La corrección de una implemen-
tación de SC dependía de la corrección de esos controles, y era difícil de comprobar debido a la
complejidad lógica de éstos. Lo anterior fue una deficiencia seria en el desarrollo de sistemas
grandes que contenían procesos concurrentes. Sin embargo, una gran ventaja de este plantea-
miento fue que no se necesitaba ningún hardware, lenguaje de programación o características
de kernel especiales para implementar una SC.
Se desarrolló una serie de primitivas de software para la exclusión mutua (por ejemplo, las
primitivas P y V de Dijkstra) con el fin de superar la complejidad lógica de implementaciones
algorítmicas. Estas primitivas fueron llevadas a cabo usando algunas características arquitectó-
nicas especiales de un sistema de cómputo, y poseían propiedades útiles para la implementación
de una SC. Tales propiedades también se podían usar para construir evidencias de corrección de
un sistema concurrente. Sin embargo, la experiencia con estas primitivas mostró que la facilidad
de uso y evidencia de corrección seguía siendo un obstáculo mayor en el desarrollo de sistemas
concurrentes grandes.
El siguiente paso importante en la historia de las implementaciones de SC fue el desarrollo
de constructores de programación concurrentes. Éstos usaban características de abstracción de
datos y encapsulado específicamente indicadas para la construcción de programas concurrentes.

11 MAQ. CAP. 09(F0694).indd 408 8/10/07 1:05:41 AM


9.3 Condiciones de ejecución en la sincronización de controles 409

Ellos tenían una semántica bien definida que fue aplicada por el compilador de lenguaje. Esta
característica hizo más práctica la construcción de sistemas concurrentes grandes.
Discutiremos los planteamientos algorítmicos de la implementación de SC en la sección
9.7. Las secciones 9.8 y 9.9 se dedican al análisis de primitivas y constructores de lenguajes de
programación. La sección 9.10 se dedica a las facilidades de abstracción y encapsulado para
la programación concurrente proporcionadas por monitores.

9.3 CONDICIONES DE EJECUCIÓN EN LA


SINCRONIZACIÓN DE CONTROLES
Los procesos usan la sincronización de controles para coordinar sus actividades entre sí. Un
requerimiento frecuente en la sincronización de procesos es que un proceso Pi deberá ejecutar
una acción ai sólo después de que el proceso Pj haya ejecutado una acción aj. Un pseudocódigo
para este tipo de procesos se muestra en la figura 9.3. Este requerimiento de sincronización se
satisface usando la técnica de señalización.

{Ejecuta la operación a i sólo después de que Pj Ejecuta la operación aj


ejecute la operación aj }
Proceso Pi Proceso Pj

Figura 9.3 Procesos que necesitan sincronización de controles.

Señalización La figura 9.4 muestra cómo se realiza la señalización. Los datos de sincro-
nización consisten en dos variables booleanas. La variable action_aj_performed es una señal
para indicar si el proceso Pj ha ejecutado la acción aj. La variable pi_blocked es una señal para
indicar si el proceso Pi se ha bloqueado a sí mismo en espera de la ejecución de la acción aj por
parte del proceso Pj. Se asume que el kernel permite llamadas al sistema para bloquear y activar
un proceso.
El proceso Pi consulta la variable action_aj_performed para verificar si el proceso Pj ya
ejecutó la acción aj. Si éste no es el caso, fija pi_blocked en true y realiza una llamada al sistema
para bloquearse a sí mismo. Procede a ejecutar la acción ai si aj ya fue ejecutado. El proceso
Pj ejecuta la acción aj y revisa si el proceso Pi se ha bloqueado a sí mismo antes de ejecutar
la acción ai. Si éste es el caso, realiza una llamada al sistema para activar Pi. De lo contrario,
fija action_aj_performed en true; de esta forma, el proceso Pi sabrá que Pj ha ejecutado la ac-
ción aj.
La tabla 9.3 muestra una ejecución del sistema donde el proceso Pi se enfrenta al bloqueo
indefinido debido a una condición de ejecución. El proceso Pi verifica el valor de action_aj_per-
formed y se da cuenta de que la acción aj no fue ejecutada. Está listo entonces para fijar la
variable pi_blocked en true cuando es desplazado. El proceso Pj está ahora programado. Realiza
la acción aj y revisa si el proceso Pi está bloqueado. Puesto que pi_blocked es false, simplemente
fija action_aj_performed en true y continúa su ejecución. En algún momento más tarde se pro-
grama Pi. Fija pi_blocked en true y realiza una llamada al sistema para bloquearse a sí mismo.
¡El proceso Pi ahora dormirá para siempre!

11 MAQ. CAP. 09(F0694).indd 409 8/10/07 1:05:41 AM


410 CAPÍTULO 9 Sincronización de procesos

var
operation aj performed : boolean;
pi blocked : boolean;
begin
operation aj performed := false;
pi blocked := false;

Parbegin

if operation aj performed = false {ejecutar operación aj }


then if pi blocked = true
pi blocked := true; then
block(Pi ); pi blocked := false;
{ejecutar operación a i } activate(Pi);
else
operation aj performed := true;

Parend;
end.

proceso Pi proceso Pj

Figura 9.4 Un intento de señalización por medio de variables booleanas.

Tabla 9.3 Condición de ejecución en la sincronización de procesos

Tiempo Acciones del proceso Pi Acciones del proceso Pj


t1 si action aj performed = false entonces
t2 {ejecuta acción a j }
t3 si pi blocked = true entonces
t4 action aj performed := true

t20 pi blocked := true;


t21 block (Pi );

Considere las instrucciones if en los procesos Pi y Pj como las operaciones fi y fj en el es-


tado del sistema. El resultado de su ejecución deberá ser uno de los siguientes: el proceso Pi se
bloquea a sí mismo, es activado por Pj y ejecuta la acción ai; o el proceso Pi se da cuenta de que
Pj ya ejecutó aj y procede a ejecutar la acción ai. Sin embargo, como se vio en la tabla 9.3, el
proceso Pi se bloquea a sí mismo y no es activado. De acuerdo con la def. 3.5, se trata de una
condición de ejecución.
La condición de ejecución se presenta porque el proceso Pi avanza después de verificar si
action_aj_performed  true, pero antes de que pueda fijar pi_blocked  true. La condición de
ejecución se puede evitar si podemos garantizar que Pi será capaz de completar ambas acciones
antes de avanzar. Introducimos la noción de una operación indivisible (también llamada opera-
ción atómica) para lograr esto.

11 MAQ. CAP. 09(F0694).indd 410 8/10/07 1:05:42 AM


9.4 La implementación de secciones críticas y operaciones indivisibles 411

Definición 9.2 (Operación indivisible) Una operación indivisible en un conjunto de ítems


de datos {ds} es una operación que no se puede ejecutar en forma concurrente con cualquie-
ra otra operación que involucra un ítem de dato incluido en {ds}.

La condición de ejecución que se muestra en la tabla 9.3 no se presentaría si las instrucciones


if fuesen implementadas como operaciones indivisibles, porque si el proceso Pi se da cuenta de
que action_aj_performed  false, sería capaz de fijar pj_blocked  true antes de avanzar. Esto
lo podríamos lograr mediante la definición de dos operaciones indivisibles check_action_aj_per-
formed y post_action_aj_performed a fin de ejecutar las instrucciones if de los procesos Pi y Pj,
respectivamente. La figura 9.5 muestra un arreglo de señalización, usando estas operaciones
indivisibles. La figura 9.6 muestra detalles de las operaciones indivisibles check_action_aj_per-
formed y post_action_aj_performed. Cuando action_aj_performed es false, la operación indi-
visible check_aj es considerada completa después de que el proceso Pi es bloqueado; ésta sería
capaz de habilitar el proceso Pj para ejecutar la operación post_aj.

var
action aj performed : boolean;
pi blocked : boolean;
begin
action aj performed := false;
pi blocked := false;
Parbegin

check aj; {ejecutar operación aj }


{ejecutar operación ai } post aj;
Parend;
end.

procesoPi procesoP j

Figura 9.5 Sincronización de controles por señalización, usando operaciones indivisibles.

Una operación indivisible en {ds} es como una sección crítica en {ds}. Sin embargo, las
distinguimos porque una SC tiene que ser explícitamente implementada en un programa, mien-
tras que el hardware o software de un sistema de cómputo podrá proporcionar operaciones in-
divisibles como sus propias operaciones primitivas. En la siguiente sección analizaremos cómo
se pueden usar operaciones indivisibles en semáforos para realizar la sincronización de acceso a
datos y la sincronización de controles sin condiciones de ejecución.

9.4 LA IMPLEMENTACION DE SECCIONES CRÍTICAS


Y OPERACIONES INDIVISIBLES
La sincronización de procesos requiere secciones críticas u operaciones de señalización que son
indivisibles. Éstas se realizan usando instrucciones indivisibles proporcionadas por sistemas de
cómputo, así como variables de bloqueo.

11 MAQ. CAP. 09(F0694).indd 411 8/10/07 1:05:42 AM


412 CAPÍTULO 9 Sincronización de procesos

procedimiento check aj
inicio
si action aj performed = false
entonces
pi blocked := true;
block (Pi )
fin;
procedimiento post aj
inicio
si pi blocked = true
entonces
pi blocked := false;
activate(Pi )
si no
action aj performed := true;
fin;

Figura 9.6 Operaciones indivisibles para la señalización.

Instrucciones indivisibles En la sección 3.6.1 vimos cómo se pueden presentar condicio-


nes de ejecución si varios procesos ejecutan una secuencia de instrucciones de load-add-store
(carga-suma-almacena) sobre datos compartidos. Si un sistema de cómputo contiene más de un
CPU, pueden presentarse condiciones de ejecución incluso durante la ejecución de una sola ins-
trucción que toma más de un acceso a una ubicación de memoria; por ejemplo, una instrucción
que incrementa el valor de una variable.
Desde mediados de los sesenta, los sistemas de cómputo han proporcionado característi-
cas especiales en su arquitectura para evitar condiciones de ejecución durante el acceso a una
ubicación de memoria que contiene datos compartidos. El tema básico es que todos los accesos
a una ubicación de memoria hechos por una instrucción deberán ser realizados sin permitir
que otro CPU tenga acceso a la misma ubicación. Las dos técnicas populares que se usan para
este fin son el bloqueo del bus de memoria (por ejemplo, en procesadores de Intel 80x86) e
instrucciones especiales que evitan condiciones de ejecución (por ejemplo, en procesadores
IBM/370 y M68000). Usaremos el término genérico instrucción indivisible para todas estas
características.

Uso de una variable de bloqueo Se usa una variable de bloqueo para puentear el espacio
entre secciones críticas u operaciones indivisibles y las instrucciones indivisibles proporciona-
das en un sistema de cómputo. La idea básica es poner un cerrojo al inicio de una sección crítica
o de una operación indivisible, y abrirlo al final de la sección crítica o de la operación indivisible.
Una operación de poner el cerrojo falla si éste ya fue cerrado por algún otro proceso. De este
modo, sólo un proceso puede ejecutar una sección crítica o una operación indivisible. Así se
evitan las condiciones de ejecución en la variable de bloqueo mediante el uso de instrucciones
indivisibles para acceder a la variable de bloqueo.
Un proceso que no consigue poner un cerrojo debe volver a intentar la operación. Este es-
quema involucra una espera activa; sin embargo, no dura mucho tiempo; sólo hasta que el proce-

11 MAQ. CAP. 09(F0694).indd 412 8/10/07 1:05:42 AM


9.4 La implementación de secciones críticas y operaciones indivisibles 413

so que puso el cerrojo termina la ejecución de una sección crítica o de una operación indivisible.
Ambos sólo requieren un tiempo corto.
La figura 9.7 ilustra cómo se realiza una sección crítica usando una instrucción indivisible y
una variable de bloqueo. La instrucción indivisible ejecuta las acciones indicadas en el recuadro
de líneas discontinuas. Esta instrucción examina el valor de la cerradura y vuelve sobre sí misma
si el bloqueo está cerrado; en caso contrario, cierra el bloqueo. En la figura que sigue ilustramos
el uso de dos instrucciones indivisibles —las llamadas instrucciones test-and-set y swap— para
realizar secciones críticas y operaciones indivisibles.

entry test: if lock = closed Realizado


then goto entry test; por una instrucción
lock := closed; indivisible
{ Sección crítica u
operación indivisible }
lock := open;

Figura 9.7 Implementación de una sección crítica o de una operación indivisible, usando una variable de bloqueo.

Instrucción test-and-set (TS) Esta instrucción indivisible en el IBM/370 realiza dos ac-
ciones. Por una parte “prueba” el valor de un byte de memoria, de tal modo que el código de
condición indica si el valor era cero o no cero. También establece todos los bits en el byte a 1s.
Ningún otro CPU puede acceder al byte de memoria hasta que ambas acciones estén comple-
tas. Esta instrucción se puede usar para realizar las instrucciones encerradas en el recuadro de
líneas discontinuas de la figura 9.7.

LOCK DC X‘00’ Lock se inicializa para abrir


ENTRY TEST TS LOCK Test-and-set lock
BC 7, ENTRY TEST Loop si está cerrado

{ Sección crı́tica u
operación indivisible }

MVI LOCK, X‘00’ Open the lock (by moving 0s)

Figura 9.8 Implementación de una sección crítica o de una operación indivisible usando test-and-set.

La figura 9.8 es un programa en lenguaje ensamblador IBM/370 que muestra cómo se ob-
tiene la indivisibilidad de operaciones wait y signal. La primera línea del programa en lenguaje
ensamblador declara la variable LOCK y la inicializa a un 0 hexadecimal. LOCK se usa como una
variable de bloqueo con la convención de que un valor no cero en LOCK implica que el bloqueo
está cerrado, y un valor cero implica que está abierto. La instrucción TS fija el código de con-
diciones de acuerdo con el valor de LOCK y también cambia su valor a cerrado. El código de
condiciones indica si el valor del bloqueo estuvo cerrado antes de la ejecución de la instrucción.
La instrucción de transferencia BC 7, TEST revisa el código de condiciones y hace un bucle de

11 MAQ. CAP. 09(F0694).indd 413 8/10/07 1:05:42 AM


414 CAPÍTULO 9 Sincronización de procesos

regreso a la instrucción TS si el bloqueo se encontró cerrado. De esta manera, un programa (o


varios programas) que encuentre el bloqueo cerrado ejecuta el bucle en una espera activa hasta
que el bloqueo está fijado para abrir. La instrucción MVI coloca 0 en todos los bits de LOCK, es
decir, abre el bloqueo. TS es una instrucción indivisible, así que abrir el bloqueo habilitaría sólo
un proceso que da a TEST un bucle para proceder.

Instrucción de intercambio Esta instrucción intercambia los contenidos de dos ubicacio-


nes de memoria. Se trata de una instrucción indivisible; por ende, ningún otro CPU puede acce-
der a cualquiera de las ubicaciones durante la sustitución. La figura 9.9 muestra cómo se puede
realizar una sección crítica o una operación indivisible usando la instrucción de intercambio.
(Por conveniencia, emplearemos las mismas convenciones de codificación que se usan para la
instrucción TS.) La ubicación temporal TEMP está fijada en un valor no cero, y sus contenidos
son intercambiados con LOCK. Esta acción cierra el bloqueo. Ahora, el viejo valor del bloqueo
está disponible en TEMP. Se prueba para ver si el bloqueo ya estaba cerrado. Si éste fuese el caso,
el proceso itera en la acción de swap-and-compare hasta que LOCK es fijado para abrir. El proce-
so que ejecuta la sección crítica u operación indivisible abre el bloqueo al final de la operación.
Esta acción habilita un proceso para pasar a la instrucción BC.

TEMP DS 1 Reserve un byte para TEMP


LOCK DC X‘00’ Lock se inicializa para abrir
MVI TEMP, X‘FF’ X‘FF’ se usa para cerrar el lazo
ENTRY TEST SWAP LOCK, TEMP
COMP TEMP, X‘00’ Test old vaue of lock
BC 7, ENTRY TEST Loop si lock está cerrado

... { Sección crı́tica u


operación indivisible }

MVI LOCK, X‘00’ Abrir lock

Figura 9.9 Implementación de una sección crítica o de una operación indivisible,


usando una instrucción de intercambio.

9.5 PROBLEMAS CLÁSICOS DE LA SINCRONIZACIÓN DE PROCESOS

Como analizamos en las secciones 9.2 y 9.3, las secciones críticas y la señalización son los ele-
mentos clave de la sincronización de procesos. La solución para un problema de sincronización
de procesos deberá usar una combinación adecuada de estos elementos. También deberá poseer
tres propiedades importantes:

• Corrección.
• Máxima concurrencia.
• No existencia de esperas activas.
Los criterios de corrección dependen de la naturaleza de un problema. Éstos proyectan requeri-
mientos referentes a la sincronización de accesos a datos y a la sincronización de controles de
procesos interactivos. La máxima concurrencia dentro de una aplicación es necesaria para acele-
rar la ejecución y obtener buenos tiempos de respuesta. Para lograr esto, los procesos deberán ser

11 MAQ. CAP. 09(F0694).indd 414 8/10/07 1:05:43 AM


9.5 Problemas clásicos de la sincronización de procesos 415

capaces de ejecutarse libremente, cuando no están bloqueados debido a requerimientos de sin-


cronización. Como se vio en la sección 9.2.2, esperas activas son indeseables porque conducen a
la degradación del desempeño del sistema y de los tiempos de respuesta, de tal modo que se debe
realizar la sincronización mediante el bloqueo de un proceso y no a través de esperas activas.
En esta sección analizaremos algunos problemas clásicos en la sincronización de procesos
y discutiremos temas (y errores comunes) acerca del diseño de sus soluciones. En secciones
posteriores implementaremos sus soluciones, usando varios elementos de sincronización propor-
cionados en lenguajes de programación.

9.5.1 Productores/consumidores con buffers acotados

Un sistema de productores/consumidores con buffers acotados consiste en un número no especi-


ficado de procesos productores y consumidores, así como un área central de memoria finita para
buffers (véase la figura 9.10). Cada buffer es capaz de contener un registro de información; se
dice que está lleno cuando un productor graba en él, y vacío cuando un productor copia un regis-
tro contenido en él; en un inicio, el buffer está vacío. Un proceso productor produce un registro
a la vez y lo graba en el buffer. Un proceso consumidor consume informaciones a un ritmo de
un registro a la vez.

Productores Consumidores

Área de memoria intermedia (buffer pool)

Figura 9.10 Productores y consumidores.

Un sistema de productores/consumidores con buffers acotados es una abstracción útil para


muchos problemas prácticos de sincronización. Un servicio de impresión es un buen ejemplo en
el dominio de SO. Un proceso de impresión es un proceso consumidor. Una cola de tamaño fijo
de solicitudes de impresión es el buffer acotado. Un proceso que agrega una solicitud de impre-
sión a la cola es un proceso productor.
Una solución para el problema de productores/consumidores debe cumplir con las siguien-
tes condiciones:
1. Un productor no debe sobrescribir en un buffer lleno.
2. Un consumidor no debe consumir de un buffer vacío.
3. Productores y consumidores deben acceder a buffers de manera mutuamente exclusiva.
En ocasiones se impone la siguiente condición:
4. Las informaciones deben consumirse en el mismo orden aplicado para colocarlas en los
buffers, es decir, en orden FIFO (primero en entrar primero en salir).

11 MAQ. CAP. 09(F0694).indd 415 8/10/07 1:05:43 AM


416 CAPÍTULO 9 Sincronización de procesos

begin
Parbegin
var produced : boolean; var consumed : boolean;
repeat repeat
produced := false; consumed := false ;
while produced = false while consumed = false
if un buffer vacío existe if un buffer lleno existe
then then
{ Producir en un buffer } { Consumir en un buffer }
produced := true; consumed := true;
{ Resto { Resto
del ciclo } del ciclo }
forever; forever;
Parend
end.
Productor Consumidor

Figura 9.11 Esquema de solución para productores/consumidores que contienen esperas activas.

La figura 9.11 muestra un esquema para el problema de productores/consumidores. Los


procesos productores/consumidores acceden a un buffer dentro de una sección crítica. Un pro-
ductor entra en su SC y revisa si existe un buffer vacío. De ser así, graba (produce) en este buffer;
en caso contrario, simplemente sale de su SC. Esta secuencia se repite hasta que encuentra un
buffer vacío. La variable booleana producido se usa para salir del bucle mientras después de que
el productor produce en el buffer vacío. De manera análoga, un consumidor realiza revisiones
repetidas hasta que encuentra un buffer lleno donde pueda consumir.
Un aspecto indeseable de este esquema es la presencia de esperas activas. Con el fin de evi-
tar una espera activa, un proceso productor deberá revisar sólo una vez si existe un buffer vacío.
Si no existe ninguno, se deberá bloquear al productor hasta que un buffer vacío esté disponible.
Cuando un consumidor consume de un buffer, debe activar un productor que esté esperando un
buffer vacío. En forma similar, un productor debe activar un consumidor en espera de un buffer
lleno. Una SC no puede dar estas facilidades; por tanto, tenemos que buscar la solución del pro-
blema de las esperas activas en otra parte.
Cuando volvemos a analizar el problema de productores/consumidores desde este punto de
vista, nos damos cuenta de que, a pesar de que involucra a la exclusión mutua entre un productor
y un consumidor que usan el mismo buffer, en realidad se trata de un problema de señalización.
Después de producir un registro en un buffer, un productor deberá señalizar a un consumidor que
desea consumir el registro del mismo buffer. Del mismo modo, un consumidor, después de con-
sumir un registro en un buffer, deberá señalizar a un productor que desea producir un registro en
ese buffer. Estos requerimientos pueden satisfacerse usando el ordenamiento que se muestra
en la figura 9.5.
Un esquema mejorado que usa este planteamiento se muestra en la figura 9.12 para un
sistema simple de productores/consumidores que consiste en un solo productor, un solo consu-
midor y un solo buffer. La operación check_b_empty, ejecutada por el productor, lo bloquea si el
buffer está lleno, mientras que la operación post_b_full fija a buffer_full en true y activa al con-

11 MAQ. CAP. 09(F0694).indd 416 8/10/07 1:05:43 AM


9.5 Problemas clásicos de la sincronización de procesos 417

var
buffer : ;
buffer full : boolean;
producer blocked, consumer blocked : boolean;
begin
buffer full := false;
producer blocked := false;
consumer blocked := false;
Parbegin
repeat repeat
check b empty; check b full;
{ Producir en el buffer } { Consumir del buffer }
post b full; post b empty;
{ Resto del ciclo } { Resto del ciclo }
forever; forever;
Parend;
end.
Productor Consumidor

Figura 9.12 Un esquema mejorado para un sistema de productores/consumidores


de un solo buffer, usando la señalización.

sumidor si el consumidor está bloqueado para que se llene el buffer. Las operaciones análogas
check_b_full y post_b_empty son definidas para ser usadas por el proceso de consumidor. Los
indicadores booleanos producer_blocked y consumer_blocked son usados por estas operacio-
nes para indicar si el proceso de productor o consumidor está bloqueado en algún momento
dado. La figura 9.13 muestra detalles de las operaciones indivisibles. Este esquema se tendrá que
ampliar para el manejo de buffers múltiples o procesos de productor/consumidor múltiples. Dis-
cutiremos este aspecto en la sección 9.8.2.

9.5.2 Lectores y escritores

Un sistema de lectores/escritores consiste en una serie de procesos que usan algunos datos com-
partidos. Un proceso que sólo lee los datos es el lector; uno que los modifica o actualiza es el es-
critor. Usamos los términos lectura y escritura para referirnos a accesos a los datos compartidos
realizados por procesos de lectores y escritores, respectivamente. Las condiciones de corrección
para el problema de lectores/escritores son las siguientes:

1. Muchos lectores pueden realizar la lectura en forma concurrente.


2. La lectura está prohibida mientras un escritor escribe.
3. Sólo un escritor puede realizar escritura en cualquier momento dado.

Las condiciones 1-3 no especifican qué proceso se deberá preferir cuando uno de lectura y uno
de escritura desea acceder a los datos compartidos al mismo tiempo. Se impone la siguiente
condición adicional si es importante dar una prioridad más alta a lectores a fin de cumplir con
algunas metas de negocio:

11 MAQ. CAP. 09(F0694).indd 417 8/10/07 1:05:43 AM


418 CAPÍTULO 9 Sincronización de procesos

procedimiento check b empty procedimiento check b full


inicio inicio
si buffer full = true si buffer full = false
entonces entonces
producer blocked := true; counsumer blocked := true;
bloquear (productor); bloquear (consumidor);
fin; fin;
procedimiento post b full procedimiento post b empty
inicio inicio
buffer full := true; buffer full := false;
si consumer blocked = true si producer blocked = true
entonces entonces
consumer blocked := false; producer blocked := false;
activar (consumidor); activar (productor);
fin; fin;
Operaciones del productor Operaciones del consumidor
Figura 9.13 Operaciones indivisibles para el problema de productores/consumidores.

4. Un lector tiene una prioridad no preferente sobre escritores, es decir, obtendrá acceso a
los datos compartidos antes que un escritor en espera, pero no tendrá preferencia sobre
un escritor activo.
Este sistema se llama sistema de lectores/escritores con preferencia de lectores. Un sistema de
lectores/escritores con preferencia de escritores se define en forma análoga.
La figura 9.14 ilustra un ejemplo del sistema de lectores/escritores. Los lectores y escritores
comparten una cuenta bancaria. Los procesos de lectores print statement y stat analysis única-
mente leen los datos de la cuenta bancaria; por ende, pueden ejecutar en forma concurrente. cre-
dit y debit modifican el saldo de la cuenta. Queda claro que sólo uno de ellos deberá estar activo
en cualquier momento dado, y ninguno de los lectores deberá estar activo cuando se modifican
los datos.

Cuenta bancaria
imprimir
estado crédito

análisis
estadístico débito

Lectores Escritores
Figura 9.14 Lectores y escritores en un sistema bancario.

Determinamos los requerimientos de sincronización de un sistema de lectores/escritores


por medio del análisis de sus condiciones de corrección. La condición 3 requiere que un escritor
ejecute la escritura en una sección crítica. Cuando termina la escritura deberá activar a un escri-

11 MAQ. CAP. 09(F0694).indd 418 8/10/07 1:05:44 AM


9.5 Problemas clásicos de la sincronización de procesos 419

tor en espera o a todos los escritores en espera. Esto se puede lograr usando un ordenamiento de
señalización. Según la condición 1, se permite la lectura concurrente. Deberemos mantener un
conteo de lectores que leen en forma concurrente. Cuando el último lector termina su lectura,
deberá activar a un escritor en espera.
La figura 9.15 contiene un esquema para un sistema de lectores/escritores. La escritura se
realiza en una SC. Una SC no se usa en un lector, pues esto impediría la concurrencia entre lec-
tores. Se usa un ordenamiento de señalización para manejar el bloqueo y la activación de lectores
y escritores. Lo anterior se complica aún más por el hecho de que un escritor posiblemente tenga
que señalizar a muchos lectores. Por tal razón, no especificamos sus detalles en el esquema; lo
discutiremos en la sección 9.8.3. El esquema de la figura 9.15 no cumple con la condición de
espera acotada para lectores y escritores, pero provee máxima concurrencia.

Parbegin
repeat repeat
If a writer is writing If reader(s) are reading, or a
then writer is writing then
{ esperar }; { esperar };
{ leer } { escribir }
If writer(s) waiting If reader(s) or writer(s) waiting
then then
activar un writer si no activar todos readers
se leen otros readers o activar un writer
forever; forever;
Parend
Lector(es) Escritor(es)

Figura 9.15 Esquema de solución para lectores/escritores sin prioridad de escritores.

9.5.3 La cena de los filósofos


Cinco filósofos están reunidos alrededor de una mesa ponderando algunos temas filosóficos.
Frente a cada filósofo se mantiene un plato de espagueti y se coloca un tenedor entre cada par de
filósofos (véase la figura 9.16). Para comer, un filósofo debe recoger los dos tenedores colocados
entre él y sus vecinos inmediatos de cada lado, pero sólo un tenedor a la vez. El problema es
el diseño de procesos para representar a los filósofos, de tal modo que cada uno pueda comer
cuando tenga hambre, y ninguno se muera de hambre.
La condición de corrección en el sistema de la cena de los filósofos es que un filósofo
hambriento no deberá enfrentarse a esperas indefinidas cuando decide comer. El reto es diseñar
una solución que no sufra de bloqueos mutuos, donde los procesos se bloquean, esperando entre
sí, ni bloqueos en vivo, donde los procesos no están bloqueados, pero se postergan uno al otro
en forma indefinida. Considere el esquema de un proceso de filósofos Pi como lo muestra la
figura 9.17, donde se han omitido los detalles de la sincronización de procesos. Esta solución es
propensa a crear un bloqueo mutuo porque si todos los filósofos levantan su tenedor simultánea-
mente, ¡ninguno podrá levantar el tenedor correcto! La misma también contiene condiciones de

11 MAQ. CAP. 09(F0694).indd 419 8/10/07 1:05:44 AM


420 CAPÍTULO 9 Sincronización de procesos

F F

F F

Figura 9.16 La cena de los filósofos.

ejecución, porque puede ser que los vecinos peleen por un tenedor compartido. Podemos evitar
los bloqueos mutuos mediante la modificación del proceso de los filósofos, de tal forma que si
el tenedor a la derecha no está disponible, el filósofo posterga a su vecino izquierdo, bajando el
tenedor de la izquierda y repitiendo el intento de tomar los tenedores en un momento posterior.
Sin embargo, este planteamiento sufre de bloqueos en vivo porque la misma situación podrá
repetirse.

repetir
si el tenedor izquierdo no está disponible
entonces
block (Pi );
levantar el tenedor izquierdo;
si el tenedor derecho no está disponible
entonces
block (Pi );
levantar el tenedor derecho
{ comer }
si el vecino izquierdo está esperando su tenedor derecho
entonces
actívate (vecino izquierdo);
si el vecino derecho está esperando su tenedor izquierdo
entonces
actívate (vecino derecho);
{ pensar }
para siempre

Figura 9.17 Esquema de un proceso de filósofos Pi.

Un esquema mejorado para el problema de la cena de los filósofos se propone en la figura


9.18. Un filósofo verifica la disponibilidad de tenedores en una SC y también recoge los tenedo-
res en la SC. Por tanto, no pueden surgir condiciones de ejecución. Este ordenamiento asegura
que por lo menos algún(os) filósofo(s) pueda(n) comer en algún momento dado, y no puede
surgir un bloqueo mutuo. Un filósofo que no puede tener ambos tenedores al mismo tiempo se

11 MAQ. CAP. 09(F0694).indd 420 8/10/07 1:05:44 AM


9.6 Estructura de sistemas concurrentes 421

bloquea a sí mismo. Sin embargo, esto no evita las esperas activas porque el filósofo es activado
cuando uno de sus vecinos baja un tenedor compartido, y por tanto tiene que verificar nuevamen-
te la disponibilidad de tenedores. Esto es el propósito del bucle mientras. Algunas soluciones
innovadoras para el problema de la cena de los filósofos previenen los bloqueos mutuos sin es-
peras activas (véase el problema 20 en el ejercicio 9). La prevención de interbloqueos se discute
en el capítulo 11.

repetir
successful := false;
mientras (no successful)
si ambos tenedores están disponibles, entonces
levantar los tenedores uno a la vez;
successful := true;
si successful = false
entonces
block (Pi );
{ comer }
bajar ambos tenedores;
si el vecino izquierdo está esperando su tenedor derecho
entonces
actívate (vecino izquierdo);
si el vecino derecho está esperando su tenedor izquierdo
entonces
actívate (vecino derecho);
{ pensar }
para siempre

Figura 9.18 Un esquema mejorado del proceso de los filósofos.

9.6 ESTRUCTURA DE SISTEMAS CONCURRENTES

Un sistema concurrente es aquel que contiene procesos concurrentes; tiene tres componentes
clave:

• Datos compartidos.
• Operaciones con datos compartidos.
• Procesos.
Los datos compartidos pueden ser de dos tipos: datos usados y manipulados por procesos
y datos definidos y usados para la sincronización entre procesos. Una operación es una unidad
conveniente de código; normalmente, es un procedimiento en un lenguaje de programación que
manipula datos compartidos.
Una operación de sincronización es aquélla con datos de sincronización. La semántica de
las operaciones de sincronización determina la facilidad, complejidad lógica y confiabilidad
de la implementación de un sistema concurrente. En las siguientes secciones introduciremos
características de lenguaje de programación para la sincronización y analizaremos la semántica

11 MAQ. CAP. 09(F0694).indd 421 8/10/07 1:05:44 AM


422 CAPÍTULO 9 Sincronización de procesos

de las operaciones de sincronización que ellas ofrecen. También ilustraremos su uso en sistemas
concurrentes con la ayuda de instantáneas del sistema, tomadas en diferentes momentos.

Instantánea de un sistema concurrente Una instantánea de un sistema concurrente es


una vista (fotografía) del sistema en un momento específico. Ésta muestra las relaciones entre
datos compartidos, operaciones y procesos en ese momento. Usamos las convenciones pictóri-
cas señaladas en la figura 9.19 para describir una instantánea. Un proceso se muestra como un
círculo. Un círculo con una cruz adentro indica un proceso bloqueado. Un ítem de dato es repre-
sentado por un recuadro rectangular. El valor del ítem de datos, si se conoce, aparece dentro del
recuadro. Una forma ovalada que encierra un ítem de dato indica que éste es compartido.

Pi : Proceso Pi d

5 : Datos
Pi : Proceso compartidos d
bloqueado Pi
d OP1
··· : Cola de procesos Pi
bloqueados 2 : Proceso Pi ejecutando OP1
en datos compartidos d
d OP2
25 : Datos d
d OP1
d OP1 : Operaciones mutuamente
8 exclusivas
37 : Operaciones
en d
OP2 OP2
Figura 9.19 Convenciones pictóricas para instantáneas de sistemas concurrentes.

Las operaciones con datos son representadas como conectores o enchufes (sockets) unidos
a los datos. Una línea interrumpida conecta a un proceso con una operación con datos si el pro-
ceso está ocupado en ese momento con la ejecución de la operación. Hemos usado un recuadro
rectangular de líneas punteadas para encerrar el código que se ejecuta como una sección crítica.
Extendemos esta convención a operaciones en datos. Por tanto, operaciones mutuamente ex-
clusivas en datos están encerradas en un recuadro rectangular de líneas punteadas. Una fila de
procesos bloqueados está asociada con el recuadro de líneas punteadas para indicar los procesos
en espera de ejecución de una de las operaciones.
La ejecución de un sistema concurrente es representada por una serie de instantáneas.

Ejemplo 9.2 Considere el sistema de la figura 9.3, donde el proceso Pi realiza la acción ai sólo
después de que el proceso Pj ejecuta la acción aj. Supongamos que las operaciones ai y aj están
operando en unos ítems de datos X y Y, respectivamente. Deje que el sistema sea implementado
usando las operaciones check_aj y post_aj de la figura 9.6. Este sistema comprende los siguientes
componentes:
Datos compartidos : Variables booleanas operation_aj_performed y pi_
blocked, ambas inicializadas para false, y los ítems
de datos X y Y.
Operaciones con datos de aplicación : Operaciones ai y aj.

11 MAQ. CAP. 09(F0694).indd 422 8/10/07 1:05:44 AM


9.7 El planteamiento algorítmico para la implementación de secciones críticas 423

Operaciones de sincronización : Operaciones check_aj y post_aj.


Procesos : Procesos Pi y P j .

ai ai ai Pi
X X X

aj Pj aj aj
Y Y Y

check aj Pi check aj Pi check aj


pi blocked F T F
operation F F F
aj performed post aj post aj post aj
Pj Pj
a) b) c)

Figura 9.20 Instantáneas del sistema para el ejemplo 9.2.

La figura 9.20 muestra unas cuantas instantáneas de este sistema. T y F indican los valores
true y false, respectivamente. Las operaciones check_aj y post_aj usan las variables booleanas ope-
ration_aj_performed y pi_blocked. Éstas son operaciones indivisibles, por lo que resultan mutua-
mente exclusivas. Por consiguiente, están encerradas en un recuadro de líneas punteadas. La figura
9.20a) muestra la situación cuando el proceso Pj está ocupado con la ejecución de la operación aj y
el proceso Pi quiere ejecutar la operación ai; entonces llama a la operación check_aj. La operación
check_aj se da cuenta de que operation_aj_performed es false, y entonces fija pi_blocked en true,
bloquea el proceso Pi y sale. Cuando Pj termina la ejecución de la operación aj, llama a la operación
post_aj (véase la figura 9.20b)). Esta operación se da cuenta de que pi_blocked es true, y entonces
fija pi_blocked en false y activa el proceso Pi. El proceso Pi ahora ejecuta la operación ai (véase
la figura 9.20c)).

9.7 EL PLANTEAMIENTO ALGORÍTMICO PARA


LA IMPLEMENTACIÓN DE SECCIONES CRÍTICAS

El planteamiento algorítmico para la sincronización de procesos no usa ninguna ayuda de la


arquitectura de la computadora o del kernel SO. En su lugar emplea un ordenamiento de con-
diciones lógicas para cumplir con los requerimientos de sincronización deseados. La sección
crítica es la clave para la sincronización de procesos en este enfoque porque es adecuada para
la sincronización de accesos a datos (véase la sección 9.2) y también puede ser usada a fin de
realizar operaciones indivisibles que se requieren para la sincronización de controles.
Todos los sistemas que usan el planteamiento algorítmico para la implementación de SC
tienen algunas características y debilidades comunes. Un proceso que desea usar una SC verifica
unas cuantas condiciones para decidir si puede entrar en la SC. Si no puede hacerlo, verifica estas
condiciones de manera repetida en una espera activa. Esta espera es un derroche inevitable por-
que una implementación algorítmica de la SC no usa ningún servicio de kernel. La complejidad

11 MAQ. CAP. 09(F0694).indd 423 8/10/07 1:05:45 AM


424 CAPÍTULO 9 Sincronización de procesos

lógica del planteamiento algorítmico también es alta. Lo es aún más cuando la sincronización
involucra a más de dos procesos.
Señalamos a un algoritmo para la implementación de SC como un pseudocódigo con las
siguientes características:

1. La estructura de control Parbegin–Parend se usa para encerrar el código que se debe-


rá ejecutar en paralelo. Esta estructura de control tiene la sintaxis Parbegin <lista de
sentencias> Parend. Si <lista de sentencias> contiene n instrucciones, la ejecución
de la estructura de control Parbegin–Parend crea n procesos, y cada uno consiste en la
ejecución de una instrucción en <lista de sentencias>. Por ejemplo, Parbegin S1, S2, S3,
S4 Parend inicia cuatro procesos que ejecutan S1, S2, S3 y S4, respectivamente.
Las facilidades de agrupamiento de instrucciones como begin–end pueden usarse si
un proceso debe consistir en un bloque de código en lugar de en una sola instrucción. Por
comodidad visual, representamos de la siguiente manera procesos concurrentes creados
en una estructura de control Parbegin–Parend:

Parbegin
S11 S21 Sn1

S1m S2m Snm


Parend
proceso P1 proceso P2 proceso Pn

donde las instrucciones S11 · · · S1m forman el código del proceso P1, etcétera.
2. Las instrucciones de variables compartidas se colocan antes de un Parbegin.
3. Las instrucciones de variables locales se colocan al principio de un proceso.
4. Los comentarios están encerrados entre llaves ‘{ }’.
5. El sangrado se usa para mostrar el anidamiento de las estructuras de control.

Empezamos por la discusión de realizaciones de SC para ser usadas por dos procesos. Pos-
teriormente ampliamos algunos de estos sistemas para ser usada por n procesos.

9.7.1 Dos algoritmos de proceso

Algoritmo 9.1 Primer intento


var turn : 1 2;
begin
turn := 1;
Parbegin
repeat repeat
while turn = 2 while turn = 1
do { nada }; do { nada };
{ Sección crítica} { Sección crítica }

11 MAQ. CAP. 09(F0694).indd 424 8/10/07 1:05:46 AM


9.7 El planteamiento algorítmico para la implementación de secciones críticas 425

turn := 2; turn := 1;
{ Resto del { Resto del
ciclo } ciclo }
para siempre; para siempre;
Parend
end.
Proceso P1 Proceso P2

La variable turn es una variable compartida. La notación 1 .. 2 en su declaración indica


que toma valores en el intervalo 1-2, es decir, su valor es 1 o 2. Se inicializa 1 antes de que
los procesos P1 y P2 sean creados. Cada proceso contiene una SC para algunos datos compar-
tidos ds. La variable compartida turn se usa para indicar cuál es el proceso siguiente que puede
entrar en su SC. Supongamos que el proceso P1 desea entrar en su SC. Si turn  1, P1 pue-
de entrar inmediatamente. Después de salir de su SC, fija turn en 2, así que P2 ya puede entrar
en su SC. Si P1 se da cuenta de que turn  2 cuando quiere entrar en su SC, esperará en el bucle
while hasta que P2 salga de su SC y ejecute la asignación turn : 1. De este modo se cumple la
condición de corrección. No obstante, los procesos podrán encontrar una espera activa antes de
obtener la entrada a la SC.
El uso de la variable compartida turn causa un problema. Supongamos que el proceso P1
esté en su SC y el proceso P2 esté en el resto de su ciclo. Si P1 sale de su SC, termina el resto
de su ciclo y desea entrar una vez más en su SC, encontrará una espera activa hasta que P2 use
su SC. Esta condición no viola la condición de espera acotada, puesto que P1 tiene que esperar
hasta que P2 pase a través de su SC exactamente una vez. Sin embargo, la condición de progreso
es violada porque P1 es actualmente el único proceso interesado en usar su SC, pero es incapaz
de hacerlo. El algoritmo 9.2 trata de eliminar ese problema.

Algoritmo 9.2 Segundo intento

var c1 , c2 : 0 .. 1;
begin
c1 := 1;
c2 := 1;
Parbegin
repeat repeat
while c2 = 0 while c1 = 0
do { nada }; do { nada };
c1 := 0; c2 := 0;
{ Sección crítica } { Sección crítica }
c1 := 1; c2 := 1;
{ Resto del { Resto del
ciclo } ciclo }
para siempre; para siempre;
Parend
end.
Proceso P1 Proceso P2

11 MAQ. CAP. 09(F0694).indd 425 8/10/07 1:05:46 AM


426 CAPÍTULO 9 Sincronización de procesos

La variable turn del algoritmo 9.1 ha sido reemplazada por las dos variables compartidas
c1 y c2. Éstas pueden considerarse como indicadores de estatus para los procesos P1 y P2, res-
pectivamente. P1 fija a c1 en 0 mientras entre en su SC, y lo vuelve a fijar en 1 después de salir
de su SC. De este modo, c1  0 indica que P1 está en su SC, y c1  1 indica que no lo está. El
proceso P2 revisa el valor de c1 para decidir si ya puede entrar en su SC. Esta revisión elimina
la violación de progreso del algoritmo 9.1 porque los procesos no están forzados a hacer turnos
usando sus SC.
El algoritmo 9.2 viola la condición de exclusión mutua cuando ambos procesos tratan de
entrar en sus SC al mismo tiempo. Tanto c1 como c2 serán 1 (puesto que ninguno de los procesos
está en su SC), así que ambos procesos entrarán en sus SC. Para evitar este problema, se podrían
intercambiar las instrucciones while c2  0 do { nada }; y c1 :0 en el proceso P1. (Del mismo
modo se podrán intercambiar en el proceso P2 while c1  0 do { nada } y c2 :0.) De esta forma,
c1 será fijado a cero antes de que P1 verifique el valor de c2; por tanto, los dos procesos no pue-
den estar en sus SC al mismo tiempo. Sin embargo, si ambos intentan entrar en sus SC al mismo
tiempo, tanto c1 como c2 estarán en 0, así que los dos esperarán uno al otro indefinidamente. Esto
representará una situación de bloqueo mutuo.
Ambas situaciones, tanto la violación de corrección como la posibilidad de bloqueo mutuo,
se pueden eliminar si un proceso posterga al otro cuando se da cuenta de que éste también desea
entrar en su SC. Esto se puede lograr del siguiente modo: si P1 se da cuenta de que P2 también
trata de entrar en su SC, puede fijar c1 en 0. Esto permitirá que P2 entre en su SC. P1 puede es-
perar algún tiempo y tratar de entrar en su SC después de convertir c1 en 1. Sin embargo, este
planteamiento podrá llevar a una situación en la que ambos procesos se posterguen uno al otro
en forma indefinida. Esta situación se llama bloqueo en vivo.

Algoritmo de Dekker El algoritmo de Dekker combina las características útiles de los


algoritmos 9.1-9.2 a fin de evitar una situación de bloqueo en vivo. Se usa una variable llamada
turn para evitar bloqueos en vivo. Si ambos procesos tratan de entrar en sus SC, turn indica a
cuál de ellos se le permite entrar. Muchas otras características del algoritmo de Dekker son aná-
logas a las que se usan en los algoritmos que anteriormente se describieron.

Algoritmo 9.3 Algoritmo de Dekker


var turn : 1 2;
c1 , c2 : 0 1;
begin
c1 := 1;
c2 := 1;
turn := 1;
Parbegin
repeat repeat
c1 := 0; c2 := 0;
while c2 = 0 do while c1 = 0 do
if turn = 2 then if turn = 1 then
begin begin

11 MAQ. CAP. 09(F0694).indd 426 8/10/07 1:05:46 AM


9.7 El planteamiento algorítmico para la implementación de secciones críticas 427

c1 := 1; c2 := 1;
while turn = 2 while turn = 1
do { nada }; do { nada };
c1 := 0; c2 := 0;
end; end;
{ Sección crítica } { Sección crítica }
turn := 2; turn := 1;
c1 := 1; c2 := 1;
{ Resto del { Resto del
ciclo } ciclo }
para siempre; para siempre;
Parend
end.
Proceso P1 Proceso P2

Las variables c1 y c2 se usan como indicadores de estatus de los procesos. La instrucción


while c2  0 do en P1 verifica si es seguro que P1 entre en su SC. A fin de evitar el problema de
corrección del algoritmo 9.2, la instrucción c1 : 0 en P1 lo antecede. Si c2  1 cuando P1 quiere
entrar en una SC, P1 se salta el bucle while y entra en su SC inmediatamente. Si ambos proce-
sos tratan de entrar en sus SC al mismo tiempo, se usa el valor de turn para forzar que uno
de ellos postergue al otro. Por ejemplo, si P1 se da cuenta de que c2  0, sólo posterga a P2 si
turn  2, en caso contrario simplemente espera a que c2 se haga 1 antes de entrar en su SC. El
proceso P2, que también trata de entrar en su SC al mismo tiempo, es forzado a postergar a P1
sólo si turn  1. De esta manera, el algoritmo cumple con la exclusión mutua y también evita
condiciones de interbloqueos.

Algoritmo de Peterson El algoritmo de Peterson es más sencillo que el de Dekker. El de


Peterson usa un indicador de arreglo booleano que contiene un indicador para cada proceso.
Éstos son equivalentes al estatus c1, c2 de los algoritmos anteriores. Un proceso pone su indica-
dor en true cuando desea entrar en una SC y lo vuelve a poner en false cuando sale de ella. Se
supone que los procesos tienen los idenfificadores P0 y P1. Un identificador de proceso se usa
como un subíndice para acceder al indicador de estatus de un proceso en el indicador de array.
La variable turn sirve para evitar bloqueos vivos, pero se usa en forma diferente que en el algo-
ritmo de Dekker.

Algoritmo 9.4 Algoritmo de Peterson


var flag : array [0 1] of boolean;
turn : 0 1;
begin
flag[0] := false;
flag[1] := false;
Parbegin
repeat repeat
flag[0] := true; flag[1] := true;
turn := 1; turn := 0;

11 MAQ. CAP. 09(F0694).indd 427 8/10/07 1:05:46 AM


428 CAPÍTULO 9 Sincronización de procesos

while flag[1] and turn = 1 while flag[0] and turn = 0


do {nothing}; do {nothing};
{ Sección crítica } { Sección crítica }
flag[0] : = false; flag[1] : = false;
{ Resto del { Resto del
ciclo } ciclo }
forever; forever;
Parend
end.
Proceso P0 Proceso P1

Un proceso que desea entrar en una SC empieza postergando a otro proceso y fijando turn
para que apunte a este otro. Sin embargo, procede y entra en su SC si el otro proceso no está inte-
resado en usar la suya. El valor de turn decide qué proceso podrá entrar en su SC si ambos tratan
de entrar en sus SC al mismo tiempo. Considere como ejemplo el proceso P0. Éste fija flag[0]
en true y turn en 1 cuando desea entrar en su SC. Sin embargo, si el proceso P2 no está intere-
sado en usar su SC, flag[1] sería falso, y por tanto P0 sale del bucle while para entrar directa-
mente en su SC. Si P1 también está interesado en entrar en su SC, flag[1] es true. En este caso el
valor de turn decide cuál de los procesos puede entrar en su SC.
Es interesante considerar la operación del algoritmo de Peterson para diferentes velocidades
relativas de P0 y P1. Considere la situación cuando tanto P0 como P1 desean usar sus SC y P0 está
ligeramente adelante de P1. Si ambos procesos se ejecutan con la misma velocidad, P0 entrará en
su SC delante de P1 porque P1 habrá cambiado turn a 0 al tiempo que P1 alcanza la instrucción
while. P1 ahora espera la instrucción while hasta que P0 sale de CS. Sin embargo, si P0 es más
lento que P1 habrá cambiado turn a 1 un tiempo después P1 habrá cambiado a 0, al tiempo que
P0 alcanza la instrucción while y P1 entra a su CS.

9.7.1.1 Algoritmos de n procesos

Muchos cambios se hacen necesarios en los algoritmos de dos procesos si se han de desarrollar
más de dos procesos. Se tiene que expandir la cadena de indicadores de estatus para que pueda
contener n elementos, donde n es el número de procesos. Las revisiones para determinar si
algún otro proceso desea entrar en la SC se vuelven más complejas, al igual que los arreglos
para evitar la posibilidad de un bloqueo en vivo. Por ejemplo, en la implementación de SC de
2 procesos usando el algoritmo de Dekker, un proceso P1 posterga a otro fijando a turn para
que apunte al otro proceso. Esto se tendrá que hacer de modo diferente en un algoritmo de n
procesos.
Un problema mayor con realizaciones algorítmicas de SC de n procesos es que cada uno
de ellos tiene que estar consciente de la cantidad de procesos que están usando una SC para el
mismo ítem de dato. El código de cada proceso tiene que cambiar conforme cambia el tamaño de
la cadena de arrays. Cada proceso también tendrá que conocer los identificadores de otros proce-
sos. Podemos ver estos problemas en el algoritmo de Eisenberg y McGuire [1972], que amplía
la solución de dos procesos del algoritmo de Dekker para formar una solución de n procesos, y
también en el algoritmo Bakery de Lamport.

11 MAQ. CAP. 09(F0694).indd 428 8/10/07 1:05:47 AM


9.7 El planteamiento algorítmico para la implementación de secciones críticas 429

Algoritmo 9.5 Un algoritmo de n procesos


const n= ;
var flag : array [0..n – 1] of (idle, want-in, in-CS);
turn : 0 n – 1;
begin
for j := 0 to n – 1 do
flag[ j] := idle;
Parbegin
process Pi :
repeat
repeat
flag[i] := want-in;
j := turn;
while j = i
do if flag[ j] = idle
then j := turn { Loop here! }
else j := j + 1 mod n;
flag[i] := in-CS;
j := 0;
while ( j < n) and ( j = i or flag[ j] = in-CS)
do j := j + 1;
until ( j ≥ n) and (turn = i or flag[turn] = idle);
turn := i;
{ Sección crítica }
j := turn +1 mod n;
while (flag[ j] = idle) do j := j + 1 mod n;
turn := j;
flag[i] := idle;
{ Resto del ciclo }
forever
process Pk :
Parend
end.

Todavía se usa la variable turn para indicar qué proceso será el siguiente que entrará en su
SC. Cada uno tiene un indicador de estatus de 3 vías que toma los valores idle, want_in e in_CS.
El indicador tiene el valor idle cuando un proceso está en el resto de su ciclo. Un proceso cam-
bia el indicador a want_in cada vez que desea entrar en una SC. Después realiza unas cuantas
revisiones para decidir si podrá cambiar el indicador a in_CS. Revisa los indicadores de otros
procesos en un orden que llamamos el orden de módulos. Éste es Pturn, Pturn1, Pn 1, P0, P1, . . .
Pturn  1. En el primer bucle while el proceso verifica si algún proceso adelante de él en el orden
de módulos quiere usar su SC. Si éste no es el caso, cambia su indicador a in_CS.

11 MAQ. CAP. 09(F0694).indd 429 8/10/07 1:05:47 AM


430 CAPÍTULO 9 Sincronización de procesos

Puesto que muchos procesos posiblemente hagan esta revisión en forma concurrente, más
de uno podrá llegar simultáneamente a la misma conclusión. Por tanto, se realiza otra revisión
para asegurar la corrección. El segundo bucle while verifica si algún otro proceso ha cambiado
su indicador a in_CS. Si éste es el caso, el proceso vuelve a cambiar su indicador a want_in y
repite todas las revisiones. Todos los demás procesos que habían cambiado sus indicadores a
in_CS también vuelven a cambiar a want_in y repiten las revisiones. Estos procesos no se volve-
rán a disputar la entrada a una SC porque todos han cambiado sus indicadores a want_in y, por
ende, sólo uno de ellos podrá pasar el primer bucle while. Esta característica evita la condición
de bloqueo en vivo. El proceso anterior en el orden de módulos de Pturn arribará y podrá entrar
en su SC delante de otros procesos.
Esta solución contiene una cierta forma injusta, puesto que los procesos no entran en sus SC
en el orden en el que solicitan la entrada. Esta injusticia queda eliminada en el algoritmo Bakery
de Lamport (1974).

Algoritmo Bakery Cuando un proceso desea entrar en una SC, elige una señal en la que el
número contenido en ella es mayor que cualquier número que se haya expedido anteriormente.
choosing es un array de indicadores booleanas. choosing[i] se usa para indicar si el proceso
Pi está actualmente ocupado en la selección de una señal. number[i] contiene el número en la
señal elegida por el proceso Pi. number[i]  0 si Pi no ha elegido una señal desde la última vez
que entró en la SC. Los procesos entran en la SC en el orden que indican los números en sus
señales.

Algoritmo 9.6 Algoritmo Bakery

const n= ;
var choosing : array [0 n – 1] of boolean;
number : array [0 n – 1] of integer;
begin
for j := 0 to n – 1 do
choosing[ j] := false;
number[ j] := 0;
Parbegin
process Pi :
repeat
choosing[i] := true;
number[i] := max (number[0], number[n – 1])+1;
choosing[i] := false;
for j := 0 to n – 1 do
begin
while choosing[ j] do { nada };
while number[ j] = 0 and (number[ j], j) < (number[i],i)
do { nada };
end;

11 MAQ. CAP. 09(F0694).indd 430 8/10/07 1:05:47 AM


9.8 Semáforos 431

{ Sección crítica }
number[i] := 0;
{ Resto del ciclo }
forever;
process Pj :
Parend
end.

Un proceso que desea entrar en una SC debe postergar a otro que tenga una señal menor.
Esta regla no puede garantizar la exclusión mutua si dos o más procesos eligen sus señales en
forma concurrente y si obtienen el mismo número. Tal problema se resuelve formando un par
(number[i], i) para cada proceso Pi que está interesado en entrar en una SC. Un proceso entra si su
par precede a todos los demás pares, donde la relación de preceder  está definida como sigue:

(number[ j], j)  (number[i], i) if


number[ j]  number[i], or
number[ j]  number[i] and j  i.

Si muchos procesos obtienen el mismo número, el que tenga el identificador más pequeño entra
primero en su SC. En todos los demás casos los procesos entran en las SC en el orden en el que
levantan sus solicitudes.

9.8 SEMÁFOROS

Como se mencionó en la sección 9.2.3, se desarrollaron primitivas de sincronización para supe-


rar las limitaciones de las realizaciones algorítmicas. Las primitivas son operaciones sencillas
que se pueden usar para realizar tanto la exclusión mutua como la sincronización de controles.
Un semáforo es un tipo especial de datos de sincronización que sólo puede ser usado mediante
primitivas de sincronización específicas. El semáforo asegura la ausencia de condiciones de
ejecución.

Definición 9.3 (Semáforo) Un semáforo es una variable entera compartida con valores no
negativos que sólo pueden estar sujetos a las siguientes operaciones:
1. Inicialización (especificada como parte de su declaración).
2. Las operaciones indivisibles wait y signal.

Originalmente, Dijkstra llamó a las operaciones wait y signal en un semáforo operaciones


P y V, respectivamente. La figura 9.21 muestra la semántica de las operaciones wait y signal.
Cuando un proceso ejecuta una operación wait en un semáforo, ésta verifica si el valor del se-
máforo es  0. De ser así, reduce su valor y deja que el proceso siga su ejecución; de no ser
así, bloquea el proceso en el semáforo. Una operación signal en un semáforo activa un proceso
bloqueado en éste, si es que existe, o incrementa el valor del semáforo en 1. La indivisibilidad
de las operaciones wait y signal queda asegurada por el lenguaje de programación o por el sis-
tema operativo que lo realiza. Ello asegura que no puedan surgir condiciones de ejecución en un
semáforo (véase la sección 9.8.4).

11 MAQ. CAP. 09(F0694).indd 431 8/10/07 1:05:47 AM


432 CAPÍTULO 9 Sincronización de procesos

operation wait(S)
begin
if S > 0
then S := S–1;
else bloquear el proceso en S;
end;
operation signal(S)
begin
if algunos procesos están bloqueados en S
then activar un proceso bloqueado;
else S := S+1;
end

Figura 9.21 La semántica de operaciones wait y signal en un semáforo.

Los procesos usan operaciones wait y signal a fin de sincronizar su ejecución con respecto
uno del otro. El valor inicial de un semáforo determina cuántos procesos podrán pasar por la ope-
ración wait. Un proceso que no puede pasar por una operación wait es bloqueado en el semáforo.
Esta característica evita esperas activas.
La sección 9.8.1 describe los usos de semáforos. En las secciones 9.8.2 y 9.8.3 se analiza
la implementación de problemas de productores/consumidores y lectores/escritores, usando se-
máforos.

9.8.1 Usos de semáforos en sistemas concurrentes

La tabla 9.4 resume tres usos de semáforos empleados en la implementación de sistemas concu-
rrentes. La exclusión mutua es útil en la implementación de secciones críticas. La concurrencia
acotada es importante cuando un recurso puede ser compartido por un total de hasta c procesos,
donde c es una constante  1. La señalización es útil en la sincronización. En la presente sección
analizaremos detalles de estos usos.

9.8.1.1 Exclusión mutua

La figura 9.22 muestra la implementación de una SC en los procesos Pi y Pj usando un semá-


foro llamado sem_CS. sem_CS es inicializado en 1. Cada proceso ejecuta una operación wait
en él antes de entrar en su SC, y una operación signal después de salir de su SC. El primer
proceso que ejecuta wait(sem_CS) se da cuenta de que el valor de sem_CS es  0, por lo
que reduce sem_CS en 1 y procede a entrar en su SC. Cuando el segundo proceso ejecuta
wait(sem_CS), el valor de sem_CS es 0, y por tanto el proceso es bloqueado en sem_CS.
Se activa cuando el primer proceso ejecuta signal(sem_CS) y entra en su SC. Si ningún pro-
ceso está bloqueado en sem_CS cuando se ejecuta una operación signal(sem_CS), el valor de
sem_CS se convierte en 1. Esto permite que un proceso que en el futuro ejecute un wait entre
inmediatamente en su SC.
La figura 9.23 muestra instantáneas tomadas durante la operación del sistema de la figura
9.22. Las operaciones wait y signal en sem_CS están encerradas en un recuadro rectangular de

11 MAQ. CAP. 09(F0694).indd 432 8/10/07 1:05:48 AM


9.8 Semáforos 433

Tabla 9.4 Usos de semáforos

Exclusión La exclusión mutua puede ser implementada usando un semáforo que es


mutua inicializado en 1. Un proceso ejecuta una operación wait en el semáforo
antes de entrar en una SC, y ejecuta una operación signal cuando sale de
ella. Un tipo especial de semáforo llamado semáforo binario simplifica
la implementación de SC aún más.
Concurrencia La concurrencia acotada implica que una función puede ser ejecutada
acotada concurrentemente por n procesos, 1  n  c, donde c es una constante.
Un semáforo inicializado a c puede ser usado para realizar la concurren-
cia acotada.
Señalización La señalización se usa cuando un proceso Pi desea realizar una acción
ai sólo después de que el proceso Pj haya realizado una acción aj. Se
realiza usando un semáforo inicializado en 0. Pi ejecuta un wait en el se-
máforo antes de realizar la acción ai. Pj realiza un signal en el semáforo
después de realizar la acción aj. Este arreglo asegura que Pi ejecute ai
sólo después de que Pj ejecute aj.

var sem CS : semaphore := 1;


Parbegin
repeat repeat
wait(sem CS); wait(sem CS);
{ Sección crítica } { Sección crítica }
signal(sem CS); signal(sem CS);
{ Resto del ciclo } { Resto del ciclo }
forever; forever;
Parend
end.
Proceso Pi Proceso Pj

Figura 9.22 Implementación de CS mediante semáforos.

líneas punteadas porque son mutuamente exclusivas (véanse las convenciones pictóricas de la
figura 9.19). Supongamos que el proceso Pi ejecute wait(sem_CS). La figura 9.23a) ilustra
la situación existente al inicio de la operación wait de Pi. La figura 9.23b) muestra la situación
después de que Pi ha completado la operación wait y Pj ejecuta una operación wait. La ope-
ración wait(sem_CS) de Pi ha reducido el valor de sem_CS a 0, así que Pj es bloqueado en
la operación wait. La figura 9.23c) muestra la situación después de que el proceso Pi realiza
una operación signal que activa al proceso Pj. El valor de sem_CS permanece 0. El proceso Pj
ejecuta una operación signal cuando sale de su SC. Puesto que ningún proceso está actualmente
bloqueado en sem_CS, la operación signal simplemente da como resultado un incremento del
valor de sem_CS en 1 (véase la figura 9.23d)).
Es interesante ver cuáles de las propiedades de realizaciones de SC mencionadas en la tabla
9.2 son satisfechas por la implementación de la figura 9.22. La implementación posee la propie-

11 MAQ. CAP. 09(F0694).indd 433 8/10/07 1:05:48 AM


434 CAPÍTULO 9 Sincronización de procesos

wait sem CS sem CS


Pi Pi
1 0
Pj Pj
signal
a) b)

sem CS sem CS
Pi Pi
0 1
Pj Pj
c) d)

Figura 9.23 Instantáneas del sistema concurrente de la figura 9.22.

dad de progreso porque un proceso que ejecuta la operación wait entra en su SC si ningún otro
se encuentra en su SC. Sin embargo, la propiedad de espera acotada no es válida porque el orden
en el que los procesos bloqueados son activados por operaciones signal no está definido en la
semántica de semáforos. Por consiguiente, un proceso bloqueado podrá morir de inanición si
otros procesos ejecutan operaciones wait y signal en forma repetida.
La exclusión mutua es una consecuencia del hecho de que sem_CS es inicializado en 1. Sin
embargo, las operaciones wait y signal son primitivas, así que no hay nada que pueda impedir
que un programa las use de manera arbitraria. Esto puede conducir a problemas de corrección.
Por ejemplo, el proceso Pi de la figura 9.22 erróneamente se podrá haber escrito como

repeat
signal(sem_CS);
{ Sección crítica }
signal(sem_CS);
{ Resto del ciclo }
forever

donde se ha usado un signal(sem_CS) en lugar de un wait(sem_CS) al entrar en su SC. Entonces


la SC no será correctamente implementada porque muchos procesos podrían entrar en sus SC al
mismo tiempo. En otro ejemplo, el uso de wait(sem_CS) en lugar de un signal(sem_CS) después
de una SC puede llevar a bloqueos mutuos. La posibilidad de tales usos equivocados lleva a una
baja confiabilidad y a un alto riesgo en el uso de semáforos.

Semáforos binarios Un semáforo binario es una forma especial de semáforo usada para
realizar la exclusión mutua. Por tanto, frecuentemente se le llama mutex. Este tipo de semáforo
es inicializado en 1 y sólo toma los valores 0 y 1 durante la ejecución de un programa. Las opera-
ciones wait y signal en un semáforo binario son ligeramente diferentes de las que se muestran en
la figura 9.21; las instrucciones S : S  1 y S : S1 son reemplazadas por las instrucciones
S :0 y S : 1, respectivamente.

11 MAQ. CAP. 09(F0694).indd 434 8/10/07 1:05:48 AM


9.8 Semáforos 435

9.8.1.2 Concurrencia acotada


Usamos el término concurrencia acotada para referirnos a la situación en la que hasta c proce-
sos pueden ejecutar en forma concurrente una operación opi, donde c es una constante  1. La
concurrencia acotada es implementada inicializando un semáforo sem_c en c. Todo proceso que
desea ejecutar opi ejecuta un wait(sem_c) antes de ejecutar opi, y un signal(sem_c) después de
ejecutarlo. Por la semántica de las operaciones wait y signal queda claro que hasta c procesos
pueden concurrentemente ejecutar opi. Los semáforos que se usan para realizar la concurrencia
acotada se llaman semáforos de conteo.
La figura 9.24 ilustra cómo una serie de procesos concurrentes comparte cinco impresoras.

var printers : semaphore := 5;


Parbegin
repeat repeat
wait(printers); wait(printers);
{ Usar una impresora } ··· { Usar una impresora }
signal(printers); signal(printers);
{ Resto del ciclo } { Resto del ciclo }
forever; forever;
Parend
end.
Proceso p1 ··· Proceso pn

Figura 9.24 Concurrencia acotada usando semáforos.

9.8.1.3 Señalización entre procesos


Considere los requerimientos de sincronización de los procesos Pi y Pj que se muestran en la
figura 9.4. Un semáforo se puede usar para lograr esta sincronización, como se muestra en
la figura 9.25. Aquí el proceso Pi ejecuta un wait(sync) antes de ejecutar la acción ai, y Pj ejecuta
un signal(sync) después de ejecutar la acción aj. El semáforo sync es inicializado en 0 y, por
tanto, Pi será bloqueado en wait(sync) si Pj no ha realizado ya un signal(sync). Procederá a eje-
cutar la acción ai sólo después de que el proceso Pj ejecute un signal. A diferencia de la solución
de la figura 9.4, no pueden surgir condiciones de ejecución porque las operaciones wait y signal
son indivisibles. El arreglo de señalización se puede usar repetidamente; no necesita restableci-
miento como en el arreglo de señalización de la figura 9.12.

9.8.2 Productores/consumidores usando semáforos

Como hemos discutido en la sección 9.5.1, el problema de productores/consumidores es un


problema de señalización. Después de consumir un registro de un buffer, un consumidor señala
a un productor que está esperando producir en el mismo buffer. De modo análogo, un productor
señala a un consumidor en espera. Por tanto, debemos realizar productores/consumidores usan-
do el arreglo de señalización que se muestra en la figura 9.25.
Por motivos de simplicidad, analizaremos primero la solución para el caso del buffer único
que se muestra en la figura 9.26. El área de memoria intermedia es representado por un array

11 MAQ. CAP. 09(F0694).indd 435 8/10/07 1:05:49 AM


436 CAPÍTULO 9 Sincronización de procesos

var sync : semaphore := 0;


Parbegin
··· ···
wait(sync); {Ejecuta la acción aj }
{Ejecuta la acción ai } signal(sync);
Parend
end.
Proceso Pi Proceso Pj

Figura 9.25 Señalización usando semáforos.

de buffers que contiene un solo elemento. Se declaran dos semáforos full y empty. Ellos se usan
para indicar el número de buffers llenos y vacíos, respectivamente. full es inicializado en 0 y
empty, en 1. Un productor ejecuta un wait(empty) antes de iniciar la acción de producir, y un
consumidor ejecuta un wait(full) antes de una acción de consumir.

type item = . . .;
var
full : Semaphore := 0; { Inicializaciones }
empty : Semaphore := 1;
buffer : array [0] of item;
begin
Parbegin
repeat repeat
wait(empty); wait(full);
buffer[0] := ...; x : buffer[0];
{ o sea, producir } { o sea, consumir }
signal(full); signal(empty);
{ Resto del ciclo } { Resto del ciclo }
forever; forever;
Parend
end.
Productor Consumidor

Figura 9.26 Productores/consumidores con un solo buffer.

Inicialmente un(os) consumidor(es) sería(n) bloqueado(s) en una acción de consumir, y sólo


un productor podría pasar por la operación wait(empty). Después de completar la acción de
producir, ejecuta signal(full). Esto habilita a un consumidor para entrar, ya sea inmediatamente
o en el futuro. Cuando un consumidor termina una acción de consumir, ejecuta una operación
signal(empty) que habilita a un productor para entrar y ejecutar una acción de producir. Esta
solución evita las esperas activas, puesto que se usan semáforos para comprobar si hay buffers
vacíos o llenos y, por ende, un proceso es bloqueado si no puede encontrar un buffer lleno
o vacío. La concurrencia total es 1; a veces ejecuta un productor y otras ocasiones ejecuta un
consumidor. El ejemplo 9.3 describe la operación de este programa.

11 MAQ. CAP. 09(F0694).indd 436 8/10/07 1:05:49 AM


9.8 Semáforos 437

Ejemplo 9.3 Un sistema de productores/consumidores de un solo buffer contiene un proceso único


de productores y un proceso único de consumidores. La figura 9.27a) muestra la situación inicial.
La figura 9.27b) muestra la situación cuando los procesos de productores y consumidores intentan
producir y consumir, respectivamente. El proceso de productores ha logrado pasar a su operación
wait en empty, puesto que empty fue inicializado en 1. El semáforo empty se vuelve 0 y el productor
empieza a producir en el buffer. El proceso de consumidores está bloqueado, puesto que full es 0.
Cuando el productor ejecuta un signal(full), se activa el proceso de consumidores que empieza a
consumir del buffer. La figura 9.27c) muestra esta situación.

buffer buffer buffer


Produce Productor Produce Productor Produce Productor

Consume Consume Consume


Consumidor Consumidor Consumidor

full full full


wait wait wait
0 0 0
signal signal signal

empty empty empty


wait wait wait
1 0 0
signal signal signal
a) b) c)

Figura 9.27 Instantáneas de productores/consumidores de un solo buffer usando semáforos.

La figura 9.28 muestra cómo se pueden usar semáforos para realizar una solución del pro-
blema de productores/consumidores de n buffers, n  1, que contiene un proceso de productores
y un proceso de consumidores. Esta solución es una simple extensión de la solución del buffer
único que se muestra en la figura 9.26. Los valores de los semáforos empty y full indican el
número de buffers vacíos y llenos, respectivamente. Se usan los punteros de buffers prod_ptr y
cons_ptr para asegurar que los buffers son producidos y consumidos en el orden FIFO. Un pro-
ductor incrementa a prod_ptr cada vez que produce un registro de información, y un consumidor
incrementa a cons_ptr cada ocasión que consume un registro de información. Un productor
y un consumidor pueden operar en forma concurrente mientras existan algunos buffers llenos y
vacíos en el sistema.
Es fácil verificar que esta solución realiza las condiciones del problema de buffers acotados
que se describe en la sección 9.5.1. Sin embargo, si existen muchos procesos de productores y
consumidores en el sistema, tenemos que proporcionar exclusión mutua entre productores para
evitar condiciones de ejecución en prod_ptr. En forma análoga se deberá proporcionar exclusión
mutua entre consumidores para evitar condiciones de ejecución en cons_ptr.

11 MAQ. CAP. 09(F0694).indd 437 8/10/07 1:05:49 AM


438 CAPÍTULO 9 Sincronización de procesos

const n = ... ;
type item = . . .;
var
buffer : array [0..n – 1] of item;
full : Semaphore := 0; { Inicializaciones }
empty : Semaphore := n;
prod ptr, cons ptr : integer;
begin
prod ptr := 0;
cons ptr := 0;
Parbegin
repeat repeat
wait(empty); wait(full);
buffer[prod ptr] := ...; x : buffer[cons ptr];
{ o sea, producir } { o sea, consumir }
prod ptr := prod ptr 1 mod n; cons ptr := cons ptr 1 mod n;
signal(full); signal(empty);
forever; forever;
Parend
end.
Productor Consumidor

Figura 9.28 Buffers acotados usando semáforos.

9.8.3 Lectores/escritores usando semáforos

Las características clave del problema de lectores/escritores se hacen evidentes en el esquema


de la figura 9.15. Se trata de las siguientes:

• Cualquier número de lectores puede leer en forma concurrente.


• Lectores y escritores deben esperar si un escritor está escribiendo. Cuando el escritor
sale, se deberán activar todos los lectores en espera o se deberá activar un escritor en
espera.
• Un escritor debe esperar si hay lectores que están leyendo. Se debe activar cuando el
último lector salga.

Implementamos estas características manteniendo la cuenta del número de lectores y escritores


que desean leer o escribir en algún momento dado. Se introducen los siguientes contadores para
este propósito:

runread conteo de lectores que están actualmente leyendo


totread conteo de lectores esperando para leer o leyendo concurrentemente
runwrite conteo de escritores que están actualmente escribiendo
totwrite conteo de escritores esperando para escribir o escribiendo concurrentemente

Los valores de estos contadores son incrementados y reducidos por los procesos en mo-
mentos adecuados. Por ejemplo, un proceso de lector incrementa totread cuando decide leer e

11 MAQ. CAP. 09(F0694).indd 438 8/10/07 1:05:50 AM


9.8 Semáforos 439

incrementa runread cuando en realidad inicia la lectura. El proceso decrementa tanto totread
como runread cuando termina la lectura. De este modo, totread runread indica cuántos lectores
están esperando iniciar la lectura. Igualmente, totwrite runwrite indica el número de escrito-
res esperando iniciar la escritura. Los valores de estos contadores se usan como sigue: un lector
tiene permiso de iniciar la lectura cuando runwrite  0, y un escritor tiene permiso de iniciar la
escritura cuando runread  0 y runwrite  0. El valor de totread se usa para activar a todos los
lectores en espera cuando un escritor termina la escritura (observe que runread  0 cuando un
escritor está escribiendo).

Parbegin
repeat repeat
if runwrite 0 if runread 0 or
then runwrite 0
{ esperar }; then { esperar };
{ leer } { escribir }
if runread 0 and if totread 0 or totwrite 0
totwrite 0 then
then activa totread lectores
activar a un escritor o activa a un escritor
forever; forever;
Parend
Lector(es) Escritor(es)

Figura 9.29 Esquema de solución refinada para lectores/escritores sin prioridad de lectores.

El esquema de la figura 9.15 se refina a fin de obtener la solución que se muestra en la figura
9.29. Los valores de los contadores son examinados dentro de secciones críticas. Se supone que
sus valores son incrementados o reducidos en otras secciones críticas en lugares adecuados. Esta
solución no usa secciones críticas explícitas para lectores o escritores. En vez de esto, son blo-
queados hasta que se les puede permitir el inicio de la lectura o de la escritura.
El bloqueo de lectores y escritores se parece al bloqueo de productores y consumidores
analizado en el problema de productores/consumidores, así que su mejor manejo es con el uso
de semáforos para la señalización. Introducimos dos semáforos llamados reading y writing. Un
proceso de lector ejecuta wait(reading) antes de empezar a leer. Esta acción bloquea el proceso
de lector si en ese momento no se cumplen las condiciones que permiten la lectura; si se cum-
plen, el lector puede pasar la operación wait y empezar a leer. Del mismo modo, un proceso de
escritor ejecuta un wait(writing) antes de escribir.
¿Quién deberá ejecutar operaciones signal para activar el proceso de lectores y escritores
bloqueados en las operaciones wait? Obviamente no se habían cumplido condiciones que rigie-
ran el inicio de lectura y escritura cuando los procesos de lectores o escritores fueron bloquea-
dos. Estas condiciones cambian cuando se modifica cualquiera de los valores de contadores, es
decir, cuando un lector termina la lectura o un escritor concluye la escritura. Por tanto, los pro-
cesos deben ejecutar operaciones signal adecuadas después de completar una operación de lec-
tura o escritura.

11 MAQ. CAP. 09(F0694).indd 439 8/10/07 1:05:50 AM


440 CAPÍTULO 9 Sincronización de procesos

Ahora vamos a ver los temas de implementación en detalle. A fin de evitar condiciones de
ejecución, todos los valores de contadores deberán ser examinados y manipulados dentro
de una SC. Usamos un semáforo binario llamado mutex para ese propósito. Cuando un lec-
tor desea iniciar la lectura, entra en una SC en mutex para verificar si runwrite  0. De ser así,
puede incrementar runread, salir de la SC e iniciar la lectura inmediatamente. De no serlo, debe
ejecutar wait(reading); sin embargo, ¡esto no se deberá hacer dentro de la SC en mutex debido
al riesgo de bloqueos mutuos!
Se emplea un planteamiento llamado autoplaneación para superar este problema. Un lector
siempre ejecuta un wait(reading) después de salir de una SC en mutex. Si se cumplen las con-
diciones que permiten el inicio de una operación de lectura cuando son examinados los valores
de contadores dentro de su SC, debe ejecutarse un signal(reading) por sí mismo. Este tipo de
lector pasará por la operación wait(reading) a la salida de la SC. Si no se cumpliesen las condi-
ciones que permiten el inicio de una operación de lectura, el lector será bloqueado en reading
debido a la operación wait. De igual modo, un escritor ejecutará un signal(writing) dentro de
su SC en mutex bajo la serie de condiciones correcta, y wait(writing), después de salir de la
SC. Lectores y escritores que son bloqueados en sus respectivas operaciones wait son activados
de la siguiente manera: cuando un lector termina la lectura, puede ejecutar un escritor si nin-
gún lector está activo y si un escritor está esperando. Cuando un escritor termina la escritura,
puede ejecutar operaciones signal para activar a todos los lectores en espera, o a un escritor en
espera.
La solución se ofrece en la figura 9.30. Cuando un escritor termina la escritura, despierta a
los lectores en espera, si existen; de no ser así, despierta a los escritores en espera. De tal modo
que este sistema es un sistema de lectores/escritores con preferencia de lectores.
La solución parece tener dos características redundantes (véase el problema 13). En primer
término, usa dos semáforos reading y writing, aunque sólo se debe controlar un recurso —los
datos compartidos. En segundo término, cada lector ejecuta una operación wait(reading), aunque
ésta es claramente redundante cuando los lectores ya están ocupados con la lectura. Sin embargo,
se necesitan ambas características para realizar un sistema de lectores/escritores con preferencia
de escritores (véase el problema 14).

9.8.4 Implementación de semáforos

La figura 9.31 muestra un esquema para realizar semáforos. Se define un tipo de semáforo. Éste
tiene campos para el valor de un semáforo, una lista que se usa para almacenar identificadores
de procesos bloqueados en el semáforo y una variable de bloqueo que se usa para asegurar la
indivisibilidad de las operaciones wait y signal en el mismo. Un programa concurrente declara
semáforos como variables del tipo de semáforo, y sus procesos invocan a los procedimientos
wait y signal para operar en ellos.
Los procedimientos wait y signal toman un semáforo sem como argumento. A fin de evitar
condiciones de ejecución durante el acceso al valor del semáforo, ambos procedimientos pri-
mero invocan a la función Close_lock para poner la variable de bloqueo sem.lock. Close_lock
usa una instrucción indivisible y una espera activa; sin embargo, las esperas activas son breves,
ya que las mismas operaciones wait y signal así lo son. Los procedimientos invocan a la función
Open_lock para restaurar el bloqueo después de completar su ejecución. Recuerde de la sec-
ción 9.22 que una espera activa podrá llevar a la inversión de prioridad en un SO usando la

11 MAQ. CAP. 09(F0694).indd 440 8/10/07 1:05:50 AM


9.8 Semáforos 441

var
totread, runread, totwrite, runwrite : integer;
reading, writing : semaphore := 0;
mutex : semaphore := 1;
begin
totread := 0;
runread := 0;
totwrite := 0;
runwrite := 0;
Parbegin
repeat repeat
wait(mutex); wait(mutex);
totread := totread 1; totwrite := totwrite 1;
if runwrite = 0 then if runread = 0 and runwrite = 0 then
runread := runread 1; runwrite := 1;
signal(reading); signal(writing);
signal(mutex); signal(mutex);
wait(reading); wait(writing);
{ Leer } { Escribir }
wait(mutex); wait(mutex);
runread := runread–1; runwrite := runwrite–1;
totread := totread–1; totwrite := totwrite–1;
if runread = 0 and while (runread<totread) do
totwrite > runwrite begin
then runread := runread 1;
runwrite := 1; signal(reading);
signal(writing); end;
signal(mutex); if runread = 0 and
forever; totwrite > runwrite then
runwrite := 1;
signal(writing);
signal(mutex);
forever;
Parend
end.
Lector(es) Escritor(es)

Figura 9.30 Lectores y escritores usando semáforos.

planificación basada en prioridad; suponemos que se usa un protocolo de herencia de prioridad


para evitar este problema. En un sistema de tiempo compartido, una espera activa puede causar
demoras en la sincronización, pero no provoca problemas más serios.

11 MAQ. CAP. 09(F0694).indd 441 8/10/07 1:05:51 AM


442 CAPÍTULO 9 Sincronización de procesos

Declaración tipo para Semáforo


type
semaphore = record
value : integer
list : ... { lista de procesos bloqueados }
end;

Procedimiento de biblioteca

procedure wait(sem)
if sem.value > 0
then sem.value := sem.value –1;
else
Adiciona id de los procesos de la lista de procesos bloqueados en sem;
block me();
end;
procedure signal(sem)
if algunos procesos son bloqueados en sem
then
proc id := id of a process blocked on sem;
activate this process(proc id);
else
sem.value := sem.value 1;
end;

Figura 9.31 Implementación de operaciones wait y signal en un semáforo.

El procedimiento wait verifica si el valor de sem es  0. De ser así, reduce su valor y regre-
sa. Si el valor es 0, el procedimiento wait agrega el identificador del proceso a la lista de procesos
bloqueados en sem y hace una llamada al sistema block_me con la variable de bloqueo como
parámetro. Esta llamada bloquea el proceso que invocó al procedimiento wait y también abre la
cerradura que recibió como parámetro. Observe que el procedimiento wait no podría haber eje-
cutado estas acciones por sí mismo; ¡surgirían condiciones de ejecución si hubiese una llamada
block_me antes de abrir el bloqueo!
El procedimiento signal verifica si algún proceso está bloqueado en sem. De ser así, selec-
ciona uno de estos procesos y lo activa haciendo la llamada al sistema activate. Si no hay pro-
cesos esperando sem, incrementa el valor de sem en 1. Conviene mantener la lista de procesos
bloqueados como una cola y activar el primer proceso bloqueado en una operación signal. Sin
embargo, la semántica de la operación signal no especifica el orden en que los procesos deberán
ser activados, así que una implementación podría elegir cualquier orden que deseara.
La operación wait tiene un índice muy bajo de fallas en la mayoría de los sistemas que usan
semáforos, es decir, procesos que ejecutan operaciones wait rara vez son bloqueados. Esta ca-
racterística se explota en algunos métodos de implementación de semáforos con la finalidad de
reducir la carga general. A continuación describiremos tres de estos métodos y realizaremos sus

11 MAQ. CAP. 09(F0694).indd 442 8/10/07 1:05:51 AM


9.9 Regiones críticas condicionadas 443

implicaciones de carga general. Recuerde que usamos el término proceso como genérico, tanto
para proceso como para hilos.

Implementación en el nivel del kernel El kernel realiza los procedimientos wait y signal
de la figura 9.31. Todos los procesos de un sistema pueden compartir un semáforo de nivel
kernel. Sin embargo, cada operación wait y signal da como resultado una llamada al sistema y
conlleva una alta carga general de uso de semáforos. En un OS de uniprocesador con un kernel
no interrumpible, no sería necesario usar una variable de bloqueo para eliminar condiciones de
ejecución, por lo que la carga general de esperas activas en la operación Close_lock puede ser
eliminada.

Implementación en el nivel del usuario Las operaciones wait y signal están codificadas
como procedimientos de biblioteca, los cuales están vinculados con un programa de aplicación,
de tal modo que procesos de la aplicación pueden compartir semáforos del nivel de usuarios.
Las llamadas block_me y activate en realidad son llamadas a procedimientos de biblioteca, los
cuales manejan el bloqueo y la activación de procesos propios hasta donde les es posible, y sólo
hacen llamadas al sistema cuando necesitan ayuda de parte del kernel. Este método de imple-
mentación convendría a hilos del nivel del usuario porque la biblioteca de hilos ya se encargaría
de bloqueos, activación y planificación de hilos. La biblioteca de hilos sólo haría una llamada al
sistema block_me cuando todos los hilos de un proceso estén bloqueados.

Implementación híbrida Las operaciones wait y signal nuevamente están codificadas


como procedimientos de biblioteca, y los procesos de una aplicación pueden compartir los se-
máforos híbridos. block_me y activate son llamadas al sistema proporcionadas por el kernel, y
las operaciones wait y signal sólo hacen estas llamadas cuando se tiene que bloquear y activar
procesos. En principio es posible realizar semáforos híbridos aun cuando este apoyo del kernel
no esté disponible. Por ejemplo, las llamadas al sistema block_me y activate pueden ser reempla-
zadas por llamadas al sistema para recibir y transmitir mensajes o señales. Sin embargo, la trans-
misión de mensajes está sujeta a la disponibilidad de espacio de buffers, y las señales pueden ser
ignoradas por procesos, así que lo mejor es usar una llamada al sistema block_me separada para
la implementación de semáforos.

9.9 REGIONES CRÍTICAS CONDICIONADAS

La región crítica condicionada (RCC) es una estructura de control en un lenguaje de programa-


ción de alto nivel. Ofrece dos características para la sincronización de procesos: proporciona la
exclusión mutua sobre accesos a datos compartidos, y permite que un proceso que ejecuta RCC
se bloquee a sí mismo hasta que una condición booleana especificada se vuelva true.
La figura 9.32 muestra un programa concurrente que usa el constructor RCC region x
do ... La variable x es declarada con el atributo shared. Se puede usar en cualquier proceso del
programa. Sin embargo, sólo se debe emplear con el RCC, es decir, dentro de un constructor
region x do .. El compilador marca como error todos los usos de x fuera de una RCC. Una RCC
es implementada como una sección crítica en la variable x. Esta característica asegura que los
accesos a datos compartidos sean mutuamente exclusivos. A la variable x se le llama variable de
control RCC.

11 MAQ. CAP. 09(F0694).indd 443 8/10/07 1:05:51 AM


444 CAPÍTULO 9 Sincronización de procesos

var x : shared <type> := < initial value>;


begin
Parbegin
repeat { proceso Pi }
region x do
begin
...
await (B); { Acceso a la variable compartida x }
...
end;
{ Resto del ciclo }
forever
... { otros procesos }
Parend
end.

Figura 9.32 Programa de muestra usando una región crítica condicionada.

Un proceso que ejecuta la RCC entra en una SC en la variable x y la ejecuta hasta que al-
canza la instrucción await (B). Si la condición B se evalúa como true, el proceso continúa con
la ejecución de la SC; en caso contrario, libera la exclusión mutua y se bloquea a sí mismo,
esperando que B se vuelva true. Cualquier otro proceso puede entonces entrar en la RCC. Un
proceso bloqueado en B es activado en algún momento futuro cuando la condición B es true y
ningún otro proceso se encuentra en una SC en x. En ese momento readquiere la sección crítica
en x y reanuda su ejecución en la instrucción que sigue a await (B).
La capacidad de esperar a una condición dentro de una SC puede emplearse para evitar
esperas activas. También puede usarse para la sincronización de procesos por medio de la
señalización. Demostraremos su uso con soluciones para el problema de productores/consu-
midores y lectores/escritores. Las soluciones usan los planteamientos que se describieron ante-
riormente.
La figura 9.33 contiene una solución del problema de productores/consumidores usando
RCC. Sigue el mismo planteamiento que la solución de la figura 9.28, usando semáforos. full es
un entero compartido en esta solución. Un proceso de productor entra en el constructor region
buffer_pool do y ejecuta un await (full  n). De esta manera, sólo producirá cuando exista por lo
menos un buffer vacío en el área de memoria intermedia (buffer pool). El consumidor consume
bajo la condición full  0. Por motivos de la máxima concurrencia en el sistema, el productor
primero produce en una variable local produced_info y entra en la RCC simplemente para colo-
car la información producida en el buffer. Del mismo modo, el consumidor copia la información
que va a ser consumida y la coloca en la variable local for_consumption, y luego ejecuta su pro-
cesamiento fuera del constructor region. Observe que el compilador asegura la exclusión mutua
por medio de la variable de control de RCC buffer_pool. Este hecho asegura la consistencia de
sus campos full, prod_ptr y cons_ptr. Pueden agregarse más procesos de productores y consumi-
dores sin cambio alguno en el código de los procesos de productores y consumidores.

11 MAQ. CAP. 09(F0694).indd 444 8/10/07 1:05:51 AM


9.9 Regiones críticas condicionadas 445

const n = . . . ;
type item = . . . ;
var
buffer pool : Shared record
buffer : array [0..n – 1] of item;
full : integer := 0;
prod ptr : integer := 0;
cons ptr : integer := 0;
end
begin
Parbegin
var produced info : item; var for consumption : item;
repeat repeat
{ Produce in produced info } region buffer pool do
region buffer pool do begin
begin await (full > 0);
await (full < n); for consumption :=
buffer[prod ptr] buffer[cons ptr];
:= produced info; cons ptr :=
prod ptr := cons ptr 1 mod n;
prod ptr 1 mod n; full := full–1;
full := full 1; end;
end; { Consume from for consumption}
{ Resto del ciclo } { Resto del ciclo }
forever; forever;
Parend
end.
Productor Consumidor

Figura 9.33 Buffer acotado usando la región crítica condicionada.

La figura 9.34 contiene una solución para el problema de lectores/escritores usando regio-
nes críticas condicionadas. read_write es una variable compartida que contiene los contadores
runread y runwrite. Un lector sólo deberá leer cuando ningún escritor esté leyendo. Por ende, un
proceso de lector ejecuta un await (runwrite  0) antes de empezar a leer. Un escritor ejecuta
una escritura dentro de region read_write do y, por tanto, es adecuado usar un await (runread
 0) antes de empezar a escribir. Cuando un escritor completa su acción, un lector bloqueado en
runwrite  0 en una instrucción await es activado y sale de la región. La condición runwrite 
0 aún se mantiene válida, así que otros lectores bloqueados en esta condición también son acti-
vados. De este modo, no se necesita el contador totread de la figura 9.30. Y tampoco el contador
totwrite, por razones similares.
Observe que el conteo runwrite de esta solución es redundante. Su objetivo es bloquearle
la entrada a su SC a un lector si un escritor está escribiendo. Sin embargo, puesto que la escri-
tura se realiza dentro de una SC, ¡ningún lector puede entrar en su SC mientras que un escritor
esté escribiendo! Por tanto, runwrite está obligado a ser 0 cada vez que un lector ejecute la

11 MAQ. CAP. 09(F0694).indd 445 8/10/07 1:05:51 AM


446 CAPÍTULO 9 Sincronización de procesos

type item = . . . ;
var
read write : shared record
runread : integer := 0;
runwrite : integer := 0;
end
begin
Parbegin
repeat repeat
region read write do region read write do
begin begin
await (runwrite 0); await (runread 0);
runread := runread 1; runwrite := runwrite 1;
end; { Escribir }
{ Leer } runwrite := runwrite–1;
region read write do; end;
runread := runread−1; { Remainder of the cycle }
end; forever;
{ Remainder of the cycle }
forever;
Parend
end.
Lector(es) Escritor(es)

Figura 9.34 Lectores y escritores sin prioridad de escritores.

instrucción await (runwrite  0). Una solución más compacta y elegante se obtiene mediante la
eliminación de runwrite y de todas las instrucciones que incrementan o verifican su valor.

9.9.1 Implementación de una RCC

La implementación de la instrucción await es sencilla. El código generado por el compilador


puede evaluar la condición y, si es false, hacer una llamada block me para bloquear el proceso.
¿Cómo y cuándo se deberá activar el proceso bloqueado? La mejor manera de lograr esto es
vinculando la condición en la instrucción await con un evento conocido por el componente de
planificación del kernel. En la figura 9.33, las condiciones en las instrucciones await (es decir,
full  n y full  0) involucran campos de buffer_pool. Cada RCC es implementada como una SC
en buffer_pool, así que estas condiciones sólo pueden cambiar cuando algún proceso ejecuta la
RCC. Por tanto, cada vez que un proceso sale de una RCC, pueden verificarse las condiciones
en todas las instrucciones await en la RCC en la que haya procesos bloqueados. Entonces se
puede activar un proceso bloqueado cuya condición await esté satisfecha.
Sin embargo, la activación de un proceso no siempre es tan sencilla. La semántica del cons-
tructor CCR permite que se use cualquier condición booleana en una instrucción await. Si la
condición no involucra un campo de la variable de control de RCC, la ejecución de algunas ins-
trucciones fuera de una RCC podrá también cambiar el valor de verdad de una condición await.

11 MAQ. CAP. 09(F0694).indd 446 8/10/07 1:05:52 AM


9.10 Monitores 447

Por ejemplo, condiciones que involucran valores devueltos por llamadas al sistema como hora
del día pueden volverse verídicas aun si ningún proceso ejecuta una RCC. Estas condiciones se
tendrán que verificar periódicamente para activar procesos bloqueados. Tales revisiones incre-
mentan la carga general de la implementación de las RCC.

9.10 MONITORES

Un monitor es un constructor de lenguaje de programación que soporta tanto la sincroniza-


ción de acceso de datos como la de controles. Un tipo de monitor se parece a una clase en un
lenguaje como C o Java. Tiene los cuatro aspectos que se resumen en la tabla 9.5: declara-
ción e inicialización de datos compartidos, operaciones en datos compartidos y operaciones de
sincronización. Un programa concurrente crea objetos de monitor, es decir, objetos de un tipo
de monitor, y los usa para ejecutar operaciones con datos compartidos y para realizar operacio-
nes de sincronización de procesos. Nos referimos a un objeto de un tipo de monitor como una
variable de monitor, o simplemente como monitor.

Tabla 9.5 Aspectos de un tipo de monitor

Aspecto Descripción
Declaración Aquí se declaran datos compartidos y variables de condición. Copias de estos datos
de datos existen en cada objeto de un tipo de monitor.
Inicialización Se inicializan datos cuando un monitor, es decir, un objeto de un tipo de monitor, es
de datos creado.
Operaciones Las operaciones con datos compartidos son codificadas como compartidos procedi-
con datos mientos del tipo de monitor. El monitor asegura que estas operaciones sean ejecuta-
das en forma mutuamente exclusiva.
Operación de Los procedimientos del tipo monitor prefieren el uso de operaciones de sincroni-
sincronización zación wait y signal sobre variables de condición para sincronizar la ejecución de
procesos.

Las operaciones con datos compartidos son codificadas como procedimientos del monitor.
A fin de asegurar la consistencia de datos compartidos y la ausencia de condiciones de ejecu-
ción en su manipulación, el monitor asegura que sus procedimientos sean ejecutados en forma
mutuamente exclusiva. Para cumplir con la propiedad de la espera acotada, las llamadas sobre
procedimientos de un monitor son tratadas según el principio FIFO. Esta característica es imple-
mentada manteniendo una cola de procesos que desean ejecutar procedimientos de monitor. La
sincronización de procesos se realiza usando las operaciones signal y wait en datos de sincroni-
zación llamados variables de condición.

Variables de condición El soporte de sincronización de procesos en monitores se parece


en muchos aspectos al mecanismo de eventos que se describe en la sección 3.3.6. Los eventos
se llaman condiciones en monitores. Una variable de condición, que es simplemente una variable
con el atributo condition, es asociada con cada condición en un monitor. De este modo,

var x : condition;

11 MAQ. CAP. 09(F0694).indd 447 8/10/07 1:05:52 AM


448 CAPÍTULO 9 Sincronización de procesos

hace de x una variable de condición. Una cola de procesos es asociada con una variable de
condición para contener los identificadores de procesos bloqueados en la condición. Se definen
dos operaciones en una variable de condición: una operación wait y una operación signal. Se
bloquea un proceso en la condición x cuando ejecuta la instrucción x.wait en un procedimiento
del monitor. El identificador de este proceso se introduce en la cola de procesos asociada con la
variable de condición x. El primer proceso de la cola es activado cuando algún proceso ejecuta
la instrucción x.signal dentro de un procedimiento de monitor. De este modo, los procesos blo-
queados en la misma condición despiertan de manera FIFO.
La semántica de condiciones usada en un monitor difiere tanto de la semántica de semáfo-
ros como de la semántica de condiciones await en regiones críticas condicionadas. Un signal es
como un señalamiento de tránsito especial que únicamente permite que pase un solo automóvil.
Activa un proceso si algunos procesos están esperando; aparte de eso, no tiene ningún efecto. Un
proceso que ejecuta una instrucción await necesariamente se bloquea hasta que algún proceso
ejecute una instrucción signal. Una condición se tiene que señalar varias veces si muchos proce-
sos están bloqueados en ella y si todos tienen que ser activados.
La implementación de un monitor mantiene varias colas de procesos: una para cada variable
de condición y otra para los procesos que esperan la ejecución de procedimientos de monitor.
Para asegurar que no haya procesos que se atasquen a mitad de la ejecución de una operación,
el monitor favorece procesos bloqueados en condiciones sobre los que desean entrar en el mo-
nitor.
El ejemplo 9.4 describe el uso de un monitor para realizar un semáforo binario. Después del
ejemplo analizaremos un tema de implementación interesante.

Ejemplo 9.4 La figura 9.35 muestra un monitor para la implementación de un semáforo binario,
así como tres procesos que usan el monitor. La variable busy toma los valores false y true. Éstos co-
rresponden a los valores 1 y 0 de un semáforo binario. De este modo, busy  true indica que algún
proceso está actualmente usando la sección crítica. La variable de condición non_busy se usa para
bloquear procesos que tratan de entrar en una SC, mientras que busy  true. sem es una variable de
monitor. La variable busy de sem se inicializa en false cuando se crea sem. Las instrucciones sem.
sem_wait y sem.sem_signal llaman a las operaciones wait y signal en sem.
La figura 9.36 representa a los cuatro componentes del monitor sem_mon_type. Se mantienen
dos colas de procesos. Una contiene procesos que esperan para ejecutar el procedimiento sem_wait
o sem_signal del monitor, mientras que la otra contiene a aquellos que esperan la ejecución de una
instrucción non_busy.signal.
Supongamos que P1 sea el primer proceso que va a ejecutar sem.sem_wait. Puesto que busy es
false, cambia busy a true y entra en la SC. Si P2 ejecuta sem.sem_wait mientras que P1 todavía está
dentro de la SC, será bloqueado en non_busy.wait. Éste espera en la cola asociada con la varia-
ble de condición non_busy. Ahora supongamos que P1 inicie la ejecución de sem.sem_signal y que
P3 trata de ejecutar sem.sem_wait antes de que P1 termine sem.sem_signal. P3 esperará en la cola
asociada con la entrada al monitor. La figura 9.37 ilustra una toma instantánea del sistema en ese
momento. Cuando el proceso P1 ejecuta un signal y sale del monitor, P2 será activado, ya que las
colas asociadas con variables de condición gozan de prioridad sobre la cola asociada con la entrada
al monitor. El proceso P3 sólo entrará en el monitor cuando el proceso P2 complete la ejecución
de sem.sem_wait, salga del monitor y entre en la SC; sin embargo, se bloqueará a sí mismo en la
condición non_busy. Sólo se activará cuando P2 ejecute la operación sem.sem_signal.

Se presenta un interesante problema de sincronización cuando el proceso P1 de la figura


9.35 llama a sem.sem_signal, que ejecuta la instrucción non_busy.signal. Como se ha visto en el

11 MAQ. CAP. 09(F0694).indd 448 8/10/07 1:05:52 AM


9.10 Monitores 449

type sem mon type = monitor


var
busy : boolean;
non busy : condition;
procedure sem wait;
begin
if busy = true then non busy.wait;
busy := true;
end;
procedure sem signal;
begin
busy := false;
non busy.signal;
end;
begin {inicialización}
busy := false;
end;
var sem : sem mon type;
begin
Parbegin
repeat repeat repeat
sem.sem wait; sem.sem wait; sem.sem wait;
{ Sección crítica } { Sección crítica } { Sección crítica }
sem.sem signal; sem.sem signal; sem.sem signal;
{ Resto del ciclo } { Resto del ciclo } { Resto del ciclo }
forever; forever; forever;
Parend
end.

Proceso P1 Proceso P2 Proceso P3

Figura 9.35 Implementación de monitor de un semáforo binario.

ejemplo 9.4, se espera que este signal active el proceso P2, que reanudará su ejecución de sem.
sem_wait. Al mismo tiempo, el proceso P1 deberá continuar su ejecución de sem.sem_signal,
ejecutando instrucciones que siguen a la instrucción non_busy.signal. Puesto que el monitor es
realizado como una SC, sólo uno de ellos puede ejecutar, y el otro tendrá que esperar. Entonces,
¿a cuál de ellos se deberá planificar?
El proceso de planificación P2 demoraría el proceso de señalización P1, lo que parece in-
justo. La planificación de P1 implicaría que P2 no está realmente activado sino hasta que P1

11 MAQ. CAP. 09(F0694).indd 449 8/10/07 1:05:52 AM


450 CAPÍTULO 9 Sincronización de procesos

busy Datos
··· non busy

Procedure sem signal


non busy.signal
··· Operaciones
Procedure sem wait
non busy.wait

busy:= false Inicializaciones

Figura 9.36 Un monitor realizando un semáforo binario.

P1 sem wait
busy
... non-busy

P3 sem signal ...


P2

Figura 9.37 Toma instantánea del sistema del ejemplo 9.4.

salga del monitor. Hoare (1974) propuso la primera alternativa. Brinch Hansen (1973) propuso
que una instrucción signal deberá ser la última instrucción de un procedimiento de monitor; de
este modo, el proceso que ejecuta signal sale del procedimiento de monitor inmediatamente y
se puede planificar el proceso activado por la instrucción signal.
Como se mencionó antes, el uso de variables de condición tiene dos ventajas: en primer tér-
mino, un signal no tiene ningún efecto si ningún proceso está bloqueado en la variable de con-
dición. Esta característica simplifica la lógica de operaciones con datos compartidos. El ejemplo
9.5 ilustra este hecho en el contexto de la solución del problema de productores/consumidores.
En segundo término, a diferencia de las regiones críticas condicionadas, los procesos son acti-
vados por la ejecución de instrucciones signal. De ahí que la implementación de monitores no
necesite verificar repetidamente si un proceso bloqueado puede ser activado; esto reduce la carga
general de la sincronización de procesos.

La figura 9.38 muestra una solución para el problema de productores/consumidores, usando mo-
nitores.

11 MAQ. CAP. 09(F0694).indd 450 8/10/07 1:05:52 AM


9.10 Monitores 451

{ Número de buffers }

{ por ejemplo productor }

{ por ejemplo consumidor }

{inicialización}

{ Resto del ciclo } { Resto del ciclo } { Resto del ciclo }

Productor P1 Productor P2 Consumidor P3

Figura 9.38 Productores/consumidores usando monitores.

11 MAQ. CAP. 09(F0694).indd 451 8/10/07 1:05:53 AM


452 CAPÍTULO 9 Sincronización de procesos

El código para los procedimientos Produce y Consume es análogo al que usa la región crítica
condicionada (véase la figura 9.33), aunque con una diferencia significativa: un proceso que eje-
cuta una operación wait en una variable de condición tiene que ser activado en forma explícita. Es
por esto que las instrucciones buff_full.signal y buff_empty.signal tienen que existir en los proce-
dimientos produce y consume, respectivamente.
El sistema contiene dos procesos de productores P1, P2, y un proceso de consumidor P3. La
operación de un solo sistema de buffers, es decir, n  1 en la figura 9.38, puede representarse de
la siguiente forma:

productor productor
P1 P1 P2
buff empty buff empty
buff full buff full
P3
consumidor consumidor
P3 P2
a) b)

Supongamos que los procesos P1 y P2 traten de producir, y que el proceso P3 trate de consumir,
todos al mismo tiempo. El proceso P1 entra en el procedimiento produce, pasa por la instrucción
wait y empieza a producir. Los procesos P2 y P3 son bloqueados en la entrada al monitor [véase la
parte a) de la instantánea]. P1 ejecuta buff_full.signal y sale. Ahora el proceso P2 es activado; sin
embargo, vuelve a ser bloqueado en buff_empty.wait porque full  1. El proceso P3 es activado
cuando P2 es bloqueado, y empieza a consumir [véase la parte b) de la instantánea]. El proceso P2
será activado cuando P3 salga después de consumir.

9.10.1 Planificador de disco: un caso de estudio

Los procesos del usuario comparten un disco de cabeza móvil. Se usa un monitor para iniciar
operaciones de E/S en el disco. Un proceso de usuario llama a un procedimiento del monitor
para transmitir los detalles de una operación de E/S. El planificador de disco ingresa estos deta-
lles en una lista. Para ello usa una política de planificación de disco a fin de decidir el orden en
el que estas operaciones se deberán ejecutar, e inicia operaciones de E/S en ese orden (véase la
sección 12.4.5 para una discusión de la planificación de discos). A fin de codificar el planificador
de disco como monitor, identificamos sus elementos clave, es decir, los datos compartidos y las
operaciones con datos compartidos.
1. Datos compartidos: Datos en relación con operaciones de E/S pendientes. Los datos se
pueden organizar como una lista llamada I/O_list.
2. Operaciones con datos compartidos: Se pueden identificar las siguientes operaciones:
a) Agregar una operación de E/S a una lista I/O_list
b) Borrar una operación de E/S de una lista I/O_list
c) Analizar operaciones de E/S en I/O_list y ejecutar planificación.
Estas operaciones son codificadas como los procedimientos de monitor IO_request, IO_
complete e IO_schedule.
La figura 9.39 muestra un tipo de monitor Disk_mon_type. La figura 9.40 muestra una parte
del planificador de disco. Contiene una variable de monitor Disk_scheduler del tipo Disk_mon_

11 MAQ. CAP. 09(F0694).indd 452 8/10/07 1:05:53 AM


9.10 Monitores 453

type Disk Mon type : monitor


const n = . . . ; { Tamaño de la lista de IO }
m = . . . ; { Número de proceso de usuario }
type Q element = record
proc id : integer;
track no : integer;
end;
var
IO list : array [1..n] of Q element;
proceed : array [1..m] of condition;
whose IO in progress, count : integer;
procedure IO request (proc id, track no : integer);
begin
{ Captura proc id y track no en la IO list }
count := count + 1;
if count > 1 then proceed[proc id].wait;
whose IO in progress := proc id;
end;
procedure IO complete (proc id : integer);
var id : integer;
begin
if whose IO in progress proc id then { indica error }
{ Quita el requerimiento de proceso desde la IO_list }
count := count – 1;
if count > 0 then
begin
{ Selecciona la operación de IO a ser inicializada desde la IO_list }
id := id of requesting process;
proceed[id].signal;
end;
end;
begin { Inicializaciones }
count := 0;
whose IO in progress := 0;
end;

Figura 9.39 Un monitor para la implementación del planificador de discos.

type. El arreglo de planificación de discos es el siguiente: en el código de un proceso de usua-


rios, cada operación de E/S es precedida por una llamada al procedimiento del monitor de disco
IO_request. El identificador de proceso y los detalles de la operación de E/S son parámetros de
esta llamada. IO_request ingresa estos parámetros en IO_list. Si se está realizando una operación
E/S, bloquea el proceso de usuario hasta que se puede iniciar su operación de E/S. Este bloqueo
es realizado emitiendo un wait en una variable de condición.
Cuando el planificador de disco decide planificar la operación de E/S, ejecuta una instruc-
ción signal para activar el proceso del usuario. Éste ahora sale del monitor e inicia su operación
de E/S. Después de la operación de E/S, llama al procedimiento de monitor IO_complete. Este

11 MAQ. CAP. 09(F0694).indd 453 8/10/07 1:05:54 AM


454 CAPÍTULO 9 Sincronización de procesos

var Disk scheduler : Disk Mon type;


Parbegin
begin { Proceso de usuario i }
repeat
Disk scheduler.IO request (i, track);
{ Rendimiento de la operación de I/O }
Disk scheduler.IO complete (i);
{ Resto de ciclo }
forever
end;
... { otros procesos de usuario }
Parend.

Figura 9.40 Procesos de usuarios y la variable de monitor.

procedimiento selecciona para su iniciación una operación de E/S pendiente, ejecuta una instruc-
ción signal para activar el proceso que lo solicita y sale del monitor. Si no hay operaciones de
E/S pendientes, simplemente sale del monitor.
El monitor usa un array proceed de variables de condición para bloquear procesos de usua-
rios. proceed contiene un elemento para cada proceso de usuario. Si el procedimiento IO_request
no puede iniciar una operación de E/S solicitada por un proceso Pi en forma inmediata, ejecuta
la instrucción proceed[i].wait para bloquear Pi. Cuando se llama a IO_complete para indicar la
finalización de una operación de E/S, analiza todas las solicitudes de E/S registradas en IO_list,
selecciona una operación de E/S para su iniciación y obtiene el identificador de su solicitante,
por ejemplo Pj, de IO_list. Ahora ejecuta proceed[j].signal. Esto activa el proceso Pj, que conti-
núa con su operación de E/S.
La figura 9.39 contiene el código del tipo de monitor Disk_mon_type. Los detalles de la
formación de cola de las solicitudes de E/S y la política de planificación en vigor no se muestran
explícitamente. El ejemplo 9.6 ilustra la operación del planificador de disco.

Ejemplo 9.6 Consideremos la operación del planificador de disco para las operaciones de E/S que
se muestran en la figura 9.41. Supongamos que las cabezas del disco se estén moviendo hacia pistas
de numeración mayor, que estén posicionadas en la pista número 55 y que la velocidad de reloj
sea 150 ms cuando finaliza la operación E/S de P6, que estaba planificada para la hora 0. Suponga-
mos que el algoritmo del planificador de disco planifique las operaciones de E/S en el orden de los
números ascendentes de pistas a partir de la posición actual (el algoritmo SCAN; véase la sección
12.4.5). Este algoritmo selecciona la solicitud en la pista 85.

Proceso id P1 P2 P3 P4 P5 P6
Número de pista 12 85 40 100 75 55
Tiempo de respuesta 10 50 100 120 175 0

Figura 9.41 Operaciones de E/S para el estudio de caso del planificador de disco.

La figura 9.42 muestra una instantánea del sistema. Se hicieron solicitudes de E/S de los
procesos P1-P4 que fueron ingresadas en IO_list. IO_list contiene los cuatro pares (1,12), (2,85),

11 MAQ. CAP. 09(F0694).indd 454 8/10/07 1:05:54 AM


9.10 Monitores 455

(3,40) y (4,100). Los procesos P1-P4 están bloqueados en diferentes elementos de proceed, que es
un array de variables de condición. IO_complete es llamado por P6, selecciona la operación de E/S
en la pista número 85 y obtiene el identificador del proceso que hizo esta solicitud de IO_list. Este
identificador es 2 y, por ende, ejecuta la instrucción proceed[2].signal. El proceso P2 está ahora
activado y procede a ejecutar su operación de E/S.

Proceso Número
id de pista proceder
P1 12
IO request P1
P2 85 1
P3 40 IO complete 2 P2
3
P4 100 4 P3
IO schedule
P4
IO list

Figura 9.42 Toma instantánea del monitor de disco.

Este monitor de disco asume de manera simplificada que se puede permitir que un proceso
ejecute sus propias operaciones de E/S. Si éste no es el caso, la operación E/S deberá ser ejecu-
tada por el propio monitor de disco (véase el problema 23 del ejercicio 9).

9.10.2 Monitores en Java

Una clase de Java se convierte en un tipo de monitor cuando el atributo synchronized es aso-
ciado con uno o varios métodos de esa clase. Un objeto de una de estas clases es un monitor. La
máquina virtual de Java asegura la exclusión mutua por medio de los métodos synchronized
en un monitor. Cada monitor contiene una sola variable de condición sin nombre. Un hilo espera
sobre la variable de condición, ejecutando la llamada wait(). La llamada notify()es como
la operación signal que se describe en la sección 9.10. Despierta a uno de los hilos que están
esperando sobre la variable de condición. La máquina virtual de Java no realiza el comporta-
miento FIFO para las llamadas de esperar y notificar; por tanto, no proporciona la propiedad
de espera acotada. La llamada notifyall()activa todos los hilos que esperan sobre la varia-
ble de condición.
La existencia de una sola variable de condición en un monitor tiene el efecto de juntar for-
zosamente todos los hilos de ejecución que requieren de sincronización en el monitor. Esto lleva
a esperas activas en una aplicación si los hilos necesitan esperar condiciones diferentes. Tal pro-
blema se encuentra en un sistema de lectores/escritores. Cuando un escritor está activo, todos los
lectores que desean leer y todos los escritores que desean escribir tendrán que esperar en la mis-
ma variable de condición. Si el escritor ejecuta una llamada notify()cuando termina de escri-
bir, un lector o un escritor será activado. Sin embargo, la lectura concurrente es deseable, así que
no basta con activar a sólo un lector. El escritor tendría que usar una llamada notifyall()para
activar todos los hilos en espera. Si hay preferencia de lectores, todas las líneas de escritores y
algunos hilos de escritores nuevamente tendrán que ejecutar llamadas wait().Si hay preferencia
de escritores, todos los hilos de lectores y algunos hilos de escritores tendrán que ejecutar nue-

11 MAQ. CAP. 09(F0694).indd 455 8/10/07 1:05:54 AM


456 CAPÍTULO 9 Sincronización de procesos

vamente llamadas wait(). De este modo, un hilo de lector o escritor podrá ser activado muchas
veces antes de tener la oportunidad de ejecutar la lectura o la escritura. Un sistema de producto-
res/consumidores también sufriría un problema similar.

9.11 LA SINCRONIZACIÓN DE PROCESOS EN UNIX

El sistema V de Unix ofrece la implementación de semáforos en el nivel del kernel. El kernel


realiza las operaciones de wait y signal y los procesos invocan a estas operaciones por medio de
llamadas al sistema. Se usan claves especificadas por el usuario como nombres de los semáforos.
Una clave está asociada con un array de semáforos. Los semáforos individuales en el array se
usan con la ayuda de subíndices. Un proceso que desea usar un semáforo obtiene acceso al mis-
mo haciendo una llamada al sistema semget con una clave como parámetro. Si ya existe un array
de semáforos con un nombre coincidente, el kernel lo hace accesible para el proceso por me-
dio de la llamada semget; en caso contrario, el kernel crea un nuevo array de semáforos, asigna
la clave para él y lo hace accesible para el proceso.
El kernel proporciona una sola llamada al sistema semop para las operaciones wait y sig-
nal. La llamada toma dos parámetros, una clave y una lista de (subscript, op) especificaciones
donde subscript identifica un semáforo en el array de semáforos, y op es la operación que se va
a realizar. La serie completa de operaciones definidas en la lista se ejecuta de modo indivisible.
La ejecución de semop también es de carácter atómico, es decir que o todas las operaciones se
ejecutan y el proceso queda libre para continuar su ejecución, o no se ejecuta ninguna de las
operaciones y el proceso es bloqueado. Un proceso bloqueado sólo es activado cuando todas
las operaciones indicadas en semop pueden tener éxito.
La semántica de semop ayuda a evitar bloqueos mutuos. Considere una situación en la que
algunos procesos necesitan usar dos recursos R1 y R2 en forma simultánea. Puede usarse un se-
máforo para controlar cada recurso. Un bloqueo mutuo puede presentarse si varios procesos eje-
cutan operaciones wait en estos semáforos en un orden distinto. Sin embargo, no se presentarán
bloqueos mutuos si los procesos ejecutan ambas operaciones wait por medio de un solo semop,
puesto que a un proceso se le asignan ambos recursos o no se le asigna ninguno de ellos. La
situación entonces se parece al planteamiento de “todas las solicitudes juntas” de la prevención
de bloqueos mutuos (véase la sección 11.5.1).
Unix SVR4 ofrece una característica interesante para hacer más confiables los programas
que usan semáforos. Mantiene pendientes todas las operaciones ejecutadas por un proceso en
cada semáforo que usa, y realiza un “deshacer” en estas operaciones cuando termina el proceso.
Esta acción ayuda a impedir trastornos en una aplicación concurrente debidos al mal compor-
tamiento de algunos procesos. Por ejemplo, si un proceso Pi ejecutó más operaciones wait que
operaciones signal en el semáforo semi y lo finalizó, se podrían dar esperas interminables para
otros procesos de la aplicación. La ejecución de una operación de deshacer en todas las opera-
ciones wait y signal implementadas por Pi podría impedir ese tipo de desastres.
A fin de realizar las operaciones de deshacer de manera eficiente, el kernel mantiene un con-
teo acumulativo de los cambios en el valor del semáforo que son causados por las operaciones de
un proceso, y lo resta del valor del semáforo cuando termina el proceso. Si un proceso Pi realizó
más operaciones wait que operaciones signal en el semáforo semi, su conteo acumulativo para
semi será negativo. Restar este conteo nulificará el efecto de Pi sobre semi. El conteo acumulativo
de Pi sería 0 si hubiese ejecutado un número equilibrado de operaciones wait y signal en semi.

11 MAQ. CAP. 09(F0694).indd 456 8/10/07 1:05:55 AM


9.12 La sincronización de procesos en Linux 457

De este modo, la operación de deshacer no interfiere con la operación normal de procesos que
usan semáforos.
Unix 4.4BSD permite que se coloquen semáforos en áreas de memoria compartidas por
una serie de procesos. Aquellos procesos que usan estos semáforos pueden acceder a los va-
lores de los semáforos en forma mutuamente exclusiva mediante el uso de instrucciones indi-
visibles. Para facilitar el bloqueo y la activación de procesos, el uso de semáforos procede de
la siguiente manera: un proceso que desea ejecutar una operación wait examina el valor del
semáforo. Si el valor es  0, reduce el valor y continúa su ejecución. Si es 0, agrega su propio
identificador a una lista de espera para el semáforo que se lleva en la memoria compartida,
y realiza una llamada al sistema block me. Si la lista de espera no está vacía, un proceso que
ejecuta una operación signal realiza una llamada al sistema activate this process acerca de
algún proceso de la lista. Este planteamiento ofrece la sincronización rápida evitando llama-
das al sistema en casos donde una operación wait no lleva al bloqueo (véase la sección 9.8.4
para una discusión semejante), o donde una operación signal no lleva a la activación de
un proceso bloqueado.

9.12 LA SINCRONIZACIÓN DE PROCESOS EN LINUX

Linux ofrece un semáforo parecido al de Unix (véase la sección 9.11) para ser usado por parte de
los procesos de usuario. También ofrece dos tipos de semáforos para su empleo por parte de un
kernel: uno convencional y uno de lectores/escritores. La puesta en funcionamiento del semáforo
convencional para el kernel es análoga al esquema de implantación en el nivel del kernel que
se discutió en la sección 9.8.4. El kernel usa una estructura que contiene el valor del semáforo,
una lista de procesos en espera y un indicador para decir si hay procesos esperando al semáfo-
ro. De este modo, a diferencia del esquema de la sección 9.8.4, no se usa un bloque para evitar
condiciones de ejecución sobre el valor del semáforo; en su lugar, las operaciones wait y signal
emplean instrucciones indivisibles para reducir e incrementar el valor del semáforo. Esto dismi-
nuye la carga general de las operaciones wait y signal. La lista de procesos en espera se bloquea
por separado cuando estas operaciones le agregan o quitan procesos. El indicador de procesos en
espera se usa para reducir esta carga general de bloqueo del modo siguiente: la operación signal
verifica el indicador para cerciorarse de si hay procesos en espera en el semáforo, y bloquea la
lista de procesos en espera solamente si se ha puesto el indicador.
El semáforo de lectores/escritores ofrece posibilidades que se pueden usar para imple-
mentar el problema de lectores/escritores planteado en la sección 9.8.3 dentro de un kernel, de
tal modo que muchos procesos pueden leer de manera concurrente una estructura de datos del
kernel, pero sólo uno la puede actualizar. El kernel realiza el semáforo de lectores/escritores,
llevando un conteo del número de lectores que concurrentemente ejecutan una operación de
lectura, y una lista de procesos que esperan para ejecutar una operación de lectura o de escri-
tura, la cual está organizada en orden cronológico. La implantación de semáforos de lectores/
escritores no favorece ni a lectores ni a escritores, sino que permite que los procesos entren en
sus secciones críticas en orden FIFO, con excepción de los lectores consecutivos, que pue-
den leer en forma concurrente. De este modo, un proceso de lectura tendrá que esperar si ya hay
un proceso de escritura en espera, y estará habilitado para leer en algún momento, después de
que finalice el escritor.

11 MAQ. CAP. 09(F0694).indd 457 8/10/07 1:05:55 AM


458 CAPÍTULO 9 Sincronización de procesos

Kernels anteriores al kernel de Linux 2.6 implementaban la exclusión mutua en el espacio


del kernel por medio de llamadas al sistema. Sin embargo, como se menciona en la sección
9.8.4, una operación wait tiene un índice de error bajo, es decir, rara vez un proceso es blo-
queado en una llamada wait, de tal modo que muchas de las llamadas al sistema realmente son
innecesarias. El kernel de Linux 2.6 ofrece un mutex rápido de espacio de usuario rápido llama-
do futex. Un futex es un entero en la memoria compartida en el cual pueden ejecutarse ciertas
operaciones. La operación wait en un futex sólo realiza una llamada al sistema cuando un pro-
ceso debe ser bloqueado en el futex, y la operación signal en un futex sólo realiza una llamada
al sistema cuando un proceso debe ser activado. La operación wait también ofrece un parámetro
que permite que un proceso pueda indicar cuánto tiempo debería estar bloqueado en wait. Una
vez transcurrido este tiempo, la operación wait falla y devuelve un código de error al proceso
que hizo la llamada.

9.13 LA SINCRONIZACIÓN DE PROCESOS EN WINDOWS

Windows es un sistema orientado a objetos. Todas las entidades del sistema están representadas
por ellos. El kernel proporciona objetos llamados dispatcher objects para la sincronización de
hilos. Cada uno de los objetos que representan procesos, archivos y eventos implanta un objeto
de despachador. De este modo, estos objetos pueden usarse para la sincronización de hilos. Mu-
texes y semáforos también son representados por objetos.
Un objeto de despachador puede estar en estado signaled (señalado) o en estado nonsigna-
led (no señalado). Si se encuentra en estado no señalado, cualquier hilo que desea sincronizarse
con él es colocado en el estado waiting. La semántica de un objeto determina cuáles de los hilos
que esperan en él serán activados cuando se le señala, y cuál será su nuevo estado cuando se le
señala o cuando un hilo ejecuta una operación wait en él (véase la tabla 9.6). Un objeto de hilo
entra en el estado señalado cuando termina, mientras que uno de proceso entra en el estado seña-
lado cuando terminan todos sus hilos. En ambos casos se activan todos los hilos que esperan en
el objeto. Un objeto de trabajo es señalado cuando transcurre el tiempo de trabajo especificado
para él. Windows también mantiene el estado signal de un objeto de hilo o proceso como una va-
riable booleana y permite que la acceda un hilo. De este modo, un hilo puede verificar el estado
de un hilo o proceso sin riesgo de ser bloqueado.
El objeto de archivo es señalado cuando finaliza una operación E/S en el archivo. Todos
los hilos que esperan en él son activados, y su estado de sincronización vuelve a cambiar a no
señalado. Si no hay hilos que esperan en él, un hilo que espere en él en algún momento futuro
pasará por la operación wait, y el estado de sincronización del objeto de archivo cambiará a no
señalado. El objeto de entrada de consola tiene un comportamiento análogo, con excepción de
que sólo un hilo en espera es activado cuando es señalado. El objeto de cambio de archivo es
señalado cuando el sistema detecta cambios. En otros aspectos, se comporta como el objeto de
archivo.
Los hilos usan los objetos de evento, mutex y semáforo para la sincronización mutua.
Ellos señalan estos objetos mediante la ejecución de funciones de biblioteca que llevan a lla-
madas al sistema adecuadas. Un objeto de evento es señalado en caso de una llamada al sis-
tema set event. Si se trata de un evento de notificación, todos los hilos que esperan en él son
activados. Si se trata de un evento de sincronización, sólo un hilo es activado y el evento es
puesto en cero.

11 MAQ. CAP. 09(F0694).indd 458 8/10/07 1:05:55 AM


Ejercicio 9 459

Tabla 9.6 Objetos de sincronización de Windows 2000

Acción de tiempo
Objeto No señalado Señalado de señal
Proceso No terminado Termina último hilo Activar todos los hilos
Hilo No terminado Termina último hilo Activar todos los hilos
Archivo Solicitud de E/S Termina E/S Activar todos los hilos
pendiente
Entrada de consola Entrada no Entrada proporcionada Activar un hilo
proporcionada
Cambio de archivo No hay cambios Detecta cambio Activar un hilo
Evento Inicializado o liberado Inicialización de Activar todos los hilos
evento ejecutado
Mutex Espera exitosa Liberado Activar un hilo
Semáforo Espera exitosa Liberado Activar un hilo

El objeto de semáforo implementa un semáforo de conteo que puede usarse para controlar
un conjunto de recursos. El número de recursos es especificado como valor inicial del semá-
foro. Un conteo en el objeto de semáforo indica cuántos de estos recursos están actualmente
disponibles para ser usados por los hilos. El objeto de semáforo está en estado no señalado cuan-
do un conteo es 0, así que cualquier proceso que ejecuta un wait en él se pondrá en estado wai-
ting. Cuando un hilo libera un recurso, el kernel incrementa el número de recursos disponibles,
y esto pone al semáforo en el estado señalado. Por consiguiente, cualquier hilo que espera en
él es activado. Un hilo puede especificar un intervalo de tiempo en una llamada de espera para
indicar cuánto tiempo está dispuesto a esperar a un objeto. Se activaría antes de que transcurra
este intervalo si el objeto es señalado; de no ser así, su solicitud de espera es retirada al final
del intervalo y se activa. Un mutex es realizado como semáforo binario. El objeto de mutex es
señalado cuando un proceso ejecuta la función de liberación y el kernel libera uno de los hilos
que están esperando en él.
El kernel de Windows ofrece una variedad de bloqueos de sincronización: un spinlock, un
bloqueo especial llamado queued spinlock para configuraciones de multiprocesadores y mutexes
rápidos y push locks que, al igual que el futex de Linux, evitan llamadas al sistema a menos que
un hilo tenga que esperar en un objeto de sincronización.

EJERCICIO 9
1. Dos procesos concurrentes comparten un ítem de dato sum que es inicializado en 0; sin embargo, estos
procesos no usan la exclusión mutua mientras que accesan su valor. Cada proceso contiene un bucle
que ejecuta la instrucción única sum : sum+1 50 veces. Si no se ejecuta ninguna otra operación
en sum, indique el límite inferior y el límite superior en el valor de sum cuando ambos procesos ter-
minan.
2. Analice los algoritmos 9.1, 9.2 y comente acerca de las propiedades de SC que ellos violan. Mencione
ejemplos que ilustren las violaciones.

11 MAQ. CAP. 09(F0694).indd 459 8/10/07 1:05:55 AM


460 CAPÍTULO 9 Sincronización de procesos

3. Demuestre que la condición de progreso está cumplida en el caso del algoritmo de Dekker. (Sugeren-
cia: Considere turn  2 y el proceso P1 que trata de entrar en su SC.)
4. Para el algoritmo de Dekker, demuestre que
a) Una condición de bloqueo mutuo no se puede presentar.
b) Una condición de bloqueo en vivo no se puede presentar.
5. ¿Se cumple la condición de espera acotada por el algoritmo de Peterson?
6. Se hacen los siguientes cambios en el algoritmo de Peterson (véase el algoritmo 9.4): las instrucciones
flag [0] :  true y flag [0] :  false en el proceso P0 son intercambiadas (y cambios análogos se hacen
en el proceso P1). Analice qué propiedades de la implantación de secciones críticas son violadas por el
sistema resultante.
7. Si la instrucción while flag[1] y turn  1 en el algoritmo de Peterson se cambia a while flag[1] o turn
 1 (y se hacen cambios análogos en el proceso P1), ¿cuáles son las propiedades de la implantación de
secciones críticas que son violadas por el sistema resultante?
8. Explique el comportamiento de un proceso Pi en el algoritmo 9.5, cuando el proceso Pi termina su SC
y ningún otro proceso está interesado en entrar en su SC.
9. En el algoritmo Bakery de Lamport, un proceso que escoge un valor simbólico en un tiempo anterior
recibe un valor simbólico menor que un proceso que escoge un valor simbólico en un momento poste-
rior. Explique la necesidad para el primer bucle while en este contexto.
10. Amplíe la solución del problema de productores/consumidores que se muestra en la figura 9.11 para
permitir múltiples procesos de productores y consumidores.
11. La solución del problema de productores/consumidores que se muestra en la figura 9.43 usa las llama-
das al kernel block y activate para la sincronización de procesos. Esta solución contiene una condición
de ejecución. Describa cómo surge la condición de ejecución.
12. Identifique características de la solución del problema de productores/consumidores de la figura 9.28
que se tienen que modificar si existe más de un productor o más de un consumidor en el sistema. (Su-
gerencia: No haga ninguna suposición respecto a las velocidades relativas de procesos.)
13. La solución de lectores/escritores de la figura 9.30 usa dos semáforos, a pesar de que una sola entidad
—los datos compartidos— debe ser controlada. Modifique esta solución para que se use un solo se-
máforo rw_permission en lugar de los semáforos reading y writing. (Sugerencia: Solamente ejecute un
wait(rw_permission) en el lector si la lectura aún no está en ejecución.)
14. Modifique la solución de lectores/escritores de la figura 9.30 para implementar un sistema de lectores/
escritores con preferencia para escritores.
15. Demuestre que puede surgir un bloqueo mutuo si el proceso de lectores de la figura 9.30 es modificado
para ejecutar un wait(reading) dentro de una SC en mutex (en lugar de ejecutarlo después de su SC)
cuando runwrite  0.
16. Demuestre que una sección crítica implementada usando semáforos cumpliría la propiedad de espera
acotada si la operación signal activa procesos en el orden FIFO.
17. Se tiene que asignar un recurso a procesos solicitantes de manera FIFO. Cada proceso está codificado
como
repeat
...
requests-resource(process_id, resources_id);
{ Usar recurso }
release-resource(process_id, resources_id);
{ Resto del ciclo }

11 MAQ. CAP. 09(F0694).indd 460 8/10/07 1:05:55 AM


Ejercicio 9 461

type item = ;
var
buffer : item;
buffer full : boolean;
producer blocked : boolean;
consumer blocked : boolean;
begin
buffer full := false;
producer blocked := false;
consumer blocked := false;
Parbegin
repeat repeat
if buffer full = false then if buffer full = true then
{ Produce en el buffer } { Consume del buffer }
buffer full := true; buffer full := false;
if consumer blocked = true then if producer blocked = true then
activate(consumer); activate(producer);
{ Resto del ciclo } { Resto del ciclo}
else else
consumer blocked := true; producer blocked := true;
block(producer); block(consumer);
consumer blocked := false; producer blocked:= false;
forever forever
Parend

Productor Consumidor

Figura 9.43 Problema de productores/consumidores con una sincronización de


procesos debidos a condiciones de ejecución.

forever
Desarrolle los procedimientos request-resource y release-resource usando
a) semáforos.
b) regiones críticas condicionadas.
18. Modifique el algoritmo de la figura 9.34 para implementar un sistema de lectores/escritores con prefe-
rencia de escritores.
19. El esquema del problema de la cena de los filósofos de la figura 9.18 es modificado para quitar la acción
“levantar ambos tenedores” del bucle while y ponerla en el siguiente bucle while. Demuestre que se
puede presentar una condición de ejecución sobre los tenedores.
20. ¿Puede una o varias de las siguientes características eliminar las deficiencias del esquema del problema
de la cena de los filósofos que está incluido al principio de la sección 9.5.3?
a) Si n filósofos existen en el sistema, tenga por lo menos n  1 sillas en la mesa.
b) Asegúrese de que por lo menos un filósofo zurdo y por lo menos uno diestro están sentados en la
mesa en todo momento.
21. Implemente el problema de la cena de los filósofos usando a) regiones críticas condicionadas y
b) monitores. Demuestre cómo su solución evita el surgimiento de bloqueos mutuos. Asegúrese de
que su solución tenga máxima concurrencia. (Sugerencia: ¡Vea el problema 20!)
22. En la figura 9.38, productores y consumidores siempre ejecutan las instrucciones buf_full.signal y
buf_empty.signal. Sugiera e implemente un método para reducir el número de instrucciones signal que
se ejecutan durante la operación del sistema.
23. El planificador de disco de la sección 9.10 se tiene que modificar de tal modo que las operaciones
de E/S serán implementadas por el propio planificador de disco en lugar de los procesos de usuarios.

11 MAQ. CAP. 09(F0694).indd 461 8/10/07 1:05:56 AM


462 CAPÍTULO 9 Sincronización de procesos

Especifique el código modificado para Disk_Mon_type y compare su comportamiento con el del mo-
nitor original.
24. Un sistema de reservaciones de aerolínea debe ser implementado usando monitores. El sistema debe
procesar solicitudes de reservaciones y cancelaciones y ejecutar las acciones correspondientes.
a) Identifique los datos compartidos, operaciones y procesos que se requieren.
b) Implemente el sistema de reservaciones usando monitores.
25. Un cliente da las siguientes instrucciones a un gerente de banco: no abone fondos a mi cuenta si el saldo
en mi cuenta excede n, y retenga todos los adeudos hasta que el saldo de la cuenta esté suficientemente
grande para permitir el pago.
Implemente una cuenta de banco usando monitores para instrumentar estas instrucciones.
26. El problema de sincronización llamado barbero durmiente se define de la siguiente manera: una pe-
luquería tiene un solo barbero y una sola silla de peluquería en un cuarto pequeño, y una sala de
espera grande con n asientos. El barbero y su silla están visibles desde la sala de espera. Después
de despachar a un cliente, el barbero revisa si hay algún cliente esperando en la sala de espera. De ser
así, él admite a uno de ellos y empieza a atenderlo; de no ser así, se duerme en la silla de peluquería.
Un cliente sólo entra en la sala de espera si hay por lo menos una silla vacante y espera hasta que el
barbero lo llame si está ocupado, o despierta al barbero si está dormido.
Identifique los requerimientos de sincronización entre los procesos del barbero y de los clientes.
Codifique los procesos del barbero y de los clientes de tal forma que no se presenten bloqueos
mutuos.
27. Un sistema de comunicación de mensajes interproceso tiene que ponerse en marcha usando monitores.
El sistema maneja mensajes intercambiados entre 4 procesos de usuarios, usando un pool global de 20
buffers de mensajes. El sistema debe operar del siguiente modo:
a) El sistema usa una convención de nombrado asimétrica (véase la sección 10.1.1).
b) El sistema asigna un buffer de mensajes y copia el mensaje del remitente en él. Si no existe ningún
buffer libre, el remitente es bloqueado hasta que un buffer de mensajes esté disponible.
c) Cuando un receptor ejecuta un receive, se le entrega un mensaje enviado a él en orden FIFO.
Un mensaje es copiado al área proporcionada por el receptor, y se vacía el buffer de mensajes. Un
receptor es bloqueado si no existe ningún mensaje para él.
d) El sistema detecta un bloqueo mutuo si es que surge.
Escriba un monitor llamado Communication_Manager para ejecutar las funciones que arriba se des-
criben. ¿Cuáles son las variables de condición que se usan en él? Explique en forma clara cómo se
activan remitentes y receptores bloqueados.
28. Se debe escribir un monitor para simular un administrador de reloj que se usa para el control de tiem-
po real de procesos concurrentes. El administrador de reloj mantiene una variable llamada clock para
llevar el tiempo actual. El SO soporta una señal llamada elapsed_time que se genera cada 2 mseg. El
administrador de reloj indica una acción de manejo de señales para elapsed_time (véase la sección
3.5.1) y actualiza clock en cada ocurrencia de la señal. Una solicitud típica que se hace al administrador
es “despiértame a las 9:00 a.m.”. El administrador bloquea los procesos que hacen estas solicitudes y
organiza su activación a la hora designada. Implemente este monitor.
29. El anidamiento de llamadas al monitor implica que un procedimiento en el monitor “A” llame a
un procedimiento de otro monitor, por ejemplo, el monitor “B”. Durante la ejecución de la llamada
anidada, el procedimiento del monitor “A” sigue manteniendo su exclusión mutua. Demuestre que las
llamadas anidadas en el monitor pueden llevar a bloqueos mutuos.
30. Escriba una breve nota sobre la puesta en funcionamiento de monitores. Su nota debe analizar lo
siguiente:

11 MAQ. CAP. 09(F0694).indd 462 8/10/07 1:05:56 AM


Bibliografía 463

a) ¿Cómo se logra la exclusión mutua entre los procedimientos de monitores?


b) ¿Se tienen que codificar procedimientos de monitores en forma reentrante?
31. Una gran colección de datos D se usa únicamente para contestar a consultas estadísticas, así que nunca
se realizan actualizaciones en D. A fin de mejorar la respuesta a consultas, una parte de D, por ejemplo,
la parte D1, se carga a la memoria para contestar consultas de usuarios. Las consultas referentes a
D1 son procesadas en forma concurrente. Si no hay consultas activas en D1, y si existen consultas en
alguna otra parte de los datos, por ejemplo, en D2, entonces se carga D2 a la memoria, y las consultas
correspondientes son procesadas en forma concurrente. A ese sistema se le puede llamar sistema de
lectores/escritores si D se divide en las dos partes D1 y D2. Ponga este sistema en funcionamiento
usando alguna primitiva o estructura de control para obtener concurrencia.
32. Un viejo puente en una carretera muy transitada es demasiado angosto para permitir el flujo de tráfico
en ambas direcciones, así que se debe poner en marcha el flujo de tráfico de sentido único en el puente,
permitiendo que vehículos que viajan en direcciones opuestas puedan usar el puente. Se formulan las
siguientes reglas para el uso del puente:
a) En todo momento usan el puente únicamente vehículos que viajan en una sola dirección.
b) Si hay vehículos esperando en ambos extremos del puente para cruzarlo, sólo un vehículo de un
extremo recibe permiso para cruzar el puente antes de que un vehículo del otro extremo empiece a
cruzar el puente.
c) Si no hay vehículos esperando en un extremo, entonces cualquier número de vehículos del otro
extremo reciben permiso para cruzar el puente.
Desarrolle un sistema concurrente para implementar estas reglas.
33. Cuando hay vehículos esperando en ambos extremos, la regla del problema 32a) lleva a un uso
inadecuado del puente. Por tanto, se deberá permitir el paso del puente para un total de hasta 10
vehículos en una dirección, aun si hay vehículos esperando en el otro extremo. Implemente las reglas
modificadas.

BIBLIOGRAFÍA
Dijkstra (1965) analizó el problema de exclusión mutua, describió el algoritmo de Dekker y presentó un
algoritmo de exclusión mutua para n procesos. Lamport (1974, 1979) describe y demuestra el algoritmo
Bakery. Ben Ari (1982) describe la evolución de algoritmos de exclusión mutua y proporciona una prue-
ba del algoritmo de Dekker. Ben Ari (2006) analiza la programación concurrente y distribuida. Peterson
(1981), Lamport (1986, 1991) y Raynal (1986) son otras fuentes sobre algoritmos de exclusión mutua.
Dijkstra (1965) propuso los semáforos. Hoare (1972) y Brinch Hansen (1972) analizan las regiones
críticas y críticas condicionadas, que son constructores de sincronización que precedían a los monitores.
Brinch Hansen (1973) y Hoare (1974) describen el concepto del monitor. Buhr et al. (1995) describen
diferentes implantaciones de monitores. Richter (1999) describe la sincronización de hilos en programas de
C/C bajo Windows. Christopher y Thiruvathukal (2001) lo hacen con respecto al concepto de monito-
res en Java, lo comparan con los monitores de Brinch Hansen y Hoare, y concluyen que la sincronización
de Java no está tan bien desarrollada como los monitores de Brinch Hansen y Hoare.
Una primitiva o constructor de sincronización está completa si se puede usar para implementar todos
los problemas de sincronización de procesos. La integridad de los semáforos fue discutido en Patil (1971),
Kosaraju (1975) y Lipton (1974).
Brinch Hansen (1973, 1977) y Ben Ari (1982, 2006) analizan la metodología para la construcción de
programas concurrentes. Owicki y Gries (1976) y Francez y Pneuli (1978) abordan la metodología para
demostrar la corrección de programas concurrentes.

11 MAQ. CAP. 09(F0694).indd 463 8/10/07 1:05:56 AM


464 CAPÍTULO 9 Sincronización de procesos

Vahalia (1996) y Stevens y Rago (2005) analizan la sincronización de procesos en Unix. Beck et al.
(2002), Bovet y Cesati (2003) y Love (2005) lo hacen respecto a la sincronización en Linux. Mauro y Mc-
Dougall (2001) evalúan la sincronización en Solaris, mientras que Richter (1999) y Russinovich y Solomon
(2005) analizan las características de sincronización en Windows.

1. Beck, M., H. Bohme, M. Dziadzka, U. Kunitz, R. Magnus, C. Schroter y D. Verworner (2002):


Linux Kernel Programming, Pearson Education,
2. Ben Ari, M. (1982): Principles of Concurrent Programming, Prentice-Hall International, Engle-
wood Cliffs, New Jersey.
3. Ben Ari, M. (2006): Principles of Concurrent and Distributed Programming, 2a. ed., Prentice-
Hall, Englewood Cliffs, New Jersey.
4. Bovet, D.P. y M. Cesati (2003): Understanding the Linux Kernel, O’Reilly, Sebastopol.
5. Brinch Hansen, P. (1972): “Structured multiprogramming”, Communications of the ACM, 15 (7),
574-578.
6. Brinch Hansen, P. (1973): Operating System Principles, Prentice-Hall, Englewood Cliffs, New
Jersey.
7. Brinch Hansen, P. (1975): “The Programming language concurrent Pascal”, IEEE Transactions on
Software Engineering, 1 (2), 199-207.
8. Brinch Hansen, P. (1977): The Architecture of Concurrent Programs, Prentice-Hall, Englewood
Cliffs, New Jersey.
9. Buhr, M., M. Fortier y M.H. Coffin (1995): “Monitor classification”, Computing Surveys, 27 (1),
63-108.
10. Chandy, K.M. y J. Misra (1988): Parallel Program Design: A Foundation, Addison-Wesley, Rea-
ding.
11. Christopher, T.W. y G.K. Thiruvathukal (2001): Multithreaded and networked programming, Sun
Microsystems.
12. Courtois, P.J., F. Heymans y D.L. Parnas (1971): “Concurrent control with readers and writers,
Communications of the ACM, 14 (10), 667-668.
13. Dijkstra, E.W. (1965): “Cooperating sequential processes”, Technical Report EWD-123, Techno-
logical University, Eindhoven.
14. Francez, N. y A. Pneuli (1978): “A proof method for cyclic programs”, Acta Informatica, 9, 133-
157.
15. Hoare, C.A.R. (1972): “Towards a theory of parallel programming”, Operating Systems Techni-
ques, Hoare, C.A.R. y R.H. Perrot (Ed.), Academic Press, London, 1972.
16. Hoare, C.A.R (1974): “Monitors: an operating system structuring concept”, Communications of
the ACM, 17 (10), 549-557.
17. Kosaraju, S. (1973): “Limitations of Dijkstra’s semaphore primitives and petri nets”, Operating
Systems Review, 7, 4, 122-126.
18. Lamport, L. (1974): “A new solution of Dijkstra’s concurrent programming problem”, Communi-
cations of the ACM, 17, 453-455.
19. Lamport, L. (1979): “A new approach to proving the correctness of multiprocess programs”, ACM
Transactions on Programming Languages and Systems, 1, 84-97.
20. Lamport, L. (1986): “The mutual exclusion problem”, Communications of the ACM, 33 (2), 313-
348.

11 MAQ. CAP. 09(F0694).indd 464 8/10/07 1:05:56 AM


Bibliografía 465

21. Lamport, L. (1991): “The mutual exclusion problem has been solved”, ACM Transactions on
Programming Languages and Systems, 1, 84-97.
22. Lipton, R. (1974): “On synchronization primitive systems”, Ph.D. Thesis, Carnegie-Mellon
University.
23. Love, R. (2005): Linux Kernel Development, 2a. ed., Novell Press.
24. Mauro, J. y R. McDougall (2001): Solaris Internals—Core Kernel Architecture, Prentice-Hall.
25. Owicki, S. y D. Gries (1976): “Verifying properties of parallel programs: An axiomatic approach”,
Communications of the ACM, 19, 279-285.
26. Patil, S. (1971): “Limitations and capabilities of Dijkstra’s semaphore primitives for co-ordination
among processes”, Technical Report, MIT.
27. Peterson, G.L. (1981): “Myths about the mutual exclusion problem”, Information Processing
Letters, 12, 3.
28. Raynal, M. (1986): Algorithms for Mutual Exclusion, MIT Press, Cambridge.
29. Richter, J. (1999): Programming Applications for Microsoft Windows, 4a. ed., Microsoft Press,
Redmond.
30. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.
31. Stevens, W.R. y S.A. Rago (2005): Advanced Programming in the Unix Environment, 2a. ed.,
Addison Wesley Professional.
32. Vahalia, U. (1996): Unix Internals—The New Frontiers, Prentice-Hall, Englewood Cliffs.

11 MAQ. CAP. 09(F0694).indd 465 8/10/07 1:05:57 AM


Capítulo
10
Paso de mensajes

Hemos discutido cuatro tipos de interacción de procesos en la sección 3.6: la sincronización de


acceso a datos, la sincronización de controles, el paso de mensajes y el intercambio de señales.
Cada tipo de interacción sirve para un propósito distinto. Los temas de sincronización de acceso
a datos y sincronización de controles se abordaron extensamente en el capítulo 9. Un núcleo
proporciona señales para transmitir la ocurrencia de situaciones excepcionales en un proceso;
por tanto, el uso de señales tiene una sintaxis y semántica estándares. Mensajes interprocesos (o
simplemente mensajes) son proporcionados para apoyar el intercambio de informaciones. El
paso de mensajes usa la sintaxis sustentada por el núcleo, pero la información transmitida en un
mensaje no tiene una sintaxis y semántica estándares; el proceso del receptor decide cómo dedu-
cir su significado.
El paso de mensajes es apropiado para una variedad de situaciones donde el intercambio de
informaciones juega un papel clave. Su mejor uso es en un paradigma de servicio, donde un
proceso transmite un mensaje a otro proceso para usar algún servicio que éste ofrece. Debido a
su generalidad, el paso de mensajes también puede usarse para otras formas de interacción de
procesos, tales como la sincronización de acceso a datos y la sincronización de controles; sin
embargo, para estos propósitos es mucho más conveniente usar las características de sincroniza-
ción especiales que analizamos en el capítulo 9.
La generalidad y utilidad del paso de mensajes depende de las características de las llamadas
al sistema que se usan para transmitir y recibir mensajes, y de los arreglos usados por el núcleo
para almacenarlos y entregarlos. Describiremos diferentes arreglos de paso de mensajes y anali-
zaremos su significado para procesos de usuarios y para el núcleo. También describiremos el
paso de mensajes en los sistemas operativos de Unix y Windows.

10.1 VISTA DE CONJUNTO DEL PASO DE MENSAJES

Como hemos visto en la sección 3.6, los procesos interactúan entre sí en cuatro formas: sincro-
nización del acceso a datos, sincronización de controles, paso de mensajes e intercambio de se-
ñales. Es importante diferenciar entre el intercambio de mensajes y el de señales. Las señales
tienen una sintaxis y semántica estándares y se usan para implementar interacciones predefinidas

12 MAQ. CAP. 10(F0694).indd 466 8/10/07 1:11:57 AM


10.1 Vista de conjunto del paso de mensajes 467

entre procesos. Los mensajes interproceso (o simplemente mensajes) buscan la generalidad de la


interacción: un mensaje no tiene una sintaxis y semántica estándares; el proceso receptor decide
cómo deducir su significado.
El paso de mensajes es adecuado para situaciones donde los procesos quieren intercambiar
informaciones, o en situaciones donde un proceso quiere influir, o posiblemente alterar, el curso
de ejecución de otro proceso. El paso de mensajes también puede usarse para otras formas de
interacción, tales como la sincronización de accesos a datos y la sincronización de procesos; sin
embargo, para estos propósitos es mucho más sencillo usar los elementos de sincronización es-
peciales que analizamos en el capítulo 9.

Proceso Pi Proceso Pj
··· ···
send (pj , <mensaje >); receive (Pi , msg area);
··· ···

Figura 10.1 Paso de mensajes.

La figura 10.1 muestra un ejemplo del paso de mensajes. El proceso Pi transmite un mensa-
je al proceso Pj, ejecutando la sentencia send (pj, <mensaje>), donde send es un módulo de
biblioteca y hace una llamada al sistema send, con Pj y el mensaje como parámetros. La ejecu-
ción de la sentencia receive (Pi, msg_area), donde msg_area es un área en el espacio de
dirección de Pj, da como resultado una llamada del sistema receive.
En caso de una llamada send por parte de Pi, el núcleo verifica si el proceso Pj está bloquea-
do en una llamada receive y, si esto sucede, copia el mensaje a msg_area y activa a Pj. Si el
proceso Pj aún no ha ejecutado una llamada de receive, el núcleo procura entregarle el mensaje
cuando ejecuta una llamada de receive en algún momento futuro. Cuando el proceso Pj recibe el
mensaje, lo interpreta y toma la acción correspondiente. Esto podrá dar como resultado una res-
puesta que se transmite a Pi mediante la ejecución de una sentencia send.
En principio, puede ejecutarse el paso de mensajes usando variables compartidas. Por ejem-
plo, msg_area en la figura 10.1 podría ser una variable compartida. Pi podría depositar un valor
o un mensaje en la variable compartida, y Pj podría recogerlo allí. Sin embargo, este proceso
requiere que cada par de procesos comunicantes cree una variable compartida. Tendrían que
estimar el tamaño correcto de la variable compartida y compartir su nombre. También tendrían
que usar una sincronización análoga a la del problema de productores/consumidores (véase la
sección 9.5.1) para asegurar que un proceso receptor sólo accederá a un mensaje en una variable
compartida después de que un proceso transmisor lo haya depositado allí. Los mensajes interpro-
ceso son más sencillos de usar porque el núcleo es responsable del almacenamiento temporal y
de la entrega de mensajes. Además, los mensajes se vuelven indispensables en un ambiente
donde el planteamiento de la variable compartida no es factible. Otras ventajas de los mensajes
interproceso ya se analizaron en la sección 3.6.3.

Problemas del paso de mensajes La tabla 10.1 describe los problemas del paso de men-
sajes. Éstos dictan los arreglos de implementación, y también influyen el poder y la generalidad

12 MAQ. CAP. 10(F0694).indd 467 8/10/07 1:11:58 AM


468 CAPÍTULO 10 Paso de mensajes

Tabla 10.1 Temas del paso de mensajes

Tema Aspectos importantes


Nombrado de procesos Procesos que participan en una transferencia de mensajes o son explícita-
mente indicados en sentencias de send y receive, o bien que los deduce
el núcleo de alguna otra manera.
Método para transferir Ya sea un proceso transmisor que es bloqueado hasta que el mensaje envia-
mensajes do por él se ha entregado, el orden en el cual se entregan los mensajes al
proceso receptor y el manejo de condiciones excepcionales en el paso de
mensajes.
Responsabilidades del Almacenamiento temporal de mensajes con entrega pendiente a procesos
núcleo receptores. Bloqueo y activación de procesos.

del paso de mensajes. Por ejemplo, requerir de un proceso transmisor que conozca la iden-
tidad de un proceso receptor podrá limitar el alcance del paso de mensajes a procesos en el
mismo programa de aplicación. Relajar este requerimiento ampliaría el paso de mensajes a pro-
cesos de programas de aplicación diferentes, e incluso a procesos que se ejecutan en sistemas de
computación diferentes. Del mismo modo, proporcionar la entrega de mensajes en orden FIFO
podrá ser bastante restrictivo; los procesos podrán querer recibir los mensajes en algún orden de
su propia elección.
Las llamadas al sistema send y receive actúan como primitivas de comunicación. El número
y significado de sus parámetros es determinado por el tema que se describe en la tabla 10.1.
Abordaremos varios aspectos de estas primitivas en las secciones siguientes.

10.1.1 Nombrado directo e indirecto

Las sentencias send y receive que se muestran en la figura 10.1 usan el nombrado directo.
Aquí los procesos transmisores y receptores mencionan los nombres del otro usando la siguiente
sintaxis:

send (<proceso_de_destino>, <mensaje>);


receive (<proceso_fuente>, <área_de_mensaje>);

donde <proceso_de_destino> y <proceso_fuente> son nombres de procesos (normalmente se


trata de identificadores de procesos asignados por el núcleo), <mensaje> es la forma textual del
mensaje que se va a transmitir y <área_de_mensaje> es un área de memoria en el espacio de
dirección del receptor donde el mensaje se ha de entregar.
En el nombrado simétrico, tanto los procesos transmisores como los receptores tienen que
especificar los nombre del otro. Este requerimiento parece bastante natural; sin embargo, de allí
surgen dos dificultades. En primer lugar, procesos que no pertenecen a la misma aplicación des-
conocen los nombres de los demás. En segundo, este requerimiento es inconveniente para pro-
cesos de servidores. Por ejemplo, un servidor de impresión en un SO recibe solicitudes de
impresión de todos los procesos del sistema. No sabe qué proceso le transmitirá la siguiente so-
licitud de impresión, así que no puede especificar el <proceso fuente> en una llamada de re-
ceive. En estas situaciones se usa el nombrado asimétrico. Las sentencias send y receive que
usan el nombrado asimétrico tienen la siguiente sintaxis:

12 MAQ. CAP. 10(F0694).indd 468 8/10/07 1:11:58 AM


10.1 Vista de conjunto del paso de mensajes 469

send (<proceso_de_destino>, <mensaje>);


receive (<área_de_mensaje>);

Aquí el receptor no nombra el proceso del que desea recibir un mensaje; el núcleo le entrega un
mensaje que le transmitió algún proceso.
En el nombrado indirecto, los procesos no mencionan el nombre del otro en sentencias de
send y receive. Abordaremos este tema en la sección 10.3.

10.1.2 Sends bloqueadores y no bloqueadores

La primitiva send tiene dos variantes. Un send bloqueador impide la ejecución a un proce-
so transmisor hasta que el mensaje que se transmite es entregado a su destino. Un send no
bloqueador permite que un transmisor continúe la ejecución después de ejecutar un send, inde-
pendientemente de si el mensaje es entregado en forma inmediata. La primitiva receive nor-
malmente es bloqueadora. De este modo, un proceso que realiza un receive debe esperar hasta
que se le pueda entregar un mensaje. Los pasos de mensajes que usan sends bloqueadores y no
bloqueadores también se conocen como pasos de mensajes síncronos y asíncronos, respectiva-
mente.
El paso de mensajes que usa sends bloqueadores ofrece unas propiedades agradables tanto
para procesos de usuarios como para el núcleo. Un proceso transmisor tiene la garantía de que el
mensaje transmitido por él es entregado antes de que continúe su ejecución. Esta propiedad sim-
plifica el diseño de procesos concurrentes. Las acciones del núcleo también son más sencillas
porque éste puede permitir que un mensaje permanezca en el área de memoria del transmisor
hasta que se entregue. Sin embargo, el bloqueo podrá retrasar innecesariamente un proceso
transmisor en determinadas situaciones, por ejemplo, mientras está comunicando con un servi-
dor de impresión enormemente cargado.
Cuando se usa un send no bloqueador, un transmisor queda libre para continuar su ejecución
inmediatamente después de transmitir un mensaje. Sin embargo, no tiene manera de saber cuán-
do es entregado su mensaje, ni si es entregado al receptor y, por ende, no sabe cuándo es seguro
volver a usar el área de memoria que contiene el texto de un mensaje. Para superar este proble-
ma, el núcleo asigna un buffer en el área de sistema y copia un mensaje en el buffer. Esta carac-
terística involucra un compromiso sustancial de memoria cuando existen muchos mensajes sin
entregar. También consume tiempo del CPU, ya que un mensaje se tiene que copiar dos veces,
una en un buffer de sistema cuando se ejecuta una llamada send, y posteriormente en el área de
mensaje del receptor en el momento de la entrega del mensaje.

Ejemplo 10.1 Considere un proceso Pi con el siguiente texto:

Send (Pj, “ . . .”);


...
Send (Pk, “ . . .”);
...

Si se usa un send bloqueador, se bloquearía el proceso Pi en el primer send hasta que el proceso
Pj ejecute una sentencia receive coincidente. De este modo, su progreso dependería de cuándo los
procesos Pj y Pk realicen sus receive. Si se usa un send no bloqueador, Pi puede progresar inde-
pendientemente de Pj y Pk. Sin embargo, el núcleo tiene que poner sus mensajes a Pj y Pk en un

12 MAQ. CAP. 10(F0694).indd 469 8/10/07 1:11:58 AM


470 CAPÍTULO 10 Paso de mensajes

almacenamiento intermedio hasta que estén entregados. El proceso Pi no tiene manera de saber si
los mensajes fueron entregados a Pj y Pk.

10.1.3 Condiciones excepcionales

Pueden presentarse varias condiciones excepcionales durante la entrega de mensajes. A conti-


nuación mencionamos algunas de ellas:

1. El proceso de destino mencionado en un send no existe.


2. En el nombrado simétrico, el proceso fuente mencionado en un receive no existe.
3. Un send no puede ser ejecutado porque se acabó la memoria de buffer del núcleo.
4. No existe ningún mensaje para un proceso cuando ejecuta una sentencia receive.

En los casos 1 y 2, el proceso que ejecuta la sentencia send o receive que lleva a la excep-
ción puede cancelarse, y su código de terminación puede ponerse para describir la condición
excepcional. En el caso 3, el proceso puede estar bloqueado hasta que algún espacio de buffer
esté disponible debido a un receive ejecutado por otros procesos. El caso 4 realmente no es
una excepción si los receive son bloqueadores (¡por lo general, lo son!), pero se puede tratar
como una excepción para dar algo de flexibilidad al proceso receptor. Por ejemplo, el núcleo
puede devolver un código de estatus correspondiente cuando se da esta condición. Si el código
de estatus es “no hay mensajes disponibles”, el proceso receptor tiene la opción de esperar la
llegada de un mensaje o de volver a ejecutar un receive después de un tiempo. En el caso an-
terior puede repetir la sentencia receive con una bandera para indicar que la indicación de esta
condición se debe suprimir. A fin de apoyar estas opciones, puede usarse la siguiente sintaxis
para una sentecia receive:

receive (<proceso_fuente>, banderas, área_de_estatus, <área_de_mensaje>);

donde <proceso_fuente> sólo se especifica cuando se usa el nombrado simétrico y área_de_


estatus es el área donde el núcleo deberá regresar la información de estatus. El módulo de biblio-
teca receive pasa estos parámetros al núcleo en una llamada al sistema receive. Las acciones
del núcleo referentes a condiciones excepcionales son regidas por banderas. La llamada receive
regresa después de poner la información de estatus en área_de_estatus.
Al dominio del SO le pertenecen excepciones más severas. Ellas incluyen bloqueos mutuos
de comunicación, donde los procesos entran en una condición mutua de espera debido a los re-
ceive, o en situaciones difíciles de manejar, como un proceso que espera por mucho tiempo una
llamada receive.

10.2 IMPLEMENTAR EL PASO DE MENSAJES

10.2.1 El almacenamiento intermedio de mensajes interproceso


Cuando un proceso Pi transmite un mensaje a un proceso Pj usando un send no bloqueador, el
núcleo construye un bloque de control de mensajes interproceso (BCMI) para almacenar toda la
información necesaria a fin de entregar el mensaje (véase la figura 10.2). El bloque de control

12 MAQ. CAP. 10(F0694).indd 470 8/10/07 1:11:59 AM


10.2 Implementar el paso de mensajes 471

Punteros BCMI
Proceso transmisor
Proceso de destino
Longitud del mensaje
Texto del mensaje
o dirección

Figura 10.2 Bloque de control de mensajes interproceso (BCMI).

contiene nombres de procesos de transmisores y destinos, la longitud del mensaje y el texto de


éste. Al bloque de control se le asigna un buffer en el área del núcleo, y el buffer es ingresado a
la lista correspondiente usando el campo puntero BCMI. Cuando el proceso Pj ejecuta una lla-
mada receive, el núcleo copia el mensaje desde el BCMI correspondiente al área de mensajes
proporcionado por Pj.
El núcleo puede simplificar la entrega de mensajes usando el campo de puntero del BCMI
para formar listas de varios BCMI. Si se usa el nombrado simétrico, sends no bloqueadores y
entrega de mensajes FCFS, puede formarse una lista separada para cada par de procesos comu-
nicantes. Si se usan sends bloqueadores, cuando mucho un BCMI existirá para cada par de pro-
cesos comunicantes. En este caso, puede llevarse una sola lista de BCMI por proceso receptor.
Puede realizarse una búsqueda en esta lista para localizar el BCMI correcto cuando el proceso
ejecuta un receive. En un nombrado asimétrico puede formarse una sola lista de los BCMI por
proceso receptor (véase la figura 10.3). Cuando un proceso ejecuta un receive, el primer BCMI
en su lista puede ser procesado para entregar un mensaje.

Encabezados de Listas BCMI


listas para procesos
Pi

Pj –
..
.
Pr

Figura 10.3 Listas de mensajes no entregados en el paso de mensajes usando el nombrado asimétrico.

Si se usan sends bloqueadores, el núcleo puede guardar un mensaje en el área de memoria


del transmisor. Sin embargo, el uso de un BCMI podrá ser preferible incluso en este caso porque
un proceso transmisor puede ser cambiado cuando está esperando que su mensaje sea entregado.
Los requerimientos de memoria no son grandes porque sólo se necesita un buffer por proceso

12 MAQ. CAP. 10(F0694).indd 471 8/10/07 1:11:59 AM


472 CAPÍTULO 10 Paso de mensajes

transmisor. Este esquema se simplifica aún más si se usan mensajes de longitud fija en el siste-
ma. Si las longitudes de mensajes son variables, o si se usan sends no bloqueadores, es posible
que el núcleo tenga que reservar una cantidad considerable de memoria para mensajes interpro-
ceso. En estos casos podrá guardar textos de mensajes en el disco. Un BCMI luego contendrá
la dirección del bloque del disco donde el mensaje está almacenado, en lugar del propio texto
del mensaje.

10.2.2 Entrega de mensajes interproceso

Se presentan dos posibilidades cuando un proceso Pi transmite un mensaje al proceso Pj:

• El proceso Pj ya ejecutó un receive y se encuentra en estado bloqueado.


• El proceso Pj no ha ejecutado un receive, pero podrá ejecutarlo en el futuro.
En el primer caso, el núcleo debe procurar entregar el mensaje a Pj inmediatamente, y cambiar
su estado a listo. En el segundo, el núcleo debe entregar el mensaje cuando Pj ejecute un receive
coincidente.
Las acciones de entrega de mensajes del núcleo son iniciadas por eventos de send y receive,
así que pueden implementarse usando bloques de control de eventos (BCE). Como analizamos
en la sección 3.3.6, se crea un BCE para un evento cuando algún proceso decide esperar su ocu-
rrencia. Un BCE contiene tres campos:

• La descripción de un evento anticipado.


• El identificador (id) del proceso que espera este evento.
• Un puntero BCE para formar listas de varios BCE.
Se usa un BCE para activar el proceso en espera cuando ocurre el evento anticipado.

Pi recibe de Pi Pj transmite a Pj
bloqueado por Pj bloqueado por Pi
Info sobre evento Pi Info sobre evento Pj

BCP de BCE de BCP de BCE de


proceso transmisor Pi proceso receptor Pj proceso receptor Pj proceso transmisor Pi
a) b)

Figura 10.4 BCE en nombrado simétrico y sends bloqueadores a) en send y b) en receive.

La figura 10.4 muestra el uso de BCE para implementar el paso de mensajes con nombrado
simétrico y sends bloqueadores. Supongamos que el proceso Pi transmite un mensaje al proceso
Pj. La figura 10.4a) ilustra el caso cuando el proceso Pi ejecuta una llamada send antes de
que Pj ejecute una llamada receive. Cuando el control llega al manejador de eventos, para los
eventos send, el manejador verifica y se da cuenta de que el proceso Pj actualmente no está
bloqueado para un mensaje, es decir, el evento send no fue anticipado. El manejador de eventos

12 MAQ. CAP. 10(F0694).indd 472 8/10/07 1:11:59 AM


10.2 Implementar el paso de mensajes 473

sabe que se debe bloquear el proceso Pi en espera de la entrega del mensaje cuando Pj ejecuta un
receive, es decir, ahora se anticipa a un evento receive. Crea entonces un BCE para el evento
“recibir de Pi por Pj” y pone a Pi como identidad del proceso que estará afectado por el evento.
El proceso Pi se pone en estado bloqueado, y la dirección del BCE se pone en el campo de infor-
mación sobre el evento del BCP de Pi.
La figura 10.4b) ilustra el caso cuando el proceso Pj ejecuta una llamada receive antes de
que Pi ejecute una llamada send. Se crea un BCE para un evento “transmitir a Pj por Pi”, y el
identificador de Pj se pone en el BCE para indicar que el estado de Pj estará afectado cuando
ocurra el evento send.

En transmite a Pj por Pi:


S1 Crea un BCMI e inicializa su campo;
S2 Si existe un BCE para un “send a Pj por Pi”;
S3 entonces
a) Entrega el mensaje a Pj;
b) Activa Pj;
c) Destruye el BCE y el BCMI;
d) Regresa a Pi;
S4 si no
a) Crea un BCE para un evento “receive de Pi por Pj” y
pone el identificador de Pi como el proceso que espera el evento;
b) Cambia el estado de Pi a bloqueado y pone la dirección de BCE
en el BCP de Pi;
c) Agrega el BCMI a la lista de BCMI de Pj;
En recibe de Pi por Pj:
R1 Si existe un BCE coincidente para un “receive de Pi por Pj”
R2 entonces
a) Entrega el mensaje del BCMI correspondiente a la lista de Pj;
b) Activa Pi;
c) Destruye el BCE y el BCMI;
d) Regresa a Pj;
R3 si no
a) Crea un BCE para un evento “send a Pj por Pi” y
pone el identificador de Pj como el proceso que espera el evento;
b) Cambia el estado de Pj a bloqueado y pone la dirección de BCE
en el BCP de Psj;

Figura 10.5 Acciones del núcleo en el paso de mensajes usando el nombrado simétrico y sends bloqueadores.

La figura 10.5 muestra los detalles completos de acciones del núcleo para implementar el
paso de mensajes usando el nombrado simétrico y sends bloqueadores. Por motivos anterior-
mente mencionados, el núcleo crea un BCMI a pesar de que un proceso transmisor o receptor
está bloqueado hasta la entrega del mensaje. Cuando el proceso Pi transmite un mensaje al pro-

12 MAQ. CAP. 10(F0694).indd 473 8/10/07 1:11:59 AM


474 CAPÍTULO 10 Paso de mensajes

ceso Pj, el núcleo revisa primero si el send es anticipado, es decir, si un BCE fue creado para el
evento send. Esto hubiese sucedido si el proceso Pj ya hubiera ejecutado una llamada receive de
Pi. Si éste es el caso, la acción S3 inmediatamente entrega el mensaje a Pj y cambia su estado
de bloqueado a listo. El BCE y el BCMI quedan entonces destruidos. Si no existe un BCE para
send, la acción S4 crea un BCE para una llamada receive por parte del proceso Pj, que ahora es
anticipado, bloquea el proceso transmisor e ingresa el BCMI en la lista BCMI del proceso Pj. En
caso de una llamada receive, se toman las acciones opuestas. Se entrega un mensaje al proceso
Pj si un send coincidente ya ha ocurrido, y Pi es activado; de no ser así, se crea un BCE para una
llamada send y Pj es bloqueado.
En los casos donde se usan sends no bloqueadores, las acciones son análogas, excepto para
bloquear y activar el transmisor (véanse las acciones S4 (b) y R2 (b) en la figura 10.5). La creación
de un BCE cuando un mensaje que se está transmitiendo no puede ser entregado de inmediato
(véase la acción S4 (a)) también es innecesaria, puesto que un transmisor no espera recibir un
mensaje.

10.3 BUZONES

Un buzón es un depósito para mensajes interproceso. Tiene una identidad única. El propietario
de un buzón es normalmente el proceso que lo ha creado. Sólo el proceso del propietario puede
recibir mensajes de un buzón. Cualquier proceso que conoce la identidad de un buzón pue-
de transmitirle mensajes. Llamaremos a estos procesos los usuarios de un buzón.
La figura 10.6 ilustra el paso de mensajes usando un buzón llamado sample. El proceso Pi
crea el buzón usando la llamada crear_buzón. El proceso Pj envía un mensaje al buzón usando
el nombre del buzón en lugar de un identificador de proceso en su llamada send. Esto es una
instancia de nombrado indirecto. Un mensaje enviado a sample es almacenado en un buffer. Se
entrega al proceso Pi cuando Pi ejecuta un receive en sample. Algunos otros procesos, por ejem-
plo, Pk y Pl, también podrán transmitir mensajes a sample. Tanto las llamadas crear_buzón
como send regresarán con códigos de estatus para indicar el éxito o fracaso de la llamada. El
núcleo puede asociar un conjunto fijo de buffers con cada buzón, o puede asignar buffers de un
centro común de buffers cuando se transmite un mensaje.
Un núcleo puede proporcionar un conjunto fijo de nombres de buzones. En forma alternati-
va, puede permitir que los procesos de usuarios creen nombres de su elección. En el primer caso,
la confidencialidad de la comunicación entre un par de procesos no se puede garantizar porque
cualquier proceso puede crear un buzón o conectarse con uno. Este problema se hace menos
grave cuando los procesos pueden asignar nombres de buzón de su propia elección. En la sección
10.4 abordaremos las herramientas de Unix para el nombrado de buzones.
A fin de ejercer el control sobre la creación y destrucción de buzones, el núcleo puede reque-
rir un proceso para “conectarse” explícitamente a un buzón antes de empezar a usarlo, y para
“desconectarse” después de terminar su uso. De esta manera, puede destruir un buzón al que
ningún proceso está conectado. Alternativamente, el núcleo puede permitir que el propietario de
un buzón lo destruya. En este caso, el núcleo tiene que informar la destrucción del buzón a todos
los usuarios que se han “conectado” a él. El núcleo puede permitir que la propiedad de un buzón
sea transferida a otro proceso.

Las ventajas de los buzones El uso de un buzón tiene las siguientes ventajas:

12 MAQ. CAP. 10(F0694).indd 474 8/10/07 1:12:00 AM


10.3 Buzones 475

proceso Pi proceso P j
··· ···
´ (sample);
crear buzon enviar (sample, ‘· · ·’);
··· ···
recibir (sample, ‘· · ·’); ···

Pj
sample
Propietario de Usuarios de
Pi Pk
sample sample

buffers Pl

Figura 10.6 Un buzón.

• Anonimidad del receptor: Un proceso que envía un mensaje a un buzón no necesita


conocer la identidad del proceso receptor. Si un SO permite que el receptor de un bu-
zón sea cambiado dinámicamente, un proceso puede asumir la funcionalidad de otro
proceso.
• Clasificación de mensajes: Un proceso podrá crear varios buzones y usar cada uno para
recibir mensajes de un tipo específico. Esta organización permite la fácil clasificación de
mensajes (véase el ejemplo 10.2).

La anonimidad del proceso receptor puede usarse para transferir una función de un proceso
a otro. Considere un SO cuyo núcleo está estructurado en forma de múltiples procesos que se
comunican por medio de mensajes. Interrupciones relevantes para la función de planificación de
procesos pueden ser modeladas como mensajes transmitidos a un buzón llamado planifica-
dor. Si el SO desea usar diferentes criterios de planificación de procesos durante diferentes pe-
riodos del día, puede implementar diferentes planificadores como procesos y pasar la propiedad
del buzón planificador entre estos procesos. De este modo, el planificador de procesos que
actualmente es propietario de planificador puede recibir todos los mensajes relacionados con
la planificación. Las funcionalidades de los servidores de SO pueden transferirse de manera si-
milar. Por ejemplo, todas las solicitudes de impresión pueden dirigirse a una impresora láser en
lugar de a una de agujas, cambiando simplemente la propiedad de un buzón print.
Aunque un proceso puede enviar un mensaje a un buzón en forma anónima, a menudo es
necesario conocer la identidad del transmisor. Por ejemplo, un servidor puede querer devolver
un código de estatus para cada solicitud que recibe. Esto puede lograrse enviando el identificador
del transmisor junto con el texto del mensaje. El transmisor del mensaje no conocerá la identi-
dad del servidor y, por tanto, debe recibir la respuesta del servidor usando un receive asimé-
trico. Si esto no es deseable, puede proporcionarse enviar_a_buzón como una llamada
bloqueadora con un mensaje implícito de retorno. Entonces la devolución de un código de esta-
tus se volverá una parte de la convención para una llamada al servidor.

12 MAQ. CAP. 10(F0694).indd 475 8/10/07 1:12:00 AM


476 CAPÍTULO 10 Paso de mensajes

Un proceso puede usar varios buzones para recibir diferentes tipos de mensajes. Esta carac-
terística puede emplearse para optimizar el funcionamiento de un servidor multifuncional, tal
como se ilustra en el ejemplo 10.2.

Ejemplo 10.2 Un sistema de reservaciones de una línea aérea consiste en una base de datos cen-
tralizada y un conjunto de procesos de reservaciones. Cada proceso representa un agente de reser-
vaciones. Un proceso de reservaciones transmite mensajes de consulta, reservación y cancelación
a los buzones consultar, reservar y cancelar, respectivamente. El propietario de estos buzones es
el servidor de reservaciones. La figura 10.7 muestra el servidor de reservaciones. El servidor reali-
za llamadas receive en los buzones usando la sintaxis de la sección 10.1.3. Los valores de flags1,
flags2 y flags3 son elegidos de tal manera que una llamada receive regresa con un código de falla si
no existe ningún mensaje. A fin de optimizar su desempeño, el servidor procesa todos los mensajes
de cancelación pendientes antes de procesar una solicitud de reservación o una de consulta, y pro-
cesa las reservaciones con una prioridad mayor que las consultas. Su funcionamiento es simplifica-
do por la separación de los mensajes de consulta, reservación y cancelación en tres buzones.

repetir
mientras receive (reservar, flags1, msg_area1) devuelve un mensaje
mientras receive (cancelar, flags2, msg_area2) devuelve un mensaje
procesa la cancelación;
procesa la reservación;
si receive (consultar, flags3, msg_area3) devuelve un mensaje entonces
mientras receive (cancelar, flags2, msg_area2) devuelve un mensaje
procesa la cancelación;
procesa la consulta;
para siempre

Figura 10.7 Servidor de reservación de una línea aérea usando tres buzones.

10.4 PASO DE MENSAJES EN UNIX

El sistema V versión 4 de Unix (Unix SVR4) proporciona tres herramientas de comunicación de


mensajes interproceso: tuberías, colas de mensajes y sockets. Una tubería es una herramienta
de comunicación universal, mientras que las colas de mensajes y sockets se usan para el paso de
mensajes. Estas herramientas tienen diferentes alcances. Las tuberías sólo pueden ser usadas por
procesos que pertenecen al mismo árbol de procesos, mientras que las colas de mensajes sólo
pueden ser usadas por procesos que existen dentro del “dominio de sistema Unix”, que es el
dominio de Unix que opera en un sistema de computación. Los sockets pueden ser usados por
procesos dentro del dominio del sistema Unix y dentro de ciertos dominios del Internet. La figu-
ra 10.8 ilustra los conceptos de tuberías, colas de mensajes y sockets.

Tuberías Una tubería es un mecanismo de primero en entrar/primero en salir para la trans-


ferencia de datos entre procesos. Una tubería se implementa en el sistema de archivos en muchas
versiones de Unix; sin embargo, se distingue de un archivo porque los datos leídos por el proce-
so son retirados de la tubería. En Unix se ofrecen dos tipos de tuberías que se llaman nombradas
y no nombradas. Su semántica es idéntica, excepto porque una tubería nombrada tiene un regis-

12 MAQ. CAP. 10(F0694).indd 476 8/10/07 1:12:00 AM


10.4 Paso de mensajes en Unix 477

Transmisor Proceso(s) transmisor(es)

Cliente Servidor
···
Socket Socket

Receptor Proceso(s) receptore(s)


a) b) c)

Figura 10.8 Comunicación interprocesos en Unix: a) tubería; b) cola de mensajes; c) socket.

tro en un directorio, y por tanto su uso es iniciado a través de un sistema llamado abierto, mien-
tras que el uso de una tubería no nombrada es iniciado por medio de la llamada pipe.
El núcleo opera en una tubería como una cola, manteniendo dos desplazamientos: uno se
usa para escribir datos en una tubería y otro para leer datos de la tubería. Una tubería se imple-
menta como un archivo, con dos diferencias. El tamaño de aquélla es limitado, de tal forma que
los datos que contiene están ubicados en los bloques directos del nodo índice (véase la sección
7.12.1). Los desplazamientos de lectura y escritura se mantienen en el nodo índice en lugar de en
la estructura de archivos, lo cual prohíbe que un proceso cambie el desplazamiento de una tube-
ría por cualquier medio, excepto la lectura y escritura de datos. Si una tubería está llena, el pro-
ceso que desea escribir datos en ella se duerme. Del mismo modo, un proceso que lee datos de
una tubería se duerme si la tubería está vacía.

Colas de mensajes El concepto de una cola de mensajes es análogo al de un buzón. Una


cola de mensajes es creada por y pertenece a un solo proceso. Otros procesos pueden transmitir
o recibir mensajes a o desde una cola de acuerdo con los permisos de acceso especificados por
su creador. Estos permisos se especifican usando las mismas convenciones que los permisos de
archivos en Unix. Una cola de mensajes tiene una capacidad finita de bytes que pueden ser alma-
cenados en un buffer.
Una cola de mensajes es creada por una llamada msgget, msgget (key, flag), donde key espe-
cifica el nombre de la cola de mensajes y flag indica algunas opciones. El núcleo mantiene un
array de colas de mensajes y sus claves. La primera llamada msgget con una llave dada produce
como resultado la creación de una nueva cola de mensajes. El proceso que ejecuta la llamada
se convierte en propietario de la cola de mensajes. La posición de ésta en el array del sistema se
convierte en el identificador de la cola de mensajes. La llamada msgget devuelve este identifi-
cador. El proceso usa este identificador para transmitir o recibir mensajes. La cuestión del nom-
brado se atiende de la siguiente manera: si un proceso ejecuta una llamada msgget con una llave
que coincide con el nombre de una cola de mensajes existente, el núcleo simplemente devuel-
ve su identificador de cola de mensajes. De este modo, una cola de mensajes puede ser usada por
todos los procesos en el sistema.

12 MAQ. CAP. 10(F0694).indd 477 8/10/07 1:12:00 AM


478 CAPÍTULO 10 Paso de mensajes

Cada mensaje consiste en un tipo de mensaje que es un entero y un texto de mensaje. El


núcleo copia cada mensaje en un buffer y construye un encabezado de mensaje para él, indican-
do el tamaño del mensaje, su tipo y un puntero dirigido al área de memoria donde el texto del
mensaje está almacenado. También lleva una lista de encabezados de mensajes para cada cola
de mensajes a fin de representar mensajes que fueron enviados a la cola, pero que aún no se han
recibido.
Los mensajes se transmiten y reciben usando las siguientes llamadas:

msgsnd (msgqid, msg_struct_ptr, count, flag)


msgrcv (msgqid, msg_struct_ptr, maxcount, type, flag)

Los parámetros count y flag de una llamada msgget especifican el número de bytes que hay en
un mensaje, así como las acciones que deben tomarse si no hay suficiente espacio en la cola de
mensajes, es decir, si debe bloquearse el transmisor o si debe regresarse con un código de error.
msg_struct_ptr es la dirección de una estructura que contiene el tipo de un mensaje, que es un
entero, así como el texto del mensaje; maxcount es la longitud máxima del mensaje y type indica
el tipo de mensaje que va a ser recibido. Cuando se transmite un mensaje a una cola de mensajes
donde hay procesos esperando, el núcleo activa todos los procesos en espera. Cuando está plani-
ficado, un proceso activado verifica si un mensaje está presente y lo consume si lo está, o es
nuevamente bloqueado. El parámetro de tipo en la llamada msgrcv, que es un entero, se usa para
realizar recepciones selectivas de mensajes. Cuando un valor positivo es especificado para el
tipo, el núcleo devuelve el primer mensaje en la cola con un tipo coincidente. Si el valor del tipo
es negativo, el núcleo devuelve el mensaje de valor más bajo cuyo tipo es menor que el valor
absoluto del tipo especificado en la llamada. El ejemplo 10.3 muestra cómo puede usarse este
elemento para codificar el servidor de reservaciones del ejemplo 10.2.

Ejemplo 10.3 La figura 10.9 muestra el servidor de reservaciones codificado usando las primitivas
de paso de mensajes de Unix SVR4. A los mensajes de cancelación, reservación y consulta se les
asignan los tipos 1, 2 y 3, respectivamente. La llamada msgrcv con el tipo = 4 y flag = “sin espera”
devuelve un mensaje de cancelación si es que alguno está presente. Si no hay presencia de mensajes
de cancelación, devuelve un mensaje de reservación si hay uno presente, o un mensaje de con-
sulta. Esto da como resultado el procesamiento prioritario de cancelaciones como deseado, mien-
tras que se evita la necesidad de los tres buzones de la figura 10.7.

Sockets Un socket es simplemente un extremo de una ruta de comunicación. Puede usarse


para la comunicación interprocesos dentro del dominio del sistema Unix, así como en el dominio
del Internet. El mecanismo del socket ofrece la flexibilidad suficiente para que los procesos que
lo usan puedan elegir el modo de operación que mejor convenga para el uso intentado. Para
aplicaciones donde una baja carga general es importante, el proceso comunicante puede emplear
un modo sin conexión mediante datagramas. Para aplicaciones donde la confiabilidad es impor-
tante, los procesos pueden usar un modo de operación basado en conexiones por medio de un
circuito virtual a fin de ofrecer una garantía confiable de entrega de datos.
En un modo de operación basado en conexiones, los procesos son clientes o servidores.
Cada uno de estos procesos crea un socket. Los dos sockets se conectan después para establecer
una ruta de comunicación que puede usarse para transmitir y recibir mensajes (véase la figura
10.8c)). La cuestión del nombrado se aborda de la siguiente manera: el servidor liga su socket

12 MAQ. CAP. 10(F0694).indd 478 8/10/07 1:12:01 AM


10.4 Paso de mensajes en Unix 479

reservations server()
{
msgqid=msgget (reservations data, flags);
...
repeat
msgrcv (msgqid, &msg struct, 200, 4, "no wait");
if ... /* existe un mensaje */
then ... /* procesarlo; */
while(true);
}

Figura 10.9 Un servidor de reservaciones en Unix 5.4.

a una dirección que es válida en el dominio donde el socket será usado. Esta dirección se anuncia
entonces ampliamente en el dominio. Un proceso de cliente usa esta dirección para realizar una
conexión entre su socket y el del servidor. Este método evita el uso de identificadores de proceso
en la comunicación.
Un servidor crea un socket usando la llamada al sistema socket. Ésta tiene la siguiente
forma:

s = socket (dominio, tipo, protocolo)

donde tipo es un datagrama o circuito virtual, y protocolo indica un protocolo de comunicación.


La llamada socket devuelve un identificador de socket al proceso. El proceso del servidor enton-
ces realiza una llamada bind, es decir

bind (s, addr, addrlen)

donde s es el identificador del socket devuelto por la llamada socket, y addr es la dirección para
el socket. Los sockets pueden usarse en diferentes dominios y, por ende, la especificación de
dirección puede tener diferentes longitudes. addrlen indica su longitud. La dirección del socket
se convierte en el “nombre” del socket, lo que se anuncia ampliamente en el dominio para el uso
de clientes.
Un cliente crea un socket usando la llamada socket, por ejemplo, cs = socket (...), y hace un
intento para conectarlo al socket de un servidor, usando la llamada

connect (cs, server_socket_addr, server_socket_addrlen)

Posiblemente hay muchos procesos que traten de conectarse al socket del mismo servidor, así
que el servidor puede decidir si las llamadas de conexión deberán aceptarse, mantenerlas pen-
dientes o rechazarlas. El núcleo soporta dos llamadas para este propósito. La llamada listen, es
decir

listen (s, pending)

indica que el servidor está interesado en considerar a algunas llamadas de conexión para la im-
plementación. pending indica cuántas llamadas de conexión pueden mantenerse pendientes en
un momento dado. El servidor es activado cuando un cliente trata de conectarse a su socket.

12 MAQ. CAP. 10(F0694).indd 479 8/10/07 1:12:01 AM


480 CAPÍTULO 10 Paso de mensajes

Ahora el servidor ejecuta la llamada

new_soc = accept (s, client_addr, client_addrlen)

El núcleo crea un nuevo socket, lo conecta al socket que se menciona en la llamada connect
de un cliente y devuelve el identificador del nuevo socket. El servidor usa este socket para
implementar la comunicación cliente-servidor. El socket mencionado por el servidor en su
llamada listen se usa simplemente para establecer conexiones. Después de la llamada connect,
el servidor normalmente bifurca un nuevo proceso para manejar la nueva conexión. Este mé-
todo deja al socket original, creado por el proceso del servidor libre para aceptar más conexio-
nes por medio de llamadas listen y connect. La comunicación entre un cliente y un servidor es
implementada por medio de llamadas read y write o send y receive. Una llamada send tiene el
formato

count = send (s, mensaje, longitud_mensaje, flags)

Esta llamada devuelve el conteo de bytes realmente transmitidos. Una conexión de socket se
cierra usando la llamada close (s) o shutdown (s, mode).

10.5 EL PASO DE MENSAJES EN WINDOWS

Las herramientas de paso de mensajes en Windows son modelados según las herramientas co-
rrespondientes del sistema operativo distribuido de Mach. Windows ofrece una herramienta de
llamada a procedimientos locales (LPC) para el paso de mensajes entre procesos ubicados en el
mismo sistema de computación. Se basa en la herramienta de llamadas a procedimientos remo-
tos (RPC) que se usa para el paso de mensajes en un ambiente distribuido. De hecho, usa un
arreglo, involucrando códigos de clientes y servidores, similar al que se abordará más adelante,
en la sección 15.6.2. LPC es usado por un proceso a fin de comunicar con un subsistema de am-
biente.
El paso de mensajes mediante LPC usa un esquema de cliente-servidor. LPC ofrece una
selección de tres tipos de paso de mensajes para adecuarse a mensajes pequeños, grandes y es-
peciales para el uso por parte de Win32 GUI. Los primeros dos tipos de LPC usan objetos de
puerto para implementar el paso de mensajes. Cada objeto de puerto es como un buzón. Este
objeto contiene un conjunto de mensajes en una estructura de datos que se llama cola de mensa-
jes. Para establecer la comunicación con clientes, un servidor crea un puerto y se conecta a él. El
nombre de este puerto se publica en el sistema. Un proceso que desea comunicarse con un servi-
dor envía una solicitud de conexión al puerto y se vuelve su cliente. Cuando el servidor recibe la
solicitud, regresa un nombre de puerto al cliente. El servidor puede comunicar con muchos clien-
tes a través del mismo puerto. Mientras transmite un mensaje, un cliente puede indicar si espera
una respuesta.
Para mensajes pequeños, la cola de mensajes contiene el texto del mensaje. Cada uno
de éstos puede tener una longitud total de 304 bytes. Como hemos analizado en la sección 10.1.2,
estos mensajes son copiados dos veces durante el paso de mensajes. Cuando un proceso envía
uno, éste es copiado a la cola de mensajes del puerto. Desde allí es copiado al espacio de direc-
ción del receptor. La longitud del mensaje en este tipo de pase de mensaje está limitada a 304
bytes a fin de controlar la carga general del paso de mensajes.

12 MAQ. CAP. 10(F0694).indd 480 8/10/07 1:12:01 AM


Ejercicio 10 481

El segundo método de paso de mensajes se usa para mensajes largos. Para evitar la carga
general que representa copiar un mensaje dos veces, un mensaje no se copia en la cola de men-
sajes del puerto. En su lugar se pone en un objeto de sección. El objeto de sección es mapeado
en los espacios de dirección de los procesos de cliente y servidor. Cuando el cliente desea enviar
un mensaje, pone el texto del mensaje en el objeto de sección y transmite un mensaje al puerto,
indicando que ha puesto un mensaje en el objeto de sección. El servidor visualiza el mensaje en
el propio objeto de sección. Este uso del objeto de sección evita la necesidad de copiar el men-
saje en el espacio de dirección del servidor.
El tercer tipo de LPC ofrece un método rápido de pase de mensaje y por ello se llama quick
LPC. Como en el segundo tipo de LPC, el mensaje real se pasa a un objeto de sección que es
mapeado en los espacios de dirección tanto en los hilos del servidor como en los del cliente.
Quick LPC usa dos elementos que no están presentes en los otros tipos de LPC. El servidor crea
un hilo para cada cliente. Este hilo es exclusivamente dedicado a solicitudes hechas por este
cliente. El segundo elemento es el uso de un objeto de pares de eventos para sincronizar los hilos
de cliente y servidor. El objeto de pares de eventos consiste en dos objetos de eventos. El hilo del
servidor siempre espera en un objeto de evento y el hilo del cliente lo hace en el otro.
El paso de mensajes se lleva a cabo de la siguiente manera: el hilo del cliente deposita un
mensaje en un objeto de sección, le señaliza al objeto de evento en el cual el hilo del servidor
está esperando y él mismo espera en el otro objeto de evento. De modo similar, el hilo del ser-
vidor espera en un objeto y le señaliza al otro objeto. Para facilitar el paso de mensajes, el nú-
cleo ofrece una función que señaliza automáticamente un objeto de evento del par y espera al
otro objeto.

EJERCICIO 10
1. En la figura 10.5, un proceso puede ser bloqueado debido a la falta de memoria para crear un BCMI o
un BCE. Explique cómo deberían manejarse estas condiciones.
2. Modifique el esquema de la figura 10.5 para implementar el paso de mensajes con nombrado asimétri-
co y sends bloqueadores.
3. El sistema de reservaciones del ejemplo 10.2 usa marcas en una operación de receive para verificar si
existen mensajes pendientes. Una herramienta de buzón no soporta marcas, así que un proceso usa el
siguiente planteamiento para obtener un efecto equivalente: cuando un proceso desea verificar si exis-
ten mensajes en un buzón, transmite un mensaje especial al buzón con el texto “revisando si hay men-
sajes”, y luego ejecuta un receive del buzón. Si su propio mensaje especial es entregado al buzón,
puede concluir que ningún otro mensaje existe en el buzón. Reescriba el sistema de reservaciones
usando este planteamiento. (Sugerencia: ¡Tenga cuidado con mensajes especiales fuera de fecha!)
4. Modifique el esquema de la figura 10.5 para implementar colas de mensajes de Unix.
5. Se ha propuesto introducir un elemento de intervalo de tiempo (time-out) en el paso de mensajes por el
cual un proceso que ejecuta un receive especifica la cantidad de tiempo que está dispuesto a esperar a
un mensaje. Una vez transcurrido este periodo, ocurre un intervalo de tiempo y el proceso es activado.
Implemente este elemento usando el mecanismo de manejo de eventos.
6. Los procesos en un SO usan el paso de mensajes asimétrico y el asíncrono. El núcleo reserva una can-
tidad ilimitada de memoria para ser usada como buffers de mensajes, y no usa espacio del disco para
este propósito. Revise este sistema para ver que no contenga bloqueos mutuos (véase el capítulo 11).
¿Cómo debería detectar el núcleo a estos bloqueos mutuos?

12 MAQ. CAP. 10(F0694).indd 481 8/10/07 1:12:01 AM


482 CAPÍTULO 10 Paso de mensajes

BIBLIOGRAFÍA
Brinch Hansen (1970) describe la comunicación interprocesos en el sistema RC4000. Accetta et al. (1986)
discuten el esquema usado en Mach. Bach (1986), McKusick et al. (1996), Vahalia (1996) y Stevens y Rago
(2005) analizan el paso de mensajes en Unix. Bovet y Cesati (2003) lo hacen con respecto al paso de men-
sajes en Linux, mientras que Russinovich y Solomon (2005) discuten el paso de mensajes en Windows.
Geist et al. (1996) describen y comparan las normas de paso de mensajes PVM y MPI para la progra-
mación paralela.

1. Accetta, M., R. Baron, W. Bolosky, D.B. Golub, R. Rashid, A. Tevanian y M. Young (1986):
“Mach: A new kernel foundation for Unix development”, Proceedings of the Summer 1986 USE-
NIX Conference, junio 1986, 93-112.
2. Bach, M.J. (1986): The Design of the Unix Operating System, Prentice-Hall, Englewood Cliffs.
3. Bovet, D.P. y M. Cesati (2003): Understanding the Linux Kernel, O’Reilly, Sebastopol.
4. Brinch Hansen, P. (1970): “The nucleus of a multiprogramming system”, Communications of the
ACM, 13 (4), 238-241, 250.
5. Geist, G., J.A. Kohl y P.M. Papadopoulos (1996): “PVM and MPI: a comparison of features”,
Calculateurs Paralleles, 8 (2).
6. McKusick, M.K., K. Bostic, M.J. Karels y J.S. Quarterman (1996): The Design and Implementa-
tion of the 4.4 BSD Operating System, AddisonWesley, Reading.
7. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft
Press, Redmond.
8. Stevens, W.R. y S.A. Rago (2005): Advanced Programming in the Unix Environment, 2a. ed.,
Addison Wesley Professional.
9. Tanenbaum, A.S. (2001): Modern Operating Systems, 2a. ed., Prentice-Hall, Englewood Cliffs.
10. Vahalia, U. (1996): Unix Internals—The New frontiers, Prentice-Hall, Englewood Cliffs.

12 MAQ. CAP. 10(F0694).indd 482 8/10/07 1:12:01 AM


Capítulo
11
Bloqueos mutuos

Un bloqueo mutuo (deadlock) es una situación en la que unos procesos esperan de manera inde-
finida las acciones de otros. Puede presentarse en una situación de sincronización, por ejemplo,
cuando unos procesos esperan a que otros les transmitan mensajes o a que liberen recursos que
necesitan. En la vida real pueden darse bloqueos mutuos cuando dos personas esperan una lla-
mada telefónica, una de la otra, o cuando cruzan un pasillo angosto en direcciones opuestas y se
topan en el centro del pasillo.
Los procesos involucrados en un bloqueo mutuo se mantienen obstruidos en forma perma-
nente. Esto afecta los índices de desempeño de sistemas operativos, tales como la capacidad
de procesamiento y la eficiencia de recursos. Un bloqueo mutuo que involucra procesos de SO
puede tener consecuencias más graves, incluso paralizar la operación del SO.
Los sistemas operativos sólo manejan bloqueos mutuos causados por compartir recursos
del sistema. Estos bloqueos mutuos surgen cuando simultáneamente son validadas algunas con-
diciones referentes a solicitudes y asignaciones de recursos. Los planteamientos del manejo de
bloqueos mutuos usan estas condiciones como base para sus acciones. La detección de blo-
queos mutuos identifica un bloqueo, verificando si todas las condiciones necesarias para un
bloqueo mutuo están simultáneamente validadas. La resolución de bloqueos mutuos lo elimina,
cancelando algunos procesos, de tal modo que otros procesos involucrados en el bloqueo mutuo
puedan continuar sus operaciones. Los enfoques de prevención de bloqueos mutuos y de evita-
bilidad de bloqueos mutuos aseguran que un bloqueo mutuo no pueda ocurrir, al no permitir que
las condiciones para bloqueos estén simultáneamente validadas.
Los sistemas operativos usan políticas de asignación de recursos que aseguran la ausencia
de bloqueos mutuos. Analizaremos estas políticas y las relacionaremos con los planteamientos
fundamentales del manejo de bloqueos mutuos.

11.1 DEFINICIÓN DEL BLOQUEO MUTUO

Un conjunto de procesos se encuentra en un bloqueo mutuo si cada uno de éstos está esperando
un evento que sólo puede ser causado por un(os) proceso(s) en el conjunto. De este modo, cada
proceso espera un evento que no puede ocurrir. Esta situación se presenta si se cumplen las con-
diciones de la definición 11.1.

13 MAQ. CAP. 11(F0694).indd 483 8/10/07 1:12:52 AM


484 CAPÍTULO 11 Bloqueos mutuos

Definición 11.1 (Bloqueo mutuo) Un bloqueo mutuo que involucra un conjunto de procesos
D es una situación en la que cada proceso Pi en D cumple con dos condiciones:
1. El proceso Pi está bloqueado en algún evento ej.
2. El evento ej sólo puede ser causado por acciones de otro(s) proceso(s) en D.

Cada proceso capaz de causar el evento ej al que espera el proceso Pi pertenece a D. Esta
propiedad hace imposible que ocurra el evento ej y provoca que el proceso Pi espere indefinida-
mente. Todos los demás procesos en D también esperan indefinidamente.
En un SO pueden presentarse varios tipos de bloqueos mutuos. Tenemos un bloqueo de re-
cursos si el evento esperado por cada proceso en D es la concesión de algún recurso. Un bloqueo
mutuo de comunicación ocurre cuando los eventos esperados tienen que ver con la recepción
de mensajes interproceso. Y uno de sincronización se presenta cuando eventos esperados con-
ciernen al intercambio de señales entre procesos. Un SO está principalmente preocupado por
bloqueos mutuos de recursos porque la asignación de éstos es una de sus responsabilidades. Rara
vez un SO se enfrenta a las otras dos formas de bloqueo mutuo.

11.2 BLOQUEOS MUTUOS EN LA ASIGNACIÓN DE RECURSOS

Diferenciamos entre una unidad de recursos, es decir, un recurso de un tipo específico, y una
clase de recursos, que es la colección de unidades de recursos de un tipo específico. Por ejem-
plo, la clase de impresoras contiene a todas las unidades de impresión existentes en el sistema.
Usamos la notación Ri para una clase de recursos, y rj para una unidad de recursos en una clase
de recursos.
En un sistema pueden ocurrir tres eventos relacionados con la asignación de recursos: la soli-
citud, la asignación y la liberación de un recurso. La tabla 11.1 describe estos eventos. Un evento
de solicitud ocurre cuando un proceso Pi hace una solicitud de un recurso rl. Si rl está en ese mo-
mento asignado a un proceso Pk, el proceso Pi es bloqueado en un evento de asignación para rl. De
hecho, Pi está esperando a que Pk libere el recurso rl. Esto puede causar el evento de asignación
que está esperando Pi. El proceso Pi enfrentará una espera indefinida si la liberación de rl por parte
de Pk se demora indefinidamente. El ejemplo 11.1 ilustra cómo puede suceder esto.

Tabla 11.1 Eventos relacionados con la asignación de recursos

Evento Descripción
Solicitud Un proceso solicita un recurso mediante una llamada al sistema. Si el recurso
está libre, el kernel lo asigna al proceso inmediatamente; de no ser así, cambia
el estado del proceso a bloqueado.
Asignación El proceso se convierte en el poseedor del recurso que le fue asignado. Se
actualiza la información sobre el estado del recurso, y el estado del proceso
cambia a listo.
Liberación Un proceso libera un recurso por medio de una llamada al sistema. Si algunos
procesos están bloqueados en el evento de asignación para el recurso, el ker-
nel usa una regla de desempate, por ejemplo, mediante la asignación FCFS,
para decidir a qué proceso se deberá asignar el recurso.

13 MAQ. CAP. 11(F0694).indd 484 8/10/07 1:12:52 AM


11.2 Bloqueos mutuos en la asignación de recursos 485

Ejemplo 11.1 Un sistema contiene una cinta y una impresora, así como dos procesos Pi y Pj que
usan la cinta y la impresora de la siguiente manera:

proceso Pi proceso Pj
Solicitar cinta Solicitar impresora
Solicitar impresora Solicitar cinta
Usar cinta e impresora Usar cinta e impresora
Liberar impresora Liberar cinta
Liberar cinta Liberar impresora

Las solicitudes de recursos por parte de Pi y Pj se llevan a cabo en el siguiente orden:


1. El proceso Pi solicita la cinta
2. El proceso Pj solicita la impresora
3. El proceso Pi solicita la impresora
4. El proceso Pj solicita la cinta
Las primeras dos solicitudes de recursos se conceden inmediatamente porque una cinta y una
impresora existen en el sistema. Ahora Pi posee la cinta y Pj, la impresora. Cuando Pi pregunta
por la impresora, es bloqueado hasta que Pj la libera. Del mismo modo, Pj es bloqueado hasta que
Pi libera la cinta. Según la definición 11.1, el conjunto de procesos {Pi, Pj} está en un bloqueo
mutuo.

11.2.1 Las condiciones para un bloqueo mutuo de recursos


Podemos interpretar las partes 1 y 2 de la definición 11.1, de tal modo que determinan las con-
diciones bajo las cuales pueden ocurrir bloqueos mutuos de recursos. Un proceso Pj 僆 D es
bloqueado para un evento de asignación por ocurrir, lo que puede ser causado solamente por
acciones de algún otro proceso Pk 僆 D. A partir de Pk 僆 D, las partes 1 y 2 de la definición 11.1
también aplican a Pk. En otras palabras, el recurso solicitado por el proceso Pj es asignado a Pk
que, por su parte, espera a que se le asigne algún otro recurso. Esta condición se llama condición
de círculo cerrado.
Las partes 1 y 2 de la definición también implican que los procesos en D deben esperarse
uno al otro. Esta condición se llama de espera circular. Una espera circular podrá ser directa,
es decir, que Pi espera a Pk y Pk espera a Pi, o puede ocurrir por medio de uno o varios procesos
incluidos en D, por ejemplo, que Pi espera a Pk, Pk espera a Pl y Pl espera a Pi. Otras condiciones
obvias para bloqueos mutuos de recursos son que si el proceso Pi necesita un recurso que en ese
momento está asignado a Pk, Pi, no debe ser capaz de compartirlo con Pk ni de arrebatárselo a
Pk y usarlo.
La tabla 11.2 resume las condiciones que deben cumplirse para que pueda existir un
bloqueo mutuo. Todas ellas deben existir simultáneamente porque una espera circular es
esencial para el bloqueo mutuo, una condición de círculo cerrado es esencial para una espera
circular, y el no compartir y no priorizar recursos son esenciales para una condición de círcu-
lo cerrado.
También las siguientes condiciones son esenciales para que un bloqueo mutuo pueda existir:
Condición Explicación
No retiro de solicitudes de Un proceso bloqueado en una solicitud de
recursos recurso no puede retirar su solicitud

13 MAQ. CAP. 11(F0694).indd 485 8/10/07 1:12:53 AM


486 CAPÍTULO 11 Bloqueos mutuos

Tabla 11.2 Condiciones para el bloqueo de recursos

Condición Explicación
Recursos no Los recursos no se pueden compartir. Un proceso necesita acceso exclusivo
compartibles a un recurso.
Círculo cerrado Un proceso continúa poseyendo los recursos asignados a él mientras está
esperando otros recursos.
No priorización El SO no puede priorizar un recurso de un proceso a fin de asignarlo a otro.
Esperas circulares En el sistema existe una cadena de condiciones de círculo cerrado.

Es posible que las esperas no sean indefinidas si se permite que un proceso retire una solicitud
de recurso y reasuma su ejecución. Esta condición no está explícitamente indicada en la lite-
ratura porque las solicitudes de recursos en un SO de uso general normalmente incluyen esta
herramienta.

11.2.2 Modelación del estado de los recursos

Según el ejemplo 11.1, queda claro que tenemos que analizar solicitudes de recursos y el estado
de asignación de recursos del sistema (en adelante simplemente llamado el “estado de recursos”)
para determinar si un conjunto de procesos se encuentra en un bloqueo mutuo.
Se usan dos tipos de modelos a fin de representar el estado de asignación de un sistema. Un
modelo gráfico puede representar el estado de asignación de una clase restringida de sistemas
en el que un proceso puede solicitar y usar exactamente una unidad de recursos de cada clase
de ellos. Esto permite el uso de un simple algoritmo gráfico para determinar si se cumple la
condición de espera circular por parte de algún proceso. Un modelo matricial tiene la ventaja de
la generalidad. Este modelo puede prefigurar el estado de asignación en sistemas que permiten
que un proceso solicite cualquier número de unidades de una clase de recursos.

11.2.2.1 Modelos gráficos

Una gráfica de solicitud y asignación de recursos (RRAG, por sus siglas en inglés) contiene
dos tipos de nodos: de proceso y de recurso. Un nodo de proceso es representado por un círculo.
Uno de recurso, por un rectángulo y representa una clase de recursos. El número de puntos en un
nodo de recurso indica cuántas unidades de esta clase de recursos existen en el sistema. Pueden
existir dos tipos de aristas entre un nodo de proceso y uno de recurso. Una arista de asignación
es dirigida desde un nodo de recurso a uno de proceso. Esto indica que una unidad de la clase
de recursos es asignada al proceso. Una arista de solicitud es dirigida desde un nodo de proceso
a uno de recurso e indica que el proceso está bloqueado en una solicitud para una unidad de la
clase de recursos. Una arista de solicitud es reemplazada por una arista de asignación cuando se
concede una solicitud pendiente. Una arista de asignación es borrada cuando un proceso libera
una unidad de recursos que le es asignado.
Una gráfica de espera (WFG, por sus siglas en inglés) puede representar el estado de asig-
nación de recursos en forma más concisa cuando cada clase de recursos en el sistema contenga

13 MAQ. CAP. 11(F0694).indd 486 8/10/07 1:12:53 AM


11.2 Bloqueos mutuos en la asignación de recursos 487

sólo una unidad de recursos. La WFG contiene nodos de un solo tipo, es decir, nodos de proceso.
Una arista (Pi, Pj) en la WFG representa el hecho de que el proceso Pi está bloqueado en una
solicitud de un recurso que en ese momento está asignado al proceso Pj, es decir, el proceso Pi
está esperando a que el proceso Pj libere un recurso (de allí el nombre de gráfica de espera).
Representando la misma información en una RRAG, hubiera requerido dos aristas.

Ejemplo 11.2 La figura 11.1a) contiene una RRAG. La clase de recursos R1 contiene sólo una
unidad que está asignada al proceso P1. En ese momento están pendientes solicitudes hechas para
este recurso por parte de P2 y P3. Se asignan unidades de la clase de recursos R2 a los procesos
P2 y P3. Una solicitud por parte del proceso P4 para una unidad de R2 está en ese momento pen-
diente.
La figura 11.1b) muestra una RRAG y una WFG para un sistema que contiene la clase de re-
cursos R1 y los procesos P1, P2 y P3. Las aristas (P2, R1) y (R1, P1) juntas indican que el proceso P2
está esperando el recurso en ese momento asignado a P1, por lo que tenemos una arista (P2, P1) en
la WFG. La arista (P3, P1) indica de manera similar que el proceso P3 está esperando el recurso que
en ese momento está asignado a P1.

p2 p2
p2
p1 R1 R2 p4 p1 R1
• •• • p1

p3
p3 p3
a) b)

Figura 11.1 Gráfica de solicitud y asignación de recursos (RRAG) y gráfica de espera (WFG).

Rutas en WFG y RRAG La naturaleza de las rutas en RRAG y WFG se presta para razonar
sobre la existencia de bloqueos mutuos. Definimos para este propósito la siguiente notación:
Blocked_P : Un conjunto de procesos bloqueados
WFi : El conjunto de espera de Pi, es decir 兵Pj 兩 Pi espera a Pj 其
Usando esta notación, las partes 1 y 2 de la definición 11.1 pueden volverse a formular como
sigue:
D 債 Blocked_P (11.1)
Para todos los Pi 僆 D, WFi 債 D. (11.2)
Considere un sistema en el que cada clase de recursos contiene sólo una unidad de recursos.
Supongamos que el sistema contiene una sola ruta P1-R1-P2-R2 . . . Rn⫺1-Pn en su RRAG. El
proceso Pn no está bloqueado en ningún recurso y ningún proceso está bloqueado en un recurso
asignado a P1. La WFG del sistema contiene la ruta única P1-P2 . . . Pn. Los procesos {P1 . . . Pn}
no están en bloqueo mutuo porque Pn no está bloqueado. Podemos formalmente establecer la
ausencia de un bloqueo mutuo en este sistema usando las condiciones (11.1) y (11.2). Considere
el conjunto de procesos {P1, . . . Pn}. Pn 僆 Blocked_P viola la condición (11.1). Por ende, este
conjunto de procesos no está en bloqueo mutuo. Ahora pruebe el conjunto de procesos {P1, . . .
Pn ⫺1}. Aquí WFn ⫺ 1 ⫽ {Pn} viola la condición (11.2). Del mismo modo, cualquier otro sub-

13 MAQ. CAP. 11(F0694).indd 487 8/10/07 1:12:53 AM


488 CAPÍTULO 11 Bloqueos mutuos

conjunto de {P1, . . . Pn} viola la condición (11.2) para algún proceso. Por tanto, no hay ningún
bloqueo mutuo en el sistema.
Ahora supongamos que Pn ⬅ P1, es decir, que tenemos un ciclo en RRAG y WFG. Los pro-
cesos del conjunto {P1, . . . Pn} entonces cumplen con las condiciones (11.1) y (11.2), puesto que

• {P1, . . . Pn} 債 Blocked_P


• Para todos los Pi 僆 {P1, . . . Pn}, WFi contiene un proceso único Pl, de tal modo que
Pl 僆 {P1, . . . Pn}.

Por tanto, un bloqueo mutuo puede existir. Según este análisis, podemos concluir que la
condición (11.2), que implica la existencia de relaciones mutuas de espera entre procesos de D,
sólo puede ser satisfecha por rutas cíclicas, de tal forma que un bloqueo mutuo no puede existir
a menos que una RRAG o una WFG contengan un ciclo.

Ejemplo 11.3 La figura 11.2 contiene la RRAG para el ejemplo 11.1. La RRAG contiene una ruta
cíclica Pi impresora Pj cinta Pi. Aquí WFi ⫽ {Pj} y WFj ⫽ {Pi}. D ⫽ {P1, P2} cumple con las
condiciones (11.1) y (11.2). Por tanto, los procesos Pi y Pj se encuentran en un bloqueo mutuo.

Pi
impresora cinta
• •

Pj

Figura 11.2 RRAG para el sistema del ejemplo 11.1.

Las rutas en una RRAG se distinguen de las de una WFG cuando las clases de recursos
contienen múltiples unidades de recursos. Considere una ruta P1-R1 . . . Pi-Ri-Pi⫹1- . . .Pn, de
tal forma que una clase de recursos Ri contenga muchas unidades de recursos y un proceso Pk
no incluido en la ruta posea una unidad de la clase de recursos Ri. Si Pk libera la unidad que le
ha sido asignada, entonces esta unidad puede ser asignada a Pi. La arista (Pi, Pi⫹1) desaparecerá
de este modo, incluso sin que Pi⫹1 libere la unidad de Ri que posee. Así, una ruta cíclica en una
RRAG podrá ser rota cuando un proceso no incluido en el ciclo libera una unidad del recurso.
En consecuencia, la presencia de un ciclo no implica necesariamente la existencia de un bloqueo
mutuo si una clase de recursos contiene más de una unidad de recursos. Usamos este hecho en la
sección 11.7 cuando desarrollamos una caracterización formal para bloqueos mutuos. El ejemplo
11.4 ilustra esta situación.

Ejemplo 11.4 Un SO contiene una impresora y dos cintas, así como tres procesos Pi, Pj y Pk. La
naturaleza de los procesos Pi y Pj es la misma que se representa en el ejemplo 11.1: cada uno de
ellos requiere una cinta y una impresora. El proceso Pk necesita sólo una unidad de cinta para su
ejecución. Supongamos que el proceso Pk solicite una cinta antes de que se hagan las solicitudes
1-4 como en el ejemplo 11.1.
La figura 11.3 muestra la RRAG después de que se han hecho todas las solicitudes. En la
gráfica existe un ciclo que involucra Pi y Pj. Éste se romperá cuando el proceso Pk se complete

13 MAQ. CAP. 11(F0694).indd 488 8/10/07 1:12:53 AM


11.2 Bloqueos mutuos en la asignación de recursos 489

Pi
impresora cinta
• ••

Pj Pk

Figura 11.3 RRAG después de que se han hecho todas las solicitudes del ejemplo 11.4.

porque la cinta liberada por él puede ser asignada a Pj. Por tanto, no existe un bloqueo mutuo. Lle-
gamos a la misma conclusión cuando analizamos el conjunto de procesos {Pi, Pj} de acuerdo con
la definición 11.1, porque WFj ⫽ {Pi, Pk} y Pk 僆 {Pi, Pj} viola la condición (11.2).

11.2.2.2 El modelo matricial

En el modelo matricial, el estado de asignación de un sistema es principalmente representado


por dos matrices. La matriz recursos_asignados (allocated_resources) indica cuántas unidades
de recursos de cada clase de ellos están asignadas a cada proceso en el sistema. La matriz recur-
sos solicitados (Requested_resources) representa las solicitudes pendientes. Esta matriz indica
cuántas unidades de recursos de cada clase de recursos fueron solicitadas por cada proceso en
el sistema. Si un sistema contiene n procesos y r clases de recursos, entonces cada una de estas
matrices es una matriz n ⫻ r. El estado de asignación con respecto a una clase de recursos Rk in-
dica el número de unidades de Rk asignadas a cada proceso y el de unidades de Rk solicitadas por
cada proceso. Éstas son representadas como múltiplos de n (Allocated_resources1,k, . . . , Alloca-
ted_resourcesn,k) y (Requested_resources1,k, . . . , Requested_resourcesn,k), respectivamente.
Se pueden usar algunas matrices auxiliares a fin de representar informaciones adicionales
que se requieran para un propósito específico. Dos de éstas son total_de_recursos (Total_resour-
ces) y recursos_libres (free_resources), que indican el número total de unidades de cada clase
de recursos y el de unidades de cada clase de recursos que están libres, respectivamente. Cada
una de estas matrices es una matriz columna que contiene r elementos. El ejemplo 11.5 muestra
un modelo matricial.

Ejemplo 11.5 Usando el modelo matricial, el estado de asignación del sistema de la figura 11.3 es
representado de la siguiente manera:

Cinta de impresora Cinta de impresora Cinta de impresora


Pi 0 1 Pi 1 0 Recursos 1 2
totales
Pj 1 0 Pj 0 1
Pk 0 1 Pk 0 0 Recursos 0 0
libres
Recursos Recursos
asignados solicitados

El modelo matricial no representa las relaciones de espera; éstas tienen que ser deducidas
por un algoritmo. Los algoritmos 11.1 y 11.2 que se discuten en secciones posteriores usan el
modelo matriz.

13 MAQ. CAP. 11(F0694).indd 489 8/10/07 1:12:54 AM


490 CAPÍTULO 11 Bloqueos mutuos

11.3 EL MANEJO DE BLOQUEOS MUTUOS

La tabla 11.3 describe tres enfoques fundamentales que se usan para el manejo de bloqueos mu-
tuos. Cada uno tiene diferentes implicaciones para procesos de usuarios y para el SO.

Tabla 11.3 Enfoques de manejo de bloqueos mutuos

Enfoque Descripción
Detección y El kernel analiza el estado de recursos para verificar si existe un bloqueo mu-
resolución de tuo. De ser así, cancela algún(os) proceso(s) y asigna los recursos que ellos
bloqueos mutuos poseen a otros procesos, de tal modo que el bloqueo mutuo deja de existir.
Prevención de El kernel usa una política de asignación de recursos que asegura que no se
bloqueos mutuos presenten en forma simultánea las cuatro condiciones para bloqueos mutuos
que se mencionan en la tabla 11.2. Este enfoque hace que sea imposible la
presencia de bloqueos mutuos.
Evasión de bloqueos El kernel analiza el estado de recursos para determinar si la concesión de una
mutuos solicitud de recurso podría llevar a un bloqueo mutuo más adelante. Sólo se
conceden solicitudes que no puedan llevar a un bloqueo mutuo, mientras que
las demás se mantienen pendientes hasta que puedan asignarse.

Cuando se usa el enfoque de detección y resolución de bloqueos mutuos, el kernel cancela


algunos procesos cuando detecta un bloqueo mutuo, y reasigna sus recursos a otros solicitantes.
Los procesos cancelados tienen que volverse a ejecutar. En el sistema del ejemplo 11.1, el kernel
detectará un bloqueo mutuo en algún momento dado, después de procesar la cuarta solicitud.
Este bloqueo mutuo puede resolverse cancelando a Pi o Pj y asignando el recurso que poseyó el
proceso cancelado al otro proceso. El costo de este enfoque incluye el de la detección del blo-
queo mutuo y el de la reejecución del proceso cancelado.
En la prevención de bloqueos mutuos, un proceso tiene que adecuarse a las reglas de uso de
recursos estipuladas por el kernel. Por ejemplo, una política de prevención de bloqueos mutuos
sencilla puede requerir que un proceso haga todas sus solicitudes de recursos en conjunto, y el
kernel asignará todos los recursos solicitados al mismo tiempo. Esta regla previene los bloqueos
mutuos, por ejemplo, el del ejemplo 11.1; sin embargo, la regla podrá forzar a un proceso a ob-
tener un recurso mucho tiempo antes de que se necesite.
Cuando se usan mecanismos para evitar bloqueos mutuos, el kernel sólo concede una soli-
citud de recurso si se da cuenta de que la concesión de la solicitud no llevará a bloqueos mutuos
en el futuro. Otras solicitudes se mantienen pendientes hasta que puedan concederse. De este
modo, un proceso podrá enfrentarse a retrasos largos en la obtención de un recurso. En el ejem-
plo 11.1, el kernel se dará cuenta de la posibilidad de un bloqueo mutuo durante el procesamiento
de la segunda solicitud, así que no concederá la impresora al proceso Pj hasta que se complete
el proceso Pi.
La elección del enfoque del manejo de bloqueos mutuos depende del costo relativo de los
enfoques y de sus consecuencias en términos de la sobrecarga, de retrasos en la asignación de
recursos y de restricciones impuestas sobre procesos de usuarios.

13 MAQ. CAP. 11(F0694).indd 490 8/10/07 1:12:54 AM


11.4 Detección y resolución de bloqueos mutuos 491

11.4 DETECCIÓN Y RESOLUCIÓN DE BLOQUEOS MUTUOS

Los bloqueos mutuos pueden detectarse verificando si existe la presencia de un ciclo en una
RRAG o en una WFG, y asegurando que la gráfica cumpla con las otras condiciones analizadas
en la sección 11.7. Sin embargo, un enfoque basado en gráficas tiene la limitación de que no
puede manejar un proceso que requiere más de una unidad de una clase de recursos, por lo que
desarrollamos otro enfoque que usa la definición 11.1 como base para la detección de bloqueos
mutuos.
Considérese un sistema que no contiene bloqueos mutuos. Debe contener por lo menos un
proceso que no está bloqueado en una solicitud de recurso. Todos los recursos que se asignen a
tal proceso estarán libres si el proceso terminase su ejecución sin solicitar más recursos. Éstos
pueden asignarse a procesos que están bloqueados en las solicitudes de esos recursos. Tales
procesos pueden completarse, liberar todos los recursos que les han asignado y seguir así hasta
que todos los procesos en el sistema puedan terminar. En forma correspondiente, verificamos si
existe la presencia de un bloqueo mutuo en un sistema tratando de construir una secuencia de
asignaciones de recursos y liberaciones mediante los cuales los procesos en el sistema puedan
terminar su ejecución. El éxito en la construcción de tal secuencia implica la ausencia de un blo-
queo mutuo en el estado actual del sistema, y el fracaso en su construcción implica la presencia
de un bloqueo mutuo. El ejemplo 11.6 ilustra el uso de este enfoque.

Ejemplo 11.6 En el ejemplo 11.3 (véase la figura 11.2) no hay ninguna secuencia de asignaciones
por medio de la cual los procesos Pi y Pj puedan terminar su ejecución. Por ende, los procesos Pi y
Pj se encuentran en un bloqueo mutuo.
En el ejemplo 11.4, la siguiente secuencia de eventos saca a los procesos Pi y Pj de su estado
bloqueado (véase la RRAG de la figura 11.3):
1. El proceso Pk termina y libera la cinta.
2. La cinta es asignada a Pj. Pj entonces termina y libera la impresora y la cinta.
3. La impresora y la cinta son asignadas entonces al proceso Pi.
Por tanto, no existe ningún bloqueo mutuo.

Análisis del bloqueo mutuo El análisis para detectar la existencia de bloqueos mutuos se
realiza simulando la operación del sistema, desde su estado actual. En la simulación sólo con-
sideraremos dos eventos que son importantes para el análisis de bloqueos mutuos: la asignación
de recurso(s) a un proceso que está bloqueado en una solicitud de recurso y la finalización de un
proceso que no está bloqueado en una solicitud de recurso. Nos referimos a cualquier proceso
que no está bloqueado en una solicitud de recurso como proceso en ejecución. El simulador
intenta construir una secuencia de asignaciones de recursos y liberaciones por medio de la cual
todos los procesos del sistema, ya sean procesos en ejecución o bloqueados, puedan completar
su ejecución.
En la simulación suponemos que un proceso en ejecución finaliza sin hacer solicitudes de
recursos adicionales. Cuando concluye, todos los recursos que se le han asignado están libres.
Estos recursos son asignados a un proceso bloqueado sólo si la asignación pone a este proce-
so en el estado en ejecución. La simulación termina cuando todos los procesos en ejecución
finalizan. Si algunos procesos aún se encuentran en estado bloqueado, entonces deben estar es-
perando recursos asignados a ellos. Puesto que todos los procesos en ejecución han finalizado,

13 MAQ. CAP. 11(F0694).indd 491 8/10/07 1:12:54 AM


492 CAPÍTULO 11 Bloqueos mutuos

los procesos bloqueados enfrentan esperas indefinidas, es decir, se encuentran en un bloqueo


mutuo en su estado actual. No hay ningún bloqueo mutuo en el estado actual si no existe nin-
gún proceso bloqueado cuando termina la simulación. Puesto que se supone que un proceso
en ejecución completa su ejecución sin realizar solicitudes de recursos adicionales, el análisis
de bloqueo mutuo no es susceptible al orden en el que se supone que los procesos bloqueados
se vuelven procesos en ejecución, o al orden en el que los procesos en ejecución supuesta-
mente finalizan.
El análisis de bloqueos mutuos mediante la simulación de la finalización de procesos es
igualmente aplicable a sistemas en los cuales los procesos pueden solicitar más de una unidad de
recursos de una clase de recursos. El ejemplo 11.7 ilustra este hecho.

Ejemplo 11.7 Un SO contiene 10 unidades de una clase de recursos Ri. El sistema ha asignado 4,
4 y 2 unidades de Ri a los procesos P1, P2 y P3, respectivamente. Los procesos P1 y P2 están actual-
mente bloqueados en solicitudes para 6 y 2 unidades del recurso. El proceso P3 está en el estado en
ejecución. Todos los procesos del sistema pueden finalizar como sigue: el proceso P3 finaliza y li-
bera 2 unidades del recurso que tiene asignado. Estas unidades pueden asignarse a P2, que se con-
vierte a en ejecución y finaliza. Las 6 unidades de recursos liberadas por P2 ahora pueden asignarse
a P1 a fin de habilitarlo para finalizar. De este modo, no existen procesos bloqueados cuando termi-
na la simulación, por lo que no existe ningún bloqueo mutuo en el sistema.
Si las solicitudes de los procesos P1 y P2 fueron para 6 y 3 unidades, respectivamente, ninguna
de ellas puede finalizar, incluso después de que el proceso P3 libera 2 unidades de recursos. Estos
procesos están en el estado bloqueado cuando termina la simulación y, por ende, se encuentran en
un bloqueo mutuo.

El análisis de bloqueos mutuos puede detectar un bloqueo mutuo en el estado actual del
sistema. Aun si el estado actual está libre de bloqueos mutuos, un bloqueo mutuo podría presen-
tarse en el futuro. En el ejemplo 11.7, esto podría ocurrir si P2, al que se asignan los recursos
liberados por P3, formula una solicitud para una unidad de recursos más. Por tanto, el análisis
de bloqueos mutuos tiene que realizarse repetidamente durante la operación del SO. Esto puede
lograrse dedicando un proceso del SO exclusivamente a la detección de bloqueos mutuos y
activándolo en intervalos fijos. De manera alternativa, el análisis de bloqueos mutuos puede
ejecutarse cada vez que un proceso es bloqueado en una solicitud de recurso. La sobrecarga
de la detección de bloqueos mutuos dependerá de factores del servidor, tales como el número de
procesos y clases de recursos en el sistema y la frecuencia con que se ejecuta el análisis de blo-
queos mutuos.

11.4.1 Un algoritmo de detección de bloqueos mutuos

El algoritmo 11.1 realiza la detección de bloqueos mutuos en un sistema que contiene n procesos
y r clases de recursos. Free_resources (recursos libres) es un array con r elementos, que indican
cuántas unidades de recursos de cada clase de recursos están en ese momento libres. Allocated_
resources (recursos asignados) es un array n ⫻ r que representa el estado actual de asignación
de recursos. El array Requested_resources (recursos solicitados) indica las solicitudes de recur-
sos en las que en ese momento existen procesos bloqueados.
El algoritmo simula la finalización de un proceso en ejecución Pj, transfiriéndolo del con-
junto Running (en ejecución) al conjunto Finished (terminado) (paso 1 (b)). Los recursos asigna-
dos a Pj se agregan a Free_resources (paso 1 (c)). Entonces el algoritmo selecciona un proceso

13 MAQ. CAP. 11(F0694).indd 492 8/10/07 1:12:54 AM


11.4 Detección y resolución de bloqueos mutuos 493

bloqueado cuya solicitud de recurso puede satisfacerse desde los recursos libres (paso 1 (d)).
Este proceso es transferido del conjunto Blocked al conjunto Running. En algún momento des-
pués, el algoritmo simulará su finalización y lo transferirá de Running a Finished. El algoritmo
termina cuando no existen procesos en el conjunto Running. Cualquier proceso existente en el
conjunto Blocked está en bloqueo mutuo.
La complejidad del algoritmo puede analizarse del siguiente modo: los conjuntos Running
y Blocked pueden contener hasta n procesos, donde n es el número total de procesos en el siste-
ma. El bucle del paso 1 repite ⱕ n veces, y el paso 1 (d) realiza un orden de n ⫻ r trabajo en cada
repetición. Por tanto, el algoritmo requiere un orden de n2 ⫻ r de trabajo.

Algoritmo 11.1 (Detección de bloqueos mutuos)

Entradas

n : Número de procesos;
r : Número de clases de recursos;
Blocked : juego de procesos;
Running : juego de procesos;
Free_resources : array [1..r] de entero;
Allocated_resources : array [1..r, 1..r] de entero;
Requested_resources : array [1..r, 1..r] de entero;

Estructuras de datos

Finished : juego de procesos;

1. repetir hasta el conjunto Running está vacío


a) Selecciona un proceso Pj del conjunto Running;
b) Borra Pj del conjunto Running y agrégalo al conjunto Finished;
c) para k ⫽ 1, r
Free_resources[k] :⫽ Free_resources[k] ⫹ Allocated_resources[j, k];
d) mientras Bloqueado contiene un proceso Pl tal que
para k ⫽ 1..r, Requested_resources[l, k] ⱕ Free_resources[k]
i) para k ⫽ 1, r
Free_resources[k] :⫽ Free_resources[k] ⫺ Requested_resources[l, k];
Allocated_resources [l, k] :⫽ Allocated_resources [l, k]
⫹ Requested_resources [l, k];
ii) Borra Pl del conjunto Blocked y agrégalo al conjunto Running;
2. Si el conjunto Blocked no está vacío entonces
declara los procesos en Blocked en bloqueo mutuo.

Ejemplo 11.8 Un sistema tiene cuatro procesos P1-P4, y 5, 7 y 5 unidades de las clases de recursos
R1, R2 y R3, respectivamente. Se encuentra en el siguiente estado, justo antes de que el proceso P3
haga una solicitud para 1 unidad de la clase de recursos R1:

13 MAQ. CAP. 11(F0694).indd 493 8/10/07 1:12:55 AM


494 CAPÍTULO 11 Bloqueos mutuos

a) Estado inicial
R1 R2 R3 R1 R2 R3 R1 R2 R3
P1
2 1 0 P1 2 1 3 Recursos 0 0 1
P2 P2 1 4 0 libres
1 3 1
P3
1 1 1 P3
P4
1 2 2 P4 1 0 2
Recursos Recursos
asignados solicitados
b) Después de simular la asignación de recursos a P4 cuando finaliza el proceso P3
R1 R2 R3 R1 R2 R3 R1 R2 R3
P1 2 1 0 P1 2 1 3 Recursos 0 1 0
P2 1 3 1 P2 1 4 0 libres
P3 0 0 0 P3
P4 2 2 4 P4
Recursos Recursos
asignados solicitados
c) Después de simular la asignación de recursos a P1 cuando finaliza el proceso P4
R1 R2 R3 R1 R2 R3 R1 R2 R3
P1 4 2 3 P1 Recursos 0 2 1
P2 1 3 1 P2 1 4 0 libres
P3 0 0 0 P3
P4 0 0 0 P4
Recursos Recursos
asignados solicitados
d) Después de simular la asignación de recursos a P2 cuando finaliza el proceso P1
R1 R2 R3 R1 R2 R3 R1 R2 R3
P1 0 0 0 P1 Recursos 3 0 4
P2 2 7 1 P2 libres
P3 0 0 0 P3
P4 0 0 0 P4
Recursos Recursos
asignados solicitados
Figura 11.4 Operación del algoritmo 11.1, el algoritmo de detección de bloqueos mutuos.

R1 R2 R3 R1 R2 R3 R1 R2 R3
P1 P1 Total de
2 1 0 2 1 3 recursos 5 7 5
P2 1 3 1 P2 1 4 0
P3 P3 R1 R2 R3
0 1 1 Recursos
P4 1 2 2 P4 1 0 2 libres 1 0 1

Recursos Recursos
asignados solicitados
Una unidad de recursos de la clase de recursos R1 es asignada al proceso P3, y se emplea el algorit-
mo 11.1 para verificar si el sistema se encuentra en un bloqueo mutuo. La figura 11.4 muestra los
pasos de la operación del algoritmo. Las entradas a él son los conjuntos Blocked y Running inicia-
lizados en {P1, P2, P4} y {P3}, respectivamente, así como las matrices Recursos_asignados, Recur-
sos_solicitados y Recursos_libres, como se muestra en la figura 11.4a). El algoritmo transfiere el
proceso P3 al conjunto Finished y libera los recursos que le han asignado. El número de unidades
libres de las clases de recursos es ahora 1, 1 y 2, respectivamente. El algoritmo se da cuenta de que

13 MAQ. CAP. 11(F0694).indd 494 8/10/07 1:12:55 AM


11.4 Detección y resolución de bloqueos mutuos 495

la solicitud pendiente del proceso P4 puede satisfacerse en ese momento, así que asigna los recursos
solicitados por P4 y transfiere P4 al conjunto Running (véase la figura 11.4b)). Puesto que P4 es el
único proceso en Running, se transfiere al conjunto Finished. Después de liberar los recursos de P4,
el algoritmo se da cuenta de que puede satisfacerse la solicitud de recurso de P1 (véase la figura
11.4c)) y, después de que finaliza P1, la solicitud de recurso de P2 puede satisfacerse (véase la fi-
gura 11.4d)). El conjunto Running está en ese momento vacío, así que finaliza el algoritmo. No
existe ningún bloqueo mutuo en el sistema porque el conjunto Blocked está vacío.

11.4.2 Resolución de bloqueos mutuos


Dado un conjunto de procesos en bloqueo mutuo D, la resolución de bloqueos mutuos implica
romper el bloqueo mutuo para asegurar el progreso para unos procesos {Pi} 僆 D. Esto puede
lograrse satisfaciendo la solicitud de recurso de un proceso Pi en una de dos formas:
1. Terminando unos procesos {Pj} 傺 D para liberar los recursos solicitados por {Pi}. (Lla-
mamos a cada proceso en {Pj} una víctima de la resolución de bloqueos mutuos.)
2. Agregando nuevas unidades de los recursos solicitados por Pi.
Observe que la resolución de bloqueos mutuos sólo asegura un progreso para un proceso Pi.
No garantiza que Pi se ejecutará hasta la finalización. Esto dependerá de las solicitudes y asigna-
ciones de recursos en el sistema después de que se resuelva el bloqueo mutuo. El ejemplo 11.9
ilustra cómo los conjuntos de espera de RRAG y los sets de espera de procesos cambian como
resultado de la resolución de bloqueos mutuos.

Ejemplo 11.9 La figura 11.5 representa una resolución de bloqueos mutuos mediante la termina-
ción de algunos procesos en bloqueo mutuo. La RRAG de la parte a) muestra un bloqueo mutuo
que involucra los procesos P1, P2, P3 y P4. Este bloqueo mutuo se resuelve eligiendo el proceso P2
como víctima. La parte b) de la figura muestra la RRAG después de terminar el proceso P2 y de
asignar el recurso R3 que posee al proceso P1. La solicitud de recurso hecho por P1 entonces está
satisfecha, y el proceso P4, que esperaba a la víctima antes de la resolución del bloqueo mutuo,
entonces espera a P1, el nuevo poseedor del recurso. Este hecho es importante para la detección de
bloqueos mutuos en el futuro.

R1 R1
• •

p2 p3 p3

R3 • • R2 R3 • • R2
p4 p4
p1 p1
a) b)
Figura 11.5 Resolución de bloqueos mutuos.

En la mayoría de los sistemas, la adición de una nueva unidad de recursos no es práctica, con
excepción de un sistema que enfrenta un bloqueo mutuo de comunicación interproceso. En un
sistema de este tipo, el kernel podrá crear mensajes ficticios y entregarlos a procesos bloqueados

13 MAQ. CAP. 11(F0694).indd 495 8/10/07 1:12:55 AM


496 CAPÍTULO 11 Bloqueos mutuos

en receive. Cada mensaje tendrá una bandera de control que lo identificará como mensaje ficti-
cio. Se esperaría que el proceso que recibe un mensaje ficticio vuelva a intentar un receive des-
pués de un lapso de tiempo, preferentemente después de ejecutar unos send. Este planteamiento
no garantiza que el bloqueo mutuo no se repetirá; sin embargo, podrá habilitar una recuperación
parcial en algunas aplicaciones.

11.5 PREVENCIÓN DE BLOQUEOS MUTUOS

Como se describe en la sección 11.2.1, cuatro condiciones tienen que ser válidas en forma simul-
tánea para que pueda surgir un bloqueo mutuo de recursos en un sistema:

• Los recursos son no compartibles.


• Los procesos retienen algunos recursos mientras esperan otros.
• No es factible priorizar recursos de procesos.
• Existen en el sistema esperas circulares.

Los bloqueos mutuos pueden ser prevenidos si el kernel usa una política de asignación
que asegure que ninguna de estas condiciones pueda surgir. La figura 11.6 ilustra cómo la de-
negación de una de estas condiciones transformaría una RRAG. Si todos los recursos se pue-
den hacer compartibles, las relaciones de espera no existirán en el sistema. Por tanto, las rutas
en una RRAG sólo contendrán aristas de asignación. Por ejemplo, la arista de solicitud (Pi, Rl)
será reemplazado por una arista de asignación (Rl, Pi) en la figura 11.6a), por lo que no pueden
surgir esperas circulares. Si no se permite que ocurra la condición de círculo cerrado, un proceso
poseerá o esperará recursos. Si no se permiten aristas de solicitud, la arista (Pi, Rl) no surgirá en
la figura 11.6b). Si no se permiten aristas de asignación, las aristas (Rk, Pi) y (Rl,..) no surgirán.
En ambos casos, rutas con ⬎ 1 proceso no pueden presentarse y, por tanto, rutas circulares no
pueden existir en una RRAG. Si los recursos se hacen priorizables, el kernel puede asegurar que
los procesos tengan todos los recursos que necesitan. Por ejemplo, en la figura 11.6c), el recurso
Rl puede ser priorizado desde su poseedor actual y asignado al proceso Pi. Por ende, pueden
prevenirse las rutas circulares en la RRAG. Si se quiere evitar esperas circulares, no puede per-
mitirse que algunos procesos esperen recursos, por ejemplo, el proceso Pj en la figura 11.6d). Por
ende, no pueden presentarse esperas indefinidas.
Primero estudiaremos cómo cada una de las cuatro condiciones para el bloqueo mutuo pue-
de ser burlada, y luego analizaremos un par de políticas de asignación de recursos diseñadas para
la prevención de bloqueos mutuos.

Recursos no compartibles El no compartir recursos es causado por la naturaleza de un re-


curso. Por ende, poco se puede hacer acerca de esto. Sin embargo, en algunos tipos de recursos es
posible usar soluciones innovadoras para este problema. Un ejemplo es el sistema de multipro-
gramación THE de los años sesenta. Ese sistema sólo contenía una impresora que no era com-
partible, así que el SO almacenaba en un buffer la salida a impresión producida por un proceso
y producía “imágenes de páginas” de ella “a escondidas”. Tan pronto se había construido una
imagen de página, se ponía en la cola para impresión. Este arreglo mezclaba las páginas impresas
producidas por diferentes procesos, por lo que las páginas impresas por diferentes procesos eran

13 MAQ. CAP. 11(F0694).indd 496 8/10/07 1:12:55 AM


11.5 Prevención de bloqueos mutuos 497

Enfoque Ilustración
Sin este enfoque Con este enfoque
Rl Rl
• •
a) Haz recursos compartibles ⇒
→ Sin esperas
El proceso Pi no es bloqueado Pj
Pi Pi Pj
en el recurso Rl.

Rk Rl Rk Rl
b) Prevén esperas circulares
• • • •
→ Sin rutas con ⇒
> 1 proceso
Al proceso Pi no se le permite
bloquearse en el recurso Rl o no Pi o Pi
se le permite poseer Rk mientras
Rk Rl
hace una nueva solicitud. • •

Pi

Rk Rl Rk Rl
c) Haz recursos priorizables • • • •
→ Sin rutas circulares ⇒
El recurso Rl es priorizado
y asignado a Pi.
Pi Pi

Pj Pj

Rk Rl Rk Rl
d) Prevén esperas circulares
• • ⇒ • •
Al proceso Pj no se le permite
solicitar el recurso Rl.
Pi Pi

Figura 11.6 Enfoques para la prevención de bloqueos mutuos.

separadas manualmente. (Es interesante recalcar que el sistema THE no realizaba el formateo de
páginas para prevenir bloqueos mutuos, sino para mejorar la utilización de la impresora. De he-
cho, la literatura del sistema THE comenta que bloqueos mutuos surgen sólo unas cuantas veces
por año y el operario del sistema puede darse cuenta de ellos. Por ende, el SO no tenía ninguna
previsión para manejar bloqueos mutuos.)
La condición que impide compartir puede ser burlada creando dispositivos virtuales. Enton-
ces, un dispositivo virtual actual no tiene por qué compartir. Este planteamiento puede funcionar

13 MAQ. CAP. 11(F0694).indd 497 8/10/07 1:12:56 AM


498 CAPÍTULO 11 Bloqueos mutuos

para dispositivos de E/S mediante el uso del spooling (colocaci); sin embargo, no puede funcio-
nar para recursos como archivos mutables no compartibles.

Círculo cerrado El círculo cerrado puede prevenirse por medio de dos métodos: no se
deberá permitir en una solicitud que un proceso que bloquea posea algún recurso o no se deberá
permitir que un proceso que posee un recurso haga solicitudes de recursos. En el primer método,
un proceso puede hacer una solicitud de recurso sólo después de liberar el recurso que posee.
Puede solicitar el recurso liberado nuevamente cuando lo necesite. Este método implica que un
recurso deberá ser priorizable. En el segundo método, un proceso puede ser forzado a pedir todos
los recursos que requiere en una sola solicitud, de tal modo que en el resto de su vida no hará
ninguna otra solicitud de recurso. Este método es generalmente más aplicable. Lo analizaremos
en la sección 11.5.1.

Priorización de recursos El no priorizar recursos es causado por la naturaleza de un recur-


so. En algunos casos podrá burlarse esta condición; por ejemplo, el planteamiento de formateo
de páginas del sistema THE puede usarse para hacer que las impresoras sean priorizables; sin
embargo, en general no pueden priorizarse dispositivos secuenciales de E/S.

Espera circular Esta condición implica la existencia de un ciclo en una WFG o en una
RRAG. Es una consecuencia de la condición del círculo cerrado, que es consecuencia a su vez de
las condiciones que impiden compartir y priorizar. Por ende, una espera circular no se presenta
si no surge una de las otras condiciones.
La condición de espera circular puede prevenirse en forma independiente, aplicando una
restricción de validez a cada solicitud de recurso. La restricción de validez es una función
booleana del estado de recursos de un proceso solicitante. Se evalúa como false si la solicitud
podrá llevar a una espera circular en el sistema. Ese tipo de solicitud se rechaza inmediatamente.
Si la restricción de validez se evalúa como true, el recurso es asignado si está disponible; de no
ser así, el proceso es bloqueado para el recurso. En la sección 11.5.2 estudiaremos una política
de prevención de bloqueos mutuos que se sirve de este enfoque.

11.5.1 Todas las solicitudes juntas

Ésta es la política de prevención de bloqueos mutuos más sencilla de todas. Un proceso debe
pedir en una sola solicitud todos los recursos que necesita. Normalmente se hace esta solicitud
al principio de su ejecución. El kernel asigna todos los recursos juntos, por lo que un proceso
bloqueado no posee ningún recurso y jamás se cumple la condición del círculo cerrado. Por
consiguiente, no pueden suceder esperas circulares y bloqueos mutuos.

Ejemplo 11.10 En el ejemplo 11.1, ambos procesos solicitaban una cinta y una impresora juntas.
Ahora un proceso poseerá ambos recursos o ninguno de ellos, por lo que no se cumple la condición
del círculo cerrado.

La simplicidad de implementación hace esta política atractiva para sistemas operativos pe-
queños. Sin embargo, tiene una desventaja práctica: influye en forma adversa en la eficiencia de
utilización de recursos. Por ejemplo, aun si un proceso requiere una cinta al inicio de su ejecu-
ción y una impresora sólo hacia el final, será forzado a solicitar tanto la cinta como la impresora

13 MAQ. CAP. 11(F0694).indd 498 8/10/07 1:12:56 AM


11.5 Prevención de bloqueos mutuos 499

desde el principio. La impresora permanecerá inactiva hasta la parte final de su ejecución y cual-
quier proceso que requiera una impresora tendrá una demora hasta que Pi finalice su ejecución.
Esta situación también reduce el grado de efectividad de la multiprogramación y, por tanto, la
eficiencia de utilización del CPU.

11.5.2 Jerarquización de recursos

Un número único llamado jerarquización de recursos está asociado con cada clase de recursos.
La restricción de validez sobre una solicitud de recurso hecha por un proceso Pi sólo vuelve a
ser true si la jerarquía del recurso solicitado es mayor que la del recurso de mayor rango en ese
momento asignado a Pi. Si la restricción de validez se evalúa como true, el recurso es asignado a
Pi si está disponible; de no ser así, Pi es bloqueado para la utilización del recurso. Si la restricción
de validez se evalúa como false, se termina el proceso que formula la solicitud.
Considérese un sistema que consiste en cinco clases de recursos R1 . . . R5 a los cuales se
asignan las jerarquías de recurso 1 . . . 5, respectivamente. El proceso Pi actualmente posee una
unidad de las clases R1 y R3. Pi será terminado si hace una solicitud para R1, R2 o R3, puesto que
la jerarquía del recurso solicitado no excede la jerarquía de R3, que es el recurso de mayor jerar-
quía poseído por Pi. Si hace una solicitud para R4 o R5, se le asignará el recurso o será bloqueado
en la solicitud del mismo.
La RRAG de la figura 11.7 ilustra la esencia de la jerarquización de recursos. Los recursos
se muestran de tal modo que sus jerarquías están en orden ascendente de izquierda a derecha.
Un nodo de proceso se encuentra debajo del recurso de mayor jerarquía que se le ha asignado.
Entonces, cada arista de solicitud en el RRAG apuntará hacia la derecha en la RRAG. La RRAG
que se ve en la figura 11.7a) muestra la situación en el momento en que se asignan los recursos
R1 y R3 al proceso Pi, y el recurso R5 al proceso Pj. Cuando el proceso Pi hace una solicitud para
R5, se le permite esperar, y la arista de solicitud (Pi, R5) se agrega a la RRAG (véase la figu-
ra 11.7b)). Cuando el proceso Pj hace una solicitud para R3, ésta es rechazada y Pj es cancelado.
De este modo, no se pueden desarrollar ciclos en la RRAG, y no pueden existir bloqueos mutuos.

R1 R2 R3 R4 R5 R1 R2 R3 R4 R5
jerarquía = 1 2 3 4 5 1 2 3 4 5
• • • • • • • • • •

Pi Pi
Pj Pj
a) b)

Figura 11.7 Prevención de bloqueos mutuos usando la jerarquización de recursos.

En general, la ausencia de relaciones circulares de espera en un sistema que usa la jerarqui-


zación de recursos puede argumentarse como sigue: supongamos que rankk denota la jerarquía
asignada a la clase de recursos Rk, y que el proceso Pi posee unidades de la clase de recursos Rk.
Si Pi es bloqueado en una solicitud para una unidad de la misma clase de recursos Rl, entonces
rankk ⬍ rankl. Entonces considere un proceso Pj que posee algunas unidades de la clase de

13 MAQ. CAP. 11(F0694).indd 499 8/10/07 1:12:56 AM


500 CAPÍTULO 11 Bloqueos mutuos

recursos Rl. El proceso Pj no puede solicitar una unidad de la clase de recursos Rk, puesto que
rankk ⬎ rankl. ¡De este modo, si Pi puede esperar a Pj, Pj no puede esperar a Pi! Por ende, no
pueden surgir esperas circulares.

Ejemplo 11.11 En el ejemplo 11.1, supongamos que rankprinter ⬎ ranktape. Las solicitudes 1 y 2
llevan a la asignación de la cinta y de la impresora a Pi y Pj, respectivamente. La restricción de
validez se evalúa como true para la solicitud 3; sin embargo, la solicitud sigue pendiente, puesto
que la impresora no está disponible. La solicitud 4 será rechazada, ya que su restricción de validez
se evalúa como false, por lo que el proceso Pj será cancelado. Entonces la impresora quedará libre
y será asignada al proceso Pi.

La política de jerarquización de recursos funciona mejor cuando todos los procesos solicitan
sus recursos en el orden de jerarquías crecientes. Sin embargo, se presentan dificultades cuando
un proceso solicita recursos en un orden distinto. Si el proceso Pi en la figura 11.7a) requie-
re una unidad de la clase de recursos R2, su solicitud de recurso violará la restricción de validez.
La única forma en la que Pi puede obtener una unidad de R2 es liberando el recurso de R3 antes
de solicitar la unidad de R2. Entonces tendrá que readquirir la unidad de la clase de recursos R3.
Esto es difícil en la práctica porque la mayoría de los recursos son no priorizables.
Los procesos podrán tender a burlar este tipo de dificultades mediante la adquisición de
recursos de jerarquía menor mucho tiempo antes de que los necesiten en realidad. Es el caso del
proceso Pi del ejemplo 11.1, que puede adquirir el recurso R2 antes de que adquiera el recurso
R3. Del mismo modo, el proceso Pj del ejemplo 11.1 podrá adquirir la cinta antes de adquirir
la impresora. En el peor de los casos, esta política podrá degenerar en la política de “todas las
solicitudes juntas” de la asignación de recursos.
Pese a estas desventajas, la política de jerarquización de recursos es atractiva por su simpli-
cidad. Un kernel puede usar esta política para sus propios requerimientos de recursos cuando los
necesita en un orden fijo. Analizaremos este aspecto en la sección 11.8.

11.6 CÓMO EVITAR LOS BLOQUEOS MUTUOS

El evitar los bloqueos mutuos se distingue de la prevención de los mismos en un aspecto vital.
No trata de prevenir ninguna de las condiciones para bloqueos mutuos que se describen en la
sección 11.2.1. Por ende, los bloqueos mutuos no son imposibles; sin embargo, el enfoque para
evitarlos usa una política de asignación de recursos que sólo concede un recurso si el kernel pue-
de establecer que la concesión del recurso no llevará a un bloqueo mutuo, ya sea inmediatamente
o en el futuro. Es fácil verificar si un bloqueo mutuo es creado por conceder una solicitud: el
análisis de bloqueos mutuos que se describe en la sección 11.4 puede usarse para este propósito.
Sin embargo, ¿cómo podría el sistema saber si un bloqueo mutuo puede surgir en el futuro?
Para evitar bloqueos mutuos se usa la técnica de análisis del peor caso a fin de verificar si
habrá bloqueos mutuos en el futuro. Cada proceso es requerido para proporcionar informaciones
acerca de su necesidad máxima de recursos. En un planteamiento simplista para evitar bloqueos
mutuos, un SO puede usar estas informaciones mientras admite un proceso: sólo admitirá un
proceso si la suma de la máxima necesidad de recursos de todos los procesos en el sistema no
excede el número de recursos de éste. Sin embargo, este planteamiento no es práctico porque
lleva a una considerable inactividad de recursos. Lo es más permitir que la suma de la máxima
necesidad de los procesos exceda el número de recursos en el sistema y que use algún análisis

13 MAQ. CAP. 11(F0694).indd 500 8/10/07 1:12:57 AM


11.6 Cómo evitar los bloqueos mutuos 501

inteligente para asegurar que no se presenten bloqueos mutuos. Estudiaremos cómo se logra esto
cuando veamos el algoritmo del banquero.

11.6.1 Algoritmo del banquero


El algoritmo del banquero usa dos pruebas —una de factibilidad y una de seguridad— cuando
un proceso hace una solicitud. Sólo se conceden solicitudes que son tanto factibles como se-
guras. Todas las demás se mantienen pendientes. Una solicitud pendiente se concede en algún
momento en el futuro cuando se convierte tanto en factible como en segura. El hecho de que no
todas las solicitudes factibles se concedan automáticamente indica la posibilidad de inactividad
de recursos en el sistema.
Un proceso puede solicitar unidades de varias clases de recursos en la misma solicitud. En
nuestro análisis usamos la siguiente notación:
requested_resourcesj, k : Número de unidades de la clase de recursos Rk solicitadas
por el proceso Pj
reqj : Vector de requested_resourcesj, k para todos los k
max_needj, k : Número máximo de unidades de la clase de recursos Rk
que el proceso Pj podrá necesitar
max_needj : Vector de max_needj, k para todos los k
allocated_resourcesj, k : Número de unidades de la clase de recursos Rk asignadas
al proceso Pj
total_allock : Número total de unidades de la clase de recursos Rk asig-
nadas, es decir, ⌺j allocated_resourcesj, k
total_existk : Número total de unidades de la clase de recursos Rk exis-
tentes en el sistema
Mientras inicia un proceso Pj, el kernel usa un criterio de admisión de sentido común max_
needj, k ⱕ total_existk para todos los k. El kernel podrá iniciar cualquier número de procesos que
cumplen con este criterio de admisión. De este modo, ⌺jmax_needj.k podrá exceder a total_existk.
Este algoritmo se llama del banquero porque los banqueros admiten préstamos cuya suma ex-
cede el capital. El algoritmo del banquero evita bloqueos mutuos asignando sólo una solicitud
segura.

Definición 11.2 (Solicitud de factibilidad) Una solicitud Reqj es factible en el momento t si


el número de unidades solicitadas de una clase de recursos no excede el número de unidades
libres de esta clase en el sistema en el momento t.

Definición 11.3 (Solicitud segura) Una solicitud Reqj es segura en el momento t si, después
de conceder la solicitud en el momento t, existe por lo menos una secuencia de asignaciones
de recursos y liberaciones por las cuales cada proceso Pj en el sistema pueda obtener recur-
sos max_needj.

La definición 11.2 indica si es posible conceder una solicitud, mientras que la definición
11.3 señala si todos los procesos en el sistema pueden ejecutarse hasta la finalización después de
que se conceda la solicitud. De este modo, una solicitud segura es aquella que puede ser conce-
dida sin ninguna posibilidad de un bloqueo mutuo.

13 MAQ. CAP. 11(F0694).indd 501 8/10/07 1:12:57 AM


502 CAPÍTULO 11 Bloqueos mutuos

Cómo evitar bloqueos mutuos en un sistema de una sola clase de recursos Considere un
sistema que contiene una sola clase de recursos Rk. Tenemos

1. max_needj, k ⱕ total_existk (éste es el criterio de admisión)


2. requested_resourcesj, k ⱕ (max_needj, k allocated_resourcesj, k)
3. total_allock ⫽ ⌺j(allocated_resourcesj, k)
4. total_allock ⱕ total_existk.

El estado de asignación de recursos del sistema con respecto a la clase de recursos Rk in-
dica el número de unidades de Rk asignadas a cada proceso. Se representa como un múltiplo de
n (allocated_resourcesl, k, . . . allocated_resourcesn, k), donde n es el número de procesos en el
sistema. La noción de seguridad se extiende a un estado de asignación de recursos como sigue:

Definición 11.4 (Estado de asignación segura) Un estado de asignación de recursos es


seguro si existe al menos una secuencia de asignaciones y liberaciones de recursos por las
cuales cada proceso Pj en el sistema pueda obtener recursos max_needj.

Una solicitud del proceso Pj para unidades de requested_resourcesj, k de la clase de recursos


Rk se procesa de la siguiente manera:

1. Determine el nuevo estado de asignación en el cual se encontrará el sistema si se concede


la solicitud (lo llamaremos estado proyectado).
2. Conceda la solicitud si el estado proyectado es tanto factible como seguro. Actualice
allocated_resourcesj, k y total_allock en forma correspondiente.
3. Mantenga la solicitud pendiente si el estado proyectado es no factible o inseguro.

Cuando un proceso libera un(os) recurso(s), se examinan todas las solicitudes pendientes y
se asignan las que son tanto factibles como seguras. De este modo, el algoritmo lleva al sistema
de un estado seguro a otro, garantizando a la vez la ausencia de bloqueos mutuos.
La factibilidad y seguridad del estado de asignación proyectado se determina de la siguiente
manera: el estado de asignación proyectado se distingue del de asignación actual sólo en que en
requested_resourcesj, k unidades de la clase de recursos Rk han sido asignadas al proceso Pj, por
lo que el estado proyectado es factible si total_existk total_allock ⱖ 0 para todos los Rk en el
estado proyectado.
La seguridad del estado de asignación proyectado es determinada por medio de la verifica-
ción si todos los procesos del sistema se ejecutan hasta su finalización. Igual que en la sección
11.4, esa verificación se aplica usando la simulación. Sin embargo, hay una diferencia en la
comparación con la simulación que se usa en la citada sección: un proceso Pl que se encuentra
en el estado en ejecución podrá solicitar más recursos en el estado de asignación proyectado.
Sólo puede finalizar cuando todas estas solicitudes de recursos se hayan concedido. Por tanto,
su finalización sólo está garantizada si sus requerimientos de recursos remanentes, es decir,
max_needl,k allocated_resourcesj,k, pueden serle asignados. La condición (11.3) cumple este
requerimiento.

total_existk total_allock ⱖ max_needl,k allocated_resourcesj,k (11.3)

13 MAQ. CAP. 11(F0694).indd 502 8/10/07 1:12:57 AM


11.6 Cómo evitar los bloqueos mutuos 503

Cuando el proceso Pl finaliza, liberará todos los recursos que le han asignado. Simulamos esto
mediante la actualización de total_allock.
De manera similar, un proceso Pg que es bloqueado con una petición para unidades reques-
ted_resourcesg,k del recurso clase Rk, se puede completar si

total_existk total_allock ⱖ max_needg,k allocated_resourcesg, k

De este modo, no se necesita hacer ninguna distinción entre procesos en ejecución y bloqueados
mientras se determina la seguridad del estado de asignación proyectado. El ejemplo 11.12 ilustra
cómo se determina la seguridad de un estado de asignación proyectado.

Ejemplo 11.12 Un sistema contiene 10 unidades de la clase de recursos Rk. Los requerimientos de
recursos de estos tres procesos P1, P2 y P3 son los siguientes:

P1 P2 P3
Requerimientos máximos 8 7 5
Asignación actual 3 1 3

La figura 11.8 representa el estado de asignación actual del sistema. Ahora el proceso P1 hace una
solicitud para una unidad de recursos. En el estado de asignación proyectado, total_alloc ⫽ 8, y por
ende es un estado de asignación factible y en el sistema están disponibles dos unidades no asigna-
das de la clase de recursos Rk.

p1 8 p1 3 p1 1 Total 7
asignaciones
p2 7 p2 1 p2 0
p3 5 p3 3 p3 0 Total 10
existentes
Necesidad Recursos Recursos
máxima asignados solicitados

Figura 11.8 Estado de asignaciones en el algoritmo del banquero para una sola clase de recursos.

La seguridad del estado proyectado se determina del siguiente modo: la condición (11.3) no
está satisfecha por los procesos P1 y P2, ya que sus requerimientos de equilibrio exceden el número
de unidades no asignadas en el sistema. Sin embargo, P3 cumple con la condición (11.3) porque
le faltan exactamente 2 unidades para sus requerimientos máximos, por lo que los dos recursos
disponibles pueden ser asignados a P3 si los solicita en el futuro, y así puede finalizar. Esto liberará
todos los recursos que le han asignado y, por ende, cinco unidades de recursos ya estarán disponi-
bles para su asignación. Ahora P1 puede finalizar, pues el número de unidades no asignadas excede
las unidades necesarias para cumplir con su requerimiento de equilibrio. Entonces todas las unida-
des de recursos del sistema están disponibles para P2 y, por tanto, este proceso también puede fina-
lizar. De este modo, los procesos pueden finalizar en la secuencia P3, P1, P2. Esto hace que el
estado de asignación proyectado sea seguro. Por ende, el algoritmo concederá la solicitud de P1.
El nuevo estado de asignación es entonces (4, 1, 3) y total_allock ⫽ 8. Ahora considere las
siguientes solicitudes:
1. P1 hace una solicitud para 2 unidades de recursos.
2. P2 hace una solicitud para 2 unidades de recursos.
3. P3 hace una solicitud para 2 unidades de recursos.

13 MAQ. CAP. 11(F0694).indd 503 8/10/07 1:12:57 AM


504 CAPÍTULO 11 Bloqueos mutuos

Las solicitudes de P1 y P2 no son seguras, puesto que ningún proceso cumple con la condición
(11.3); entonces, estas solicitudes no se concederán. Sin embargo, la solicitud de P3 se concederá
porque este proceso es seguro.

El algoritmo del banquero para clases de recursos múltiples En un sistema que contiene
clases de recursos múltiples, se deberá aplicar la condición (11.3) para todos los recursos a fin de
determinar si un proceso puede finalizar. El algoritmo 11.2 usa este método para definir si una
solicitud es segura. Se invoca este algoritmo cuando el proceso Preq formula una solicitud. El
algoritmo concede una solicitud segura; si no lo es, la mantiene en estado de pendiente. Cuando
un proceso finaliza y libera todos los recursos que le han asignado, el algoritmo es invocado para
cada solicitud pendiente.
El resumen de este algoritmo es el siguiente: en el paso 1 ingresa la solicitud en la tabla de
solicitudes pendientes. En el paso 2 simula la concesión de la solicitud. El paso 3 verifica la fac-
tibilidad de la solicitud. Si ésta no lo es, el control es dirigido al paso 5 para retirar la concesión.
Efectivamente, la solicitud se mantendrá pendiente.
El paso 4 es la parte fundamental del algoritmo. En él se determina la seguridad de la solici-
tud, verificando la seguridad del nuevo estado simulado. Este paso verifica si se puede satisfacer
la máxima necesidad de cualquier o cualesquiera proceso(s) activo(s) mediante la asignación de
algunos de los recursos libres. Si este proceso existe, el paso simula su finalización, borrándolo
del conjunto Active y liberando los recursos que le han asignado. Si el nuevo estado es seguro,
el conjunto Active estará vacío al final de este paso. El paso 5 verifica la seguridad del estado. Si
no es seguro, retira la concesión; de no ser éste el caso, la concesión se retiene y, por tanto, se
borra la solicitud de la lista de solicitudes pendientes.
Observe la similitud del paso 5 con el algoritmo de detección de bloqueos mutuos. De modo
análogo, el algoritmo requiere un orden de n2 ⫻ r de trabajo.

Algoritmo 11.2 (algoritmo del banquero)


Entradas
n : Número de procesos;
r : Número de clases de recursos;
Blocked : conjunto de procesos;
Running : conjunto de procesos;
Prequesting_process : Proceso que hace la solicitud de recurso nuevo;
Max_need : array [1..n, 1..r] de entero;
Allocated_resources : array [1..n, 1..r] de entero;
Requested_resources : array [1..n, 1..r] de entero;
Total_alloc : array [1.. r] de entero;
Total_exist : array [1.. r] de entero;
Estructuras de datos
Active (activo) : conjunto de procesos;
feasible (factible) : booleano;
New_request (nueva solicitud) : array [1.. r] de entero;
Simulated_allocation : array [1..n, 1..r] de entero;
Simulated_total_alloc : array [1.. r] de entero;

13 MAQ. CAP. 11(F0694).indd 504 8/10/07 1:12:58 AM


11.6 Cómo evitar los bloqueos mutuos 505

a) Estado inicial
R1 R2 R3 R4 R1 R2 R3 R4 R1 R2 R3 R4
p1 2 1 2 1 p1 1 1 1 1 p1 0 0 0 0 R1 R2 R3 R4
p2 p2 p2 Asignaciones
2 4 3 2 2 0 1 0 0 1 1 0 totales 5 3 5 4
p3 5 4 2 2 p3 2 0 2 2 p3 0 0 0 0
p4 0 3 4 1 p4 0 2 1 1 p4 Total
0 0 0 0 existentes 6 4 8 5
Máxima Recursos Recursos
necesidad asignados solicitados Activos {p1 , p2 , p3 , p4 }

b) Antes del bucle “mientras” del paso 5


p1 2 1 2 1 p1 1 1 1 1 p1 0 0 0 0
p2 2 4 3 2 p2 2 1 2 0 p2 0 1 1 0 Asignaciones 5 4 6 4
simuladas
p3 5 4 2 2 p3 2 0 2 2 p3 0 0 0 0
p4 0 3 4 1 p4 0 2 1 1 p4 0 0 0 0 Total 6 4 8 5
existentes
Máxima Recursos Recursos
necesidad asignados solicitados Activos {p1 , p2 , p3 , p4 }

c) Después de simular la finalización del proceso p1


p1 2 1 2 1 p1 1 1 1 1 p1 0 0 0 0
p2 p2 p2 Asignaciones
2 4 3 2 2 1 2 0 0 1 1 0 simuladas 4 3 5 3
p3 5 4 2 2 p3 2 0 2 2 p3 0 0 0 0
p4 p4 p4 Total
0 3 4 1 0 2 1 1 0 0 0 0 existentes 6 4 8 5
Máxima Recursos Recursos {p2 , p3 , p4 }
necesidad asignados solicitados Activos

d) Después de simular la finalización del proceso p4


p1 2 1 2 1 p1 1 1 1 1 p1 0 0 0 0
p2 p2 p2 Asignaciones
2 4 3 2 2 1 2 0 0 1 1 0 simuladas 4 1 4 2
p3 5 4 2 2 p3 2 0 2 2 p3 0 0 0 0
p4 p4 p4 Total
0 3 4 1 0 2 1 1 0 0 0 0 existentes 6 4 8 5
Máxima Recursos Recursos {p2 , p3 }
necesidad asignados solicitados Activos

e) Después de simular la finalización del proceso p2


p1 2 1 2 1 p1 1 1 1 1 p1 0 0 0 0
p2 2 4 3 2 p2 2 1 2 0 p2 0 1 1 0 Asignaciones 2 0 2 2
p3 p3 p3 simuladas
5 4 2 2 2 0 2 2 0 0 0 0
p4 0 3 4 1 p4 0 2 1 1 p4 0 0 0 0 Total 6 4 8 5
existentes
Máxima Recursos Recursos
necesidad asignados solicitados Activos {p3 }

Figura 11.9 Operación del algoritmo del banquero para el ejemplo 11.13.

13 MAQ. CAP. 11(F0694).indd 505 8/10/07 1:12:58 AM


506 CAPÍTULO 11 Bloqueos mutuos

1. Active :⫽ Running 傼 Blocked;


para k ⫽ 1..r
New_request[k] :⫽ Requested_resources[requesting_process, k];
2. Simulated_allocation :⫽ Allocated_resources;
para k ⫽ 1..r /* Computar estado de asignación proyectado */
Simulated_allocation[requesting_process, k] :⫽
Simulated_allocation[requesting_process, k] ⫹ New_request[k];
Simulated_total_alloc[k] :⫽ Total_alloc[k] ⫹ New_request[k];
3. feasible :⫽ true;
para k ⫽ 1..r /* Verificar si el estado de asignación proyectado es seguro */
si Total_exist[k] ⬍ Simulated_total_alloc[k] entonces feasible :⫽ false;
4. si feasible ⫽ true
entonces /* Verificar si el estado de asignación proyectado es seguro */
mientras conjunto Active contenga un proceso Pl tal que
Para todos los k, Total_exist[k] – Simulated_total_alloc[k]
ⱖ Max_need[l, k] – Simulated_allocation[l, k]
Borrar Pl de Active;
para k ⫽ l..r
Simulated_total_alloc[k] :⫽
Simulated_total_alloc[k] – Simulated_ allocation[l, k];
5. si el conjunto Active está vacío
entonces /* Estado de asignación proyectado es seguro */
para k ⫽ l..r /* Borrar la solicitud de solicitudes pendientes */
Requested_resources[requesting_process k] :⫽ 0;
para k ⫽ l..r /* Conceder la solicitud */
Allocated_resources[requesting_process, k] :⫽
Allocated_resources[requesting_process, k] ⫹ New_request[k];
Total_alloc[k] :⫽ Total_alloc[k] ⫹ New_request[k];

Ejemplo 11.13 La figura 11.9 ilustra la operación del algoritmo del banquero en un sistema que
contiene cuatro procesos P1 . . . P4 y 6, 4, 9 y 5 unidades de recursos de cuatro clases de recursos.
El estado de asignación del sistema es (5, 3, 6, 3). El proceso P2 hizo una solicitud (0, 1, 1, 0) que
está a punto de ser procesada. El algoritmo simula la concesión de esta solicitud en el paso 2, y
verifica la seguridad del nuevo estado en el paso 4. La figura 11.9b) muestra la estructura de datos
del algoritmo del banquero al inicio de esta revisión. En este estado sólo el proceso P1 puede termi-
nar, así que el algoritmo simula su finalización. La figura 11.9c) muestra estructuras de datos des-
pués de que P1 ha finalizado. Los procesos restantes pueden concluir en el orden P4, P2, P3. Por
tanto, la solicitud hecha por el proceso P2 es segura.

11.7 CARACTERIZACIÓN FORMAL DE BLOQUEOS


MUTUOS DE RECURSOS

Según la sección 11.2.1, una relación circular de espera entre procesos es condición necesaria
para un bloqueo mutuo. Esto queda de manifiesto en un ciclo en una RRAG o en una WFG. Sin
embargo, ¿implica la presencia de un ciclo un bloqueo mutuo? En otras palabras, ¿es la presen-
cia de un ciclo suficiente para concluir que un bloqueo mutuo existe? La respuesta a esta pre-
gunta depende de la naturaleza de las clases y solicitudes de recursos en el sistema. Por ende,
empezaremos con el análisis de modelos para clases y solicitudes de recursos.

13 MAQ. CAP. 11(F0694).indd 506 8/10/07 1:12:58 AM


11.7 Caracterización formal de bloqueos mutuos de recursos 507

Modelos de clases de recursos Una clase de recursos Ri podrá contener una sola o muchas
instancias del recurso. Nos referimos a éstas como clases de recursos de instancia simple (SI) y
clases de recursos de instancia múltiple (MI), respectivamente.

Modelo de solicitudes de recursos Definimos dos tipos de solicitudes de recursos. En una


solicitud simple (SR) se permite que un proceso solicite una unidad de una sola clase de recur-
sos. En una solicitud múltiple (MR), un proceso tiene permiso de solicitar una unidad de varias
clases de recursos. El kernel nunca asigna una solicitud múltiple en forma parcial, es decir, asig-
na todos los recursos solicitados en una SM o no asigna ninguno de ellos. En este último caso, el
proceso que formula la solicitud es bloqueado hasta que se le puedan asignar todos los recursos.
El ejemplo 11.14 ilustra cómo se manejan solicitudes múltiples en la práctica.

Ejemplo 11.14 En la figura 11.1a), las clases de recursos R1 y R2 son del tipo SI y MI, respectiva-
mente. En el ejemplo 11.1, las cuatro solicitudes hechas por los procesos son solicitudes simples.
Los procesos Pi y Pj podrán haber hecho solicitudes múltiples involucrando la cinta y la impresora.
En este caso, un bloqueo mutuo no se presentará, puesto que se le asignará a un proceso tanto la
impresora como la cinta al mismo tiempo; de hecho, como se puede ver en la sección 11.5.1, pedir
que los procesos sólo hagan una solicitud múltiple en su vida forma la base de un enfoque de pre-
vención de bloqueos mutuos.

Usando los modelos de clases de recursos y de solicitudes de recursos podemos definir


cuatro tipos de sistemas, tal como se muestra en la figura 11.10. Primero analizaremos las condi-
ciones necesarias y suficientes para bloqueos mutuos en estos sistemas. Más tarde presentaremos
una caracterización general de bloqueos mutuos que es aplicable a todos los sistemas. Es posible
usar las WFG para representar el estado de recursos de sistemas SISR y SIMR. Sin embargo, por
motivos de generalidad, usaremos en todos los casos las RRAG a fin de representar el estado de
recursos de un sistema.

Modelos de solicitudes de recursos


Modelo de Modelo de solicitud
solicitud simple (SR) múltiple (MR)
Modelo de Instancia múltiple Instancia múltiple
instancias Solicitud simple Solicitud múltiple
Modelos múltiples (MI) (MISR) (MIMR)
de instancias de
recursos Modelo de Instancia simple Instancia simple
instancia Solicitud simple Solicitud múltiple
simple (SI) (SISR) (SIMR)

Figura 11.10 Clasificación de sistemas según los modelos de clases de recursos y solicitudes de recursos.

11.7.1 Sistemas de instancia simple/solicitud simple (SISR)

En un sistema SISR, cada clase de recursos contiene una sola instancia del recurso, y cada solici-
tud es una solicitud simple. Como hemos discutido en la sección 11.2.2, la existencia de un ciclo

13 MAQ. CAP. 11(F0694).indd 507 8/10/07 1:12:58 AM


508 CAPÍTULO 11 Bloqueos mutuos

en RRAG implica una relación mutua de espera para un conjunto de procesos. Puesto que cada
clase de recursos en el sistema contiene una sola unidad de recursos, cada proceso bloqueado
Pi en el ciclo espera a otro proceso, es decir, a que Pk libere el recurso requerido. El que cada
solicitud en el sistema sea una solicitud simple implica que Pk también está incluido en el ciclo;
por tanto, la condición (11.2) se cumple para todos los procesos en el ciclo. Así, cada ciclo es
una condición tanto necesaria como suficiente para concluir que un bloqueo mutuo existe en el
sistema.

11.7.2 Sistemas de instancia múltiple/solicitud simple (MISR)

En estos sistemas, las clases de recursos podrán contener múltiples instancias, pero todas las
solicitudes son simples. Un ciclo es una condición necesaria para la existencia de un bloqueo
mutuo debido a la condición de espera circular de la sección 11.2.1.
Un ciclo no es una condición suficiente para un bloqueo mutuo en sistemas MISR. Pode-
mos explicar esto de la siguiente manera: la existencia de un ciclo P1 . . . Pn tal que P1 ⬅ Pn
implica que algunos procesos están involucrados en una relación mutua de espera. Sin embargo,
puesto que una clase de recursos puede contener muchas unidades de ellos, es posible que una
unidad de recursos requerida por algún proceso en el ciclo pueda ser concedida por un proceso
que no está incluido en el ciclo. El ejemplo 11.4 contiene una instancia de ese tipo. La espera de
Pj a Pi forma parte del ciclo que involucra Pi y Pj, pero Pj también espera a Pk y a que Pi o Pk
puedan liberar una unidad de cinta. De este modo, la relación mutua de espera entre Pi y Pj deja
de existir cuando Pk libera una unidad de cinta. Para que un bloqueo mutuo pueda existir es esen-
cial que ningún proceso fuera de D sea capaz de suministrar una unidad de recursos requerida
por algún proceso en D. Ésta es la implicación de la condición (11.2).
Usamos conceptos de la teoría grafos para caracterizar formalmente los bloqueos mutuos en
sistemas MISR. Un grafo G es un par ordenado G ⬅ (N, E) donde N es un conjunto de nodos y E
es un conjunto de aristas. Un grafo G⬘ ⬅ (N⬘, E⬘) es un subgrafo de un grafo G ⬅ (N, E) si N⬘ 債
N y E⬘ 債 E, es decir, si todos los nodos y aristas contenidos en G⬘ también están contenidos en G.
G⬘ es un subgrafo no trivial de G si E⬘ ⫽ ␾, es decir, si contiene por lo menos una arista. Ahora
introduciremos la noción de un nudo para caracterizar un bloqueo mutuo en sistemas MISR.

Definición 11.5 (Nudo) Un nudo es un subgrafo no trivial G⬘ ⬅ (N⬘, E⬘) de una RRAG en la
que cada nodo ni en N⬘ cumple con las siguientes condiciones:
1. Para cada arista de la forma (ni, nj) en E: (ni, nj) está incluido en E⬘ y nj está incluido
en N⬘.
2. Si una ruta ni-. . .-nj existe en G⬘, entonces una ruta nj-. . .-ni también existe en G⬘.

La parte 1 de la definición 11.5 asegura que si un nodo está incluido en un nudo, todos
sus aristas salientes, es decir, todos los que emanan de él, también están incluidos en el nudo.
Una arista es también una ruta, así que la parte 2 de la definición 11.5 implica que cada arista
saliente de cada nodo necesariamente está en el estado bloqueado. Las partes 1 y 2 juntas impli-
can que todos los procesos que pueden liberar un recurso necesitado por un proceso en el nudo
están incluidos en él, lo que cumple con la condición (11.2). Por ende, se puede concluir que la

13 MAQ. CAP. 11(F0694).indd 508 8/10/07 1:12:59 AM


11.7 Caracterización formal de bloqueos mutuos de recursos 509

presencia de un nudo en una RRAG es condición necesaria y suficiente para la existencia de un


bloqueo mutuo en un sistema MISR.

Ejemplo 11.15 La RRAG de la figura 11.3 (véase el ejemplo 11.4) no contiene un nudo, puesto
que la ruta Pi . . . Pk existe, pero la ruta Pk . . . Pi no existe en ella. Ahora considere la situación si
se hace la siguiente solicitud:
6. Pk solicita una impresora.
El proceso Pk se bloquea ahora en la sexta solicitud. La resultante RRAG se muestra en la figura
11.11. La RRAG completa es un nudo porque se cumple trivialmente la parte 1 de la definición
11.5, y cada arista saliente de cada nodo está involucrado en un ciclo, lo que satisface la parte 2
de la definición 11.5. Es fácil verificar que los procesos {Pi, Pj, Pk} están en un bloqueo mutuo,
puesto que Blocked_P ⫽ {Pi, Pj, Pk}, WFi ⫽ {Pj,}, WFj ⫽ {Pj, Pk} y WFk ⫽ {Pj,} cumple con las
condiciones (11.1) y (11.2).

Pi
impresora cinta
• ••

Pj Pk

Figura 11.11 Un nudo en la RRAG de un sistema MISR implica un bloqueo mutuo.

11.7.3 Sistemas de instancia simple/solicitud múltiple (SIMR)


Cada clase de recursos en el sistema SIMR contiene sólo una unidad de recursos y, por tan-
to, tiene exactamente una arista saliente en una RRAG. Un proceso podrá hacer una solicitud
múltiple, y, por lo mismo, podrá tener más de una arista saliente. Este tipo de proceso permanece
bloqueado hasta que cada recurso que solicita esté disponible. Un ciclo implica que uno de los
recursos que ha solicitado no está disponible. Por ende, un ciclo es una condición necesaria y
suficiente para bloqueos mutuos en un sistema SIMR.
Considere que un nodo de proceso Pi tiene una arista saliente (Pi, R1), que es una parte de
un ciclo, y una arista saliente (Pi, R3), que no es parte de ningún ciclo (véase la figura 11.12). El
proceso Pi permanece bloqueado hasta que se le puedan asignar unidades de recursos tanto de
R1 como de R3. Puesto que su arista saliente (Pi, R1) está involucrado en un ciclo, y R1 sólo tiene
una arista saliente, Pi enfrenta una espera indefinida. Pj también enfrenta una espera indefinida.
Por tanto, {Pi, Pj} están involucrados en un bloqueo mutuo.

11.7.4 Sistemas de instancia múltiple/solicitud múltiple (MIMR)


En el modelo MIMR, tanto los nodos de procesos como los de recursos de una RRAG pueden
tener múltiples aristas salientes. Si uno de los nodos de recursos involucrados en un ciclo en la
RRAG tiene múltiples aristas salientes, el ciclo es similar a uno en la RRAG de un sistema SIMR

13 MAQ. CAP. 11(F0694).indd 509 8/10/07 1:12:59 AM


510 CAPÍTULO 11 Bloqueos mutuos

Pi

R1 • R2 • • R3

pj Pk
Figura 11.12 Un ciclo es necesario y suficiente para un bloqueo mutuo en un sistema SIMR.

o SISR. Por tanto, un ciclo de ese tipo es una condición suficiente para la existencia de un
bloqueo mutuo. Sin embargo, si un nodo de recurso en un ciclo tiene múltiples aristas salientes,
un ciclo es una condición necesaria, pero no suficiente, para un bloqueo mutuo. En tales casos,
cada arista saliente del nodo de recurso debe estar involucrada en un ciclo. El ejemplo 11.16
ilustra este aspecto.

Ejemplo 11.16 La RRAG de la figura 11.13 contiene el ciclo R1-Pi-R2-Pj-R1. El nodo de recur-
so R1 contiene una arista saliente (R1, Pk) que no pertenece a este ciclo. El proceso Pk podrá libe-
rar una instancia de la clase de recursos R1 que podrá ser asignada al proceso Pj. Esto
romperá el ciclo en la RRAG, y por ende no hay ningún bloqueo mutuo en el sistema. Si la arista
de asignación de R3 fuera (R3, Pi), ambas aristas salientes de R1 estarían involucradas en ciclos.
La solicitud de Pj para R1 tendría entonces que enfrentar una espera indefinida, y por tanto se ten-
dría una situación de bloqueo mutuo. Observe que la arista saliente (Pi, R4) de Pi no está involu-
crada en un ciclo; sin embargo, se presenta un bloqueo mutuo porque la solicitud de Pi para una
clase de recursos R2 lleva a una espera indefinida.

Pi

• R3 • • R1 • R2 • R4

Pk Pj Pl
Figura 11.13 RRAG para un sistema MIMR.

Según la discusión que antecede y el ejemplo 11.16, queda claro que tenemos que diferen-
ciar entre nodos de proceso y de recurso de una RRAG. Todas las aristas salientes de un nodo de
recurso deben estar involucradas en ciclos, mientras que un nodo de proceso sólo necesita tener
una arista saliente involucrada en un ciclo. Introduciremos la noción de un nudo de recurso para
incorporar estos requerimientos.

Definición 11.6 (Nudo de recurso) Un nudo de recurso es un subgrafo no trivial G⬘ ⬅ (N⬘,


E⬘) de una RRAG en el cual cada nodo ni en N⬘ cumple con las siguientes condiciones:
1. Si ni es un nodo de recurso para cada arista de la forma (ni, nj) en E: (ni, nj) está
incluido en E⬘ y nj está incluido en N⬘.

13 MAQ. CAP. 11(F0694).indd 510 8/10/07 1:12:59 AM


11.7 Caracterización formal de bloqueos mutuos de recursos 511

2. Si una ruta ni-. . .-nj existe en G⬘, entonces una ruta nj-. . .-ni también existe en G⬘.

Un nudo de recurso se distingue de un nudo en que la parte 1 de la definición 11.6 aplica sólo
nodos de recursos. De este modo, algunas aristas salientes de nodos de proceso posiblemente no
pertenezcan al nudo de recurso, mientras que los nodos de recursos no pueden poseer tales aris-
tas salientes.
Ejemplo 11.17 Los nodos Pi, Pj, Pk, R1, R2 y R3 de la figura 11.13 están involucrados en un nudo
de recurso si la arista de asignación de la clase de recursos R3 es (R3, Pi). Observe que el proceso Pi
tiene otra arista saliente que no está incluida en el nudo de recurso.

Queda claro que un nudo de recurso es una condición necesaria y suficiente para la exis-
tencia de un bloqueo mutuo en un sistema MIMR. De hecho, indicamos aquí sin prueba que un
nudo de recurso es una condición necesaria y suficiente para bloqueos mutuos en todos los siste-
mas de recursos que hemos discutido en esta sección (véase el problema 22 del ejercicio 11).

11.7.5 Procesos en bloqueos mutuos

D, el conjunto de procesos en bloqueo mutuo contiene procesos representados por nodos de


proceso en nudos de recursos. También contiene algunos otros procesos que enfrentan esperas
indefinidas. Usamos la siguiente notación para identificar todos los procesos en D.

RRi : El juego de clases de recursos solicitados por el proceso Pi.


HSk : El conjunto propietario de la clase de recursos Rk, es decir, el conjunto de
procesos al que están asignadas unas unidades de la clase de recursos Rk.
KS : El conjunto de nodos de proceso en nudo(s) de recurso (lo llamamos el
knotset de la RRAG).
AS : Un juego auxiliar de nodos de proceso en RRAG que enfrentan esperas
indefinidas. Estos nodos no están incluidos en un nudo de recurso.

KS es el conjunto de nodos de proceso incluido en nudos de recurso. Ahora un proceso Pi 僆


KS enfrenta una espera indefinida si todos los poseedores de una clase de recursos Rk solicitados
por él están incluidos en KS. Clases de recursos cuyos poseedores están incluidos en {Pi} 傼 KS
del mismo modo causan esperas indefinidas para sus solicitantes. Por tanto, podemos identifi-
car D, el conjunto de procesos en bloqueo mutuo, de la siguiente manera:

AS ⫽ { Pi 兩 RRi contiene Rk tal que HSk 債 (KS 傼 AS)} (11.4)


D ⫽ KS 傼 AS (11.5)

Ejemplo 11.18 La figura 11.14 muestra una RRAG de un sistema MIMR. El ciclo P1-R1-P2-R2-
P3 -R3-P1 en la RRAG forma un nudo de recursos porque ninguno de los recursos R1, R2 o R3 tiene
una arista saliente que sale del ciclo. Por tanto, existe un bloqueo mutuo en el sistema. Identifica-
mos los procesos en D como sigue:
KS ⫽ {P1, P2, P3}
AS ⫽ {P4} puesto que RR4 ⫽ {R5}, HS5 ⫽ {P1} y {P1} 債 {P1, P2, P3}
D ⫽ KS 傼 AS ⫽ {P1, P2, P3, P4}.
El proceso P6 no está incluido en AS, puesto que RR6 ⫽ {R7}, HS7 ⫽ {P4, P8} y HS7 債 (KS
傼 AS).

13 MAQ. CAP. 11(F0694).indd 511 8/10/07 1:13:00 AM


512 CAPÍTULO 11 Bloqueos mutuos

p8 R3

p3
•• • p1 R2 •
p6 R7 p4 R5 R1

p2 p11


R10

Figura 11.14 Procesos en bloqueo mutuo.

11.7.6 Caracterización del bloqueo mutuo usando gráficas de espera

Las aristas en una WFG indican las relaciones de “esperar a” entre procesos. Aristas salientes
de un proceso Pi señalan las relaciones de espera de Pi con otros procesos en el sistema. Estas
aristas pueden ser de dos tipos, dependiendo de la naturaleza de la solicitud hecha por Pi y de la
naturaleza de la(s) clase(s) de recursos cuyas unidades ha solicitado.

• Aristas OR: Las aristas (Pi, Pj) y (Pi, Pk) existen en la WFG si Pi solicita una unidad de la
clase de recursos R1 que contiene dos unidades de recursos asignadas a los procesos Pj y
Pk. La solicitud de Pi puede satisfacerse cuando Pj o Pk libera una unidad de R1; por ello
estas aristas salientes de Pi se llaman aristas OR.
• Arista AND: Las aristas (Pi, Pl) y (Pi, Pg) existen en la WFG si Pi hace una solicitud múl-
tiple para unidades de las clases de recursos de instancia simple R1 y R2 cuyas unidades
están asignadas a los procesos Pl y Pg, respectivamente. Pi requiere recursos poseídos
tanto por Pl como Pg; por ello estas aristas salientes se llaman aristas AND.

Distinguimos entre aristas OR y AND en una WFG dibujando un arco que conecta las aristas
salientes AND de un proceso. Un proceso puede tener aristas salientes de ambos tipos al mismo
tiempo; sin embargo, por motivos de simplicidad, suponemos que todas las aristas salientes de
un proceso son OR o AND. El ejemplo 11.19 ilustra las aristas OR y AND.

Ejemplo 11.19 La figura 11.15 muestra dos WFG. La WFG de la parte a) de la figura 11.15 co-
rresponde a la RRAG de la figura 11.11, donde dos unidades de cinta están en posesión de los
procesos Pi y Pk, y el proceso Pj ha solicitado una unidad de cinta. Esta situación da pie a dos aris-
tas salientes para el proceso Pj. Éstas son aristas OR. La WFG de la parte b) de la figura 11.15
corresponde a la RRAG de la figura 11.12, donde el proceso Pi ha hecho una solicitud múltiple para
recursos actualmente poseídos por los procesos Pj y Pk. Las aristas salientes de Pi son aristas AND,
y por ello dibujamos un arco conectándolos.

La caracterización de bloqueo mutuo para diferentes sistemas de recursos es como sigue:

• Sistemas SISR: Todos los procesos en la WFG contienen aristas salientes simples. Un
ciclo es una condición necesaria y suficiente para el bloqueo mutuo.

13 MAQ. CAP. 11(F0694).indd 512 8/10/07 1:13:00 AM


11.8 Manejo del bloqueo mutuo en la práctica 513

Pi Pi
Pj Pj

Pk Pk

a) b)

Figura 11.15 WFG con aristas salientes múltiples.

• Sistemas MISR: Todos los procesos con aristas salientes múltiples tienen aristas OR. Un
ciclo es una condición necesaria pero no suficiente para un bloqueo mutuo. Un nudo es
una condición necesaria y suficiente para el bloqueo mutuo.
• Sistemas SIMR: Todos los procesos con aristas salientes múltiples tienen aristas AND.
Un ciclo es una condición necesaria y suficiente para un bloqueo mutuo.

La caracterización del bloqueo mutuo en la WFG de un sistema MIMR no se analiza aquí.


Se deja como ejercicio (véase el problema 23 del ejercicio 11).

11.8 MANEJO DEL BLOQUEO MUTUO EN LA PRÁCTICA

Los recursos en un SO pueden dividirse en recursos de hardware, tales como la memoria y dis-
positivos de E/S, y recursos de software, tales como archivos que contienen programas o datos,
mensajes interproceso y bloques de control usados por procesos del sistema o por el mismo
kernel. Los sistemas operativos tienden a usar políticas sencillas de manejo de bloqueos mutuos
que no causan una sobrecarga grande del CPU. Por ende, no sorprende que políticas para evitar
bloqueos mutuos se usen sólo en contadas ocasiones, si es que se usan. Un SO usa la prevención
de bloqueos mutuos o crea una situación en la que acciones explícitas de manejo de bloqueos
mutuos son innecesarias.

Memoria La memoria es un recurso priorizable y por tanto su uso por parte de procesos
no puede causar un bloqueo mutuo. Por ende, el manejo explícito de bloqueos mutuos es innece-
sario. La memoria asignada a un proceso es liberada intercambiando el proceso cada vez que se
necesita la memoria para otro proceso.

Dispositivos E/S El enfoque de “todas las solicitudes juntas” requiere que los procesos
hagan una solicitud múltiple para todos sus requerimientos de recursos. Esta política provoca la
menor sobrecarga del CPU; sin embargo, tiene el inconveniente que se menciona en la sección
11.5.1 de provocar la infrautilización de los dispositivos de E/S que tienen que ser asignados
mucho antes de que un proceso realmente los necesite. La jerarquización de recursos no es una
política factible para controlar el uso de dispositivos de E/S porque toda asignación de jerarquías
de recursos causa algún inconveniente para alguna sección de usuarios. Esa dificultad es com-
plicada por el hecho de que los dispositivos de E/S son, por lo general, no priorizables. La evita-
bilidad provoca una sobrecarga del CPU y también un compromiso de memoria para las
estructuras de datos de algoritmos de evasión tales como el algoritmo del banquero. De este
modo, todos los enfoques parecen tener debilidades en la práctica.

13 MAQ. CAP. 11(F0694).indd 513 8/10/07 1:13:00 AM


514 CAPÍTULO 11 Bloqueos mutuos

Los sistemas operativos superan esta dificultad mediante la creación de dispositivos virtuales
que usan la técnica de spooling (colocación de trabajos en un buffer). Por ejemplo, el sistema
crea una impresora virtual usando algún área del disco para almacenar un archivo que debe
ser impreso. La impresión real se lleva a cabo cuando una impresora se encuentra disponible.
Puesto que los dispositivos son creados cada vez que se necesitan, no es necesario asignarlos
de antemano, como en el enfoque de “todas las solicitudes juntas”, a menos que el sistema
enfrente una escasez de espacio en disco. Por tanto, el manejo de dispositivos de E/S causa
escasa sobrecarga del CPU.

Archivos y mensajes interproceso Un archivo es un recurso creado por el usuario. Por


ende, existe un gran número de archivos en un SO. Las políticas de manejo de bloqueos mutuos
causarían cargas generales de CPU y memoria inaceptablemente altas mientras controlan el ac-
ceso a archivos. Por tanto, SO de uso general no extienden acciones de manejo de bloqueos
mutuos a los archivos. Procesos que acceden a un conjunto común de archivos deben hacer
sus propios arreglos para evitar bloqueos mutuos. Por motivos similares, los SO no manejan
bloqueos mutuos causados por mensajes interproceso. Los procesos que intercambian mensajes
deben establecer sus propias convenciones para el manejo de bloqueos mutuos.

Bloques de control El kernel reparte los bloques de control como PBC y ECB para proce-
sar una orden específica (un PCB se distribuye cuando un proceso se crea y un ECB cuando el
proceso resulta bloqueado por un evento). Sin embargo, se puede recurrir a un ordenamiento de
recursos. Si se desea una estrategia más sencilla, todos los bloques de control para un trabajo o
proceso pueden ser repartidos juntos en su inicio.

11.8.1 El manejo de bloqueos mutuos en Unix

La mayoría de los sistemas operativos ignoran la posibilidad de bloqueos mutuos que involucran
procesos de usuarios. A esto se le puede llamar el cuarto enfoque para el manejo de bloqueos
mutuos: el enfoque avestruz. Unix no es la excepción. Sin embargo, contiene herramientas para
abordar el problema de bloqueos mutuos involucrando a procesos que ejecutan el código del ker-
nel como resultado de interrupciones o llamadas al sistema. El planteamiento general es el de la
prevención de bloqueos mutuos mediante la jerarquización de recursos (véase la sección 11.5.2).
Las estructuras de datos en el kernel son bloqueadas y liberadas en un orden estándar. Sin embar-
go, hay excepciones a esta regla porque no todas las funcionalidades del kernel pueden bloquear
las estructuras de datos en el orden estándar, por lo que bloqueos mutuos son posibles. Presenta-
remos perspectivas simplificadas de dos arreglos que se usan para evitar bloqueos mutuos.
El kernel de Unix usa una caché de buffers para acelerar accesos a bloques de disco frecuen-
temente usados (véase la sección 12.10.2). La caché de buffers consiste en un pool de buffers
en la memoria y una estructura de datos hashed para verificar si un bloque de disco específico
existe en un buffer. Se lleva una lista de buffers en orden LRU para facilitar la reutilización de
buffers. El orden normal a fin de acceder a un bloque de disco es usar una estructura de datos
hashed para localizar un bloque de discos, poner un bloqueo en el buffer que contiene el bloque
de disco y luego poner un candado en la lista de buffers para actualizar el estatus LRU del buffer.
Sin embargo, si un proceso únicamente desea obtener un buffer para cargar un nuevo bloque
de disco, accede directamente a la lista de buffers y quita el primer buffer que en ese momento
no está en uso. A fin de lograr esto, el proceso pone un candado en la lista. Luego verifica si el

13 MAQ. CAP. 11(F0694).indd 514 8/10/07 1:13:00 AM


Ejercicio 11 515

candado en el primer buffer de la lista ya ha sido puesto por algún proceso. De no ser así, coloca
el candado y usa el buffer; de lo contrario, repite el proceso en el siguiente buffer de la lista.
Bloqueos mutuos son posibles porque este orden al cerrar la lista y un buffer es distinto al orden
estándar al colocar estos candados.
Unix usa un enfoque innovador para evitar bloqueos mutuos. El proceso que busca un bu-
ffer libre evita ser bloqueado en su candado. El proceso usa una operación especial que trata de
poner un candado, pero regresa con un código de condición de falla si éste ya está puesto. Si lo
anterior sucede, el proceso simplemente trata de poner el candado en el siguiente buffer, hasta
que encuentra un buffer que pueda usar. Este enfoque evita bloqueos mutuos, evitando esperas
circulares.
Otra situación en la que los candados no pueden colocarse en un orden estándar es en la
función del sistema de archivos que establece una liga (véase la sección 7.4.1). Un comando de
liga proporciona nombres de ruta para un archivo, así como un directorio que deberá contener
la liga al archivo. Este comando puede ser implementado poniendo candados a los directorios
que contienen el archivo y la liga. Sin embargo, no puede definirse un orden estándar para poner
candados a estos directorios. Por consiguiente, dos procesos que intentan cerrar los mismos
directorios en forma concurrente podrán entrar en un bloqueo mutuo. Para evitar estos bloqueos
mutuos, la función del sistema de archivos no trata de adquirir ambos candados al mismo tiempo.
Primero cierra un directorio, lo actualiza del modo deseado y suelta el candado. Luego cierra el
otro directorio y lo actualiza. De este modo, sólo requiere un candado en algún momento dado.
Este enfoque previene bloqueos mutuos porque estos procesos no cumplen con la condición de
espera.

EJERCICIO 11
1. Compare y contraste las siguientes políticas de asignación de recursos:
a) Todas las solicitudes de recursos juntas
b) Asignación mediante jerarquización de recursos
c) Asignación mediante el algoritmo del banquero
sobre la base de a) inactividad del recurso y b) sobrecarga del algoritmo de asignación de recursos.
2. Cuando se usa la jerarquización de recursos como política de prevención de bloqueos mutuos, sólo se
permite que un proceso solicite una unidad de la clase de recursos Rk si rankk > ranki para cada clase de
recursos Ri, cuyos recursos le han sido asignados. Explique si pueden presentarse bloqueos mutuos
cuando la condición cambia a Rk si rankk ⱖ ranki.
3. Un sistema contiene 6 unidades de un recurso y 3 procesos que lo usan. ¿Pueden surgir bloqueos
mutuos en el sistema si el requerimiento máximo de recursos de cada proceso es de 3 unidades? Si el
sistema tuviera 7 unidades del recurso, ¿estaría libre de bloqueos mutuos para siempre? Explique con
claridad.
4. Un sistema que contiene recursos priorizables emplea la siguiente política de asignación de recursos:
cuando un recurso solicitado por un proceso Pi no está disponible
a) El recurso es priorizado de uno de sus procesos poseedores Pj si Pj es más joven que Pi. El recurso
se asigna ahora a Pi. Se volverá a asignar a Pj cuando Pi finaliza. (Un proceso se considera más
joven cuando fue iniciado más tarde.)
b) Si no se cumple la condición en 4 a), Pi es bloqueado para el recurso.

13 MAQ. CAP. 11(F0694).indd 515 8/10/07 1:13:01 AM


516 CAPÍTULO 11 Bloqueos mutuos

Un recurso liberado siempre se asigna al solicitante más viejo. Demuestre que no puede surgir un
bloqueo mutuo en ese sistema. También demuestre que cada proceso completa su ejecución en tiempo
finito.
5. Demuestre que el resultado de un análisis de bloqueos mutuos, ejecutado mediante el algoritmo 11.1,
no depende del orden en el que los procesos son transferidos de Running a Finished. (Sugerencia:
Considere los pasos 1 a) y 1 b).)
6. ¿Es seguro el estado de asignación (6, 1, 2) para el sistema del ejemplo 11.12? ¿Es seguro el estado de
asignación (5, 1, 1)?
7. ¿Se concederán las siguientes solicitudes en el estado actual?
R1 R2 R1 R2 R1 R2
p1 p1 Asignaciones
2 5 1 3 3 4
totales
p2 3 2 p2 2 1
Total
Necesidad Recursos existentes 4 5
máxima asignados

a) El proceso P2 solicita (1, 0)


b) El proceso P2 solicita (0, 1)
c) El proceso P2 solicita (1, 1)
d) El proceso P1 solicita (1, 0)
e) El proceso P1 solicita (0, 1)
8. En el siguiente sistema:
R1 R2 R3 R1 R2 R3 R1 R2 R2
p1 3 6 8 p1 2 2 3 Asignaciones 5 4 10
p2 p2 2 0 3 totales
4 3 3
p3 p3 1 2 4 Total
3 4 4 7 7 10
existentes
Necesidad Recursos
máxima asignados

a) ¿Es el estado actual de asignaciones seguro?


b) ¿Se concederán las siguientes solicitudes en el estado actual?
i) El proceso P1 solicita (1, 1, 0)
ii) El proceso P3 solicita (0, 1, 0)
iii) El proceso P2 solicita (0, 1, 0).
9. En un sistema de recursos simples que usa el algoritmo del banquero, 2 unidades de recursos no asig-
nadas existen en el estado actual de asignación. Tres procesos P1, P2 y P3 existen en el sistema. Se des-
cubre que si P1 o P2 solicitan la asignación de una unidad de recursos, las solicitudes son rechazadas,
pero si P3 solicita dos unidades de recursos, la solicitud se concede. Explique por qué podrá suceder
esto.
10. Un sistema que usa el algoritmo del banquero para la asignación de recursos contiene n1 y n2 unidades
de recursos de la clase de recursos R1 y R2, y tres procesos P1, P2 y P3. Los recursos no asignados en el
sistema son (1, 1). Se hacen las siguientes observaciones con respecto a la operación del sistema:
a) Si el proceso P1 hace una solicitud (1, 0) seguida por una solicitud (0, 1), se concederá la solicitud
(1, 0), pero no se concederá la solicitud (0, 1).
b) Si el proceso P1 hace una solicitud (0, 1) en lugar de las solicitudes de recursos que se mencionan
en 10 a), la solicitud se concederá.

13 MAQ. CAP. 11(F0694).indd 516 8/10/07 1:13:01 AM


Ejercicio 11 517

Halle un conjunto de valores posible para las asignaciones actuales y para los requerimientos de re-
cursos máximos de los procesos, de tal forma que las decisiones que usan el algoritmo del banquero
coincidan con las observaciones antes mencionadas.
11. Demuestre que cuando se aplica el algoritmo del banquero a un conjunto finito de procesos, cada uno
con un tiempo de ejecución finito, una solicitud insegura se hará segura en tiempo finito.
12. Los procesos de un SO hacen solicitudes múltiples. El SO usa un algoritmo del banquero diseñado
para una clase de recursos simples a fin de evitar bloqueos mutuos de la siguiente manera: cuando un
proceso hace una solicitud múltiple, vea la solicitud como un conjunto de solicitudes simples. Sólo
asigne las solicitudes múltiples si cada solicitud simple es segura en el estado de asignación actual del
sistema.
¿Se trata de un planteamiento sólido para evitar bloqueos mutuos? De ser así, demuestre que es
cierto. De lo contrario, dé un contraejemplo.
13. Un sistema de recursos simples contiene unidades exists de la clase de recursos Rs. Si el sistema contie-
ne n procesos, muestre que un bloqueo mutuo no puede surgir si se cumple cualesquiera de las siguien-
tes condiciones (véase la notación usada en el algoritmo 11.2):
a) Para todos los i : maxi,s ⱕ exists/n
b) ⌺i maxi,s ⱕ exists
c) ⌺i maxi,s ⱕ exists ⫹ n ⫺ 1 y para todos los i, 1 ⱕ maxi,s ⱕ exists.
14. En un sistema de recursos simples que contiene unidades exists de la clase de recursos Rs, el conjunto
PA se define como sigue:
PA ⫽ {Pi 兩 Pi le han sido asignado unos recursos, pero no todos sus requerimientos
de recursos han sido satisfechos }
Comente sobre la validez de los siguientes enunciados (véase la notación que se usa en el algoritmo
11.2):
a) “Los procesos en PA definitivamente entrarán en bloqueo mutuo si ⌺i maxi,s ⬎ exists.”
b) “Los procesos en PA sólo podrán entrar en bloqueo mutuo si existe un entero k de tal modo que
num_proc(k) ⬎ exists / k, donde num_proc(k) es el número de procesos en PA cuyos requerimientos
máximos para las unidades de la clase de recursos Rs excede k.”
15. Un sistema que contiene 4 procesos usa un algoritmo del banquero de recursos múltiples para la asig-
nación de recursos. El sistema ha estado en operación desde hace tiempo.
a) Un nuevo proceso llega al sistema. Inicialmente no se le asignan recursos. ¿Es seguro el nuevo
estado de asignación de recursos?
b) Un proceso es cancelado por el SO porque trata de acceder a un archivo para el cual no tiene los
privilegios correspondientes. ¿Es seguro el nuevo estado de asignación de recursos?
16. Un SO usa una estrategia sencilla para hacer frente a situaciones de bloqueos mutuos. Cuando se da
cuenta de que un conjunto de procesos está en un bloqueo mutuo, cancela todos e inmediatamente los
vuelve a iniciar. ¿Cuáles son las condiciones bajo las que el bloqueo mutuo no se repetirá?
17. Un SO tiene un solo disco que se usa a fin de: a) crear archivos de usuarios y b) poner en una cola de
prioridades la salida de impresoras para varios procesos usuarios. Para ambos usos, el espacio se asigna
con base en la demanda, y un proceso es bloqueado si no se puede conceder su requerimiento de espa-
cio en disco. La salida en cola de prioridad de la impresora se entrega a la impresora cuando finaliza un
proceso. ¿Existe la posibilidad de bloqueos mutuos en este sistema? De ser así, ¿bajo qué condiciones?
Sugiera una solución para el problema de bloqueos mutuos.
18. Un bloqueo mutuo fantasma es una situación donde un algoritmo de manejo de bloqueos mutuos decla-
ra un bloqueo mutuo, pero en realidad no existe ninguno. Demuestre que el algoritmo 11.1 no detecta
los bloqueos mutuos fantasma si no se permite que los procesos retiren sus solicitudes de recursos.

13 MAQ. CAP. 11(F0694).indd 517 8/10/07 1:13:01 AM


518 CAPÍTULO 11 Bloqueos mutuos

19. Una carretera cruza una vía férrea en dos puntos. En cada paso a nivel se construyen barreras en la ca-
rretera para detener el tráfico de la carretera cuando se acerca un tren. El tráfico ferroviario se detiene si
un automóvil bloquea las vías. Se permite el tráfico de automóviles en ambas direcciones de la carretera
y se permite el tráfico de trenes en ambas direcciones.
a) Discuta si bloqueos mutuos pueden surgir en el tráfico de carretera y en las vías férreas. ¿No habrá
bloqueos mutuos si tanto el tráfico de carretera como de trenes únicamente es en una sola direc-
ción?
b) Diseñe un conjunto de reglas sencillas para evitar bloqueos mutuos en el tráfico de carretera y de
trenes.
20. Se propone usar un planteamiento de prevención de bloqueos mutuos para el problema de la cena de
filósofos (véase la sección 9.5.3) de la siguiente manera: las sillas de la mesa están numeradas de 1 a
n, y los tenedores también están numerados de 1 a n, de tal modo que el tenedor izquierdo para la silla
i tiene el tenedor número i. Los filósofos deben seguir la siguiente regla: un filósofo tiene que levantar
primero el tenedor de numeración más baja y después el de numeración más alta.
Demuestre que no pueden surgir bloqueos mutuos en este sistema.
21. Un conjunto de procesos D se encuentra en un bloqueo mutuo. Se observa que
a) Si un proceso Pj 僆 D es cancelado, un juego de procesos D⬘ 傺 D aún sigue en un bloqueo mutuo.
b) Si un proceso Pi 僆 D es cancelado, ningún bloqueo mutuo existe en el sistema.
Indique posibles razones para esta diferencia y explíquelas por medio de un ejemplo. (Sugerencia:
Refiérase a los ejemplos 11.4 y 11.5.)
22. Muestre que un nudo de recursos en una RRAG es una condición necesaria y suficiente para bloqueos
mutuos en los sistemas SISR, MISR, SIMR y MIMR.
23. Desarrolle una caracterización de bloqueos mutuos por medio de una WFG para un sistema de recursos
en el cual las clases de recursos pueden contener unidades y procesos múltiples y hacer solicitudes de
recursos múltiples.
24. Un sistema usa una política de detección y resolución de bloqueos mutuos. Se considera que el costo
de cancelar un proceso es una unidad. Discuta cómo puede minimizarse el costo de la resolución de
bloqueos mutuos en los sistemas SISR, SIMR, MISR y MIMR.

BIBLIOGRAFÍA
Dijkstra (1965), Havender (1968) y Habermann (1969) elaboraron obras tempranas sobre el manejo de
bloqueos mutuos. Dijkstra (1965) y Habermann (1969) analizan el algoritmo del banquero. Coffman et
al. (1971) estudian el algoritmo de detección de bloqueos mutuos para un sistema que contiene recursos
de instancias múltiples. Holt (1972) ofreció una caracterización de bloqueos mutuos basada en la teoría de
grafos. Isloor y Marsland (1980) hicieron un buen estudio de análisis sobre este tema. Zobel (1983) pre-
senta una amplia bibliografía. Howard (1973) analiza el enfoque práctico del manejo de bloqueos mutuos
que se describe en la sección 11.8. Tay y Loke (1995) y Levine (2003) estudian la caracterización de los
bloqueos mutuos.
Bach (1986) describe el manejo de bloqueos mutuos en Unix.

1. Bach, M.J. (1986): The Design of the Unix Operating System, Prentice-Hall, Englewood Cliffs.
2. Coffman, E.G., M.S. Elphick y A. Shoshani (1971): “System deadlocks”, Computing Surveys, 3
(2), 67-78.
3. Dijkstra, E.W. (1965) : “Cooperating sequential processes”, Technical report EWD–123, Techno-
logical University, Eindhoven.

13 MAQ. CAP. 11(F0694).indd 518 8/10/07 1:13:01 AM


Bibliografía 519

4. Habermann, A.N. (1969): “Prevention of System deadlocks”, Communications of the ACM, 12


(7), 373-377.
5. Habermann, A.N. (1973): “A new approach to avoidance of system deadlocks”, en Lecture notes
in Computer Science, vol. 16, Springer-Verlag.
6. Havender, J.W. (1968): “Avoiding deadlock in multitasking systems”, IBM Systems Journal, 7 (2),
74-84.
7. Holt, R.C. (1972): “Some deadlock properties of computer systems”, Computing Surveys, 4 (3),
179-196.
8. Howard, J.H. (1973): “Mixed solutions to the deadlock problem”, Communications of the ACM,
6 (3), 427-430.
9. Isloor, S.S. y T.A. Marsland (1980): “The deadlock problem—an overview”, Computer, 13 (9),
58-70.
10. Levine, G. (2003): “Defining deadlock”, Operating Systems Review, 37, 1.
11. Rypka, D.J. y A.P. Lucido (1979): “Deadlock detection and avoidance for shared logical resour-
ces”, IEEE transactions on Software Engg, 5 (5), 465-471.
12. Tay, Y.C. y W.T. Loke (1995): “On Deadlocks of exclusive AND-requests for resources”, Distri-
buted Computing, Springer Verlag, 9, 2, 77-94.
13. Zobel, D. (1983): “The deadlock problem—a classifying bibliography”, Operating Systems Re-
view, 17 (4), 6-15.

13 MAQ. CAP. 11(F0694).indd 519 8/10/07 1:13:02 AM


Capítulo
12
Implementación de
operaciones de archivos

El procesamiento de archivos se implementa por medio de módulos del sistema de archivos


y del Sistema de Control Entrada Salida (IOCS, por sus siglas en inglés). Los módulos del sis-
tema de archivos abordan temas concernientes a nomenclatura, compartición, protección y al-
macenamiento confiable de archivos. Los módulos del IOCS abordan tópicos relativos al acceso
eficiente a los registros de un archivo y al uso eficiente de los dispositivos de E/S.
La capa del IOCS consiste en dos subcapas llamadas métodos de acceso y el IOCS físico
(PIOCS). La capa de los métodos de acceso aborda asuntos relacionados con el acceso eficiente
a registros en un archivo, y la capa del IOCS físico lo hace en relación con el rendimiento de los
dispositivos.
El IOCS físico, junto con un método de acceso, implementa operaciones en archivos. El
primero ejecuta entradas/salidas en el nivel del dispositivo de E/S y usa políticas de planificación
para aumentar el rendimiento de los discos. El método de acceso usa las técnicas de coloca-
ción en memoria intermedia (buffering) y bloqueo de registros para reducir, y de ser posible
eliminar, los tiempos de espera involucrados en acceder a un registro en un archivo.
En primer término analizaremos las características de dispositivos de E/S y los arreglos que
se usan para ofrecer alta confiabilidad, rápido acceso y altos índices de transferencia de datos.
Luego estudiaremos cómo se realizan operaciones de E/S en el nivel de los dispositivos de E/S,
las facilidades que ofrecen los IOCS físicos para simplificar operaciones de E/S y cómo la pla-
nificación de estas operaciones aumenta el rendimiento de un disco. Por último analizaremos las
técnicas de colocación en memoria intermedia (buffering) y el bloqueo de registros en un archivo
a fin de reducir los tiempos de espera de E/S.

12.1 CAPAS DEL SISTEMA DE CONTROL ENTRADA SALIDA

El esquema de la figura 12.1 muestra cómo el Sistema de Control Entrada Salida (IOCS) imple-
menta operaciones de archivos. Los procesos Pi y Pj están ocupados con actividades de proce-
samiento de archivos y ya han abierto algunos. Cuando uno de estos procesos hace una solicitud
para leer o escribir datos de un archivo, el sistema de archivos pasa la solicitud al IOCS. Para una

14 MAQ. CAP. 12(F0694).indd 520 8/10/07 1:15:25 AM


12.1 Capas del sistema de control entrada salida 521

operación de lectura, el IOCS verifica si los datos requeridos por el proceso están presentes en
un área de memoria que se usa como buffer de archivos o en la memoria caché del disco. De ser
así, se permite que el proceso acceda a los datos inmediatamente; en el caso contrario, el IOCS
emite una o varias operaciones de E/S para cargar los datos en un buffer de archivos o en la
memoria caché del disco, y el proceso tiene que esperar hasta que finaliza esta operación de E/S.
Las operaciones de E/S son planificadas por un algoritmo de planificación que tiene el objetivo
de proporcionar un alto rendimiento del disco. De este modo, el IOCS implementa operaciones
de E/S de manera que proporciona eficiencia de actividades de procesamiento de archivos en
procesos y un alto rendimiento de los dispositivos de E/S.

Métodos de acceso

IOCS físico
Proceso
Pi

memoria Operaciones
intermedia/
bloqueo de E/S

Proceso Buffers de Planificación


Pj archivos/ del disco Bloques del disco
Memoria caché contienen ≥ 1
del disco registros

Figura 12.1 Organización física en métodos de acceso e IOCS físicos.

El IOCS está estructurado en dos capas llamadas método de acceso e IOCS físico. La capa
del método de acceso proporciona el procesamiento eficiente de archivos y la del IOCS físico
proporciona un alto rendimiento del dispositivo. Esta estructura del IOCS separa los asuntos
del nivel proceso en la implementación exitosa de una operación de E/S de los asuntos del nivel
dispositivo.
La figura 12.2 muestra la jerarquía del sistema de archivos y las capas del IOCS. El número
de capas del IOCS y sus interfaces varía en los diferentes sistemas operativos. En la mayoría de
ellos, el IOCS físico forma parte del kernel. Sin embargo, diferenciaremos entre los dos en aras
de la claridad. Vamos a suponer que el IOCS físico es invocado por medio de llamadas al sistema
e invoca a su vez a otras funcionalidades del kernel, también mediante llamadas al sistema.
La tabla 12.1 resume mecanismos y políticas significativos implementados por capas del
IOCS en un diseño convencional de un IOCS de dos capas. La capa del IOCS físico implemen-
ta E/S del nivel dispositivo. Sus módulos de política determinan el orden en el cual deberán
ejecutarse operaciones del IOCS para lograr un desempeño alto del dispositivo. Estos módulos
invocan mecanismos del IOCS físico para ejecutar operaciones de E/S. El método de la capa de
acceso proporciona módulos de política que aseguran E/S eficientes de archivos y mecanismos

14 MAQ. CAP. 12(F0694).indd 521 8/10/07 1:15:26 AM


522 CAPÍTULO 12 Implementación de operaciones de archivos

Proceso

Capa del sistema de archivos

Capa del método de acceso

Capa del IOCS físico

Kernel

Figura 12.2 Capas del sistema de archivos e IOCS.

que admiten E/S del nivel de archivos de puerto. Estos mecanismos usan módulos de política
del IOCS físico para lograr E/S eficientes del nivel dispositivo. La capa del sistema de archi-
vos implementa la compartición y protección de éstos, usando módulos de política y mecanis-
mos del método de acceso.

Tabla 12.1 Mecanismos y políticas en el sistema de archivos y las capas del IOCS

IOCS físico
• Mecanismos: Iniciación de E/S, Proporcionar el estatus de operaciones de
E/S, Procesamiento de finalización de E/S, Recuperación de errores
• Política: Optimización del desempeño de dispositivos de E/S
Métodos de acceso
• Mecanismos: Abrir y cerrar archivos, Lectura y escritura
• Política: Optimización del desempeño del acceso a archivos
Sistemas de
Archivos (FS)
• Mecanismos: Asignación de bloques del disco, Mantenimiento de directo-
rios, colocación/revisión de la información sobre protección de archivos
• Políticas: Asignación de espacio en disco para la eficiencia de acceso,
compartición y protección de archivos

Observe que la tabla 12.1 enumera sólo aquellos mecanismos a los que se puede acceder
de manera intencionada desde un nivel mayor. Otros, que son “privados” para una capa, no se
enumeran aquí. Por ejemplo, los mecanismos de colocación en memoria intermedia de E/S y los
de bloqueo existen en la capa del método de acceso. Sin embargo, sólo están disponibles para
los módulos de la política del método de acceso; no hay acceso a ellos directamente desde la capa
del sistema de archivos.

La organización física en los métodos de acceso e IOCS físico La figura 12.1 muestra la
organización física. Las operaciones de lectura o escritura en procesos dan como resultado lla-
madas a métodos de acceso correspondientes. Estas acciones producen comandos para ejecutar

14 MAQ. CAP. 12(F0694).indd 522 8/10/07 1:15:26 AM


12.2 Visión general de la organización de E/S 523

operaciones de E/S para transferir datos entre un bloque de disco y un área de memoria que se
usa como un buffer de archivo o una memoria caché del disco. Los datos se copian luego desde
ahí al espacio de dirección de un proceso. El IOCS físico realiza la planificación del disco para
determinar el orden en el que se deberán ejecutar las operaciones de E/S y las inicia.

12.2 VISIÓN GENERAL DE LA ORGANIZACIÓN DE E/S

Interrupciones
Bus Prot E/S
Unidad de ....
Memoria traducción
de direcciones
PSW

Registros
CPU

DMA
Controladores
de dispositivos
Dispositivos

Figura 12.3 Modelo de un sistema de cómputo.

La sección 2.1 contiene una visión general de la organización de E/S. La figura 12.3 se reproduce
de acuerdo con esa visión. Cada controlador de dispositivo recibe una id numérica única (identi-
ficador) en el sistema. De igual modo, cada dispositivo conectado a él tiene una id de dispositivo
numérica única. Una dirección de dispositivo es un par (controller_id, device_id).
Una operación de E/S consiste en una secuencia de tareas elementales de E/S. Se inicia
mediante la ejecución de una instrucción de E/S. El CPU, el controlador DMA, el controlador
de dispositivo y el dispositivo de E/S participan para realizar una instrucción de E/S. Una ta-
rea de E/S es implementada por un comando de E/S, que requiere la participación del controlador
DMA y del controlador de dispositivo, pero no del CPU.

Ejemplo 12.1 La operación de E/S para leer un registro del disco con la id (track_id, record_id)
involucra las siguientes instrucciones y comandos de E/S:
Instrucción de E/S : Inicia E/S en (controller_id, device_id)
Comandos de E/S : Posiciona las cabezas del disco en la pista track_id
Lee el registro record_id
El comando de E/S “posiciona las cabezas del disco” no implica la transferencia de datos; en
cambio, “lee el registro” sí implica dicha transferencia.

14 MAQ. CAP. 12(F0694).indd 523 8/10/07 1:15:26 AM


524 CAPÍTULO 12 Implementación de operaciones de archivos

Tres modos de realizar operaciones de E/S —el modo programado, el modo de interrupción
y el modo de acceso directo a la memoria (DMA)— fueron resumidos en la tabla 2.1. Empeza-
remos con la descripción del modo DMA.

Acceso directo a la memoria (DMA) En el modo DMA se transfieren datos entre un dis-
positivo de E/S y la memoria sin involucrar al CPU. Cuando se ejecuta una instrucción de E/S,
el CPU transfiere los siguientes detalles al controlador del DMA:

• La dirección del dispositivo de E/S.


• La operación que se va a ejecutar, es decir, lectura o escritura.
• El número de bytes de datos que se van a transferir.
• La dirección en la memoria y, de ser aplicable, la dirección del dispositivo de E/S desde
donde la transferencia empezará.

Esta información normalmente se coloca en un área de la memoria. Una instrucción de E/S


usa la dirección de esa área como operando. Cuando se ejecuta la instrucción, el CPU pasa
esta dirección a la interface del DMA. Más allá de este punto, el CPU no está involucrado en
la operación, está libre para ejecutar operaciones mientras la operación de E/S se está reali-
zando.
El arreglo llamado DMA de terceros (third party) funciona de la siguiente manera: contro-
ladores de dispositivos están conectados con el controlador de DMA, tal como se muestra en la
figura 12.3. Cuando se ejecuta una instrucción de E/S, el controlador de DMA pasa algunos
detalles de la operación de E/S al controlador de dispositivo del dispositivo de E/S para que
pueda iniciar la operación. Los controladores del dispositivo y del DMA coordinan la transfe-
rencia de datos entre el dispositivo de E/S y la memoria. Al final de la transferencia de datos, el
controlador del DMA plantea una interrupción de finalización de E/S con la dirección del dis-
positivo como código de interrupción. La rutina de manejo de interrupciones analiza el código
de interrupción para determinar qué dispositivo ha terminado su operación de E/S y realiza las
acciones correspondientes.
La implementación de la transferencia de datos entre un dispositivo de E/S y la memoria
se lleva a cabo de la siguiente manera: el controlador del dispositivo transmite una señal de
solicitud de DMA cuando está dispuesto a realizar una transferencia de datos. Al ver esta señal,
el controlador del DMA obtiene el control del bus, pone en él la dirección de la ubicación de
memoria que participará en la transferencia de datos y transmite una señal de reconocimiento del
DMA al controlador del dispositivo. Después, el controlador del dispositivo transfiere los datos
hacia o desde la memoria.
El CPU ejecuta instrucciones mientras se está realizando una operación de E/S. Por ende,
el CPU y el controlador del DMA están en competencia para el uso del bus. La técnica del robo
de ciclos se usa para asegurar que ambos pueden usar el bus sin enfrentar largas demoras. El
CPU posterga al controlador del DMA para el uso del bus en algunos puntos específicos en su
ciclo de instrucción, normalmente cuando está a punto de leer una instrucción o sus datos de la
memoria. Cuando el DMA quiere transferir datos hacia o desde la memoria, espera hasta que el
CPU llega a uno de estos puntos. Luego roba un ciclo de memoria del CPU para implementar su
transferencia de datos.
El DMA principal (first-party) logra índices de transferencia de datos más altos que el DMA
de terceros. En este arreglo, el controlador del dispositivo y el del DMA se combinan para formar

14 MAQ. CAP. 12(F0694).indd 524 8/10/07 1:15:26 AM


12.3 Dispositivos de E/S 525

una sola unidad. Dicha unidad obtiene el control del bus cuando está lista para una transferencia
de datos. Esta técnica se llama bus maestro (bus mastering).

12.3 DISPOSITIVOS DE E/S

Los dispositivos de E/S usan para el registro de datos una variedad de principios, tales como
principios electromecánicos de generación de señales y principios electromagnéticos u ópticos.
Además, emplean una variedad de medios de E/S, sirven para diferentes propósitos y usan di-
ferentes métodos de organización de datos y de acceso a ellos. Los dispositivos de E/S pueden
clasificarse según los siguientes criterios:

• Objetivo: Dispositivos de entrada, impresión y almacenamiento.


• Naturaleza del acceso: Dispositivos de acceso secuencial y aleatorio.
• Modo de transferencia de datos: Dispositivos de modo de caracteres y bloques.

Un dispositivo de acceso secuencial usa su medio de E/S de manera secuencial, de tal modo
que una operación siempre se lleva a cabo en un elemento de datos que adjunta con el elemento
de datos accedido en la operación anterior. El acceso a cualquier otro elemento de datos requiere
comandos adicionales para saltar sobre elementos de datos que intervienen. Un dispositivo de
acceso aleatorio puede ejecutar una operación de lectura o escritura en datos ubicados en cual-
quier parte del medio de E/S.
El modo de transferencia de datos de un dispositivo depende de su velocidad de transferen-
cia de datos. Un dispositivo de E/S lento opera en el modo de caracteres, es decir, transfiere un
carácter a la vez entre la memoria y el dispositivo. El dispositivo contiene un buffer pequeño
para almacenar el carácter. El controlador del dispositivo levanta una interrupción después de
que un dispositivo de entrada lee un carácter o de que un dispositivo de salida escribe un carácter.
Los controladores de estos dispositivos pueden conectarse directamente al bus. El teclado, el
mouse y la impresora son dispositivos del modo de caracteres.
Un dispositivo capaz de un alto índice de transferencia de datos opera en el modo de bloques
de transferencia de datos. Está conectado a un controlador de DMA. Cintas y discos son dispo-
sitivos del modo de bloques. Un dispositivo del modo de bloques necesita leer o escribir datos
con una velocidad especificada. Se perderán datos durante una operación de lectura si el bus es
incapaz de aceptar datos de un dispositivo de E/S con la velocidad requerida de transferencia a
la memoria, y una operación de escritura fracasará si es incapaz de entregar datos al dispositivo
de E/S con la velocidad requerida. Se podrá presentar una pérdida de datos si una transferen-
cia de datos se retrasa debido a una competencia por el bus.
A fin de prevenir la pérdida de datos durante una operación de E/S, no se transfieren datos a
través del bus durante la operación. En el transcurso de una operación de entrada, los datos entre-
gados por el dispositivo de E/S se guardan en un buffer del controlador de DMA. Se transfieren
a la memoria después de la finalización de la operación de E/S. Para ejecutar una operación de
salida, los datos que van a escribirse al dispositivo de E/S primero se transfieren de la memoria
al buffer del DMA. Durante la operación de E/S se transfieren del buffer del DMA al dispositivo
de E/S.
La tabla 12.2 enumera dispositivos de E/S clasificados de acuerdo con el objetivo y el modo
de acceso. Una unidad de un medio de E/S se llama volumen de E/S. Un cartucho de cinta y un
disco pueden llamarse entonces un volumen de cinta y un volumen de disco, respectivamente.

14 MAQ. CAP. 12(F0694).indd 525 8/10/07 1:15:27 AM


526 CAPÍTULO 12 Implementación de operaciones de archivos

Tabla 12.2 Dispositivos de E/S

Objetivo Modo de acceso Ejemplos


Entrada Secuencial Teclado, mouse, conexiones de red, cintas, discos
Aleatorio Discos
Impresión Secuencial Impresoras, conexiones de red, cintas, discos
Aleatorio Discos
Almacenamiento Secuencial Cintas, discos
Aleatorio Discos

Los volúmenes de E/S en algunos dispositivos de E/S son desmontables, por ejemplo, discos
flexibles (floppies), discos compactos (CD) o cartuchos de cintas de audio digitales (DAT), mien-
tras que los de otros dispositivos de E/S, por ejemplo, discos duros, están fijos en el dispositivo
de forma permanente. Se dice que las informaciones escritas (o leídas) en una operación E/S
forman un registro.
Usaremos la siguiente notación para la discusión de operaciones de E/S.

tio : Tiempo de E/S, es decir, intervalo de tiempo entre la ejecución de una


instrucción to-init y la finalización de E/S.
ta : Tiempo de acceso, es decir, intervalo de tiempo entre la emisión de un
comando de lectura o escritura y el inicio de la transferencia de datos.
tx : Tiempo de transferencia, es decir, el tiempo que se toma para transferir
los datos de/a un dispositivo de E/S durante una operación de lectura o
escritura.

La figura 12.4 ilustra los factores que influyen en tio. El tiempo de E/S para un registro es la
suma de su tiempo de acceso y del tiempo de transferencia, es decir:

tio  ta  tx (12.1)

Dispositivo preparado
para transferencia Transferencia de
de datos datos en proceso
ta tx

Se emitió comando Inicia Termina


de lectura/escritura transferencia transferencia
de datos de datos
Figura 12.4 Tiempos de acceso y transferencia en una operación de E/S.

Las acciones de un dispositivo secuencial están relacionadas con la posición que guarda
en cada momento. Puede operar en dirección hacia delante o hacia atrás con respecto a su po-

14 MAQ. CAP. 12(F0694).indd 526 8/10/07 1:15:27 AM


12.3 Dispositivos de E/S 527

sición. Debido a su característica, un dispositivo secuencial sólo puede leer registros ubicados
en cada lado de su posición actual, y sólo puede escribir el siguiente registro en su dirección
hacia delante. Un dispositivo de acceso aleatorio puede leer o escribir cualquier registro en un
volumen de E/S. A fin de implementar esta capacidad, a todos los registros en un volumen se
les asigna direcciones o ids. Mientras que realiza una operación de lectura o escritura, el dispo-
sitivo debe localizar el registro deseado antes de comenzar una operación de lectura o escritura.
Debido a esta peculiaridad, el tiempo de acceso en un dispositivo secuencial (véase la ecuación
(12.1)) es una constante, mientras que varía para diferentes registros en un dispositivo de ac-
ceso aleatorio.

Detección de errores Pueden ocurrir errores de registro de datos mientras se escriben és-
tos o mientras se leen desde un medio de E/S. De igual modo, errores de transmisión de datos
pueden suceder cuando se transfieren datos entre un medio de E/S y la memoria. Para facilitar
la detección de errores, los datos que están siendo escritos o transmitidos se ven como un flujo
de bits, es decir, como un flujo de unos y ceros, y se usan códigos especiales para representar el
flujo de bits mientras éste es escrito o transmitido.
La detección de errores se realiza por medio de la redundancia. Algunas informaciones
de detección de errores están asociadas con los datos y se escriben con ellos. Cuando se leen
datos de un medio de E/S, estas informaciones también se leen del medio. Ahora bien, la infor-
mación de detección de errores es generada nuevamente a partir de los datos de lectura, usando
la misma técnica, y se compara con la información de detección de errores que se lee desde el
medio. Una falta de coincidencia indica errores de escritura.
La figura 12.5 describe dos planteamientos de la detección y corrección de errores. En el
planteamiento de bits de paridad, se calculan np bits de paridad para nd bits de datos. Los bits
de paridad son colocados en ubicaciones prefijadas en un registro. Son indistinguibles de datos,
excepto para el algoritmo de detección/corrección de errores. En el planteamiento de suma veri-
ficadora de la redundancia cíclica (CRC), se registra una suma verificadora de nc bits al final de
los datos. np depende de nd, mientras que nc es independiente de nd.
Ambos planteamientos usan la aritmética de módulo 2. Ésta ignora las “cargas” y “prés-
tamos” generados en cualquier posición de bits y, por tanto, es más rápida que la aritmética
binaria. Una suma de módulo 2 se representa como una operación de OR exclusiva 丣. Emplea
las siguientes reglas: 0 丣 0  0, 1 丣 0  1, 0 丣 1  1 y 1 丣 1  0. Una variante popular del
planteamiento de bits de paridad que se usa en las RAM y cintas magnéticas más viejas asocia
un bit de paridad individual con un byte de datos. Como se describe en la figura 12.5, el
bit de paridad es generado a partir de todos los bits de un byte que usan la operación 丣. Puede
detectar un solo error en un byte, pero falla si ocurren dos. Tampoco puede corregir errores. La
sobrecarga de detección de errores es un bit de paridad para ocho bits de datos, es decir, 12.5
por ciento.
La suma verificadora de la redundancia cíclica (CRC) se calcula a partir de datos que serán
transmitidos o escritos, y se pone en el campo de CRC de un registro. Puede indicar si uno o
más errores han ocurrido en cualquier byte de datos, o si han sido intercambiados o reordenados.
Como se describió antes, cuando se lee un registro, se calcula una CRC a partir de su campo
de datos y se compara con el código en su campo de CRC. Un error existe si los dos no coin-
ciden. Un valor práctico de nc es 16 o 32 bits, independientemente del valor de nd. Para nc 
nd, la detección de errores no es infalible porque dos flujos de bits, supongamos s1 y s2, podrían
generar la misma CRC. Si uno de ellos es transformado en el otro debido a un error, la CRC no
puede detectar ese error. La probabilidad de este suceso es 21nc , así que la confiabilidad de la CRC

14 MAQ. CAP. 12(F0694).indd 527 8/10/07 1:15:27 AM


528 CAPÍTULO 12 Implementación de operaciones de archivos

Datos Suma
verificadora
nd + n p bits Bit de paridad nd bits nc bits
Un registro Un registro
Bits de paridad Suma verificadora de redundancia
cíclica (CRC)
a) b)
Cálculo de un bit de paridad
Un bit de paridad se calcula a partir de una colección de bits de datos mediante la aritmética de
módulo 2, es decir, por medio del operador de OR exclusivo 丣. Por ejemplo, el bit de paridad para
cuatro bits de datos bi, bj, bk y bl se calcula del siguiente modo: p = bi 丣 bj 丣 bk 丣 bl 丣 c1, donde c1
es una constante que es 1 para paridad impar y 0 para paridad par.
Suma verificadora de redundancia cíclica (CRC)
Paso 1: Un flujo de bits es considerado como un polinomio binario, es decir, un polinomio en el que
cada uno de sus coeficientes es un 0 o un 1. Por ejemplo, un 1101 de un flujo de bits se considera
como un polinomio binario 1  x3  1  x2  0  x1  1  x0, es decir, x3  x2  1. Aquí un signo
de  se interpreta como una suma de módulo 2: una operación de OR exclusiva 丣.
Paso 2: Los datos en un registro recibido son aumentados por agregar nc ceros al final. El polinomio
que se obtiene de los datos aumentados es dividido entre un polinomio predefinido del grado nc  1.
El residuo de esta división es un polinomio del grado nc. Los coeficientes en este polinomio forman
la CRC. Por ejemplo, la CRC para los datos 11100101 que usa un polinomio predefinido 11011 de
cinco bits es 0100.
Paso 3: Cuando se recibe un registro, el receptor calcula la CRC a partir de la parte de datos del re-
gistro y la compara con la parte CRC del registro. Una falta de coincidencia indica un(os) error(es).
De modo alternativo, el receptor calcula la CRC a partir del registro completo. Un error existe si la
CRC calculada no es 0.

Figura 12.5 Planteamientos de detección de errores: a) bits de paridad; b) suma verificadora.

es 1  21nc . Para una CRC de 16 bits, la confiabilidad es de 99.9985 por ciento. Para una CRC de
32 bits, es de 99.9999 por ciento.

12.3.1 Cintas y cartuchos magnéticos

El medio de E/S en una cinta o cartucho es una tira de material magnético en el cual se escriben
informaciones en la forma de unos y ceros, usando principios de la grabación electromagnética.
La grabación en una cinta es de pistas múltiples. Una cabeza de lectura/escritura se posiciona
en cada pista. Esta cabeza graba o lee informaciones de los bits de un byte, así como también
algunas informaciones adicionales que se usan para la detección y corrección de errores.
Las unidades de cinta son dispositivos de acceso secuenciales. Las operaciones que se pue-
den ejecutar en estos dispositivos son las siguientes: read/write (count, addr (I/O_area)),
skip y rewind, donde count (conteo) es el número de bytes de datos que va a ser transferido,

14 MAQ. CAP. 12(F0694).indd 528 8/10/07 1:15:27 AM


12.3 Dispositivos de E/S 529

y addr (I/O_area), es la dirección de un área de memoria hacia la cual se deberá realizar la


transferencia de datos desde el medio de E/S (o viceversa). Frecuentemente se usan cintas y
cartuchos DAT para los propósitos de archivado. En este tipo de uso, todos los registros se leen
y escriben cada vez que se usa la cinta, lo que es fácil de realizar debido a la naturaleza secuen-
cial de los dispositivos.
En cintas más antiguas, los registros contiguos de una cinta son separados por un inter-
record gap. Este espacio entre registros se encarga del movimiento de arranque/detención del
medio entre la lectura o escritura de registros sucesivos. El tiempo de acceso durante una ope-
ración de lectura o escritura (ta) es el usado para lograr la velocidad uniforme del medio de E/S
antes de que se pueda iniciar la transferencia de datos. El tiempo total de E/S para un registro
del tamaño de s bytes es proporcionado por la fórmula tio ta d s v , donde d es la densidad de
grabación y v es la velocidad del medio de E/S.
Los espacios entre registros causan sanciones muy costosas. Llevan a un uso pobre del
medio de grabación y retrasan las actividades de procesamiento de archivos. Pese al inconve-
niente de la pobre utilización del medio de grabación, en los años noventa las cintas ofrecieron
un costo por megabyte que fue una décima parte de lo que ofrecieron los discos. Sin embargo,
en la década posterior, las cintas perdieron esta ventaja porque la tecnología de discos tuvo un
gran progreso y discos grandes se volvieron prácticos y baratos. Con el fin de recuperar la ven-
taja de costo, se desarrolló la tecnología de la cinta continua.
Una cinta continua contiene un solo registro que se almacena sin pausa, independiente-
mente de su tamaño. Por ende, no existen espacios entre registros aun cuando se grabe un gran
volumen de datos en una cinta. Un dispositivo de cinta continua contiene un buffer. Se inicia
una operación de escritura después de colocar unos datos en él. El dispositivo escribe los datos
desde el buffer hacia la cinta. A fin de mantener la cinta continua operando a plena velocidad, es
importante poner nuevos datos al buffer con una velocidad que corresponda a la de escritura de
la cinta. Ésta deja de escribir al darse cuenta de que el buffer está vacío. Cuando se ponen nuevos
datos en el buffer, la cinta reanuda la operación de escritura. Para evitar la creación de un espacio
entre registros, la cinta se mueve primero hacia atrás y luego nuevamente hacia delante, de tal
forma que puede adquirir la velocidad de grabación al tiempo que la cabeza pasa sobre el último
bit que había escrito. Entonces reanuda la escritura. De hecho, la reanudación de la escritura
consume unos cuantos milisegundos.
La cinta continua ofrece un alto índice de transferencia de datos si no se permite que el
buffer se vacíe en ningún momento. No obstante, si la cinta se detiene frecuentemente, la ve-
locidad de escritura efectiva puede bajar a un valor mucho más pequeño. El IOCS físico tiene
que asegurar que esto no suceda. El movimiento de arranque y detención también requiere un
posicionamiento y alineación precisos. Esto hace que las cintas continuas sean caras.

12.3.2 Discos
Un disco es un objeto circular plano llamado plato, que gira alrededor de su propio eje. Las su-
perficies circulares de un plato están cubiertas con material magnético. Se usa una sola cabeza de
lectura/escritura para realizar la grabación en una superficie; por tanto, un byte es grabado en
serie a lo largo de una pista. La cabeza de lectura/escritura puede moverse en forma radial sobre
el plato. Para cada posición de la cabeza, la información grabada forma una pista circular so-
bre la superficie del disco. En un disco no se usa la información de paridad; una suma verifica-
dora de redundancia cíclica (CRC) se escribe junto con cada registro para admitir la detección
de errores.

14 MAQ. CAP. 12(F0694).indd 529 8/10/07 1:15:28 AM


530 CAPÍTULO 12 Implementación de operaciones de archivos

Una posición de inicio de pista se marca en cada pista, y se dan números seriados a los re-
gistros de una pista con respecto a esta marca. El disco puede acceder a cualquier registro usando
una dirección de registro de la forma (track_no, record_no). El tiempo de acceso para un registro
de disco se da mediante la fórmula
ta  ts  tr (12.2)
donde ts : tiempo de búsqueda, es decir, el tiempo para posicionar la cabeza sobre la pista
requerida
tr : latencia rotacional, es decir, el tiempo para acceder al registro deseado en la
pista
El tiempo de búsqueda es causado por el movimiento mecánico de la cabeza. La latencia rota-
cional surge porque una operación de E/S sólo puede iniciar cuando el registro requerido está a
punto de pasar por debajo de la cabeza. La latencia rotacional promedio es el tiempo que tarda la
mitad de una revolución del disco. Los valores representativos de la latencia rotacional prome-
dio son 3-4 milisegundos, los tiempos de búsqueda están en el orden de 5-15 milisegundos y las
velocidades de transferencia de datos se ubican alrededor de 10 M bytes por segundo.
Variaciones en la organización de discos han sido motivadas por el deseo de reducir el
tiempo de acceso, aumentar la capacidad del disco y hacer un uso óptimo de su superficie. Con
la finalidad de ofrecer el acceso rápido, puede suministrarse una cabeza para cada pista de la su-
perficie del disco. Estos discos, que se conocen como de cabeza por pista (HPT), se usaron como
dispositivos de paginación en los primeros sistemas de memoria virtual.
Se obtienen mayores capacidades de discos montando muchos platos sobre el mismo eje
para formar un paquete de disco. Se proporciona una cabeza de lectura/escritura para cada su-
perficie circular de un plato. Todas las cabezas del paquete de disco están montadas sobre un solo
brazo de disco, por lo que en todo momento las cabezas están ubicadas en pistas idénticamente
posicionadas en diferentes superficies. Esta propiedad del paquete de disco se explota por medio
de la noción de un cilindro.
Un cilindro es una colección de pistas idénticamente posicionadas en diferentes superfi-
cies (véase la figura 12.6). Por tanto, pueden llevarse a cabo operaciones de E/S en registros
situados en el mismo cilindro sin incurrir en tiempos de búsqueda. El paquete de disco puede
ser considerado como compuesto de un conjunto de cilindros concéntricos entre el cilindro más
interior, que son las pistas más interiores de todas las superficies, y el cilindro más exterior, que
son las pistas más exteriores de todas las superficies. La dirección de un registro se especifica
como (número de cilindro, número de superficie, número de registro). Los comandos admitidos
por un dispositivo de disco son read/write (record address, addr(I/O_area)) y seek (número
de cilindro, número de superficie).

Discos sectorizados Una organización de disco sectorizado se usa para optimizar el uso de
la superficie del disco. Un sector es un registro del disco con un tamaño estándar. Se selecciona
el tamaño del sector para asegurar el mínimo desperdicio de capacidad de grabación debido
a espacios entre registros en la superficie. La sectorización puede formar parte del hardware
del disco (sectorización dura) o puede implementarse por medio del software (sectorización
blanda).

Técnicas de escalonado de datos Como se describe antes, un controlador de DMA colo-


ca en un buffer los datos involucrados en una operación de E/S y los transfiere hasta y desde la

14 MAQ. CAP. 12(F0694).indd 530 8/10/07 1:15:28 AM


12.3 Dispositivos de E/S 531

Cabezas de lectura/escritura

Plato
Brazo del disco

Cilindro

Pista

Figura 12.6 Noción de un cilindro en un paquete de disco.

memoria como un solo bloque de datos. Para una operación de lectura, el controlador de DMA
ejecuta la transferencia de datos luego de que los datos completos han sido leídos del dispo-
sitivo. Mientras se está realizando esta transferencia, el disco continúa girando, y uno o más
sectores pueden pasar por debajo de la cabeza hasta el momento en que la transferencia está
completa. Por tanto, un intento de leer el siguiente sector no puede tener éxito en el mismo
giro del disco. Durante una operación de escritura, la transferencia de datos se lleva a cabo
antes de que se inicie la grabación de ellos. Sin embargo, el efecto es el mismo: no pueden escri-
birse datos al siguiente sector durante el mismo giro. En ambos casos se afecta el rendimiento
del disco.
Un problema similar es causado cuando el primer sector de un plato debe leerse inmediata-
mente después de la lectura del último sector del plato anterior. Entonces, la operación de lectura
se deberá cambiar entre cabezas posicionadas en diferentes platos; esto causa un retraso llamado
tiempo de cambio de cabezas. En el procesamiento de archivos secuencial, ese tiempo tiene que
transcurrir después de la lectura del último sector de un plato, antes de que se pueda ejecutar
la siguiente operación de lectura. Para entonces, unos cuantos sectores del siguiente plato han
pasado por debajo de la cabeza de lectura/escritura. El tiempo de búsqueda para mover la cabeza
al siguiente cilindro también causa un problema parecido. Todos estos problemas afectan en
forma desfavorable el rendimiento de un disco.
Las técnicas del entrelazado de sectores, sesgo de la cabeza y sesgo del cilindro abordan
los problemas causados por los tiempos de transferencia de datos, de cambio de cabezas y de
búsqueda, respectivamente. Estas técnicas aseguran que la cabeza de lectura/escritura será capaz
de ejecutar la siguiente operación antes de que el siguiente sector de numeración consecutiva
pase por debajo de ella. De este modo, una operación de lectura/escritura en el siguiente sector
puede realizarse en el giro que en ese momento da el disco. La técnica del entrelazado de sec-
tores separa los sectores de numeración consecutiva en una pista, poniendo otros sectores entre
ellos. La expectativa es que la transferencia de datos involucrada en la lectura de un sector pueda
completarse antes de que el siguiente sector de numeración consecutiva pase por debajo de la
cabeza. El sesgo de la cabeza escalona el arranque de pistas en diferentes platos de un cilindro,
de tal modo que los tiempos en los que el último sector de una pista y el primer sector de la si-
guiente pasan por debajo de las cabezas respectivas son separados por los tiempos de cambio de

14 MAQ. CAP. 12(F0694).indd 531 8/10/07 1:15:28 AM


532 CAPÍTULO 12 Implementación de operaciones de archivos

cabezas. En forma análoga, el sesgo del cilindro escalona el arranque de una pista en cilindros
consecutivos con la finalidad de tomar en cuenta el tiempo de búsqueda.
El intrelazado de sectores tenía un impacto dramático sobre el rendimiento en discos vie-
jos. En discos modernos, no se necesita porque éstos tienen controladores que transfieren datos
hacia y desde la memoria a velocidades altas; los discos modernos sólo usan el sesgo de cabeza
y cilindro. A pesar de esto, analizaremos el entrelazado de sectores porque nos da una idea de la
optimización del rendimiento pico del disco por medio del escalonado de datos.

8 1 6 1
7 2 3 4

6 3 8 7
5 4 5 2

a) b)

Figura 12.7 Entrelazado de sectores: a) sin entrelazado; b) factor de entrelazado  2.

La figura 12.7 ilustra la técnica del entrelazado de sectores. El factor de entrelazado (inf)
es el número de sectores que separan sectores de numeración consecutiva en la misma pista del
disco. La parte b) de la figura 12.7 ilustra el arreglo cuando inf  2, es decir, cuando sectores
de numeración consecutiva tienen otros dos sectores entre ellos. Este entrelazado es exacto,
es decir, cada par de sectores de numeración consecutiva es separado por otros dos sectores,
porque n  1, donde n es el número de sectores en una pista, es un múltiplo de inf  1. Observe
que el entrelazado con inf  1 o 3 no será exacto, puesto que inf  1 es un factor de n. En estos
casos, algunos sectores consecutivos tendrán que ser separados por más de inf sectores, lo que
lleva a una limitación de desempeño.
El desempeño del disco depende de manera obvia del factor de entrelazado. Supongamos
que tdt sea el tiempo necesario para transferir los datos de un sector entre el controlador de DMA
y la memoria, y que tsect sea el tiempo necesario para que un sector pase por debajo de la cabeza
del disco. Se obtiene el rendimiento óptimo si tdt  inf  tsect, ya que E/S en el siguiente sector
puede iniciarse inmediatamente después de que DMA termine la transferencia de los datos del
sector anterior. tdt  inf  tsect implica que el siguiente sector había pasado por debajo de la
cabeza antes de que el DMA finalizó la transferencia de datos para el sector anterior, por lo que
al siguiente sector sólo puede accederse en el siguiente giro del disco. tdt  inf  tsect implica
que el disco está inactivo durante un tiempo antes de acceder al siguiente sector en el mismo
giro. En ambos casos, se afecta el rendimiento del disco. El ejemplo 12.2 ilustra la variación del
rendimiento pico del disco mediante el factor de entrelazado de sectores.

Ejemplo 12.2 Un disco completa un giro en 8 milisegundos y tiene 8 sectores en una pista, cada
uno con 1 K bytes de datos. Los valores de td y tsect cumplen con la relación tsect  tdt  2  tsect.
Para obtener el desempeño pico del disco para un valor de inf, leemos los sectores en el orden
1 . . . 8 una y otra vez, y observamos el número de bytes que se transfieren en un segundo. La figu-
ra 12.8 muestra la variación del desempeño pico del disco para diferentes valores de inf.

14 MAQ. CAP. 12(F0694).indd 532 8/10/07 1:15:29 AM


12.3 Dispositivos de E/S 533

Arreglo de tio para sectores Promedio de Rendimiento pico


inf sectores (mseg) tio (mseg) (K bytes/seg)
0 1,2,3,4,5,6,7,8 9,9,9,9,9,9,9,9 9 111.1
1 1,5,2,6,3,7,4,8 9,3,10,10,10,10,10,10 9 111.1
2 1,4,7,2,5,8,3,6 3,3,3,3,3,3,3,3 3 333.3
3 1,3,5,7,2,4,6,8 9,5,5,5,4,4,4,4 5 200.0
4 1,6,3,8,5,2,7,4 5,5,5,5,5,5,5,5 5 200.0

350

↑ 250
Rendimiento
pico del 150
disco
50
0 1 2 3 4
Factor de entrelazado →

Figura 12.8 Variación del rendimiento con el factor de entrelazado de sectores.

El entrelazado con inf  1 o 3 no es exacto. Para inf  1, el arreglo de sectores en las pistas
es 1,5,2,6,3,7,4,8. Después de leer el sector 1, el sector 2 no puede leerse en el mismo giro del
disco, así que tarda 10 mseg para leer el sector 2. Del mismo modo, los sectores 3 y 4 requieren 10
mseg. Los sectores 4 y 5 están separados por 2 sectores. Por lo tanto, ellos pueden ser leídos en el
mismo giro del disco; sólo tarda 3 mseg para leer el sector 5 luego de haber leído el sector 4. La
lectura de los sectores 6, 7 y 8 requiere 10 mseg para cada uno, mientras que la lectura del sector 1
tarda 9 mseg. inf  2 es adecuado para satisfacer a tdt  inf  tsect; por tanto, el rendimiento au-
menta pronunciadamente. Los valores de inf  2 son contraproducentes porque el dispositivo pasa
algún tiempo en inactividad antes de que el siguiente sector pase por debajo de la cabeza. Por con-
siguiente, el rendimiento baja para inf  2.

12.3.3 RAID

Los usuarios de computadoras constantemente claman por discos que ofrezcan mayor capacidad,
un acceso más rápido a datos, un índice de transferencia de datos más alto y mayor confiabi-
lidad. Todos estos problemas se abordan por medio de arreglos que involucran discos múltiples.
La tecnología del array redundante de discos económicos (RAID) fue empleada originalmente
para ofrecer grandes capacidades de disco a bajo costo mediante el uso de varios discos econó-
micos; sin embargo, hoy en día se usa para ofrecer un acceso más rápido, índices de transferencia
de datos más altos y alta confiabilidad. Por tanto, la tecnología RAID se llama en la actualidad
más apropiadamente array redundante de discos independientes.
La tecnología RAID extiende los datos involucrados en una operación de E/S a través
de varios discos y en forma paralela ejecuta operaciones de E/S en éstos. Tal característica
puede proporcionar el acceso más rápido o una mayor velocidad de transferencia de datos,

14 MAQ. CAP. 12(F0694).indd 533 8/10/07 1:15:29 AM


534 CAPÍTULO 12 Implementación de operaciones de archivos

dependiendo del arreglo que se use. La alta confiabilidad se logra mediante la grabación de
informaciones redundantes; sin embargo, la redundancia empleada en un RAID se distingue
en forma cualitativa de la que se emplea en discos convencionales. Un disco convencional sólo
ofrece confiabilidad escribiendo una suma de verificación de redundancia cíclica (CRC) al final
de cada registro (véase la sección 12.3), mientras que las técnicas de redundancia en un RAID
emplean discos adicionales para almacenar informaciones redundantes, por lo que pueden recu-
perarse datos aun cuando fallen algunos discos. El acceso a informaciones redundantes no cuesta
tiempo de E/S adicional porque puede accederse en forma paralela tanto a los datos como a las
informaciones redundantes.

Rayado de disco La técnica del rayado de disco crea una oportunidad para lograr altas
velocidades de transferencia de datos durante el procesamiento de un archivo. Funciona del
siguiente modo: una tira del disco es una unidad de datos en un disco que puede ser un sector,
un bloque del disco o una pista del disco. Tiras de disco idénticamente posicionadas sobre dis-
cos diferentes forman una raya de disco. A un archivo se le asigna un número integral de rayas
de disco. Los datos que residen en las tiras de disco de la misma raya pueden leerse o escribirse
simultáneamente porque existen en diferentes discos. Si el array de discos contiene n discos,
entonces la velocidad de transferencia de datos podrá ser, en teoría, n veces la de un solo dis-
co. Los valores prácticos de las velocidades de transferencia de datos dependen de la sobrecarga
y de todos los factores que podrán limitar el paralelismo de operaciones de E/S mientras se pro-
cesa un archivo.
Se han propuesto varias organizaciones de RAID que usan diferentes técnicas de redundan-
cia y arreglos de rayado de discos. Éstas se llaman niveles de RAID. La tabla 12.3 resume las
propiedades de varios niveles de RAID. Los niveles de RAID 0  1 y 1  0, que son organiza-
ciones híbridas basadas sobre los niveles 0 y 1, y el nivel 5 de RAID son las organizaciones de
RAID más usadas.

RAID nivel 0 El nivel 0 emplea solamente el rayado de disco; no es realmente una organi-
zación de RAID porque no involucra la grabación redundante de datos. Proporciona velocidades
de transferencia altas, particularmente si cada disco está bajo un controlador de disco separado.
Sin embargo, este nivel presenta baja confiabilidad. Los datos se vuelven inaccesibles aun si un
solo disco es inoperativo. La falta de redundancia también implica que se pierden datos si
un disco falla, y aún así se tiene que lograr la confiabilidad por medios distintos de la organiza-
ción de RAID.

RAID nivel 1 Una organización de nivel 1 de RAID escribe informaciones idénticas en


dos discos; esto se llama efecto de espejo del disco. Cuando un proceso escribe o actualiza un
registro en un archivo, una copia del registro es escrita en cada disco. De este modo, RAID 1
incurre en 100 por ciento de sobrecarga; sin embargo, se garantiza que una copia de un registro
esté accesible incluso si ocurre una sola falla. Durante una lectura, el RAID simplemente lee
la copia de más rápido acceso. Pueden alcanzarse altas velocidades de transferencia de datos
durante operaciones de lectura porque ambos discos pueden operar en forma paralela cuando no
se presentan errores.
Frecuentemente se usan en la práctica organizaciones híbridas que emplean las característi-
cas de los niveles 0 y 1 de RAID con la finalidad de obtener ambas cosas, tanto velocidades altas
de transferencia de datos —como en el nivel 0 de RAID— como también una alta confiabilidad
—como en el nivel 1 de RAID—. RAID 0  1 emplea el rayado de disco como en RAID 1 y

14 MAQ. CAP. 12(F0694).indd 534 8/10/07 1:15:30 AM


12.3 Dispositivos de E/S 535

Tabla 12.3 Niveles de RAID

Nivel Técnica Descripción


Nivel 0 Rayado del disco Los datos están entrelazados en varios discos. Du-
rante una operación de E/S, se accede a los discos
en forma paralela. Potencialmente, esta organización
D D puede proporcionar un incremento de n veces en las
velocidades de transferencia de datos cuando se usan
n discos.
Nivel 1 Efecto espejo del disco Se graban datos idénticos en dos discos. Durante la
lectura de datos, se usa la copia de acceso más rá-
pido. Una de las copias es accesible aun después
Disco Disco de que ocurre una falla. En forma paralela pueden
1 2 ejecutarse operaciones de lectura si no se presentan
errores.
Nivel 2 Códigos de corrección Se graban informaciones de redundancia para detec-
tar y corregir errores. Cada bit de datos o información
• • • •
de redundancia se almacena sobre un disco distinto
D D P P y se lee o escribe en forma paralela. Se proporciona
una alta velocidad de transferencia de datos.
Nivel 3 Paridad de entrelazado Análogo al nivel 2, excepto que usa un disco de pa-
de bits ridad único para la corrección de errores. Un error
que ocurre durante la lectura de datos de un disco es
• • •
detectado por su controlador de dispositivo. Se usa
D D P el bit de paridad para recuperar datos perdidos.
Nivel 4 Paridad de entrelazado Escribe un bloque de datos, es decir, bytes conse-
de bloques cutivos de datos, en una tira y calcula una sola tira
de paridad para las tiras de una raya. Proporciona
velocidades altas de transferencia de datos para ope-
D D P raciones de lectura grandes. Operaciones de lectura
pequeñas tienen bajas velocidades de transferencia
de datos; sin embargo, muchas de estas operaciones
pueden realizarse en paralelo.
Nivel 5 Paridad distribuida de Análogo al nivel 4, excepto porque las informacio-
entrelazado de bloques nes de paridad quedan distribuidas a través de to-
das las unidades de discos. Impide que el disco de
paridad se convierta en un cuello de botella de E/S
como en el nivel 4. También proporciona un mejor
desempeño de lectura que el nivel 4.
Nivel 6 Redundancia P + Q Análogo al nivel 5 de RAID, excepto porque usa dos
esquemas de paridad distribuida independientes. So-
porta la recuperación de la falla de dos discos.
D D P P

(Nota: D y P indica discos que contienen solamente datos e informaciones de paridad, respectivamente.
La marca • indica bits de un byte que están almacenados en discos diferentes, así como sus bits de pari-
dad. indica una tira que contiene informaciones de paridad.)

14 MAQ. CAP. 12(F0694).indd 535 8/10/07 1:15:30 AM


536 CAPÍTULO 12 Implementación de operaciones de archivos

refleja como espejo a cada raya, como en RAID 1. RAID 1  0 primero refleja cada disco y lue-
go ejecuta el rayado. Estas organizaciones proporcionan diferentes tipos de tolerancia de fallas:
En RAID 0  1, un solo error en una copia de una raya causa que toda la copia sea inaccesible,
por lo que errores en ambas copias de una raya causarían que la raya sea inaccesible. En RAID
1  0, un error en un solo disco sería tolerado accediendo a su disco espejo. Una raya solamente
se volvería inaccesible si tanto un disco como su disco espejo tienen errores.

RAID nivel 2 Esta organización de RAID usa el rayado de bits, es decir, almacena cada
bit de datos o información redundante en un disco diferente. Cuando tienen que escribirse datos,
la i-ésima tira de datos contiene el i-ésimo bit de cada byte, y una tira de paridad contiene uno
de los bits de paridad calculado a partir de bits correspondientes en todas las tiras de la raya. Un
código de corrección de errores se usa para calcular y almacenar informaciones de redundancia
para cada byte (véase la sección 12.3). Por tanto, se usan ocho discos para grabar los bits de un
byte, y unos cuantos discos más para grabar las informaciones de redundancia. Por ejemplo,
el (12, 8) código Hamming, que es adecuado para la recuperación de una sola falla, requeriría
cuatro bits de redundancia. Si el arreglo de RAID 2 emplease este código, consistiría de 8 discos
de datos y 4 discos con informaciones de redundancia, cada uno almacenando un bit de datos o
informaciones de redundancia. Este arreglo de RAID puede leer/escribir datos ocho veces más
rápidamente que un disco único. Sin embargo, esto resulta caro porque se necesitan varios discos
para almacenar informaciones de redundancia.

RAID nivel 3 El nivel 3 emplea el rayado de disco con un esquema de paridad de entre-
lazado de bits —escribe los bits de un byte en diferentes discos— y usa un solo bit de paridad
por byte. Las tiras de datos de una raya se almacenan en 8 discos de datos y la tira de paridad lo
hace en el disco de paridad. De este modo, el nivel 3 de RAID emplea una cantidad considera-
blemente menor de informaciones redundantes que el nivel 2 de RAID. Una operación de lectura
se lleva a cabo de la siguiente manera: el controlador del disco verifica si existe un error dentro
de una tira. De ser así, ignora toda la tira y recupera los datos usando la tira de paridad; el va-
lor de un bit de datos es la diferencia de módulo 2 entre el bit de paridad y la suma de módulo 2
de los bits correspondientes de otras tiras en la raya.
Todos los discos de datos participan en una operación de E/S. Esta característica propor-
ciona altas velocidades de transferencia de datos. Sin embargo, también implica que sólo una
operación de E/S puede estar en ejecución en un momento dado. Otro inconveniente del nivel 3
de RAID es que el cálculo de paridad puede ser una merma significativa de la potencia del CPU.
Por tanto, se descarga al propio RAID.

RAID nivel 4 El nivel 4 es análogo al nivel 3, excepto porque emplea la paridad de


entrelazado de bloques. Cada tira acomoda un bloque de datos, es decir, unos cuantos bytes de
datos consecutivos. Si una operación de E/S involucra una gran cantidad de datos, implicará a
todos los discos de datos como en el nivel 3 de RAID, por lo que el nivel 4 de RAID puede ofre-
cer altas velocidades de transferencia de datos para operaciones grandes de E/S. Una operación
de lectura cuyos datos caben en un bloque únicamente involucrará a un solo disco de datos, por
lo que operaciones de E/S pequeñas tienen pequeños índices de transferencia de datos; sin em-
bargo, varias de estas operaciones de E/S pueden realizarse en forma paralela.
Una operación de escritura involucra el cálculo de informaciones de paridad basado sobre
datos grabados en todas las tiras de una raya. Esto puede lograrse si se leen primero los datos

14 MAQ. CAP. 12(F0694).indd 536 8/10/07 1:15:31 AM


12.4 E/S de nivel de dispositivo 537

contenidos en todas las tiras de una raya, se reemplazan los datos en algunas de las tiras con
datos nuevos que deben escribirse, se calculan las nuevas informaciones de paridad y se escriben
los nuevos datos e informaciones de paridad en todos los discos. Sin embargo, este procedimien-
to limita el paralelismo porque todos los discos están involucrados en la operación de escritura,
aun cuando hay nuevos datos que deben escribirse en un solo bloque blocki de la raya stripei. Por
ende, se calcula la información de prioridad por medio de un método más sencillo que involucra
la OR exclusiva de tres ítems: la información vieja en el bloque de paridad, los datos viejos en
un bloque blocki y los nuevos datos que van a ser escritos en el bloque blocki. De este modo, sólo
el(los) disco(s) que contiene(n) el(los) bloque(s) que va(n) a ser escrito(s) y el bloque de paridad
están involucrados en la operación de escritura; de este modo, varias operaciones de lectura
pequeñas que involucran otros discos pueden ejecutarse en forma paralela con la operación de
escritura.

RAID nivel 5 El nivel 5 usa la paridad del nivel de bloques, igual que el nivel 4, pero
distribuye las informaciones de paridad a través de todos los discos en el RAID. Esta técnica
permite que operaciones de escritura pequeñas que involucran un solo bloque de datos puedan
realizarse en forma paralela si sus informaciones de paridad están ubicadas en diferentes discos.
Pueden ejecutarse pequeñas operaciones de lectura libres de fallas en forma paralela, tal como
en el nivel 4 de RAID. Esta organización es particularmente adecuada para operaciones de E/S
pequeñas que se realizan a alta velocidad. Operaciones mayores no pueden ejecutarse en forma
paralela; sin embargo, la organización ofrece altas velocidades de transferencia de datos para
estas operaciones. También proporciona un mayor desempeño pico del disco que el nivel 4
para operaciones de lectura porque puede participar un disco más en operaciones de lectura.

RAID nivel 6 Esta organización usa dos esquemas de paridad distribuida independientes.
Éstos admiten la recuperación de la falla de dos discos. El desempeño pico del disco es levemen-
te más alto que en el nivel 5 debido a la existencia de un disco más.

12.4 E/S DE NIVEL DE DISPOSITIVO

Supongamos que se realizan operaciones de E/S en el modo DMA. Como se mencionó en la


sección 12.2, el DMA es un procesador de propósitos especiales. Éste realiza un acceso directo a
memoria a través del bus para implementar una transferencia de datos entre la memoria y un dis-
positivo de E/S. El DMA implementa una operación de E/S completa, es decir, una secuencia de
comandos de E/S, y levanta una interrupción de E/S al final de la operación de E/S. Supongamos
que un sistema de cómputo contiene las características relacionadas con E/S que se describen en
la tabla 12.4.

Ejemplo 12.3 La operación de E/S del ejemplo 12.1, por ejemplo, lectura del registro (track_id,
record_id) en el dispositivo (controller_id, device_id), se implementa emitiendo la instrucción

I/O-init (controller_id, device_id), addr

donde addr es la dirección inicial del área de memoria que contiene los dos comandos de E/S

Posiciona las cabezas de disco sobre la pista track_id


Lee el registro record_id

14 MAQ. CAP. 12(F0694).indd 537 8/10/07 1:15:31 AM


538 CAPÍTULO 12 Implementación de operaciones de archivos

Tabla 12.4 Características de un sistema de cómputo admitiendo funciones en E/S de nivel dispositivo

Descripción de una característica de sistema


Función de cómputo que la admite
Iniciación de una Instrucción I/O-init (cu, d), command_address inicia una operación E/S. (cu, d)
operación de E/S es la dirección del dispositivo y command_address es la dirección de la ubica-
ción en memoria donde el primer comando de la operación de E/S está alma-
cenado. Supongamos que los comandos de E/S que describen una operación de
E/S se encuentran en ubicaciones de memoria consecutivas. (Algunos sistemas
buscan la dirección del comando de E/S en una ubicación estándar de memoria
cuando se ejecuta la instrucción I/O-init). La instrucción I/O-init coloca un
código de condición para indicar si la operación de E/S ha iniciado.
Verificación del La instrucción I/O-status (cu, d) obtiene informaciones de estatus para el dis-
estatus del positivo de E/S con la dirección (cu, d). Las informaciones indican si el dispo-
dispositivo sitivo está ocupado, libre o en un estado de error, así como la causa del error,
en su caso.
Ejecución de Los comandos de E/S para operaciones de E/S específicas del dispositivo im-
operaciones de E/S plementan operaciones, como el posicionamiento de cabezas sobre una pista y
la lectura de un registro.
Manejo de El hardware de interrupción implementa la acción de interrupción que se des-
interrupciones cribe en la sección 2.1.1.

12.4.1 Programación de E/S

Usamos el término programación de E/S para describir todas las acciones con respecto a la
iniciación y finalización de una operación de E/S. La iniciación de E/S se realiza por medio
de una instrucción I/O-init. Las acciones de finalización de E/S se ejecutan cuando ocurre una
interrupción de E/S, indicando la finalización de una operación de E/S. Para ver los detalles de
la programación de E/S, consideraremos un programa de aplicación que usa el hardware de la
máquina, es decir, un sistema de cómputo que no tiene capas de software entre el programa de
aplicación y el hardware de la máquina. Este programa tiene que ejecutar por su propia cuenta
todas las acciones relacionadas con la iniciación y finalización de una operación E/S.

Iniciación de E/S Cuando se ejecuta una instrucción I/O-init, el CPU envía la dirección
del dispositivo al DMA. El DMA interroga al dispositivo para verificar su disponibilidad. Este
proceso se llama selección de dispositivo. El DMA informa al CPU sobre las acciones de selec-
ción de dispositivo, y éste coloca un correspondiente código de condición en su registro de códi-
gos de condición. Entonces la instrucción I/O-init está completa; el CPU queda libre para
ejecutar otras instrucciones.
Si la selección de dispositivos es exitosa, el DMA inmediatamente inicia la operación E/S
mediante el acceso y la decodificación del primer comando de E/S. Si la selección de dispositivo
falla, el código de condición establecido por la instrucción I/O-init describe la causa de la falla,
por ejemplo, si el dispositivo está ocupado con alguna otra operación, o si ocurrió una falla de
hardware. Si el dispositivo estuvo ocupado, el programa puede reintentar la iniciación de E/S
en algún momento futuro. Si se presentó una falla de hardware, el programa puede reportar la
condición al administrador del sistema.

14 MAQ. CAP. 12(F0694).indd 538 8/10/07 1:15:31 AM


12.4 E/S de nivel de dispositivo 539

Procesamiento de finalización de E/S Puesto que el programa se lleva a cabo en el hard-


ware de una máquina, y no en un sistema de multiprogramación o compartición de tiempo (véase
el capítulo 2), no puede bloquearse sino hasta que la operación de E/S finaliza. Por tanto, el
CPU permanece disponible para el programa incluso durante la operación de E/S, y continúa
con la ejecución de instrucciones. Sin embargo, ¡no realiza ningún trabajo hasta que finaliza la
operación de E/S!
El programa aborda este problema por medio de una bandera para indicar si la operación
de E/S ha finalizado. Para empezar, su valor se pone en “ejecutando”. La rutina de procesamien-
to de interrupciones cambia el valor de la bandera a “completo”. Luego de iniciar la operación
de E/S, el CPU entra en un bucle donde repetidamente verifica su bandera. (Esto es una espera
activa; véase la sección 9.2.2.) Cuando la rutina de procesamiento de interrupción cambia la
bandera a “completo”, el CPU sale del bucle y reanuda la ejecución del programa.
El ejemplo 12.4 describe detalles de la programación de E/S.

Ejemplo 12.4 La figura 12.9 ilustra las acciones básicas involucradas en la programación de E/S.
IO_FLAG se fija en “1” para indicar que la operación de E/S está en ejecución, y se ejecuta la ins-
trucción I/O-init. Las instrucciones de rama condicional (BC) verifican el código de condición fija-
do por la instrucción I/O-init. Se coloca el código de condición cc1 si la iniciación de E/S es
exitosa. En este evento la operación de E/S todavía no se ha iniciado, entonces el programa procede
a ejecutar la instrucción con la etiqueta PROCEED. Las dos instrucciones COMP (es decir, compara)
y BC en PROCEED implementan una espera activa; el CPU compara el valor de IO_FLAG con 1 y
continúa en el bucle, si éste es el caso. El código de condición cc2 indica que el dispositivo está
ocupado; entonces el programa reintenta la instrucción de E/S hasta que la iniciación de E/S tenga
éxito. El código de condición cc3 indica una situación de error de E/S. Este error se reporta al ad-
ministrador de sistema. Tales detalles no se muestran en el esquema.

SET IO FLAG, ‘1’ E/S en ejecución


REINICIAR: IO init (cu, d ), COMANDOS
BC cc1 , PROCEDE ¿Iniciación exitosa?
BC cc2 , REINICIAR ¿Está ocupado el dispositivo?
BC cc3 , ERROR Error, informa al operador

PROCEDE: COMP IO FLAG, ‘1’ ¿E/S sigue en ejecución?


BC EQ, PROCEDE
···

COMANDOS: ··· {Comandos de E/S}


···

IO INTRPT: SET IO FLAG, ‘0’ Interrupción procesamiento


···

Figura 12.9 Nivel de dispositivo E/S.

El procesamiento de finalización de E/S involucra las siguientes acciones: cuando ocurre una
interrupción de E/S, el control es transferido a la instrucción con la etiqueta IO_INTRPT (véase
la sección 2.1.1). Esto es el inicio de la rutina de procesamiento de interrupción de E/S. La rutina
de procesamiento de interrupción de E/S cambia IO_FLAG a “0” y regresa. Esta acción saca el
programa de la espera activa en PROCEED.

14 MAQ. CAP. 12(F0694).indd 539 8/10/07 1:15:32 AM


540 CAPÍTULO 12 Implementación de operaciones de archivos

12.4.2 El IOCS físico (PIOCS)

El funcionamiento de un componente del SO tiene tres aspectos importantes: ofrecer una con-
veniencia de algún tipo, asegurar el uso eficiente de recursos bajo su control y ayudar a asegurar
la eficiencia general del sistema operativo. Todos estos aspectos están presentes en el caso del
IOCS físico. El primer aspecto implica ofrecer una interfaz conveniente para realizar el nivel de
dispositivo E/S. Los otros dos aspectos de su funcionamiento son un poco menos obvios. La ta-
bla 12.5 contiene una visión general de estos tres aspectos. La capa del IOCS físico proporciona
las siguientes funcionalidades para implementarlos:

1. Iniciación, finalización y recuperación de errores de E/S.


2. Espera de la finalización de una operación de E/S.
3. Optimización del desempeño del dispositivo de E/S.

Tabla 12.5 Aspectos de las funciones del IOCS físico

Aspecto Descripción
Interfaz para E/S de El IOCS físico ofrece medios sencillos y de fácil uso para realizar operacio-
nivel dispositivo nes de E/S y manejar interrupciones de E/S. De este modo, un programa no
requiere conocimientos intrincados del procesamiento de iniciación e inte-
rrupción de E/S a fin de realizar E/S.
Buen rendimiento La ejecución de E/S en el nivel del hardware de la máquina involucra una
del sistema espera activa siguiendo a una iniciación de E/S, que dura hasta que ocurre
una interrupción de E/S (véase el ejemplo 12.4). Esto desperdicia tiempo
valioso del CPU. El IOCS físico evita esperas activas mediante la comuni-
cación con el componente de manejo de procesos para poner un programa
en el estado bloqueado mientras espera la finalización de una operación
de E/S.
Buen rendimiento El buen rendimiento del dispositivo se obtiene por medio de la planificación
del dispositivo de operaciones de E/S dirigida a un dispositivo en el orden adecuado. Esta
actividad se llama planificación de dispositivo de E/S, o simplemente plani-
ficación de E/S.

Iniciación, finalización y recuperación de errores de E/S El soporte del IOCS físico para
la programación del DMA hace que las complejidades del DMA y del dispositivo sean transpa-
rentes para un proceso. El proceso sólo necesita especificar la dirección del dispositivo y detalles
de la operación de E/S. La operación de E/S se lleva a cabo de manera asíncrona con respecto a
la operación del proceso. Si el proceso no contiene cálculos que pueden ser realizados en forma
concurrente con la operación de E/S, puede esperar la finalización de la operación de E/S usando
la sincronización que proporciona PIOCS. Cuando se presenta una interrupción que pertenece
al dispositivo, el IOCS físico la analiza para determinar el estatus de la operación de E/S. Si la
operación de E/S ha finalizado exitosamente, toma nota de ese hecho y lo usa para implementar
la sincronización de un proceso con la finalización de una operación de E/S. Si la interrupción
indica que un error ha ocurrido durante la operación de E/S, llama a un procedimiento de recu-

14 MAQ. CAP. 12(F0694).indd 540 8/10/07 1:15:32 AM


12.4 E/S de nivel de dispositivo 541

peración de errores. De este modo, la recuperación de un error de E/S es transparente para el


proceso; sólo se le reporta un error si la recuperación no es posible.

En espera de la finalización de una operación de E/S El IOCS físico devuelve el control


a un proceso después de notar su solicitud de E/S, así que el proceso puede operar en forma
concurrente con la operación de E/S. Sin embargo, ésta debe estar completa antes de que el
proceso pueda usar los valores leídos por él. Esto queda asegurado sincronizando el proceso
con la finalización de la operación de E/S. Por ejemplo, considere un programa de lenguaje de
alto nivel

read a, b, c;
...
resultado : a  5.2;

Durante su ejecución, la operación read debe finalizar antes de acceder el valor de a en el enun-
ciado de asignación. A fin de lograr esta sincronización, el proceso invoca la funcionalidad de
“esperar finalización de E/S” del IOCS físico con parámetros que identifican la operación de E/S.
Normalmente estos parámetros especifican la dirección del dispositivo y detalles de la operación
de E/S. Si el IOCS físico se da cuenta de que la operación de E/S no está completa, solicita al
kernel que bloquee el proceso. Este arreglo evita la espera activa del ejemplo 12.4. El estado del
proceso se cambia a disponible cuando finaliza la operación de E/S. De este modo, el uso de esta
funcionalidad asegura que el enunciado resultado : a  5.2 es ejecutado sólo después
de que finalice la operación read.

Optimización del desempeño del dispositivo de E/S El rendimiento de un dispositivo


de E/S puede definirse como el número de bytes de datos que se le transfieren por unidad de
tiempo. El rendimiento puede optimizarse minimizando los tiempos de acceso sufridos durante
operaciones de E/S. En dispositivos de disco, esto puede lograrse mediante la reducción de la
latencia rotacional y del movimiento mecánico de las cabezas de discos, ejecutando operaciones
de E/S en el orden adecuado.
El IOCS físico registra todas las solicitudes de iniciación de E/S en sus estructuras de datos,
por lo que tiene conocimiento de todas las operaciones de E/S pendientes en un dispositivo de
E/S. Usa estos conocimientos para optimizar el rendimiento del dispositivo mediante la plani-
ficación inteligente de las operaciones de E/S. Esta función, que se llama planificación de E/S,
es realizada en forma automática por parte del IOCS físico; no es explícitamente invocada por
un proceso.
La figura 12.10 ilustra cómo un proceso podrá usar la capa del IOCS físico para ejecutar
sus E/S. Un proceso podrá hacer dos tipos de solicitudes: para ejecutar operaciones de lectura
o escritura, y para bloquearse a sí mismo hasta que finalice una operación de E/S. Estas solici-
tudes son marcadas por los números rodeados con un círculo en la figura 12.10. Solicitudes y
respuestas fluyen a través de dos interfaces: la interfaz entre el proceso y el IOCS físico, y la
interfaz entre el IOCS físico y el kernel. Las solicitudes al PIOCS normalmente se implementan
en cuatro pasos.

1. El proceso hace una solicitud invocando una funcionalidad proporcionada por la interfaz
del IOCS físico. El control se transfiere a una rutina relevante de PIOCS.

14 MAQ. CAP. 12(F0694).indd 541 8/10/07 1:15:32 AM


542 CAPÍTULO 12 Implementación de operaciones de archivos

Aguardar
Lectura/ finalización Proceso
escritura 1 2 de E/S

Capa del
Unidad Obtén info. Bloquea el IOCS físico
de E/S de estatus proceso

Kernel
Figura 12.10 Acciones de la capa del IOCS físico.

2. La rutina del PIOCS pasa la solicitud al kernel.


3. El kernel envía una respuesta a la rutina del IOCS físico.
4. La rutina del IOCS físico envía una respuesta al proceso.

La tabla 12.6 muestra algunas solicitudes y respuestas típicas a través de la capa del IOCS
físico. Observe que una respuesta puede ser en forma de alguna información devuelta al invoca-
dor o una acción realizada en nombre de un invocador.

Tabla 12.6 Solicitudes y respuestas a través de las interfaces del IOCS físico

Solicitud de A Detalles Respuesta


Programa de PIOCS Leer/escribir Regresar al programa después de registrar la solicitud de
aplicación E/S en la estructura de datos de PIOCS. (De ser posible,
E/S es iniciado inmediatamente)
PIOCS Kernel I/O init Iniciar E/S en el dispositivo
PIOCS Kernel Obtén estatus Proporcionar información sobre el estatus de operación
Programa de PIOCS Aguarda Bloquear el programa hasta que finaliza E/S
aplicación finalización
de E/S
PIOCS Kernel Bloquea el El programa se pone en el estado bloqueado
programa

12.4.3 Dispositivos lógicos

Una operación de E/S se inicia mediante la instrucción I/O-init (cui, dj), dirección del comando,
donde (cui, dj) es la dirección del dispositivo de E/S. Un programa que contiene estas instruc-
ciones depende de la disponibilidad del dispositivo de E/S específico con la dirección (cui, dj).
El programa tendrá que modificarse si otro dispositivo de E/S en lugar de (cui, dj) se usara, y se
deberá compilar de nuevo cada vez que se modifica. Se introduce el concepto de un dispositivo
lógico para evitar estas modificaciones y recopilaciones.
Un dispositivo lógico es un dispositivo de E/S abstracto con un nombre simbólico. Algunos
sistemas operativos proporcionan un conjunto de nombres estándares para dispositivos lógi-
cos, mientras que otros permiten que un proceso elija sus propios nombres para dispositivos

14 MAQ. CAP. 12(F0694).indd 542 8/10/07 1:15:32 AM


12.4 E/S de nivel de dispositivo 543

lógicos. El IOCS físico proporciona una funcionalidad para ejecutar la asignación de un dispo-
sitivo físico para un dispositivo lógico. Esta funcionalidad podrá ser invocada por medio del
procesador de comandos del SO antes de iniciar la ejecución de un programa. En forma alterna-
tiva, un proceso podrá invocarla en forma dinámica emitiendo una llamada al sistema durante
su ejecución.
Un proceso podrá asignar un dispositivo físico (cui, dj) de una clase de dispositivos corres-
pondiente a un dispositivo lógico mydisk. Entonces podrá hacer una solicitud I/O-init mydisk,
command address. El IOCS físico implementará este comando en el dispositivo (cui, dj). Los
dispositivos físicos también se usan para implementar la noción de dispositivos virtuales que se
describen en la sección 1.3.2.1. Para crear muchos dispositivos virtuales en un disco, el disco
puede ser asignado a muchos dispositivos lógicos.

12.4.4 Estructuras de datos del IOCS físico

El IOCS físico usa las siguientes estructuras de datos:

• Tabla de dispositivos físicos (PDT).


• Tabla de dispositivos lógicos (LDT).
• Bloque de control de E/S (IOCB).
• Cola de E/S (IOQ).

La figura 12.11 ilustra la relación entre estas estructuras de datos. La tabla de dispositivos físicos
(PDT) es una estructura de datos que abarca todo el sistema y que contiene informaciones acerca
de todos los dispositivos físicos del sistema. Los campos importantes de esta tabla son direc-
ción del dispositivo, tipo de dispositivo y puntero IOQ. El campo del puntero IOQ de un registro
de PDT contiene un puntero a la cola de solicitudes de E/S para el dispositivo. Las informaciones
en la cola se usan para la planificación de E/S.
La tabla de dispositivos lógicos (LDT) es una estructura de datos por proceso que describe
asignaciones a los dispositivos lógicos usados por el proceso. Una copia de la LDT existe para
cada proceso del sistema. Esta copia es accesible desde el PCB del proceso. La LTD contiene
una entrada para cada dispositivo lógico. Los campos nombre del dispositivo lógico y dirección
del dispositivo lógico en la entrada contienen informaciones relativas a la asignación actual, en
su caso, para el dispositivo lógico. Observe que para ciertas clases de dispositivos (por ejemplo,
discos) el mapeo de los dispositivos lógicos a los dispositivos físicos puede ser “muchos-a-uno”.
De este modo, muchos dispositivos lógicos, posiblemente pertenecientes a diferentes procesos,
pueden compartir el mismo dispositivo físico.
El IOCS físico verifica si existen conflictos de asignación mientras realiza nuevas asigna-
ciones. Por ejemplo, sólo una asignación puede estar en vigor para un dispositivo no comparti-
ble, como una impresora. El campo del tipo de dispositivo de la PDT se usa para determinar si
la compartición es factible para un dispositivo. Una asignación de dispositivo podrá ser nulifica-
da por un proceso mediante una llamada al IOCS físico. Además, el IOCS físico invalida todas
las asignaciones de dispositivos de un proceso al final de su ejecución.
Un bloque de control de E/S (IOCB) contiene todas las informaciones correspondientes a
una operación de E/S. Los campos importantes en un IOCB son nombre del dispositivo lógico,
detalles de E/S y bandera de estatus. El campo de detalles de E/S contiene la dirección inicial del

14 MAQ. CAP. 12(F0694).indd 543 8/10/07 1:15:33 AM


544 CAPÍTULO 12 Implementación de operaciones de archivos

Nombre Dirección Dirección Tipo


del dispo- física del del dispo- de dispo- Puntero
sitivo dispositivo sitivo sitivo de IOQ

lógico .
Disco
físico .

Tabla de dispositivos Tabla de dispositivos


lógicos (LDT) físicos (PDT)
del proceso Pi

Cola de E/S (IOQ)


Espacio del kernel
Espacio del usuario
Nombre del
dispositivo Detalles Bandera
lógico de E/S de estatus

Bloque de control de E/S (IOCB)

Figura 12.11 Estructuras de datos del IOCS físico.

área de memoria que incluye todos los comandos de E/S involucrados en la operación de E/S. La
bandera de estatus indica si una operación de E/S está “en ejecución” o “completa”.
La cola de E/S (IOQ) es una lista de todas las operaciones de E/S pendientes en un dis-
positivo físico. Cada entrada de IOQ contiene un puntero dirigido a un bloque de control de
E/S. Las informaciones en el IOQ se usan para optimizar el desempeño del dispositivo de E/S.
Observe que el PDT de un dispositivo físico, a diferencia de la entrada de LDT de un disposi-
tivo lógico, apunta al IOQ. Esto es significativo cuando un dispositivo físico es asignado a mu-
chos dispositivos lógicos. Las informaciones con respecto a operaciones de E/S dirigidas a todos
los dispositivos lógicos a los que está asignado están entonces disponibles en un solo lugar para
la planificación de E/S.
Se accede a las tablas de dispositivos físicos y lógicos por medio de números de dispositivos
a manera de llaves. El PDT es una tabla fija; puede formarse a la hora de carga inicial del sistema,
obteniendo detalles de todos los dispositivos conectados al sistema. Por lo general, la LDT es
una tabla de tamaño fijo especificado en el momento de generación del sistema o al tiempo de
carga inicial. Estas tablas están organizadas como tablas lineales. Un bloque de control de E/S
se asigna a petición cuando se inicia una operación de E/S y se destruye cuando la operación

14 MAQ. CAP. 12(F0694).indd 544 8/10/07 1:15:33 AM


12.4 E/S de nivel de dispositivo 545

de E/S finaliza, por lo que lo mejor es asignar los IOCB en un heap (véase la sección 5.3.1).
La IOQ se muestra como un array de punteros en la figura 12.11; sin embargo, es más práctico
organizarla como una lista ligada de varios IOCB.
Las estructuras de datos de las PDT, LDT e IOQ existen dentro del kernel. El proceso crea
un IOCB en su propio espacio de dirección, inicializa sus campos y lo usa como parámetro
en una llamada al IOCS físico. Su presencia en el espacio de dirección del proceso permite que
se verifique el estatus de una operación de E/S sin tener que invocar el kernel, lo que evita la
llamada al sistema implícita en la llamada al IOCS físico “Obtén información del estatus” en
la figura 12.10.

12.4.5 Implementación de funciones del IOCS físico

Las funciones del IOCS físico se invocan de dos maneras. Funciones como “lectura/escritura” y
“aguarda finalización de E/S” son invocadas explícitamente por un proceso mediante llamadas
al sistema, es decir, a través de interrupciones de software causadas por la ejecución de instruc-
ciones de interrupciones de software (SI). Otras funciones se invocan en forma implícita cuando
ocurren interrupciones de E/S. Éstas incluyen lo siguiente:

• Procesamiento de finalización de E/S: invocado por una interrupción que indica la finali-
zación exitosa de una operación de E/S.
• Recuperación de errores de E/S: invocado cuando una interrupción indica un mal funcio-
namiento de E/S.
• Iniciación de E/S: después del procesamiento de finalización de E/S, la iniciación de E/S
es invocada para una operación de E/S pendiente en el mismo dispositivo. Esta función
engloba la optimización del desempeño de los dispositivos de E/S.

Cuando una función del IOCS físico es invocada por medio de una instrucción de SI, el código
de interrupción indica la identidad de la función deseada del IOCS físico. Normalmente, un
IOCB es el parámetro solitario en cada invocación. Su dirección se carga a un registro antes de
causar la interrupción de software. Cuando una función es invocada debido a una interrupción
de E/S, el IOCS físico obtiene la dirección del dispositivo del código de interrupción y la usa
para obtener informaciones sobre la operación de E/S que fue causante de la interrupción. El
ejemplo 12.5 ilustra cómo se inicia una operación de E/S.

Ejemplo 12.5 La figura 12.12 muestra el código de un programa ejecutado por un proceso. Define
un bloque de control llamado OPN y coloca en él la id del dispositivo lógico y la dirección inicial
del área de memoria que contiene los comandos de E/S. Para iniciar la operación de E/S, el proceso
carga la dirección de OPN a un registro, tal como lo requiere el IOCS físico, y causa una interrupción
de software mediante el código de interrupción correcto. Al obtener el control, el IOCS físico
recupera la dirección del IOCB del registro. El código de interrupción indica que debe iniciarse una
operación de E/S. El IOCS físico usa las informaciones en el IOCB, así como la secuencia de
instrucción que se muestra en el ejemplo 12.4, para iniciar la operación de E/S.

Biblioteca del IOCS físico Programas de lenguaje ensamblador invocan funciones del
IOCS físico usando la interfaz del IOCS físico que se muestra en la figura 12.12. Un programa
escrito en un lenguaje de alto nivel contiene una declaración para el archivo alpha y usa enun-

14 MAQ. CAP. 12(F0694).indd 545 8/10/07 1:15:33 AM


546 CAPÍTULO 12 Implementación de operaciones de archivos

< move> < reg > , Ad(OPN)


< SI instrn > < int code>

Dispositivo lógico
OPN : Detalles de E/S
Bandera de estatus

Figura 12.12 Operación de E/S usando facilidades del IOCS.

ciados de open, read y close para procesar alpha. Durante su ejecución, un proceso invoca
las operaciones del sistema de archivos (FS) open, read y close a fin de realizar el procesa-
miento de archivos. En caso de una llamada open, el sistema de archivos construye un FCB para
alpha en la tabla de archivos activos (AFT) y devuelve internal idalpha, que es el desplaza-
miento del FCB en la AFT (véase la sección 7.8). En el caso de una llamada read, el FS invoca
iocs-read con internal idalpha como parámetro. iocs-read contiene una llamada en el mó-
dulo de biblioteca del IOCS físico start-io con una dirección del IOCB como parámetro.
Por tanto, el enlazador liga los módulos de biblioteca read y start-io con el programa. Las
siguientes acciones se llevan a cabo cuando el proceso que representa la ejecución del programa
desea iniciar una operación de E/S:

1. Se llama a iocs-read con internal idalpha como parámetro.


2. iocs-read usa a internal idalpha para acceder a fcbalpha. Forma un bloque de control
interno para la operación de E/S e inicia start-io con su dirección como parámetro.
3. start-io ejecuta una instrucción de SI, lo que invoca el IOCS físico usando la secuen-
cia de instrucciones que se muestra en la figura 12.12.

La figura 12.13 ilustra estos pasos. Por motivos de simplicidad, se supondrá en el siguiente
análisis que todas las invocaciones de las funciones del IOCS físico se realizan por medio de los
módulos de biblioteca del IOCS físico. Definimos los siguientes dos módulos de biblioteca del
IOCS físico para este propósito:

• start-io (<IOCB_address>);
• await-io (<IOCB_address>);

Iniciación de E/S Para iniciar una operación de E/S, un proceso (o un módulo de biblioteca
que trabaja en su nombre) coloca todas las informaciones concernientes a la operación de E/S en
un bloque de control de E/S y hace una llamada start-io (Ad(<iocb>)) en el módulo de biblio-
teca start-io. El módulo start-io carga (Ad(<iocb>) en <reg> y causa una interrupción de
software para invocar la función de iniciación de E/S del IOCS físico (véase la figura 12.13). El
IOCS físico entonces ejecuta las siguientes acciones:

1. Pone el campo bandera de estatus del IOCB en “en ejecución”.


2. Ingresa la dirección de IOCB en la IOQ del dispositivo físico.
3. Inicia la operación de E/S, si el dispositivo de E/S no está ocupado.
4. Regresa al invocador.

14 MAQ. CAP. 12(F0694).indd 546 8/10/07 1:15:33 AM


12.4 E/S de nivel de dispositivo 547

... ... ...


< move > < reg > ,
iocs-read start-io Ad(< iocb> )
(internal idalpha ) (Ad(< iocb> )) < SI instrn > < int code>
... ... ...

Módulo FS Módulo IOCS Módulo de biblioteca


read iocs-read del IOCS físico
start-io
Figura 12.13 Invocación del módulo de biblioteca del IOCS físico start-io.

Para introducir la dirección del bloque de control de E/S en la IOQ correcta, el IOCS físico
extrae la id del dispositivo lógico del IOCB y obtiene la dirección del dispositivo físico asignada
al dispositivo lógico de la tabla de dispositivos lógicos del proceso. Luego obtiene la dirección
de la IOQ para el dispositivo físico de la tabla de dispositivos físicos y agrega la dirección del
IOCB al final de la IOQ. La operación E/S puede iniciarse inmediatamente si no existe ninguna
otra entrada en la IOQ. Si existen otras entradas, cabe suponer que una de las operaciones pre-
vias de E/S está en ejecución, por lo que la nueva solicitud simplemente es ingresada en la IOQ,
y se iniciará en algún momento futuro (véase la descripción de la finalización de E/S para los
detalles).
La iniciación de E/S se realiza tal y como se describe en la sección 12.4. El campo bandera
de estatus del bloque de control de E/S se usa en forma análoga a IO_FLAG del ejemplo 12.4.

Procesamiento de finalización de E/S La función de procesamiento de finalización de E/S


se invoca de manera implícita en caso de ocurrencia de una interrupción de finalización de E/S.
Esta función realiza las siguientes acciones:

1. Invoca la función de recuperación de errores de E/S si la operación de E/S no tuvo


éxito.
2. Pone la bandera de estatus del IOCB en “completado” y retira la dirección del IOCB de
la IOQ del dispositivo.
3. Si hay operaciones de E/S pendientes en el dispositivo, inicia una de ellas.
4. Si el proceso que emite la operación de E/S está bloqueado aguardando su finalización,
cambia su estado a disponible.

El procesamiento de finalización de E/S se implementa del siguiente modo: el hardware de


interrupción proporciona dos ítems de información: la dirección del dispositivo físico que levan-
ta la interrupción de E/S y un código de estatus de E/S que describe la causa de la interrupción.
Estos ítems de información son disponibles para el IOCS físico cuando se le pasa el control.
Usa la dirección del dispositivo para encontrar la entrada de la tabla de dispositivos físicos del

14 MAQ. CAP. 12(F0694).indd 547 8/10/07 1:15:34 AM


548 CAPÍTULO 12 Implementación de operaciones de archivos

dispositivo. Entonces localiza el bloque de control de E/S que corresponde a la operación de E/S
que causó la interrupción. Si el código de estatus de E/S indica una condición de error, el IOCS
físico consulta el campo tipo de dispositivo de la entrada de la PDT e invoca la correspondiente
rutina de recuperación de errores con la dirección del IOCB como parámetro. Si la finalización
de E/S fue normal, el IOCS físico cambia el campo bandera de estatus del IOCB a “completado”
y retira la dirección del IOCB de la IOQ. Si la IOQ no está vacía, se inicia ahora otra operación
de E/S.
Las acciones de la rutina de recuperación de errores son específicas del dispositivo. En
el caso de algunos dispositivos, tales como cintas y discos, pueden presentarse errores de E/S
temporales, y por esta razón la rutina de recuperación reinicia la operación defectuosa algunas
veces antes de declararla irrecuperable. La falla se reporta al proceso si ha fijado los parámetros
correspondientes en la llamada read o write; de no ser así, se cancela el proceso. Si la recupe-
ración de errores es exitosa, la rutina de recuperación de errores regresa el control a la función
de procesamiento de finalización de E/S, la cual realiza entonces todas las acciones correspon-
dientes de la finalización exitosa de la operación de E/S. Este arreglo hace que la ocurrencia de
fallas temporales de E/S sea transparente para un proceso.
Un aspecto esencial del procesamiento de finalización de E/S es la manera en la que el
IOCS físico localiza el bloque de control de E/S (IOCB) para la operación de E/S que causó una
interrupción. La dirección del dispositivo físico que causa una interrupción está disponible para
el IOCS físico, por lo que deberá ser posible localizar esta dirección de la entrada en la DPT de
este dispositivo de E/S. La función de iniciación de E/S puede poner la dirección del IOCB en
un campo especial de la entrada de la PDT cuando inicia una operación de E/S en el dispositivo
o puede mover el IOCB al principio de la IOQ mientras que inicia otra operación de E/S. El
procesamiento de finalización de E/S simplemente recoge la dirección del IOCB de la entrada
de la PDT o de la IOQ del dispositivo para anunciar la finalización de la operación de E/S o para
pasarla al procedimiento de recuperación de errores.

En espera de la finalización de una operación de E/S Un proceso invoca esta función por
medio de la llamada a la biblioteca del dispositivo físico await-io (<IOCB_address>) donde
el IOCB describe la operación de E/S esperada. El IOCS físico solamente verifica la bandera
de estatus en el IOCS y regresa al proceso si el valor de la bandera es “completado”. De no
ser así, la rutina de biblioteca del IOCS físico solicita al kernel que lo bloquee en el evento de
“finalización exitosa de E/S”. El kernel crea un ECB para el evento de finalización de E/S y lo
ingresa en la lista del ECB. Este ECB contiene la id del proceso que espera la finalización de
la operación de E/S. Cuando ocurre el evento de finalización de E/S, el mecanismo de manejo
de eventos localiza su ECB, extrae la id del proceso y marca el cambio correspondiente en su
estado. Este arreglo asegura que la rutina de biblioteca sea activada con la finalización de la
operación de E/S. (Véase el ejemplo 3.5 para una explicación de este arreglo.) El control regresa
ahora al proceso.

Optimización del desempeño del dispositivo de E/S El IOCS físico puede optimizar
el desempeño de un dispositivo de E/S de dos maneras. Puede realizar la planificación inteli-
gente de operaciones de E/S dirigida a un dispositivo de E/S para lograr una mayor capacidad
de procesamiento. Alternativamente, puede reducir el número de operaciones de E/S que van a
ejecutarse, metiendo una parte de los datos almacenados en un dispositivo en la memoria inter-
media. Analizaremos estas técnicas en las secciones 12.5 y 12.9, respectivamente.

14 MAQ. CAP. 12(F0694).indd 548 8/10/07 1:15:34 AM


12.4 E/S de nivel de dispositivo 549

Proceso

Biblioteca del IOCS


físico Start-io Await-io

IOCS físico Traducción de


IOQ la dirección
del dispositivo

Interrupción Manejador de Planificador Iniciador Planificador


de E/S finalización de E/S de E/S de proceso
de E/S

Recuperación Datos
de errores Control

Figura 12.14 Resumen de funcionalidades del IOCS físico.

Resumen de funcionalidades del IOCS físico La figura 12.14 resume las funcionalidades
del IOCS físico. Cada bloque representa un módulo del IOCS físico. Los módulos colocados
arriba de la línea interrumpida se ejecutan en el modo de usuario, mientras que los que se en-
cuentran debajo de esta línea se ejecutan en el modo del kernel. El módulo “Planificador de
E/S” realiza la planificación de disco inteligente de operaciones de E/S para obtener un buen
rendimiento de dispositivos. Las funcionalidades del IOCS físico se activan de dos maneras:
Llamadas a los módulos de biblioteca del IOCS físico start-io o await-io por parte de un
proceso, o mediante la ocurrencia de una interrupción de finalización de E/S. Cuando un pro-
ceso de usuario invoca start-io, start-io invoca a su vez la funcionalidad de iniciación de
E/S del IOCS físico. Luego de la traducción de la dirección del dispositivo, la solicitud ingresa
a la IOQ del dispositivo físico y el control pasa al planificador de E/S. El planificador de E/S
invoca al iniciador de E/S para iniciar la operación de E/S de inmediato si no existe ninguna otra
operación de E/S en la IOQ del dispositivo. Después pasa el control al planificador del proceso,
que lo devuelve al proceso que hizo la solicitud.
Cuando se invoca el módulo await-io del IOCS físico, éste verifica la bandera de esta-
tus del IOCB. Si la operación de E/S está completa, el control se devuelve inmediatamente al
proceso; de no ser así, el proceso hace una llamada al kernel para bloquearse a sí mismo. En el
caso de una interrupción de finalización de E/S, se invoca una rutina de recuperación de errores
si es que ha ocurrido un error de E/S; de no ser así, la bandera de estatus del IOCB se coloca en
“completo”. Se usa el arreglo de ECB-PCB para activar (en caso de que exista) un proceso que
esté esperando la finalización de E/S, y se llama al planificador de E/S para iniciar la siguiente
operación de E/S. Luego el control se pasa al planificador de proceso.

14 MAQ. CAP. 12(F0694).indd 549 8/10/07 1:15:34 AM


550 CAPÍTULO 12 Implementación de operaciones de archivos

12.4.6 Manejadores de dispositivos


El diseño del IOCS físico que hasta ahora se ha descrito tiene un inconveniente: supone que el
IOCS físico tiene los conocimientos suficientes para manejar la iniciación, el procesamiento
de finalización y recuperación de errores de E/S para todos los tipos de dispositivos de E/S que
existen en el sistema. La incorporación de un nuevo dispositivo de E/S requiere cambios del
IOCS físico que pueden ser tanto complejos como caros. Esta característica limita las clases de
dispositivos de E/S que pueden ser conectados al sistema, restringiendo de esa manera el alcance
para el crecimiento y evolución de este último.
A fin de superar este problema, el IOCS físico proporciona sólo el soporte genérico para
operaciones de E/S. El IOCS invoca un módulo manejador de dispositivo especializado (DD)
para el manejo de detalles de nivel dispositivo para una clase específica de dispositivos. Por
tanto, los manejadores de dispositivos no forman parte del IOCS físico. Este arreglo permite
que se agreguen nuevos dispositivos de E/S al sistema sin tener que reconfigurar el kernel. Los
DD son cargados por el procedimiento de iniciación del sistema, dependiendo de la clase de dis-
positivos de E/S que existen en él. Alternativamente, los manejadores de dispositivos se pueden
cargar cada vez que sea necesario durante la operación del SO.

Dirección
del Nombre Puntero
dispositivo del DD de IOQ

Tape DD Tape DD
PDT
Disk DD

Tabla de
puntos
IOQ de entrada IO init: Disk DD
Int proc:

Figura 12.15 El uso de manejadores de dispositivos.

La figura 12.15 ilustra el arreglo que se usa para admitir la carga dinámica de DD. La en-
trada de PDT de un dispositivo muestra el nombre de su manejador de dispositivo en lugar del
nombre de su clase de dispositivos. Cuando se invoca E/S en un dispositivo particular, se obtiene
el nombre de su DD de su entrada de PDT. Disk_DD, el manejador de dispositivos para el disco
del sistema, ya fue cargado en el momento de iniciación del sistema. Otros DD, por ejemplo,
Tape_DD, se cargarán a petición.
Un manejador de dispositivos contiene funcionalidades de los cuatro módulos que se mues-
tran en la figura 12.14, es decir, planificador de E/S, iniciador de E/S, manejador de finaliza-
ción de E/S y recuperación de errores de E/S, para una clase de dispositivos de E/S. Contiene
puntos de entrada para cada una de estas funcionalidades y ofrece una tabla de puntos de entrada
al inicio de su código. El IOCS físico se refiere a esta tabla a fin de escoger la dirección del punto

14 MAQ. CAP. 12(F0694).indd 550 8/10/07 1:15:34 AM


12.5 Planificación del disco 551

de entrada para una operación específica. Como ya se describió, las invocaciones del IOCS físico
pueden ser clasificadas en invocaciones explícitas e invocaciones implícitas. Cuando el IOCS
físico se invoca en forma explícita para iniciar una operación de E/S ejecuta la función genérica
de ingresar detalles de la operación de E/S en la IOQ del dispositivo correspondiente. Entonces
consulta el campo nombre del DD de la entrada de PDT para el dispositivo y obtiene la identidad
del manejador de dispositivos, así como la dirección del punto de entrada para I/O-init, siguiendo
las convenciones estándares. (Si el DD aún no existe en la memoria, se carga en este momento.)
Entonces pasa el control a este punto de entrada del DD. El DD realiza la planificación de E/S
seguida por la iniciación de E/S y devuelve el control al IOCS físico. El IOCS físico entrega el
control al planificador de proceso. Cuando el IOCS físico es implícitamente invocado en el evento
de una interrupción de E/S realiza acciones similares a fin de identificar el punto de entrada del
DD para el manejo de interrupciones y le entrega el control. Después de procesar la interrupción,
el DD devuelve el control al IOCS físico, que a su vez lo entrega al planificador de proceso.

12.5 PLANIFICACIÓN DEL DISCO

El tiempo de búsqueda de un bloque de disco depende de su posición en relación con la posición


actual de las cabezas del disco. Por consiguiente, el tiempo de búsqueda total involucrado en la
ejecución de un conjunto de operaciones de E/S depende del orden en el que se realizaron las
operaciones. La capacidad de procesamiento de un disco, definida como el número de operacio-
nes de E/S realizadas por segundo, también depende del orden en el que se efectuaron las opera-
ciones de E/S. Por ende, el IOCS físico y los manejadores de dispositivos para discos emplean
una política de planificación del disco para realizar operaciones de E/S del disco en un orden
apropiado. Analizaremos las siguientes políticas de planificación de discos antes de describir la
planificación de discos en sistemas modernos:

• Planificación “first-come, first-served” (FCFS, “al primero que llega es al primero que
se atiende”): Selecciona la operación de E/S que fue solicitada primero.
• Planificación “shortest seek time first” (SSTF, “el de tiempo de búsqueda más corto va
primero”): Selecciona la operación de E/S cuyo tiempo de búsqueda desde la posición
actual de las cabezas del disco es el más corto.
• Planificación SCAN: Esta política mueve las cabezas del disco de un extremo del plato
al otro, dando servicio a operaciones de E/S en cada pista o cilindro antes de avanzar a
la siguiente. Esto se llama un barrido (scan). Cuando las cabezas del disco llegan al otro
extremo del plato, se mueven en dirección invertida, y las solicitudes recién llegadas son
procesadas en un barrido inverso. Una variante llamada planificación look invierte la
dirección de las cabezas del disco cuando ya no se puede dar servicio a más operaciones
de E/S en la dirección actual. También se le llama algoritmo del elevador.
• SCAN circular o planificación CSCAN: Esta política realiza un barrido como en la plani-
ficación SCAN. Sin embargo, nunca ejecuta un barrido invertido; en su lugar mueve las
cabezas del disco de regreso a aquel extremo del plato donde habían arrancado e inicia un
nuevo barrido. La variante de look circular (la llamaremos planificación C-look) mueve
las cabezas sólo hasta donde sea necesario para dar servicio a la última operación de E/S
en un barrido antes de comenzar un nuevo barrido.

14 MAQ. CAP. 12(F0694).indd 551 8/10/07 1:15:35 AM


552 CAPÍTULO 12 Implementación de operaciones de archivos

Las políticas de planificación del disco FCFS y SSTF son análogas a algunas políticas de pla-
nificación que fueron analizadas en la sección 4.2. La política de planificación del disco FCFS
es fácil de implementar, pero no garantiza una buena capacidad de procesamiento del disco. La
política de “El tiempo de búsqueda más breve va primero” (SSTF) es análoga a la política de
“La solicitud más corta sigue” (SRN). Se logra una buena capacidad de procesamiento del disco,
pero podrá matar de inanición a algunas solicitudes. A fin de implementar la política de SSTF,
el IOCS físico usa un modelo del disco, que calcula el tiempo de búsqueda de una operación de
E/S dada la posición actual de las cabezas y la dirección del bloque del disco involucrado en la
operación de E/S. La política de SSTF y las diferentes políticas de barrido pueden implementarse
en forma eficiente si las IOQ se mantienen en un orden clasificado por números de pista.
El ejemplo 12.6 describe la operación de varias políticas de planificación de discos para
un conjunto de cinco solicitudes de E/S. La política look funciona mejor que otras políticas en
este ejemplo porque completa todas las operaciones de E/S en el periodo de tiempo más corto.
Sin embargo, ninguna de estas políticas es un vencedor convincente en la práctica porque no se
puede pronosticar el patrón de accesos al disco.

Ejemplo 12.6 La figura 12.16 resume el desempeño de las políticas de planificación de discos
FCFS, SSTF, Look y C-Look para cinco solicitudes de E/S dirigidas a un disco hipotético con 200
pistas. Las solicitudes se hacen en diferentes momentos del tiempo. Se supone que la operación
previa de E/S finaliza cuando el reloj del sistema muestra 160 milisegundos. Se supone que el
tiempo necesario para que las cabezas del disco se muevan desde track1 a track2 es una función li-
neal de la diferencia entre sus posiciones:

thm  tconst  兩 track1  track2 兩  tpt

donde tconst es una constante, tp es el tiempo del movimiento de la cabeza por pista y thm es el tiempo
total de movimiento de la cabeza. Suponemos que los tiempos de latencia rotacional y transferencia
de datos sean mínimos, tconst  0 mseg y tpt  1 mseg. Un valor práctico de tconst es 2 mseg. También
cabe señalar que la fórmula para thm no es lineal en la práctica.
La figura 12.16 muestra los siguientes detalles para cada decisión: el tiempo en el que se tomó
la decisión, solicitudes pendientes y posición de la cabeza en este momento, la solicitud planificada
y su tiempo de búsqueda. La última columna muestra el tiempo total de búsqueda para cada políti-
ca. Las gráficas muestran el movimiento de las cabezas del disco para cada política. Observe que
los tiempos totales de búsqueda varían considerablemente en las diferentes políticas. SSTF es me-
jor que FCFS; sin embargo, look tiene el menor tiempo total de búsqueda en este ejemplo. Es mejor
que C-Look porque puede invertir la dirección de travesía tras completar la operación de E/S en la
pista 100 y dar servicio a las solicitudes en las pistas 75, 40 y 12, mientras que C-Look empieza un
nuevo barrido con la solicitud de la pista 12.

La planificación en discos Un disco SCSI puede aceptar hasta 32 comandos en forma con-
currente. El disco almacena estos comandos en una tabla y usa la planificación para decidir en
qué orden los deberá ejecutar. El IOCS físico asocia una etiqueta con cada comando de E/S para
indicar cómo deberá ser manejado el comando por parte del disco. Esta etiqueta se introduce en
la tabla de comandos junto con otros detalles del comando. Se usa mientras se toman decisiones
de planificación. Esta herramienta se llama formación de colas de comandos etiquetados.
La planificación en el disco puede superar la planificación en el IOCS físico porque el disco
usa un modelo más preciso que considera tanto el tiempo de búsqueda como la latencia rotacio-
nal de uno de sus bloques. Por consiguiente, un disco puede establecer una distinción fina en-
tre dos comandos de E/S que parecen ser equivalentes al IOCS físico. Como ejemplo, considere

14 MAQ. CAP. 12(F0694).indd 552 8/10/07 1:15:35 AM


12.5 Planificación del disco 553

tconst y t pt = 0 mseg y 1 mseg, respectivamente


Posición actual de la cabeza = Pista 65
Dirección del último movimiento = Hacia pistas de numeración más alta
Tiempo del reloj actual = 160 mseg
Solicitudes de E/S:
Número de serie 1 2 3 4 5
Número de pista 12 85 40 100 75
Tiempo de llegada 65 80 110 120 175

Detalles de planificación:
Decisiones de planificación Σ Tiempo de
Política Detalles 1 2 3 4 5 búsqueda
FCFS Tiempo de la decisión 160 213 286 331 391
Solicitudes pendientes 1,2,3,4 2,3,4,5 3,4,5 4,5 5
Posición de la cabeza 65 12 85 40 100
Solicitud seleccionada 1 2 3 4 5
Tiempo de búsqueda 53 73 45 60 25 256
SSTF Tiempo de la decisión 160 180 190 215 275
Solicitudes pendientes 1,2,3,4 1,3,4,5 1,3,4 1,3 1
Posición de la cabeza 65 85 75 100 40
Solicitud seleccionada 2 5 4 3 1
Tiempo de búsqueda 20 10 25 60 28 143
Look Tiempo de la decisión 160 180 195 220 255
Solicitudes pendientes 1,2,3,4 1,3,4,5 1,3,5 1,3 1
Posición de la cabeza 65 85 100 75 40
Solicitud seleccionada 2 4 5 3 1
Tiempo de búsqueda 20 15 25 35 28 123
C-Look Tiempo de la decisión 160 180 195 283 311
Solicitudes pendientes 1,2,3,4 1,3,4,5 1,3,5 3,5 5
Posición de la cabeza 65 85 100 12 40
Solicitud seleccionada 2 4 1 3 5
Tiempo de búsqueda 20 15 88 28 35 186

100 100 100 100


85 85
85 85
75 75
↑ 65 75 65 75 65 65
Pista 40 40 40
no. 40
12 12
12 12
160 416 160 303 160 283 160 346
Tiempo →
FCFS SSTF Look C-Look

Figura 12.16 Resumen de planificación de disco usando las políticas FCFS, SSTF, Look y C-Look.

14 MAQ. CAP. 12(F0694).indd 553 8/10/07 1:15:35 AM


554 CAPÍTULO 12 Implementación de operaciones de archivos

comandos de E/S que conciernen a bloques de disco que están a una distancia de n y n de
la posición actual de las cabezas del disco. Ambos comandos tienen tiempos de búsqueda igua-
les, por lo que el IOCS físico tendrá que hacer una selección al azar entre ellos. Sin embargo,
la planificación de disco podrá descubrir que uno de los comandos tiene una latencia rotacional
más grande que el otro. Dada la posición rotacional actual de los platos, así como la posición
del bloque o sector del disco requerido, el disco podrá darse cuenta de que el bloque de disco
que se encuentra a una distancia de n posiblemente ya está pasando por debajo de las cabezas
al tiempo que éstas son posicionadas sobre la pista. En este caso, el bloque del disco sólo puede
ser leído en el siguiente giro del disco. El bloque del disco que está a una distancia de n pistas
podrá pasar algún tiempo después de que las cabezas se han posicionado sobre la pista, por lo
que su latencia rotacional será menor que la del bloque del disco que está a una distancia de n
pistas. Estas distinciones finas pueden contribuir al mayor rendimiento del disco.
La etiqueta en un comando puede ser de tres tipos: de cola simple, de cola ordenada o de
cabeza de cola. Una etiqueta simple de cola en un comando indica que éste puede ser reorde-
nado para optimizar el rendimiento del disco. Un comando con una etiqueta de cola ordenada
indica que todos los comandos que fueron introducidos en la cola deberán ser planificados antes
de que él sea planificado. Este comando deberá emitirse de vez en cuando para asegurar que
las operaciones de E/S no mueran de inanición, es decir, que no permanezcan por tiempo in-
definido en la tabla de comandos. Un comando con una etiqueta de cabeza de cola deberá ser
ejecutado inmediatamente por el disco, es decir, deberá ejecutarse antes de cualquier otro
comando. Esta herramienta podrá usarse para asegurar que los metadatos se escriben en el disco
antes que los datos de archivos.
La planificación en un disco también tiene sus inconvenientes. El disco considera todas las
operaciones de E/S como iguales, así que podría interferir con optimizaciones del nivel archivo
ejecutadas por métodos de acceso. Considérese el procesamiento de un archivo secuencial con
unos cuantos buffers. Cuando se abre el archivo, el método de acceso emite el comando de leer
los primeros registros del archivo en sus buffers. A fin de explotar las ventajas del almacena-
miento en la memoria intermedia, estos comandos de lectura deberán ejecutarse en el orden de
su emisión; sin embargo, el disco podrá reordenarlos con base en sus latencias de búsqueda y
latencias rotacionales. Por consiguiente, ¡se podrá leer un registro posterior del archivo mientras
que un proceso espera para acceder a un registro anterior!
Los inconvenientes de la planificación en disco llevaron a la pregunta obvia: ¿la planifica-
ción del disco debería llevarse a cabo en el disco, en el IOCS físico o en ambos? El uso de un
modelo más preciso para calcular latencias de búsqueda y latencias rotacionales indica que la
planificación deberá realizarse en el disco. Requerimientos de ordenado de comandos para ad-
mitir la optimización de acceso en el nivel archivo implican que la planificación también deberá
realizarse en el IOCS físico. Un diseñador de SO tiene que asegurar que estos planificadores
colaboren de manera armoniosa.

12.6 ALMACENAMIENTO TEMPORAL DE REGISTROS

Las técnicas de programación de E/S analizadas en la sección 12.4 e ilustradas en la figura 12.9
proporcionan las herramientas básicas para el manejo de iniciación de E/S y procesamiento de
finalización de E/S. Cuando un proceso usa estas técnicas para procesar un archivo secuencial,
su desempeño depende de la cantidad de tiempo que pasa en la lectura/escritura de un registro y
de la cantidad de tiempo del CPU para procesarlo.

14 MAQ. CAP. 12(F0694).indd 554 8/10/07 1:15:36 AM


12.6 Almacenamiento temporal de registros 555

Usaremos la siguiente notación para analizar el desempeño de un proceso que procesa un


archivo secuencial de entrada:

tio : Tiempo de E/S por registro (véase la ecuación 12.1)


tc : Tiempo de copiado por registro (es decir, el tiempo necesario para
copiar un registro de un área de memoria a otra)
tp : Tiempo de procesamiento por registro (el tiempo de CPU que el pro-
ceso dedica al procesamiento de un registro)
tw : Tiempo de espera de E/S por registro (el tiempo durante el cual el
proceso está bloqueado esperando la finalización de una operación
de lectura para un registro)
tee : Tiempo efectivo transcurrido por registro (el tiempo de reloj desde
que el proceso emitió una operación de lectura para un registro hasta
el final del procesamiento de un registro)

En forma análoga, tw y tee quedan definidos para el archivo de salida. Llamaremos a la proporción
1− ttiow el traslape de CPU-E/S en un programa.
Cuando tw  tio, el traslape de CPU-E/S es 0. Puede mejorarse el desempeño de un proceso
haciendo que tw  tio. El mejor rendimiento del proceso se obtendrá si tw  0, lo que sólo es
posible si un registro está disponible en la memoria cada vez que lo necesita el proceso. El plan-
teamiento básico para lograr esta condición es traslapar el procesamiento de un registro con la
lectura del siguiente registro (o escritura del registro previo). Usando este arreglo, tw se volverá
0 si E/S para el siguiente registro está completo en el momento en que se procese el registro
previo. Se usan las técnicas de almacenamiento temporal y bloqueado de registros para lograr
esta condición.
Un buffer de E/S es un área de la memoria que se usa temporalmente para almacenar datos
involucrados en una operación de E/S. El almacenamiento temporal en buffers se emplea para
proporcionar el traslape de las actividades de E/S y del CPU en un proceso —es decir, traslapar
tio y tp— con el fin de reducir tw. Esto se logra mediante la

• Prelectura de un registro de entrada en un buffer de E/S; o


• Posescritura de un registro de salida de un buffer de E/S.

En la lectura previa, la operación de E/S para leer el siguiente registro se inicia en un


buffer algún tiempo antes de que el proceso necesite el registro. Esto se podrá iniciar mien-
tras el CPU está procesando el registro anterior. Este arreglo traslapa una parte de tio para
la lectura del siguiente registro con tp para el registro anterior. De este modo, el proceso
desperdicia menos tiempo esperando la finalización de una operación de E/S. En la escritura
posterior, el registro que va a ser escrito simplemente se copia a un buffer cuando el pro-
ceso emite una operación de escritura. La salida verdadera se realiza desde el buffer algún
tiempo más tarde. Puede traslaparse con (una parte de) el procesamiento para el siguiente
registro.
Para ver el efecto del almacenamiento temporal en el tiempo transcurrido de un proceso,
tomaremos en cuenta un programa que lee y procesa 100 registros de un archivo secuencial.

14 MAQ. CAP. 12(F0694).indd 555 8/10/07 1:15:36 AM


556 CAPÍTULO 12 Implementación de operaciones de archivos

Consideraremos tres versiones del programa llamado Unbuf_P, Single_buf_P y Multi_buf_P,


que usan cero, uno y n buffers n  1, respectivamente. Suponemos tio  75 mseg, tp  50
mseg y tc  5 mseg.
La figura 12.17 ilustra la operación y el desempeño de procesos que representan ejecucio-
nes de los programas Unbuf_P, Single_buf_P y Multi_buf_P. Por motivos de conveniencia,
supondremos que un proceso tiene el mismo nombre que el programa que ejecuta. Para cada
proceso, la figura muestra el código del programa, ilustra los pasos involucrados en la lectura
y procesamiento de un registro, y muestra una tabla de tiempos que describe su desempeño.
Unbuf_P usa una sola área de memoria llamada Rec_area para leer y procesar un registro del
archivo F (véase la figura 12.17a)). Emite una operación de lectura y aguarda su finalización
antes de procesar un registro. El diagrama de tiempos muestra que E/S se realiza en Rec_area
desde t  0 hasta t  75 milisegundos, y el procesamiento del CPU ocurre entre t  75 mseg
y t  125 mseg. Por tanto, tw  tio, tee  tio  tp y no existen traslapes de CPU-E/S en el
proceso. El tiempo transcurrido del proceso es 100  (75  50) mseg  12.5 segundos.
La figura 12.17b) ilustra la operación de Single_buf_P, que usa un solo buffer llamado
Buffer. El proceso emite una operación de lectura para leer el primer registro en Buffer y
entra al bucle principal del proceso, que repite el siguiente procedimiento de 4 pasos 99
veces:

1. Aguarda el final de la operación de E/S en Buffer.


2. Copia el registro de Buffer a Rec_area.
(12.3)
3. Inicia una operación de E/S en Buffer.
4. Procesa el registro existente en Rec_area.

Como se muestra en el diagrama de tiempos de la figura 12.17b), el proceso enfrenta una


espera de E/S en el primer paso de (12.3) hasta que finaliza la operación de lectura de Buffer.
Ahora ejecuta los pasos 2-4 de (12.3). Luego copia el primer registro a Rec_area, inicia una
operación de lectura para el segundo registro y empieza a procesar el primer registro. Estas
dos actividades proceden en forma concurrente, logrando así un traslape CPU-E/S. Represen-
tamos este hecho dibujando un cuadro rectangular para encerrar el procesamiento del primer
registro y la lectura del segundo registro en la parte de actividades de la figura 12.17b). Un
traslape parecido se obtiene mientras se procesan los registros 2-99. El paso 2 de (12.3), es
decir, el copiado del siguiente registro de Buffer a Rec_area, sólo se realiza después de que
ambos, la lectura del siguiente registro y el procesamiento del registro actual, finalizan. De
este modo, para los registros 2-99, el tiempo efectivo transcurrido por registro (tee) es repre-
sentado por

tee  tc  máx (tio, tp) (12.4)

Ningún procesamiento está activo cuando el primer registro se está leyendo, y ningún E/S
está activo cuando el último registro está siendo procesado. De este modo, la operación del
proceso atraviesa tres fases distintas: la de arranque cuando se lee el primer registro, el estado
estable cuando se leen y se procesan los registros, y la fase final, cuando se procesa el último
registro. El tiempo total transcurrido se da entonces por

Tiempo total transcurrido  tio  (número de registros  1)  tee  (tc  tp) (12.5)

14 MAQ. CAP. 12(F0694).indd 556 8/10/07 1:15:36 AM


12.6 Almacenamiento temporal de registros 557

Programas
Programa Unbuf P Programa Single buf P Programa Multi buf P

inicia una operación E/S para inicia una operación E/S para for i := 1 a n
lectura (F, Rec area); lectura (F, Buffer); inicia una operación E/S
aguarda finalización de E/S; aguarda finalización de E/S; para lectura(F, Buf i );
while (not end of file(F)) while (not end of file(F)) aguarda finalización E/S en
begin begin Buf 1 ;
procesa Rec area; copia Buffer a Rec area; k := 1;
inicia una operación E/S para inicia una operación E/S para while (not end of file(F))
lectura (F, Rec area); lectura (F, Buffer); copia Bufk a Rec_area;
aguarda finalización ;de E/S; procesa Rec area; inicia una operación E/S para
end aguarda finalización de E/S; lectura (F, Buf k );
end procesa Rec area;
k := (k mod n) + 1;
aguarda finalización de E/S en
Buf k ;
end
E/S, actividades de copiado y procesamiento durante la ejecución (UP:Unbuf_P, SP:Single_buf_P, MP:Multi_buf_P)

Rec area Buffer Buf 1

UP
Rec area Buffer Rec area Buf 2

Rec area Buf 1 Rec area


Buffer
MP
UP SP
Rec area
Rec area Rec area
..
.
Buffer Rec area Buf 1

Buffer Buf 2 Rec area


.. SP .. MP
. Rec area . Rec area
Diagramas de tiempos (I: operación de E/S; C: copiado; P: procesamiento)

I
C
Buf 1 75 150

I I
C C
Buffer 75 155 Buf 2 75 150

I C C
P P P
Rec area 75 125 200 Rec area 80 130160 210 Rec area 80 130155 205

a) b) c)
Figura 12.17 Procesamiento de archivos sin y con almacenamiento temporal. (Nota: La condición end_of_file se fija cuando
el enunciado espera finalización de E/S se ejecuta para una operación que trata de leer más allá del fin de un
archivo.)

14 MAQ. CAP. 12(F0694).indd 557 8/10/07 1:15:36 AM


558 CAPÍTULO 12 Implementación de operaciones de archivos

donde los tres términos de la ecuación (12.5) explican las fases de arranque, estado estable y final
del proceso. Para Single_buf_P, tee es 80 mseg y el tiempo total transcurrido del proceso es 75 
99  80  55 mseg  8.05 segundos.
En el estado estable, tw  tio  (tc  tp). Por tanto, el almacenamiento temporal será más
efectivo para valores menores de tio. De hecho, tw  0 si tio  tc  tp. Por ejemplo, si tio fuese 50
mseg, el tiempo total transcurrido del proceso sería 5.55 segundos.
La figura 12.17c) ilustra la operación del proceso Multi_buf_P, que usa áreas de buffers
llamados Buf1, Buf2 . . . Bufn. Al principio del procesamiento de archivos, Multi_buf_P inicia E/S
en todos los buffers n. Dentro del bucle de procesamiento de archivos usa los buffers turnándose,
siguiendo los pasos de (12.3) para procesar un registro en un buffer. El enunciado k : (k mod n)
 1 asegura que se usen los buffers de manera cíclica. El proceso espera hasta que E/S finalice en
el siguiente buffer, copia el registro del buffer a Rec_area, inicia E/S en el buffer y, por último,
procesa el registro en Rec_area.
Hay una diferencia significativa entre Multi_buf_P y Single_buf_P. Considere el proce-
samiento de los primeros dos registros en la figura 12.17c). Cuando finaliza E/S en Buf1,
Multi_buf_P copia el primer registro de Buf1 a Rec_area y empieza a procesar los contenidos
de Rec_area. Al mismo tiempo, inicia una operación de lectura en Buf2. Entonces ambas
operaciones —el copiado y procesamiento del registro de Buf1 y la E/S en Buf2— se realizan
en forma concurrente. En la figura 12.17c) representamos este hecho por medio de un recua-
dro rectangular con líneas interrumpidas alrededor del copiado y procesamiento del registro
desde Buf1, y encerrando el recuadro rectangular con líneas interrumpidas y la operación de
E/S en Buf2 dentro de otro recuadro rectangular. El tiempo transcurrido del proceso se da
entonces así:

tee  máx (tio, tc  tp) (12.6)


Tiempo total transcurrido  tio  (100  1)  tee  (tc  tp) (12.7)

El tiempo total transcurrido de Multi_buf_P es 75  99  75  55 mseg  7.555 segundos, lo


cual es marginalmente mejor que el tiempo transcurrido de Single_Buf_P de 8.05 segundos.
La proporción del tiempo transcurrido de Unbuf_P y Multi_buf_P es el factor de aceleración
debido al almacenamiento temporal. Considerando el estado estable, el factor de aceleración es
t +t
aproximadamente iotee p . En la ecuación (12.6) puede verse que su mejor valor se obtiene cuando
tio  tc  tp. Este valor tiene el límite superior de 2.
Considere la operación de Multi_buf_P cuando se usa  1 buffer. La figura 12.18 ilustra
una situación típica durante la ejecución de Multi_buf_P. El CPU acaba de copiar el registro de
Bufi 1 a Rec_area e inició una operación de E/S en Bufi 1. De este modo, E/S fue iniciado
en todos los buffers n. Algunas de las operaciones de E/S, es decir, las operaciones en Bufi . . .
Bufj 1, ya están completas. E/S está en ese momento en ejecución para Bufj, mientras que Bufj1
. . . Bufn, Buf1 . . . Bufi 1 se encuentran actualmente en la cola para la iniciación de E/S. De este
modo, (j i) buffers están llenos en este momento, E/S está activo para un buffer y (n  j  i
 1) buffers están en la cola para E/S.
El valor de (j  i) dependerá de los valores de tio y tp. Si tio  tp, es decir, si E/S para un
registro es más rápido que su procesamiento, podemos ver que los buffers Bufi1 . . . Bufn, Buf1
. . . Bufi  2 estarán llenos y Bufi 1 o estarán bajo E/S o llenos cuando el CPU está procesando
el registro copiado desde Bufi  1. Si tio  tp, la situación de estado estable será que Bufi estará
bajo E/S cuando el CPU está procesando el registro copiado desde Bufi 1, y los buffers Bufi1
. . . Bufn, Buf1 . . . Bufi  1 estarán vacíos.

14 MAQ. CAP. 12(F0694).indd 558 8/10/07 1:15:37 AM


12.7 Bloqueo de registros 559

n 1
n–1 2

E/S j
i–1
i
i+1
buffer vacío
buffer lleno

Figura 12.18 El uso de buffers en Buf_P.

El uso de buffers múltiples es irrelevante si un proceso maneja cada registro en forma indivi-
dual. Sin embargo, hay una diferencia marcada si un programa maneja muchos registros juntos.
Usar n buffers ayuda en estos casos porque muchos buffers podrán estar llenos cuando el proceso
necesita más de un registro al mismo tiempo.

Definición 12.1 (Requerimiento pico de registros) El requerimiento pico de registros de un


archivo en un proceso es el número más grande de registros de ese archivo que probablemen-
te son manejados juntos por el proceso.

El ejemplo 12.7 ilustra cómo el requerimiento pico de un proceso puede ser más grande
que 1; muestra también la manera de usar el almacenamiento temporal para satisfacer el reque-
rimiento pico de registros.

Ejemplo 12.7 Cada línea de un programa escrito en el lenguaje L se almacena en un registro del
archivo F. El compilador de L que se usa para compilar este programa tiene que leer a la memoria
un enunciado completo antes de comenzar su procesamiento. Un enunciado podrá contener hasta l
líneas, y por tanto su requerimiento pico es l registros. Las E/S esperan que termine el compilador
sólo si las siguientes condiciones son válidas:
1. tio  tpl y
2. l  n
donde tpl es el promedio de tiempo de procesamiento para cada línea de un enunciado. La condición
1 asegura que en la operación normal todos los buffers estarán llenos cuando el compilador termina
con el procesamiento de un enunciado. La condición 2 asegura que por lo menos l buffers están
llenos cuando el compilador termina con el procesamiento de un enunciado, así que no tendrá que
enfrentar esperas de E/S. Habrá enfrentado esperas de E/S si l  n, por ejemplo si l  3 y si usaba
2 buffers.

12.7 BLOQUEO DE REGISTROS

En el procesamiento sin almacenamiento temporal de un archivo por parte de un proceso, el


tiempo que se pasa en la ejecución de E/S podrá dominar el tiempo transcurrido del proceso.
Incluso en el procesamiento de un archivo con almacenamiento temporal, tw  0 si tio  tp, o

14 MAQ. CAP. 12(F0694).indd 559 8/10/07 1:15:37 AM


560 CAPÍTULO 12 Implementación de operaciones de archivos

tio  tc  tp (véanse las ecuaciones (12.4) y (12.6)). De este modo, tanto el procesamiento sin
almacenamiento temporal como el procesamiento con almacenamiento temporal de archivos se
beneficiarán de una reducción en tio. La técnica del bloqueo de registros se usa para reducir el
tiempo de E/S efectivo por registro.
Según la ecuación (12.1), tio  ta  tx, donde ta y tx son el tiempo de acceso por registro y el
tiempo de transferencia por registro, respectivamente. Ahora considere un proceso que lee o escri-
be dos registros juntos en una sola operación de E/S. El tiempo de transferencia de datos para la
operación de E/S es 2  tx, por lo que el tiempo de E/S para la operación, t* io, es expresado por

io  ta  2  tx
t* (12.8)
La operación de E/S lee o escribe dos registros, por lo que
tio∗ ta
Tiempo efectivo de E/S por registro  = + tx
2 2
De este modo, el tiempo efectivo de E/S fue reducido, escribiendo más de un registro en una
operación de E/S.

Registros lógicos y físicos Un registro lógico es la unidad de datos procesados por un


proceso. Un registro físico o bloque es la unidad de datos para la transferencia desde o hasta
un medio de E/S. Se dice que un archivo emplea el bloqueo de registros si un registro físico
contiene más de un registro lógico.

Definición 12.2 (Factor de bloqueo) El factor de bloqueo de un archivo es el número de


registros lógicos en un registro físico.

De un archivo que usa el factor de bloqueo  1 se dice que contiene registros bloqueados.
La figura 12.19 muestra un archivo que usa un factor de bloqueo 3.

Hueco entre Hueco entre


registros registros
Registro Registro Registro
lógico lógico lógico

Bloque

Figura 12.19 Un archivo con el factor de bloqueo  3.

Acciones de desbloqueo Una operación de lectura en un archivo que tiene registros blo-
queados transfiere m registros lógicos a la memoria, donde m es el factor de bloqueo. Las accio-
nes para extraer un registro lógico de un bloque para el procesamiento en un proceso se llaman
en forma colectiva acciones de desbloqueo.
La figura 12.20 muestra un programa que manipula un archivo con registros bloqueados
sin almacenamiento temporal. El bucle principal del programa no inicia una operación de lec-
tura después de procesar cada registro lógico. Un índice continuo l apunta al siguiente registro
lógico dentro del bloque que se está procesando. Cuando l excede m, el factor de bloqueo l es
reiniciado a 1 y se lee el siguiente bloque. Una lógica parecida puede estar incorporada en los

14 MAQ. CAP. 12(F0694).indd 560 8/10/07 1:15:38 AM


12.7 Bloqueo de registros 561

programas de la figura 12.17b), c) para lograr el procesamiento con almacenamiento temporal de


un archivo que contiene registros bloqueados.

inicia una operación E/S para read (F, Rec_area);


aguarda finalización de E/S;
while (not end_of_file (F))
for i : 1 to m
{ extrae el registro i-ésima en Rec_area y procésalo }
inicia una operación E/S para lectura (F, Rec_area);
aguarda finalización de E/S;
end

Figura 12.20 Procesamiento de un archivo con registros bloqueados sin almacenamiento temporal.

Elección del factor de bloqueo Generalizando con respecto a la discusión previa, si slr y
spr representan el tamaño de un registro lógico y físico, respectivamente, entonces spr  m. slr.
El tiempo total de E/S por registro físico, (tio)pr, y el tiempo de E/S por registro lógico, (tio)lr, son
dados por

(tio )pr = ta + m × tx (12.9)


ta
(tio )lr = + tx (12.10)
m
De este modo, el bloqueo reduce el tiempo efectivo de E/S por registro lógico. Si tx  tp,
mediante una elección apropiada de m será posible reducir (tio)lr de tal modo que (tio)lr  tp  tc.
Una vez que se logra esto, se deduce de las ecuaciones (12.4) y (12.6) que el almacenamiento
temporal puede ser usado para reducir el tiempo de espera por registro.

Tabla 12.7 Variación de (tio)lr con factor de bloqueo

Factor de Tamaño del ta m  tx (tio)pr (tio)ir


bloqueo (m) bloque mseg mseg mseg mseg
1 200 10 0.25 10.25 10.25
2 400 10 0.50 10.50 5.25
3 600 10 0.75 10.75 3.58
4 800 10 1.00 11.00 2.75

Ejemplo 12.8 La tabla 12.7 muestra que la variación de (tio)lr con m para un dispositivo de disco
con ta  10 mseg, velocidades de transferencia de 800 K bytes/seg y slr  200 bytes. tx, el tiempo
de transferencia por registro lógico es 200
800
mseg, es decir, 0.25 mseg. (tio)pr y (tio)lr se calculan
como en las ecuaciones (12.9) y (12.10). Si tp  3 mseg, m  4 hace (tio)lr  tp.

El valor de m se limita en la parte inferior por el deseo de hacer (tio)lr  tp  tc. En la parte
superior está limitado por las siguientes consideraciones:

14 MAQ. CAP. 12(F0694).indd 561 8/10/07 1:15:38 AM


562 CAPÍTULO 12 Implementación de operaciones de archivos

• Compromiso de memoria para buffers de archivos.


• Tamaño de una pista o sector del disco.
Un valor práctico del factor de bloqueo es el valor más pequeño de m que hace (tio)lr  tp 
tc. Entonces dos buffers son suficientes para eliminar esperas de E/S para el segundo y los poste-
riores bloques. Como hemos analizado en la sección 12.6, podrá considerarse un mayor número
de buffers para satisfacer el requerimiento pico de registros en un proceso.

Registros Registros
Buf 1 de de
Buf 1 Buf 2
Buf 2 Rec area 1 2 3 4 1 2 3 4

0 11 2223 3435 0 11 23 35
Actividades de E/S Actividades de procesamiento

Figura 12.21 Procesamiento con almacenamiento temporal de registros bloqueados usando


el factor de bloqueo  4 y dos buffers.

Ejemplo 12.9 La figura 12.21 muestra la tabla de tiempos para el procesamiento del archivo blo-
queado del ejemplo 12.8 con un factor de bloqueo 4, usando dos buffers Buf1 y Buf2. Suponemos que
tc es nimio. El procesamiento empieza con operaciones de lectura en Buf1 y Buf2. La operación en
Buf1 finaliza con t  11 mseg. El proceso atiende ahora los cuatro registros lógicos copiados de Buf1.
Cada registro lógico requiere 3 mseg de tiempo del CPU, así que el procesamiento de los cuatro
registros de Buf1 consume 12 mseg. Este procesamiento se traslapa con la operación de lectura en
Buf2, lo que consume 11 mseg. Por consiguiente, un bloque fue leído a Buf2 antes de que finalice el
procesamiento de registros en Buf1. El CPU empieza a procesar los registros lógicos copiados de Buf2
con t  23 mseg. De este modo, el proceso no sufre esperas de E/S después de la fase de arranque.

12.8 MÉTODOS DE ACCESO


El IOCS ofrece una biblioteca de módulos de métodos de acceso. Como se mencionó en la
sección 7.3.4, un método de acceso proporciona el soporte para el procesamiento eficiente de
una clase de archivos que usa una organización de archivos específica. Para las organizaciones
fundamentales de archivos que se analizaron en la sección 7.3, el IOCS podrá ofrecer métodos
de acceso para los siguientes tipos de procesamiento:
• Procesamiento sin almacenamiento temporal de archivos de acceso secuencial.
• Procesamiento con almacenamiento temporal de archivos de acceso secuencial.
• Procesamiento de archivos de acceso directo.
• Procesamiento sin almacenamiento temporal de archivos de acceso secuencial con índice.
• Procesamiento con almacenamiento temporal de archivos de acceso secuencial con índice.
Los métodos de acceso para el procesamiento con almacenamiento temporal de archivos
de acceso secuencial y secuencial con índice incorporan la técnica de almacenamiento temporal
ilustrada en la figura 12.17c). Los métodos de acceso para el procesamiento con almacenamiento

14 MAQ. CAP. 12(F0694).indd 562 8/10/07 1:15:39 AM


12.8 Métodos de acceso 563

temporal de archivos de acceso secuencial y secuencial con índice también ofrecen una opción
para realizar el bloqueo de registros usando la técnica que se muestra en la figura 12.20.
Suponemos que cada módulo de método de acceso proporciona tres puntos de entrada con
los siguientes parámetros:

1. AM-open (<internal id>)


2. AM-close (<internal id>)
3. AM-read/write (<internal id>, <record info>, <I/O area addr>)

Los módulos del sistema de archivos e IOCS invocan estas funcionalidades para implementar
el procesamiento de archivos. AM-open es invocado por iocs-open después de copiar las
informaciones de la entrada del directorio del archivo a su FCB. De igual modo, AM-close
es invocado por iocs-close. AM-read/write son invocados por un módulo del sistema de
archivos. El punto de entrada AM-read es en realidad el módulo de biblioteca de IOCS seq-
read de la figura 12.13.

AM−open (internal id alpha ); 1. Asigna buffers, fija sus direcciones en fcbalpha.


2. Emite llamadas start-io en todos los buffers.

AM−read (internal id alpha , 1. Emite await-io para las operaciones de E/S en


< Rec area address > ); el siguiente buffer.
2. Si se emplea el bloqueo, ejecuta acciones de
desbloqueo. Copia el registro a Rec_area. De
ser necesario, emite start-io para el siguiente
bloque.
3. De no ser así, copia el registro en Rec_area y
emite start-io para el siguiente registro.

AM−close (internal id alpha); 1. Libera todos los buffers

Programa de aplicación Acciones de métodos de acceso

Figura 12.22 Acciones de un método de acceso para la lectura de un archivo con almacenamiento temporal.

La figura 12.22 muestra acciones del método de acceso para el procesamiento de un archi-
vo de acceso alpha con almacenamiento temporal. AM-read usa la información en fcbalpha,
incluido fmtalpha, a fin de formar un par (id del registro, id del byte) para el siguiente bloque en el
archivo. Cuando se emplea el bloqueo, esta acción sólo será necesaria después de que el último
registro de un bloque sea entregado al proceso. Algunas acciones del método de acceso serán
diferentes si alpha es un archivo de salida. Se invocará AM-write para realizar operaciones de
escritura. En el paso 2, el método invocará un módulo del sistema de archivos para asignar más
espacio en disco e ingresar su dirección en fmtalpha.

14 MAQ. CAP. 12(F0694).indd 563 8/10/07 1:15:39 AM


564 CAPÍTULO 12 Implementación de operaciones de archivos

12.9 CACHÉ DE DISCO UNIFICADA

Un sistema operativo mantiene una caché de disco para acelerar accesos repetidos a datos de
archivos y metadatos, como tablas de mapas de archivos almacenados en el disco. La caché
contiene copias de bloques de disco que recientemente fueron leídos desde distintos archivos
por procesos y copias de datos de salida que un proceso desea escribir en un archivo, pero que
aún no están escritos en el disco. Cuando se va a iniciar una operación de lectura o escritura en
un archivo, el sistema de archivos convierte el desplazamiento de un byte de datos en el archivo
en una dirección de un bloque del disco y en un desplazamiento en el bloque. El sistema usa la
dirección del bloque del disco para verificar si éste existe en la caché del disco. De ser así, se
accederá a él para realizar la operación de E/S; de no ser así, el bloque del disco se lee en la caché
y la operación de E/S se completa. Si la caché está llena, se emplea la política de reemplazo LRU
para crear espacio para la nueva página. Un bloque del disco modificado se escribe en el archivo
cuando debe ser retirado de la caché.
El uso de la caché de disco acelera los accesos a archivos. Los estudios que mencionamos
en la sección 12.10.2 indican que puede lograrse una proporción de 0.9 y superiores cuando
se compromete una cantidad limitada de la memoria a la caché de disco. El uso de la caché de
disco también tiene algunos inconvenientes. Una operación de E/S involucra dos operaciones
de copiado, una entre el disco y la caché de disco y la otra entre la caché de disco y el espa-
cio de dirección del proceso que inició la operación de E/S. Otra desventaja es que su desempeño
es susceptible al comportamiento de acceso a archivos de los procesos. Por ejemplo, la lectura
de un gran archivo secuencial por parte de un proceso llenará la caché de disco con partes de
este archivo, por lo que los accesos a datos en otros archivos se verán afectados hasta que parte
de este archivo sea reemplazado por bloques de otros archivos. La caché de disco también lleva
a una baja confiabilidad del sistema de archivos porque en el evento de una caída del sistema se
perderán bloques de discos que contiene.
El SO también mantiene otra caché, ya sea implícita o explícitamente, que se llama caché de
página. Ésta contiene todas las páginas de código y datos de procesos que existen en la memoria,
incluidos todos los archivos mapeados en la memoria. Una nueva página se carga en la caché
cuando ocurre una falla de página. Por lo común, el tamaño de la página es de unos cuantos blo-
ques, por lo que esta operación implica leer unos pocos bloques de un archivo de programa o un
archivo de intercambio. Esto es, el archivo de E/S. Primero, los bloques del disco se leen en la
caché de disco y luego se copian a la caché de página. Cuando tiene que retirarse de la memoria
una página modificada, primero se copia a la caché de disco. Desde allí se escribe al disco en
algún momento futuro.
La figura 12.23a) es un esquema que muestra la caché de disco y la caché de página. El
uso de estas dos cachés implica dos operaciones de copiado cuando se va a ejecutar una opera-
ción de entrada o salida de página: una operación de copiado entre un disco y la caché de disco,
así como una operación de copiado entre la caché de disco y la caché de página. Durante un
tiempo, dos copias de la página podrán existir en la memoria hasta que se sobrescribe la copia en
la caché de disco en la caché de página.
El copiado doble de datos en páginas y copias duplicadas de páginas causa problemas
de desempeño. Un diseñador de SO o un administrador de sistema también se enfrenta a una
difícil decisión de diseño: ¿cuánta memoria se deberá comprometer en cada caché? Esta de-
cisión puede afectar el desempeño del sistema porque la falta de compromiso de memoria en
la caché de página llevará a un grado reducido de multiprogramación y a una posible degene-
ración mientras que la falta de compromiso en la caché de disco aminorará el procesamiento de

14 MAQ. CAP. 12(F0694).indd 564 8/10/07 1:15:39 AM


12.10 Procesamiento de archivos en Unix 565

Proceso Proceso

Paginación, archivos
mapeados en memoria
Paginación, archivos
Sistema de archivos Sistema de archivos
mapeados en memoria
Caché de páginas

Caché de
Caché de disco
disco unificada

Disco Disco

a) b)
Figura 12.23 Cachés de disco: a) cachés separadas de discos y páginas; b) caché de disco unificada.

archivos debido a frecuentes accesos al disco. La fusión de las dos cachés resolverá estos proble-
mas. Se eliminan las copias duplicadas y el copiado doble de datos. Se puede variar el tamaño de
cachés individuales para ser indicado para la carga de trabajo actual del sistema.
Una caché de disco unificada es una sola caché que se usa tanto para la paginación como
para E/S de archivos. La figura 12.23b) muestra un esquema de la caché unificada. Se hace un
cambio en el sistema de archivos a fin de facilitar esta unificación. El sistema de archivos enton-
ces considera los archivos como objetos paginados en el disco. Cuando una operación de lectura
o escritura proporciona el desplazamiento de un byte en un archivo, entonces descompone el
desplazamiento del byte a un número de página y un desplazamiento en una página. El número de
página se entrega a la caché unificada para cargar la página a la memoria. E/S de página continúa
siendo manejado como en sistemas convencionales porque la caché unificada es realmente una
caché de páginas.
La caché de disco unificada fue introducida en el SO de Sun 4.0. Más tarde se implementó
en el Unix System 5, versión 4. Las versiones de Linux a partir de 2.4 también usan una caché
de disco unificada.

12.10 PROCESAMIENTO DE ARCHIVOS EN UNIX

12.10.1 Controladores de dispositivos


Un controlador de dispositivos de Unix está estructurado en dos mitades que se llaman mitad
superior y mitad inferior. La superior consiste en rutinas que inician operaciones de E/S en un
dispositivo, en respuesta a llamadas de leer, escribir, abrir o cerrar emitidas por un proceso,
mientras que la mitad inferior consiste en el manejador de interrupciones para la clase de disposi-
tivos a los que el controlador da servicio. La mitad superior corresponde entonces al planificador
de E/S y a los modelos de iniciadores de E/S de la figura 12.14, mientras que la mitad infe-
rior corresponde al manejador de finalización de E/S y a módulos de recuperación de errores.

14 MAQ. CAP. 12(F0694).indd 565 8/10/07 1:15:39 AM


566 CAPÍTULO 12 Implementación de operaciones de archivos

El SO define una interfaz del controlador de dispositivos estándar que consiste en un con-
junto de puntos de entrada predefinidos a las rutinas de controladores de dispositivos. Algunos
de ellos son los siguientes:

1. <ddname>_init : Rutina de inicialización de DD.


2. <ddname>_read/write : Rutinas para leer o escribir un carácter.
3. <ddname>_int : Rutina de manejador de interrupciones.

La rutina <ddname>_init se llama en el momento de inicialización del sistema. Esta rutina


inicializa varias banderas usadas por el DD. También verifica si existe la presencia de varios
dispositivos, coloca banderas para indicar su presencia y podrá asignar buffers a ellos. E/S de
carácter se realiza invocando las rutinas <ddname>_read y <ddname>_ write. El controlador
de dispositivos tiene que ofrecer una rutina de estrategia para transferencias de bloques de datos.
La rutina de estrategia es aproximadamente equivalente al planificador de E/S que se muestra
en la figura 12.14. Una llamada en la rutina de estrategia toma la dirección de bloque de control
de E/S como parámetro. La rutina de estrategia agrega este IOCB a una IOQ, y de ser posible ini-
cia la operación de E/S. Si la iniciación inmediata no es posible, la operación de E/S es iniciada
posteriormente por el manejador de interrupciones.

12.10.2 Caché de buffers

Unix admite sólo archivos de flujos de bytes, es decir, archivos secuenciales sin estructura algu-
na. En la sección 7.12 hemos analizado el arreglo que consiste en un inodo, descriptor de archivo
y estructura de archivo que se establece cuando se abre un archivo para su procesamiento (véase
la figura 7.30). La caché de buffers es una caché de disco (véase la sección 12.9) que se usa para
ofrecer las ventajas del almacenamiento temporal y del bloqueo de datos, y también para mini-
mizar operaciones de disco para datos de acceso frecuente.
La caché de buffers consiste en un pool de buffers. Un buffer tiene el mismo tamaño que
un bloque del disco. Los buffers en una caché no se asignan por proceso ni por archivo. En su
lugar, un buffer se asigna a un bloque del disco y es usado por cada proceso que necesita tener
acceso a los datos en el bloque del disco. Cuando un archivo es compartido por muchos proce-
sos, los datos requeridos por un proceso ya podrán existir en un buffer si otro proceso ha tenido
acceso a ellos últimamente, por lo que no se necesita un acceso al disco en cada operación de
lectura. De modo similar, se evitan accesos al disco si un proceso accede a ciertos datos más
de una vez.
Se mantiene un encabezado para cada buffer. El encabezado contiene tres ítems de informa-
ción: un par (dirección del dispositivo, dirección del bloque del disco) da la dirección del bloque
del disco que actualmente existe en el buffer. Una bandera de estatus indica si E/S está activo
para el buffer y una bandera de ocupado indica si algún proceso tiene actualmente acceso a los
contenidos del buffer.
Se usa una tabla hash para acelerar la búsqueda de un bloque del disco requerido (véase la fi-
gura 12.24). La tabla hash consiste en un número de recipientes donde cada uno apunta hacia una
lista de buffers. Se usa una función de cálculo de llave (hashing) h para acceder a la tabla. Tiene
la propiedad básica de que, dado cualquier número x, calcula un resultado que se encuentra en el
rango de 1 ... n, donde n es el número de recipientes en la tabla hash. Cuando un bloque del disco
con la dirección aaa se carga al buffer sin la dirección bbb, aaa se consulta mediante la función h

14 MAQ. CAP. 12(F0694).indd 566 8/10/07 1:15:40 AM


12.10 Procesamiento de archivos en Unix 567

para calcular un número de recipiente e  h(aaa) en la tabla hash. Entonces se ingresa el buffer
en la lista de buffers en el recipiente e-ésimo. Por ende, todos los buffers que contienen bloques
del disco cuyas direcciones entran en el recipiente e-ésimo se encuentran en esta lista.

Tabla hash Buffers

Recipiente #1 9 25 13

Recipiente #2 6 18

Recipiente #3 11 3 Puntero de
lista libre

Recipiente #4 4

Figura 12.24 Caché de buffers de Unix.

Se usa el siguiente procedimiento cuando un proceso P realiza una operación de lectura en


el archivo alpha:

1. Forma el par (dirección del dispositivo, dirección del bloque del disco) para el byte re-
querido por P.
2. Reagrupa los datos de dirección de bloque del disco para obtener un número de reci-
piente. Busca entre los buffers en el recipiente para verificar si un buffer tiene un par
coincidente en su encabezado.
3. Si no existe un buffer con un par coincidente, asigna un buffer libre, coloca la informa-
ción (dirección del dispositivo, dirección del bloque del disco) en su encabezado, ingresa
el buffer en la lista de el recipiente correspondiente, fija su bandera de estatus en “E/S
en ejecución”, coloca el buffer en la cola para E/S y pone P a dormir cuando E/S está
completada.
4. Si existe un buffer con un encabezado correspondiente, regresa a P con su dirección si
las banderas indican que la operación de E/S en el buffer está completa y el buffer “no
está ocupado”; de no ser así, pone P a dormir luego de la finalización de una operación
de lectura en el buffer o condición buffer “no ocupado”.
5. Si existe un buffer libre, verifica si el siguiente bloque de disco asignado a alpha ya
existe en la memoria. Si no, asígnale un buffer libre y coloca el buffer en la cola para una
operación de lectura.

Este procedimiento realiza la lectura previa de datos por proceso, iniciando una E/S para el
siguiente bloque del disco del archivo (paso 5). Las ventajas del bloqueo de registros son inhe-
rentes en el hecho de que un bloque del disco completo es lectura/escritura cuando se accede a
cualquiera de sus bytes.

14 MAQ. CAP. 12(F0694).indd 567 8/10/07 1:15:40 AM


568 CAPÍTULO 12 Implementación de operaciones de archivos

Los buffers en el pool de buffers se reutilizan sobre una base de LRU como sigue: todos los
buffers se ponen en una lista libre. Un buffer se mueve al final de la lista cada vez que se hace
referencia a su contenido. De este modo, los buffers más recientemente usados se mueven a la
cabeza de la lista libre. En el paso 3, el buffer del principio de la lista libre es asignado, a menos
que contenga datos modificados que aún no se han escrito en el archivo. En este caso, se pone en
la cola una operación de escritura y se asigna el siguiente buffer de la lista.

Ejemplo 12.10 La figura 12.24 ilustra la caché de buffers de Unix. Los bloques 9, 25 y 13 del
disco entran en la primera entrada de la tabla hash, y por tanto son ingresados en la lista li-
gada a partir de esta entrada. Del mismo modo, 6, 18 y 11, 3 forman las listas ligadas, empe-
zando en la segunda y tercera entrada de la tabla hash. También se ingresan todos los buffers
en la lista libre. La posición de un buffer en la lista libre indica cuán recientemente el buffer fue
accedido por un proceso. Si el proceso P necesita acceder a datos residentes en el bloque de
disco 18, el buffer que contiene el bloque 18 se trasladará al final de la lista libre. Si P ahora
necesita datos en el bloque de disco 21, el primer buffer de la lista libre, es decir, el buffer que
contiene el bloque 13, le será asignado si el contenido del buffer no ha sido modificado desde
que se cargó el bloque 13. Después de cargar el bloque de disco 21 al buffer, éste se agregará a
la lista correspondiente en la tabla hash. Este buffer también será trasladado al final de la lista
libre.

12.11 PROCESAMIENTO DE ARCHIVOS EN LINUX

La organización del IOCS de Linux es análoga a la del IOCS de Unix. Dispositivos de E/S del
tipo bloque y carácter son admitidos por controladores de dispositivos individuales, los dispo-
sitivos se tratan como archivos y se usa una caché de buffers para acelerar el procesamiento de
archivos. Sin embargo, muchos detalles de IOCS son diferentes. Enumeraremos algunos de ellos
antes de analizar detalles de la planificación del disco en Linux 2.6.

1. Los módulos del kernel de Linux pueden cargarse en forma dinámica, por lo que tiene
que registrarse un controlador de dispositivos en el kernel cuando se carga y tiene que
eliminarse el registro antes de ser retirado de la memoria.
2. En cuanto a los dispositivos, la estructura de datos vnode del sistema virtual de archivos
(VFS) (véase la sección 7.11) contiene apuntadores dirigidos hacia funciones específicas
de dispositivos para las operaciones de archivos abrir, cerrar, leer y escribir.
3. Cada buffer en la caché del disco tiene un encabezado de buffer que está asignado a un
slab del slab allocator (véase la sección 5.10).
4. Los buffers sucios (datos modificados en la memoria) en la caché del disco se escriben
en la caché cuando ésta se encuentra demasiado llena, cuando un buffer ha estado en la
caché por mucho tiempo o cuando un archivo le ordena al sistema de archivos eliminar
sus buffers en aras de la sincronización.

La planificación de E/S en Linux 2.6 usa algunas innovaciones para mejorar el desempeño
de esta planificación. Es necesario emitir una operación de lectura al disco cuando un proceso
hace una llamada read y los datos requeridos aún no existen en la caché de buffers. El proceso se
bloqueará hasta que la operación de lectura esté completa. Por otra parte, cuando un proceso

14 MAQ. CAP. 12(F0694).indd 568 8/10/07 1:15:40 AM


12.12 Procesamiento de archivos en Windows 569

hace una llamada write, los datos que se van a escribir se copian a un buffer y la verdadera ope-
ración de escritura se lleva a cabo en un momento posterior. Entonces el proceso que emite una
llamada write no será bloqueado; podrá seguir y emitir más llamadas write. Para proporcionar
mejores tiempos de respuesta a procesos, el IOCS realiza, por ende, las operaciones de lectura
con mayor prioridad que las de escritura.
El planificador de E/S lleva una lista de operaciones de E/S pendientes y planifica a partir
de ella. A fin de mejorar el desempeño del disco, combina nuevas operaciones de E/S con
operaciones de E/S pendientes cuando esto es posible. Cuando un proceso hace una llamada
read o write, el IOCS verifica si alguna operación de E/S pendiente involucra la ejecución de
la misma operación en algunos datos contiguos. Si esta revisión es exitosa, combina la nueva
operación con la operación pendiente, por lo que las cabezas del disco tienen que posicionarse
solamente una vez sobre la pista correspondiente, lo que reduce el movimiento de las cabezas
del disco.
Linux 2.6 ofrece cuatro planificadores de E/S. El administrador del sistema puede elegir
el planificador que mejor le convenga para la carga de trabajo en una instalación específica. El
planificador No-op es simplemente un planificador de FCFS. El planificador deadline utiliza
la planificación Look como base, pero también incorpora una herramienta para evitar retrasos lar-
gos. Implementa la planificación Look con una lista de planificación de solicitudes clasificadas
por números de pista y selecciona una solicitud basándose en la posición que ocupan en ese mo-
mento las cabezas del disco. Sin embargo, la planificación Look enfrenta un problema cuando un
proceso ejecuta un gran número de operaciones de escritura en una parte del disco: operaciones
de E/S en otras partes del disco se retrasarán. Si una operación retrasada es una lectura, causará
retrasos considerables en el proceso solicitante. A fin de prevenir estos retrasos, el planificador
asigna un plazo de 0.5 segundos para una operación de lectura, y un plazo de 5 segundos para
una operación de escritura, y mantiene dos colas —una para solicitudes de lectura y otra para so-
licitudes de escritura— de acuerdo con los plazos. Normalmente planifica solicitudes de la lis-
ta de planificación; sin embargo, si vence el plazo de una solicitud que encabeza la cola de
lectura o escritura, planifica esta solicitud, así como dos solicitudes más de esta cola, fuera
de secuencia, antes de reanudar su planificación normal. El planificador de colas completamente
justo mantiene una cola separada de solicitudes de E/S para cada proceso y va de una a la otra
entre estas colas. Este planteamiento evita largos retrasos para los procesos.
Un proceso que ejecuta E/S síncronas es bloqueado hasta que se completa su operación E/S.
Estos procesos normalmente emiten la siguiente operación de E/S inmediatamente después de
despertar. Cuando se usa la planificación Look, es muy probable que las cabezas del disco hayan
pasado por encima de la pista que contiene los datos involucrados en la siguiente operación de
E/S, por lo que la siguiente operación de E/S del proceso recibe el servicio apenas en el siguiente
barrido de las cabezas del disco. El planificador previsor aborda ese problema. Luego de finali-
zar una operación de E/S, el planificador espera unos milisegundos antes de emitir la siguiente
operación de E/S. De este modo, si el proceso que fue activado cuando finalizó la operación de
E/S anterior emite inmediatamente otra operación de E/S, a ésta también se le podrá atender en
el mismo barrido del disco.

12.12 PROCESAMIENTO DE ARCHIVOS EN WINDOWS

Windows provee un administrador de caché centralizado que es usado tanto por el administra-
dor de E/S como por el administrador de memoria virtual (VM). La figura 12.25 muestra un

14 MAQ. CAP. 12(F0694).indd 569 8/10/07 1:15:40 AM


570 CAPÍTULO 12 Implementación de operaciones de archivos

esquema del arreglo. El administrador de E/S consiste en el NFTS y el controlador de disposi-


tivos para discos.

Hilos

Administrador Solicitud de E/S


de caché Sistema de
archivos

Transferencia Vaciado
de datos de caché
Transfe-
rencia
Administrador de datos
de VM Controlador
Carga de del disco
páginas

Administrador de E/S

Figura 12.25 Administración de la memoria caché en Windows 2000.

La caché está organizada como un conjunto de bloques de caché. Cada bloque de caché tiene
un tamaño de 256 K bytes. La parte de un archivo contenido en un bloque de caché se llama vista.
Un bloque de control de dirección virtual (VACB) se usa para describir cada vista. Cada entrada
en un VACB también indica el número de hilos que usan esta vista. El administrador de caché crea
un conjunto de VACB. Eso ayuda a determinar rápidamente si una parte requerida de un archivo
se encuentra en la caché en un momento dado. También indica fácilmente si una vista está en ese
momento en uso. A fin de facilitar este arreglo, un archivo es considerado como una secuencia de
vistas, cada una de 256 K bytes, y se instala un array de VACB para él cuando se abre.
Cuando un hilo hace una solicitud para leer/escribir desde un archivo, el administrador de
E/S pasa esta solicitud al administrador de caché. El administrador de caché consulta al array
de VACB para el archivo y determina si la parte requerida de éste forma parte de una vista en
la caché. De no ser así, asigna un bloque de caché y mapea la vista en él. Si la solicitud fue de
lectura, copia los datos requeridos al espacio de dirección del usuario. Esta operación involucra
al administrador de MV en cuanto al manejo de accesos al espacio de dirección del usuario. Si
surge una falla de página durante la operación de copiado, el administrador de MV invoca al
controlador del disco por medio de NTFS para que lea la página requerida a la memoria. Por
razones obvias, esta operación se realiza sin caché.
El administrador de caché realiza la colocación de un archivo en la memoria intermedia
mediante el análisis de las solicitudes de lectura/escritura. Si se da cuenta de que las solicitudes
inmediatamente anteriores indican un acceso secuencial al archivo, realiza una lectura previa de
los bloques de datos posteriores. Las actualizaciones de archivos se llevan a cabo de manera
interesante. Los datos que van a escribirse a un archivo se reflejan a la vista del campo guardada

14 MAQ. CAP. 12(F0694).indd 570 8/10/07 1:15:41 AM


Ejercicio 12 571

en el administrador de caché. El administrador de caché periódicamente anima al administrador


de MV para grabar los datos en el archivo. Cuando esto se ha hecho, puede liberar el bloque de
caché asignado a la vista.

EJERCICIO 12
1. Explique cómo (si ése es el caso) el almacenamiento temporal y el bloqueo de registros serán prove-
chosos para archivos con las siguientes organizaciones:
a) Organización secuencial
b) Organización secuencial con índice
c) Organización directa.
2. Un archivo update es un archivo que es leído y modificado durante el procesamiento; un proceso lee un
registro, lo modifica en la memoria y lo escribe en forma retardada mientras procesa el archivo.
a) ¿Qué dispositivo de E/S es el más adecuado para grabar un archivo de actualización?
b) ¿Es el almacenamiento temporal y el bloqueo de registros útil para un archivo de actualización?
Justifique sus respuestas.
3. Analice cómo puede optimizarse la capacidad de procesamiento de un dispositivo de disco en un sis-
tema de archivos que realiza la asignación no contigua de bloques del disco a archivos. (Sugerencia:
Piense en las técnicas de escalonado de datos.)
4. Un disco sectorizado tiene las siguientes características:
tiempo para 1 revolución  8 mseg
tsect  1 mseg
tdt  3 mseg
tamaño del sector  1 024 bytes
Trace el desempeño pico del disco contra el factor de entrelazado de sectores (inf).
5. Comente sobre la efectividad de a) una caché de disco y b) un disco RAM, para la aceleración de acce-
so a registros, usando organizaciones de archivos secuenciales y directas.
6. En las siguientes pistas hay solicitudes de operaciones de E/S pendientes a un tiempo  160 mseg:

7, 45, 98, 70, 68, 180


Si las solicitudes se hicieron en el orden antes indicado, construya una tabla análoga a la tabla 12.16
para el disco del ejemplo 12.6.
7. Un disco sesgado es un dispositivo de disco hipotético cuyo tiempo de búsqueda para la pista n es una
función lineal en n (por ejemplo, tiempo de búsqueda  0.1  n). {ri} es el conjunto de solicitudes de
E/S generadas en un SO a través de un determinado periodo de tiempo. Comente acerca de si el orden
en el que se planifican solicitudes de E/S en un disco sesgado mediante el algoritmo SSTF será idén-
tico al orden en el que las mismas solicitudes de E/S serán planificadas por un algoritmo SCAN en el
disco convencional que se describe en el ejemplo 12.6.
8. Cuando se procesa un archivo secuencial, los tiempos de E/S y de procesamiento para cada registro son
los siguientes:
Tiempo de acceso del dispositivo  10 mseg
Tiempo de transferencia por registro  6 mseg
Tiempo de copiado por registro  0.5 mseg
Tiempo de procesamiento por registro  10 mseg

14 MAQ. CAP. 12(F0694).indd 571 8/10/07 1:15:41 AM


572 CAPÍTULO 12 Implementación de operaciones de archivos

a) Si se usan dos buffers, encuentre el valor del factor de bloqueo más pequeño que puede eliminar
esperas de E/S para el segundo y los siguientes bloques.
b) Si se usan dos buffers y un factor de bloqueo de 5, ¿cuál es el requerimiento pico de registros en un
proceso que este arreglo de bloqueo y almacenamiento temporal pueda satisfacer?
9. Se graba un archivo secuencial usando el bloqueo. Se procesa por medio de dos buffers. Los tiempos
de E/S y de procesamiento son los siguientes:

Tiempo de acceso (promedio)  20 mseg


Tiempo de transferencia por registro  4 mseg
Tiempo de copiado por registro  0.5 mseg
Requerimiento pico de registros por el proceso  5 registros
Tiempo de procesamiento por registro  10 mseg

Determine los valores óptimos del factor de bloqueo y el número de buffers.


¿Cuáles serían los cambios, si proceden, que usted haría en su diseño si el requerimiento pico de regis-
tros fuera i) 3 registros, ii) 8 registros?
10. Se usa un buffer en el procesamiento del archivo info del problema 7 en el ejercicio 7. Calcule el
tiempo transcurrido del proceso si el tiempo de transferencia por registro es 0.5 mseg. Explique sus
cálculos.
11. Comente sobre la validez del siguiente enunciado: “Por medio de la selección sensata del factor de blo-
queo y del número de buffers, siempre es posible eliminar esperas de E/S por completo para el segundo
y los siguientes bloques en un archivo.”
12. Se espera que un proceso abra un archivo antes de acceder a él. Si trata de acceder a un archivo sin
abrirlo, FS realiza un open antes de implementar el acceso. Un manual de programadores de sistemas
le advierte a todos los programadores que abran un archivo antes de acceder a él a fin de no sufrir una
penalización de desempeño. Explique la naturaleza y las causas de la penalización de desempeño.
13. Analice el impacto de algoritmos de planificación de discos sobre la efectividad del almacenamiento
temporal de E/S.
14. Se procesa un archivo de entrada usando muchos buffers. Comente sobre la validez de los siguientes
enunciados:
a) “De todos los algoritmos de planificación de discos, la planificación de discos FCFS probablemente
ofrecerá el mejor desempeño de tiempo transcurrido para el programa.”
b) “El entrelazado de sectores sólo es útil mientras se lean los primeros registros en el archivo; no es
útil mientras se lean otros registros.”
15. Una cinta magnética tiene una densidad de grabación de 8 bits por milímetro a lo largo de una pista.
La cinta se mueve con una velocidad de 2 metros por segundo mientras que lee/escribe datos. El hueco
entre registros tiene un ancho de 0.5 cm, y el tiempo de acceso de la cinta es de 5 mseg. Un archivo
secuencial que contiene 5 000 registros, cada uno de un tamaño de 400 bytes, se almacena en esta cinta
magnética. Calcule la longitud de la cinta magnética ocupada por el archivo, así como el tiempo total de
E/S requerido para leer el archivo si el archivo se graba a) sin bloqueo y b) con un factor de bloqueo de 4.
16. Un proceso usa varios buffers mientras procesa un archivo que contiene registros bloqueados. Durante
su ejecución ocurre una falla del sistema. ¿Es posible reanudar la ejecución del proceso desde el punto
de la falla?
17. El factor de aceleración que resulta del uso de una técnica especial de E/S es la relación entre el tiempo
transcurrido de un proceso sin usar bloqueo o almacenamiento temporal y el tiempo transcurrido del

14 MAQ. CAP. 12(F0694).indd 572 8/10/07 1:15:41 AM


Bibliografía 573

mismo proceso usando la técnica especial de E/S. En la sección 12.6 se demostró que el factor de
aceleración debido al almacenamiento temporal tiene un límite superior de 2.
Desarrolle una fórmula para el factor de aceleración cuando un proceso no usa buffers mientras procesa
un archivo que contiene registros bloqueados. ¿Puede el valor de este factor de aceleración exceder a
2? De ser así, dé un ejemplo.
18. Desarrolle una fórmula para el factor de aceleración cuando un proceso usa 2 buffers mientras procesa
un archivo que contiene registros y ttp  tx.
19. Describa las implicaciones de la caché de buffers de Unix para la confiabilidad del sistema de archivos.
Unix admite una llamada al sistema flush para forzar el kernel a escribir salidas con almacenamiento
temporal al disco. ¿Puede un programador usar flush para mejorar la confiabilidad de sus archivos?
20. El comando lseek de Unix indica que el desplazamiento del siguiente byte en un archivo secuencial
debe ser leído/escrito. A este comando le sigue un verdadero comando de lectura/escritura.
a) Comente sobre las ventajas de usar el comando lseek en un proceso.
b) Indique la secuencia de acciones que se deberán ejecutar cuando un proceso emite un comando
lseek.

BIBLIOGRAFÍA
Tanenbaum (1990) describe el hardware de E/S. Ruemmler y Wilkes (1994) presentan un modelo de con-
trolador de discos que puede usarse para el análisis y la afinación del desempeño. Teorey y Pinkerton (1972)
y Hofri (1980) comparan varios algoritmos de planificación de discos, mientras que Worthington et al.
(1994) analizan la planificación de discos para unidades de disco modernos. Lumb et al. (2000) estudian la
manera en que actividades de segundo plano, tales como la reorganización del disco, pueden ejecutarse du-
rante el posicionamiento mecánico de las cabezas del disco para dar servicio a actividades del primer plano,
así como el efecto de algoritmos de planificación de discos sobre la efectividad de este planteamiento.
Chen y Patterson (1990), así como Chen et al. (1994) describen organizaciones RAID, mientras que
Wilkes et al. (1996) y Yu et al. (2000) analizan mejoras para sistemas RAID. Alvarez et al. (1996) analizan
cómo pueden tolerarse fallas múltiples en una arquitectura RAID, mientras que Chau y Fu (2000) estudian
un nuevo método de diseño para distribuir de manera uniforme las informaciones de paridad para RAID
desagrupados. Gibson et al. (1997) estudian servidores de archivos para discos adjuntados a redes. Nagle et
al. (1999) analizan la integración de la conexión en red de nivel usuario con el almacenamiento adjuntado
a redes (NAS). Curtis Preston (2002) estudia NAS y redes de áreas de almacenamiento (SAN), mientras
que Clark (2003) se dedica a la tecnología SAN. Toigo (2000) analiza discos modernos y tecnologías de
almacenamiento futuras.
Cachés de discos son analizadas en Smith (1985); Braunstein et al. (1989) estudian cómo se aceleran ac-
cesos a archivos cuando se utiliza hardware de memoria virtual para buscar la caché del buffer de archivos.
McKusick et al. (1996) analizan el sistema Berkeley Fast File para Unix 4.4BSD. Bach (1986) y
Vahalia (1996) lo hacen en relación con otros sistemas de archivado de Unix. Ruemmler y Wilkes (1993)
presentan estudios de desempeño con respecto a varias características de accesos a discos hechos en el sis-
tema de archivado de Unix. Beck et al. (2002), así como Bovet y Cesati (2003), analizan los planificadores
de E/S de Linux. Love (2004, 2005) describe los planificadores de E/S en Linux 2.6. Custer (1994) describe
el sistema de archivos de Windows NT, mientras que Russinovich y Solomon (2005) analizan NTFS para
Windows.

1. Alvarez, G.A., W.A. Burkhard, F. Cristian (1996): “Tolerating multiple failures in RAID architec-
tures with optimal storage and uniform declustering”, Proceedings of the 24th Annual Internatio-
nal Symposium on Computer Architecture, 62-72.

14 MAQ. CAP. 12(F0694).indd 573 8/10/07 1:15:41 AM


574 CAPÍTULO 12 Implementación de operaciones de archivos

2. Bach, M.J. (1986): The design of the Unix operating system, Prentice-Hall, Englewood Cliffs.
3. Beck, M., H. Bohme, M. Dziadzka, U. Kunitz, R. Magnus, C. Schroter y D. Verworner (2002):
Linux Kernel Programming, Pearson Education.
4. Bovet, D.P. y M. Cesati (2003): Understanding the Linux Kernel, O’Reilly, Sebastopol.
5. Braunstein, A., M. Riley y J. Wilkes (1989): “Improving the efficiency of Unix buffer caches”,
ACM Symposium on OS Principles, 71-82.
6. Chau, A. y A.W. Fu (2000): “A gracefully degradable declustered RAID architecture with near
optimal maximal read and write parallelism”, Cluster Computing, 5 (1), 97-105.
7. Chen, P.M. y D. Patterson (1990): “Maximizing performance in a striped disk array”, Proceedings
of Seventeenth Annual International Symposium on Computer Architecture, mayo 1990.
8. Chen, P.M., E.K. Lee, G.A. Gibson, R.H. Katz y D.A. Patterson (1994): “RAID—high performan-
ce, reliable secondary storage”, Computing Surveys, 26 (2), 145-186.
9. Clark, T. (2003): Designing Storage Area Networks: A Practical Reference for Implementing Fi-
bre Channel and IP SANS, 2a. ed., Addison Wesley Professional.
10. Curtis Preston, W. (2002): Using SANs and NAS, O’Reilly, Sebastopol.
11. Custer, H. (1994): Inside the Windows NT File System, Microsoft Press, Redmond.
12. Gibson, G.A., D. Nagle, K. Amiri, F.W. Chang, E.M. Feinberg, H. Gobioff, C. Lee, B. Ozceri,
E. Riedel, D. Rochberg y J. Zelenka (1997): “File server scaling with network-attached secure
disks”, Measurement and Modeling of Computer Systems, 272-284.
13. Hofri, M. (1980): “Disk scheduling: FCFS vs. SSTF revisited”, Communications of the ACM, 23
(11), 645-53.
14. Iyer, S. y P. Druschel (2001): “Anticipatory scheduling: a disk scheduling framework to overcome
deceptive idleness in synchronous I/O”, Proceedings of the 18th ACM Symposium on Operating
Systems Principles.
15. Lampson, B. (1981): “Atomic transactions”, Distributed Systems—Architecture and Implementa-
tion: An Advanced Course, Goos, G. y J. Hartmanis (Eds), Springer Verlag, Berlín, 246-265.
16. Love, R. (2004): “I/O schedulers”, Linux Journal, 118.
17. Love, R. (2005): Linux Kernel Development, 2a. ed., Novell Press.
18. Lumb, C.R., J. Schindler, G.R. Ganger y D.F. Nagle (2000): “Towards higher disk head utiliza-
tion: extracting free bandwidth from busy disk drives”, Proceedings of the 4th Symposium on
Operating Systems Design and Implementation.
19. McKusick, M.K., K. Bostic, M.J. Karels y J.S. Quarterman (1996): The Design and Implementa-
tion of the 4.4 BSD Operating System, AddisonWesley, Reading.
20. Nagle D., G. Ganger, J. Butler, G. Gibson y C. Sabol (1999): “Network support for network-atta-
ched storage”, Proceedings of Hot Interconnects.
21. Ruemmler, C. y J. Wilkes (1993): “Unix disk access patterns”, Proceedings of the Winter 1993
USENIX Conference, 405-420.
22. Ruemmler, C. y J. Wilkes (1994): “An introduction to disk drive modeling”, IEEE Computer, 27
(3), 17-29.
23. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a, ed., Microsoft Press,
Redmond.
24. Smith, A.J. (1985): “Disk cache-miss ratio analysis and design considerations”, ACM Transac-
tions on Computer Systems, 3 (3), 161-203.
25. Tanenbaum, A.S. (1990): Structured Computer Organization, 3a. ed., Prentice Hall, Englewood
Cliffs.

14 MAQ. CAP. 12(F0694).indd 574 8/10/07 1:15:41 AM


Bibliografía 575

26. Teorey, T.J. y T. B. Pinkerton (1972): “A comparative analysis of disk scheduling policies”, Com-
munications of the ACM, 15 (3), 177-184.
27. Toigo, J. (2000): “Avoiding a data crunch”, Scientific American, 282 (5), 58-74.
28. Vahalia, U. (1996): Unix Internals—The New Frontiers, Prentice Hall, Englewood Cliffs.
29. Wilkes, J., R. Golding, C. Staelin y T. Sullivan (1996): “The HP autoRAID hierarchical storage
system”, ACM Transactions on Computer Systems, 14 (1), 108-136.
30. Worthington, B.L., G.R. Ganger y Y. N. Patt (1994): “Scheduling algorithms for modern disk
drives”, Proceedings of the 1994 ACM Sigmetrics Conference on Measurement and Modeling of
Computer Systems, 241-251.
31. Yu, X., B. Gum, Y. Chen, R.Y. Wang, K. Li, A. Krishnamurthy y T. E. Anderson (2000): “Trading
capacity for performance in a disk array”, Proceedings of the 2000 Symposium on Operating Sys-
tems Design and Implementation, 243-258.

14 MAQ. CAP. 12(F0694).indd 575 8/10/07 1:15:42 AM


Capítulo
13
Sincronización y planificación
en sistemas operativos
multiprocesador

Un sistema multiprocesador puede ofrecer tres ventajas en comparación con un sistema mono-
procesador: mayor rendimiento, aceleración de cálculo y degradación elegante. Un SO multipro-
cesador puede ejecutar varios procesos en los CPU al mismo tiempo, logrando así un rendimiento
más alto. Si una aplicación está estructurada para ser un conjunto de procesos concurrentes, en-
tonces esta característica también puede proporcionar una aceleración para la aplicación. Cuan-
do un procesador falla, el sistema puede continuar la operación con sus procesadores restantes.
Esta característica se llama degradación elegante. Es vital a fin de admitir aplicaciones de mi-
sión crítica y de tiempo real.
Un SO multiprocesador debe explotar plenamente la presencia de múltiples CPU para apro-
vechar estas ventajas. Lo logra atendiendo tres asuntos. El kernel está estructurado de tal modo
que varios CPU pueden ejecutar su código y realizar funciones de control en forma paralela. De
esta manera, el kernel no se convierte en un cuello de botella del rendimiento. Se usan canda-
dos de sincronización especiales para reducir la priorización y conmutación de procesos que son
debidos a la sincronización. Los procesos de una aplicación están planificados de tal forma que
puedan ejecutarse de manera eficiente y armoniosa en varios CPU.
Empezaremos con una vista general de la arquitectura de sistemas multiprocesadores, lo
que nos dará los antecedentes para un análisis de los temas de sincronización y planificación.
Después analizaremos los tres asuntos que se mencionaron en las líneas anteriores.

13.1 LA ARQUITECTURA DE SISTEMAS


MULTIPROCESADORES
El desempeño y la confiabilidad de un sistema monoprocesador dependen del desempeño y la
confiabilidad del CPU y de la memoria. Estos últimos pueden ser aumentados mediante el uso
de chips más rápidos y de varias capas de cachés; sin embargo, el desempeño no puede ser mejo-
rado más allá de los límites tecnológicos. Otras mejoras del desempeño pueden lograrse usando

15 MAQ. CAP. 13(F0694).indd 576 8/10/07 1:16:26 AM


13.1 La arquitectura de sistemas multiprocesadores 577

múltiples CPU. Ésta es la razón por la cual las arquitecturas de procesadores múltiples ganaron
importancia a finales de los años noventa.

Tabla 13.1 Ventajas de multiprocesadores

Ventaja Descripción
Alto rendimiento El CPU puede dar servicio a varios procesos al mismo tiempo. Por
tanto, se realiza más trabajo.
Aceleración de cálculo Puede darse servicio a varios procesos de una aplicación al mismo
tiempo, lo que lleva a la finalización más rápida del cálculo y a mejo-
res tiempos de reacción.
Degradación elegante La falla de un procesador no detiene la operación del sistema. Éste
puede seguir funcionando con capacidades un tanto reducidas.

Las arquitecturas de multiprocesadores ofrecen las tres ventajas que se resumieron en la


tabla 13.1. Se incrementa el rendimiento porque el SO puede planificar varios procesos en forma
paralela. Sin embargo, el desempeño no varía de modo lineal en relación con el número de pro-
cesadores debido a la disputa por la memoria. Analizaremos este aspecto más adelante en esta
sección. Un cálculo puede completarse más rápidamente si sus procesos están planificados en
paralelo. La verdadera aceleración de un cálculo depende de varios factores, por ejemplo, de la
política de planificación, de la carga general del sistema operativo y del paralelismo inherente
en una aplicación. Una falla en el procesador detiene la operación de un monoprocesador. Sin
embargo, en un sistema multiprocesador, otros procesadores podrán continuar su operación. Esta
característica ofrece una habilidad vital que se necesita en aplicaciones de misión crítica, como
los servicios en línea.
La jerarquía de memoria en un sistema monoprocesador consta de: el disco, la memo-
ria principal y la caché (véase sección 2.1.2). En los sistemas de multiprocesadores, la me-
moria principal, por sí misma, puede tener dos niveles: la memoria local y la memoria no-local.
Las velocidades en las cuales un procesador puede acceder a las memorias local y no-local
dependen de las asociaciones procesador-memoria. Esta característica es crucial en la sincroni-
zación de procesos ya que ésta se alcanza mediante el uso de candados y semáforos almacenados
en la memoria compartida. Es también importante la planeación, debido a que puede ocurrir
una baja considerable en el desempeño si el CPU ejecuta un proceso que existe en la memoria
no-local.

La clasificación de sistemas multiprocesadores Los sistemas multiprocesadores se cla-


sifican en tres tipos, basados en la manera en que procesadores y unidades de memoria están
asociados entre sí.

• Arquitectura de memoria uniforme (arquitectura UMA): Todos los CPU en el sistema


pueden acceder a la memoria completa en forma idéntica, es decir, con la misma velo-
cidad de acceso. Algunos ejemplos de arquitecturas UMA son el sistema Balance de
Sequent y VAX 8800 de Digital. En la literatura más vieja, esta arquitectura se llamaba

15 MAQ. CAP. 13(F0694).indd 577 8/10/07 1:16:27 AM


578 CAPÍTULO 13 Sincronización y planificación en sistemas operativos multiprocesador

de multiprocesadores firmemente acoplados. También se llama arquitectura de multipro-


cesadores simétricos (SMP).
• Arquitectura de memoria no uniforme (arquitectura NUMA): Este sistema consiste en
un número de nodos. Cada nodo consiste en uno o varios CPU, una unidad de memoria
y un subsistema de E/S. De la unidad de memoria de un nodo se dice que es local para
los CPU en ese nodo. De otras unidades de memoria se dice que son no locales. Todas
las unidades de memoria juntas constituyen un solo espacio de direcciones. Cada CPU
puede acceder al espacio de direcciones completo, pero puede hacerlo más rápidamente
a la unidad de memoria local que a las no locales. Algunos ejemplos de la arquitectura
NUMA son el AlphaServer de HP y el NUMA-Q de IBM.
• Arquitectura de acceso a memoria no remota (arquitectura NORMA): Cada CPU tiene
su memoria local. Los procesadores pueden acceder a unidades de memoria remotas,
pero este acceso está en la red; por tanto, es lento comparado con el acceso a la memoria
local. El sistema Hypercube de Intel es un ejemplo de arquitectura NORMA. Un sistema
NORMA es un sistema distribuido según la definición 2.10; por tanto, no hablaremos de
la arquitectura de sistemas NORMA en este capítulo.

Tabla 13.2 Características de varias redes de interconexión

Red Características
Bus Bajo costo. Velocidad de acceso razonable con baja densidad de trá-
fico. Sólo una conversación puede estar en progreso en un momento
dado.
Interruptor cross-bar Alto costo. Baja posibilidad de escalar. Los procesadores y las unida-
des de memoria están conectados al interruptor. Una conversación se
implementa mediante la selección de una ruta entre un procesador y
una unidad de memoria. Permite múltiples conversaciones en forma
concurrente.
Red de interconexiones Un compromiso entre un bus y un interruptor cross-bar. Consiste de
etapas múltiples (MIN) en muchas etapas de interruptores cross-bar
2 ⫻ 2. Una conversación se establece seleccionando una ruta a través
de cada etapa. Permite algunas conversaciones concurrentes.

Redes de interconexiones Los CPU en un sistema multiprocesador usan una red de inter-
conexiones para acceder a las unidades de memoria. Dos importantes atributos de una red de
interconexiones son el costo y la velocidad efectiva de acceso. La tabla 13.2 ilustra tres redes
populares de interconexiones. La figura 13.1 contiene esquemas de estas redes.
El uso de un bus en un sistema de multiprocesadores es simplemente una extensión de su
uso en un sistema monoprocesador. Todas las unidades de memoria y todos los CPU están co-
nectados al bus. Éste admite entonces el tráfico de datos entre cualquier CPU y cualquier unidad
de memoria. Sin embargo, solamente puede llevarse a cabo una conversación en un momento
dado. La organización es simple y económica, pero lenta debido a la disputa por la memoria con
medianas o altas densidades de tráfico.

15 MAQ. CAP. 13(F0694).indd 578 8/10/07 1:16:27 AM


13.1 La arquitectura de sistemas multiprocesadores 579

M0 M1 M2 M3

P0 • • • •

P0 P1 • • • •
M0
P1 P2 • • • •
M1
P2 P3 • • • •

Bus Interruptor cross-bar

0 1 0 1 0 1

0 M0
S11 S21 S31
P1 M1

0 1 0 1 0 1

P2 M2
S12 S22 S32
P3 M3

0 1 0 1 0 1

P4 M4
S13 S23 S33
P5 M5

0 1 0 1 0 1

P6 M6
S14 S24 S34
P7 M7
Primera Segunda Tercera
etapa etapa etapa

Red de interconexiones de etapas múltiples

Figura 13.1 Redes de interconexiones.

Un interruptor cross-bar elimina el problema de disputa usando una organización de ma-


triz donde los CPU están ordenados a lo largo de una dimensión y las unidades de memoria, a
lo largo de la otra (véase la figura 13.1). Cada CPU y unidad de memoria tienen su propio bus
independiente. Cuando el CPU Ci desea acceder a una ubicación de palabra ubicada en la uni-
dad de memoria Mj, entonces el interruptor conecta el bus de Pi con el de Mj. En ese momento
la conversación entre CPU y memoria se lleva a cabo a través de ese bus. Es evidente que esta
conversación no sufre ninguna limitación debido a una conversación de algún otro par (de CPU
y memoria). La disputa sólo surge si dos o más CPU quieren conversar con la misma unidad de
memoria. El interruptor cross-bar es caro debido a su gran número de rutas de CPU-memoria.
Asimismo, sufre de bajas posibilidades de expansión.
Una red de interconexiones de etapas múltiples (MIN) es un compromiso entre un bus y
un interruptor cross-bar en términos de costo y paralelismo. Consiste en muchas etapas que

15 MAQ. CAP. 13(F0694).indd 579 8/10/07 1:16:27 AM


580 CAPÍTULO 13 Sincronización y planificación en sistemas operativos multiprocesador

contienen interruptores cross-bar 2 ⫻ 2. La conmutación en cada etapa es gobernada por un bit


en la dirección de la unidad de memoria accedida. El valor del bit, ya sea 0 o 1, conecta la entra-
da de un interruptor con diferentes interruptores en la siguiente etapa —decimos que selecciona
interruptores diferentes en la siguiente etapa— y así hasta llegar a un interruptor en la última
etapa, que selecciona una de dos unidades de memoria. De hecho, los bits de direcciones de
una unidad de memoria seleccionan una ruta entre un CPU y la unidad de memoria a la que
desean acceder. Muchas conversaciones entre CPU y memoria pueden llevarse a cabo en un
momento dado, siempre y cuando sus rutas en MIN no se crucen. Una red de interconexiones de
múltiples etapas se usa en el BBN Butterfly, que tiene una arquitectura NUMA.
La figura 13.1 muestra una red Omega 8 ⫻ 8. Una columna contiene interruptores corres-
pondientes a una etapa en la red de interconexiones. Para cada interruptor cross-bar 2 ⫻ 2, una
hilera representa un CPU y una columna representa el valor de un bit en la dirección binaria de
la unidad de memoria que va a ser accedida. Si un bit de dirección es 0, se selecciona la salida
superior del interruptor cross-bar. Si es 1, se selecciona la salida inferior. Estas salidas llevan a
interruptores en la siguiente etapa. Cuando los bits en la dirección de una memoria se enumeran
con el bit 0 como el bit más significativo, los interruptores en la etapa i conciernen al bit (i ⫺ 1)
de la dirección. El interruptor j en la etapa i es denotado por Sij.
Cuando el CPU C1 quiere acceder a la unidad de memoria M4, la interconexión toma lugar
como sigue: la dirección binaria de la unidad de memoria es 100. Por ende, se selecciona la
salida inferior del interruptor S11. Esto lleva a S22, cuya salida superior es seleccionada porque
el siguiente bit de dirección es 0. Esto lleva a S33, cuya entrada superior es seleccionada. Y esto
lleva a M4, como se deseaba. Los interruptores S13, S24 y S34 se seleccionarán si el CPU C4 desea
acceder a la unidad de memoria 7. La red de interconexiones usa 12 interruptores de 2 ⫻ 2. El
costo de éstos es mucho más bajo que el de un interruptor cross-bar de 8 ⫻ 8. En general, una
red de múltiples etapas N ⫻ N usa etapas log2N, donde cada etapa contiene –N2 interruptores de
2 ⫻ 2.
Otras redes de interconexión usan combinaciones de estas tres redes de interconexiones fun-
damentales. Por ejemplo, la interfaz coherente escalable (SCI) IEEE usa una red de base anular
que provee servicios de tipo bus, pero emplea ligas unidireccionales de punto a punto más rápi-
das a fin de proporcionar un desempeño mayor. Se usa un interruptor cross-bar para seleccionar
la liga unidireccional correcta conectada a un procesador.

13.1.1 Arquitectura SMP

La figura 13.2 muestra arquitecturas alternativas de sistemas SMP. En la figura 13.2a), los
CPU, la memoria y el subsistema de E/S están conectados al bus del sistema. Cada chip de CPU
contiene una caché de nivel 1 que cuenta con las últimas instrucciones y operandos a las que
accedió el CPU. Adicionalmente, un CPU podrá usar una caché de nivel 2 que es externa en rela-
ción con él. La memoria contiene una caché de nivel 3 que cuenta con las últimas instrucciones
y operandos que se recogieron de la memoria. Como hemos visto con anterioridad, únicamente
puede llevarse a cabo una sola conversación a través del bus en un momento dado y, por tanto,
éste podrá llegar a ser un cuello de botella y limitar el desempeño del sistema. Los CPU enfren-
tarán retrasos impredecibles mientras acceden a la memoria.

15 MAQ. CAP. 13(F0694).indd 580 8/10/07 1:16:28 AM


13.1 La arquitectura de sistemas multiprocesadores 581

M1 M2 M3 M4
L3 L3 L3 L3

CPU1
CPU1 CPU2 CPUn • • • •
L1
L1 L1 L1
CPU2
• • • •
L1
Caché L3 E/S
Memoria • • • •

E/S • • • •

a) b)

Figura 13.2 Arquitectura SMP.

La figura 13.2b) muestra un sistema que usa un interruptor cross-bar para conectar los
CPU y los subsistemas de E/S con las unidades de memoria. Los CPU y el subsistema de E/S
enfrentan menos retrasos en el acceso a la memoria, puesto que el interruptor cross-bar permite
que se realicen varias conversaciones en paralelo, siempre y cuando no estén en conflicto en sus
entidades de fuente o destino. Los retrasos en el interruptor también serán más predecibles
que en el caso del bus. El desempeño del sistema será mejor que cuando se use un bus.
Ignorando los retrasos en la red de interconexión, los tiempos efectivos de acceso a la me-
moria en ambas arquitecturas dependerán de la proporción de aciertos en las cachés L1, L2 y
L3, y del tiempo de acceso a la memoria. En ambas arquitecturas tiene que usarse un protocolo
de coherencia de cachés para asegurar que la existencia de los mismos datos en la caché de
más de un CPU no lleve a inconsistencias debido a condiciones de carrera. Considere la siguien-
te situación: un proceso que se ejecuta en CPU1 incrementa un ítem de dato d en 1. CPU1 carga a
d en su caché L1 y agrega 1. El nuevo valor de d existirá solamente en su caché. La memoria con-
tendrá el viejo valor de d. Si un proceso que se ejecuta en otro CPU desea actualizar a d, el CPU
podrá cargar el valor de d de la memoria a su propia caché y operar con él. Esto deberá evitarse.
El hardware deberá darse cuenta de que el valor de d existe en la caché L1 de CPU1, y obtenerlo
de allí en lugar de hacerlo de la memoria. El protocolo de coherencia de la caché aumentará el
costo de la arquitectura y también podrá reducir la velocidad de acceso a la memoria.
La escalabilidad de una arquitectura requiere que el desempeño de un sistema varíe en for-
ma lineal con el número de CPU en ella. El sistema que usa el bus como una red de interconexión
no es escalable, puesto que el bus se convertirá en un cuello de botella cuando se aumente el nú-
mero de CPU. Un sistema que usa el interruptor cross-bar será escalable con bajas densidades de
tráfico entre los CPU y la memoria. Sin embargo, la adición de un CPU requiere de la expansión
del interruptor cross-bar, cuyo costo no necesariamente será lineal con el número de CPU. En
todo caso, el aumento en los retrasos del sistema de la red de intercomunicaciones implica que el
sistema SMP no escala muy bien más allá de un pequeño número de CPU.

15 MAQ. CAP. 13(F0694).indd 581 8/10/07 1:16:28 AM


582 CAPÍTULO 13 Sincronización y planificación en sistemas operativos multiprocesador

13.1.2 Arquitectura NUMA

La figura 13.3 ilustra la arquitectura de un sistema NUMA. El rectángulo grande encierra un


nodo del sistema. Podrá consistir en un sistema de un solo CPU; sin embargo, es común usar
un sistema SMP como nodo de un sistema NUMA. Un nodo consiste en varios CPU, unidades
de memoria local y un subsistema de E/S conectado por medio de una red local de interconexio-
nes. También existe un puerto global en la red local de interconexiones. Los puertos globales de
todos los nodos están conectados con una red local de interconexiones capaz de proporcionar
velocidades de transferencia arriba de 1 G byte por segundo. Se usan para el tráfico entre los
CPU y unidades de memoria no locales. Un puerto global también podrá contener una caché para
guardar instrucciones y datos de memorias no locales accedidas por el CPU de un nodo. La red
global de intercomunicaciones que se muestra en la figura 13.1 se parece a la interfaz coherente
y escalable IEEE (SCI). Ésta usa una red con base anular que proporciona ligas rápidas unidirec-
cionales de punto a punto entre los nodos.

CPU CPU Puerto CPU CPU


Caché L1 Caché L1 global Caché L1 Caché L1

E/S
Red local de
intercomunicaciones
• Caché
remota
Caché
remota • Red local de
intercomunicaciones
E/S
Red
global de
Caché L3 Caché L3 interco- Caché L3 Caché L3
Memoria Memoria munica- Memoria Memoria
ciones
de alta
• Caché
remota
velocidad Caché
remota

Figura 13.3 Arquitectura NUMA.

Igual que en un sistema de SMP, el hardware de un sistema NUMA debe asegurar la co-
herencia entre cachés en los CPU de un nodo. También debe garantizar la coherencia entre los
cachés no locales. Este requerimiento puede reducir la velocidad de acceso a la memoria y con-
sumir parte del ancho de banda de las redes de interconexión.
Ignorando los retrasos en las redes de interconexiones locales y no locales, el tiempo efec-
tivo de acceso a la memoria dependerá de la proporción de aciertos en las cachés L1, L2 y L3, y
del tiempo de acceso a la memoria. El tiempo de acceso a una memoria no local dependerá de la
proporción de aciertos en las cachés L1, L2 y de la caché remota en el puerto global, así como
del tiempo de acceso a la memoria.
Los nodos de una arquitectura NUMA son normalmente SMP de alto rendimiento con 4 u 8
CPU. Debido a la red de interconexiones de alta velocidad, el rendimiento de estas arquitecturas
NUMA es escalable cuando se le agregan más nodos. El desempeño real de un sistema NUMA
dependerá de los accesos a la memoria no local realizados por procesos durante su ejecución.
Esto es un tema del SO que analizaremos en la siguiente sección.

15 MAQ. CAP. 13(F0694).indd 582 8/10/07 1:16:28 AM


13.2 Sistemas operativos multiprocesadores 583

13.2 SISTEMAS OPERATIVOS MULTIPROCESADORES

A fin de aprovechar las ventajas de alta capacidad de procesamiento y aceleramiento de cálculo


que ofrece un sistema multiprocesador, los CPU tienen que usarse en forma efectiva, y los pro-
cesos de una aplicación deberán ser capaces de interactuar de manera armoniosa. Es claro que
estas dos consideraciones tendrán un impacto sobre la planificación y sincronización de proce-
sos. También afectan los propios métodos del sistema operativo para funcionar en respuesta a
interrupciones y llamadas al sistema. La tabla 13.3 resalta los tres asuntos fundamentales que
se desprenden de estas consideraciones. En esta sección describiremos la importancia de tales
asuntos, y en las que siguen analizaremos sus detalles.

Tabla 13.3 Asuntos en la sincronización y planificación en un SO multiprocesador

Asunto Descripción
Estructura del kernel La ejecución de las funciones del kernel no deberá convertirse en un
cuello de botella. Muchos CPU deberán ser capaces de ejecutar el
código del kernel en forma concurrente.
Sincronización de procesos La presencia de múltiples CPU deberá dar como resultado la reduc-
ción de la carga general por la conmutación entre procesos y en la
reducción de retrasos de sincronización.
Planificación de procesos La política de planificación deberá explotar la presencia de múltiples
CPU para proporcionar el aceleramiento de cálculo para aplicaciones.
También deberá asegurar una alta proporción de aciertos de caché.

Los primeros sistemas operativos multiprocesadores funcionaban en el modo de maestro-


esclavo. En ese modo, se designa un CPU como maestro y todos los demás operan como sus es-
clavos. Sólo el CPU maestro ejecuta el código del kernel. Este CPU maneja interrupciones y
llamadas al sistema, y realiza la planificación. Comunica sus decisiones de planificación a otros
CPU por medio de interrupciones interprocesos (IPI). La ventaja más importante de la estruc-
tura maestro/esclavo del kernel es su sencillez. Su desventaja es que un proceso que hace una
llamada al sistema es retrasado hasta que se haya manejado la llamada al sistema. El CPU en el
que opera queda inactivo hasta que el proceso reanuda su operación o hasta que el CPU maestro
asigna nuevos trabajos al CPU. Las dos cosas solamente pueden suceder después de que el CPU
maestro haya manejado la llamada al sistema y ejecutado la planificación. Por ende, la ejecución
de las funciones del kernel es un cuello de botella, lo que afecta el desempeño del sistema. Este
problema puede resolverse cuando se estructura el kernel de tal modo que muchos CPU puedan
ejecutar su código en forma paralela.
Puede aprovecharse la presencia de múltiples CPU para reducir retrasos de sincronización
en un sistema multiprocesador. En uno monoprocesador, dejar que un proceso se quede en un
bucle hasta que se cumpla la condición de sincronización le niega el CPU a otros procesos y
podrá llevar a la inversión de prioridades (véase la sección 9.2.2). Por tanto, la sincronización
se realiza mediante el bloqueo de un proceso hasta que se cumpla su condición de sincroniza-
ción. Sin embargo, en un sistema multiprocesador, los procesos pueden ejecutarse en paralelo

15 MAQ. CAP. 13(F0694).indd 583 8/10/07 1:16:29 AM


584 CAPÍTULO 13 Sincronización y planificación en sistemas operativos multiprocesador

en los CPU, por lo que la sincronización por medio de la repetición no conduce a la inversión
de prioridades. Será preferible dejar un proceso en repetición en lugar de bloquearlo si la carga
general del CPU por bloquear el proceso y planificar otro proceso, seguido por la activación del
proceso y su nueva planificación, excede la cantidad de tiempo durante el cual el proceso estará
en repetición. Esta condición se cumplirá si un proceso que se repite para entrar en una sección
crítica y el dueño de la sección crítica están planificados en paralelo. Los sistemas operativos
multiprocesadores ofrecen técnicas de sincronización especiales para aprovechar esta caracte-
rística.
La planificación de procesos es influida por dos factores: el desempeño de las cachés
durante la operación de un proceso y los requerimientos de sincronización de los procesos
de una aplicación. Planificar un proceso cada vez en el mismo CPU puede llevar a una alta
proporción de aciertos en cachés, lo que mejorará el desempeño del proceso y también con-
tribuirá al mejor desempeño del sistema. Si los procesos de una aplicación interactúan con
frecuencia, su planificación en paralelo les dará oportunidad de interactuar en tiempo real, lo
que llevará a un aceleramiento de la aplicación. Por ejemplo, un productor y un consumidor
en un sistema de productores/consumidores de un solo buffer podrán realizar varios ciclos de
producción o consumo de registros en un intervalo de tiempo si se planifican para correr en
paralelo.
Analizaremos las técnicas de sincronización y planificación para sistemas multiprocesado-
res en las secciones 13.4 y 13.5. La sección 13.3 aborda la estructura del kernel.

13.3 ESTRUCTURA DEL KERNEL

Todos los CPU en un sistema SMP pueden ejecutar código en el kernel. La explotación de esta
característica requiere dos arreglos fundamentales:

• Todos los CPU deberán estar en condiciones para iniciar una operación de E/S en cual-
quier dispositivo del sistema.
• Un CPU deberá ser capaz de comunicarse con otros CPU del sistema.

El primer requerimiento puede satisfacerse mediante la introducción de un interruptor cross-


bar entre el CPU y el subsistema de E/S, o agregando una columna para el subsistema de E/S en
el interruptor cross-bar de la figura 13.2b). Las interrupciones de E/S son dirigidas al CPU que
inició una operación de E/S o a un procesador fijado en el hardware.
El kernel reserva un conjunto de áreas de comunicación en el área del kernel de la memoria
para la comunicación entre los CPU. Cada vez que un CPU C1 desea comunicarse con otro CPU
C2, coloca una información en el área de comunicación de C2 y levanta una interrupción inter-
proceso (IPI) en C2. El CPU C2 recoge esta información desde el área de comunicaciones y actúa
sobre ella. Este arreglo se usa cuando un CPU realiza la planificación.
Supongamos que los CPU C1 y C2 están ocupados con la ejecución de los procesos Pi y
Pj con las prioridades pri y prj, respectivamente, de tal modo que pri ⬎ prj. Entonces ocurre
una interrupción que es manejada por el CPU C1. La interrupción activa un proceso Pk, de
tal modo que pri ⬎ prk ⬎ prj. Esto conduce a una situación interesante. Cuando el CPU C1
ejecute la planificación, se dará cuenta de que Pi, el proceso que estuvo ejecutando antes de
la interrupción, sigue siendo el proceso de la prioridad más alta, y por tanto no hay cambio
en su propia carga de trabajo. Sin embargo, el proceso Pk tiene una prioridad más alta que el

15 MAQ. CAP. 13(F0694).indd 584 8/10/07 1:16:29 AM


13.3 Estructura del kernel 585

proceso Pj, que el CPU C2 estuvo ejecutando, por lo que el CPU C1 tiene que levantar un IPI
en el CPU C2 para indicar que su carga de trabajo cambió. El CPU C2 priorizará entonces a Pj
y empezará a ejecutar Pk, y el CPU C1 reanudará la ejecución de Pi que estuvo ejecutando antes
de la interrupción.

id de Trabajo
CPU asignado
L1 L2
C1 Pi Pi Cola de prioridad más alta
C2 Pj
Cola de prioridad menor
Pj
que la más alta

Tabla de carga de trabajo Cola de prioridad más baja


asignada (AWT)

Figura 13.4 Bloqueo de estructuras de datos en un kernel SMP.

La figura 13.4 ilustra estructuras de datos sencillas para el uso por parte de un kernel SMP.
La lista PCB es análoga a la que se usó en la sección 4.4.5. La única diferencia es que más de
un proceso podrá estar en estado running. El kernel mantiene una estructura de datos adicional
que se llama tabla de carga de trabajo asignada (AWT), en la que registra las cargas de trabajo
asignadas a varios CPU.

Ejemplo 13.1 La figura 13.4 muestra el contenido de la tabla AWT y la lista PCB cuando los CPU C1
y C2 ejecutan los procesos Pi y Pj, respectivamente. Tanto el estado de Pi como el de Pj se muestran
como en ejecución. La lista PCB contiene los PCB en orden descendente por prioridad de proceso.
El proceso Pk está actualmente en estado bloqueado. Cuando surge la interrupción que activa a Pk,
el CPU P1 cambia el estado de Pi a dispuesto, ya que Pi no está más en ejecución. Este CPU cam-
bia el estado de Pk, a dispuesto, cuando procesa la interrupción. Entonces realiza la planificación y se
da cuenta de que la carga de trabajo de C2 debe cambiar. Por consiguiente, pone el estado de Pk en el
área de comunicaciones y envía un IPI a C2.
Cuando C2 recibe el IPI, detiene la ejecución del proceso Pj y registra su estado en el área de
comunicaciones. Entonces carga el estado de Pk, desde el área de comunicaciones, envía un IPI a
C1 y empieza la ejecución de Pk. Cuando C1 recibe el IPI, cambia los estados de Pk y Pj a en eje-
cución y dispuesto, respectivamente, mueve el estado almacenado por C2 al PCB de Pj y cambia
la carga de trabajo de C2 a Pk en la tabla AWT.

El kernel de SMP Puesto que muchos CPU pueden ejecutar código del kernel de SMP
en forma paralela, su código tiene que ser reentrante (véase la sección 5.11.3.2). Por tanto,
es esencial asegurar la exclusión mutua sobre estructuras de datos del kernel mediante el uso
de semáforos binarios (véase la sección 9.8). Nos referiremos a ellos como candados mutex.
La granularidad de bloqueos influye en el desempeño de sistemas de manera obvia. Si un solo
candado controla todas las estructuras de datos del kernel, únicamente un procesador podrá usar
las estructuras de datos en un momento dado. Si candados separados controlan estructuras de

15 MAQ. CAP. 13(F0694).indd 585 8/10/07 1:16:29 AM


586 CAPÍTULO 13 Sincronización y planificación en sistemas operativos multiprocesador

datos individuales, los procesadores podrán acceder a diferentes estructuras de datos en paralelo.
Sin embargo, debe tenerse cuidado de que no surjan bloqueos mutuos cuando el kernel necesita
acceder a más de una estructura de datos.
Como mencionamos en la sección 11.8, puede usarse la jerarquización de recursos para
prevenir bloqueos mutuos cuando varios procesadores quieren acceder a estructuras de datos
de planificación del kernel. Como se muestra en la figura 13.4, las estructuras de datos de
las listas AWT y PCB están protegidas mediante los candados L1 y L2, respectivamente. Un
procesador que desea realizar una planificación intentará poner estos candados en el orden L2
seguido por L1.
Un kernel de SMP ofrece la degradación elegante porque sigue operando a pesar de fallas,
aunque su eficiencia podrá verse afectada. Por ejemplo, la falla de un procesador cuando no
está ejecutando código del kernel no interfiere con la operación de otros procesadores en el sis-
tema, por lo que continuarán su ejecución en forma normal. La indisponibilidad del procesador
averiado afectará el proceso que estaba ejecutando en él cuando ocurrió la falla. También lo hará
hasta cierto grado la capacidad de procesamiento y los tiempos de respuesta del sistema.

El kernel NUMA En un sistema NUMA, los CPU experimentan diferentes tiempos de


acceso a la memoria para memorias locales y no locales, por lo que un proceso que se ejecuta en
un CPU debe hacer uso predominante de unidades de memoria locales. Asimismo, cada nodo
en el sistema debe tener su propio kernel que planifica procesos que existen en memorias loca-
les en los CPU dentro del nodo.
Históricamente, este arreglo se llama kernel separado. El sistema está dividido en varios
dominios, y un kernel separado administra cada dominio. En un sistema NUMA, el uso de un
kernel separado para cada nodo asegura que los procesos experimenten cortos tiempos de acceso
a la memoria, ya que la mayoría de sus accesos son a memorias locales. El kernel deberá planifi-
car un proceso todo el tiempo en el mismo CPU. Esto asegurará el buen desempeño del proceso
y contribuirá al buen desempeño del sistema, garantizando altas proporciones de aciertos en la
caché del CPU, es decir, en la caché L1. Buenas proporciones de aciertos en la caché L3 serán
resultado de que la memoria asignada a un proceso exista en una sola unidad de memoria local.
El kernel de un nodo puede asegurar el buen desempeño de una aplicación asignando la
memoria a todos sus procesos en la misma unidad de memoria y dedicando unos cuantos CPU
a su ejecución. La noción de una región de aplicaciones incorpora esta idea. Consiste en una
partición de recursos y una instancia del kernel. La primera contiene uno o varios CPU, unas uni-
dades de memoria y unos dispositivos de E/S. El kernel de la región de aplicaciones solamente
ejecuta procesos de una aplicación. La ventaja de este arreglo es que el kernel puede optimizar
el desempeño de la aplicación por medio de una planificación inteligente y de una alta pro-
porción de aciertos en caché. Esto puede llevarse a cabo sin interferencia de procesos de otras
aplicaciones. Los sistemas operativos para la mayoría de los sistemas NUMA ofrecen estas ca-
racterísticas o sus equivalentes.
El uso de un kernel separado para un nodo de un sistema NUMA o para una región de apli-
caciones también tiene algunas desventajas. Los accesos a memorias no locales se hacen más
complejos, puesto que abarcan los dominios de más de un kernel. El arreglo del kernel separado
también sufre de los problemas genéricos asociados a la creación de particiones; podrá resultar
una infrautilización de recursos porque los recursos inactivos de una partición no pueden ser usa-

15 MAQ. CAP. 13(F0694).indd 586 8/10/07 1:16:29 AM


13.4 Sincronización de procesos 587

dos por procesos de otras particiones. La confiabilidad también es mala porque un cálculo tiene
que ser cancelado o retrasado si falla un recurso (incluido un CPU) en una partición.

13.4 SINCRONIZACIÓN DE PROCESOS

Un proceso que llega a un punto de sincronización de datos o de control tiene que esperar si otro
está ocupado con el acceso a datos compartidos, o si otro más aún no envía la señal de control
necesaria. En un SO convencional, este tipo de proceso es priorizado. Lo anterior se hace para
que otro proceso pueda ejecutar en el CPU y liberar los datos compartidos, o enviar una señal de
control que activará al proceso bloqueado.
Los sistemas operativos multiprocesadores usan un planteamiento radicalmente distinto
para la sincronización de procesos. Puesto que en el sistema existen muchos CPU, no es ne-
cesario priorizar un proceso que no puede pasar por un punto de sincronización de datos o de
control. Los procesos que se ejecutan en otros CPU del sistema pueden liberar datos compartidos
o enviar la señal de control necesaria. Bajo ciertas condiciones, puede entonces permitirse que
un CPU se quede con un proceso que está esperando en un punto de sincronización de datos o
de control.
La sincronización de procesos implica el uso de secciones críticas o de operaciones de se-
ñalización indivisibles. Como ya se analizó en la sección 9.4, cada una de ellas se implementa
usando una variable de candado que sólo puede asumir dos valores: abierto y cerrado. Si un
proceso que quiere ejecutar una sección crítica se da cuenta de que el valor de la variable de
candado es abierto, lo cambia a cerrado, ejecuta la sección crítica u operación de señalización
indivisible y vuelve a cambiar el valor a abierto. Un proceso que se da cuenta de que el valor
de una variable de candado es cerrado debe esperar hasta que el valor sea cambiado a abierto.
Nos referimos a este arreglo que involucra el uso de una variable de candado como candado de
sincronización, o simplemente candado.
La escalabilidad de un candado de sincronización implica que el desempeño de una aplica-
ción que usa el candado de sincronización deberá ser independiente del número de procesos en
la aplicación y del número de CPU que haya en el sistema. Otras características de un candado
de sincronización incluyen la de si un CPU puede manejar interrupciones mientras el proceso
que según la planificación deberá ejecutar en él está ocupado tratando de colocar un candado de
sincronización.
La figura 13.5 ilustra el uso de los tres candados de sincronización. La figura 13.5a) muestra
un proceso Pi que se ejecuta en el CPU Cj y un candado L que se usa para vigilar una región de
exclusión mutua. El símbolo “⫻“ dentro del casillero que representa el candado indica que éste
se encuentra puesto. Un símbolo parecido dentro de un círculo que representa un proceso indica
que el proceso está bloqueado.

Candado en cola de espera Un candado en cola de espera es un candado convencional


que se usa para la sincronización de procesos. El kernel realiza las siguientes acciones cuando el
proceso Pi que se ejecuta en el CPU Cj solicita un candado L: se verifica el candado L. Si todavía
no se ha puesto, el kernel lo pone en representación de Pi y reanuda su ejecución. Si el candado
ya fue colocado por otro proceso Pi, se prioriza y su solicitud del candado se registra en una cola
de espera. Entonces otro proceso queda planificado para ejecutarse en el CPU Cj.

15 MAQ. CAP. 13(F0694).indd 587 8/10/07 1:16:29 AM


588 CAPÍTULO 13 Sincronización y planificación en sistemas operativos multiprocesador

Pi Pk Pi Pi

C1 C1 C1 C1
IPI

L L L L

Pi

a) b) c) d)

Figura 13.5 Candados en cola, candados en bucles (candado circular) y candados


latentes (sleep locks) en sistemas operativos multiprocesadores.

La figura 13.5b) ilustra la situación existente después de la priorización. La id de Pi ingresa


en la cola de espera del candado L y el CPU Cj conmuta a la ejecución de algún otro proceso.
Cuando el proceso que ha puesto el candado L termina el uso del proceso de sección crítica, el
proceso a la cabeza de la cola de L es activado y se le concede el candado.
Un proceso que no puede poner un candado en cola renuncia al CPU en el cual se está
ejecutando. Ese proceso no usa un CPU y no accede a la memoria mientras espera para
poner el candado. La longitud de promedio de una cola para un candado determina si la solu-
ción es escalable. Si los procesos no requieren el candado L con frecuencia, la longitud de la
cola está acotada por la constante c (es decir, nunca es más grande que c), por lo que incremen-
tar el número de CPU o procesos en el sistema no aumenta el retraso promedio de adquisición
del candado. La solución es escalable bajo estas condiciones. Si los procesos requieren candados
L a menudo, la longitud de la cola de espera podrá ser proporcional al número de procesos. En
este caso la solución no es escalable.

Candado en bucle (candado circular) Un candado circular se distingue de un candado en


cola en que un proceso que hace un intento fallido de poner un candado no renuncia al CPU
en el cual se está ejecutando. En su lugar, entra en un bucle donde hace repetidos intentos de co-
locar el candado hasta tener éxito (véase la figura 13.5c)). De allí el nombre de candado circular.
Representamos una situación donde el CPU Cj da vueltas en el candado L con el dibujo de una
flecha desde Cj hasta L. ¡Tenemos entonces una situación de espera activa que un SO convencio-
nal trata de evitar a toda costa! El CPU Cj en repetidas ocasiones accede al valor del candado y
lo prueba, usando una instrucción indivisible, como la instrucción Test-and-Set (véase la sección
9.8.4). Esta acción crea tráfico en el bus de la memoria o en toda la red.
El uso de candado circular podrá degradar el desempeño del sistema de dos maneras: pri-
mero, el CPU permanece con el proceso dando vueltas al candado circular, de tal modo que a
otros procesos se les niega el uso del CPU. Segundo, se genera tráfico de memoria mientras el
CPU está girando en un bucle alrededor del candado. Ese último inconveniente posiblemente no
sea significativo si el bus de la memoria o la red sólo tienen una carga ligera, pero causará una
degradación del desempeño en otras situaciones.

15 MAQ. CAP. 13(F0694).indd 588 8/10/07 1:16:30 AM


13.4 Sincronización de procesos 589

El uso de candado circular puede ser justificado en dos situaciones: cuando el número de
procesos no excede el número de CPU en el sistema, no hay ninguna ventaja en la priorización
de un proceso. Asimismo, cuando un candado debe usarse para controlar una sección crítica y el
tiempo del CPU que se necesita para ejecutar la sección crítica es menor que el del CPU necesa-
rio para priorizar un proceso y planificar otro. En el primer caso, la priorización es innecesaria.
En el segundo, resulta contraproducente.
El uso de un candado circular tiene una interesante ventaja sobre el empleo de un candado
en cola de espera. Un CPU que da vueltas en un candado puede manejar interrupciones, y el
proceso que se ejecuta en él puede manejar señales. Esta característica es particularmente im-
portante en una aplicación de tiempo real, ya que retrasos en el procesamiento de interrupciones
y señales pueden degradar los tiempos de respuesta. No obstante, los candados circulares no
son escalables debido al tráfico de memoria y de red que generan.
En un sistema NUMA, un proceso que usa candado circular podrá enfrentar una situación
que se llama inanición de candados, en la que se le podrá negar el candado durante largos perio-
dos de tiempo, posiblemente por tiempo indefinido. Considere un proceso Pi que trata de poner
un candado circular que se encuentra en su memoria no local. Supongamos que los proce-
sos Pj y Pk, que existen en el mismo nodo que el candado traten de colocarlo. Puesto que el
acceso a la memoria local es mucho más rápido que el usado para la memoria no local, los
procesos Pj y Pk giran mucho más rápidamente en el candado que el proceso Pi. Por tanto,
es probable que tengan una oportunidad para colocar el candado antes de Pi. Si ellos colocan
y usan el candado repetidamente, es posible que Pi no sea capaz de colocar el candado durante
mucho tiempo. El esquema en la sección 13.4.2 evita la inanición de candados.

Candado latente (sleep lock) Cuando un proceso hace un intento fallido de poner un can-
dado latente, su CPU se pone en un estado especial llamado así, latente. En ese estado no ejecuta
instrucciones y no responde a interrupciones, con excepción de interrupciones interproceso. En
la figura 13.5d) presentamos esta situación. Ponemos un símbolo “⫻“ en todas las interrupcio-
nes, excepto en IPI. El CPU que espera el candado no da vueltas sobre él y entonces no causa
tráfico de memoria o de red.
El CPU que libera el candado tiene la responsabilidad de enviar interrupciones interproceso
a aquellos CPU que están durmiendo en el candado. Ese requerimiento lleva a la carga gene-
ral a generar y procesar interrupciones interproceso, involucrando una conmutación de contexto
y ejecución de código del kernel. El candado latente escalará mal si existe una competencia
pesada para un candado; sin embargo, se desempeñará bien si existe poca competencia para un
candado. El uso de candados latentes en aplicaciones de tiempo real también puede afectar los
tiempos de respuesta de la aplicación. No obstante, se podrán preferir los candados latentes si las
densidades del tráfico de la memoria o de la red son altas.

Sincronización consciente de la planificación Como hemos visto antes, algunos tipos de


sincronización sólo son efectivos cuando los procesos involucrados en la sincronización están
planificados para funcionar en paralelo. El SO Solaris para sistemas SUN ofrece un candado
de sincronización que se llama candado adaptable. Un proceso en espera de su candado da
vueltas sobre él si el dueño del candado está planificado para correr en paralelo; de no ser así,
el proceso es priorizado y se pone en la cola como un candado en cola de espera. El kernel
implementa el candado verificando si el dueño de éste se encuentra en ese momento en estado
de ejecución.

15 MAQ. CAP. 13(F0694).indd 589 8/10/07 1:16:30 AM


590 CAPÍTULO 13 Sincronización y planificación en sistemas operativos multiprocesador

13.4.1 Hardware especial para la sincronización de procesos

Algunos sistemas usan dispositivos de hardware especiales para evitar problemas de desempeño
causados por candados en cola, candado circular y candados latentes. Analizaremos un bus
especial llamado Controlador de Ligas e Interfaces de Sistema (SLIC) que se usa para la sincro-
nización en el sistema Sequent Balance.

Bus SLIC

Procesador 1 Procesador 2 Registro


SLIC

Bus de memoria

Figura 13.6 Bus SLIC.

El SLIC consiste en un registro especial de 64 bits en cada CPU del sistema. Los registros
de los CPU diferentes están conectados a través del bus SLIC (véase la figura 13.6). Cada bit
representa un candado circular. SLIC puede entonces admitir 64 candados. Cuando un CPU C1
quiere poner un candado Lk, trata de colocar el bit correspondiente, digamos bk, en su registro
especial. Este intento falla si el bit ya fue colocado por otro CPU. En este caso, el CPU sigue
dando vueltas en este candado, es decir, en el bit bk de su registro especial. Si el bit todavía no
está colocado, un intento de hacerlo da como resultado una comunicación a través del bus SLIC.
Si no hay ningún otro CPU que esté simultáneamente tratando de colocar el mismo bit, el can-
dado se otorga a C1 y el bit bk es colocado en los registros especiales de todos los CPU. Ci puede
ahora proceder a su ejecución. Cuando libera el candado, se reinicializa el bit bk en los registros
especiales de todos los CPU. Si dos o más CPU tratan simultáneamente de colocar el mismo
candado, el árbitro de hardware lo otorga a un CPU.
La ventaja del planteamiento SLIC es que un CPU da vueltas sobre un candado local, por lo
que el movimiento no genera memorias fantasmas o tráfico de la red. El uso del candado que da
vueltas en lugar del candado durmiente también evita el uso de interrupciones interproceso para
la sincronización. El empleo de un bus especial de sincronización alivia la presión sobre el bus de
memoria. Esto es una ventaja significativa cuando la densidad de tráfico de la memoria es alta.

13.4.2 Un esquema escalable para la sincronización de procesos

Describimos una solución eficiente para la sincronización de procesos en la arquitectura NUMA


y NORMA que no requiere ningún hardware especial y proporciona un efecto que es análogo
al chip SLIC. También evita el problema de inanición de los candados circulares. Las carac-
terísticas sobresalientes de esta solución son las siguientes: un candado principal es como un
candado convencional que se usa para la sincronización. Un CPU crea un candado sombra en su
memoria local para un candado principal que es incapaz de colocarse. Este CPU da vueltas sobre
el candado sombra hasta que pueda obtener el candado primario.

15 MAQ. CAP. 13(F0694).indd 590 8/10/07 1:16:30 AM


13.5 Planificación de procesos 591

Un CPU prueba un candado principal sólo una vez cuando quiere ponerlo. Si no puede
colocar el candado, da vueltas sobre su propio candado sombra. De esta manera, los giros no ge-
neran tráfico en memoria y en red. Cuando un CPU que había puesto el candado principal desea
reiniciarlo, tiene que habilitar un CPU que está dando vueltas sobre un candado sombra. Esto lo
logra reiniciando el candado sombra del CPU.

Puntero de dirección
Cola para un
candado principal
Candado
sombra Memoria local
del procesador Pj

Pj

pi

Figura 13.7 Una solución de software eficiente para la sincronización de procesos.

La figura 13.7 ilustra una implementación de este esquema. Se mantiene una cola de can-
dados sombra para cada candado principal. Cada entrada en la cola contiene la dirección de un
candado sombra y un puntero dirigido hacia el siguiente candado sombra en la cola de espera.
Un CPU que desea colocar un candado trata de colocar el candado principal. Este paso podrá
generar algo de tráfico de memoria o de red, puesto que el candado principal posiblemente no
sea local para el CPU solicitante. Si este intento falla, el CPU asigna un candado sombra a su
propia memoria, entra su dirección en la cola de espera del candado principal y empieza a dar
vueltas sobre él. La cola de espera podrá abarcar diferentes unidades de memoria en el sistema.
Por tanto, el paso de entrar el candado sombra en la cola de espera genera tráfico de memoria
o de red. El CPU da vueltas sobre su candado sombra hasta que el candado es reinicializado por
un CPU que completa el uso que hace del candado principal. Reinicializar un candado sombra
también genera tráfico de memoria o de red. Sobra decir que la propia manipulación de la cola
de espera deberá efectuarse bajo un candado.

13.5 PLANIFICACIÓN DE PROCESOS

Un proceso puede ejecutarse en cualquier CPU de un sistema multiprocesador. Sin embargo,


puede mejorarse su desempeño de ejecución mediante una selección inteligente del CPU para
ejecutarlo, es decir, por la decisión de dónde ejecutarlo. El desempeño de ejecución de un grupo
de procesos que se sincronizan y comunican entre sí puede mejorarse mediante la decisión de
cómo y cuándo ejecutar los procesos. La presente sección analiza las cuestiones involucradas en
la toma de estas decisiones.

Selección del CPU Cuando un proceso Pi opera en un CPU, digamos el CPU C1, se cargan
algunas partes de su espacio de direcciones a la caché L1 del CPU. Cuando éste es conmutado

15 MAQ. CAP. 13(F0694).indd 591 8/10/07 1:16:31 AM


592 CAPÍTULO 13 Sincronización y planificación en sistemas operativos multiprocesador

a la ejecución de otro proceso, algunas de estas partes se sobrescriben con partes del espacio
de direcciones del nuevo proceso, pero otras partes del espacio de direcciones podrán sobrevivir
durante un tiempo en la memoria caché de C1. Éstas se llaman espacio de direcciones residua-
les de un proceso. Se dice que un proceso tiene una afinidad para un CPU si cuenta con un
espacio de direcciones residuales en su caché. El proceso tendrá una proporción de aciertos de
caché más alta en este CPU que en uno con el cual no tiene afinidad.
La planeación basada en afinidad planifica un proceso en un CPU para el cual tiene una
afinidad. Esta técnica ofrece una buena proporción de aciertos de caché, acelera de este modo
la operación del proceso y reduce el tráfico del bus de memoria. Otra manera de aprovechar la
afinidad es la de planificar los hilos de un proceso en el mismo CPU en estrecha sucesión. Sin
embargo, la planeación basada en afinidad interfiere con el equilibrio de carga por todos los
CPU, puesto que procesos e hilos se vinculan con CPU específicos. La sección 13.6.3 describe
cómo esto también lleva a anomalías de planificación en el sistema Windows.
En la sección 13.3 hemos analizado cómo el kernel de SMP permite que cada CPU realice
su propia planificación. Este arreglo impide que el kernel se convierta en un cuello de botella
del desempeño; sin embargo, conduce a anomalías de planificación donde un proceso de mayor
prioridad está en estado dispuesto, aunque se ha planificado un proceso de menor prioridad.
La corrección de esa anomalía requiere barajar un proceso entre los CPU, como se indica en el
siguiente ejemplo.

Ejemplo 13.2 Un sistema SMP contiene dos CPU C1 y C2, y tres procesos Pi, Pj y Pk con las priori-
dades 8, 6 y 5, respectivamente. La figura 13.8a) muestra una situación donde el proceso Pi está en
estado bloqueado debido a una operación de E/S y los procesos Pj y Pk están en operación, usando
los CPU C1 y C2, respectivamente. Cuando finaliza la operación de E/S de Pi, la interrupción de
E/S es procesada por el CPU C1, que cambia el estado de Pi a dispuesto y se conmuta a sí mismo
para dar servicio al proceso Pi. De este modo, el proceso Pj, es decir, el proceso con la siguiente
prioridad más alta, está en estado dispuesto, y Pk, cuya prioridad es la más baja, está en operación.
Para corregir esta situación, el proceso Pk deberá priorizarse y el proceso Pj deberá planificarse en
el CPU C2. La figura 13.8b) muestra la situación después de estas acciones.

C1 C2 C1 C2

Pi Pj Pk Pi Pj Pk

Pi Pj Pk Pi Pj Pk
8 6 5 8 6 5
bloqueado activo activo activo activo dispuesto

a) b)

Figura 13.8 El proceso Pj es movido del CPU C1 al CPU C2 cuando el proceso


Pi se vuelve dispuesto.

15 MAQ. CAP. 13(F0694).indd 592 8/10/07 1:16:31 AM


13.6 Estudio de caso real 593

Barajar procesos puede implementarse usando la tabla de carga de trabajo asignada (AWT),
que fue analizada en la sección 13.3, y la interrupción interproceso (IPI). Sin embargo, lleva a
una alta carga general de planificación; este efecto es aún más pronunciado en un sistema que
contiene un gran número de CPU. Es por eso que los sistemas operativos no corrigen las anoma-
lías de planificación al barajar procesos.

La planificación consciente de la sincronización Se podrán ejecutar partes de un cálculo


en diferentes CPU para lograr una aceleración del cálculo. Sin embargo, la sincronización y co-
municación entre los procesos de una aplicación influyen en la naturaleza del paralelismo entre
sus procesos, por lo que una política de planificación deberá tomarlo en cuenta. Como hemos
comentado en la sección 13.2, los procesos de una aplicación deberán planificarse en diferentes
CPU al mismo tiempo, si usan candado circular para la sincronización. Esto se llama plani-
ficación en conjunto o planificación en banda. Se requiere un planteamiento distinto cuando pro-
cesos intercambian mensajes usando un protocolo de bloqueo. Cuando Pi envía un mensaje a Pj,
sólo puede continuar con su cálculo luego de que se entregó su mensaje. Puesto que esto podrá
implicar una larga espera, es mejor bloquear a Pi. En estos casos se hacen esfuerzos muy grandes
para no planificar estos procesos en el mismo intervalo de tiempo. Puesto que este planteamiento
está en conflicto con la planeación en conjunto, el kernel tiene que tomar una decisión difícil.
Puede basar su decisión sobre el comportamiento pasado de procesos en esta aplicación o sobre
la preferencia de usuarios para un método de planificación específico.

13.6 ESTUDIO DE CASO REAL

13.6.1 El sistema operativo Mach

El sistema operativo Mach, desarrollado en la Universidad Carnegie Mellon, es un SO para


sistemas multiprocesadores y sistemas distribuidos. El multiprocesador Mach usa una estructu-
ra de kernel SMP.
La figura 13.9 muestra una visión general del arreglo de planificación de procesadores que
se usa en Mach. Los procesadores de un multiprocesador están divididos en conjuntos de pro-
cesadores. A cada conjunto de procesadores se asigna un subconjunto de hilos para su ejecu-
ción. Los hilos pueden tener prioridades entre 0 y 31, donde 0 es la más alta. Cada conjunto de
procesadores tiene 32 colas de espera tipo dispuesto para guardar informaciones sobre hilos en
cada uno de los niveles de prioridad. Estas colas son comunes para todos los procesadores del
conjunto de procesadores. Además, cada uno tiene una cola local de hilos. Éstos son los hilos que
únicamente deben ejecutarse en este procesador. Ellos tienen una prioridad más alta que todos
los hilos en las colas de hilos. Esta característica permite la planificación basada en la afinidad.
Sólo se prioriza un hilo al final de una rebanada de tiempo si existe otro en las colas de hilos
dispuestos; de no ser así, se le da a este hilo otro intervalo de tiempo. El intervalo de tiempo varía
de acuerdo con el número de hilos dispuestos; se usa un intervalo más pequeño si existen muchos
hilos dispuestos, y una más grande si existen pocos hilos dispuestos.
Una característica interesante en el sistema operativo Mach es la noción de consejos de pla-
nificación. Un hilo usa un consejo para influir en las decisiones de planificación del procesador.
Se supone que un consejo está basado en el conocimiento que tiene el hilo acerca de algunas

15 MAQ. CAP. 13(F0694).indd 593 8/10/07 1:16:31 AM


594 CAPÍTULO 13 Sincronización y planificación en sistemas operativos multiprocesador

0 0
1 1
Subconjunto .. ..
de hilos . .

31 31

P1
P4
P2 Colas locales
de hilos
P5
P3

Conjunto de Conjunto de
procesadores procesadores

Figura 13.9 Planificación en Mach.

características de ejecución de una aplicación. Un hilo podrá usar un consejo para asegurar una
mejor planificación cuando los hilos de una aplicación necesitan usar la sincronización o la co-
municación. Un consejo de desaliento reduce la prioridad de un hilo; lo usará un hilo que tiene
que dar vueltas sobre un candado que fue colocado por otro proceso. Un hilo da un consejo de
no intervención para indicar que quiere renunciar al procesador a favor de otro hilo. También
puede indicar la id de un hilo al que desea pasar el procesador. Al recibir un consejo de ese
tipo, el planificador conmuta el proceso a la ejecución del hilo nombrado, independientemente
de su prioridad. Esta característica puede usarse de manera efectiva cuando un hilo da vueltas
sobre un candado y el dueño de éste está siendo priorizado. El hilo que da vueltas puede pasar
su proceso al hilo priorizado. Esta acción acelerará su ejecución y llevará a una liberación del
candado.

13.6.2 Linux

El soporte multiprocesador en Linux fue introducido en el kernel de Linux 2.0. El bloqueo por
medio de la granularidad gruesa fue empleado para prevenir condiciones de carrera sobre estruc-
turas del kernel. La granularidad del bloqueo se hizo más fina en las versiones posteriores; sin
embargo, estas estructuras eran aún no priorizables. A partir de Linux 2.6, el kernel de Linux se
hizo priorizable (véase la sección 14.10) y emplea también el bloqueo de muy fina granularidad.

15 MAQ. CAP. 13(F0694).indd 594 8/10/07 1:16:31 AM


13.6 Estudio de caso real 595

El kernel de Linux proporciona candado circular para el bloqueo de estructuras de datos.


Asimismo, proporciona un candado circular especial de lector/escritor que permitirá cualquier
cantidad de procesos —es decir, procesos que no modifican datos del kernel— para acceder a
datos detectados al mismo tiempo; sin embargo, permite que sólo un proceso de escritor actua-
lice los datos al mismo tiempo.
El kernel de Linux usa un candado distinto que se llama candado de secuencia que incurre
en una baja carga general y es escalable. El candado de secuencia es realmente un entero que se
usa como un contador de secuencias por medio de una instrucción de incrementos atómica, es
decir, indivisible. Cada vez que un proceso desea usar una estructura de datos del kernel, simple-
mente incrementa el entero en el candado de secuencia asociado con la estructura de datos, anota
su nuevo valor y realiza la operación. Después de completar la operación, verifica si el valor en
el candado de secuencia ha cambiado. Si ése es el caso, la operación se considera fracasada, por
lo que anula la operación que acaba de ejecutar y la intenta otra vez, repitiendo el procedimiento
hasta que la operación tenga éxito.
Linux usa estructuras de datos por CPU para reducir la competencia por candados en estruc-
turas de datos del kernel. Como se mencionó en la sección 13.3, sólo se accede a una estructura
de datos por CPU de un CPU cuando ese mismo CPU ejecuta el código del kernel; sin embargo,
incluso esta estructura de datos necesita bloquearse porque es posible que se hagan accesos
concurrentes a ella cuando una interrupción activa una rutina de servicio a interrupciones, mien-
tras que se estaba ejecutando el código del kernel para dar servicio a una llamada de sistema.
Linux elimina este candado deshabilitando la priorización de este CPU debido a interrupciones:
el código ejecutado por el CPU hace una llamada al sistema cuando está a punto de acceder a
las estructuras de datos por CPU, y realiza otra al sistema para habilitar la priorización cuando
termina su acceso a las estructuras de datos por CPU.
La planificación para un multiprocesador comprende consideraciones de afinidad; un usua-
rio puede especificar una afinidad dura para un proceso indicando un conjunto de procesadores
en los que tiene que operar, y un proceso tiene una afinidad suave para el último procesador en
el cual se operaba. Puesto que la planificación se realiza basándose en la noción de “por
CPU”, el kernel efectúa el equilibrio de carga para asegurar que las cargas computacionales
dirigidas hacia diferentes CPU sean comparables. Esta tarea la realiza un CPU que se da cuenta
de que sus colas disponibles están vacías; también lo hace periódicamente el kernel cada 1 mseg
si el sistema está inactivo, y cada 200 mseg de no ser así.
La función load_balance es invocada para realizar el equilibrio de carga con la id de un
CPU no cargado a capacidad. load_balance busca un “CPU ocupado” que tiene por lo menos
25 por ciento menos procesos en sus colas de dispuestos que las colas de dispuestos del CPU no
cargado a capacidad. Entonces localiza algunos procesos en sus colas de espera de dispuestos
y los mueve a las colas del CPU no cargado a capacidad. Para ello procede de la siguiente ma-
nera: primero mueve los procesos de mayor prioridad en la lista de agotados del CPU ocupado,
porque no es probable que estos procesos tengan una afinidad suave con el CPU ocupado. Si se
tienen que mover más procesos, entonces mueve los procesos de mayor prioridad en la lista de
activos del CPU ocupado.

13.6.3 Soporte de SMP en Windows

La política de planificación de Windows incorpora la planificación de afinidad, lo que ayuda a


lograr un buen desempeño de acceso a la memoria para un hilo, utilizando su espacio de direc-

15 MAQ. CAP. 13(F0694).indd 595 8/10/07 1:16:31 AM


596 CAPÍTULO 13 Sincronización y planificación en sistemas operativos multiprocesador

ciones residuales guardado en la caché de un procesador. El atributo afinidad de procesador


de hilos de un objeto de hilo, en conjunto con el atributo afinidad de procesador de default del
objeto de proceso, del proceso que contiene los hilos, define un conjunto de afinidades para un
hilo. Si este conjunto de afinidades es non-null, un hilo siempre se ejecuta en un procesador del
conjunto de afinidades. Esto es la planificación basada en afinidad dura. Si el conjunto de afini-
dades de un hilo es null, el kernel usa la planificación basada en afinidad suave, donde un hilo es
planificado en el mismo procesador en el cual fue ejecutado la última vez.
La planificación basada en afinidad dura a veces conduce a un comportamiento anómalo.
Considere n hilos que ejecutan en n procesadores. Supongamos que un hilo Ti hace una transi-
ción al estado dispuesto debido a una interrupción de E/S, y que la prioridad de ese hilo sea más
alta que las prioridades de algunos hilos de estado en ejecución. El hilo Ti podrá ser forzado a
esperar si el procesador con el cual tiene una afinidad dura está ocupado con la ejecución de un
hilo cuya prioridad excede a la prioridad de hilo Ti. En realidad, Ti se podrá haber planificado
en otro procesador, especialmente si se trata de un hilo de tiempo real.
Otra característica interesante del soporte SMP en Windows es que reserva un procesador
para planificar todas las tareas, excepto las que se ejecutan en otros procesos. En efecto, en un
sistema de n procesadores, n ⫺ 1 procesadores ejecutan los hilos n ⫺ 1 de la más alta prioridad,
mientras que el n-ésimo procesador ejecuta todos los demás hilos.
Estos hilos usan candado circular para implementar la exclusión mutua mientras acceden
a estructuras de datos del kernel. A fin de garantizar que estructuras de datos del kernel no per-
manezcan en bloqueo durante un periodo extenso de tiempo, el kernel nunca prioriza un hilo
que guarda un candado circular si otro hilo está tratando de adquirir el candado circular. De
este modo, el hilo que guarda el candado puede terminar su sección crítica lo más pronto
posible.

EJERCICIO 13
1. Escriba una nota sobre la sincronización de procesadores que ejecutan código de un kernel SMP en
forma paralela. También analice la conveniencia de varios tipos de candados para satisfacer estos re-
querimientos de sincronización.
2. Describa dos situaciones en las que un kernel SMP requiere el uso de la interrupción interproceso
(IPI).
3. Analice si la característica de no intervención de Mach puede usarse con provecho implementando la
solución de software para la sincronización de procesos que analizamos en la sección 13.4.2.
4. Un SO asigna la misma prioridad a todos los procesos/hilos de una aplicación. Comente acerca de la
validez de las siguientes declaraciones:
a) En un sistema monoprocesador, esta asignación de prioridades proporciona una ventaja que es
parecida a la que ofrece la planificación por afinidad.
b) En un sistema multiprocesador, esta asignación de prioridades proporciona una ventaja que es pa-
recida a la que ofrece la planificación por banda.
5. ¿Puede ocurrir una inversión de prioridades cuando se usan candados tipo candado circular o sleep
lock? (Véase la sección 9.2.2 para una definición de la inversión de prioridades.)
6. El término granularidad de sincronización se usa para indicar con qué frecuencia los procesos o hilos
en una aplicación tienen que sincronizarse entre sí. La granularidad o sincronización fina indica que los

15 MAQ. CAP. 13(F0694).indd 596 8/10/07 1:16:32 AM


Bibliografía 597

procesos tienen que sincronizarse con alta frecuencia, mientras que la granularidad gruesa indica que
los procesos rara vez tienen que sincronizarse.
Comente acerca de la conveniencia de los candados en cola, candado circular y latentes para
aplicaciones con una granularidad fina.

BIBLIOGRAFÍA
La mayoría de los libros sobre arquitectura de computadoras hablan de la arquitectura de multiprocesadores
y redes de interconexiones, por ejemplo, Hennessy y Patterson (2002), Hamacher et al. (2002) y Stallings
(2003).
Mellor-Crummey y Scott (1991), Menasse et al. (1991) y Wisniewski et al. (1997) analizan la sin-
cronización de procesos en un ambiente multiprocesador. La solución de software eficiente para la
sincronización de procesos que se describe en la figura 13.7 es adaptada de Mellor-Crummey y Scott
(1991). Ousterhout (1982), Tucker y Gupta (1989) y Squillante (1990) abordan asuntos de planificación en
sistemas operativos multiprocesadores.
Eykholt et al. (1992) estudian el multihilado del kernel de SunOS para aumentar la efectividad de su
estructura SMP. Accetta et al. (1986) describen el sistema operativo multiprocesador Mach. Love (2005)
analiza la sincronización y planificación en Linux 2.6, en tanto Russinovich y Solomon (2005) describen la
sincronización y planificación en Windows.

1. Accetta, M., R. Baron, W. Bolosky, D.B. Golub, R. Rashid, A. Tevanian y M. Young (1986):
“Mach: A new kernel foundation for Unix development”, Proceedings of the Summer 1986
USENIX Conference, junio de 1986, 93-112.
2. Eykholt, J.R., S.R. Kleiman, S. Barton, S. Faulkner, A. Shivalingiah, M. Smith, D. Stein, J. Voll,
M. Weeks y D. William (1992): “Beyond multiprocessing: multithreading the SunOS kernel”,
Proceedings of the Summer 1992 USENIX Conference, 11-18.
3. Hamacher, C., Z. Vranesic y S. Zaky (2002): Computer Organization, 5a. ed., McGraw-Hill.
4. Hennessy, J. y D. Patterson (2002): Computer Architecture: A Quantitative Approach, 3a. ed.,
Morgan Kaufmann, San Mateo.
5. Mellor-Crummey y M.L. Scott (1991): “Algorithms for scalable synchronization on shared me-
mory multiprocessor”, ACM Transactions on Computer Systems, 9 (1), 21-65.
6. Karlin, A.R., K. Li, M.S. Menasse y S. Owicki (1991): “Empirical studies of competitive spinning
for shared memory multiprocessor”, Proceedings of 13th ACM Symposium on Operating System
Principles, 41-55.
7. Kontothanassis L.I., R.W. Wisniewski y M.L. Scott (1997): “Scheduler conscious synchroniza-
tion”, ACM Transactions on Computer Systems, 15 (1), 3-40.
8. Love, R. (2005): Linux Kernel Development, 2a. ed., Novell Press.
9. Ousterhout, J.K. (1982): “Scheduling techniques for concurrent systems”, Proceedings of the 3rd
International Conference on Distributed Computing Systems, 22-30.
10. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.
11. Squillante, M. (1990): “Issues in shared-memory multiprocessor scheduling: a performance eva-
luation”, Tesis doctoral, Departamento de Ciencias e Ingeniería Computacionales, Universidad de
Washington.

15 MAQ. CAP. 13(F0694).indd 597 8/10/07 1:16:32 AM


598 CAPÍTULO 13 Sincronización y planificación en sistemas operativos multiprocesador

12. Stallings,W. (2003): Computer Organization and Architecture, 6a. ed., Prentice Hall, Upper Sad-
dle River.
13. Tanenbaum, A.S. (2001): Modern Operating Systems, 2a. ed., Prentice-Hall, Englewood Cliffs.
14. Tucker, A. y A. Gupta (1989): “Process control and scheduling issues for multiprogrammed sha-
red memory multiprocessors”, Proceedings of 12th ACM Symposium on Operating System Prin-
ciples, 159-166.

15 MAQ. CAP. 13(F0694).indd 598 8/10/07 1:16:32 AM


Capítulo
14
La estructura de
los sistemas operativos
La principal preocupación de un SO es la administración de cálculos y recursos de usuarios
para lograr la utilización efectiva de un sistema de cómputo. La tabla 14.1 resume las funciones
realizadas por un SO en busca de su objetivo. Los elementos de las cuatro primeras funciones se
describieron en el capítulo 2.

Tabla 14.1 Funciones realizadas por un SO

Función Detalles
Interfaz del usuario Procesamiento de comandos del usuario para
crear estructuras computacionales y para ac-
ceder a recursos.
Administración de Iniciación y terminación de procesos, plani-
procesos ficación, comunicación entre procesos.
Administración de Asignación y retiro de asignación de memo-
memoria ria, intercambio, administración de la me-
moria virtual.
Administración de E/S Procesamiento de interrupciones de E/S, ini-
ciación de operaciones de E/S.
Administración de Creación, almacenamiento y acceso de ar-
archivos chivos.
Protección y seguridad Prevenir la interferencia con recursos y pro-
cesos.

Durante la vida útil de un sistema operativo se llevan a cabo varios cambios en los sistemas
de cómputo y en los entornos de cómputo. Un sistema operativo debe poder adaptarse a estos
cambios y a nuevos dispositivos de hardware, implementándose en nuevas computadoras y ex-
tendiendo su alcance a nuevos entornos de cómputo. Analizaremos diferentes filosofías para
estructurar los módulos de un SO a fin de proporcionar estas características. Empezaremos con
la recapitulación de algunos detalles de la operación del SO de los capítulos 1 y 2.

16 MAQ. CAP. 14(F0694).indd 599 8/10/07 1:17:06 AM


600 CAPÍTULO 14 La estructura de los sistemas operativos

14.1 OPERACIÓN DE UN SO

La tabla 14.2 describe tres aspectos que son importantes para entender la operación de un SO.
Ésta se inicializa mediante el procedimiento de carga inicial en la memoria de la computadora,
usando una combinación de herramientas de hardware/firmware en el sistema de cómputo y la
técnica de software de bootstrapping (secuencia o programa de inicialización). Una computado-
ra está diseñada para realizar dos funciones en forma automática cuando es conectada: instruye
al dispositivo de E/S que está contenido en el medio de inicialización para que lea un programa
almacenado en una pista o sector especial en el medio de inicialización. Este programa carga
otros programas en la memoria que, a su vez, cargan otros hasta que el software de carga inicial
está cargado completamente en la memoria.

Tabla 14.2 Aspectos principales de operación del SO

Aspecto Descripción
Carga inicial La inicialización se realiza cuando se enciende un sistema de cómputo.
Carga el kernel en la memoria, inicializa sus estructuras de datos y le en-
trega el control.
Manejo de Cada evento causa una interrupción y se asegura el servicio correspon-
interrupciones diente tomando las medidas indicadas. La asignación de recursos E/S e
inicialización/terminación de programas se realizan como aspectos del
manejo de eventos.
Planificación El kernel selecciona un programa para la ejecución.

El software de inicialización realiza las siguientes funciones:


1. Determina la configuración del sistema, es decir, tipo de CPU, tamaño de la memoria, dis-
positivos de E/S y detalles de otros dispositivos de hardware conectados en el sistema.
2. Carga en la memoria programas del SO que constituyen el kernel.
3. Inicializa las estructuras de datos del SO.
4. Pasa el control al SO.
Al final del procedimiento de inicialización, el sistema operativo tiene el control del siste-
ma. La operación del sistema operativo es impulsada a través de interrupciones. Un evento que
requiere la atención del SO causa una interrupción. La acción de interrupción pasa el control
al SO (véase la sección 2.1.1). El hardware reconoce eventos como la finalización de E/S y el
final de un intervalo de tiempo, lo que conduce a las interrupciones del tipo correspondiente.
Cuando un proceso hace una llamada al sistema para solicitar recursos, iniciar operaciones de
E/S o crear/terminar otros procesos, esta acción también lleva a una interrupción que se llama
interrupción de software (véase la sección 2.1.2.2).
La figura 14.1 contiene un esquema del arreglo que se usa para realizar el manejo de even-
tos. El código de interrupción indica naturaleza y causa de una interrupción (véase la sección
2.5.1). El módulo manejador de interrupciones del SO analiza el código de interrupciones para
identificar el evento que ha ocurrido, activa un manejador de eventos que toma las medidas co-
rrespondientes y pasa el control al planificador. Éste selecciona un proceso para la ejecución y
le pasa el control.

16 MAQ. CAP. 14(F0694).indd 600 8/10/07 1:17:06 AM


14.2 Estructura de un sistema operativo 601

Eventos

Interrupciones

Manejador de
interrupciones

Manejador ·· Manejador ·· ··· Manejadores


de E/S de memoria de eventos

Planificador

Programa
del usuario
Figura 14.1 Visión general de la operación del SO.

La conmutación entre varios CPU ocurre dos veces durante el manejo de un evento. La
primera se presenta cuando la acción de interrupción pasa el control al SO. El manejador de
interrupciones guarda el estado del CPU del proceso que fue interrumpido. La segunda conmuta-
ción sucede cuando debe pasarse el control a un proceso usuario. El estado del CPU del proceso
seleccionado se carga al CPU.
El SO funciona impulsado por interrupciones, de tal modo que algunas de las funciones de
la tabla 14.1 son invocadas por varias interrupciones. Una interrupción de E/S invoca a algunas
de las funciones de la administración de E/S. Una parte de la función de administración de pro-
cesos está incrustada en el planificador y en el despachador, que son invocados durante su salida
del SO luego de procesar una interrupción. Todas las demás funciones se invocan por medio de
llamadas al sistema y, por ende, su lógica puede encontrarse en varios manejadores de eventos
(véase la figura 14.1).
Los procesos usuarios se cargan en la memoria conforme los usuarios abren su sesión y em-
piezan a emplear el sistema. Por tanto, en todo momento existe una colección de procesos de
SO y usuarios en la memoria de la computadora durante su operación. La memoria está dividida
en dos áreas —el área del sistema y el área de usuarios— para acomodar los procesos del SO
y los de usuarios (véase la figura 14.2). Algunos procesos de usuarios activos están ubicados en
la memoria, mientras que otros posiblemente habrán sido retirados de ella mediante un inter-
cambio.

14.2 ESTRUCTURA DE UN SISTEMA OPERATIVO


14.2.1 Políticas y mecanismos
Una función realizada por un SO administra una clase de recursos o una clase de entidades. Por
ejemplo, la función de planificación administra los procesos en el sistema y la de administración
de memoria administra su memoria. Mientras diseña una función, un diseñador tiene que pensar
en dos niveles distintos:

16 MAQ. CAP. 14(F0694).indd 601 8/10/07 1:17:07 AM


602 CAPÍTULO 14 La estructura de los sistemas operativos

Área del Área residente


sistema
Área transitoria Parte no residente
del SO
Área de
usuarios

Programas retirados
por intercambio
Figura 14.2 Programas de usuarios y SO en la memoria.

• Política: Una política especifica el principio guía que deberá usarse mientras se adminis-
tra una clase de recursos o entidades.
• Mecanismo: Un mecanismo es una operación específica que se necesita para implemen-
tar una política.

La mejor forma de explicar la diferencia entre una política y un mecanismo es la siguiente:


una política especifica qué se debe hacer, mientras que un mecanismo indica cómo se debe
hacer. Un mecanismo se implementa como un módulo que realiza una tarea específica, mientras
que una política se implementa como un módulo de toma de decisiones que decide a qué módu-
los de mecanismos se va a llamar. El ejemplo 14.1 analiza políticas y mecanismos en la función
de planificación.

Ejemplo 14.1 Un SO usa la política de planificación round-robin. Se necesitan los siguientes me-
canismos para implementarla:
Mantener una cola de procesos dispuestos.
Seleccionar el primer proceso de la cola para la ejecución.
Conmutar el CPU a la ejecución del proceso seleccionado.
Un diseñador puede elegir entre varias políticas de planificación. Es interesante recalcar que éstas
necesitan algunos mecanismos comunes, por ejemplo, el mecanismo despachador.

14.2.2 Portabilidad y extensibilidad de sistemas operativos

El diseño e implementación de sistemas operativos involucra enormes inversiones económicas.


Para protegerlas, un sistema operativo deberá tener una vida útil de más de una década. Durante
este periodo, se llevarán a cabo varios cambios en la arquitectura de computadoras, en la tec-
nología de dispositivos de E/S y en los entornos de aplicaciones, por lo que deberá ser posible
adaptar un SO a estos cambios.
En este contexto hay dos características importantes: la portabilidad y la extensibilidad.
Portabilidad se refiere a la facilidad con la que pueda implementarse un SO en un sistema de
cómputo que tenga una arquitectura distinta. De por sí, un SO tiene poca portabilidad porque
su código depende de la arquitectura de un sistema de cómputo de varias maneras, por ejemplo:

16 MAQ. CAP. 14(F0694).indd 602 8/10/07 1:17:07 AM


14.3 Sistemas operativos con estructura monolítica 603

• El hardware de interrupciones tiene que ser inicializado de tal modo que el control se
pase al manejador de interrupciones cuando ocurra una interrupción. El software de car-
ga inicial realiza esta función formando vectores de interrupción correspondientes.
• El hardware de direccionamiento de la memoria tiene que ser inicializado a fin de imple-
mentar la protección de la memoria y de la memoria virtual.
• Tiene que usarse el hardware de E/S para implementar operaciones de E/S.
De este modo, la portabilidad de un SO implicará cambios en todas las funciones del SO
que dependen de la arquitectura. Afortunadamente, es posible limitar el esfuerzo involucrado en
la portabilidad de un SO porque normalmente se encuentra el código dependiente de arquitectu-
ra en módulos que implementan mecanismos del SO. En las secciones 14.6 y 14.7 analizaremos
cómo puede aprovecharse este hecho para proporcionar alta portabilidad.
La extensibilidad permite que se modifiquen funcionalidades del SO o que se agreguen
fácilmente nuevas funcionalidades a un SO. Esta característica es importante para asegurar que
un SO pueda adaptarse a cambios en la tecnología de hardware/software y a las expectativas
de usuarios durante su larga vida útil. Analizamos las previsiones para la extensibilidad en la
sección 14.7.

14.3 SISTEMAS OPERATIVOS CON ESTRUCTURA MONOLÍTICA

Los primeros sistemas operativos tenían una estructura monolítica, es decir, el código del SO
no consistía en un conjunto de módulos con interfaces claramente definidas; más bien estaba
compuesto por un solo módulo. Es por esto que las diferentes funcionalidades y servicios de
un SO estaban enteradas de la naturaleza y direcciones de los otros, y usaban libremente estos
conocimientos en su código.
La figura 14.3 muestra un esquema de un SO de estructura monolítica. El SO formaba una
capa de software entre el usuario y el hardware de la máquina, es decir, el hardware del sistema
computacional. No había estructura perceptible en la capa del SO porque éste tenía una estructu-
ra monolítica. La interfaz del usuario se proporcionaba por medio de un lenguaje de comandos.
El intérprete del lenguaje de comandos organizaba la ejecución de los procesos usuarios. Tanto el
intérprete del lenguaje de comandos como los procesos usuarios invocaban las funcionalidades
y servicios del SO por medio de llamadas al sistema.

Interfaz Programa
de usuario usuario

Capa del SO

Hardware de la máquina
Figura 14.3 SO monolítico.

A través del tiempo, surgieron dos problemas acerca de la estructura monolítica. La capa
del SO tenía una interfaz con el hardware de la máquina, por lo que el código dependiente de la
arquitectura se extendía a través de todo el SO. Por consiguiente, éste era altamente dependiente

16 MAQ. CAP. 14(F0694).indd 603 8/10/07 1:17:07 AM


604 CAPÍTULO 14 La estructura de los sistemas operativos

de la arquitectura y poseía poca portabilidad. Diferentes funcionalidades y servicios del SO


podían usar el conocimiento de los datos de los otros en su código, de tal modo que los cambios
hechos en una funcionalidad podían afectar a otras funcionalidades. Esta característica hacía que
la verificación y depuración fuera muy difícil y llevaba a altos costos de mantenimiento y de
aumento de calidad.
Dichos problemas condujeron a la búsqueda de maneras alternativas de estructurar un SO.
En las siguientes secciones analizaremos tres métodos para estructurar un SO, propuestos a fin
de abordar estos problemas.

• Estructura de capas: La estructura de capas ataca la complejidad y costo del desarrollo


y mantenimiento de un SO, estructurándolo para formar un número de capas (véase la
sección 14.4). El sistema de multiprogramación THE es un ejemplo famoso de un SO de
capas.
• Estructura basada en el kernel: La estructura basada en el kernel limita la dependencia
de la máquina a una pequeña sección de código del SO que constituye el kernel (véase la
sección 14.6). Este planteamiento reduce el esfuerzo involucrado en la portabilidad de
un SO a otro sistema de cómputo.
• Estructura del SO basada en el microkernel: La estructura del SO basada en el microker-
nel ofrece muchas de las ventajas de una estructura basada en el kernel, y también pro-
porciona la extensibilidad. Por consiguiente, puede usarse un microkernel para construir
más de un sistema operativo (véase la sección 14.7).

14.4 EL DISEÑO POR CAPAS DE SISTEMAS OPERATIVOS

La estructura monolítica de sistemas operativos tenía el problema de que todos los componentes
del SO tenían que usar el hardware de la máquina. Esta característica aumentaba el costo y el
esfuerzo en el desarrollo de un SO debido a la gran brecha semántica entre el sistema operativo
y el hardware de la máquina.

Definición 14.1 (Brecha semántica) La brecha semántica entre una aplicación y el hardware
de la máquina es aquella existente entre la naturaleza de las operaciones requeridas por la
aplicación y la naturaleza de las operaciones admitidas por la máquina.

La existencia de la brecha semántica puede explicarse de la siguiente forma: una instruc-


ción de la máquina implementa una operación primitiva en el nivel máquina, por ejemplo, la
manipulación de cifras y caracteres usando la aritmética o instrucciones lógicas. Un módulo
de E/S contiene un algoritmo que usa operaciones primitivas en el nivel SO, que se parecen
a mecanismos, por ejemplo, operaciones como guardar el contexto de un proceso e iniciar una
operación de E/S. Estas operaciones son más complejas que las primitivas en el nivel máquina.
Tal diferencia lleva a una brecha semántica grande que se puentea mediante la programación.
Cada operación deseada por el SO se convierte entonces en una secuencia de instrucciones,
y posiblemente en una rutina (en la figura 14.4), por lo que los costos de programación son
altos.
Puede reducirse la brecha semántica entre el SO y la máquina en la que opera usando una
máquina con hardware más capaz —una máquina que proporciona instrucciones para realizar al-
gunas (o todas) de las operaciones que los sistemas operativos tienen que realizar— o simulando

16 MAQ. CAP. 14(F0694).indd 604 8/10/07 1:17:07 AM


14.4 El diseño por capas de sistemas operativos 605

Sistema Administración Administración


operativo de programas de E/S

Brecha
semántica

Hardware de Instrucciones Instrucciones Instrucciones


la máquina aritméticas lógicas de E/S

Figura 14.4 Brecha semántica.

un hardware de la máquina inteligente en el software. El primer planteamiento es caro. En el


segundo, el simulador se ejecuta en el hardware de la máquina y simula (es decir, adopta la apa-
riencia de) una máquina más poderosa que tiene muchas de las características deseadas por un
SO. A esta máquina se le denomina máquina extendida, y a su simulador, software de máquina
extendida. Entonces el SO usa la máquina extendida en lugar del hardware de la máquina; el
software de máquina extendida forma una capa entre el SO y el hardware de la máquina. Este
arreglo da como resultado una estructura del SO de dos capas. La ventaja de esta estructura es
que las funciones del SO se enfrentan a una máquina extendida hipotética cuyas instrucciones de
máquina pueden ejecutar muchas operaciones requeridas en un SO.

Sistema Administración Administración


operativo de programas de E/S
Brecha
semántica
Máquina Guardar Expedir un Realizar
extendida contexto programa E/S

Hardware de la máquina

Figura 14.5 Diseño por capas de un SO.

La figura 14.5 ilustra esta estructura del SO de dos capas. La capa del sistema operativo se
ubica encima de la de la máquina extendida. La máquina extendida proporciona operaciones
como guardar el contexto, expedición, intercambio e iniciación de E/S. Tal arreglo simplifica de
manera considerable la codificación y verificación de módulos del SO, separando el algoritmo
de una función de la implementación de sus operaciones primitivas. Entonces es más fácil veri-
ficar, depurar y modificar este módulo del SO que en un SO monolítico.

16 MAQ. CAP. 14(F0694).indd 605 8/10/07 1:17:08 AM


606 CAPÍTULO 14 La estructura de los sistemas operativos

Un SO podrá ser estructurado para contener muchas capas. Cada una usa la interfaz pro-
porcionada por la capa que está debajo de ella y ofrece una interfaz más inteligente a la que está
encima de ella. La capa más baja es la de la máquina extendida. Ella proporciona una interfaz de
máquina extendida y usa el hardware de la máquina. Esta capa hace que la(s) capa(s) superior(es)
del SO sea(n) más fácil(es) de diseñar.
La disciplina básica en un diseño por capas del SO es que las rutinas de una capa sólo usan
los recursos de la capa directamente inferior; esto quiere decir que no pueden pasar por encima
de ninguna capa que haya en la estructura. Además, el acceso a rutinas de una capa inferior debe
llevarse a cabo estrictamente a través de la interfaz entre las capas. Por tanto, a diferencia de
un diseño monolítico, una rutina situada en una capa desconoce las direcciones de estructuras
de datos o instrucciones de la capa inferior; sólo sabe cómo invocar una rutina de esa capa.
La estructura por capas proporciona buena modularidad; cada capa del SO forma un
módulo con una funcionalidad claramente definida y una interfaz con el resto del SO. Un be-
neficio enorme de la modularidad es la ocultación de informaciones. Los detalles internos de
un módulo, es decir, el arreglo de sus datos y programas, se esconden de los demás módulos.
Esta propiedad del módulo impide el uso indebido o la corrupción de los datos de una capa por
rutinas situadas en otras capas del SO. Durante la depuración, la localización de errores se hace
fácilmente, pues la causa de un error, por ejemplo, un valor incorrecto en un elemento de datos
que pertenece a una capa, debe estar ubicada en esta misma capa. La ocultación de informacio-
nes también implica que un módulo del SO podrá ser modificado sin afectar a otros módulos.
Esta característica simplifica la verificación y depuración de un SO. El ejemplo 14.2 describe la
estructura de capas del sistema de multiprogramación THE. Este ejemplo ilustra cómo la estruc-
turación por capas simplifica el diseño de un SO.

Ejemplo 14.2 El sistema de multiprogramación THE fue desarrollado en la Technische Hogeschool


Eindhoven, en los Países Bajos, por Dijkstra y otros, usando un diseño por capas. La tabla 14.3
muestra capas en el sistema THE.

Tabla 14.3 Capas en el sistema de multiprogramación THE

Capa 0 Asignación de procesadores y multiprogramación


Capa 1 Administración de memoria y disco
Capa 2 Comunicación operador-proceso
Capa 3 Administración de E/S
Capa 4 Procesos usuarios

La capa 0 del sistema maneja la asignación de procesadores para implementar la multiprogra-


mación. Esta función implica estar al corriente de los estados de procesos y cambiar entre procesos.
Las capas situadas arriba de la capa 1 no tienen que preocuparse de estos asuntos. De hecho, pueden
no ser conscientes de la presencia de múltiples procesos en el sistema.
La capa 1 realiza la gestión de la memoria. Esta capa asigna suficiente memoria para satisfacer
las necesidades de procesos y usa el disco cuando se le acaba la memoria. Los detalles de transfe-
rencia entre la memoria y el disco no incumben al resto del sistema. Por tanto, la posibilidad de
que parte de un proceso pueda existir en el disco no tiene que abordarse en forma explícita para
cualquier capa situada arriba de la capa 2.

16 MAQ. CAP. 14(F0694).indd 606 8/10/07 1:17:08 AM


14.5 Sistemas operativos de máquina virtual 607

La capa 2 implementa la comunicación entre un proceso y la consola del operador mediante


la asignación de una consola virtual a cada proceso. La capa 3 realiza la administración de E/S.
Asimismo, proporciona funciones fáciles de usar para realizar operaciones de entrada y salida en
los dispositivos que existen en el sistema. De este modo, las complejidades de la programación de
E/S (véase la sección 12.4) quedan ocultas para la capa situada arriba (capa 4), que es ocupada por
procesos usuarios.

El planteamiento por capas del diseño de SO sufre de dos problemas. Puede ser que se re-
duzca la velocidad de operación de un sistema debido a la estructura por capas. Recuerde que
cada capa sólo puede interactuar con las capas contiguas. Esto implica que una solicitud del ser-
vicio del SO hecha por un proceso usuario debe bajar lentamente desde la capa del número más
alto hasta el más bajo antes de que el sistema de cómputo realice la acción solicitada.
El segundo problema se refiere a dificultades en el desarrollo de un diseño por capas. Una
capa sólo puede acceder a la capa inmediatamente inferior, por lo que todas las herramientas y
servicios que necesita deben estar disponibles en las capas inferiores. Este requerimiento podrá
presentar un problema para el ordenamiento de las capas, que se resuelve frecuentemente par-
tiendo una capa en dos y colocando otras capas entre las dos partes. Por ejemplo, las funciones
de manejo de procesos se realizan en la capa más baja del sistema operativo THE (véase la tabla
14.3). La capa colocada directamente encima realiza la gestión de memoria. Este arreglo podrá
resultar inconveniente porque el SO tiene que realizar la asignación de memoria como parte de
la creación de un proceso. Esta dificultad puede superarse partiendo el manejo de procesos en
dos capas. Una realizará funciones de administración de procesos, tales como guardar contextos,
conmutación, planificación y sincronización de procesos. Esta capa seguirá siendo la más baja
de la estructura. La otra estará ubicada encima de la capa de administración de memoria y reali-
zará la creación de procesos.

14.5 SISTEMAS OPERATIVOS DE MÁQUINA VIRTUAL

Diferentes clases de usuarios necesitan diferentes tipos de servicio al usuario. Es por eso que la
operación de un solo SO en un sistema de cómputo puede decepcionar a muchos usuarios. Este
problema se resuelve mediante el uso de un sistema operativo de máquina virtual (SO MV) para
controlar el sistema de cómputo. El SO MV crea varias máquinas virtuales. Cada una se asigna a
un solo usuario que puede emplear cualquier SO de su propia elección en la máquina virtual para
operar sus programas bajo este SO. De este modo, los usuarios del sistema de cómputo pueden
usar diferentes sistemas operativos al mismo tiempo. Denominamos a cada uno de estos sistemas
operativos SO invitado, y a la máquina virtual del SO, SO host.
Una máquina virtual es un recurso virtual (véase la sección 1.3.2.1). Tiene la misma ar-
quitectura que la computadora que usa el SO MV, que denominamos máquina host, es de-
cir, tiene un CPU virtual capaz de ejecutar las mismas instrucciones, una memoria virtual y
dispositivos de E/S virtuales. Sin embargo, podrá ser distinta de la máquina host en algunos
elementos de su configuración, tales como tamaño de memoria y dispositivos de E/S. Debido
a la arquitectura idéntica de las máquinas virtual y host, no existe una brecha semántica entre
ellas, por lo que el uso de una máquina virtual no introduce una sobrecarga ni causa pérdida
de desempeño (confronte eso con el uso de la capa de máquina extendida que se describió en
la sección 14.4); tampoco se necesita intervención de software para operar un SO invitado
en una máquina virtual.

16 MAQ. CAP. 14(F0694).indd 607 8/10/07 1:17:08 AM


608 CAPÍTULO 14 La estructura de los sistemas operativos

El SO MV logra la operación concurrente de sistemas operativos invitados por medio de una


acción que se parece a la planificación de procesos: selecciona una máquina virtual y organiza
lo necesario para que se permita que el SO invitado que opera en él ejecute sus instrucciones en
el CPU. El SO invitado en operación goza del control completo sobre el ambiente de la máquina
host, incluido el servicio para interrupciones. La ausencia de una capa de software entre la má-
quina host y el SO invitado asegura un uso eficiente de la primera. Un SO invitado se queda con
el control de la máquina host hasta que el SO MV decide cambiar a otra máquina virtual. Esto
normalmente sucede en respuesta a interrupciones que ocurren en el sistema. El SO MV puede
emplear el temporizador para implementar la división del tiempo en intervalos y la planificación
round-robin de SO invitados.
Se necesita un arreglo un tanto más complejo para manejar interrupciones que surgen cuan-
do un SO invitado está en operación. Algunas de las interrupciones pertenecerán a su propio do-
minio —por ejemplo, una interrupción de E/S de un dispositivo incluido en su propia máquina
virtual—, mientras que otras pertenecerán al dominio de otro SO invitado. El SO MV puede or-
ganizar que se le dé el control cuando se presentan interrupciones, diferenciar entre los dos tipos
de interrupción y pasarlas al correspondiente SO invitado. Sin embargo, este arreglo requerirá
que cada interrupción se haga pasar a través del SO MV, lo que será ineficiente. Por ende, el SO
MV asegura que el SO invitado en operación se invocará directamente por interrupciones que
surgen en su propio dominio. Esto se logra de la siguiente manera: mientras pasa el control a un
sistema operativo invitado, el SO MV sustituye sus propios vectores de interrupción por los que
están definidos en el SO invitado. Esta acción asegura que una interrupción conmutará el CPU a
una rutina de servicio para interrupciones del SO invitado. Si el SO invitado se da cuenta de que
la interrupción pertenece al dominio de otro SO invitado, pasa el control al SO MV mediante una
llamada especial al sistema “invoca SO MV”. El SO MV entonces organiza que la interrupción
pase al SO invitado correspondiente.
El ejemplo 14.3 describe la operación del VM/370 de IBM, que es un SO MV famoso de la
década de los setenta.

Ejemplo 14.3 La figura 14.6 muestra tres de los SO invitados admitidos por el VM/370. El Sis-
tema Monitor Conversacional (CMS) es un sistema operativo de un solo usuario, mientras que el
OS/370 y el DOS/370 son sistemas operativos de multiprogramación. Un proceso usuario no es
consciente de la presencia del VM/370; sólo ve al SO invitado que lo usa. Para impedir la inter-
ferencia entre los SO invitados, el CPU se pone en modo de usuario mientras que ejecuta un SO
invitado. La iniciación de operaciones de E/S se maneja de la siguiente manera: cuando el kernel
de un SO invitado ejecuta una instrucción de E/S, parece ser un intento para ejecutar una instruc-
ción privilegiada mientras el CPU está en modo de usuario, por lo que esto causa una interrupción
del programa. La interrupción se dirige al VM/370 en lugar de al SO invitado. Entonces el VM/370
inicia la operación de E/S mediante la ejecución de la instrucción de E/S que había causado la
interrupción.

La distinción entre el modo privilegiado y el modo de usuario del CPU causa algunas difi-
cultades en el uso de un SO MV. Éste debe protegerse de SO invitados, por lo que debe operar
SO de invitados con el CPU en modo de usuario. Sin embargo, de esta manera tanto un SO
invitado como los procesos usuarios bajo su control operan en modo de usuario, lo que hace
que el SO invitado sea susceptible a corrupción por parte de un proceso invitado. La familia de
computadoras Intel 80x86 tiene una característica que proporciona una salida a esta dificultad.

16 MAQ. CAP. 14(F0694).indd 608 8/10/07 1:17:08 AM


14.5 Sistemas operativos de máquina virtual 609

CMS OS/370 DOS/370

VM/370

Figura 14.6 Sistema operativo de máquina virtual VM/370.

Las computadoras 80x86 admiten 4 modos del CPU. De esta forma, el SO host puede operar
mientras el CPU está en el modo privilegiado; un SO invitado puede ejecutar procesos que ope-
ran bajo él mientras el CPU está en modo de usuario, pero él mismo puede operar mientras el
CPU está en uno de los modos restantes.
La virtualización es el proceso mediante el cual las capacidades de una máquina host es-
tán disponibles como capacidades en una máquina virtual. El término virtualización completa
implicará que la máquina host y una máquina virtual tengan capacidades idénticas, por lo que
un SO puede operar en forma idéntica mientras corre en el hardware de la máquina y en una
máquina admitida por un SO MV. Sin embargo, la virtualización completa podrá conducir a
una carencia de seguridad. En el ejemplo 14.3 vimos cómo el VM/370 permite que un invita-
do ejecute una instrucción privilegiada, pero su ejecución causa una interrupción y el propio
VM/370 ejecuta la instrucción por parte del SO invitado. Este arreglo es poco seguro porque el
SO MV no puede diferenciar el uso legítimo de la instrucción privilegiada en un proceso usua-
rio que opera bajo un SO invitado. En ambientes modernos de máquinas virtuales, esta dificul-
tad se resuelve por medio de la modificación del código de un SO que debe ser usado como un
SO invitado. El código modificado provoca una interrupción de software y pasa informaciones
sobre la instrucción privilegiada que desea ejecutar al SO MV, y éste ejecuta la instrucción en
su nombre.
En ambientes de cómputo modernos, las máquinas virtuales se han usado para reducir cos-
tos de hardware y operación mediante el uso de servidores existentes para nuevas aplicaciones
que requieren el uso de diferentes sistemas operativos. VMware y XEN son dos productos de
máquina virtual que apuntan hacia la implementación de hasta 100 SO invitados en una máquina
host con apenas una degradación de desempeño marginal en comparación con su implementa-
ción en el hardware de la máquina. Puesto que el SO MV impide la interferencia entre máquinas
virtuales, el entorno de las máquinas virtuales también puede usarse para probar un SO modifi-
cado o una nueva versión de código de aplicación en el mismo servidor que se usa para corridas
de producción del SO o de la aplicación.
Los entornos de máquinas virtuales también se han usado para ofrecer capacidades de mane-
jo de desastres; esto se hace mediante la transferencia a otro servidor disponible en la red de una
máquina virtual hospedada en un servidor que tiene que apagarse debido a una emergencia. La
transferencia de la máquina virtual a un nuevo servidor, seguida por su iniciación en éste, puede

16 MAQ. CAP. 14(F0694).indd 609 8/10/07 1:17:09 AM


610 CAPÍTULO 14 La estructura de los sistemas operativos

ser finalizada en menos de dos segundos, por lo que los usuarios de la aplicación que estaba
corriendo en la máquina virtual ni siquiera se dan cuenta de que su aplicación fue transferida a
una nueva máquina host.

14.6 SISTEMAS OPERATIVOS BASADOS EN EL KERNEL

El kernel es el corazón de un SO; proporciona un conjunto de funciones y servicios para apoyar a


varias funcionalidades del SO. El resto del SO está organizado como un conjunto de programas
no kernel, que implementan operaciones en procesos y recursos que son de interés para usuarios,
y una interfaz de usuario que invoca a estos programas no kernel a implementar comandos de
usuario. La figura 14.7 es una visión abstracta de un SO basado en el kernel. La operación del
kernel es impulsada por interrupciones. Obtiene el control cuando una interrupción señaliza la
ocurrencia de un evento que requiere la atención del SO, por ejemplo, cuando sucede una inte-
rrupción de temporizador o E/S. El kernel también obtiene el control cuando un programa no
kernel hace una llamada al sistema para invocar una función o servicio del kernel. Esto normal-
mente sucede en respuesta a un comando de usuario. Por ejemplo, cuando un usuario emite un
comando para ejecutar el programa almacenado en un archivo, por ejemplo, el archivo alpha,
la interfaz del usuario del SO por lo regular invoca un programa no kernel para organizar la
iniciación del programa contenido en el archivo alpha. Este programa no kernel hace llamadas
al sistema para asignar memoria para la ejecución del programa, abre un archivo alpha y carga
su contenido al área de memoria asignada, seguido por otra llamada al sistema para iniciar la
ejecución del programa.

Interfaz de usuario

Módulos no kernel

Kernel

Hardware de la máquina
Figura 14.7 Capas del SO.

Las motivaciones históricas para la estructura del SO basada en el kernel eran una conve-
niencia en la codificación de programas no kernel. La portabilidad del SO se logró poniendo en
el kernel partes del SO dependientes de la arquitectura y manteniendo las partes independientes
de la arquitectura fuera de él, por lo que el esfuerzo de portabilidad estuvo limitado a la porta-
bilidad del kernel. Éste normalmente es monolítico para asegurar la eficiencia; la parte no kernel
de un SO puede ser monolítica o estructurada en capas.
La tabla 14.4 contiene una lista muestra de funciones y servicios que ofrece el kernel para
apoyar varias funcionalidades del SO. Estas funciones y servicios proporcionan un conjunto
de abstracciones a los programas no kernel, cuyo uso simplifica su diseño y codificación. Por

16 MAQ. CAP. 14(F0694).indd 610 8/10/07 1:17:09 AM


14.6 Sistemas operativos basados en el kernel 611

ejemplo, las funciones de E/S de la tabla 14.4 implementan colectivamente la abstracción de


dispositivos virtuales (véase la sección 1.3.2.1). Un proceso es otra abstracción proporcionada
por el kernel.

Tabla 14.4 Mecanismo típico en un kernel

Función Ejemplos de los mecanismos


Procesamiento Salva el estado del CPU
de interrupciones
Planificación Expide un programa
Manipula listas de planificación
Administración Coloca la información de protección de la memoria
de memoria Intercambio de entrada/intercambio de salida
Mecanismos de memoria virtual, por ejemplo, falla de manejo de página, carga
de página
E/S Iniciación de E/S
Procesamiento de finalización de E/S
Recuperación de errores
Comunicación Mecanismos de comunicación interproceso
Mecanismos de disposición en red

Es posible que un diseño basado en el kernel sufra de estratificación en forma análoga al


diseño por capas del SO (véase la sección 14.4) porque el código para implementar un comando
del SO podrá contener una parte dependiente de la arquitectura, la cual se mantendrá fuera del
kernel. Estas partes tendrán que comunicarse entre sí por medio de llamadas al sistema, lo cual
aumentará la sobrecarga del SO debido a acciones de servicio por interrupciones. Considere
el comando para iniciar la ejecución del programa en un archivo denominado alpha. Como
hemos analizado al principio de esta sección, el programa no kernel que implementa el co-
mando hará cuatro llamadas al sistema para asignar memoria, abrir el archivo alpha, cargar el
programa que contiene a la memoria e iniciar su ejecución, lo que incurrirá en una sobrecarga
considerable. Algunos diseños de sistemas operativos reducen la sobrecarga del SO, incluida
la parte independiente de la arquitectura del código de una función, también presente en el
kernel. De este modo, el programa no kernel que inició la ejecución de un programa se volverá
parte del kernel. Otros ejemplos de ese tipo son los planificadores de procesos (incluidas las polí-
ticas de planificación), partes de planificación de E/S de controladores de dispositivos, servicios
de sistemas de archivado del kernel y políticas de gestión de memoria. Estas inclusiones reducen
la sobrecarga del SO, así como la portabilidad del SO.
Sistemas de operación basados en el kernel ofrecen poca extensibilidad porque la adición
de nuevas funcionalidades al SO requerirá la modificación del kernel para proporcionar nuevas
funciones y servicios.

14.6.1 Módulos del kernel dinámicamente cargables

Una tendencia reciente en el diseño de kernel es estructurarlo como un conjunto de módulos


dinámicamente cargables. Cada módulo tiene una interfaz bien especificada por medio de la

16 MAQ. CAP. 14(F0694).indd 611 8/10/07 1:17:09 AM


612 CAPÍTULO 14 La estructura de los sistemas operativos

cual interactúa con otros módulos. Se carga un conjunto kernel de módulos cuando se inicializa
el sistema. Otros se cargan cuando se necesitan y se retiran de la memoria cuando ya no se re-
quieren.
Estructurar el kernel como un conjunto de módulos cargables supera varios inconvenientes
de grandes kernel monolíticos o kernel con capas. Durante la operación del SO se conserva
memoria porque sólo los módulos requeridos del kernel están en la memoria en un momento
dado. Se evita la estratificación de funcionalidades del kernel en varias capas, y la subsiguiente
sobrecarga de comunicación entre diferentes partes de una funcionalidad. Esta estructura tam-
bién proporciona la extensibilidad, ya que los módulos del kernel pueden ser modificados por
separado y agregarse fácilmente nuevos módulos. Los sistemas Linux y Solaris usan esta meto-
dología del diseño de módulos.

14.7 SISTEMAS OPERATIVOS BASADOS EN MICROKERNEL

La colocación de todo el código dependiente de la arquitectura en el kernel proporciona buena


portabilidad. Sin embargo, en la práctica, los kernel también incluyen código independiente de la
arquitectura. Esta característica conduce a varios problemas. Lleva a un gran tamaño del kernel,
lo que resta importancia al objetivo de portabilidad, y posiblemente necesite una modificación
del kernel para incorporar nuevas características, razón por la que baja la extensibilidad. Un gran
kernel admite un número muy grande de llamadas al sistema. Es posible que algunas de éstas se
usen rara vez y, por ende, su implementación a través de diferentes versiones del kernel no sea
verificada en forma exhaustiva, lo que compromete la confiabilidad del SO.
El microkernel fue desarrollado a principios de la década de los noventa con la finalidad
de superar estos problemas con referencia a portabilidad, extensibilidad y confiabilidad. Un
microkernel es una parte central esencial de código del SO; por tanto, únicamente contiene
un subconjunto de los mecanismos que normalmente están incluidos en un kernel y admite sólo un
pequeño número de llamadas al sistema, las cuales se prueban y usan severamente. Esta carac-
terística aumenta la portabilidad y confiabilidad del microkernel. Las partes menos esenciales
de código del SO están fuera del microkernel y usan sus servicios. De este modo, pueden modi-
ficarse estas partes sin afectar al kernel; ¡por principio, estas modificaciones pueden realizarse
sin tener que reinicializar el SO! Los servicios que se proporcionan en un microkernel no tie-
nen ningún prejuicio contra características o políticas específicas en un SO, por lo que pueden
agregarse nuevas funcionalidades y características al SO para satisfacer entornos de operación
específicos.
La figura 14.8 ilustra la estructura de un SO basado en el microkernel. Éste incluye me-
canismos para la planificación de procesos y administración de memoria, etc., pero no cuenta
con planificador ni manejador de memoria. Estas funciones se implementan como servidores,
que simplemente son procesos que nunca terminan. Los servidores y procesos usuarios operan
encima del microkernel, que simplemente realiza el manejo de interrupciones y proporciona la
comunicación entre los servidores y los procesos usuarios.
El tamaño pequeño y la extensibilidad de los microkernel son propiedades valiosas para el
ambiente de sistemas incrustados (sistemas embebidos), porque, por un lado, los sistemas ope-
rativos tienen que ser pequeños y, por el otro, finamente afinados a los requerimientos de una
aplicación incrustada (embebida). La extensibilidad de los microkernel también refuerza la op-
ción de usar el mismo kernel para un amplio espectro de sistemas de cómputo, desde sistemas

16 MAQ. CAP. 14(F0694).indd 612 8/10/07 1:17:09 AM


14.7 Sistemas operativos basados en microkernel 613

Procesos
Servidores usuarios

Planificador Manejador
de procesos . . . . de ...
round-robin memoria

Microkernel

Hardware de la máquina

Figura 14.8 Estructura de sistemas operativos basados en los microkernel.

portátiles de tamaño pequeño hasta grandes sistemas paralelos y distribuidos. Hasta cierto grado,
esta visión se ha realizado. El microkernel Mach ha sido usado para implementar varias versio-
nes distintas de Unix. El sistema operativo distribuido Amoeba usa un microkernel idéntico en
todas las computadoras de un sistema distribuido, incluidas estaciones de trabajo, servidores y
grandes multiprocesadores.
La interpretación del término “kernel esencial de código del SO” ha sido objeto de discusión,
y como resultado hay una variedad considerable en los servicios incluidos en un microkernel.
Por ejemplo, la implementación del microkernel Mach por IBM deja la política de planifica-
ción de procesos y controladores de dispositivos fuera del kernel; estas funciones operan como
servidores. El microkernel QNX incluye rutinas de servicio a interrupciones, planificación de
procesos, comunicación interproceso y servicios básicos de la red. El microkernel L4 incluye la
administración de memoria y admite únicamente siete llamadas al sistema. Tanto el QNX como
el L4 sólo tienen un tamaño de 32 K bytes.
El exokernel usa una filosofía radicalmente distinta: la gestión de recursos tiene que ser
centralizada; la pueden realizar las mismas aplicaciones en forma distribuida. Por consiguiente,
un exokernel solamente proporciona la multiplexación eficiente de recursos de hardware, mas no
proporciona abstracciones. Un proceso de aplicación ve un recurso en el sistema de cómputo en
su forma cruda. Este enfoque da como resultado operaciones primitivas extremadamente rápi-
das, de 10 a 100 veces más rápidas que en caso de usar un kernel monolítico Unix. Por ejemplo,
datos leídos de un dispositivo E/S pasan directamente al proceso que los solicitó; no transitan
a través del microkernel, como sí lo hubieran hecho a través del kernel de Unix. Puesto que las
funcionalidades tradicionales del SO se implementan en el nivel de aplicación, una aplicación
puede seleccionar y usar un SO a partir de una biblioteca de sistemas operativos. El SO se ejecu-
ta como un proceso en el modo no kernel y usa características del exokernel.
Puede argumentarse que un microkernel debe proporcionar determinados servicios. Éstos
incluyen el soporte de gestión de memoria, la comunicación interproceso y la gestión de las
interrupciones. La gestión de memoria y el servicio a interrupciones serán invocados por mó-
dulos de un nivel mayor en el código del SO de los que existen fuera del microkernel. La rutina
de gestión de las interrupciones aceptará éstas y las pasará a módulos de nivel mayor para su
procesamiento.

16 MAQ. CAP. 14(F0694).indd 613 8/10/07 1:17:09 AM


614 CAPÍTULO 14 La estructura de los sistemas operativos

Las ventajas de los microkernel son un tanto contrarrestadas por dudas acerca del desem-
peño de sistemas operativos que se basan en ellos. El origen del problema reside en el hecho de
que algunas funcionalidades de un kernel convencional están divididas entre un microkernel y
un SO implementado por medio del microkernel: nuevamente el ya conocido problema de estra-
tificación. Por ejemplo, un kernel contiene la función completa de la administración de procesos
que realiza la creación, planificación y expedición de procesos, mientras que un microkernel
posiblemente sólo incluirá la creación y expedición de procesos, y la planificación de procesos
podrá operar como un proceso bajo el microkernel. La comunicación entre las dos partes puede
causar problemas de desempeño.

14.8 CONFIGURACIÓN E INSTALACIÓN DEL KERNEL

En los años sesenta y setenta era común que un fabricante de computadoras comercializara una
serie de computadoras que consistía en un número de modelos con la misma arquitectura básica.
Los modelos se distinguían en el tamaño de la memoria, la velocidad del CPU y periféricos (¡y,
desde luego, en el precio!). Esta diferencia entre las capacidades de los modelos planteaba un
problema difícil para diseñadores de sistemas operativos. No se podía usar un kernel idéntico
en todos los modelos, puesto que no utilizaría plenamente las capacidades de un modelo o bien
proporcionaría un rendimiento bajo.
Se usaba un procedimiento elaborado, denominado generación de sistemas, para obtener un
kernel que era apropiado para la configuración de un sistema de cómputo. El procedimiento se
codificaba en forma de una herramienta de generación de sistemas. Una distribución del SO era
un conjunto de cintas magnéticas que contenían la herramienta de generación de sistemas y otros
códigos del SO. Se cargaba físicamente en el sistema de cómputo donde se tenía que instalar el
SO. Un experto en sistemas desarrollaba una especificación del sistema de cómputo, es decir,
los detalles de su CPU, memoria y dispositivos de E/S, así como una especificación del entor-
no operativo. Estas especificaciones formaban la entrada para la herramienta de generación de
sistemas. La herramienta generaba una versión del kernel cuyas estructuras de datos contenían
la especificación del sistema. El kernel generado se cargaba al disco. Luego se copiaban otras
partes del SO al disco para formar una versión usable del SO.
Desde aquel entonces, los sistemas operativos han recorrido un largo camino. Hoy en día,
las distribuciones pueden estar guardadas en discos compactos o accedidos a través de la red.
Una distribución contiene los siguientes elementos:

• Un kernel que contiene un conjunto mínimo de dispositivos.


• Módulos del SO.
• Una utilidad de configuración del kernel para adaptarlo a la configuración del sistema de
cómputo.

En muchos sentidos, la utilidad de configuración del kernel es una variante avanzada de un


programa de generación de sistemas. La diferencia no es de naturaleza conceptual, sino simple-
mente una cuestión de detalles. Dada la sofisticación del hardware contemporáneo, es posible
que un SO encuentre detalles acerca de distintos CPU, tamaños de memoria y dispositivos de
E/S en el propio hardware. Tal como se describió al principio de este capítulo, el procedimiento
de inicialización del sistema puede consultar estos detalles usando instrucciones especiales, y

16 MAQ. CAP. 14(F0694).indd 614 8/10/07 1:17:10 AM


14.9 Arquitectura de Unix 615

registrar la información necesaria en tablas del kernel, por lo que la especificación del sistema
no necesita incrustarse directamente en éstas. La utilidad de configuración acepta otros ítems de
entradas de la generación de sistemas de manera interactiva desde el administrador de sistema
durante la instalación del SO, y prepara una versión correspondiente del kernel. Ésta se escribe
en el disco y la versión mínima del kernel copiada de la distribución del SO se borra. Luego de
terminar esto, se pide que el administrador del sistema lo reinicialice para que el kernel generado
asuma su control.

Configuración dinámica del kernel Los planteamientos de configuración de los kernel


que usan el programa de generación de sistemas y la utilidad de configuración del kernel tienen
una característica en común. Todas las variaciones en el kernel tienen que ser predefinidas y los
detalles correspondientes, especificados durante la generación del kernel. Este arreglo no pro-
porciona la suficiente flexibilidad para la evolución del sistema; por ejemplo, no permite el uso
de un nuevo tipo de dispositivo de E/S. Esta dificultad se resuelve mediante la configuración del
kernel en forma dinámica durante la operación del sistema. El sistema operativo de Linux ofrece
esta característica.
La configuración dinámica se implementa por medio de la integración de un nuevo módulo
y del supervisor, a través del ligado dinámico cuando se usa el módulo por primera vez. Esto
permite que el nuevo módulo acceda a módulos y estructuras de datos clave del kernel.

14.9 ARQUITECTURA DE UNIX

En las secciones anteriores hemos analizado la estructura de sistemas operativos, es decir, la


disposición de sus partes, así como las propiedades de estos arreglos. En ésta y en la siguiente
sección estudiaremos la arquitectura de dos sistemas operativos modernos de uso muy común:
Unix y Windows, lo que se refiere, aparte de la estructura del sistema operativo, a las propieda-
des de componentes del SO y a las relaciones entre ellos.
Unix es un sistema operativo basado en el kernel. La figura 14.9 es un diagrama del kernel
de Unix, que consiste en dos componentes principales: la administración de procesos y la ad-
ministración de archivos. Estos componentes se activan mediante interrupciones declaradas en
el hardware y llamadas al sistema hechas por programas no kernel del SO. Los programas no
kernel, a su vez, interactúan con la interfaz de usuarios del SO. La comunicación interproceso
involucra a facilidades para la comunicación y sincronización entre procesos. El componente de
administración de archivos ejecuta E/S por medio de controladores de dispositivos. Cada con-
trolador de dispositivo maneja una clase específica de dispositivos de E/S y usa técnicas como
la planificación del disco para asegurar la buena capacidad de procesamiento de un dispositivo
de E/S. La caché de buffers se usa para reducir esperas de E/S y el número de operaciones de
E/S para dispositivos como discos. (La planificación de discos y las cachés de dispositivos se
analizan en el capítulo 12.)
El kernel de Unix tiene una larga historia de cuatro décadas. El kernel original fue pequeño
y sencillo. Proporcionaba un pequeño conjunto de abstracciones, características pequeñas pero
poderosas como el mecanismo pipe (vía de transferencia), que permitía que usuarios crearan
la estructura computacional de ejecución secuencial de varios programas individuales (véase la
sección 1.3.1), así como un pequeño sistema de archivos que únicamente admitía una organi-
zación de archivos llamada por la organización de flujo de bytes. Todos los dispositivos se

16 MAQ. CAP. 14(F0694).indd 615 8/10/07 1:17:10 AM


616 CAPÍTULO 14 La estructura de los sistemas operativos

Programas no kernel

Llamadas al sistema
Interrupciones Kernel

Administración
de archivos

Comunica- Administra-
Planificador ción inter- ción de
Caché de proceso memoria
buffers

Controladores Administración de proceso


de dispositivos

Hardware

Figura 14.9 Kernel del sistema operativo Unix.

representaban como archivos, lo que unificaba la administración de dispositivos y archivos de


E/S. El kernel estaba escrito en el lenguaje C y tenía un tamaño menor a 100 K bytes, por lo que
era fácil de transportar.
El kernel Unix tiene dos puntos débiles: es monolítico y no es extensible. Por esta razón,
tuvo que modificarse conforme evolucionaron nuevos entornos de cómputo, por ejemplo, el
ambiente de cliente/servidor. Asimismo, el soporte para la realización de redes requirió la mo-
dificación del kernel.
El principal punto fuerte de Unix fue su uso de estándares abiertos. Esto permitía que
un gran número de organizaciones comprendidas entre el mundo académico y la industria
participaran en su desarrollo, lo que llevó al uso extendido de Unix, pero también al desarrollo
de un gran número de variantes debido a los desarrollos concurrentes y no coordinados. El kernel
se volvió voluminoso y creció hasta varios M bytes de tamaño, lo que afectaba su portabilidad.
Aproximadamente en ese periodo se agregó una herramienta para cargar módulos de kernel a
la memoria en forma dinámica. Esto permitió que sólo pudieran cargarse módulos del kernel
cuando se necesitaban. Tal característica redujo el requerimiento de memoria del kernel, mas no
el tamaño de su código, por lo que no aumentaba su portabilidad de alguna manera.
Se hicieron varios esfuerzos para rediseñar el kernel de Unix a fin de hacerlo modular y
extensible. El kernel Mach, que tiene un énfasis específico en sistemas multiprocesadores, es un
ejemplo de esta tendencia. Posteriormente, el desarrollo de Mach dio como resultado un sistema
operativo basado en el microkernel.

16 MAQ. CAP. 14(F0694).indd 616 8/10/07 1:17:10 AM


14.10 El kernel de Linux 617

14.10 EL KERNEL DE LINUX

El sistema operativo Linux ofrece las funcionalidades de Unix System V y Unix BSD; también
está en conformidad con el estándar POSIX. Inicialmente, fue implementado en el Intel 80386 y
desde entonces lo ha sido en procesadores Intel posteriores y en varias otras arquitecturas.
Linux tiene un kernel monolítico, diseñado para consistir en un conjunto de módulos indivi-
dualmente cargables. Cada módulo tiene una interfaz bien especificada que indica cómo pueden
invocarse sus funcionalidades y cómo otros módulos pueden acceder a sus datos. A la inversa,
esta interfaz también indica las funciones y datos de otros módulos que son usados por este
módulo. Cada módulo puede cargarse o retirar de la memoria en forma individual, dependiendo
de la probabilidad de su uso en el futuro próximo. Por principio, todo componente del kernel
puede estructurarse como un módulo cargable, pero normalmente los controladores de dispositi-
vos se convierten en módulos separados.
Algunos módulos del kernel se cargan cuando se inicializa el sistema; otros, en forma di-
námica conforme son necesitados. En cualquier momento existen unos cuantos módulos del
kernel en la memoria. El kernel mantiene informaciones acerca de sus funciones y datos para
ser usados mientras carga un nuevo módulo. Cuando debe cargarse un nuevo módulo, el ker-
nel “ata” ese módulo a otros módulos, obteniendo las direcciones de las funciones y datos de
otros módulos que usa el nuevo módulo, y las inserta en las instrucciones correspondientes del
nuevo módulo. Este paso integra el nuevo módulo con los módulos que ya existen en la memo-
ria, por lo que todos constituyen un kernel monolítico. Entonces el kernel agrega informaciones
sobre las funciones y datos del nuevo módulo a las informaciones que ya tiene.
El uso de módulos del kernel con interfaces bien especificadas simplifica la verificación
y mantenimiento del kernel. Un módulo individual puede ser modificado de tal manera que
proporcione nuevas funcionalidades o mejore las existentes. Esta característica supera la baja
extensibilidad que normalmente está asociada a kernel monolíticos. El uso de módulos cargables
también limita el requerimiento de memoria del kernel, porque algunos módulos posiblemen-
te no estén cargados durante una operación del sistema. Para aumentar esta ventaja, el kernel
tiene una herramienta que automáticamente retira módulos no deseados de la memoria: produce
periódicamente una interrupción y verifica cuáles de sus módulos en la memoria no fueron usa-
dos desde la última de estas interrupciones. Estos módulos son desligados del kernel y se elimi-
nan de la memoria. En forma alternativa, los módulos pueden ser individualmente cargados y
eliminados de la memoria por medio de llamadas al sistema.
El kernel de Linux 2.6, que fue comercializado en 2003, eliminó gran parte de las limitacio-
nes del kernel de Linux 2.5 y también mejoró sus capacidades de varias maneras. Dos de las me-
joras más destacadas fueron que el sistema es ahora más receptivo y capaz de soportar sistemas
incrustados. Los kernel antes de Linux 2.5 fueron no priorizables, de tal modo que si el kernel
estuvo ocupado con la realización de una tarea de baja prioridad, se retrasaban tareas del ker-
nel de mayor prioridad. El kernel de Linux 2.6 es priorizable, lo que lo hace más receptivo a
usuarios y programas de aplicación. Sin embargo, el kernel no deberá priorizarse cuando sea
difícil de salvar su estado o cuando esté realizando operaciones sensibles, por lo que el kernel
deshabilita y habilita su propia priorizabilidad por medio de funciones especiales. El kernel de
Linux 2.6 también puede admitir arquitecturas que no poseen una unidad de administración de
memoria (MMU), por lo que resulta apropiado para sistemas incrustados. Ahora puede usar-
se el mismo kernel en sistemas incrustados, computadoras de escritorio y servidores. La otra
característica notable en el kernel de Linux 2.6 es la mejor escalabilidad por medio de un mode-

16 MAQ. CAP. 14(F0694).indd 617 8/10/07 1:17:10 AM


618 CAPÍTULO 14 La estructura de los sistemas operativos

lo mejorado de hilos, un planificador mejorado y la sincronización rápida entre procesos; estas


características se describen en los capítulos posteriores.

14.11 ARQUITECTURA DE WINDOWS

La figura 14.10 muestra la arquitectura del SO de Windows. La capa de abstracción de hardware


(HAL) se comunica con el hardware de la máquina y proporciona abstracciones de las interfa-
ces de E/S, controladores de interrupciones y mecanismos de comunicación entre procesadores
en un sistema multiprocesador. El kernel usa las abstracciones proporcionadas por HAL para
ofrecer servicios básicos, tales como el procesamiento de interrupciones y la sincronización de
multiprocesadores. De este modo, el kernel está protegido contra las peculiaridades de una ar-
quitectura específica, lo que aumenta su portabilidad. La HAL y el kernel en conjunto son equi-
valentes a un kernel convencional (véase la figura 14.7). Un controlador de dispositivo también
usa las abstracciones proporcionadas por HAL para gestionar operaciones de E/S en una clase
de dispositivos.

Aplicación
Subsistemas de usuario
del entorno
DLL de
subsistemas

Ejecutivo

Adminis-
trador Controladores de
Kernel dispositivos
de E/S
Capa de abstracciones de hardware (HAL)

Hardware de la máquina

Figura 14.10 Arquitectura de Windows.

El kernel realiza las funciones de sincronización de procesos y planificación (véase la sec-


ción 4.8). El ejecutivo comprende los programas no kernel del SO; su código usa facilidades en
el kernel para proporcionar servicios como creación y terminación de procesos (véase la sección
3.5.4), administración de memoria virtual (véase la sección 6.9), una facilidad de pase de mensa-
jes entre procesos para la comunicación servidor/cliente denominada llamada de procedimiento
local (LPC), administración de E/S y de una caché de archivos para proporcionar un eficiente
E/S de archivos (véase la sección 12.2), y un monitor de referencias de seguridad que mejora el

16 MAQ. CAP. 14(F0694).indd 618 8/10/07 1:17:10 AM


Bibliografía 619

control de acceso para archivos. El administrador de E/S usa controladores de dispositivos que
se cargan en forma automática cuando es necesario. Muchas funciones del ejecutivo operan en
el modo del kernel y evitan de esta manera cambios de contexto frecuentes cuando el ejecutivo
interactúa con el kernel. Este arreglo tiene beneficios de desempeño obvios.
Los subsistemas del entorno proporcionan apoyo para la ejecución de programas desarrolla-
dos para otros sistemas operativos, como MS-DOS, Win32 y OS/2. De hecho, un subsistema de
entorno es análogo a un sistema operativo de invitado dentro de un SO de máquina virtual (véase
la sección 14.5). Opera como un proceso que se mantiene al tanto del estado de aplicaciones
de usuarios que usan sus servicios. Para implementar la interfaz de un SO invitado, cada sub-
sistema del entorno proporciona una biblioteca de ligas dinámicas (DLL) y espera que una apli-
cación de usuario invoque la DLL cuando necesita un servicio de sistema específico. La DLL
implementa el servicio requerido por su cuenta propia, o lo pasa al ejecutivo o envía un mensaje
al proceso del subsistema del entorno para que se proporcione el servicio.

EJERCICIO 14

1. Prepare una tabla que muestre varios manejadores de eventos en un SO y las interrupciones que los
activan.
2. Un proceso que está haciendo una llamada al sistema necesita intercambiar informaciones relevantes
con el manejador de eventos invocado por la llamada. Describa las informaciones que deberán
intercambiarse para cada manejador de evento invocado por una llamada al sistema (vea la tabla que
usted construyó en el problema 1).
3. El mecanismo de planificación “manipula listas de planificación” (véase la tabla 14.4), cambia estados
de procesos y mueve procesos entre listas de planificación. Describa las condiciones bajo las cuales
diferentes funciones invocan a este mecanismo.

BIBLIOGRAFÍA
Dijkstra (1968) describe la estructura del sistema de multiprogramación THE. El sistema operativo de
máquina virtual VM/370 está basado en CP/67 y se describe en Creasy (1981). Los productos de máqui-
nas virtuales XEN y VMware se describen en Barham et al. (2003) y Sugarman et al. (2001), respecti-
vamente.
Warhol (1994) analiza los progresos hechos a pasos agigantados por microkernels a principios de los
noventa, mientras que Liedtke (1996) describe los principios de diseño para microkernels. Engler et al.
(1995) analizan el diseño de un microkernel. Bach (1986), Vahalia (1996) y McKusick et al. (1996) des-
criben el kernel de Unix. Beck et al. (2002), Bovet y Cesati (2003) y Love (2005) lo hacen con respecto
al kernel de Linux, mientras que Mauro y McDougall (2001) describen el kernel de Solaris. Tanenbaum
(2001) describe los microkernel de los sistemas operativos de Amoeba y Mach. Russinovich y Solomon
(2005) describen la arquitectura de Windows.

1. Bach, M.J. (1986): The Design of the Unix Operating System, Prentice Hall, Englewood Cliffs.
2. Barham, P., B. Dragovic, K. Fraser, S. Hand, T. Harris, A. Ho, R. Neugebauer, I. Pratt y A. Warfield
(2003): “XEN and the art of virtualization”, ACM Symposium on Operating System Principles,
164-177.

16 MAQ. CAP. 14(F0694).indd 619 8/10/07 1:17:10 AM


620 CAPÍTULO 14 La estructura de los sistemas operativos

3. Beck, M., H. Bohme, M. Dziadzka, U. Kunitz, R. Magnus, C. Schroter y D. Verworner (2002):


Linux Kernel Programming, 3a. ed., Pearson Education.
4. Bovet, D.P. y M. Cesati (2003): Understanding the Linux Kernel, O’Reilly, Sebastopol.
5. Creasy. R.J. (1981): “The origin of the VM/370 time-sharing system”, IBM Journal of Research
and Development, 25 (5), 483-490.
6. Dijkstra, E.W. (1968): “The structure of THE multiprogramming system”, Communications of the
ACM, 11, 341-346.
7. Engler D.R., M.F. Kasshoek y J. O’Toole (1995): “Exokernel: An operating system architecture
for application-level resource management”, Symposium on OS Principles, 251-266.
8. Liedtke J. (1996): “Towards real microkernels”, Communications of the ACM, 39 (9).
9. Love, R. (2005): Linux Kernel Development, 2a. ed., Novell Press.
10. Mauro, J. y R. McDougall (2001): Solaris Internals—Core Kernel Architecture, Prentice Hall.
11. McKusick, M.K., K. Bostic, M.J. Karels y J.S. Quarterman (1996): The Design and Implementation
of the 4.4 BSD Operating System, Addison Wesley, Reading.
12. Meyer, J. y L. H. Seawright (1970): “A virtual machine time-sharing system”, IBM Systems Jour-
nal, 9 (3), 199-218.
13. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.
14. Sugarman, J., G. Venkitachalam y B.H. Lim (2001): “Virtualizing I/O devices on VMware
workstation’s hosted virtual machine monitor”, 2001 USENIX Annual Technical Conference.
15. Tanenbaum, A.S. (2001): Modern Operating Systems, 2a. ed., Prentice Hall, Englewood Cliffs.
16. Vahalia, U. (1996): “UNIX Internals—the New Frontiers”, Prentice Hall, Englewood Cliffs, New
Jersey, 1996.
17. Warhol, P.D. (1994): “Small kernels hit it big”, Byte, enero de 1994, 119-128.

16 MAQ. CAP. 14(F0694).indd 620 8/10/07 1:17:11 AM


Parte III
Sistemas operativos
distribuidos

Un sistema distribuido consiste en varios nodos, donde cada uno es un sistema de cómputo con
su propio reloj y memoria que pueden comunicarse entre sí a través de una red. Un sistema
operativo distribuido aprovecha estas características de la siguiente manera: el sistema permite
que un usuario estructure su aplicación como un cálculo distribuido, que consiste en varios pro-
cesos ubicados en diferentes nodos del sistema distribuido. Para dar servicio a todos los proce-
sos del sistema en forma eficiente, equilibra las cargas computacionales en varias computadoras
mediante la transferencia de procesos entre nodos si es necesario. De esta manera, los procesos
de una aplicación pueden competir por los CPU en diferentes nodos, lo que proporciona una
aceleración de cálculo dentro de la aplicación y un mejor desempeño del sistema. Además, el
SO usa la redundancia de recursos y ligas de la red en el sistema a fin de proporcionar alta con-
fiabilidad.
Para obtener estas ventajas de aceleración del cálculo, desempeño y confiabilidad, el SO
tiene que realizar funciones de control, como la planificación y el manejo de bloqueos mutuos en
todo el sistema. Debido a la naturaleza distribuida de éste, un SO distribuido no puede usar las
nociones de tiempo y estado del mismo modo que un SO convencional para realizar funciones de
control, por lo que realiza estas funciones de manera distribuida, es decir, por medio de procesos
en varias computadoras que trabajan en estrecha coordinación para tomar decisiones.
La presencia de la red tiene varias implicaciones para el SO distribuido. Una falla no pa-
raliza todo el sistema. Posiblemente sólo afecte a algunos cálculos, o a algunas partes de un
cálculo, por lo que el SO distribuido usa técnicas de confiabilidad especiales para minimizar el
impacto de una falla. La comunicación a través de la red es lenta; por tanto, puede seriamente
erosionar el desempeño del sistema si los procesos acceden a sus archivos a través de ella. Para
prevenir eso, los sistemas de archivos distribuidos emplean técnicas que reducen el tráfico de la
red durante el procesamiento de archivos. El componente de realización de redes también hace
que el SO sea susceptible a ataques de seguridad, por lo que emplea técnicas especiales para
garantizar ésta.

17 MAQ. PARTE 3.indd 621 8/10/07 1:17:47 AM


622 Parte III Sistemas operativos distribuidos

Guía para la parte III


Sistemas
operativos
distribuidos

Problemas teóricos Seguridad de


en sistemas sistemas
distribuidos distribuidos

Algoritmos Recuperación
de control y tolerancia
distribuidos de fallas

Sistemas de
archivos
distribuidos

Capítulo 15: Sistemas operativos distribuidos


Un sistema distribuido consiste en componentes de hardware, tales como sistemas de
cómputo y la red, y componentes de software, tales como protocolos de redes, cálculos distri-
buidos y el sistema operativo. En este capítulo se discuten características importantes de estos
componentes y la forma en que influyen en la aceleración de cálculo, confiabilidad y desempeño
que pueden ser proporcionados por un sistema operativo distribuido.

Capítulo 16: Problemas teóricos en sistemas distribuidos


Tiempo y estado son dos nociones clave que se usan en un SO convencional. Estas nociones
están ausentes en un sistema distribuido porque contiene varios sistemas de cómputo, cada uno
con su propio reloj y memoria, que se comunican por medio de mensajes que provocan retrasos
de comunicación impredecibles. Este capítulo analiza alternativas prácticas a las nociones tradi-
cionales de tiempo y estado, que se usan en el diseño de algoritmos de control distribuidos y en
esquemas de recuperación empleados en un SO distribuido.

Capítulo 17: Algoritmos de control distribuidos


Un SO distribuido usa un algoritmo de control distribuido (DCA) para implementar una
función de control. El algoritmo involucra acciones en varios nodos del sistema distribuido. Este
capítulo aborda diferentes clases de algoritmos de control distribuido y presenta algoritmos para
realizar cinco funciones de control en un SO distribuido: exclusión mutua, manejo de bloqueos
mutuos, planificación, detección de terminación y elección del líder.

Capítulo 18: Recuperación y tolerancia de fallas


Una falla podrá trastornar la operación de un sistema, dañando los estados de algunos datos
y procesos. El enfoque de recuperación es la restauración de datos o procesos a un estado con-
sistente, tal que se pueda restaurar la operación normal. La tolerancia de fallas proporciona la

17 MAQ. PARTE 3.indd 622 8/10/07 1:17:47 AM


Parte III Sistemas operativos distribuidos 623

operación ininterrumpida del sistema a pesar de las fallas. Este capítulo analiza las técnicas de
recuperación y tolerancia de fallas que se usan en un sistema operativo distribuido. También se
analiza la resiliencia, técnica empleada para la minimización del impacto de una falla.

Capítulo 19: Sistemas de archivos distribuidos


Un sistema de archivos distribuidos (DFS) almacena archivos en varios nodos de un sistema
distribuido, por lo que el proceso y el archivo que usa podrían estar ubicados en diferentes nodos
de un sistema. La conveniencia del usuario en el uso de un DFS es determinado por la manera
en que ordena archivos y directorios en los nodos de un sistema distribuido. El desempeño y la
confiabilidad de un DFS son determinados por la manera como se accede a un archivo solicitado.
Este capítulo analiza los diferentes modelos que se usan para organizar archivos y directorios
en los nodos de un sistema, así como técnicas tales como formación de cachés y servidores de
archivos sin estado que se usan para asegurar el buen desempeño y la buena confiabilidad, res-
pectivamente.

Capítulo 20: Seguridad de sistemas distribuidos


La presencia de la red hace que un sistema distribuido sea susceptible a ataques contra la
seguridad lanzados por medio de mensajes interproceso. Este capítulo estudia cómo pueden los
procesos garantizar la seguridad de mensajes y verificar la autenticidad de datos y mensajes para
frustrar estos ataques.

17 MAQ. PARTE 3.indd 623 8/10/07 1:17:47 AM


17 MAQ. PARTE 3.indd 624 8/10/07 1:17:48 AM
Capítulo
15
Sistemas operativos
distribuidos

La confiabilidad y desempeño de un sistema distribuido son influidos por las características


de cuatro componentes de hardware y software: los sistemas computacionales existentes en el
sistema distribuido, la red que los conecta, los cálculos distribuidos realizados en el sistema
y el sistema operativo. Esta influencia se da de la siguiente manera. Un sistema de cómputo
forma un nodo de un sistema distribuido. Su arquitectura influye en su capacidad para proveer
la aceleración de computación y confiabilidad de operación. El sistema operativo integra la ope-
ración de nodos de un sistema distribuido a fin de realizar el potencial para compartir recursos,
aceleración de computación y confiabilidad en un sistema distribuido. Un usuario emplea una
computación distribuida, cuyas acciones se realizan en varios nodos del sistema a fin de explotar
las características del SO para el acceso a recursos no locales y la aceleración de computación.
Estas computaciones usan protocolos de comunicación interproceso (IPC), que son conjuntos
de reglas que aseguran la comunicación efectiva de datos para transferir en forma confiable men-
sajes que contienen datos y cálculos entre nodos. Estos mensajes se envían realmente a través de
la red por medio de protocolos de red.

15.1 CARACTERÍSTICAS DE SISTEMAS DISTRIBUIDOS

Un sistema distribuido consiste en dos o más sistemas de cómputo, cada uno con su propia me-
moria, algo de hardware de red y la capacidad para realizar algunas de las funciones de control
del SO (véase la definición 2.10). Las características de un sistema distribuido se analizaron en
la sección 2.8 y se resumen aquí en la tabla 15.1.
El uso de los sistemas distribuidos se difundió rápidamente en los noventa, cuando disminu-
yeron los precios para hardware de cómputo y el uso del estándar del sistema abierto facilitaba
el crecimiento incremental de un sistema. Un sistema abierto tiene interfaces bien definidas y

18 MAQ. CAP. 15(F0694).indd 625 8/10/07 1:18:24 AM


626 CAPÍTULO 15 Sistemas operativos distribuidos

Tabla 15.1 Características de un sistema distribuido

Característica Descripción
Compartición Las aplicaciones pueden usar recursos ubicados en cualquier
de recursos sistema de computación.
Confiabilidad Un sistema distribuido provee la disponibilidad, es decir, la
continuidad de los servicios a pesar de fallas. Esto se logra me-
diante redundancias en la red y en los recursos, así como en los
servicios del SO.
Aceleración La aceleración de computación se logra mediante la ejecución
de la computación de partes de una computación en paralelo en diferentes siste-
mas de cómputo.
Comunicación Usuarios de sus subcomputaciones ubicados en diferentes no-
dos pueden comunicarse en forma confiable usando los servi-
cios del SO.
Crecimiento Los estándares de sistema abierto permiten que se añadan nue-
incremental vos subsistemas a un sistema distribuido sin tener que reempla-
zar o actualizar subsistemas existentes. De este modo, el costo
para aumentar las capacidades de un sistema distribuido es pro-
porcional a la deseada capacidad adicional.

no propietarias con sus propios componentes y con otros sistemas. Éstas son normalmente desa-
rrolladas o aprobadas por un cuerpo de normas, por lo que tienen una aceptación abierta dentro
de la industria de la informática. Su uso habilita la adición de nuevos componentes y subsistemas
a un sistema de cómputo y facilita así el crecimiento incremental. La red de área local (LAN) es
un excelente ejemplo para un sistema abierto. Toda la gama de sistemas de cómputo, desde las
supercomputadoras caras hasta las PC económicas, puede conectarse a ella porque todos usan
una interfaz estándar. Cuando se implementa un sistema distribuido por medio de una LAN, sus
capacidades de computación pueden incrementarse conectando un nuevo sistema de cómputo a
la LAN.
Las características de los sistemas distribuidos enumeradas en la tabla 15.1 se realizan usan-
do los siguientes componentes de hardware y software:

• Componentes de hardware: Sistemas de cómputo individuales y hardware de realización


de redes tales como cables, ligas y amplificadores.
• Componentes de software: Componentes de sistemas operativos que manejan la creación
y planeación de cálculos distribuidos y recursos distantes, herramientas de SO y lengua-
jes de programación que admiten la escritura de cálculos distribuidos, así como software
de realización de redes que aseguran la comunicación confiable.

Se usan varios términos para un sistema de cómputo que forma parte de un sistema distribui-
do. Nosotros usaremos la siguiente convención: un host es un sistema de cómputo en el sentido
físico, un nodo es un sistema de cómputo en el sentido lógico y un sitio es una ubicación en un
sistema distribuido que contiene un host. Entidades en el mismo sitio, tales como procesos y
recursos, se conocen como entidades locales, y las que se sitúan en sitios diferentes se llaman
entidades distantes.

18 MAQ. CAP. 15(F0694).indd 626 8/10/07 1:18:24 AM


15.3 Sistemas operativos de red 627

15.2 NODOS DE SISTEMAS DISTRIBUIDOS

Un sistema distribuido contiene diferentes tipos de nodos. Un nodo de minicomputadora tiene


un solo CPU que es compartido para dar servicio a aplicaciones de varios servidores. Un nodo
de estación de trabajo también tiene un solo CPU, pero da servicio a una o varias aplicaciones
iniciadas por un solo usuario. Un nodo que es un sistema multiprocesador se llama nodo de pool
de procesadores. Contiene varios CPU y el número de éstos posiblemente exceda el de usuarios
a cuyas aplicaciones se da servicio en forma paralela.

RAID

P CU CU CU CU P
Nodo Nodo
M M

LAN privada

Red pública
Figura 15.1 Arquitectura de un cluster.

Un cluster es un grupo de host que trabajan en conjunto en forma integrada. Constituye


un solo nodo de un sistema distribuido; cada host individual es un nodo dentro del cluster. El
software de cluster controla la operación de todos los nodos en un cluster. Posee algunas carac-
terísticas de un sistema operativo distribuido, tales como la planificación para lograr aceleración
de computación y confiabilidad. La figura 15.1 es un diagrama esquemático de la arquitec-
tura de un cluster. El que se muestra tiene dos nodos; sin embargo, podrán agregarse más nodos
para proveer el crecimiento incremental. Cada nodo es un sistema de cómputo con su propia
memoria y dispositivos de E/S. Los nodos comparten el almacenamiento de discos, que po-
dría ser un RAID de múltiples host, que ofrece tanto una alta velocidad de transmisión como
alta confiabilidad (véase la sección 12.3.3), o una red de áreas de almacenamiento, que ofrece el
crecimiento incremental. Cada nodo está conectado a dos redes: una LAN privada a la que sólo
los nodos del cluster están conectados y una red pública a través de la cual se puede comunicar
con otros nodos en el sistema distribuido.
El software del cluster puede proveer la aceleración de cálculos mediante la planificación
de subtareas en una aplicación en diferentes nodos dentro del cluster, y la confiabilidad mediante
el aprovechamiento de la redundancia de los CPU y otros recursos dentro del cluster. La sección
15.4 describe cómo se implementan estas características en el servidor de cluster de Windows y
en el de Sun.

15.3 SISTEMAS OPERATIVOS DE RED


Un sistema operativo de red es la forma más antigua de un SO para arquitecturas distribuidas.
Su objetivo es proveer la compartición de recursos entre dos o más sistemas de cómputo bajo sus

18 MAQ. CAP. 15(F0694).indd 627 8/10/07 1:18:25 AM


628 CAPÍTULO 15 Sistemas operativos distribuidos

propios SO. Como se muestra en el esquema de la figura 15.2, existe una capa de SO de red entre
el kernel del SO local y los procesos de usuarios. Estos últimos interactúan con la capa de SO
de red en lugar del kernel del SO local. El proceso solicita acceso al recurso no local, el SO de
red contacta la capa de SO de red del nodo que contiene el recurso e implementa el acceso a
éste con su ayuda. Si un proceso solicita acceso a un recurso local, la capa de SO de red sim-
plemente pasa la solicitud al kernel del SO local. Muchos sistemas operativos de red han sido
desarrollados usando como base el sistema operativo de Unix. La conexión Newcastle, tam-
bién denominada Unix United, es un famoso SO de red desarrollado en la Universidad de New-
castle-upon-Tyne. Provee el acceso a archivos remotos usando llamadas al sistema que son idén-
ticas a las que se usan para archivos locales.

Proceso usuario Proceso usuario

Capa de OS Capa de OS
Sistema de de red de red Sistema de
cómputo 1 Kernel del Kernel del cómputo 2
SO local SO local

Figura 15.2 Un sistema operativo de red.

Un sistema operativo de red es más fácil de implementar que un SO distribuido de pleno


derecho. Sin embargo, los sistemas operativos locales conservan sus identidades y se comportan
como sistemas operativos independientes, por lo que su funcionamiento no está integrado y sus
identidades son visibles para los usuarios. En algunos SO de red, un usuario tiene que iniciar
sesión en un sistema operativo remoto antes de poder usar sus recursos. Este arreglo implica que
debe saber dónde se ubica un recurso a fin de usarlo.
Un SO de red no puede equilibrar ni optimizar la utilización de recursos porque éstos no
están bajo su control. Por tanto, algunos recursos en un nodo pueden estar sumamente cargados,
mientras que otros recursos idénticos en otros nodos pueden estar ligeramente cargados o libres.
El SO de red tampoco puede proveer la tolerancia de fallas; una computación explícitamente usa
una id de recurso mientras accede a un recurso, por lo que tiene que ser cancelada si éste falla.

15.4 SISTEMAS OPERATIVOS DISTRIBUIDOS

Un SO distribuido controla la operación de todos los nodos del sistema de manera bien inte-
grada, haciendo que el kernel de cada nodo realice funciones de control en su representación.
Las ventajas resumidas en la tabla 15.1 se realizan esparciendo los procesos de una aplica-
ción a través de varios nodos del sistema 1) cada vez que sea posible, para lograr la aceleración
de computación y eficiencia de recursos, y 2) cada vez que sea necesario, para lograr confiabi-
lidad. Analizaremos algunos sistemas para proporcionar un resumen de las características de
sistemas operativos distribuidos. En la sección 15.9 estudiaremos características en el diseño
del kernel.

18 MAQ. CAP. 15(F0694).indd 628 8/10/07 1:18:25 AM


15.4 Sistemas operativos distribuidos 629

Software de clusters en Sun y Windows Un software de clusters no es un sistema opera-


tivo distribuido, pero contiene varias características que se encuentran en estos sistemas: provee
la disponibilidad por medio de la redundancia de recursos tales como los CPU y otros medios de
E/S, y la aceleración de computación mediante el aprovechamiento de la presencia de varios
CPU dentro del cluster.
El servidor de cluster de Windows ofrece el soporte de tolerancia de fallas en clusters que
contienen dos o más nodos del servidor. La tolerancia de fallas básica se proporciona por me-
dio de RAIDS de los niveles 0, 1 o 5 (véase la sección 12.3.3), que son compartidos por todos
los nodos del servidor. Además, cuando ocurre una falla o un paro en un servidor, el servidor
de clusters mueve sus funciones a otro sin causar un trastorno en sus servicios. Una aplicación
tiene que usar una interfaz de programas de aplicaciones especial (API) para acceder a servicios
de clusters.
Un cluster es administrado usando algoritmos de control distribuidos que son implementa-
dos por medio de acciones realizadas en todos los nodos (véase el capítulo 17). Estos algoritmos
requieren que todos los nodos tengan una vista constante del cluster, es decir, deben poseer listas
idénticas de nodos dentro del cluster. El siguiente arreglo se usa para satisfacer este requerimien-
to: cada nodo tiene un administrador de nodos que lleva la lista de nodos en un cluster. El admi-
nistrador de nodos periódicamente envía mensajes denominados heartbeat (pulsaciones, latidos
del corazón) a otros administradores de nodos para detectar una falla de nodo, y lo anuncia a
otros nodos del cluster por medio de un mensaje difundido en la LAN privada. Tras la recepción
de este mensaje, cada administrador de nodos corrige su lista de nodos. Este evento es denomi-
nado evento de reagrupación.
Un recurso en el servidor de cluster puede ser un recurso físico, un recurso lógico o un servicio.
Un recurso es implementado como una biblioteca de ligas dinámicas (DLL), por lo que está
especificado que proporciona una interfaz de DLL. Un recurso pertenece a un grupo. Un grupo
le pertenece a un nodo del cluster en algún momento dado; sin embargo, puede ser trasladado a
otro nodo en el evento de una falla. El administrador de recursos de un nodo es responsable de
iniciar y detener un grupo. Si falla un recurso, el administrador de recursos avisa al administra-
dor de respaldo de ejecución y le entrega el grupo que contiene el recurso, por lo que puede ser
reiniciado por otro nodo. Cuando se detecta una falla de nodo, se “jalan” todos los grupos ubica-
dos en este nodo a otros grupos para que se pueda acceder a los recursos contenidos en ellos. El
uso de un disco compartido facilita ese arreglo. Cuando se reinicia un nodo después de una falla,
el administrador de respaldo de ejecución decide qué grupo se le puede entregar. Esta acción se
llama recuperación y salvaguarda la eficiencia de recursos en el sistema. Las acciones de entrega
y recuperación también pueden realizarse en forma manual.
La herramienta de equilibrio de la carga de la red distribuye el tráfico de red entrante entre
los nodos del servidor en un cluster. Esto se logra de la siguiente manera: se asigna una sola
dirección IP al cluster; sin embargo, mensajes entrantes van a todos los nodos del servidor en el
cluster. Dependiendo del arreglo actual de distribución de carga, exactamente uno de los servi-
dores acepta el mensaje y lo contesta. Cuando un nodo falla, su carga se distribuye entre otros
nodos, y cuando se agrega un nuevo nodo, se reconfigura la distribución de carga de tal manera
que dirige parte del tráfico entrante al nuevo nodo.
La estructura de cluster de Sun integra un cluster de dos o más sistemas Sun operando bajo
el SO Solaris para proveer la disponibilidad y escalabilidad de servicios.
La disponibilidad se proporciona por medio del administrador de respaldo de ejecución,
donde los servicios que estuvieron operando en un nodo fallado son reubicados a otro nodo. La

18 MAQ. CAP. 15(F0694).indd 629 8/10/07 1:18:25 AM


630 CAPÍTULO 15 Sistemas operativos distribuidos

escalabilidad es proporcionada mediante la compartición de la carga a lo largo de los servidores.


Tres componentes clave del cluster de Sun son la administración global de procesos, el sistema
de archivos distribuidos y la realización de redes. La administración global de procesos ofrece
id de procesos globalmente únicas. Esta característica es útil en la migración de procesos, donde
se transfiere un proceso de un nodo a otro para equilibrar las cargas computacionales en diferen-
tes nodos, o para lograr la aceleración de computación. Un proceso migrado deberá ser capaz de
continuar usando los mismos nombres de rutas para acceder a archivos de un nodo nuevo. El uso
de un sistema de archivos distribuidos proporciona esta herramienta.

Amoeba Amoeba es un sistema operativo distribuido que fue desarrollado en la Universi-


dad Libre de los Países Bajos durante los ochenta. El objetivo principal del proyecto Amoeba es
el de construir un sistema operativo distribuido que se viera y sintiera como un SO estándar
de tiempo compartido, como Unix. Otro objetivo es proveer un banco de pruebas para la progra-
mación distribuida y paralela.
La arquitectura del sistema Amoeba tiene tres componentes principales: terminales X, un
pool de procesadores y servidores, tales como de archivos e impresión. La terminal X es una
estación de usuario que consiste en un teclado, un ratón y una terminal en mapa de bits conec-
tada a una computadora. El pool de procesadores tiene las características que se describen en la
sección 15.2. El microkernel de Amoeba trabaja en todos los servidores, procesadores de pool y
terminales, y realiza las cuatro siguientes funciones:

1. Manejo de procesos e hilos;


2. Propone soporte de manejo de memoria de bajo nivel;
3. Soporte de comunicación, y
4. Manejo de E/S de bajo nivel.

Amoeba proporciona hilos en el nivel del kernel y dos protocolos de comunicación. Un protoco-
lo admite el modelo de comunicación cliente-servidor por medio de llamadas al procedimiento
remoto (RPC), mientras que el otro provee la comunicación de grupos. Para la transmisión real
de mensajes, ambos protocolos usan un subyacente protocolo de Internet denominado protocolo
rápido local de Internet (FLIP) que es un protocolo de capas de red en la pila del protocolo ISO
(véase la sección 15.7.6).
Muchas de las funciones realizadas por kernel tradicionales son implementadas por medio
de servidores que trabajan encima de un microkernel. De este modo, las acciones de inicializa-
ción, creación de procesos y planeación de procesos son realizadas por servidores. El sistema
de archivos también es implementado como servidor de archivos. Este planteamiento reduce
el tamaño del microkernel y lo hace apropiado para un amplio rango de sistemas de cómputo,
desde servidores hasta procesadores de pool. El concepto de objetos es central para Amoeba.
Los objetos son manejados por servidores y son capacidades de uso protegidas (véase la sec-
ción 8.9).
Cuando un usuario comienza la sesión, se inicia un shell en algún host del sistema. Confor-
me el usuario emite comandos, se crean procesos en otros host para ejecutar los comandos. De
este modo se difunde la computación de un usuario a través de los host en el sistema; no existe
la noción de una máquina local para un usuario. Esta indiferencia para los límites de máquinas
muestra lo integrados que están todos los recursos en el sistema. Amoeba usa el modelo del pool

18 MAQ. CAP. 15(F0694).indd 630 8/10/07 1:18:25 AM


15.5 Comunicación interproceso confiable 631

de procesadores de nodos en el sistema. Cuando un usuario emite un comando, el SO asigna


procesadores del pool a la ejecución del comando. Donde sea necesario, los procesadores de
pool se comparten como usuarios.

15.5 COMUNICACIÓN INTERPROCESO CONFIABLE

En un SO convencional, los procesos que desean comunicarse por medio de mensajes existen
en el mismo host, y el kernel les asigna id únicas. Sin embargo, en un sistema distribuido,
los procesos que existen en diferentes nodos posiblemente quieran comunicarse entre sí, y por
tanto el SO distribuido asigna nombres globalmente únicos a procesos. También provee un arre-
glo por medio del cual un proceso con un nombre dado puede ser localizado en el sistema, por lo
que otros procesos pueden comunicarse con él. Analizaremos estas características en la sección
15.5.1.
Una vez que se haya determinado la ubicación de un proceso destinatario, un mensaje in-
tentado para él se le podrá enviar a través de la red. Sin embargo, la entrega del mensaje podrá
fallar debido a problemas en las ligas de comunicación o nodos que se ubican en ruta(s) de la red
hacia el proceso destinatario. Por este motivo, los procesos tienen que hacer sus propios arreglos
para asegurar la entrega confiable de mensajes. Este arreglo está en forma de un protocolo de
comunicación interproceso (protocolo IPC), que es un conjunto de reglas y convenciones con la
finalidad de manejar fallas temporales.

Tabla 15.2 Estipulaciones para la confiabilidad en un protocolo IPC

Estipulación Descripción
Confirmación Cuando un proceso recibe un mensaje, envía un acu-
se de recibo al transmisor del mensaje.
Timeout El protocolo especifica un intervalo de tiempo den-
tro del cual espera que un proceso transmisor reciba
una confirmación. Se dice que ocurre un timeout si la
confirmación no se recibe dentro de este intervalo.
Retransmisión de Un proceso transmisor retransmite su mensaje si un
un mensaje intervalo de tiempo ocurre antes de que reciba una
confirmación.

La tabla 15.2 resume tres estipulaciones clave de protocolos IPC: confirmaciones, interva-
los de tiempo y retransmisiones. Cuando un proceso envía un mensaje, el protocolo hace una
llamada de sistema al SO en el sitio del transmisor para solicitar una interrupción al final de un
intervalo de tiempo específico. Esta interrupción se llama interrupción de timeout. Cuando se
entrega el mensaje al proceso destinatario, éste envía una confirmación al proceso transmisor
para informarle que su mensaje fue entregado. Si la interrupción de timeout ocurre antes de
recibir una confirmación, el protocolo retransmite el mensaje al proceso destinatario y hace una
llamada al sistema para solicitar otra interrupción de timeout. Estas acciones se repiten hasta que
se recibe una confirmación. Se podrá usar un arreglo similar para asegurar que una respuesta

18 MAQ. CAP. 15(F0694).indd 631 8/10/07 1:18:26 AM


632 CAPÍTULO 15 Sistemas operativos distribuidos

enviada por el proceso receptor llegue al proceso transmisor. Analizaremos los protocolos ICP
en las secciones 15.5.2 y 15.5.3.

15.5.1 Nombrado de procesos

A todas las entidades en un sistema distribuido, ya sean procesos o recursos, se les asignan
nombres únicos de la siguiente manera: a cada host en un sistema se asigna un nombre único en
todo el sistema, que puede ser numérico o simbólico, y a cada proceso o recurso en un host se
le asigna una id que es única en el host. De este modo, el par (<host_name>), (<process_id>) es
único para cada proceso y se podrá usar como su nombre. Un proceso que quiere enviar un men-
saje a otro proceso usa un par como (human_resources, Pj) a manera de nombre del proceso
destinatario, donde human_resources es el nombre de un host. Este nombre se deberá traducir
en una dirección de la red para el envío del mensaje.
A fin de poder localizar un host fácilmente en el Internet, éste se divide en un conjunto
de dominios que tienen nombres únicos; cada dominio está dividido en dominios más pequeños
que tienen nombres únicos en el dominio, etc. Un host tiene un nombre único en el dominio
inmediato que lo contiene, pero su nombre posiblemente no sea único en el Internet, por lo que
se crea un nombre único para un host mediante la adición de nombres de todos los dominios
que lo contienen, separados por puntos, empezando con el dominio más pequeño y terminando
con el más grande. Por ejemplo, el nombre de host Everest.cse.iitb.ac.in se refiere al servidor
Everest del departamento CSE del IIT de Bombay, que se encuentra en el dominio académico
en la India.
Cada host conectado al Internet tiene una dirección única que se conoce como Internet
protocol address (dirección del protocolo de Internet, IP). El domain name system (sistema
de nombres de dominios, DNS) es un servicio distribuido de directorios del Internet que pro-
porciona la dirección IP de un host con un nombre dado. Tiene un servidor de nombres en cada
dominio cuya dirección IP les está notificada a todos los host en el dominio. El servidor de
nombres contiene un directorio que incluye la dirección IP de cada host en el dominio. Cuando
un proceso en un host desea enviar un mensaje a otro proceso con el nombre (<host_name>,
<process_id>), el host realiza una resolución de nombres para determinar la dirección IP de
<host_name>. Si <host_name> no es su propio nombre, envía el nombre al servidor de nombres
en su dominio inmediato que lo contiene, hasta que el nombre llega al servidor de nombres del
dominio más grande contenido en <host_name>. Este servidor de nombres retira su propio nom-
bre de <host_name> y verifica si la cadena restante es el nombre de un host individual. De ser
así, obtiene la dirección IP del host del directorio y lo regresa por la misma ruta por la que había
recibido <host_name>; de lo contrario, el nombre restante contiene por lo menos un nombre de
dominio, por lo que pasa el nombre restante al servidor de nombres de este dominio. Una vez
que el proceso transmisor recibe la dirección IP de <host_name>, se usa el par (dirección IP,
<process_id>) para enviar el mensaje al proceso destinatario.
La resolución de nombres que usa servidores de nombres puede ser lenta, por lo que
cada host puede poner en caché algunos datos del servidor de nombres. Esta técnica acelera
la resolución de nombres repetida, del mismo modo que una caché de directorio acelera las
referencias a la entrada del directorio de un archivo (véase la sección 7.15). Frecuentemente
se reproduce o distribuye el servidor de nombres de un dominio para aumentar su disponibilidad
y evitar la competencia.

18 MAQ. CAP. 15(F0694).indd 632 8/10/07 1:18:26 AM


15.5 Comunicación interproceso confiable 633

15.5.2 Semántica IPC

La semántica IPC es el conjunto de propiedades de un protocolo IPC. La semántica IPC depende


del arreglo de confirmaciones y retransmisiones que se usan en un protocolo IPC. La tabla 15.3
resume tres semánticas IPC de uso común.

Tabla 15.3 Semántica IPC

Semántica Descripción
Semántica Un proceso destinatario recibe un proceso una vez o no lo
“máximo una vez” recibe en absoluto. Esta semántica se obtiene cuando un pro-
ceso que recibe un mensaje no envía una confirmación y un
proceso transmisor no realiza la retransmisión de mensajes.
Semántica Se garantiza que un proceso destinatario recibe un mensaje;
“mínimo una vez” sin embargo, podrá recibir varias copias del mensaje. Esta
semántica se obtiene cuando un proceso que recibe un men-
saje envía una confirmación y un proceso transmisor retrans-
mite un mensaje si no recibe una confirmación antes de que
ocurra un intervalo de tiempo.
Semántica Un proceso destinatario recibe un mensaje exactamente una
“exactamente vez. Esta semántica se obtiene cuando el envío de la con-
una vez” firmación y la retransmisión se realizan como una semánti-
ca “exactamente una vez”, pero el protocolo IPC reconoce
mensajes duplicados y los descarta.

La semántica “máximo una vez” resulta cuando un protocolo no usa confirmaciones o


retransmisiones. Esta semántica se usa si un mensaje perdido no constituye una amenaza seria
para la corrección de una aplicación, o si ésta sabe cómo recuperarse de tales situaciones.
Por ejemplo, una aplicación que recibe reportes periódicos de otros procesos sabe cuando un
mensaje no se recibe como se espera, por lo que podrá comunicar por su propia decisión con
un transmisor cuyo mensaje está perdido para pedirle que reenvíe el mensaje. Esta semántica
va acompañada por una alta eficiencia de comunicación porque no se usan confirmaciones y
retransmisiones.
La semántica “mínimo una vez” resulta cuando un protocolo usa confirmaciones y retrans-
misiones, porque un proceso destinatario podrá recibir un mensaje más de una vez si una con-
firmación se pierde o retrasa debido a la congestión de la red. Un mensaje que se recibe por
segunda o una subsiguiente vez se denomina mensaje duplicado. Una aplicación sólo puede
usar la semántica “mínimo una vez” si el procesamiento de mensajes duplicados no representa
un problema de corrección como múltiples actualizaciones de datos en lugar de una sola actua-
lización.
La semántica “exactamente una vez” resulta cuando un protocolo usa confirmaciones y
retransmisiones, pero descarta los mensajes duplicados. Esta semántica oculta las fallas tem-
porales tanto del proceso transmisor como del proceso receptor; sin embargo, el protocolo
IPC incurre en una alta carga general de comunicación debido al manejo de fallas y mensajes
duplicados.

18 MAQ. CAP. 15(F0694).indd 633 8/10/07 1:18:26 AM


634 CAPÍTULO 15 Sistemas operativos distribuidos

15.5.3 Protocolos IPC

Un protocolo IPC especifica qué acciones se deberán realizar en los sitios de procesos trans-
misores y receptores, por lo que un mensaje se entrega a un proceso destinatario y su respuesta
se entrega al proceso transmisor. Los protocolos IPC se clasifican con base en sus propiedades
de confiabilidad y en la capacidad de un proceso transmisor para realizar acciones después del
envío de un mensaje.

Protocolos confiables y no confiables Un protocolo confiable garantiza que un mensaje, o


su respuesta, no esté perdido. Lo logra por medio de la semántica “mínimo una vez” o “exactamen-
te una vez” tanto para mensajes como para sus respuestas. Un protocolo no confiable no garantiza
que un mensaje o su respuesta no se pierdan; provee la semántica “máximo una vez” para men-
sajes o para sus respuestas. Como hemos comentado en la sección anterior, un protocolo confiable
incurre en una carga general sustancial debido a confirmaciones y retransmisiones de mensajes y
respuestas, mientras que un protocolo no confiable no incurre en estas cargas generales.

Protocolos bloqueadores y no bloqueadores Como hemos discutido en el capítulo 10, es


común bloquear un proceso que ejecuta una llamada receive si no se le han enviado mensajes.
No hay razones intrínsecas para bloquear un proceso que ejecuta una llamada al sistema send;
sin embargo, el bloqueo de un proceso transmisor podrá simplificar un protocolo, reducir su
carga general y también agregar unas características deseables a su semántica. Por ejemplo, si un
proceso transmisor es bloqueado hasta que su mensaje sea entregado a un proceso destinatario, el
mensaje jamás se tendrá que retransmitir después de que el transmisor es activado, por lo que
el mensaje no tendrá que guardarse en un buffer por parte del protocolo después de que el trans-
misor es activado. También, el bloqueo del transmisor ayuda a proveer una semántica similar
para la llamada al procedimiento convencional.
Un protocolo es bloqueador si se bloquea un proceso transmisor hasta que recibe una res-
puesta a su mensaje; de lo contrario se trata de un protocolo no bloqueador. Suponemos que si
un protocolo no bloquea un proceso transmisor, se generarán interrupciones para informar al
proceso la llegada de una respuesta o confirmación para que pueda tomar las acciones corres-
pondientes. Los protocolos bloqueadores y no bloqueadores también se denominan protocolos
sincronizados con el proceso o no sincronizados con el proceso, respectivamente.

15.5.3.1 El protocolo solicitud-respuesta-confirmación (RRA)


El protocolo solicitud-respuesta-confirmación (RRA) es un protocolo confiable para ser usado
por procesos que intercambian solicitudes y respuestas. La recepción de la respuesta implica que
el proceso destinatario ha recibido la solicitud, por lo que no se necesita una confirmación sepa-
rada de la solicitud. El transmisor, sin embargo, envía una confirmación explícita de la respuesta.
Una versión bloqueadora del protocolo RRA es presentada como algoritmo 15.1. La figura 15.3
presenta su operación.
Algoritmo 15.1 (Una versión de bloqueo del protocolo RRA)
1. Cuando un proceso hace una solicitud: La respuesta se copia al buffer denominado bu-
ffer de solicitudes en su sitio y también se envía al proceso destinatario en forma de un
mensaje. El proceso transmisor es bloqueado hasta que se reciba una respuesta del pro-
ceso destinatario.

18 MAQ. CAP. 15(F0694).indd 634 8/10/07 1:18:26 AM


15.5 Comunicación interproceso confiable 635

2. Cuando un proceso destinatario recibe un mensaje: El proceso destinatario analiza la


solicitud contenida en el mensaje y prepara una respuesta. La respuesta se copia a un
buffer llamado buffer de respuestas en el sitio destinatario y también se envía al proceso
transmisor.
3. Cuando ocurre un intervalo de tiempo en el proceso transmisor: Se retransmite la copia
de la solicitud almacenada en el buffer de solicitudes.
4. Cuando el proceso transmisor recibe una respuesta: El proceso transmisor envía una
confirmación al proceso destinatario. También libera al buffer de solicitudes, si todavía
no se ha hecho.
5. Cuando ocurre un intervalo de tiempo en el proceso destinatario: Se retransmite la copia
de la respuesta almacenada en el buffer de respuestas.
6. Cuando el proceso destinatario recibe una confirmación: El proceso destinatario libera
al buffer de respuestas.

Buffer de 1 Respuesta del


solicitudes 2 encabezado Buffer de
3 respuestas
4

Sitio del Sitio del


transmisor destinatario
Figura 15.3 Operación del protocolo solicitud-respuesta-confirmación (RRA).

El proceso transmisor es bloqueado hasta que recibe una respuesta, por lo que un solo bu-
ffer de respuesta en el sitio del transmisor basta, independientemente del número de mensajes
que un proceso envía o del número de procesos a los que se envían. El proceso destinatario no
es bloqueado hasta que recibe una confirmación, por lo que podrá manejar solicitudes de otros
procesos mientras espera a ésta. Por consiguiente, el sitio del destinatario necesita un buffer
de respuestas para cada proceso transmisor. El número de mensajes puede reducirse mediante
piggybacking (uno lleva al otro a cuestas), que es la técnica de incluir la confirmación de una res-
puesta en la siguiente respuesta al mismo proceso destinatario. Puesto que un proceso transmisor
queda bloqueado hasta que recibe una respuesta, la confirmación de ésta es incluso implícita
en su próxima solicitud. Sólo la respuesta a la última solicitud requerirá entonces un explícito
mensaje de confirmación.
El protocolo RRA tiene la semántica “mínimo una vez” porque mensajes y respuestas se
pueden perder, pero también pueden entregarse más que una vez. Como se menciona en la tabla
15.3, tendrán que descartarse respuestas duplicadas en el sitio del destinatario para proveer una
semántica “exactamente una vez”. Esto puede lograrse de la siguiente manera: un transmisor
asigna números ascendentes a sus respuestas y los incluye en sus mensajes de solicitud. El nú-
mero secuencial de un mensaje es copiado a su respuesta y confirmación, así como al campo de
encabezado del buffer de respuesta en el sitio del destinatario. El protocolo también conserva
por separado el número secuencial de la última solicitud recibida del proceso transmisor. Se
habla de solicitud duplicada si su número secuencial no es más grande que el número secuencial

18 MAQ. CAP. 15(F0694).indd 635 8/10/07 1:18:26 AM


636 CAPÍTULO 15 Sistemas operativos distribuidos

conservado. Cuando un sitio recibe una solicitud duplicada, retransmite la respuesta si su copia
está presente en el buffer de respuestas. De lo contrario, se tendrá que descartar la copia de la
respuesta en el buffer de respuesta después de recibir la confirmación, en cuyo caso la solicitud
es una retransmisión antigua, o el proceso destinatario aún está procesando la solicitud y envia-
rá su respuesta en algún momento futuro. En cualesquiera de estos casos, la respuesta duplicada
simplemente se descarta.

15.5.3.2 El protocolo solicitud-respuesta (RR)


El protocolo solicitud-respuesta (RR) simplemente realiza la retransmisión de una solicitud
cuando ocurre un intervalo de tiempo. Una versión no bloqueadora del RR se presenta como
algoritmo 15.2. La figura 15.4 ilustra esta operación.
Algoritmo 15.2 (Una versión no bloqueadora del protocolo RR)
1. Cuando un proceso hace una solicitud: La respuesta se copia a un buffer en el sitio del
transmisor y también se envía al proceso destinatario en forma de un mensaje. El trans-
misor continúa su computación.
2. Cuando el proceso destinatario recibe un mensaje: El proceso destinatario analiza la
solicitud contenida en el mensaje y prepara una respuesta. Ésta se copia a un buffer de
respuestas en el sitio del destinatario y también se envía al proceso transmisor.
3. Cuando ocurre un intervalo de tiempo en el sitio del transmisor: Se retransmite la copia
de la solicitud almacenada en el buffer de solicitudes.
4. Cuando se recibe una respuesta en el sitio del transmisor: Se produce una interrupción
para informar al proceso transmisor sobre la llegada de una respuesta. El proceso trans-
misor libera al buffer de solicitudes.

Buffer de 1 Respuesta del


solicitudes 2 encabezado
3 Buffers de
respuesta

Sitio del Sitio del


transmisor destinatario
Figura 15.4 Operación del protocolo solicitud-respuesta (RR).

El proceso destinatario tiene que guardar sus respuestas en un buffer en forma indefinida
porque un transmisor no confirma una respuesta explícitamente y, a diferencia del protocolo
RRA, una confirmación no se lleva de modo implícito a cuestas de la próxima solicitud del trans-
misor, porque éste posiblemente hizo la siguiente respuesta antes de recibir la respuesta a su soli-
citud previa. Por consiguiente, el protocolo tiene un requerimiento de espacio en buffer muy alto.
El protocolo RR posee la semántica “mínimo una vez”. Por consiguiente, tienen que
descartarse solicitudes y respuestas duplicadas si se desea la semántica “exactamente una vez”.
Si solicitudes hechas por un transmisor se entregan al proceso destinatario en el mismo orden,

18 MAQ. CAP. 15(F0694).indd 636 8/10/07 1:18:27 AM


15.6 Paradigmas de computación distribuidos 637

el arreglo de reconocimiento y descarte de duplicados del protocolo RRA puede usarse con po-
cos cambios. Un proceso destinatario conserva los números secuenciales y respuestas de todas
las solicitudes en un pool de buffers. Cuando reconoce una solicitud duplicada por medio de la
comparación de números secuenciales, busca la respuesta a la solicitud en el pool de buffers
usando el número secuencial y retransmite la respuesta si se encuentra en un buffer; de no ser
así, simplemente ignora la respuesta, ya que se enviará una respuesta después del procesamiento
de la solicitud. El problema 5 del ejercicio 15 se refiere a un refinamiento de este planteamien-
to que en la práctica resulta necesario.
El protocolo no bloqueador RR puede simplificarse para su uso en aplicaciones que invo-
lucran computaciones idempotentes. Una computación idempotente tiene la característica de
producir el mismo resultado si se ejecuta en forma repetida. Por ejemplo, la computación i :⫽ 5
es idempotente, mientras que la computación i :⫽ i ⫹ 1 no lo es. Cuando una aplicación sólo
involucra computaciones idempotentes, no estará afectada la consistencia de datos si se procesa
una solicitud más de una vez, por lo que es posible omitir el arreglo para descartar solicitudes
duplicadas. Operaciones de lectura y escritura realizadas en un archivo son idempotentes, por
lo que es posible emplear el protocolo RR simplificado mientras se usa un servidor de archivos
remoto. Eso tiene la ventaja adicional de que el servidor de archivos no necesita llevar informa-
ciones acerca de qué solicitudes ha procesado, lo que ayuda a hacerlo sin estado y más confiable
(véase la sección 19.4.3).

15.6 PARADIGMAS DE COMPUTACIÓN DISTRIBUIDOS

Los datos pueden estar ubicados en diferentes sitios de un sistema distribuido debido a las si-
guientes consideraciones:

• Replicación de datos: Podrán almacenarse varias copias de un conjunto de datos D en di-


ferentes sitios de un sistema distribuido para proveer disponibilidad y acceso eficiente.
• Distribución de datos: Partes de un conjunto de datos D podrán estar ubicadas en dife-
rentes sitios de un sistema, ya sea porque el conjunto de datos D es muy voluminoso o
porque sus partes provinieron o se usan frecuentemente en diferentes sitios.

Cuando el conjunto de datos D no es replicado ni distribuido, el SO podrá posicionarlo de tal


modo que el tráfico total de la red generado debido a accesos a D por varias aplicaciones es
mínimo.
La tabla 15.4 resume estos tres modos de acceder a datos en un sistema distribuido. En ac-
ceso remoto de datos se accede a los datos in situ, es decir, en el lugar donde se encuentren. De
este modo no interfiere con decisiones en relación con la colocación de los datos. La migración
de datos implica moverlos al sitio de la computación que los usa. Enfrenta dificultades si muchas
computaciones usan los datos o si es replicado para proveer alta disponibilidad. En el peor de los
casos, este planteamiento podrá forzar que los datos sean usados estrictamente por una compu-
tación a la vez. La migración de computación implica mover una computación al sitio donde los
datos están ubicados. No interfiere con la replicación y distribución de éstos. También facilita
la aceleración de computación. Debido a estas ventajas, una variedad de herramientas para la
migración de computación fue concebida y puesta en práctica.
Una computación distribuida es un cálculo cuyas porciones pueden ejecutarse en diferentes
sitios por motivos de eficiencia del acceso de datos, aceleración de computación o confiabilidad.

18 MAQ. CAP. 15(F0694).indd 637 8/10/07 1:18:27 AM


638 CAPÍTULO 15 Sistemas operativos distribuidos

Tabla 15.4 Modos de acceso a datos en un sistema distribuido

Modo de acceso Descripción


Acceso remoto Una computación accede a datos a través de la red. Este
de datos modo de acceso no interfiere con la organización o ac-
ceso de datos y no requiere la reestructuración de una
computación. Sin embargo, se reduce la velocidad de
las computaciones debido a retrasos de comunicación.
Migración Los datos se mueven al sitio donde una computación está
de datos ubicada. La migración de datos provee el acceso eficiente
a datos; sin embargo, podrá interferir con la replicación y
distribución de datos.
Migración de Una computación (o una parte de ella) se mueve al sitio
computación donde sus datos están ubicados. Provee el acceso eficien-
te a datos sin interferir con la organización o el acceso
de datos.

Un paradigma de computación distribuida es un modelo de prácticas que son útiles para el dise-
ño de cálculos distribuidos. El asunto principal que aborda un paradigma de computación distri-
buida es la manipulación de datos y la iniciación de subcomputaciones en diferentes sitios de un
sistema distribuido. La tabla 15.5 resume tres paradigmas de computación distribuida. El de
computación cliente/servidor se enfoca al acceso y manipulación remotos de datos, mientras que
los paradigmas de llamada al procedimiento remoto y evaluación remota proveen diferentes
maneras de realizar la migración de computación.
Los sistemas operativos proveen algo de soporte para cada modo de acceso de datos, mismo
que se resume en la tabla 15.5. Como se describe en la sección 15.3, un SO de red admite el
acceso remoto de datos. El protocolo de transferencia de archivos (FTP) es un dispositivo para
la migración de datos; realiza la transferencia de archivos de manera off-line y no durante la
ejecución de una computación. La migración de procesos es una herramienta para migrar una
computación, o parte de ella, mientras que ésta se encuentra ejecutándose. Se describirá más
adelante en la sección 17.8.2.

15.6.1 La computación cliente/servidor


Un servidor es un proceso en un sistema distribuido que provee un servicio específico para sus
clientes. Por lo regular, el nombre de un servidor y una especificación de su servicio se anuncian
ampliamente en un sistema. Cualquier proceso puede enviar un mensaje a un servidor y con-
vertirse en su cliente. Un servicio podrá tener una connotación física, como acceder o imprimir
un archivo, o una connotación computacional, como la ejecución de consultas en un servidor
de bases de datos o la evaluación de funciones matemáticas en un servidor de matemáticas. En
forma correspondiente, el papel del servidor abarca desde el puro acceso de datos hasta la ma-
nipulación de ellos. En ese último caso, el servidor podrá incluso jugar un papel computacional
en una computación distribuida.
Un servidor podrá convertirse en un cuello de botella si la velocidad con la que el cliente
hace solicitudes excede aquella con la que el servidor las pueda atender. La figura 15.5 presenta
tres métodos de abordar este problema. La figura 15.5a) muestra muchos servidores idénticos,

18 MAQ. CAP. 15(F0694).indd 638 8/10/07 1:18:27 AM


15.6 Paradigmas de computación distribuidos 639

Tabla 15.5 Paradigmas de computación distribuida

Paradigma Descripción
Computación Un proceso de servidor provee un servicio específi-
cliente/servidor co a sus clientes. Un proceso cliente pide sus servi-
cios enviándole un mensaje y el servidor devuelve
sus resultados en otro. Las aplicaciones usan el pa-
radigma cliente/servidor extensamente para realizar
el acceso remoto de datos o la manipulación remota
de ellos.
Llamada al Un procedimiento remoto se parece a un procedi-
procedimiento miento convencional, excepto porque se ejecuta en un
nodo diferente del sistema. Un procedimiento remoto
es instalado en un nodo por el administrador del sis-
tema y es registrado con un servidor de nombres. La
llamada al procedimiento remoto ha sido usada exten-
samente para la migración de computación.
Evaluación Si un programa usa la instrucción at <node> eval
remota <code_segment>, el compilador del lenguaje del pro-
grama toma en cuenta que se debe transferir <code_
segment> al nodo designado por <node >, ejecutarlo
allí y devolver sus resultados. No hay necesidad de
instalar el segmento de código en el nodo remoto.
Java proporciona una facilidad para la evaluación
remota.

cada uno con su propia cola de solicitudes. Los clientes son particionados de tal modo que cada
uno sabe qué servidor deberá usar. Este arreglo hereda los inconvenientes del particionado: al-
gunos servidores posiblemente están severamente cargados, mientras que otros están inactivos.
En la figura 15.5b) muchos servidores comparten la misma cola en forma dinámica. Este arreglo
es más flexible que particionar los clientes para que usen diferentes servidores. La figura 15.5c)
muestra un servidor de múltiples hilos. Se crea un hilo nuevo para manejar cada solicitud. Los
hilos compiten entre sí por el CPU y por otros recursos. Si la función del servidor está orientada
a E/S, este arreglo puede traslaparse con las atenciones de servicio de varias solicitudes. Un
planteamiento alternativo para la eliminación del cuello de botella del servidor empuja la mayor
parte de la carga computacional hacia un proceso de cliente. Ahora el servidor puede proporcio-
nar mejores tiempos de respuesta para sus clientes. Se han desarrollado metodologías de diseño
para estos arreglos de cliente/servidor.
La computación de cliente/servidor es un pobre paradigma para la computación distribuida
porque las metodologías para estructurar una computación distribuida en forma de una configu-
ración cliente/servidor no han sido desarrolladas. La principal dificultad es que una computación
distribuida involucra a muchas entidades con una relación simétrica. Ésta es difícil de modelar
usando el paradigma cliente/servidor. En la práctica, este paradigma se usa extensamente para
papeles no computacionales en un ambiente LAN, tales como el acceso de archivos o la evalua-
ción de consultas de base de datos. Para lograr que su implementación sea eficiente, se prefieren
simples protocolos, como el RR, sobre protocolos de capas múltiples, como el protocolo ISO.

18 MAQ. CAP. 15(F0694).indd 639 8/10/07 1:18:27 AM


640 CAPÍTULO 15 Sistemas operativos distribuidos

S S S S S S

Clientes Clientes Clientes


a) b) c)

Figura 15.5 Servidores con colas independientes y compartidas y con un servidor de hilos múltiples.

15.6.2 Llamadas al procedimiento remoto

Una llamada al procedimiento remoto (RPC) es una herramienta de lenguaje de programación


diseñada para la computación distribuida. Su sintaxis y semántica se parecen a las de una llama-
da convencional al procedimiento. En la llamada al procedimiento remoto

call <proc_id> (<message>);

<proc_id es la id de un procedimiento remoto, <message> es una lista de parámetros y la llama-


da se implementa usando un protocolo bloqueador. El resultado de la llamada podrá pasarse de
regreso a través de uno de los parámetros o por medio de un valor de regreso explícito. Podemos
considerar la relación de invocador/invocado como una relación de cliente/servidor. De este
modo, el procedimiento remoto es el servidor y un proceso que lo llama es un cliente.

Servidor
de
3 nombres

Proceso Resguardo Resguardo Procedimiento


cliente del cliente del servidor del servidor
1 4 6
2 9 5
10 8 7

Sitio del Sitio del


cliente servidor

Figura 15.6 Implementación de una llamada al procedimiento remoto.

El diagrama esquemático de la figura 15.6 representa el arreglo que se usa para realizar la
resolución de nombres pase de parámetros y devolución de resultados durante una llamada al
procedimiento remoto. El servidor de nombres de dominio (DNS) que se describe en la sección

18 MAQ. CAP. 15(F0694).indd 640 8/10/07 1:18:27 AM


15.6 Paradigmas de computación distribuidos 641

15.5.1 se usa para obtener la dirección IP del proceso destinatario. Las funciones de los resguar-
dos de clientes y servidores son las siguientes: el resguardo del cliente organiza los parámetros y
los convierte en una forma independiente de la máquina, el resguardo del servidor los convierte
en la representación específica de la máquina apropiada para el host del servidor, y los resultados
del procedimiento llamado se pasan de regreso al proceso del cliente a través del servidor y de
los resguardos del cliente. Los números rodeados de un círculo en la figura 15.6 denotan los
pasos para implementar la llamada del procedimiento remoto. Los detalles de estos pasos son
los siguientes:

1. El proceso cliente llama al resguardo cliente con parámetros. Esta llamada es una llama-
da convencional al procedimiento. Por tanto, la ejecución del proceso cliente queda
suspendida hasta que la llamada está completada.
2. El resguardo cliente organiza los parámetros y los convierte en un formato indepen-
diente de la máquina. Luego prepara un mensaje que contiene esta representación de
parámetros.
3. El resguardo cliente interactúa con el servidor de nombres para encontrar la identidad
del sitio en el cual existe el procedimiento remoto.
4. El resguardo cliente envía el mensaje preparado en el paso 2 al sitio donde existe el
procedimiento remoto, usando un protocolo bloqueador. Esta operación de transmisión
bloquea el resguardo cliente hasta que llegue una respuesta a su mensaje.
5. El resguardo servidor recibe el mensaje enviado por el resguardo cliente. Convierte los
parámetros al formato específico de la máquina adecuado para el sitio del servidor.
6. El resguardo servidor ahora ejecuta una llamada en el procedimiento del servidor con
estos parámetros. Se trata de una llamada convencional al procedimiento, y por tanto
se suspende la ejecución del resguardo servidor hasta que la llamada al procedimien-
to está completada.
7. El procedimiento del servidor devuelve sus resultados al resguardo servidor. Éste los
convierte en un formato independiente de la máquina y prepara un mensaje que contie-
ne los resultados.
8. El mensaje que contiene los resultados se envía al sitio del cliente.
9. El resguardo cliente convierte los resultados al formato adecuado para el sitio del
cliente.
10. El resguardo cliente devuelve los resultados al proceso cliente.

El paso 10 completa la ejecución de la llamada al procedimiento remoto. El proceso cliente que-


da ahora libre para continuar su ejecución.
En el paso 3, el resguardo cliente no necesita realizar la resolución de nombres cada vez que
se ejecuta el RPC. Lo puede hacer la primera vez, guardando las informaciones en relación con
el sitio del procedimiento remoto en una caché de nombre para su uso futuro. La resolución de
nombres puede incluso realizarse en forma estática, es decir, antes de que empiece la ejecución
del programa.
Durante una llamada al procedimiento remoto pueden ocurrir fallas, ya sea en la liga de
comunicación, en el sitio del servidor o en el propio cliente. Si se cuelga el sitio del servidor, la
llamada se convierte en huérfano porque su resultado no tendrá ningún uso. Analizaremos los
huérfanos y su manejo más adelante, en la sección 18.3. Fallas de comunicación y servidores

18 MAQ. CAP. 15(F0694).indd 641 8/10/07 1:18:28 AM


642 CAPÍTULO 15 Sistemas operativos distribuidos

pueden manejarse usando un arreglo que involucra confirmaciones y retransmisiones (véase la


sección 15.5). Idealmente, las RPC deberían poseer la semántica “exactamente una vez”; sin
embargo, la implementación de esta semántica resulta cara. Es más barata la de la semántica
“mínimo una vez”, pero requiere que el procedimiento remoto sea idempotente o que tenga que
descartar las solicitudes duplicadas.
La herramienta de la llamada al procedimiento remoto puede usarse como una pieza de
construcción para cálculos distribuidos. Sus ventajas sobre el paradigma cliente/servidor se de-
ben a dos factores. En primer lugar, podrá establecer un procedimiento remoto simplemente
comunicando su nombre y ubicación al servidor de nombres. Esto es mucho más fácil que es-
tablecer un servidor. En segundo lugar, sólo aquellos procesos que saben de la existencia de un
procedimiento remoto lo pueden llamar. De este modo, el uso de procedimientos remotos provee
más privacidad y, por ende, más seguridad que el del paradigma cliente/servidor. Su principal
desventaja es la falta de flexibilidad: el procedimiento remoto tiene que ser registrado con un
servidor de nombres para que su ubicación no pueda ser cambiada tan fácilmente.

15.6.3 Evaluación remota

El paradigma de la evaluación remota fue propuesto por Stamos y Gifford (1990). Se implemen-
ta por medio de la instrucción

at <node> eval <code_segment>

donde <node> es una expresión que evalúa la identidad de unos nodos en el sistema distribuido
y <code_segment> es un segmento de código, posiblemente una secuencia de instrucciones.
Cuando se encuentra un enunciado durante la ejecución de un programa, <node> es evaluado
para obtener la identidad de un nodo. Entonces se estipula la ejecución de <code_segment> en
este nodo. Los resultados de esta ejecución, si los hay, se devuelven al nodo que ejecuta el enun-
ciado at.
Este paradigma tiene varias ventajas sobre los paradigmas de cliente/servidor y RPC. Re-
quiere un mínimo soporte del SO. La mayoría del trabajo es realizada por el compilador del
lenguaje en el cual el programa está escrito. Con la ayuda del SO, el compilador estipula la trans-
ferencia de <code_segment> al nodo destino para ejecutarlo allí. El SO del nodo destino crea un
proceso para ejecutar el código y devolver sus resultados. No se necesita la instalación previa de
<code_segment> o un elaborado montaje de procedimientos de resguardos.
Los asuntos de nombrado y ligado también son mucho más sencillos que en un ambiente
de RPC. La decisión de qué nodo deberá usarse para ejecutar el segmento de código se toma
en forma dinámica. Esta decisión podrá usar informaciones acerca de cargas computacionales en
varios nodos. <code_segment> es una sección de código arbitraria que puede ser ejecutada
en forma remota. No es necesario darle la forma sintáctica de un procedimiento. El paradigma
de evaluación remota puede usarse junto con los paradigmas de cliente/servidor o RPC, es de-
cir, el segmento de código podrá llamar a procedimientos durante su ejecución o él mismo ser
un procedimiento.
El paradigma de evaluación remota puede usarse para la aceleración de computación o
para mejorar la eficiencia de una computación. Por ejemplo, si una subcomputación involucra

18 MAQ. CAP. 15(F0694).indd 642 8/10/07 1:18:28 AM


15.6 Paradigmas de computación distribuidos 643

a una manipulación considerable de datos ubicados en algún nodo específico Si, la subcompu-
tación misma puede ser ejecutada en Si. Esto reducirá la cantidad de tráfico de red involucrada
en el acceso remoto de datos. De modo similar, si un usuario desea enviar un correo electrónico
a un número de personas en Si, el propio comando de transmisión de correo puede ser ejecutado
en Si.

15.6.4 Estudios de casos reales

SUN RPC Sun RPC fue diseñado para la comunicación cliente/servidor en NFS, el sistema de
archivos de red de Sun. NFS modela las acciones de procesamiento de archivos como acciones
idempotentes, por lo que Sun RPC provee la semántica “mínimo una vez”. Esta característica
hace al RPC eficiente; sin embargo, requiere aplicaciones que usan RPC para hacer sus propios
arreglos a fin de suprimir duplicados si se desea la semántica “exactamente una vez”.
Sun RPC ofrece un lenguaje de interfaz denominada XDR y un compilador de interfaces lla-
mado rpcgen. Para usar un procedimiento remoto, un usuario tiene que escribir una definición
de interfaz para él en XDR que contiene una especificación del procedimiento remoto y sus pa-
rámetros. La definición de interfaz se compila por medio de rpcgen, lo que produce lo siguiente:
un resguardo cliente, el procedimiento del servidor y un resguardo servidor, un archivo de en-
cabezado para el uso en los programas de cliente y servidor, y dos procedimientos de manejo de
parámetros que son llamados por el resguardo de cliente y servidor, respectivamente.
El programa del cliente se compila con el archivo de encabezado y el resguardo del cliente,
mientras que el programa del servidor lo hace con el archivo de encabezado y el resguardo del
servidor. El procedimiento de manejo de parámetros llamado por el resguardo del cliente recaba
parámetros y los convierte en un formato independiente de la máquina denominado represen-
tación de datos externos (XDR). El procedimiento llamado a partir del resguardo del servidor
convierte parámetros del formato XDR a la representación de máquina adecuada para el proce-
dimiento llamado.
El esquema del Sun RPC tiene sus limitaciones. El procedimiento remoto sólo puede acep-
tar un parámetro. Esta limitación es superada mediante la definición de una estructura que
contiene muchos miembros de datos y pasando la estructura como el parámetro. El esquema del
Sun RPC tampoco usa los servicios de un servidor de nombres. En su lugar, cada sitio contiene
un mapeador de puertos que es como un servidor local de nombres. Contiene los nombres de
procedimientos y sus id de puertos. A un procedimiento que va a ser llamado como procedi-
miento remoto se le asigna un puerto, y esta información se registra con el mapeador de puertos.
El cliente primero hace una solicitud al mapeador de puertos del sitio remoto para averiguar
qué puerto usa el procedimiento remoto. Luego llama al procedimiento de ese puerto. Un punto
débil de este arreglo es que un llamador debe conocer el sitio donde existe un procedimiento
remoto.

Java RMI Java ofrece una facilidad de llamada de método remoto (RMI) que es de na-
turaleza específica de lenguaje. Una aplicación del servidor que opera en un host crea un tipo
especial de objeto denominado objeto remoto cuyos métodos pueden ser llamados por clientes
que operan en otros host. El servidor selecciona un nombre para el servicio que va a ser ofrecido
por medio de un método del objeto remoto, y lo registra con un servidor de nombres denomina-
do rmiregistry, que opera en el host del servidor. El rmiregistry normalmente escucha en
un puerto estándar para solicitudes de registro y llamada. Los potenciales clientes del servicio

18 MAQ. CAP. 15(F0694).indd 643 8/10/07 1:18:28 AM


644 CAPÍTULO 15 Sistemas operativos distribuidos

conocen la dirección IP del host del servidor. Un cliente consulta el rmiregistry en el servidor
del host para localizar el servicio con un nombre dado. El rmiregistry devuelve un manejador
de objeto para el objeto remoto que provee el servicio y el cliente usa este manejador de objeto
para llamar al servicio. La sintaxis de esta llamada se parece a una operación similar en un ob-
jeto local. La llamada al servicio remoto es similar al esquema familiar que se describió en la
sección 15.6.2: se usa el compilador javac para compilar los archivos fuente que contienen los
programas de servidores y clientes, y el compilador rmic para generar resguardos de clientes y
servidores.
Un cliente puede pasar tipos especiales de objetos denominados objetos serializables como
parámetros del método remoto. El Java RMI pasa el código y los datos de estos objetos al mé-
todo remoto llamado. Este código se carga al host del servidor mientras que se desorganizan los
parámetros; podrá ser llamado por el objeto que ofrece el servicio remoto. Puede usarse esta
herramienta para lograr un efecto análogo a la evaluación remota que se describió en la sección
15.6.3 del siguiente modo: un servidor registra un servicio remoto r_eval que toma un objeto
serializable alpha como parámetro y simplemente llama al método alpha.gamma(). Si un clien-
te crea un objeto serializable y lo pasa como un parámetro en una llamada de r_eval, entonces
r_eval cargaría el código del objeto y llamará a su método gamma. De hecho, el cliente habrá
logrado la ejecución de una parte de su propio código en el sitio del servidor. Diferentes clientes
pueden usar el mismo servicio r_eval para obtener diferentes códigos ejecutados en el sitio del
servidor.

15.7 REALIZACIÓN DE REDES (NETWORKING)

El término networking incluye tanto el hardware como el software de redes. Por ende, considera
tanto la tecnología de redes y el diseño de redes de computadoras como también aspectos de
software para implementar la comunicación entre un par de procesos. Los temas básicos en la
realización de redes se resumen en la tabla 15.6. El tipo de red, la topología de redes y la tecnolo-
gía de la realización de redes conciernen al diseño de redes. Todos los demás asuntos tienen que
ver con la comunicación por mensaje entre procesos: encontrar la dirección IP del nodo donde se
ubica un proceso destinatario, decidir qué ruta seguirá un mensaje hacia este nodo y asegurar que
el mensaje es entregado en forma eficiente y confiable. Hemos analizado el servicio de nombres
de dominio (DNS) que determina la dirección IP de un host en la sección 15.5.1. Todos los demás
asuntos de la realización de redes se analizarán en esta sección.

15.7.1 Tipos de redes

Una red amplia (WAN) conecta recursos y usuarios que son geográficamente distantes. Cuando
se usaban computadoras de unidad central caras, era sensato hacerlos accesibles a un gran nú-
mero de usuarios de diferentes organizaciones y diferentes ubicaciones por medio de WAN. La
otra motivación para las WAN fue la habilitación de la comunicación y compartición de datos
entre usuarios.
Cuando las computadoras personales baratas llegaron al mercado, muchas organizaciones
instalaron un gran número de PC en las oficinas. Datos usados por usuarios y recursos como

18 MAQ. CAP. 15(F0694).indd 644 8/10/07 1:18:28 AM


15.7 Realización de redes (networking) 645

Tabla 15.6 Asuntos de la realización de redes

Asunto Descripción
Tipo de red El tipo de una red es determinado por la distribución geográ-
fica de usuarios y recursos en el sistema. Los dos principales
tipos de redes son la red amplia (WAN) y la red de área local
(LAN).
Topología La topología de la red es el arreglo de nodos y ligas de comuni-
de la red cación en una red. Esto influye en la velocidad y confiabilidad
de comunicación y en el costo del hardware de la red.
Tecnología de La tecnología de la realización de redes se preocupa de la
realización transmisión de datos a través de una red. Influye en el ancho
de redes de banda y la latencia.
Nombrado Usando el servicio de nombres del dominio (DNS), el nombre
de procesos de un proceso destinatario se traduce en el par (dirección IP,
id de proceso).
Estrategia de Una estrategia de conexión decide cómo establecer rutas de
la conexión datos entre procesos de comunicación. Esto tiene un impacto
sobre la capacidad de procesamiento de ligas de comunicación
y la eficiencia de comunicación entre procesos.
Estrategia de Una estrategia de asignación de rutas decide la ruta a lo lar-
asignación go de la cual el mensaje deberá viajar a través del sistema.
de rutas Esto influye en los retrasos de comunicación que sufre un
mensaje.
Protocolos Un protocolo de red es un conjunto de reglas y convenciones
de redes que aseguran la comunicación efectiva a través de una red. Se
usa una jerarquía de protocolos de la red para obtener la se-
paración de varios asuntos involucrados en la transmisión de
datos y la confiabilidad.
Ancho de banda El ancho de banda de una red es la velocidad con la que se
y latencia transfieren datos a través de la red. La latencia es el tiempo
de redes transcurrido antes de que los datos sean entregados en el sitio
destinatario.

impresoras láser de buena calidad se convirtieron en recursos críticos, por lo que se establecieron
redes de áreas locales (LAN) para conectar a usuarios y recursos ubicados dentro de la misma
oficina o el mismo edificio. Puesto que todos los recursos y usuarios en una LAN pertenecían a
la misma organización, había poca motivación para compartir los datos y recursos con extraños.
Por este motivo, pocas LAN fueron conectadas a WAN, aunque la tecnología para la realización
de estas conexiones existía. La llegada del Internet cambió el escenario y la mayoría de las LAN
y WAN hoy en día está conectada al Internet.
La figura 15.7 ilustra las WAN y LAN. La LAN consiste en PC, impresoras y un servidor
de archivos. La LAN se conecta a una WAN a través de una puerta de acceso (gateway), que es
una computadora que está conectada a dos o más redes y transfiere mensajes entre ellas. Proce-
sadores de propósitos especiales denominados procesadores de comunicación (CP) se usan en
la WAN para facilitar la comunicación de mensajes entre host distantes. Las LAN usan cables

18 MAQ. CAP. 15(F0694).indd 645 8/10/07 1:18:29 AM


646 CAPÍTULO 15 Sistemas operativos distribuidos

Estaciones de trabajo

Red de área
Host local (LAN)

Red amplia CP
(WAN) puerta de servidor impresora
acceso de archivos
(gateway)
CP CP

Host Host

Figura 15.7 Tipos de redes.

caros de alta velocidad como de la categoría 5 o de fibra óptica para proveer altas velocidades
de transferencia de datos. Las WAN frecuentemente usan líneas públicas para la transferen-
cia de datos debido a consideraciones de costo, por lo que por lo general no es posible que admi-
tan altas velocidades de transferencia.

15.7.2 Topología de la red

La figura 15.8 ilustra cinco topologías de redes que se distinguen en el costo del hardware de
red, la velocidad de comunicación y la confiabilidad. La topología del bus es parecida al bus en
una PC. Todos los host están directamente conectados al bus, por lo que el costo del hardware de
red es bajo. Solamente un par de host puede comunicar a través del bus en un momento dado. La

...
Bus Estrella Anillo Completamente Parcialmente
conectado conectado

Figura 15.8 Topologías de la red.

18 MAQ. CAP. 15(F0694).indd 646 8/10/07 1:18:29 AM


15.7 Realización de redes (networking) 647

velocidad de comunicación es buena, excepto cuando existe competencia por el bus. La topolo-
gía del bus se usa en las LAN basadas en ethernet.
En la topología tipo estrella, cada host está conectado únicamente al host en el sitio cen-
tral del sistema. Esta topología es útil cuando el sistema distribuido contiene un servidor y
los nodos contienen procesos que usan este servidor. La confiabilidad de una red tipo estrella
depende de la del host central. Los retrasos de comunicación entre un host y el host central, o
entre dos host, depende de la competencia en el host central. La ethernet rápida usa la topología
tipo estrella.
En una red tipo anillo, cada host tiene dos vecinos. Cuando un host desea comunicarse con
otro, un mensaje es pasado a lo largo del anillo hasta que llegue al host destinatario. Por consi-
guiente, la carga de comunicación en un host es alta, incluso cuando ninguno de sus procesos
está comunicando. En un anillo unidireccional, una liga transporta mensajes en una sola direc-
ción, mientras que en un anillo bidireccional, una liga puede transportar mensajes en ambas
direcciones. Por supuesto, anillos unidireccionales y bidireccionales tienen diferentes caracterís-
ticas de confiabilidad. Una red de anillo bidireccional es inmune a fallas individuales de host o
liga, mientras que un anillo unidireccional no lo es.
En una red completamente conectada, existe una liga entre cada par de host. Por consiguien-
te, la comunicación entre un par es inmune a caídas de otros host o faltas de hasta n ⫺ 2 ligas,
donde n es el número de host en la red. Uno o varios host podrán ser aislados si el número de
fallas es mayor a n ⫺ 2. Esta situación se llama particionamiento de la red. Una red parcialmente
conectada contiene menos ligas que una completamente conectada. Esta red tiene un costo me-
nor que una completamente particionada; sin embargo, se podrá particionar con menos caídas de
host o ligas que una red completamente conectada.

15.7.3 Tecnologías de realización de redes

Hablaremos de tres tecnologías de realización de redes. Las tecnologías de ethernet y token ring
se usan para redes de áreas locales, y la tecnología de modo de transferencia asíncrona (ATM) se
usa para redes ISDN.

Ethernet La ethernet es una red parecida a un bus (bus sencillo o ramificado) que usa un
circuito que consiste en cables vinculados por repetidores. Varias entidades denominadas esta-
ciones están conectadas al mismo cable. Los datos se transmiten en unidades denominadas mar-
cos. Cada marco contiene las direcciones de su fuente y destino, así como un campo de datos.
Cada estación escucha en el bus en todo momento. La estación copia un archivo a un buffer si
el marco está destinado a él; de no ser así, se ignora el marco. La ethernet original operaba con
una velocidad de transmisión de 10 M bits por segundo. La ethernet rápida, que opera con 100
M bits por segundo, Gigabit Internet, y 10 Gigabit Internet son las variantes predominantes de
ethernet. Se usa un puente para conectar las LAN de Ethernet. Se trata de una computadora que
recibe marcos en una ethernet y, dependiendo de sus direcciones de destino, los reproduce en
otra ethernet a la que está conectada.
Puesto que la topología básica de ethernet es la de un bus, sólo una conversación se puede
realizar en un momento dado. La tecnología “Acceso Múltiple con Escucha de Portadora y
Detección de Colisiones” (CSMA/CD) lo asegura de la siguiente manera: una estación que de-
sea enviar un mensaje monitorea el tráfico en el cable para verificar si se está transmitiendo una

18 MAQ. CAP. 15(F0694).indd 647 8/10/07 1:18:29 AM


648 CAPÍTULO 15 Sistemas operativos distribuidos

señal. Esta revisión se llama lectura de portadoras. La estación empieza a transmitir su marco si
no detecta ninguna señal. Sin embargo, si muchas estaciones no encuentran una señal en el cable
y transmiten al mismo tiempo, sus marcos se interfieren entre sí, causando un voltaje anormal en
el cable. Esta situación se denomina colisión. Una estación que detecta una colisión emite una
señal especial de obstrucción de 32 bits para informar a otras estaciones acerca de una colisión.
Entonces todas las estaciones que están transmitiendo retroceden, abandonando sus transmisio-
nes y esperando durante un periodo de tiempo aleatorio antes de retransmitir sus marcos. Este
procedimiento de recuperarse de una colisión no garantiza que los marcos no vayan a colisionar
nuevamente; sin embargo, esto ayuda a asegurar que a final de cuentas todos los marcos serán
transmitidos y recibidos sin colisiones. El tamaño de los marcos debe exceder un mínimo que
facilita la detección de colisiones. Ese tamaño es 512 bits para la ethernet de 10 M bits y 100 M
bits, y 4 096 bits para la ethernet de un gigabit.

Token rings Un token ring es una red con una topología de anillo que usa la noción de un
token (valor simbólico) para decidir qué estación podrá transmitir un mensaje en un momento
dado. El token es un mensaje especial que circula en la red. Tiene un bit de estatus que puede ser
libre u ocupado. El valor del bit de estatus ocupado indica que un mensaje se está transmitiendo
actualmente a través de la red, mientras que el valor libre indica que la red está actualmente
inactiva. Una estación que desea transmitir un mensaje espera hasta que pueda ver el token con el
bit de estatus libre. Entonces cambia el estatus a ocupado y empieza a transmitir su mensaje. Un
mensaje sigue entonces a un token ocupado, por lo que sólo un mensaje puede estar en tránsito
en un momento dado. Un mensaje puede ser de cualquier longitud. No tiene que estar partido en
marcos de un tamaño estándar.
Cada estación que ve un mensaje verifica si el mensaje está destinado a ella; la estación des-
tinataria copia el mensaje. Cuando la estación transmisora ve el token ocupado en la red, repone
su bit de estatus a libre. La operación del token ring se detiene si el token se pierde debido a erro-
res de comunicación. Una de las estaciones es responsable de la recuperación de esta situación.
Esta estación monitorea continuamente el tráfico en la red para verificar si hay presencia de un
token, y crea uno nuevo si se da cuenta que el token se perdió.

Tecnología del modo de transferencia asíncrona (ATM) ATM es una tecnología de con-
mutación por paquetes orientada a un circuito virtual (véase las secciones 15.7.4 y 15.7.5). Éste
se llama ruta virtual en la terminología de ATM, y un paquete se llama célula. ATM implementa
una ruta virtual entre sitios, reservando un ancho de banda específico en ligas físicas situadas
en una ruta de red entre los sitios, es decir, mediante la reservación de una parte específica de la
capacidad de cada liga física para la ruta virtual. Cuando una liga física es común a muchas rutas
virtuales, multiplexa el tráfico de las diferentes rutas virtuales sobre una base estadística tal que
cada ruta virtual recibe la parte especificada del ancho de la banda de la liga física. De este modo,
las células que van a ser transmitidas en una ruta virtual no sufren retrasos debidos al tráfico en
otras rutas virtuales.
El principio de reservar ancho de banda es llevado un paso más adelante por host en
una red ATM. Una ruta virtual puede ser establecida entre dos host, digamos los host X y Y.
Cuando un proceso Pi en el host X desea comunicar con un proceso Pj en el host Y, los host
podrán establecer un canal virtual entre Pi y Pj, reservando una parte del ancho de banda de
la ruta virtual entre X y Y. Este arreglo de dos niveles asegura que el tráfico de mensajes entre
un par de procesos no incurra en retrasos debidos al tráfico de mensajes entre otros pares de
procesos.

18 MAQ. CAP. 15(F0694).indd 648 8/10/07 1:18:29 AM


15.7 Realización de redes (networking) 649

La tecnología ATM intenta proveer capacidades de transporte en tiempo real para aplica-
ciones multimedia, incorporando a diversos tráficos, tales como voz, video y datos de alta velo-
cidad. ATM usa un tamaño de célula de 53 bytes. Este tamaño es una solución intermedia entre
un tamaño de célula pequeño que se desea para asegurar retrasos pequeños para paquetes de voz
y uno de célula algo más grande que es deseable en la comunicación de datos a fin de reducir la
carga general de la formación de paquetes para un mensaje y para tener que volver a ensamblar-
los con objeto de formar un mensaje. Cada célula contiene un encabezado de 5 bytes y un campo
de datos de 48 bytes. El encabezado contiene dos ítems de información: una id de ruta virtual
(VPI) y una id de canal virtual (VCI).
La figura 15.9 contiene un diagrama esquemático que ilustra el funcionamiento de un con-
mutador ATM. El interruptor contiene una tabla de enrutamiento que tiene una entrada para
cada ruta virtual definida en el interruptor. La entrada contiene dos campos: el campo VPI y el
campo puerto. En la figura 15.9, el identificador de rutas virtuales de la célula entrante es n, y
la n-ésima entrada en la tabla de enrutamiento contiene m y p. El conmutador copia m al campo
VPI de la célula y envía la célula modificada en el puerto p. Este arreglo sencillo asegura que
las id asignadas a rutas virtuales no tienen que ser únicas en el sistema; sólo lo tienen que ser en
el conmutador. Las acciones de conmutación se realizan en el hardware del conmutador; ellas
proveen conmutaciones extremadamente rápidas, del orden de dígitos dobles bajos de micro-
segundos, que hacen posible que se provean velocidades de transmisión tipo LAN a través de
grandes áreas de la red.

VPI port
VPI VCI p VPI VCI
n #n m p m
encabeza- datos encabeza- datos
miento tabla de miento
enrutamiento

conmutador
ATM

Figura 15.9 Un conmutador ATM.

Mientras crea una nueva ruta virtual, una aplicación especifica el ancho de banda deseado.
El SO establece una ruta virtual reservándole ancho de banda en ligas individuales, seleccionan-
do un identificador de ruta virtual única en cada conmutador y actualizando su tabla de enruta-
miento. Mientras manejan el tráfico en canales virtuales de la misma ruta virtual, los host usan

18 MAQ. CAP. 15(F0694).indd 649 8/10/07 1:18:30 AM


650 CAPÍTULO 15 Sistemas operativos distribuidos

el multiplexado estadístico para proveer el ancho de banda correspondiente para aplicaciones


individuales. De este modo, diferentes aplicaciones pueden transmitir mensajes en forma simul-
tánea a través de sus rutas virtuales. Esto permite una buena utilización de anchos de banda en
el sistema.
Una red ATM tiene una arquitectura tipo malla-estrella. Los conmutadores están conectados
entre sí en forma de una malla. Los host están conectados a los conmutadores ATM en una red
de estrellas. Esta estrategia provee una ruta entre cada par de nodos. La figura 15.10 muestra
las capas de protocolo en el modelo de referencia de protocolo ATM. La capa física realiza la
transferencia de células en toda la red. La capa ATM realiza la transmisión de mensajes entre
entidades ATM. Esta capa realiza el multiplexado y desmultiplexado de canales virtuales a rutas
virtuales, planificación de células y enrutamiento de células. La capa de adaptación de ATM
provee diferentes tipos de servicios para diferentes tipos de tráfico, tales como la comunica-
ción por voz, video y datos. Proporciona protocolos separados para cada tipo de tráfico.

Aplicaciones
Voz Video Datos

Capa de adaptación

Capa ATM

Capa física

Figura 15.10 Modelo de referencia del protocolo ATM.

15.7.4 Estrategias de conexión

Una conexión es una ruta de datos entre procesos comunicantes. Una estrategia de comunicación,
también denominada técnica de conmutación, determina cuándo y por cuánto tiempo se deberá
establecer una conexión entre un par de procesos. La elección de la técnica de conmutación in-
fluye en la eficiencia de comunicación entre un par de procesos y la capacidad de procesamiento
de las ligas de comunicación. La figura 15.11 ilustra tres estrategias de conexión. Usaremos la
notación mi para un mensaje y pcj(mi) para el paquete j-ésimo del mensaje mi.

Conmutación por circuitos Un circuito es una conexión que se usa exclusivamente por
parte de un par de procesos comunicantes y que transporta todos los mensajes entre ellos (véase
la figura 15.11a)). Se establece un circuito cuando varios procesos deciden comunicarse, es decir,
antes de que se transmita el primer mensaje. Las acciones de configuración de un circuito invo-
lucran la decisión sobre la ruta actual de red que los mensajes van a seguir y la correspondiente

18 MAQ. CAP. 15(F0694).indd 650 8/10/07 1:18:30 AM


15.7 Realización de redes (networking) 651

m1 pc1 (m1 )

m3 m2 m1
m2
Pi Pj Pi Pj Pi Pj
pc3 (m1 )

m3 pc2 (m1 )

Conmutación por Conmutación por Conmutación por


circuitos mensajes paquetes
a) b) c)

Figura 15.11 Estrategias de comunicación: la conmutación por circuitos, mensajes y paquetes.

reservación de los recursos de comunicación. A cada conexión se le da una id única y los proce-
sos especifican la id de conexión mientras envían y reciben mensajes.
La ventaja de la conmutación por circuitos es que los mensajes no enfrentan retrasos una vez
que el circuito está establecido. Sin embargo, un circuito inmoviliza un conjunto de recursos de
comunicación y causa cargas generales y retrasos de preparación, por lo que el uso de la conmu-
tación por circuitos sólo es justificable si la densidad general de mensajes en el sistema es baja,
aunque se espera una densidad entre media y alta entre un par de procesos.

Conmutación por mensajes Se establece una conexión para cada mensaje que se inter-
cambia entre un par de procesos. De esta forma, los mensajes entre el mismo par de procesos
podrán viajar a lo largo de diferentes rutas en el sistema (véase la figura 15.11b)). La conmuta-
ción por mensajes causa una carga general repetitiva y podrá causar retrasos debido al tiempo de
configuración de la conexión, por lo que su uso es justificado si existe un tráfico ligero entre un
par de procesos. No inmoviliza recursos de comunicación y, por tanto, otros procesos pueden
usar la misma conexión, o algunas ligas de ella, para su comunicación. El tráfico en la red deberá
ser suficientemente denso para explotar esta posibilidad.

Conmutación por paquetes En la conmutación por paquetes, un mensaje es partido en


dos partes de tamaño estándar que se llaman paquetes. Se establece una conexión para cada
paquete individual, por lo que los paquetes de un mensaje podrán viajar a lo largo de diferentes
rutas (véase la figura 15.11c)) y llegar fuera de secuencia en un sitio de destino. El uso de la
conmutación por paquetes causa dos tipos de carga general: un paquete tiene que llevar una
identificación en su encabezado —la id del mensaje al que pertenece, el número secuencial
dentro del mensaje y las id de los procesos de transmisor y destinatario— y los paquetes deben
estar agrupados para formar mensajes en el sitio de destino. Sin embargo, el uso de paquetes
de tamaño fijo reduce el costo de la retransmisión cuando surge un error. Además, las ligas no
están monopolizadas por pares específicos de procesos, por lo que todos los pares de procesos
comunicantes reciben un servicio justo e imparcial. Por estas características, la conmutación por
paquetes es atractiva para procesos interactivos.
Debido al costo de la configuración de conexiones, a menudo se usan en la práctica proto-
colos sin conexión para el envío de mensajes y paquetes. En este protocolo, el nodo de origen
simplemente selecciona uno de sus nodos vecinos y le envía el mensaje. Si éste no es el nodo

18 MAQ. CAP. 15(F0694).indd 651 8/10/07 1:18:30 AM


652 CAPÍTULO 15 Sistemas operativos distribuidos

destinatario, guarda el mensaje en su memoria y decide a cuál de los vecinos enviarlo, y repite
la acción hasta que el mensaje llegue al nodo destinatario. Este método es denominado método
de almacenar y remitir de transmisión de un mensaje. Un paquete se transmite en forma similar.
La transmisión sin conexión puede adaptarse mejor a las densidades en ligas de comunicación
que la conmutación por mensajes o paquetes porque un nodo puede hacer la selección de la liga
cuando está listo para enviar un mensaje o paquete. Normalmente es implementado por medio
del intercambio de informaciones de tráfico entre nodos y llevando una tabla en cada nodo que
indica a qué vecino enviarlo a fin de llegar a un nodo destinatario. Sin embargo, cada nodo debe-
rá tener una memoria grande para el almacenamiento intermedio de mensajes y paquetes cuando
sus ligas de salida están congestionadas.

15.7.5 Enrutamiento

Se invoca la función de enrutamiento cada vez que se va a establecer una conexión. Esta función
decide qué ruta de la red deberá usar la conexión. La elección de la estrategia de enrutamiento
influye en la capacidad de adaptarse a los cambios en los patrones de tráfico del sistema. La
figura 15.12 ilustra tres estrategias de enrutamiento.

Pk Pl Pk Pl Pk m2 Pl

m3 m2 m1
m1
Pi Pj Pi Pj Pi Pj

N1 N2 N1 N2 N1 N2
m3

Enrutamiento fijo Circuito virtual Enrutamiento dinámico


a) b) c)

Figura 15.12 Estrategias de enrutamiento: enrutamiento fijo, circuito virtual y enrutamiento dinámico.

Enrutamiento fijo Se especifica una ruta en forma permanente para la comunicación entre
un par de nodos (véase la figura 15.12a)). Cuando se desean comunicar procesos ubicados en
estos nodos, se establece una conexión que usa esta ruta. La implementación del enrutamiento
fijo es sencilla y eficiente: cada nodo solamente contiene una tabla que muestra rutas a todos los
demás nodos del sistema; sin embargo, le falta la flexibilidad para hacer frente a fluctuaciones
en densidades de tráfico y fallas de nodos o ligas. Por tanto, su uso puede dar como resultado
retrasos o baja capacidad de procesamiento.

Circuito virtual Se selecciona una ruta al inicio de una sesión entre un par de procesos. Se
usa para todos los mensajes enviados durante la sesión (véase la figura 15.12b)). Se usan infor-
maciones sobre densidades de tráfico y retrasos de comunicación a lo largo de diferentes ligas
en el sistema para decidir la mejor ruta para una sesión. Esta estrategia puede entonces adaptarse
a cambios en los patrones de tráfico y fallas de nodos o ligas; por tanto, asegura una buena capa-
cidad de procesamiento de la red y buenos tiempos de respuesta.

18 MAQ. CAP. 15(F0694).indd 652 8/10/07 1:18:30 AM


15.7 Realización de redes (networking) 653

Enrutamiento dinámico Se selecciona una ruta cada vez que se va a enviar un mensaje
o paquete, de tal modo que diferentes mensajes entre un par de procesos y diferentes paquetes
de un mensaje podrán usar diferentes rutas (véase la figura 15.12c)). Esta característica permite
que la estrategia de enrutamiento responda en forma más efectiva a cambios en los patrones
de tráfico y fallas en nodos y ligas. Por tanto, lleva a una mejor capacidad de procesamiento
y mejores tiempos de respuesta de los que se obtienen usando circuitos virtuales. En el Arpa-
net, que fue el precursor del Internet, se intercambiaban constantemente informaciones entre
nodos respecto a la densidad de tráfico y retrasos de comunicación a lo largo de cada liga.
Estas informaciones se usaban para determinar la mejor ruta actual hacia un nodo destinatario
determinado.

15.7.6 Protocolos de redes

Se tienen que abordar varios asuntos mientras se implementa la comunicación, tales como el
nombrado de sitios en el sistema, la resolución de nombres eficiente, el aseguramiento de la
eficiencia de comunicación y cómo hacer frente a fallas. Un protocolo de red es un conjunto de
reglas y convenciones que se usa para implementar la comunicación a través de una red.
Se usa una jerarquía de protocolos de redes para proveer una separación de los asuntos.
Cada protocolo aborda uno o varios asuntos referentes a la comunicación y provee una interfaz
con los protocolos que están arriba y abajo de él en la jerarquía. Los protocolos de nivel menor
se dirigen a aspectos relacionados con la transmisión de datos, mientras que los de mayor ni-
vel se dirigen a asuntos de semántica que se refieren a aplicaciones. Las capas de los protocolos
son como las capas de abstracción en un modelo (véase la sección 1.1). Ofrecen las mismas
ventajas: una entidad que usa un protocolo en una capa más alta no necesita estar consciente de
los detalles de una capa más baja.

El protocolo ISO La Organización Internacional de Normas (ISO, por sus siglas en inglés)
desarrolló un modelo de referencia de interconexión de sistemas abiertos (modelo OSI) para
la comunicación entre entidades de un sistema abierto. Este modelo consiste en siete capas de
protocolos que se describen en la tabla 15.7. Según el caso, se denomina protocolo ISO, pila
de protocolos ISO o modelo ISO.

Proceso de
aplicación
Capa de aplicaciones
Capa de presentaciones
Capa de sesiones
Capa de transporte
Capa de la red
Capa de enlace de datos
Capa física
Transmisor Receptor

Figura 15.13 Operación de la pila de protocolos ISO.

18 MAQ. CAP. 15(F0694).indd 653 8/10/07 1:18:31 AM


654 CAPÍTULO 15 Sistemas operativos distribuidos

Tabla 15.7 Capas de la pila de protocolos ISO

Capa Función
1. Capa física Provee los mecanismos eléctricos para la
transmisión de bits por medio de una liga
física.
2. Capa de enlaces Organiza los bits recibidos en marcos. Rea-
de datos liza la detección de errores en marcos. Reali-
za el control de flujo.
3. Capa de la red Realiza el enrutamiento y control de flujo.
4. Capa de transporte Forma paquetes salientes. Ensambla paque-
tes entrantes. Realiza la detección de fallas
y retransmisiones.
5. Capa de sesiones Establece y termina sesiones. Toma medi-
das para reiniciaciones y recuperación.
6. Capa de Implementa la semántica de datos realizan-
presentaciones do el cambio de presentación, compresión y
cifrado/descifrado donde sea necesario.
7. Capa de Provee la interfaz de red para aplicaciones.
aplicaciones

La figura 15.13 ilustra la operación del modelo OSI cuando dos procesos de aplicación
intercambian un mensaje. El mensaje proviene de una aplicación que lo presenta a la capa de
aplicaciones. Ésta le agrega unas informaciones de control en forma de un campo de encabe-
zado. El mensaje pasa entonces a través de las capas de presentación y sesiones, que agregan
sus propios encabezados. La capa de presentación realiza el cambio de representación de datos
y cifrado/descifrado. La capa de sesiones establece una conexión entre los procesos transmisor y
receptor. La capa de transporte parte el mensaje en paquetes y entrega los paquetes a la capa de la
red. La capa de la red determina la liga en la que cada paquete debe enviarse y le pasa una id de
liga y un paquete a la capa de enlaces de datos. La capa de enlaces de datos ve el paquete como
una cadena de bits, le agrega informaciones de detección y corrección de errores y lo entrega a
la capa física para su transmisión efectiva. Cuando se recibe el mensaje, la capa de enlaces de
datos realiza la detección de errores y forma marcos, la capa de transporte forma mensajes y la
capa de presentación convierte los datos a la presentación deseada por la aplicación. Las capas
de protocolo se analizan a continuación.
La capa física es responsable de los aspectos mecánicos, eléctricos, funcionales y de pro-
cedimiento para transmitir flujos de bits a través de la red. Se implementa en el hardware de un
dispositivo de realización de redes. RS-232C y EIA-232D son las normas comunes para capas
físicas.
La capa de enlaces de datos provee las facilidades de detección de errores, corrección de
errores y control de flujo. Parte el flujo de bits que va a ser enviado en bloques de tamaño fijo que
se llaman marcos y agrega una suma verificadora de redundancia cíclica (CRC) a cada marco.
También provee el control de flujo mediante el envío de marcos a una velocidad que el receptor
pueda manejar. El HDLC (control de enlaces de datos de alto nivel) es un protocolo común de
esta capa.

18 MAQ. CAP. 15(F0694).indd 654 8/10/07 1:18:31 AM


15.7 Realización de redes (networking) 655

La capa de la red es responsable de proveer conexiones y rutas entre dos sitios de un sis-
tema. Protocolos comunes de esta capa son el protocolo X.25, que es un protocolo orientado
a la conexión que usa circuitos virtuales, y el protocolo Internet (IP), que es un protocolo sin
conexión. De este modo, el enrutamiento es la función principal de esta capa y la conexión es
una función opcional. La capa de la red es sobre todo redundante en las LAN y en sistemas con
conexiones de punto a punto.
La capa de transporte provee la transmisión libre de errores de mensajes entre sitios. Parte
un mensaje en paquetes y los entrega a la capa de la red. También maneja errores de comunica-
ción tales como la no entrega de paquetes debido a fallas de nodos o ligas. Esta característica se
parece a la de confiabilidad de los protocolos IPC y, por ende, se implementa en forma análoga
por medio de intervalos de tiempo y retransmisiones (véase la sección 15.5). ISO tiene cinco
clases de protocolos de capas de transporte enumerados de TP0 hasta TP4. Otros protocolos de
capas de transporte comunes son el protocolo de control de transporte (TCP), que es un protoco-
lo confiable orientado a la conexión, y el protocolo de datagramas del usuario (UDP), que es un
protocolo no confiable sin conexión.
La capa de sesiones provee medidas para controlar el diálogo entre dos entidades que usa
un protocolo orientado a la conexión. Provee la autentificación, diferentes tipos de diálogos
(de un solo sentido, de doble sentido alterno o de doble sentido simultáneo) y facilidades de re-
cuperación de controles. Ofrece el control de diálogos para asegurar que los mensajes intercam-
biados que usan primitivas no bloqueadoras send lleguen en el orden correcto (véase la sección
15.5). También provee un servicio de cuarentena donde los mensajes son almacenados tempo-
ralmente en un sitio de receptor hasta que son explícitamente enviados por el transmisor. Esta
facilidad es útil en la realización de acciones atómicas en un archivo (véase la sección 7.10.2.2)
y en la implementación de transacciones atómicas (véase la sección 18.4).
La capa de presentación admite servicios que cambian la representación de un mensaje
para manejar diferencias de hardware entre transmisores y receptores, para conservar la confi-
dencialidad de datos por medio del cifrado y para reducir los volúmenes de datos mediante la
compresión.
La capa de aplicaciones admite servicios específicos de aplicaciones, tales como la trans-
ferencia de archivos, correo electrónico y el establecimiento remoto de comunicación. Algunos
protocolos comunes de esta capa son FTP (protocolo de transferencia de archivos), X.400 (co-
rreo electrónico) y rlogin (establecimiento remoto de comunicación).

Protocolo TCP/IP El protocolo de control de transmisión/protocolo Internet (TCP/IP) es


un protocolo usual para la comunicación a través del Internet. Tiene menos capas que el protoco-
lo ISO, por lo que es más eficiente y a la vez más difícil de implementar. La figura 15.14 muestra
detalles de sus capas. La más baja está ocupada por un protocolo de enlace de datos. El protocolo
Internet (IP) es un protocolo de capas de redes en la pila del protocolo ISO; este protocolo puede
operar encima de cualquier protocolo de enlaces de datos. El IP realiza la transmisión de datos
entre dos host en el Internet. La dirección del host destinatario se proporciona en el formato de
dirección de 32 bits. El IP es un protocolo no confiable sin conexión; no garantiza que paquetes
de un mensaje sean entregados sin errores, sólo una vez y en el orden correcto. Estas propiedades
son proporcionadas por los protocolos que ocupan niveles mayores en la jerarquía.
El protocolo Internet provee la comunicación de host a host por medio de una dirección IP
que identifica en forma única un host en el Internet. Los protocolos en las siguientes capas más
altas proveen la comunicación entre procesos: cada host asigna números de puerto únicos de 16
bits a procesos, y un proceso transmisor usa una dirección de proceso destinatario que es un par

18 MAQ. CAP. 15(F0694).indd 655 8/10/07 1:18:31 AM


656 CAPÍTULO 15 Sistemas operativos distribuidos

Protocolo de transferencia de archivos (FTP), correo


Capas ISO 5-7 electrónico, establecimiento remoto de comunicación
o un protocolo específico de una aplicación

Protocolo Protocolo de
Capa ISO 4 de control de datagrama del
transmisión (TCP) usuario (UDP)

Capa ISO 3 Protocolo Internet (IP)

Capa ISO 2 Protocolo de enlaces de datos

Figura 15.14 La pila del protocolo de control de transmisión/protocolo Internet (TCP/IP).

(dirección IP, número de puerto). El uso de números de puertos permite que muchos procesos
dentro de un host envíen y reciban mensajes en forma concurrente. A algunos servicios famosos,
tales como FTP, telnet, SMTP y HTTP se asignaron números de puertos estándares por parte de
la autoridad de números asignados del Internet (IANA); otros números de puerto son asignados
por el SO en un host.
Como se muestra en la figura 15.14, pueden usarse dos protocolos en la capa que está arriba
del IP, que corresponde a la capa de transporte, es decir, capas dentro de la pila del protocolo
ISO. El protocolo de control de transmisiones (TCP) es un protocolo confiable orientado a co-
nexiones. Este protocolo emplea un circuito virtual entre dos procesos y provee confiabilidad,
retransmitiendo un mensaje que no fue recibido dentro de un intervalo de tiempo esperado (véa-
se la sección 15.5 para una discusión de confirmaciones e intervalos de tiempo que se usan para
asegurar la entrega confiable de mensajes). La carga general por asegurar la confiabilidad es alta
si las velocidades de un transmisor y un receptor no coinciden o si la red sufre de una sobrecarga;
por tanto, el TCP realiza el control de flujo para asegurar que el transmisor no envía paquetes con
una velocidad más alta que la de recepción del receptor, y el control de congestión para asegurar
que el tráfico es regulado de tal manera que una red no esté sobrecargada.
El protocolo de datagramas de usuarios (UDP) es un protocolo no confiable sin conexión
que ni garantiza la entrega de un paquete ni asegura que los paquetes de un mensaje sean entre-
gados en el orden correcto. Esto causa una carga general baja en comparación con el TCP porque
no tiene que establecer ni mantener un circuito virtual ni asegurar la entrega confiable. El UDP
se emplea en aplicaciones multimedia y en videoconferencias porque la pérdida ocasional de
paquetes no es un problema de corrección en estas aplicaciones; sólo causa una baja calidad
de imagen. Estas aplicaciones usan sus propios mecanismos de control de congestión, tales como
la reducción de la resolución de imágenes —y, por consiguiente, reducción de la calidad de la
imagen— si un transmisor, un receptor o la red están sobrecargados.
La capa superior de la pila TCP/IP está ocupada por un protocolo de capas de aplicación,
como el protocolo de transferencia de archivos, un protocolo de correo electrónico, como
el SMTP, o un protocolo de conexión remota. Esta capa corresponde a las capas 5-7 en el

18 MAQ. CAP. 15(F0694).indd 656 8/10/07 1:18:31 AM


15.8 Modelo de un sistema distribuido 657

protocolo ISO. Cuando se usa el UDP en las capas inferiores, la capa superior puede ser ocu-
pada por un protocolo específico de aplicaciones implementado en un proceso de la misma
aplicación.

15.7.7 Ancho de banda y latencia de redes

Cuando se van a intercambiar datos entre dos nodos, el hardware de realización de redes y los
protocolos de la red participan en la transferencia de datos a través de una liga, y procesadores
de comunicación (CP) almacenan y reexpiden los datos hasta que lleguen al nodo destinatario.
Dos aspectos del desempeño de la red son la prontitud con la que los datos pueden llegar al nodo
destinatario y la velocidad con la que los datos pueden ser entregados.
El ancho de banda es la velocidad con la que los datos se transfieren a través de una red.
Está sujeto a varios factores, tales como capacidades de las ligas de redes, índices de error y
retrasos en routers, puentes y puertos de interconexión. El ancho de banda pico es la máxima
velocidad teórica con la que pueden transferirse datos entre dos nodos. El ancho de banda efec-
tivo puede ser menor que el ancho de banda pico debido a errores de transmisión de datos que
llevan a intervalos de tiempo y retransmisiones. La latencia es el tiempo transcurrido entre el
envío de un byte de datos por parte de un nodo fuente y su recepción en el nodo destinatario.
Normalmente se calcula para el primer byte de los datos que van a ser transferidos. El tiempo de
procesamiento en las capas de un protocolo de red y los retrasos debidos a la congestión de redes
contribuyen a la latencia.

15.8 MODELO DE UN SISTEMA DISTRIBUIDO

Un modelo de sistema se emplea para razonar las propiedades útiles de un sistema distribui-
do, tales como el impacto de fallas sobre su funcionamiento así como la latencia y el costo
de la comunicación por mensajes. Un sistema distribuido normalmente se modela como una
gráfica

S ⫽ (N, E)

donde N y E son conjuntos de nodos y aristas, respectivamente. Cada nodo podrá representar un
host, es decir, un sistema de cómputo, y cada arista podrá representar una liga de comunicación
que conecta dos nodos; sin embargo, como se discutirá más adelante, nodos y aristas también
podrán tener otras connotaciones. El grado de un nodo es el número de aristas conectadas a él.
Se supone que cada nodo tiene una lista de importación que describe recursos no locales y ser-
vicios que el nodo puede utilizar, y una lista de exportación que describe los recursos locales del
nodo que son accesibles para otros nodos. Por motivos de sencillez, no incluiremos el servidor
de nombres en el modelo del sistema (véase la sección 15.5.1).
Dos tipos de modelos gráficos de un sistema distribuido son útiles en la práctica. Un modelo
físico se usa para representar el arreglo de entidades físicas en un sistema distribuido. En este
modelo, los nodos y aristas tienen las implicaciones que se describieron con anterioridad, es
decir, un nodo es un sistema de cómputo y una arista es una liga de comunicación. Un modelo ló-
gico es una abstracción. Los nodos en un modelo lógico representan entidades lógicas, tal como
procesos y aristas representan relaciones entre entidades. Un modelo lógico podrá usar aristas

18 MAQ. CAP. 15(F0694).indd 657 8/10/07 1:18:31 AM


658 CAPÍTULO 15 Sistemas operativos distribuidos

no dirigidas o aristas dirigidas. Una arista no dirigida representa una relación simétrica, como la
comunicación entre procesos de doble sentido. Una arista dirigida representa una relación asimé-
trica, como la relación padre-hijo entre procesos o comunicación interproceso de un solo sentido.
Nótese que los nodos y aristas en un modelo lógico posiblemente no tengan una correspondencia
idéntica con entidades físicas en un sistema distribuido.

Tabla 15.8 Propiedades de sistema determinadas mediante el análisis de un modelo de sistema

Propiedad Descripción
Impacto de fallas Fallas pueden particionar un sistema, es decir, partirlo en dos o más par-
tes aisladas de tal modo que un nodo en una parte no puede ser alcanza-
do por un nodo en otra parte. Un modelo de sistema puede ser analizado
para encontrar el número más pequeño de fallas que pueden particionar
el sistema.
Resistencia Un sistema se dice ser k-resistente, donde k es una constante, si k es el
número más grande de fallas a pesar de las cuales un sistema puede fun-
cionar sin alteración.
Latencia entre La latencia mínima entre dos nodos depende del número de ligas de co-
dos nodos municación en una ruta cualquiera entre los nodos, y la mínima latencia
de cada liga de comunicación.
El costo de enviar En un sistema completamente conectado que contiene n nodos, el costo
informaciones a puede ser tan bajo como n ⫺ 1 mensajes. El costo puede ser mayor si el
cada nodo sistema no está completamente conectado.

Se analiza un modelo de sistema para determinar sus propiedades útiles. La tabla 15.8 des-
cribe algunas de estas propiedades. El número más bajo de fallas que pueden particionar un
sistema puede determinarse mediante el análisis del grado de todos los nodos en el sistema. Si
n⬘ es el grado más pequeño de un nodo, n⬘ fallas podrán particionar un sistema. Este sistema es
(n⬘⫺ 1) resistente porque puede tolerar hasta n⬘ ⫺ 1 fallas sin sufrir particiones. Como lo ilustra
el ejemplo 15.1, un análisis similar puede usarse como una técnica de diseño de redes.

Ejemplo 15.1 Si se espera que solamente uno o dos sitios en un sistema podrán sufrir fallas si-
multáneamente, y si nunca ocurren fallas en ligas de comunicación, será adecuado posicionar tres
unidades de cada recurso en tres diferentes sitios en el sistema. Si ligas de comunicación también
podrán sufrir fallas, pero el número total de fallas no excede dos, entonces deben existir tres unida-
des de cada recurso, y cada sitio debe tener por lo menos tres ligas de comunicación directamente
conectadas a él. En este tipo de sistema un recurso sólo puede llegar a ser indisponible si ocurren
tres o más fallas.

Para enviar una información a todos los nodos del sistema, el nodo donde se origina la
información normalmente la envía a sus vecinos, y cada nodo que la recibe la envía también a
sus vecinos, y así sucesivamente. Por lo general, este método requiere e mensajes, donde e es
el número de aristas en el sistema. Sin embargo, si el sistema está completamente conectado,
es posible usar un protocolo más sencillo en el que sólo el nodo de origen envía mensajes a sus
vecinos. Esta operación requerirá solamente n ⫺ 1 mensajes.

18 MAQ. CAP. 15(F0694).indd 658 8/10/07 1:18:32 AM


15.9 Cuestiones de diseño en sistemas operativos distribuidos 659

Los análisis para determinar el impacto de fallas en un sistema, la resistencia de un sistema


y el costo de enviar informaciones a todos los nodos del sistema podrán realizarse en un modelo
físico o en un modelo lógico de una computación distribuida. La latencia entre dos nodos es
determinada mediante el análisis de un modelo físico. Los análisis en modelos lógicos se usan
normalmente para determinar la complejidad de algoritmos de control que se usan en un SO
distribuido. Veremos este tipo de uso en el capítulo 17.

15.9 CUESTIONES DE DISEÑO EN SISTEMAS


OPERATIVOS DISTRIBUIDOS

El usuario de un sistema distribuido espera que su sistema operativo provea el aspecto y tacto de
un SO convencional y que también provea los beneficios de un sistema distribuido que se resu-
men en la tabla 15.1. Para satisfacer estas expectativas, deberán distribuirse los datos, recursos,
usuarios y sus computaciones de manera efectiva entre los nodos del sistema. Un SO distribuido
logra esto por medio de las cuestiones de diseño que se analizan a continuación.

Transparencia de recursos y servicios La transparencia de recursos y servicios implica


que sus nombres no dependen de sus ubicaciones en el sistema. Por ende, la transparencia de
recursos le permite a un usuario acceder a recursos locales y no locales de manera idéntica.
También permite que un SO cambie la ubicación de un recurso libremente porque un cambio de
ubicación no afecta al nombre del recurso y, por tanto, no afecta a sus usuarios ni a sus aplica-
ciones. El SO puede aprovechar esta característica para realizar la migración de datos a fin de
reducir el tráfico de la red generado por accesos a los datos. La transparencia es importante en un
sistema de archivos distribuidos porque el sistema de archivos querrá almacenar los archivos de
usuarios en diferentes nodos para optimizar el uso de discos y de la red, mientras que un usuario
querrá acceder a archivos en forma idéntica, independientemente de sus ubicaciones. Analizare-
mos en detalle la transparencia en el capítulo 19.

Distribución de funciones de control Una función de control es una función realizada por
el kernel con la finalidad de controlar recursos y procesos en el sistema, por ejemplo, la asig-
nación de recursos, el manejo de bloqueos mutuos y la planificación. Las funciones de control
centralizadas enfrentan dos problemas en un sistema distribuido: debido a la latencia, de la red
no es posible obtener informaciones consistentes sobre el estado actual de procesos y recursos en
todos los nodos del sistema. Una función centralizada también es un potencial cuello de botella
para el desempeño y un punto individual de falla en el sistema. Debido a estos problemas, un
SO distribuido realiza una función de control por medio de un algoritmo de control distribuido
cuyas acciones se realizan en diferentes nodos del sistema en forma coordinada. Hablaremos de
algoritmos distribuidos para realizar funciones de control, como la detección de bloqueos mu-
tuos, planificación y exclusión mutua en el capítulo 17.

Desempeño del sistema Un buen desempeño del sistema bajo condiciones de carga pre-
dominantes se obtiene enfocándose en la eficiencia de recursos. Además de las técnicas de SO
convencionales, un SO distribuido usa dos técnicas nuevas para proveer un buen desempeño
del sistema: la migración de datos y la migración de computación. La primera es empleada para
reducir latencias de la red y para mejorar los tiempos de respuesta de procesos. La migración de

18 MAQ. CAP. 15(F0694).indd 659 8/10/07 1:18:32 AM


660 CAPÍTULO 15 Sistemas operativos distribuidos

computación se emplea para asegurar que se dirijan casi idénticas cantidades de la carga compu-
tacional a todos los CPU en el sistema. Esta técnica se llama equilibrio de carga.
Un sistema distribuido normalmente crece en tamaño a través del tiempo debido a la adi-
ción de nodos y usuarios. Conforme crece el tamaño de un sistema, los tiempos de respuestas
de procesos podrán degradar debido al aumento de carga de recursos y servicios del SO, y por
el aumento de la carga general de las funciones de control del SO. Esta degradación obstruye el
crecimiento de un sistema, por lo que el desempeño de un sistema distribuido deberá ser escala-
ble, es decir, el desempeño medido como el promedio del tiempo de respuesta no deberá variar
mucho con el tamaño del sistema. Una importante técnica de escalabilidad es hacer autosuficien-
tes los clusters de host que hemos analizado en la sección 15.4, de tal modo que el tráfico de la
red no crezca conforme se agreguen más clusters al sistema. En el capítulo 19 discutiremos cómo
la técnica de copia de archivos en caché que se usa en sistemas de archivos distribuidos ayuda a
satisfacer este requerimiento.

Confiabilidad La disponibilidad de recursos queda asegurada usando la técnica de toleran-


cia de fallas para protegerse contra fallas probables. Se toleran fallas de ligas y nodos mediante
la provisión de la redundancia de recursos y ligas de comunicación. Si una falla ocurre en una
ruta de la red a un recurso o en el propio recurso, una aplicación puede usar otra ruta de la red a
un recurso o usar otro recurso. De este modo, un recurso no está disponible sólo cuando suceden
fallas imprevistas.
La consistencia de datos se convierte en un problema cuando se distribuyen o reproducen
datos. Si varias partes de un conjunto de datos distribuidos tienen que modificarse, una falla no
deberá poner al sistema en un estado donde algunas partes de los datos han sido actualizadas
pero otros no. Un SO convencional usa la técnica de acciones atómicas para cumplir con este
requerimiento (véase la sección 7.10.2.2). Un SO distribuido emplea una técnica llamada proto-
colo de compromiso de dos fases para este propósito (véase la sección 18.4.3).
Partes de una computación podrán ejecutarse en diferentes nodos de un sistema. Si ocurre
una falla de nodo o liga durante la ejecución de una de estas computaciones, el sistema deberá
evaluar el daño causado por la falla y juiciosamente restaurar algunas de las subcomputaciones
a estados previos registrados en respaldos. Este planteamiento se llama recuperación. El sistema
también debe enfrentarse a incertidumbres con respecto a la causa de una falla. El ejemplo 15.2
ilustra estas incertidumbres.

solicitud
Pi Pj

Nodo Ni Nodo N j

Figura 15.15 Cuestiones de resistencia en una solicitud remota.

Ejemplo 15.2 Una computación distribuida consiste en dos subcomputaciones representadas por
los procesos Pi y Pj, que se ejecutan en los nodos N1 y N2, respectivamente (véase la figura 15.15).
El proceso Pi envía una solicitud al proceso Pj y espera una respuesta. Sin embargo, un intervalo de
tiempo ocurre antes de que recibe una respuesta. El intervalo de tiempo podrá ser causado por una
de las siguientes posibilidades:

18 MAQ. CAP. 15(F0694).indd 660 8/10/07 1:18:32 AM


Ejercicio 15 661

1. El proceso Pj nunca recibió la solicitud, por lo que nunca empezó a procesarla.


2. El procesamiento tarda más de lo esperado, es decir, el proceso Pj aún está procesando la soli-
citud.
3. El proceso Pj empezó a procesar la solicitud, pero sufrió una falla antes de completarla.
4. El proceso Pj completó el procesamiento de la solicitud, pero se perdió su respuesta al proceso
Pi.

En el ejemplo 15.2 se necesitan diferentes acciones para manejar la causa de un intervalo


de tiempo. Si el nodo N2 se hubiera colgado, la subcomputación Pj se tendría que repetir, posi-
blemente en algún nodo diferente en el sistema. En otros casos, la subcomputación Pj se podría
haber completado, por lo que su reejecución en otra parte del sistema podrá afectar la consis-
tencia de datos (¡por ejemplo, una actualización se podrá ejecutar dos veces!) o desperdiciar
tiempo del CPU. Hablaremos de técnicas de recuperación especiales diseñadas para el manejo
de incertidumbres en el capítulo 18.

Seguridad La seguridad adquiere una nueva dimensión en un sistema distribuido porque


los mensajes interproceso podrán pasar a través de un procesador de comunicación que opera
bajo un SO diferente. Un intruso podrá ganar el control de este sistema de cómputo y manipular
mensajes que pasan por él o usarlos para hacerse pasar por él. Se usan técnicas especiales para
la seguridad de mensajes y autentificación para impedir estos ataques; las discutiremos en el
capítulo 20.

EJERCICIO 15
1. Discuta cuáles de los medios de sincronización de procesos que se usan en sistemas multiprocesadores
simétricos pueden adaptarse para su uso en clusters (véase el capítulo 13).
2. Analice la posibilidad de implementar los protocolos bloqueadores y no bloqueadores usando monito-
res. ¿Cuáles son las dificultades de la implementación?
3. Escriba una nota breve sobre los factores que influyen en la duración del intervalo de tiempo en el
protocolo RRA de la sección 15.5.3.1.
4. Desarrolle un esquema para descartar respuestas duplicadas recibidas en el sitio del transmisor en el
protocolo RRA.
5. Cuando se usa el enrutamiento dinámico, solicitudes hechas con el uso de llamadas send no bloqueado-
ras podrán llegar al sitio de destino fuera de secuencia. Discuta cómo un protocolo RR no bloqueador
deberá descartar solicitudes duplicadas cuando esta propiedad es válida (refiérase a la sección
15.5.3.2).
6. Comente sobre las propiedades del siguiente protocolo no bloqueador:
a) Un transmisor envía una solicitud y continúa procesando.
b) El receptor envía una respuesta.
c) El transmisor envía una confirmación cuando recibe la respuesta.
7. Se hace un cambio en el protocolo RRA de la sección 15.5.3.1: un proceso destinatario se bloquea
hasta que recibe una confirmación de su respuesta. Analice las propiedades de este protocolo.
8. a) Determine: i) las fallas de sitio, ii) las fallas de ligas y iii) las fallas totales que los sistemas de la
figura 15.16a) pueden tolerar para la comunicación interproceso.

18 MAQ. CAP. 15(F0694).indd 661 8/10/07 1:18:32 AM


662 CAPÍTULO 15 Sistemas operativos distribuidos

b) Determine la colocación de copias de los datos D en los sistemas de la figura 15.16b) si D debe estar
disponible a pesar de dos fallas de sitio/liga en el sistema.

a) b)

Figura 15.16 Ejercicios para determinar la resistencia de los sistemas distribuidos.

9. El diámetro de un sistema distribuido d) es el número más grande de ligas en una ruta entre cualquier
combinación de dos nodos del sistema. Si el máximo retraso de comunicación a lo largo de cual-
quier liga en el sistema es ␦, explique si el máximo retraso de comunicación entre nodos del sistema
puede ser ⬍ d.␦. ¿Será diferente la respuesta si ocurren f fallas en un sistema k-resistente donde f ⱕ k?
10. Compare los paradigmas RPC y evaluación remota sobre la siguiente base:
a) Flexibilidad
b) Eficiencia
c) Seguridad

BIBLIOGRAFÍA
Tanenbaum y van Renesse (1985) es un artículo de estudio sobre sistemas operativos distribuidos. Los
autores analizan protocolos de comunicación bloqueadores y no bloqueadores. Los textos de Sinha (1997),
Coulouris et al. (2005) y Tanenbaum y Van Steen (2002) analizan los temas incluidos en este capítulo.
Comer y Stevens (2000) hablan del modelo de computación cliente-servidor. Birrell y Nelson (1984)
estudian la implementación de llamadas a procedimientos remotos. Tay y Ananda (1990) es un artículo
de estudio de llamadas a procedimientos remotos. Lin y Gannon (1985) analizan el RPC esquemático con
semántica exactly-once. Stamos y Gifford (1990) analizan la evaluación remota. Tanenbaum (2001) estudia
el protocolo ISO, el modelo cliente-servidor y el RPC. Birman (2005) analiza el modelo cliente-servidor
y el RPC.
Tanenbaum (2003) es un texto dedicado a las redes de computadoras que cubre el protocolo ISO con
gran detalle. Comer (2004) es una introducción amplia a la realización de redes que explica el protocolo
TCP/IP. Stallings (2004) analiza varios protocolos de realización de redes. Stevens y Rago (2005) describen
la programación de redes en Unix.

1. Birman, K. (2005): Reliable Distributed Systems: Technologies, Web Services, and Applications,
Springer.
2. Birrell, A.D. y B.J. Nelson (1984): “Implementing remote procedure calls”, ACM Transactions on
Computer Systems, 2, 39-59.
3. Comer, D. (2004): Computer Networks and Internets, 4a. ed., Prentice Hall, Englewood Cliffs.
4. Comer, D. y D. Stevens (2000): Internetworking with TCP/IP, Volume III: Client–Server Program-
ming and Applications, Linux/POSIX Socket Version, Prentice Hall, Englewood Cliffs.

18 MAQ. CAP. 15(F0694).indd 662 8/10/07 1:18:32 AM


Bibliografía 663

5. Coulouris, G., J. Dollimore y T. Kindberg (2005): Distributed Systems—Concepts and Design, 4a.
ed., Addison-Wesley, Nueva York.
6. Lin, K.J. y J.D. Gannon (1985): “Atomic remote procedure call”, IEEE Transactions on Software
Engineering, 11 (10), 1126-1135.
7. Sinha, P.K. (1997): Distributed Operating Systems, IEEE Press, Nueva York.
8. Stallings, W. (2004): Computer Networking with Internet Protocols, Prentice Hall, Englewood
Cliffs.
9. Stamos, J.W. y D.K. Gifford (1990): “Remote evaluation,” ACM Transactions on Programming
Languages and Systems, 12 (4), 537-565.
10. Stevens, W.R. y S.A. Rago (2005): Advanced Programming in the Unix Environment, 2a. ed.,
Addison Wesley Professional.
11. Tanenbaum, A.S. (2001): Modern Operating Systems, 2a. ed., Prentice Hall, Englewood Cliffs.
12. Tanenbaum, A.S. (2003): Computer Networks, 4a. ed., Prentice Hall, Englewood Cliffs.
13. Tanenbaum, A.S. y M. van Steen (2002): Distributed Systems: Principles and Paradigms, Prenti-
ce Hall, Englewood Cliffs.
14. Tanenbaum, A.S. y R. Van Renesse (1985): “Distributed Operating Systems”, Computing Surveys,
17 (1), 419-470.
15. Tay, B.H. y A.L. Ananda (1990): “A survey of remote procedure calls”, Operating Systems Re-
view, 24 (3), 68-79.

18 MAQ. CAP. 15(F0694).indd 663 8/10/07 1:18:33 AM


Capítulo
16
Problemas teóricos
en sistemas distribuidos

Tiempo y estado son dos nociones clave en un sistema operativo: el SO necesita conocer el
orden cronológico en que ocurren eventos, como solicitudes de recursos, y también los estados
de los recursos y los procesos para realizar la asignación y planificación de los primeros. En un
sistema de cómputo convencional, la presencia de una sola memoria y un solo CPU simplifican
el manejo de tiempo y estado. Solamente un evento puede ocurrir en un momento dado, por lo
que el SO conoce de manera implícita el orden cronológico de los eventos y los estados de todos
los procesos y recursos existentes en el sistema.
Un sistema distribuido contiene varios sistemas de cómputo, cada uno con un reloj, una me-
moria y uno o varios CPU; la comunicación entre sistemas de cómputo se lleva a cabo por medio
de mensajes que provocan retrasos de comunicación impredecibles. Por consiguiente, el SO
distribuido no puede conocer el orden cronológico en el cual ocurren los eventos, ni los estados
de recursos y procesos que hay en todos los nodos del sistema en el mismo instante de tiempo.
Por ende, los problemas teóricos clave en sistemas distribuidos son el desarrollo de alternativas
prácticas a las nociones tradicionales de tiempo y estado, el desarrollo de algoritmos para imple-
mentar estas alternativas y la demostración de lo correcto de estos algoritmos.
Presentaremos la noción de precedencia de eventos que se puede usar para descubrir el
orden cronológico en el que algunos eventos ocurren en un sistema distribuido. Luego analizare-
mos dos alternativas a la noción tradicional del tiempo, usando las nociones de relojes lógicos y
relojes vectores. También presentaremos la noción de un registro consistente de estados que pue-
de usarse como una alternativa al estado global de un sistema distribuido en varias aplicaciones.
Estas nociones alternativas de tiempo y estado se emplean en el diseño de algoritmos de control
distribuido y de los algoritmos de recuperación que se usan en un SO distribuido.

19 MAQ. CAP. 16(F0694).indd 664 8/10/07 1:19:16 AM


16.2 Estados y eventos en un sistema distribuido 665

16.1 NOCIONES DE TIEMPO Y ESTADO

El tiempo es la cuarta dimensión: indica cuando ocurre un evento. El estado de una entidad es la
condición o modo de su existencia, que depende de sus características; por ejemplo, el estado de
una célula de memoria es el valor que contiene. Si una entidad está compuesta de otras entidades,
su estado contiene los estados de sus entidades. El estado global de un sistema es compuesto por
los estados de todas las entidades que existen en el sistema en un instante específico de tiempo.
Un SO usa la noción de tiempo y estado para realizar la planificación de recursos y del CPU.
El SO usa el tiempo para saber cuándo ocurrió un evento de solicitud o para encontrar el orden
cronológico en el que ocurrieron eventos de solicitud, y emplea el estado de un recurso para
decidir si se puede asignar. Un SO distribuido también usa estas nociones en la recuperación
para asegurar que los procesos de una computación distribuida estarán en estados mutuamente
consistentes cuando se cuelga y recupera un nodo que contiene algunos de los procesos.
Es fácil manejar tiempo y estado en un SO monoprocesador. El sistema tiene un reloj y
un solo CPU, por lo que el SO puede encontrar los momentos en los que los procesos hicieron
sus solicitudes de recursos y usar esta información para determinar su orden cronológico. Sin
embargo, un sistema operativo normal emplea la noción de tiempo sólo en forma implícita.
Mantiene las informaciones relativas a eventos en una cola de espera, por lo que ésta muestra
el orden cronológico de eventos. El SO también conoce los estados de procesos, así como los
recursos físicos y lógicos.
En un sistema distribuido, cada nodo es un sistema de cómputo con su propio reloj y una
memoria local, y los nodos están conectados por ligas de comunicación que tienen retrasos de
comunicación impredecibles. Por consiguiente, un nodo no puede determinar con precisión el
momento en que ocurrió un evento en otro nodo; también puede ser que su percepción del estado
de un proceso o recurso remoto esté caducada. Por tanto, un SO distribuido no puede usar las
nociones de tiempo y estado de la misma manera que un SO monoprocesador.
En este capítulo analizaremos algunos conceptos teóricos sobre sistemas distribuidos y los
usaremos para desarrollar alternativas prácticas a las nociones de tiempo y estado conforme se
emplean en un sistema monoprocesador. Estas nociones alternativas de tiempo y estado se usan
en el capítulo 17 en el diseño de algoritmos de control distribuidos y en el capítulo 18 en el di-
seño de algoritmos de recuperación.

16.2 ESTADOS Y EVENTOS EN UN SISTEMA DISTRIBUIDO

16.2.1 Estados locales y globales

Cada entidad en un sistema tiene su propio estado. El estado de una célula de memoria es el valor
que contiene. El estado de un CPU es el contenido de sus PSW y registros. El de un proceso es su
etiqueta de estado, el estado de la memoria asignada a él, el estado del CPU si está actualmente
planificado en el CPU o los contenidos de los campos PCB si no lo está, así como el estado de
su comunicación interproceso. El estado de una entidad se llama estado local. El estado global
de un sistema en el instante de tiempo t es la colección de estados locales de todas las entidades
existentes en él en el momento t.

19 MAQ. CAP. 16(F0694).indd 665 8/10/07 1:19:17 AM


666 CAPÍTULO 16 Problemas teóricos en sistemas distribuidos

Denotamos como stk el estado local de un proceso Pk en el momento t, donde se omite el


subíndice si la identidad del proceso está implícito en el contexto. Denotamos el estado global
de un sistema en el momento t como St. Si un sistema contiene n procesos P1 . . . Pn, St ⬅ {st1, t2,
. . . , stn}.

16.2.2 Eventos
Un evento puede ser el envío o recepción de un mensaje a través de un canal, que es una ruta de
comunicación interproceso u otro suceso que no involucra un mensaje. El estado de un proceso
cambia cuando un evento ocurre en él. Representamos un evento de la siguiente manera:

(id del proceso, estado viejo, estado nuevo, descripción del evento, canal, mensaje)

donde canal y mensaje se escriben como “ ” si el evento no involucra el envío o recepción de


un mensaje. Un evento ei ⬅ (Pk, s, s⬘, send, c, m) sólo puede ocurrir cuando el proceso Pk está
en el estado s. El evento es el envío de un mensaje m a través de un canal c. Cuando este evento
ocurre, el proceso Pk entra en el nuevo estado s⬘ (véase la figura 16.1).

Evento ei

Estado viejo s Estado nuevo


de Pk s de Pk

Figura 16.1 Cambio de estado en el proceso Pk al ocurrir el evento ⬍ Pk, s, s⬘, send, c, m ⬎.

Ciertos eventos solamente pueden ocurrir cuando se cumplen algunas condiciones; por
ejemplo, un evento de recepción para el mensaje m por el canal c sólo puede ocurrir si este canal
contiene el mensaje m. De este modo, algunos eventos podrán ser viables en el estado actual de
un proceso.

16.3 PRECEDENCIAS DE TIEMPO, RELOJES Y EVENTOS

Supongamos que un reloj global sea un reloj abstracto al que se puede acceder desde diferen-
tes sitios de un sistema distribuido con resultados idénticos. Si procesos en dos nodos de un
sistema distribuido realizan la llamada al sistema “dar tiempo actual” en el mismo instante,
obtendrán idénticos valores de tiempo. Si realizan estas llamadas al sistema con un intervalo de
␦ unidades de tiempo, obtendrán resultados que difieren por exactamente ␦ unidades de tiempo.
En la práctica, no se puede implementar un reloj global debido a retrasos de comunicación.
Solicitudes de tiempo actual hechas en dos diferentes nodos en el mismo instante enfrentarán
diferentes retrasos de comunicación para llegar al sitio donde se mantiene el reloj. Por consi-
guiente, se les darán diferentes valores de tiempo. Del mismo modo, solicitudes hechas con
intervalos de ␦ unidades de tiempo podrán obtener valores de tiempo que no difieren por exac-
tamente ␦ unidades de tiempo.
Puesto que no se puede implementar un reloj global, podemos explorar un arreglo alterna-
tivo que usa un reloj en cada proceso. Éste se llama reloj local. Se accederá al reloj local de un
proceso cada vez que un proceso realice una llamada “dar tiempo actual”. A fin de implementar

19 MAQ. CAP. 16(F0694).indd 666 8/10/07 1:19:17 AM


16.3 Precedencias de tiempo, relojes y eventos 667

un servicio práctico de cronometrado usando esta idea, los relojes locales deberán estar razo-
nablemente bien sincronizados. La sección 16.3.2 analiza cómo puede lograrse esto usando la
noción de precedencia de eventos.

16.3.1 Precedencia de eventos

La notación e1 → e2 se usa para indicar que el evento e1 precede al evento e2 en el tiempo,


es decir, que el evento e1 ocurrió antes del evento e2. El ordenamiento de eventos implica arre-
glar un conjunto de eventos en una secuencia tal que cada evento de la secuencia preceda al
siguiente. En esencia, implica determinar el orden en que los eventos han ocurrido en un sis-
tema. Se dice que existe un orden total con respecto a la relación de precedencia “→” si todos
los eventos que puedan ocurrir en un sistema pueden ser ordenados. Un orden parcial implica
que algunos eventos, pero no todos, pueden ser ordenados; para ser preciso, en un orden parcial
existen por lo menos dos eventos que no pueden ser ordenados.

Ta

Tabla 16.1 Reglas para el ordenamiento de eventos en un sistema distribuido

Categoría Descripción de la regla


Eventos dentro de un El SO realiza el manejo de eventos, por lo que conoce el orden en el que
proceso ocurren éstos dentro de un proceso.
Eventos en diferentes En una relación causal, es decir, una relación de causa y efecto, un evento
procesos que corresponde a la causa precede a un evento en otro proceso que corres-
ponde al efecto.
Precedencia transitiva La relación de precedencia es transitiva, es decir, e1 → e2, y e2 → e3 implica
e1 → e3.

La tabla 16.1 resume las reglas fundamentales que se usan para realizar el ordenamien-
to de eventos. El SO puede determinar fácilmente la precedencia entre eventos que ocurren
dentro del mismo proceso. Eventos como la ejecución de un evento “send P3, ⬍message mi⬎”
en un proceso P2 y un evento de recepción en P3 que recibe el mensaje mi tienen una relación
causal, es decir, una relación de causa y efecto. Por consiguiente, el evento de envío en el pro-
ceso P2 precede el evento de recepción P3. La relación “→” es de naturaleza transitiva, por ende
e1 → e3 si e1 → e2 y e2 → e3. Esta propiedad puede usarse para determinar precedencias entre
algunos eventos que no son causalmente relacionados ni ocurren dentro del mismo proceso.
Por ejemplo, un evento ei que precede al evento de envío para el mensaje mi en P2 precede a un
evento ej que sigue después del evento de recepción para el mensaje mi en P3 porque ei precede
al evento de envío, el evento de envío precede al evento de recepción y el evento de recepción
precede al evento ej.
Usando las reglas de la tabla 16.1, la precedencia entre dos eventos ei y ej puede clasificarse
de la siguiente manera:

• ei precede ej: Si los eventos ek y el existen de tal modo que ek → el, ei → ek o ei ⬅ ek, y
el → ej o el ⬅ ej.

19 MAQ. CAP. 16(F0694).indd 667 8/10/07 1:19:17 AM


668 CAPÍTULO 16 Problemas teóricos en sistemas distribuidos

• ei sigue después de ej: Si los eventos eg y eh existen de tal modo que eg → eh, ej → eg o
ej ⬅ eg, y eh → ei o eh ⬅ ei.
• ei es concurrente con ej: Éste es el caso si ei no precede ni sigue después de ej.
Un diagrama de tiempos es una gráfica de las actividades de diferentes procesos contra el
tiempo: los procesos están marcados a lo largo del eje vertical en la gráfica y el tiempo lo está a
lo largo del eje horizontal. El ejemplo 16.1 demuestra el uso de un diagrama de tiempos en prece-
dencias determinantes de eventos usando la transitividad de la relación de precedencia. También
ilustra por qué un orden total sobre los eventos no existe en un sistema distribuido.

Ejemplo 16.1 La figura 16.2 muestra actividades en los procesos P1 y P2. El evento e23 es un
evento de “envío”, mientras que e12 es un evento de “recepción” para el mensaje m1. Por ende e23
→ e12. La naturaleza transitiva de “→” lleva a las relaciones de precedencia e22 → e12 y e21 → e12.
La transitividad también proporciona e22 → e13 y e21 → e13. El evento e11 es concurrente con los
eventos e21 y e22. ¡También es concurrente con los eventos e23 y e24!

e11 e12 e13


P1
m1
P2
e21 e22 e23 e24

Figura 16.2 Precedencia de eventos vía diagrama de tiempos.

16.3.2 Relojes lógicos

Un SO necesita un método práctico de ordenamiento de eventos para fines relacionados con la


planificación y asignación de recursos. El método deberá ser eficiente, por lo que deberá realizar
el ordenamiento de eventos en forma directa en lugar de trabajar por medio de relaciones causa-
les y mediante la transitividad. También deberá proveer un orden total sobre eventos, de tal modo
que el SO pueda proporcionar el servicio FCFS para solicitudes de recursos. Este orden podrá
obtenerse de la siguiente manera:

• Incorporación de precedencias en el orden de eventos.


• Ordenamiento arbitrario de eventos que son concurrentes, por ejemplo, los eventos e11 y
e21 en la figura 16.2.

El sellado de tiempo de eventos provee un método directo para el ordenamiento de eventos.


Cada proceso tiene un reloj local que sólo es accesible a sí mismo. El sello de tiempo de un even-
to es su tiempo de ocurrencia de acuerdo con el reloj local del proceso. Supongamos que ts(ei)
represente el sello de tiempo del evento ei. Se realiza el ordenamiento de eventos de acuerdo con
los sellos de tiempo de eventos, es decir, ∀ei, ej : ei → ej si ts(ei) ⬍ ts(ej) y ej → ei si ts(ei) ⬎ ts(ej).
Sin embargo, los relojes locales en diferentes procesos podrán indicar diferentes tiempos debido
a deriva del reloj, lo que afectará la confiabilidad del ordenamiento de eventos basado en el sello
de tiempo. Por ejemplo, si el evento ei ocurrió antes del evento ej, ts(ei) deberá ser ⬍ ts(ej); sin
embargo, si el reloj en el proceso donde ocurrió el evento ei corre más rápido que el reloj en el

19 MAQ. CAP. 16(F0694).indd 668 8/10/07 1:19:18 AM


16.3 Precedencias de tiempo, relojes y eventos 669

proceso donde ocurrió ej, ts(ei) podrá ser > ts(ej). Para evitar estas situaciones es necesario sin-
cronizar los relojes de todos los procesos.
La sincronización de relojes locales se logra usando la relación causal que se encuentra en
el intercambio de mensajes interproceso. Considere un mensaje m enviado por el proceso Pk
para procesar Pl. Supongamos que los sellos de tiempo de los eventos de envío y recepción sean
tk y tl, respectivamente. La relación de causa y efecto entre los eventos de envío y recepción
implica que tk debe ser más pequeño que tl. De no ser así, puede corregirse la situación incre-
mentando el tiempo en el reloj local del proceso receptor a un valor mayor a tk antes del sellado
de tiempo del evento receptor. El algoritmo 16.1 es el algoritmo completo de sincronización de
relojes.

Algoritmo 16.1 (Sincronización de relojes)

1. Cuando un proceso Pk desea enviar un mensaje m al proceso Pl: Pk ejecuta un comando


“send Pl, (ts(send)m)), m)”, donde ts(send (m)) es un sello de tiempo obtenido justo antes
de enviar el mensaje m.
2. Cuando el proceso Pl recibe un mensaje: el proceso Pl realiza las siguientes acciones:
si reloj local(Pl) < ts(send(m)), entonces
reloj local(Pl) :⫽ ts(send(m)) ⫹ ␦;
sellado de tiempo del evento receptor.
donde reloj local(Pl) es el reloj local en el proceso Pl, y ␦ es el promedio de retraso de
comunicación en la red.

La sincronización de relojes lograda por el algoritmo 16.1 se llama sincronización suelta


porque los relojes de los dos procesos son mutuamente consistentes en un intercambio de men-
sajes, pero pueden derivar en otras ocasiones (véase el problema 1 del ejercicio 16). La calidad
de la sincronización de relojes depende de la frecuencia de la comunicación interproceso: una
frecuencia más alta de comunicación provee una sincronización más estrecha. Puede mejorarse
la sincronización por medio de mensajes de sincronización especiales que se intercambian en
intervalos cortos simplemente para mantener los relojes sincronizados.
Note que relojes sincronizados de este modo no muestran el tiempo “real”. Por ejemplo, si el
reloj de un proceso transmisor va adelantado, el reloj en el proceso receptor también se adelanta-
rá. Una vez que aceptamos que los relojes locales no indican el tiempo “real”, no hay necesidad
de incrementarlos todo el tiempo. Un proceso podrá incrementar su reloj local en 1 solamente
cuando ocurre un evento en él, y sincronizar el reloj local, de ser necesario, cuando recibe un
mensaje. Estos relojes se llaman relojes lógicos. Denotamos el reloj lógico del proceso Pk como
LCk. Los relojes lógicos se implementan siguiendo las siguientes reglas:

R1 : Un proceso Pk incrementa LCk en 1 cada vez que ocurre un evento en


él.
R2 : Cuando el proceso Pk recibe un mensaje m que contiene ts(send(m)),
Pk pone su reloj siguiendo la regla LCk = máx (LCk, ts(send(m))
+ 1).

El siguiente ejemplo ilustra la sincronización de relojes mediante estas reglas.

19 MAQ. CAP. 16(F0694).indd 669 8/10/07 1:19:18 AM


670 CAPÍTULO 16 Problemas teóricos en sistemas distribuidos

Ejemplo 16.2 La figura 16.3 contiene el diagrama de tiempos para un sistema que consiste en tres
procesos. El par de números que aparece entre paréntesis debajo de un evento indica valores en
el reloj lógico del proceso antes y después del evento. El reloj lógico en P1 contiene 9 cuando P1
decide enviar el mensaje m1 a P2. Es incrementado mediante la regla R1 y el evento de envío es
sellado con el tiempo, por lo que m1 contiene el sello de tiempo 10. Cuando P2 recibe el mensaje,
su reloj indica 3. Primero incrementa su reloj a 4 usando la regla R1 y luego lo sincroniza usando
la regla R2. El reloj indica ahora 11.

e11 e12 e13


(9,10) (10,27) (27,28)
P1
m1 e22 m3 m4
(11,12)
P2
e21 e23 e24
(3, 11) m2 (12,13) (13,29)

P3
e31 e32
(24, 25) (25, 26)

Figura 16.3 Sincronización de relojes lógicos.

Cuando P2 decide enviar el mensaje m2, su reloj lógico es incrementado a 12. De este modo,
m2 contiene el sello de tiempo 12. Cuando m2 llega a P3, éste aplica las reglas R1 y R2. La regla R2
no tiene efecto, ya que el valor del reloj lógico de P3 es mucho más grande que el sello de tiempo en
el mensaje. Cuando P3 envía m3 a P1, el reloj de P1 es sincronizado al reloj de P3. Del mismo modo
se sincroniza el reloj de P2 al reloj de P1 y, por tanto, al reloj de P3 cuando P1 envía m4 a P2.

Los sellos de tiempo que se obtienen usando relojes lógicos tienen la propiedad de que
ts(ei) ⬍ ts(ej) si ei → ej. Sin embargo, lo contrario no está garantizado para eventos que ocurren
en diferentes procesos, es decir, posiblemente ei no precede a ej incluso si ts(ei) ⬍ ts(ej). Esta
situación podrá presentarse si ei y ej ocurren en los procesos X y Y, respectivamente, del sistema,
y si no hubo sincronización directa de los relojes de X y Y, ya sea por falta de tráfico de mensajes
entre ellos o porque el reloj en el proceso Y es más rápido que el reloj en el proceso X (porque
ocurrieron más eventos en el primero que en el segundo). Vemos esta situación en la figura
16.3, donde e32 ocurre “antes del” evento e23, pero tiene un sello de tiempo más grande que el
de e23.

Obtener sellos de tiempo únicos Los eventos que ocurran en diferentes procesos obten-
drán sellos de tiempo idénticos si los relojes lógicos en sus procesos tienen por casualidad valo-
res de tiempo idénticos cuando ocurrieron. Por consiguiente, estos sellos de tiempo no pueden
usarse para obtener el orden total de eventos. Este problema puede superarse usando el siguiente
par como sello de tiempo de un evento ei:

pts(ei) ⬅ (tiempo local, id de proceso)

De esta manera, los eventos no pueden tener sellos de tiempo idénticos. Entonces se realiza el
ordenamiento de eventos, definiendo la precedencia de eventos como sigue:

19 MAQ. CAP. 16(F0694).indd 670 8/10/07 1:19:18 AM


16.3 Precedencias de tiempo, relojes y eventos 671

ei precede a ej si y sólo si i) pts(ei).tiempo local ⬍ pts(ej).tiempo local, o


ii) pts(ei).tiempo local ⫽ pts(ej).tiempo local, y
pts(ei).id de proceso ⬍ pts(ej).id de proceso (16.1)

donde pts(ej).tiempo local y pts(ei).id de proceso son el tiempo local e id de proceso en pts(ei),
respectivamente. Note que esta noción de precedencia de eventos proveerá un ordenamiento
idéntico de los eventos ei y ej al que se obtiene por medio de relojes lógicos si los procesos tuvie-
ran tiempos locales diferentes cuando los eventos ei y ej ocurrieron en ellos.

16.3.3 Relojes vectores

Un reloj vector es un vector que contiene n elementos, donde n es el número de procesos en el


sistema distribuido, VCk es el reloj vector del proceso Pk, y VCk[l] es su l-ésimo elemento. Los
elementos del reloj vector VCk tienen el siguiente significado:

VCk[k] : El reloj lógico del proceso Pk


VCk[l], l ⫽ k : El valor más alto en el reloj lógico del proceso Pl —es
decir, el valor más alto de VCl[l]— que conoce el proceso
Pk.

VCk[k] cambia cuando ocurren eventos en el proceso Pk. Como se describe a continuación, VCk[l]
cambia debido a la sincronización de relojes realizada usando mensajes con sellos de tiempo.
Del mismo modo cambia VCl[k] debido a la sincronización de relojes que se realiza en el proceso
Pl. Por consiguiente, VCk[k] ⱖ VCl[k] para todos los l.
El sello de tiempo para un evento ei que ocurre en un proceso Pk es el valor de VCk cuando
ocurre ei. De este modo, el sello de tiempo es un vector; lo llamamos sello de tiempo vector.
vts(ei) denota el sello de tiempo vector del evento ei y vts(ei)[l] denota el l-ésimo elemento
de vts(ei).
Cuando el proceso Pk envía un mensaje m al proceso Pl, incluye a vts(send(m)) en el men-
saje. Los relojes vectores se implementan usando las siguientes reglas:

R3 : Un proceso Pk incrementa a VCk[k] en 1 cada vez que ocurre en él.


R4 : Cuando el proceso Pk recibe un mensaje m que contiene vts(send(m)),
Pk pone su reloj como sigue:
Para todos los l: VCk[l] ⫽ máx (VCk[l], vts(send(m))[l]).

La precedencia entre los eventos ei y ej se obtiene de la siguiente manera:

• ei precede a ej: Para todos los k: vts(ei)[k] ⱕ vts(ej)[k], pero para algunos l: vts(ei)[l] ⫽
vts(ej)[l].
• ei sigue a ej: Para todos los k: vts(ei)[k] ⱖ vts(ej)[k], pero para algunos l: vts(ei)[l] ⫽
vts(ej)[l].
• ei, ej son concurrentes: Para algunos k, l: vts(ei)[k] ⬍ vts(ej)[k] y vts(ej)[k] y vts(ei)[l] ⬎
vts(ej)[l].

19 MAQ. CAP. 16(F0694).indd 671 8/10/07 1:19:19 AM


672 CAPÍTULO 16 Problemas teóricos en sistemas distribuidos

El sellado de tiempo mediante relojes vectores tiene dos propiedades importantes: cada evento
tiene un sello de tiempo único debido a las reglas R3 y R4, y vts(ei) ⬍ vts(ej) si y sólo si ei → ej.
El siguiente ejemplo ilustra estas propiedades.

Ejemplo 16.3 La figura 16.4 muestra la sincronización de relojes vectores para el sistema de la
figura 16.3. El sello de tiempo vector después de la ocurrencia de un evento se muestra debajo
de él. Cuando se recibe el mensaje m1, C2[2] es incrementado en 1 y C2[1] es actualizado a 10.
Análogamente, cuando el mensaje m2 es recibido por el proceso P3, C3[3] es incrementado en 1 y
C3[1] y C3[2] son actualizados. Los eventos e32 y e23 son concurrentes porque vts(e32) ⱕ vts(e23)
y vts(e32) ⱖ vts(e23).

e11 e12 e13


(10,0,0) (11,4,26) (12,4,26)
P1
m1 e22 m3 m4
(10,4,0)
P2
e21 e23 e24
(10,3,0) m2 (10,5,0) (12,6,26)

P3
e31 e32
(10,4,25) (10,4,26)

Figura 16.4 Sincronización de relojes vectores.

La propiedad de que vts(ei) ⬍ vts(ej) si y sólo si ei → ej implica que relojes vectores no pro-
veen un orden total de eventos. El orden total puede obtenerse usando un par pvts(ei) ⬅ (tiempo
local, id de proceso) y la siguiente relación:

ei precede a ej si y sólo si i) pvts(ei).tiempo local ⬍ pvts(ej).tiempo local, o


ii) ei,ej son eventos concurrentes y
pvts(ei).id de proceso ⬍ pvts(ej).id de proceso (16.2)

donde pvts(ei).tiempo local y pvts(ei).id de proceso son el tiempo de vector local e id de proceso
en pvts(ei), respectivamente.

16.4 REGISTRAR EL ESTADO DE UN SISTEMA DISTRIBUIDO

Como hemos analizado en la sección 16.2.1, el estado global de un sistema distribuido en un


instante de tiempo t es la colección de estados locales de todas las entidades del sistema en el
momento t. No es posible conseguir que todos los nodos registren sus estados en el mismo ins-
tante de tiempo porque los relojes locales no están perfectamente sincronizados. Cualquier otra
colección de estados locales podrá ser inconsistente. Considere el sistema distribuido que se
muestra en la figura 16.5. Supongamos que una aplicación banquera tenga un proceso P1 en el
nodo N1 que deduce 100 dólares de la cuenta A y envía un mensaje al proceso P2 en el nodo N2
para depositar esta cantidad en la cuenta B. Los estados registrados de los nodos N1 y N2 serán
inconsistentes si el saldo en la cuenta A se registra antes de la transferencia y el saldo en la cuenta
B se registra después de la transferencia.

19 MAQ. CAP. 16(F0694).indd 672 8/10/07 1:19:19 AM


16.4 Registrar el estado de un sistema distribuido 673

A B
N1 900 300 N2

Figura 16.5 Un sistema de transferencia de fondos.

En esta sección presentaremos un algoritmo para obtener una colección consistente de es-
tados locales. Una colección de estados de este tipo no es un sustituto para el estado global; sin
embargo, tiene propiedades que pueden usarse para realizar algunas de las funciones de control
en un SO distribuido.

Registros de estados consistentes Un registro de estados es una colección de estados lo-


cales de entidades en un sistema, registrada por medio de un algoritmo. Un registro de estados
consistentes es un registro en el que los estados de procesos para cada par de procesos en el
sistema son consistentes según la definición 16.1.

Definición 16.1 (Estados locales mutuamente consistentes) Los estados locales de los pro-
cesos Pk y Pl son mutuamente consistentes si

1. Cada mensaje registrado como “recibido de Pl” en el estado de Pk se registra como “en-
viado a Pk” en el estado de Pl; y
2. Cada mensaje registrado como “recibido de Pk” en el estado de Pl se registra como “en-
viado a Pl” en el estado de Pk.

El registro de estados que se menciona al principio de esta sección no es consistente porque


el estado de P2 indica que ha recibido un mensaje de P1, pero el estado de P1 no indica que ha
enviado tal mensaje. Un registro de estado que muestre cualesquiera de las siguientes situaciones
será consistente:

1. Las cuentas A y B contienen 900 y 300 dólares, respectivamente.


2. Las cuentas A y B contienen 800 y 400 dólares, respectivamente.
3. Las cuentas A y B contienen 800 y 300 dólares, respectivamente.

La consistencia de los estados locales de los procesos P1 y P2 es obvia en los casos 1 y 2. En


el 3, el mensaje de P1 a P2 está en tránsito. Será entregado al proceso P2 en algún momento futu-
ro, y el proceso P2 sumará 100 dólares a la cuenta B cuando reciba el mensaje. De este modo, la
consistencia mutua de estados de procesos requiere que cada mensaje registrado como recibido
deba registrarse como enviado, ¡pero no al contrario!

16.4.1 Propiedades de un registro de estados consistentes

La figura 16.6 muestra un modelo de una computación distribuida que consiste en 4 procesos
P1-P4 que comunican entre sí a través de mensajes. Una arista (Pi, Pj) representa un canal Chij,

19 MAQ. CAP. 16(F0694).indd 673 8/10/07 1:19:19 AM


674 CAPÍTULO 16 Problemas teóricos en sistemas distribuidos

P1 P4

Ch42
Ch21 Ch43
Ch23
P2 P3
Ch32

Figura 16.6 Una computación distribuida para el registro de estados.

es decir, una ruta de comunicación interproceso que usa el proceso Pi para enviar mensajes al
proceso Pj. Note que un canal es unidireccional; un proceso envía o recibe mensajes a lo largo de
un canal, pero no en ambas direcciones. Los canales Ch23 y Ch32 juntos indican que los procesos
P2 y P3 envían mensajes entre uno y otro.

e11 e12 tP1 e13


P1
m21
e23 tP2 e24 e25
P2
e21 e22 m23
m32
e31 e32 tP3
P3
e33 e34
m43 m42
tP4
P4
e41 e42

Figura 16.7 Un diagrama de tiempos para la computación distribuida de la figura 16.6.

La figura 16.7 muestra el diagrama de tiempos de la computación. Los estados de los cuatro
procesos se registran en los instantes de tiempo tP1, tP2, tP3 y tP4, respectivamente. La tabla 16.2
muestra los estados registrados, donde cada estado indica los mensajes enviados y recibidos por
un proceso. Los estados de P3 y P4 no son mutuamente consistentes porque el proceso P3 registra
el mensaje m43 como recibido, pero el proceso P4 no lo registra como enviado (véase la definición
16.1). Por ende, el registro de estado de la tabla 16.2 no es un registro de estado consistente.

Corte de un sistema Un corte de un sistema describe un registro de estado del sistema en


un diagrama de tiempos. Esto ayuda a razonar las propiedades de un registro de estado. Suponga-
mos que {tPi} sea el conjunto de puntos en un diagrama de tiempos donde se registran los estados
de los procesos {Pi}.

Definición 16.2 (Corte de un sistema) Un corte Ck en el diagrama de tiempos de un sistema


es una curva que conecta puntos del conjunto {tPi} en el orden ascendente de i.

19 MAQ. CAP. 16(F0694).indd 674 8/10/07 1:19:20 AM


16.4 Registrar el estado de un sistema distribuido 675

Tabla 16.2 Estados locales de procesos

Proceso Descripción del estado registrado


P1 No se han enviado mensajes. El mensaje m21
fue recibido.
P2 Se enviaron los mensajes m21 y m23. No se
han recibido mensajes.
P3 No se han enviado mensajes. El mensaje m43
fue recibido.
P4 No se han enviado mensajes. No se han reci-
bido mensajes.

La curva en la figura 16.7 es el corte de la computación distribuida que representa el estado


registrado que se muestra en la tabla 16.2. El término “se toma un corte” significa que se registra
una colección de estados locales. De un evento que ocurrió en un proceso antes de que se registró
el estado del proceso se dice que ocurrió “a la izquierda del corte” en el diagrama de tiempos.
Este evento pertenece al pasado del corte. Un evento que ocurriera en un proceso después de
registrar el estado del proceso sucede “a la derecha del corte” en el diagrama de tiempos. Este
evento pertenece al futuro del corte. Un corte representa un registro de estado consistente de un
sistema si los estados de cada par de procesos cumplen con la definición 16.1.

Estado de un canal El estado de un canal Chij es el conjunto de mensajes contenido en


Chij, es decir, los mensajes enviados por el proceso Pi. Usamos la siguiente notación para deter-
minar el estado de un canal Chij:

Recorded_sentij : el conjunto de mensajes registrados como enviados a


través del canal Chij en el estado de Pi
Recorded_recdij : el conjunto de mensajes registrados como recibidos a
través del canal Chij en el estado de Pj

Recorded_sentij ⫽ Recorded_recdij implica que todos los mensajes enviados por Pi han
sido recibidos por Pj. Por tanto, el canal está vacío. Recorded_sentij ⫺ Recorded_recdij ⫽ ␾
donde “⫺” representa el operador de diferencias del conjunto que implica que algunos men-
sajes enviados por Pi no fueron recibidos por Pj. Estos mensajes todavía están contenidos en
el canal Chij. Recorded_recdij ⫺ Recorded_sentij ⫽ ␾ implica que el proceso Pj ha registrado
como recibido por lo menos un mensaje que no está registrado como enviado por el proceso
Pi. Esta situación indica inconsistencia de los estados locales registrados de Pi y Pj según la
definición 16.1.
Un corte podrá cruzarse con un mensaje mk enviado por el proceso Pi al proceso Pj a través
del canal Chij. A continuación siguen tres de estas posibilidades:

• Sin intersección: Los eventos de envío y recepción de mensajes están ubicados ambos a
la izquierda del corte o ambos a la derecha del corte. En todo caso, el mensaje no existía
en el canal Chij cuando se tomó el corte.

19 MAQ. CAP. 16(F0694).indd 675 8/10/07 1:19:20 AM


676 CAPÍTULO 16 Problemas teóricos en sistemas distribuidos

• Intersección hacia delante: El evento de envío del mensaje está ubicado a la izquierda
del corte y el de recepción está ubicado a la derecha. Por tanto, el mensaje existió en el
canal Chij cuando se tomó el corte.
• Intersección hacia atrás: El evento de envío del mensaje está ubicado a la derecha del
corte y el de recepción está ubicado a la izquierda. Por tanto, el mensaje había sido reci-
bido, pero no había sido enviado cuando se tomó el corte. Este tipo de mensaje representa
una inconsistencia.

Con base en estas observaciones, podemos formular así una condición de consistencia para
un corte:

CC : Un corte C representa un registro de estado consistente de un siste-


ma distribuido si el futuro del corte está cerrado bajo la relación de
precedencia de eventos, es decir, cerrado bajo →.

La condición CC puede explicarse de la siguiente forma: de un conjunto de ítems I se dice


que está cerrado bajo una relación R si el uso de la relación para cualquier ítem en I rinde un
ítem que también está en I. Supongamos que I sea el conjunto de eventos futuros de un corte. La
aplicación de la relación → a un evento ei nos da un evento ej de tal modo que ei → ej, es decir,
que ei precede a ej. Si I está cerrado bajo →, este evento también pertenece a I. Esto quiere de-
cir que no pertenece al pasado del corte. Esta condición es equivalente a la restricción de que un
corte no deberá tener una intersección hacia atrás con un mensaje. Una intersección hacia delante
no viola la condición CC, ya que su evento de envío está en el pasado y su evento de recepción,
en el futuro.

C1 C2 C3
e12 e13
P1

e23
P2
e22
e32
P3
e33 e34

P4
e41

Figura 16.8 Consistencia de cortes: los cortes C1, C2 son consistentes, mientras que C3 es inconsistente.

Ejemplo 16.4 En la figura 16.8, los cortes C1 y C2 son consistentes porque no hay un evento ej que
pertenezca al pasado del corte que sigue a un evento ei en el futuro del corte. El corte C3 es incon-
sistente porque el evento e13 sigue al evento e34 debido a la relación de causa y efecto entre un envío
y una recepción; sin embargo, e34 está en el futuro de C3 mientras que e13 está en el pasado.

19 MAQ. CAP. 16(F0694).indd 676 8/10/07 1:19:21 AM


16.4 Registrar el estado de un sistema distribuido 677

16.4.2 Un algoritmo para el registro


de estados consistentes
Esta sección describe el algoritmo de registro de estados de Chandy y Lamport (1985). El algo-
ritmo parte de las siguientes suposiciones:

1. Los canales son unidireccionales.


2. Los canales tienen capacidades ilimitadas para guardar mensajes.
3. Los canales son FIFO.

La suposición de canales FIFO implica que los mensajes recibidos por un proceso destina-
tario deben ser los primeros enviados por el proceso transmisor, y los mensajes contenidos en un
canal deben ser los últimos enviados por un proceso.
Para iniciar un registro de estados, un proceso registra su propio estado y envía una solicitud
de registro de estado denominado marcador por cada canal saliente. Cuando un proceso recibe
un marcador, registra el estado del canal por el cual recibió el marcador. Si es el primer marcador
que ha recibido, también registra su propio estado y envía un marcador por cada canal saliente.
Usaremos la siguiente notación para discutir cómo se determina el estado de un canal:

Receivedij : el conjunto de mensajes recibidos por el proceso Pj a


través del canal Chij antes de que recibió el marcador
por el canal Chij.
Recorded_recdij : el conjunto de mensajes registrados como recibidos a
través del canal Chij en el estado del proceso Pj.

Algoritmo 16.2 (Algoritmo de Chandy-Lamport para el registro


de estados consistentes)

1. Cuando un proceso Pi inicia el registro de estado: Pi registra su propio estado. Luego


envía un marcador por cada canal saliente conectado a él.
2. Cuando el proceso Pj recibe un marcador a través de un canal entrante Chij: El proceso
Pj realiza las siguientes acciones:
a) Si se trata del primer marcador que Pj ha recibido, entonces
i) Registra su propio estado.
ii) Registra el estado del canal Chij como vacío.
iii) Envía un marcador por cada canal saliente conectado a él.
b) Registra el estado del canal Chij para que contenga los mensajes (Receivedij ⫺ Recor-
ded_recdij).

Supongamos que un proceso Pi envíe los mensajes m1, m2, . . . mn por el canal Chij antes
de registrar su propio estado y de enviar un marcador por Chij. Supongamos que el proceso Pj
tenga dos canales entrantes Chij y Chkj. Si el marcador en el canal Chij es el primero que recibió
Pj, registrará su propio estado que contendrá a Recorded_recdij y Recorded_recdkj. Pj también
registrará el estado de Chij. Debido a que los canales son FIFO, el proceso Pj habrá recibido el

19 MAQ. CAP. 16(F0694).indd 677 8/10/07 1:19:21 AM


678 CAPÍTULO 16 Problemas teóricos en sistemas distribuidos

marcador después de recibir los mensajes m1, m2, . . . mn por el canal Chij, por lo que es correcto
registrar el canal Chij como vacío.
Supongamos que el proceso Pj no reciba ningún mensaje más por el canal Chkj antes de
recibir un marcador por el canal Chkj. El estado del canal Chkj se registrará como Receivedkj ⫺
Recorded_recdkj, es decir, como vacío. Si Pj hubiera recibido dos mensajes mk1 y mk2 más por el
canal Chkj antes de recibir el marcador, Receivedkj ⫽ Recorded_recdkj 艛 {mk1, mk2}. El estado
del canal Chkj se registrará entonces como conteniendo el conjunto de los mensajes Receivedkj
⫺ Recorded_recdkj, es decir, {mk1, mk2}.
El ejemplo 16.5 ilustra la operación del algoritmo de Chandy-Lamport. Observe que las re-
glas del algoritmo son ejecutadas en forma atómica, es decir, como operaciones indivisibles.

m2 m2 m 3
P2 P3 P2 P3 P2 P3
P3 ∆ ∆
m1 m1

∆ ∆
P1 P1 P1
a) b) c)

Figura 16.9 Ejemplo del algoritmo Chandy-Lamport: el sistema en los instantes 0,2⫹ y 5⫹.

Ejemplo 16.5 La figura 16.9a) muestra un sistema distribuido en el momento 0. El proceso P1 en-
vió el mensaje m1 a P3. El mensaje existe actualmente en Ch13. En el instante 1, el proceso P3 envía
el mensaje m2 al proceso P2. En el instante 2, P1 decide registrar el estado del sistema, por lo que
registra su propio estado y envía marcadores por sus canales salientes. La figura 16.9b) muestra la
situación en el instante 2⫹. El mensaje m1 aún está en el canal Ch13 y m2 está en Ch32. Las viñetas
indican marcadores. El símbolo ⌬ indica que el estado de un proceso fue registrado.
El proceso P2 recibe el marcador en Ch12 en el instante 3, registra su propio estado y el estado
de Ch12 como vacío. El proceso P3 envía el mensaje m3 al proceso P2 en el instante 4 y recibe el
marcador por el canal Ch13 en el instante 5. Entonces registra su propio estado, registra el estado de
Ch13 como vacío y envía un marcador por el canal Ch32. La figura 16.9c) muestra la situación en
el instante 5+. Los estados de todos los procesos fueron registrados. Los de los canales Ch12 y Ch13
también lo fueron; sin embargo, el estado del canal Ch32 falta que se registre.
Cuando el marcador en Ch32 llega al proceso P2, P2 registrará el estado de Ch32 de acuerdo
con el paso 2b) del algoritmo 16.2. Se registra como mensajes {m2, m3}, ya que estos mensajes se
encuentran en Received32, pero no en Recorded_recd32. La tabla 16.3 muestra el registro de estados
del sistema.

Propiedades del estado registrado Supongamos que tb y te sean los instantes de tiempo
cuando el registro de estados S empieza y termina. Supongamos también que RS sea el estado
registrado del sistema. Se podrá esperar que el sistema S hubiera estado en el estado RS en algún
instante de tiempo ti, de tal modo que tb ⬍ ti ⬍ te. Sin embargo, ¡esto posiblemente no sea así!
Es decir, el estado registrado RS posiblemente no coincide con algún estado global del sistema.
El ejemplo 16.6 ilustra este hecho.

19 MAQ. CAP. 16(F0694).indd 678 8/10/07 1:19:21 AM


16.4 Registrar el estado de un sistema distribuido 679

Ejemplo 16.6 La figura 16.7 muestra el diagrama de tiempos del sistema distribuido de la figura
16.6. Supongamos que P4 inicie el registro de estado en el instante de tiempo t1. El diagrama de
tiempos de la figura 16.10 muestra cómo los marcadores son enviados y recibidos por procesos
durante el registro de estados. Los marcadores se muestran como flechas punteadas.

Tabla 16.3 Estados registrados de procesos y canales en la figura 16.9

Entidad Descripción del estado registrado


P1 El mensaje m1 fue enviado. Ningún mensaje fue recibido.
P2 Ningún mensaje fue enviado o recibido.
P3 Los mensajes m2 y m3 fueron enviados. El mensaje m1
fue recibido.
Ch12 Vacío.
Ch13 Vacío.
Ch22 Contiene los mensajes {m2, m3}.

e11 e12 e13


P1
m21
e23 e24 e25
P2
e22
m23 m32
e32
P3
e33 e34
m43 m42
P4
e41 e42
t14

Figura 16.10 Registro de estados del sistema de las figuras 16.6 y 16.7.

La tabla 16.4 muestra estados de canales y procesos registrados por medio del algoritmo
de Chandy-Lamport. Sólo el mensaje m21 es registrado como enviado por P2 y recibido por P1.
Ningún otro es registrado como enviado o recibido. Sin embargo, si el diagrama de tiempos de
la figura 16.7 está a escala, queda claro que el sistema nunca existió en un estado en el cual el
mensaje m21 se había enviado y recibido, pero ningún otro mensaje se había enviado. Esto es así
porque los eventos de envío de mensaje y recepción de mensaje e23, e32 y e41 ocurrieron antes
del evento e12, que es el evento de recepción de mensaje para el mensaje m21. De tal modo que
cualquier estado global que registró el mensaje m21 como recibido también habría registrado el
mensaje m43 como enviado y recibido, y el mensaje m23 como enviado.

19 MAQ. CAP. 16(F0694).indd 679 8/10/07 1:19:22 AM


680 CAPÍTULO 16 Problemas teóricos en sistemas distribuidos

Tabla 16.4 Un estado registrado que no coincide con ningún estado global

Entidad* Descripción del estado registrado


P1 Ningún mensaje fue enviado. El mensaje m21 fue recibido.
P2 El mensaje m21 fue enviado. Ningún mensaje fue recibido.
P3 Ningún mensaje fue enviado o recibido.
P4 Ningún mensaje fue enviado o recibido.

* Los estados de todos los canales se registran como vacíos.

Aunque el sistema posiblemente no hubiese existido en el estado registrado en algún instante


del tiempo, el estado registrado es útil para aplicaciones que requieren solamente la consistencia
mutua de estados locales. Considere el problema que implica encontrar el total de fondos en un
sistema bancario. Cuando se transfieren 100 dólares de la cuenta A a la cuenta B, es irrelevante si
el estado registrado muestra esta suma en la cuenta A o en la cuenta B o en el canal que conecta
a las dos, mientras que muestre exactamente una de estas tres posibilidades. El estado registrado
por el algoritmo 16.2 satisface este requerimiento.
Chandy y Lamport (1985) demuestran que el algoritmo 16.2 puede usarse para encontrar
una clase de propiedades denominadas estables. Una propiedad estable es una propiedad que si
se vuelve true en algún instante del tiempo ti, permanece true en todos los instantes del tiempo
> ti. Para detectar una propiedad estable, el algoritmo 16.2 es ejecutado periódicamente a fin de
obtener un registro de estado, y el estado registrado se analiza para detectar la presencia de la
propiedad estable. El algoritmo podrá fallar en la captura de una propiedad estable incluso si se
ejecuta en el instante del tiempo ti+. Sin embargo, esto no es ningún desastre porque la propiedad
se quedará en true y la ejecución posterior del algoritmo lo capturará. Una propiedad estable útil
es la detección de ciclos, nudos o nudos de recursos en un WFG o un RRAG, y puede usarse
para la detección de bloqueos mutuos (véase el capítulo 11). Otra útil propiedad estable es la
terminación de una computación distribuida que se define como una situación en la que todos
los procesos participantes en la computación son pasivos y entre los procesos no hay mensajes
en tránsito (véase la sección 17.6).

EJERCICIO 16
1. En el ejemplo 16.2, el tiempo de P3 es mucho más largo que el tiempo de P1 o P2. Enumere todas las
condiciones bajo las cuales esto puede pasar.
2. Los siguientes eventos ocurren en un sistema que consiste en tres procesos:
proceso P1 proceso P2 proceso P3
evento e1; evento e3; evento e5;
–– –– ––
Envía mensaje a P2; Recibe mensaje de P3; Envía mensaje a P2;

evento e2 ; Recibe mensaje de P1; evento e6 ;


–– Recibe mensaje de P2;
evento e4 ; ––
Envía mensaje a P3; evento e7;

19 MAQ. CAP. 16(F0694).indd 680 8/10/07 1:19:22 AM


Ejercicio 16 681

a) Dibuje un diagrama de tiempos para el sistema.


b) Demuestre las precedencias de eventos en este sistema.
c) Haga una lista de eventos concurrentes.
3. Synch(Pi, Pj, tk) ⫽ true si los relojes lógicos de Pi y Pj son razonablemente consistentes en el instante de
tiempo tk, es decir, si la diferencia entre sus valores es ⬍ ␦, para un valor pequeño ␦. Si RP (i, k) es el
conjunto de procesos de los cuales Pi recibió un mensaje antes de tk y SP(i, k) es el conjunto de procesos
a los cuales Pi envió un mensaje antes de tk, determine si Synch(Pi, Pj, tk) será true en las siguientes
situaciones:
a) RP(i,k) 艚 RP(j,k) ⫽ ␾
b) ᭚Pg 僆 SP(i,k) 像 Pj 僆 SP(g,k)
c) Pj 僆 SP(i,k)
d) Pj 僆 RP(i,k) pero Pj 僆 RP(i,k⫺1)
e) Pj 僆 SP(i,k) y Pi 僆 SP(j,k)
f ) Pj 僆 RP(i,k) pero Pj 僆 RP(i,k⫺1) y Pi no ha recibido ningún mensaje de cualquier proceso después
del instante que envió un mensaje a Pj.
4. La relación 16.1 impone un orden total incluso si los eventos sólo pueden ser parcialmente ordenados
usando relaciones causales. Dé un ejemplo de un sistema que muestre este tipo de eventos. Comente
acerca de las ventajas e inconvenientes de usar la relación 16.1.
5. En lugar de usar la relación 16.2 para obtener un orden total usando sellos de tiempo vectores, se pro-
pone usar la siguiente relación:

ei precede a ej si y sólo si i) pvts(ei).tiempo local < pvts(ej).tiempo local, o


ii) pvts(ei).tiempo local = pvts(ej).tiempo local y
pvts(ei).id de proceso < pvts(ej).id de proceso

Comente acerca de lo correcto de esta propuesta.


6. A y B son usuarios de un sistema operativo distribuido usando relojes lógicos. El usuario A causa el
evento eA y luego llama por teléfono al usuario B. Después de la conversación telefónica, el usuario B
causa el evento eB. Sin embargo, el sello de tiempo de eB es más pequeño que el de eA. Explique por
qué esto puede ser así (adaptado de Lamport [1978]).
7. ti y tj son sellos de tiempo de los eventos ei y ej.
a) Dé un ejemplo de un sistema en el cual ti ⬍ tj cuando se usan relojes lógicos, pero ti ⬍ tj cuando se
usan relojes vectores.
b) Si ti ⬍ tj cuando se usan relojes vectores, demuestre que ti debe ser ⬍ tj cuando se usan relojes
lógicos.
c) Si ti ⬍ tj cuando se usan relojes lógicos, demuestre que ti no puede ser ⬎ tj cuando se usan relojes
vectores.
8. Los sellos de tiempo vectores de los eventos concurrentes ei y ej son tales que vts(ei)[k] ⬍ vts(ei)[k].
Demuestre que los eventos ei y ej son concurrentes si vts(ei)[g] ⫽ vts(ej)[g] para todos los g ⫽ k y
vts(el)[k] ⬎ vts(ej)[k].
9. Explique, por medio de un ejemplo, por qué el algoritmo de Chandy-Lamport requiere canales para ser
FIFO.
10. Un estado sin tránsito de un sistema es un estado en el cual no hay mensajes en tránsito. (Véase la
tabla 16.4 para un ejemplo.) Dé un ejemplo de un sistema en el cual todos los estados registrados por
el algoritmo de Chandy-Lamport son necesariamente estados sin tránsito.

19 MAQ. CAP. 16(F0694).indd 681 8/10/07 1:19:24 AM


682 CAPÍTULO 16 Problemas teóricos en sistemas distribuidos

11. Un sistema consiste en los procesos Pi, Pj y los canales Chij y Chji. Cada proceso envía un mensaje al
otro proceso cada ␦ segundos. El primer mensaje se envía en el instante de tiempo t = 0. Cada mensaje
requiere ␴ segundos para llegar a Pj. Demuestre que si ␦ ⬍ ␴, el registro de estados iniciado por Pi
usando el algoritmo de Chandy-Lamport no puede ser un estado sin tránsito.
12. Dé un ejemplo de un sistema en el cual el estado registrado por el algoritmo de Chandy-Lamport es uno
de los estados en los cuales el sistema existía en algún momento durante la ejecución del algoritmo.
13. ¿Cuál será el registro de estado en el ejemplo 16.6 si la solicitud de registro de estado en el canal Ch42
es retrasada y se entrega al proceso P2 inmediatamente después de que ocurre el evento e23?
14. El algoritmo de Chandy-Lamport funciona correctamente si más de un nodo en un sistema distribuido
inicia en forma espontánea un registro de estado. Describa el funcionamiento del algoritmo si los pro-
cesos P2 y P4 de la figura 16.6 inician el registro de estado a) antes de enviar algún mensaje; b) después
de que se envió un mensaje por cada uno de los canales Ch21, Ch32 y Ch43, y no se ha enviado ningún
otro mensaje.
15. La suposición referente a los canales FIFO puede eliminarse del algoritmo 16.2 de la siguiente manera:
se agrega un campo flag a cada mensaje. Este campo contiene los valores before token o after token,
dependiendo de si el mensaje se envía antes o después de enviar una señal por el mismo canal. Si un
proceso recibe un mensaje con el valor de la bandera after token antes de recibir una señal por el mismo
canal, realiza las mismas acciones que al recibir una señal, e ignora la señal cuando lo reciba posterior-
mente. Formule reglas para registrar el estado de un canal.

BIBLIOGRAFÍA
Lamport (1978) analiza el ordenamiento de eventos en un sistema distribuido y define un orden parcial para
eventos. Mattern (1989), Garg (2002) y Attiya y Welch (2004) estudian los relojes vectores y la consisten-
cia de cortes. Ésta también se analiza en Chandy y Lamport (1985) y en Knapp (1987).
Chandy y Lamport (1985) desarrollaron el problema de la toma instantánea distribuida que se describe
en la sección 16.2 y que requiere canales FIFO. Li, Radhakrishnan y Venkatesh (1987), así como Lai, Yang
(1987) y Mattern (1989) describen algoritmos que no requieren canales para ser FIFO. Lynch (1996) y Tel
(2000) analizan algoritmos para tomas instantáneas globales.

1. Attiya, H. y J. Welch (2004): Distributed Computing: Fundamentals, Simulations and Advanced


Topics, John Wiley, New Jersey.
2. Chandy K.M. y L. Lamport (1985): “Distributed snapshots: Determining global states of distribu-
ted systems”, ACM Transactions on Computer Systems, 3, 1 (febrero de 1985), 63-75.
3. Garg, V.K. (2002): Elements of Distributed Computing, Wiley-IEEE.
4. Knapp, E. (1987): “Distributed deadlock Detection”, Computing Surveys, 19, 4 (diciembre de
1987), 303-328.
5. Lai, T.H. y T.H. Yang (1987): “On distributed snapshots”, Information Processing Letters, 25,
153-158.
6. Lamport L. (1978): “Time, clocks, and the ordering of events in a distributed system”, Communi-
cations of the ACM, 21, 7 (julio de 1978), 558-565.
7. Li, H.F., T. Radhakrishnan y K. Venkatesh (1987): “Global state detection in non-FIFO networks”,
Proceedings of the 7th International Conference on Distributed Computing Systems, 364-370.
8. Lynch, N. (1996): Distributed Algorithms, Morgan Kaufmann.

19 MAQ. CAP. 16(F0694).indd 682 8/10/07 1:19:24 AM


Bibliografía 683

9. Mattern, F. (1989): “Virtual time and global states of distributed systems”, M. Cosnard et al.
(Eds.), Parallel and Distributed Algorithms, Elsevier Science, North Holland.
10. Spezialetti, M. y P. Kearns (1986): “Efficient distributed snapshots”, Proceedings of the 6th Inter-
national Conference on Distributed Computing Systems, 382-388.
11. Tel, G. (2000): Introduction to Distributed Algorithms, 2a. edición, Cambridge University Press,
Cambridge.

19 MAQ. CAP. 16(F0694).indd 683 8/10/07 1:19:24 AM


Capítulo
17
Algoritmos de
control distribuido

Un sistema operativo distribuido realiza varias funciones de control. De éstas, las de exclusión
mutua y manejo de bloqueos mutuos son parecidas a las que se realizan en un SO convencional.
La función de planificación efectúa el equilibrio de carga para asegurar que las cargas compu-
tacionales en todos los nodos del sistema sean comparables. La función de elección elige un pro-
ceso como coordinador entre un grupo de ellos. La función de detección de terminación verifica
si todos los procesos de una computación distribuida, que posiblemente operen en diferentes
nodos del sistema, han completado sus tareas.
A fin de responder rápida y confiablemente a eventos que ocurren en el sistema, un sistema
operativo distribuido realiza una función de control usando un algoritmo de control distribuido,
cuyas acciones se efectúan en varios nodos del sistema distribuido. Estos algoritmos evitan el
uso del estado global de un sistema. En su lugar, dependen de estados locales de diferentes nodos
y usan mensajes interproceso para consultar los estados y tomar decisiones. Su corrección de-
pende del arreglo de estados locales y mensajes interproceso que se usan para llegar a decisiones
correctas y evitar las equivocadas. Estos dos aspectos de la corrección se llaman vivacidad y
seguridad, respectivamente.
Presentaremos algoritmos de control distribuido para las diferentes funciones de control
y analizaremos sus propiedades, tales como carga general e impacto sobre el desempeño del
sistema.

17.1 OPERACIÓN DE ALGORITMOS DE CONTROL DISTRIBUIDO

Un sistema operativo distribuido implementa una función de control por medio de un algoritmo
de control distribuido cuyas acciones se llevan a cabo en varios nodos del sistema y sus datos
también están extendidos a través de varios nodos. Este enfoque tiene las siguientes ventajas
sobre la implementación centralizada de funciones de control:

• Se evitan los retrasos y la carga general involucrados en la recolección del estado global
de un sistema.

20 MAQ. CAP. 17(F0694).indd 684 8/10/07 1:22:43 AM


17.1 Operación de algoritmos de control distribuido 685

• La función de control es capaz de responder rápidamente a eventos en diferentes nodos


del sistema.
• La falla de un nodo individual no paraliza las funciones de control.

Tabla 17.1 Visión general de funciones de control en un SO distribuido

Función Descripción
Exclusión mutua Implementa una sección crítica (SC) para un ítem de dato ds a fin de usar pro-
cesos en un sistema distribuido. Involucra la sincronización de procesos que
operan en diferentes nodos del sistema, por lo que se encuentra un máximo de
un proceso en una SC para ds en un momento dado.
Manejo de bloqueos Impide o detecta bloqueos mutuos que surgen debido a la compartición de
mutuos recursos dentro y a través de nodos de un sistema distribuido.
Planificación Realiza el equilibrio de carga para asegurar que las cargas computacionales
en diferentes nodos de un sistema distribuido sean comparables. Involucra la
transferencia de procesos de nodos muy cargados a nodos de carga ligera.
Detección de Los procesos de una computación distribuida podrán operar en varios nodos
terminación de un sistema distribuido. La detección de terminación es el acto de deter-
minar si una de estas computaciones ya completó su operación. Involucra la
verificación si algún proceso de la computación está activo o si algún mensaje
interproceso está en tránsito entre procesos de la computación.
Elección Un coordinador (también llamado proceso líder) es el que realiza una función
privilegiada, por ejemplo, la asignación de recursos. Una elección se lleva a
cabo cuando un coordinador falla o ha terminado. Selecciona un proceso para
que sea el nuevo coordinador y notifica a todos los demás la identidad del
nuevo coordinador.

Un algoritmo de control distribuido provee un servicio entre cuyos clientes se encuentran


tanto aplicaciones de usuarios como el kernel. La tabla 17.1 describe las funciones de control en
un SO distribuido. La exclusión mutua y la elección son servicios que se proporcionan a procesos
usuarios; el manejo de bloqueos mutuos y la planificación se ofrecen al kernel, mientras que el
servicio de detección de terminación puede ser usado tanto por procesos usuarios como por
el kernel. En la literatura sobre los SO, a los nombres de estas funciones por lo general se agre-
ga el término “distribuido” para indicar que se realizan en forma distribuida. Observe que la tole-
rancia de fallas y los temas de recuperación no se estudiarán aquí; se analizarán en el capítulo 18.
Un algoritmo de control distribuido opera en paralelo con sus clientes, por lo que puede
responder fácilmente a eventos relacionados con su servicio. Se usa la siguiente terminología
para distinguir entre las acciones de un cliente y las de un algoritmo de control.

• Computación básica: La operación de un cliente constituye una computación básica.


Ésta podrá involucrar procesos en uno o varios nodos del sistema. Los mensajes que
intercambian tales procesos se denominan mensajes básicos.
• Computación de control: La operación de un algoritmo de control constituye una compu-
tación de control. Los mensajes intercambiados por procesos de una computación de
control se llaman mensajes de control.

20 MAQ. CAP. 17(F0694).indd 685 8/10/07 1:22:44 AM


686 CAPÍTULO 17 Algoritmos de control distribuido

Llamadas al kernel

Parte de Mensajes
cpi control de control
Proceso Solicitud Respuesta
Pi
bpi Parte básica Mensajes
básicos

Llamadas al kernel

Figura 17.1 Partes básicas y de control de un proceso Pi.

A fin de entender la operación de un algoritmo de control distribuido, nos imaginamos


que cada proceso consiste en dos partes que operan en paralelo: una básica y una de control. La
figura 17.1 ilustra las dos partes de un proceso Pi. La parte básica de un proceso participa en una
computación básica. Esta parte intercambia mensajes básicos con partes básicas de otros proce-
sos. Cuando requiere un servicio que ofrece un algoritmo de control, hace una solicitud a la parte
de control del proceso. Todas las demás solicitudes se hacen directamente al kernel. La parte de
control de un proceso participa en una computación de control. Esta parte intercambia mensajes
de control con partes de control de otros procesos y podrá interactuar con el kernel para imple-
mentar su parte en la función de control. La parte básica de un proceso podrá bloquearse debido
a una solicitud de recurso; en cambio, la parte de control nunca se bloquea; esta característica la
habilita para responder en forma oportuna a eventos relacionados con su servicio.

Ejemplo 17.1 Una aplicación distribuida consiste en cuatro procesos P1-P4. Supongamos que el
proceso P2 se encuentre actualmente en una SC para los datos compartidos ds. Cuando el proceso
P1 quiere entrar en una SC para ds, bp1 hace una solicitud a cp1, que forma parte de uno de los
algoritmos de exclusión mutua distribuida que analizaremos más adelante, en la sección 17.3. Para
decidir si se puede permitir que P1 entre en una SC para ds, cp1 intercambia mensajes con cp2, cp3
y cp4. Por sus respuestas se da cuenta de que algún otro proceso se encuentra actualmente en una
SC para ds, por lo que hace una llamada al kernel para bloquear bp1. Observe que cp2 participa en
esta decisión incluso mientras bp2 estuvo ejecutando en una SC. Cuando el proceso P2 quiere salir
de la SC, bp2 hace una solicitud a cp2, que interactúa con las partes de control de otros procesos
y decide que el proceso P1 puede entrar en una SC para ds. De manera correspondiente, cp1 hace
una llamada al kernel para activar a bp1.

17.2 CORRECCIÓN DE ALGORITMOS DE CONTROL DISTRIBUIDO

Los procesos de un algoritmo de control distribuido intercambian datos de control y coordinan


sus acciones por medio de mensajes de control. Sin embargo, la comunicación por mensajes pro-
voca retrasos, por lo que los datos que usa el algoritmo pueden volverse viejos e inconsistentes,

20 MAQ. CAP. 17(F0694).indd 686 8/10/07 1:22:44 AM


17.2 Corrección de algoritmos de control distribuido 687

y el algoritmo puede errar en la ejecución de acciones correctas o realizar las acciones equivoca-
das. Así, la corrección de un algoritmo de control distribuido tiene dos facetas:

• Vivacidad: La vivacidad implica que un algoritmo a final de cuentas realizará acciones


correctas, es decir, las efectuará sin retrasos indefinidos.
• Seguridad: La seguridad implica que el algoritmo no realiza acciones equivocadas.
La falta de vivacidad implica que un algoritmo dejará de realizar acciones correctas. Por
ejemplo, un algoritmo de exclusión mutua distribuida podrá dejar de satisfacer las propiedades
de progreso y espera acotada de la sección 9.2.1, o un algoritmo de detección de bloqueos mu-
tuos podrá ser incapaz de detectar un bloqueo mutuo que existe en el sistema. Note que el perio-
do de tiempo que se necesita para realizar una acción correcta es irrelevante para la propiedad de
vivacidad; a final de cuentas la acción se tendrá que realizar. La falta de seguridad implica que
un algoritmo podrá realizar acciones equivocadas, por ejemplo, permitir que más de un proceso
estén dentro de la SC al mismo tiempo. La tabla 17.2 resume las propiedades de vivacidad y
seguridad de algunos algoritmos de control distribuido.

Tabla 17.2 Vivacidad y seguridad de algoritmos de control distribuido

Algoritmo Vivacidad Seguridad


Exclusión mutua 1. Si una SC está libre y unos Un máximo de un proceso estará
procesos han solicitado entrar en una SC al mismo tiempo.
en ella, uno de ellos entrará en
ella en tiempo finito.
2. Un proceso que solicita entrar
en una SC entrará en ella en
tiempo finito.
Manejo de bloqueos Si se presenta un bloqueo mutuo, No se declarará un bloqueo sino
mutuos será detectado en tiempo finito. hasta que haya ocurrido.
Detección de La terminación de una compu- No se declarará una terminación
terminación tación distribuida será detectada sino hasta que haya ocurrido.
dentro de un tiempo finito.
Elección Un nuevo coordinador será ele- Se elegirá exactamente un proce-
gido en un tiempo finito. so como coordinador.

Suponiendo un conjunto de acciones distintas en un algoritmo de control distribuido y un


conjunto de condiciones distintas en él, podemos especificar un algoritmo de control distribui-
do como un conjunto de reglas de la forma <condición> : <acción>, donde <acción> es una ac-
ción que el algoritmo deberá realizar si y sólo si <condición> es verdadera. Si se usa la notación
→ para las palabras “finalmente conduce a”, la implicación de definir vivacidad y seguridad de
esta manera es que

• Vivacidad: Para todas las reglas, <condición> → <acción>, es decir, <acción> será final-
mente realizada si <condición> es válido.

20 MAQ. CAP. 17(F0694).indd 687 8/10/07 1:22:45 AM


688 CAPÍTULO 17 Algoritmos de control distribuido

• Falta de seguridad: Para una regla, ¬ <condición> → <acción>, es decir, <acción> se


podrá llevar a cabo a final de cuentas aunque <condición> no es válido.

Demostrar la corrección de un algoritmo distribuido es una tarea compleja. Deberán especi-


ficarse <condición> y <acción> para representar el algoritmo correctamente, y deben usarse téc-
nicas formales para demostrar que un algoritmo posee las propiedades de vivacidad y seguridad.
Los fundamentos teóricos necesarios para la demostración formal de algoritmos distribuidos no
existían antes de los principios de los noventa. Ésta es la razón por la cual muchos algoritmos
que fueron desarrollados anteriormente contienen errores.
Deberá notarse que la vivacidad y seguridad sólo se preocupan de la corrección de un algo-
ritmo. Otras propiedades deseables de un algoritmo, por ejemplo, el servicio FCFS en algoritmos
de exclusión mutua distribuida, deben declararse y comprobarse por separado.

17.3 EXCLUSIÓN MUTUA DISTRIBUIDA

17.3.1 Un algoritmo basado en el permiso


El algoritmo de Ricart y Agrawala (1981) concede la entrada en una sección crítica en el
orden FCFS. El algoritmo es completamente distribuido en el sentido de que todos los procesos
participan de igual modo en la decisión de qué proceso deberá ser el próximo en entrar en una
SC. Un proceso que desea entrar en una SC envía mensajes de solicitud con sello de tiempo a
todos los demás procesos y espera hasta que recibe una respuesta de “adelante” de parte de cada
uno de ellos. Si el sistema contiene n procesos, tienen que intercambiarse 2 ⫻ (n ⫺ 1) mensajes
antes de que un proceso pueda entrar en la sección crítica. La seguridad de la exclusión mutua se
deduce del hecho de que a lo mucho un proceso podrá obtener (n ⫺ 1) respuestas en un momento
dado. La entrada a la SC se concede en el orden FCFS; por tanto, cada proceso logra el acceso
en tiempo finito. Esta característica cumple con la propiedad de vivacidad.

Algoritmo 17.1 (Algoritmo de Ricart-Agrawala para la exclusión mutua)


1. Cuando un proceso quiere entrar en una SC: El proceso envía un mensaje de solicitud
con sello de tiempo a todos los demás procesos en el sistema y es bloqueado.
2. Cuando un proceso Pi recibe un mensaje de solicitud de otro proceso:
a) Si Pi no está interesado en usar una SC, inmediatamente envía una respuesta de “ade-
lante” al proceso solicitante.
b) Si Pi desea entrar en una SC, envía una respuesta de “adelante” al proceso solicitante
si el sello de tiempo en la solicitud recibida es menor que el de su propia solicitud; de
lo contrario, agrega la solicitud a la lista de pendientes.
c) Si Pi ya está en una SC, simplemente añade la solicitud a la lista de pendientes.
3. Cuando un proceso recibe n ⫺ 1 respuestas de “adelante”: El proceso se activa y entra
en una SC.
4. Cuando un proceso sale de una SC: El proceso envía una respuesta de “adelante” a cada
proceso en su lista de pendientes.
La tabla 17.3 muestra cómo se implementan los pasos del algoritmo 17.1 en la parte de con-
trol de un proceso. La primera columna presenta los pasos en la computación básica realizada
por un proceso. Consiste en un bucle en el cual el proceso solicita la entrada en una SC, realiza

20 MAQ. CAP. 17(F0694).indd 688 8/10/07 1:22:45 AM


17.3 Exclusión mutua distribuida 689

Tabla 17.3 Acciones básicas y de control en un algoritmo de exclusión mutua completamente distribuida

Acciones de la parte de control


Acciones de la parte básica Pasos Detalles
repetir para siempre i) Enviar (solicitud, sello de tiempo) a todos los
demás procesos y solicitar que el kernel blo-
quee la parte básica.
ii) Cuando se recibe una solicitud proveniente
de otro proceso, enviar una respuesta de “ade-
{ Solicitar entrada a SC } 1, 2b), 3 lante” si la solicitud tiene un sello de tiempo
menor; de lo contrario, agregar la solicitud a la
lista de pendientes.
iii) Contar las respuestas de “adelante” recibidas.
Activar la parte básica del proceso tras haber
recibido (n ⫺ 1) respuestas.
{ Sección crítica } 2c) Registrar todas las solicitudes recibidas en la lista
de pendientes.
{ Realizar salida de SC } 4 Enviar una respuesta de “adelante” a cada solicitud
en la lista de pendientes.
{ Resto del ciclo } 2a) Cuando se recibe una solicitud, enviar una respues-
ta de “adelante” inmediatamente.
fin

algo de procesamiento dentro de la SC y sale de ella. La otra columna muestra las acciones de la
parte de control del algoritmo.
El número de mensajes necesarios para entrada en una SC puede reducirse cuando se soli-
cita que un proceso Pi obtenga permisos de un subconjunto Ri de procesos en un sistema. Ri se
denomina el conjunto de solicitud de Pi. Deberá garantizarse la seguridad mediante la formación
cuidadosa de los conjuntos
√ de solicitudes. El algoritmo de Maekawa [1985] usa conjuntos de
solicitudes del tamaño 苵n y emplea las siguientes reglas para garantizar la seguridad (véase el
problema 4 del ejercicio 17):
1. Para todos los Pi : Pi 僆 Ri.
2. Para todos los Pi, Pj : Ri 艚 Rj ⫽ ␾.

17.3.2 Algoritmos basados en privilegio o paso de símbolos (token)


para la exclusión mutua
Un token representa el privilegio para usar una SC; sólo un proceso que posee el token puede
entrar en la SC. La seguridad de un algoritmo basado en tokens se deduce de esta regla. Cuando
un proceso hace una solicitud para entrar en una SC, el algoritmo de exclusión mutua asegura
que la solicitud llegue al proceso que está procesando al token, y que éste sea finalmente transfe-
rido al proceso que lo solicita. Esta característica asegura la vivacidad. La complejidad lógica y
el costo de un algoritmo de exclusión mutua depende de las propiedades del modelo del sistema.

20 MAQ. CAP. 17(F0694).indd 689 8/10/07 1:22:45 AM


690 CAPÍTULO 17 Algoritmos de control distribuido

Por ende, los algoritmos basados en tokens usan modelos de sistema abstractos en los cuales
los bordes representan las rutas que se usan para pasar mensajes de control, y la gráfica forma-
da por los nodos y estos bordes tiene ciertas propiedades agradables. Analizaremos dos algorit-
mos que usan las topologías abstractas de anillo y árbol.

Un algoritmo que emplea la topología anular La figura 17.2 muestra el modelo lógico de
una computación distribuida y su modelo anular abstracto y unidireccional. El token es un obje-
to, es decir, una estructura de datos, que contiene una cola de solicitudes. En la figura 17.2b), el
token se encuentra en ese momento junto con el proceso P4, que está en una SC, y la cola de soli-
citudes en el token contiene a P2 y P5. El algoritmo funciona de la siguiente manera: un proceso
que quiere entrar en una SC envía un mensaje que contiene su solicitud y es bloqueado. El men-
saje se encamina a lo largo del anillo hasta que llegue al dueño del token. Si el dueño del token
se encuentra actualmente en una SC, el algoritmo de control ingresa la id del solicitante en la cola
de solicitudes que contiene el token. Cuando el dueño del token termina de usar la SC, elimina
la primera id de proceso de la cola de solicitudes en el token y envía un mensaje que contiene el
token y la id del proceso. Este mensaje es encaminado a lo largo del anillo hasta que llegue al pro-
ceso cuya id coincide con la del proceso en el mensaje. La parte de control de este proceso extrae
y retiene el token para su uso futuro, y su parte básica se activa y entra en una SC. En la figura
17.2b), el proceso P2 recibirá el token cuando P4 sale de su SC. El algoritmo se muestra como
algoritmo 17.2 El número de mensajes intercambiados por entrada en una SC es O(n).

P2 P3
P2 P3
P2
P1 P4 P1 P4
P5
P6 P5 token
P6 P5
a) b)
Figura 17.2 a) Modelo de sistema, y b) modelo de sistema abstracto.

Algoritmo 17.2 (Algoritmo basado en paso de token para una topología anular)
1. Cuando un proceso Pi desea entrar en una SC: El proceso envía un mensaje de solicitud
(“solicitud”, Pi) a lo largo de su borde saliente y se bloquea.
2. Cuando un proceso Pi recibe un mensaje de solicitud del proceso Pr: Si Pi no procesa el
token, remite el mensaje a lo largo de su borde saliente. Si Pi posee el token y no se encuen-
tra actualmente en una SC, forma el mensaje (“token”, Pr) y lo envía a lo largo de su borde
saliente. Si Pi está en un SC, solamente entra Pr en la cola de solicitudes en el token.
3. Cuando un proceso Pi completa la ejecución de una SC: Verifica si la cola de solicitudes
está vacía. De no ser así, elimina la primera id de proceso de la cola. Supongamos que esta
id sea Pr. Entonces forma un mensaje (“token”, Pr) y lo envía a lo largo de su borde
saliente.
4. Cuando un proceso Pi recibe el mensaje (“token”, Pj): Pi verifica si Pi ⫽ Pj. En caso
afirmativo, crea una estructura de datos local para almacenar el token, se activa y entra
en su SC.

20 MAQ. CAP. 17(F0694).indd 690 8/10/07 1:22:45 AM


17.3 Exclusión mutua distribuida 691

Si Pi ≠ Pj, solamente reenvía el mensaje a lo largo de su borde saliente.

Algoritmo de Raymond El algoritmo de Raymond usa un árbol abstracto invertido como


modelo de sistema. El árbol invertido se distingue de un árbol convencional porque un borde
del árbol de un nodo apunta hacia su padre en el árbol. Pholder designa el proceso en pose-
sión del token. Las características clave del algoritmo de Raymond son: invariantes que aseguran
que una solicitud llegue a Pholder, una cola de solicitantes en cada nodo, herramientas para reducir
el número de mensajes de solicitud y previsiones para asegurar la vivacidad.

P2 P4 Pholder P5

P1 P3
P1 P6

P3 P5 P6 P2 P4
a) b)

Figura 17.3 a) Modelo de sistema, y b) modelo de sistema abstracto.

La figura 17.3 representa el modelo de una computación distribuida y su modelo de árbol in-
vertido abstracto. El proceso P5 sostiene el token, por lo que se encuentra en la raíz del árbol. Los
procesos P1 y P3, que son sus hijos, tienen bordes salientes que apuntan hacia P5. Del mismo
modo, los bordes salientes (P6, P1), (P2, P3) y (P4, P3) apuntan desde un proceso hacia su padre.
El algoritmo mantiene tres invariantes con respecto al árbol abstracto invertido:

1. El proceso Pholder es la raíz del árbol.


2. Cada proceso en el sistema pertenece al árbol.
3. Cada proceso Pi ⫽ Pholder tiene exactamente un borde saliente (Pi, Pj) donde Pj es su
padre en el árbol.

Estas invariantes aseguran que el modelo de sistema abstracto contenga una ruta desde cada
proceso Pi ⫽ Pholder a Pholder. Esta propiedad es útil para asegurar que una solicitud hecha por
Pi llegue a Pholder. Se mantienen estas invariantes por bordes cambiantes en el árbol invertido
abstracto cuando un proceso Pk, Pk ⫽ Pholder envía el token a otro proceso, digamos al proceso
Pj: se borra el borde (Pj, Pk) y se agrega el borde (Pk , Pj). Estas acciones efectivamente invierten
la dirección de los bordes del árbol junto con el token que envió y establecen una ruta desde el
dueño anterior del token al nuevo dueño. Por ejemplo, el borde (P3, P5) en la figura 17.3b) se
invertirá cuando P5 envíe el token a P3.
Cada proceso mantiene una cola de espera local de solicitantes. Un mensaje de solicitud
contiene un solo campo requester_id. Un proceso que quiere entrar en una SC pone su propia id
en su cola local y también envía un mensaje de solicitud a lo largo de su borde saliente. Cuando
un proceso Pi recibe un mensaje de solicitud, ingresa la id del proceso solicitante en su cola local.
Entonces forma un mensaje de solicitud en el cual pone su propia id, es decir, Pi, y lo envía a lo
largo de su borde saliente. De este modo, la solicitud llega a Pholder a lo largo de una ruta asegu-

20 MAQ. CAP. 17(F0694).indd 691 8/10/07 1:22:46 AM


692 CAPÍTULO 17 Algoritmos de control distribuido

rada por la invariante 3; sin embargo, la id del solicitante es diferente en cada borde de la ruta.
Para reducir el número de mensajes de solicitud, un proceso no crea o envía una solicitud si una
solicitud enviada por él con anterioridad aún no ha sido cumplida.
Pholder ingresa todas las solicitudes que recibe en su cola local. Cuando sale de la SC elimina
la primera id de proceso de su cola local y envía el token a este proceso. El proceso que recibe el
token lo envía al primer proceso en su cola, a menos que el token sea para él mismo. Esta acción
se repite hasta que el token llegue a un proceso que se encuentra en la cabecera de su propia
cola. La parte de control de este proceso se queda con el token. Su parte básica se activa y entra
en una SC.
La vivacidad requiere que cada proceso que solicita la entrada en una SC pueda entrar en
ella en tiempo finito. Para asegurar esta propiedad, un proceso que transfiere el token a otro
proceso verifica si la cola local está vacía. Si todavía contiene solicitudes, forma una nueva
solicitud con su propia id en el campo requester_id y la envía al proceso al que había enviado
el token. Esta acción asegura que recibirá el token en algún momento futuro para dar servicio a
otras solicitudes en su cola local.

Algoritmo 17.3 (Algoritmo de Raymond para la exclusión mutua)

1. Cuando un proceso Pi quiere entrar en una SC: El proceso Pi ingresa su propia id en su


cola local. También envía un mensaje de solicitud que contiene su propia id a lo largo de
sus borde salientes si no ha enviado un mensaje anteriormente o si su última solicitud ya
fue cumplida.
2. Cuando un proceso Pi recibe un mensaje de solicitud de otro proceso: El proceso Pi rea-
liza las siguientes acciones:
a) Pone la id del solicitante en su cola local.
b) Si Pi ⫽ Pholder, envía un mensaje de solicitud que contiene su propia id a lo largo de
su borde saliente si no ha enviado un mensaje de solicitud con anterioridad o si su
última solicitud ya fue cumplida.
3. Cuando un proceso Pi completa la ejecución de una SC: Pi realiza las siguientes ac-
ciones:
a) Elimina la id de proceso en la cabecera de la cola local. Supongamos que sea Pj.
b) Envía el token a Pj.
c) Invierte el borde del árbol (Pj, Pi).
d) Si la cola local no está vacía, envía un mensaje de solicitud que contiene su propia id
a Pj.
4. Cuando un proceso recibe el token:
a) Si su propia solicitud se encuentra en la cabecera de la cola local, elimina la solicitud
de la cola. Entonces su parte básica se activa y entra en una SC.
b) Si su propia solicitud no está en la cabecera de la cola local, realiza los pasos 3a) a
3d).

El algoritmo requiere un orden de log n mensajes por cada solicitud. No asegura la entra-
da FIFO a una sección crítica (véase el paso 2b)). El ejemplo 17.2 ilustra la operación de este
algoritmo.

20 MAQ. CAP. 17(F0694).indd 692 8/10/07 1:22:46 AM


17.4 Manejo del bloqueo mutuo distribuido 693

Ejemplo 17.2 La figura 17.4a) muestra la situación en el sistema de la figura 17.3 después de
que las solicitudes hechas por P4 y P1 han llegado a P5, que es el Pholder (véase los pasos 1 y 2
del algoritmo 17.3). Cuando el proceso P5 sale de su SC, elimina a P3 de su cola local, pasa el token
a P3 e invierte el borde (P3, P5). P5 envía entonces una solicitud a P3, ya que su cola local no está
vacía (véase el paso 3d)). P3 realiza acciones parecidas (véase el paso 4), que dan como resultado
el envío del token al proceso P4, inversión de los bordes (P4, P3) y el envío de una solicitud P3
a P4.
La figura 17.4b) muestra el resultante árbol abstracto invertido. Ahora P4 entra en su SC.
Después de que P4 completa la SC, el token se transfiere al proceso P1 vía P3 y P5 de manera aná-
loga, lo que habilita a P1 para entrar en su SC. Observe que esto no hubiera sido posible si el paso
3d) no existiera en el algoritmo.

p3 p1 p5 p1 p5

p1 p1 p3 p4 p1 p1 p3 p5

p4 p3
p6 p2 p4 p6 p2 p4
a) b)

Figura 17.4 Un ejemplo del algoritmo de Raymond.

17.4 MANEJO DEL BLOQUEO MUTUO DISTRIBUIDO

Los planeamientos para la detección, prevención y evasión de bloqueos mutuos que se analiza-
ron en la sección 11.3 usan informaciones sobre los estados. Esta sección ilustrará los problemas
que implica extender estos planteamientos a un sistema distribuido, y luego describirá los plan-
teamientos de detección de bloqueos mutuos y prevención de bloqueos mutuos distribuidos. En
la literatura sobre sistemas operativos, no se ha analizado ninguna técnica especial para evitar
bloqueos mutuos distribuidos. Por motivos de sencillez, en esta sección se limita la discusión
al modelo “una sola instancia/una sola solicitud” (SISR) de asignación de recursos (véase la
sección 11.3). Por tanto, cada clase de recursos contiene sólo una instancia de recursos y cada
solicitud se hace para una sola instancia de una clase de recursos.

17.4.1 Problemas en la detección de bloqueos mutuos centralizados

Las aplicaciones distribuidas pueden usar recursos que se ubican en varios nodos del sistema.
Los bloqueos mutuos que involucran estas aplicaciones podrán detectarse recabando las gráficas
de espera (WFG) de todos los nodos en un nodo central, superponiéndolas para formar una WFG
fusionada y empleando un algoritmo de detección de bloqueos mutuos convencional para buscar
bloqueos mutuos. Sin embargo, este método tiene un punto débil. Podrá obtener WFG de nodos
individuales en diferentes instantes de tiempo, por lo que la WFG fusionada podrá representar
una visión engañosa de relaciones de espera en el sistema. Esto podrá llevar a la detección de
bloqueos mutuos fantasmas, que es una violación de la propiedad de seguridad en la detección
de bloqueos mutuos. El ejemplo 17.3 ilustra una de estas situaciones.

20 MAQ. CAP. 17(F0694).indd 693 8/10/07 1:22:46 AM


694 CAPÍTULO 17 Algoritmos de control distribuido

P4 P4 P4 P4 P4
r5 r5 r6 r5 r6

P5 r4 P6 P5 P6 P5 P6 P5 P6 P5 r4 P6
Nodo N3 Nodo N4 Nodo N3 Nodo N4
Las WFG en el paso 6 Las WFG en el paso 9 WFG fusionada
a) b) c)

Figura 17.5 Bloqueo mutuo fantasma en el ejemplo 17.3: WFG de nodos en los pasos 6, 9 y la WFG fusionada.

Ejemplo 17.3 La secuencia de eventos en un sistema que contiene tres procesos P4, P5 y P6 es la
siguiente:
1. El proceso P5 solicita y obtiene el recurso r5 en el nodo N3.
2. El proceso P6 solicita y obtiene el recurso r4 en el nodo N3.
3. El proceso P5 solicita y obtiene el recurso r6 en el nodo N4.
4. El proceso P4 solicita el recurso r5 en el nodo N3.
5. El proceso P5 solicita el recurso r4 en el nodo N3.
6. El nodo N3 envía su WFG local al nodo coordinador.
7. El proceso P6 libera el recurso r4 en el nodo N3.
8. El proceso P6 solicita y obtiene el recurso r6 en el nodo N4.
9. El nodo N4 envía su WFG local al nodo coordinador.
Las figuras 17.5a) y b) muestran WFG de los nodos en los pasos 6 y 9, respectivamente. Puede
verse que ningún bloqueo mutuo existe en el sistema en cualesquiera de estos momentos. Sin em-
bargo, la WFG fusionada se construye mediante la superposición de la WFG del nodo N3 tomada en
el paso 6 y la WFG del nodo que usa el N4 tomada en el paso 9 (véase la figura 17.5c)), por lo que
contiene un ciclo {P5, P6} y el coordinador detecta un bloqueo mutuo fantasma.

17.4.2 Detección de bloqueos mutuos distribuidos


En el planteamiento de detección de bloqueos mutuos, cada nodo en el sistema tiene la capacidad
de detectar un bloqueo mutuo. Analizaremos dos de estos algoritmos.

Detección de bloqueos mutuos basada en la computación por difusión La computación


por difusión es una computación de control distribuido que tiene las propiedades de vivacidad
y seguridad. (Dijkstra y Scholten, que la propusieron en 1980, la denominaron computación
difusora.) La computación por difusión incluye dos fases: una de difusión y otra de colección de
información. En la primera, la computación procede de un nodo y se difunde a otros por medio
de mensajes de control denominados consultas, que se envían a lo largo de todos los bordes en el
sistema. Un nodo podrá recibir más de una consulta si tiene muchos bordes entrantes. La primera
consulta recibida por un nodo se llama consulta demandante, mientras que las que se reciben
más tarde se denominan consultas no demandantes. Cuando un nodo recibe una consulta deman-
dante, envía consultas a lo largo de todos sus bordes salientes. Si recibe posteriormente una
consulta no demandante, no envía ninguna consulta porque ya las habrá enviado cuando recibió
la consulta demandante. En la fase de colección de información, cada nodo en el sistema envía
una respuesta a cada consulta recibida por él. La respuesta a una consulta demandante contiene

20 MAQ. CAP. 17(F0694).indd 694 8/10/07 1:22:46 AM


17.4 Manejo del bloqueo mutuo distribuido 695

informaciones correspondientes al nodo al que estaba dirigida la consulta demandante y acerca


de otros nodos conectados a este nodo. La respuesta a una consulta no demandante normalmente
no contiene información. Se llama respuesta ficticia.
El algoritmo 17.4 usa una computación por difusión para llevar a cabo la detección de blo-
queos mutuos. La computación por difusión se difunde a través de bordes en la WFG. Todos los
pasos en el algoritmo se ejecutan en forma atómica. Si un proceso recibe entonces dos mensajes
al mismo tiempo, se procesarán uno después del otro. Se supone que se asignan id distintas a
computaciones por difusión iniciadas por diferentes procesos, y que sus consultas y respuestas
portan estas id. De esta forma las diferentes computaciones por difusión no interfieren una con
la otra.

Algoritmo 17.4 (Detección de bloqueos mutuos distribuidos basada


en la computación por difusión)

1. Cuando un proceso es bloqueado en una solicitud de recursos: El proceso inicia una


computación por difusión por medio de las siguientes acciones:
a) Enviar consultas a lo largo de todos sus bordes salientes en la WFG.
b) Recordar el número de consultas enviadas, esperar las respuestas a ellas.
c) Si se recibe una respuesta a cada una de las consultas enviadas y si ha estado en el
estado bloqueado de manera continua desde que inició la computación por difusión,
declarar un bloqueo mutuo.
2. Cuando un proceso recibe una consulta demandante: Si el proceso está bloqueado, rea-
liza las siguientes acciones:
a) Enviar consultas a lo largo de todos sus bordes salientes en la WFG.
b) Recordar el número de consultas enviadas, esperar las respuestas a ellas.
c) Si se recibe una respuesta a cada una de sus consultas y si ha estado en el estado
bloqueado de manera continua desde que recibió la consulta demandante, enviar una
respuesta al nodo del que había recibido la consulta demandante.
3. Cuando un proceso recibe una consulta no demandante: Si el proceso estuvo en estado
bloqueado en forma continua desde que recibió la consulta demandante, enviar una res-
puesta al nodo del que había recibido la consulta no demandante.

Considere un sistema SISR que contiene cuatro procesos P1... P4. La WFG de la figura
17.6a) muestra el estado del sistema después de que el proceso P1 solicitó un recurso que en ese
momento está asignado a P2. P1, P2 y P3 están entonces en estado bloqueado, mientras que P4 no
lo está. P1 inicia la computación por difusión cuando se bloquea. Cuando P2 recibe su consulta,
envía una consulta a P3, que envía una consulta a P4. Sin embargo, P4 no está en estado bloquea-
do, por lo que no responde a la consulta de P3. Por ende, P1 no recibe respuesta y no declara que
se encuentra en un bloqueo mutuo. Supongamos que P4 ahora solicite el recurso asignado a P2 y
sea bloqueado (véase la WFG de la figura 17.6b)). P4 iniciará en ese momento una computación
por difusión que se difundirá a los procesos P2 y P3. Puesto que estos procesos están bloqueados,
P4 recibirá la respuesta a su consulta y declarará que está involucrado en un bloqueo mutuo. Las
condiciones por las que un proceso deberá estar en estado bloqueado continuamente desde el
momento en que inició la computación por difusión o desde el momento en que recibió la con-

20 MAQ. CAP. 17(F0694).indd 695 8/10/07 1:22:47 AM


696 CAPÍTULO 17 Algoritmos de control distribuido

sulta demandante no se necesitan en este sistema, que es un sistema SISR; estas condiciones son
necesarias para detectar bloqueos mutuos en sistemas MISR.

P1 P2 P3 P4 P1 P2 P3 P4
a) b)

Figura 17.6 Sistema para ilustrar la detección de bloqueos mutuos basada en la computación por difusión.

Algoritmo de Mitchell-Merritt Pertenece a la clase de algoritmos que se llaman algo-


ritmos distribuidos de sondeo: un mensaje de control se envía a través de un borde en la WFG
para facilitar la detección de ciclos en la WFG. A cada proceso se le asignan dos etiquetas nu-
méricas que se denominan pública y privada. Las etiquetas pública y privada de un proceso son
idénticas cuando se crea el proceso. Cambian cuando un proceso es bloqueado en un recurso.
La etiqueta pública de un proceso también cambia cuando espera a un proceso con una etiqueta
pública más grande. Un borde de espera que tiene una relación específica entre las etiquetas pú-
blicas y privadas de sus procesos de inicio y fin señala un bloqueo mutuo.

Nombre de la regla Precondición Después de aplicar la regla


u x z x
Bloquear z

Activar

u w w w
Transmitir u<w

u u u u
Detectar u u

Figura 17.7 Reglas del algoritmo Mitchell-Merritt.

La figura 17.7 ilustra las reglas del algoritmo de Mitchell-Merritt. Un proceso es represen-
tado como uv donde u y v son sus etiquetas pública y privada, respectivamente. Una regla se
aplica cuando las etiquetas pública y privada de procesos al principio y fin de un borde de espera
cumplen con la precondición. Cambia las etiquetas de los procesos como se muestra a la derecha
de “⇒”. A continuación se indican los detalles de las cuatro reglas:
1. Bloquear: Las etiquetas pública y privada de un proceso cambian a un valor z cuando
el proceso es bloqueado debido a una solicitud de recurso. El valor z es generado por el
enunciado z :⫽ inc(u, x), donde u es la etiqueta pública del proceso, x es la etiqueta

20 MAQ. CAP. 17(F0694).indd 696 8/10/07 1:22:47 AM


17.4 Manejo del bloqueo mutuo distribuido 697

pública del proceso al que espera y la función inc genera un valor único más grande que
u y x.
2. Activar: El borde saliente de un proceso es eliminado de la WFG cuando se activa debido
a una asignación de recurso. Su etiqueta queda sin cambios.
3. Transmitir: Si la etiqueta pública de un proceso al inicio de un borde de espera (u) es más
pequeña que la etiqueta pública del proceso al final del borde (w), entonces u es sustitui-
do por w.
4. Detectar: Se declara un bloqueo mutuo si las etiquetas pública y privada de un proceso
al inicio de un borde de espera son idénticas y también iguales a la etiqueta pública del
proceso al final del borde.

La operación del algoritmo puede explicarse de la siguiente manera: considere una ruta en
u
la WFG de Pi a Pk. Supongamos que las etiquetas de los procesos Pi sean vii y que las de Pk sean
uk
vk . Según la regla de transmitir, aplicada a todos los bordes en la ruta de Pi a Pk, ui es mayor
que o igual a la etiqueta pública de cada proceso en la ruta de Pi a Pk. Supongamos que Pk haga
una solicitud de recurso que resulta en un borde de espera (Pk,, Pi). Según la regla de bloquear,
las etiquetas públicas y privadas de Pk asumen un valor dado por inc(uk, ui). Supongamos que
esto sea n. Por tanto, n ⬎ ui. Según la regla de transmitir, n es propagado a Pi por medio de
procesos a lo largo de la ruta de Pi a Pk. El borde (Pk,, Pi) satisface ahora la regla de detectar. En
la figura 17.6 se le darán nuevas etiquetas públicas y privadas al proceso P4 cuando se bloquea.
Su etiqueta pública será mayor que las etiquetas públicas de P2 y P3, pero podría propagarse por
P2 a través de P3. Por consiguiente, el proceso P4 detectará un bloqueo mutuo.
La corrección del algoritmo se deduce del hecho de que la etiqueta pública de un proceso
Pi al inicio de un borde de espera es propagada a otro proceso Pj solamente si existe una ruta
de Pj a Pi (véase el paso de transmitir). Por ende, si el borde de espera de Pi a Pj satisface la re-
gla de detectar, completa un ciclo en la WFG, por lo que existe un bloqueo mutuo. La seguridad
se deduce en forma trivial si no se permite que los procesos retiren sus solicitudes de manera
espontánea.

17.4.3 Prevención de bloqueos mutuos distribuidos

Los enfoques de prevención de bloqueos mutuos que se analizaron en la sección 11.5 impiden
que surjan ciclos en una gráfica de solicitud y asignación de recursos (RRAG) o en una gráfica
de espera (WFG) por medio de restricciones de solicitudes de recursos. Los bloqueos mutuos en
un sistema distribuido pueden prevenirse en forma análoga: cada evento de creación de procesos
recibe un sello de tiempo mediante un par de id de tiempo/nodo local, y el sello de tiempo es
asociado con el proceso de nueva creación. Esperas circulares en la RRAG o WFG se impiden
mediante la anulación de ciertos tipos de relaciones de espera a través de una comparación de
sellos de tiempo de procesos usando la relación 16.1. Analizaremos dos de estos métodos para la
prevención de bloqueos mutuos distribuidos.

• Espera o muere: Cuando un proceso Preq hace una solicitud para un recurso que en ese
momento está en posesión de Pholder, se permite que Preq espere el recurso si es más viejo
que Pholder; de no ser así, se le mata. No puede surgir un ciclo porque un proceso más

20 MAQ. CAP. 17(F0694).indd 697 8/10/07 1:22:47 AM


698 CAPÍTULO 17 Algoritmos de control distribuido

viejo puede esperar a un proceso más reciente, pero un proceso más reciente no puede
esperar a un proceso más viejo.
• Herir o esperar: Si Preq es más reciente que Pholder se le permite esperar al recurso soste-
nido por Pholder; de no ser así, se mata a Pholder y el recurso solicitado es asignado a Preq.

En ambos planteamientos se cancela el proceso más reciente y tiene que reiniciarse en algún
momento futuro. Para evitar la inanición debido a cancelaciones repetidas, puede permitírsele a
un proceso retener su viejo sello de tiempo cuando es reiniciado. El método de espera o muere
puede preferirse en la práctica porque no involucra la priorización de un recurso, a diferencia del
método de herir o esperar.

17.5 ALGORITMOS DE PLANIFICACIÓN DISTRIBUIDA

Tanto el desempeño del sistema como las aceleraciones de computación serán afectados en for-
ma desfavorable si las cargas computacionales en los nodos de un sistema distribuido fuesen
desiguales. Un algoritmo de planificación distribuida equilibra las cargas computacionales en los
nodos mediante la transferencia de algunos procesos desde un nodo altamente cargado a uno
menos cargado. La figura 17.8 ilustra esta técnica que se denomina migración de procesos. El
proceso Pi es creado en el nodo N1 en el momento t = 0. En el momento ti, la función de planifi-
cación decide transferir el proceso al nodo N2, por lo que la operación del proceso es detenida en
el nodo N1 y el kernel empieza a transferir su estado al nodo N2. En el momento tj la transferencia
del estado está completa y el proceso empieza a trabajar en el nodo N2.

Proceso Pi Estado de Pi Proceso Pi


opera en el es transferido opera en el
nodo N1 al nodo N2 nodo N2
Actividades en
el nodo N2
Actividades en
el nodo N1

0 ti tj tiempo →

Figura 17.8 Migración del proceso Pi del nodo N1 al nodo N2.

A fin de realizar el equilibrio de carga por medio de la migración de procesos, un algorit-


mo de planificación tiene que medir la carga computacional en un nodo y aplicar un umbral
para decidir si está cargado severa o ligeramente. En momentos apropiados transfiere procesos
desde nodos severamente cargados a nodos de carga ligera. Éstos se llaman nodos transmisores
y nodos receptores, respectivamente. La utilización del CPU es un indicador directo de la carga
computacional en un nodo; sin embargo, el monitoreo de la utilización del CPU provoca una
alta carga general de ejecución. Por tanto, los sistemas operativos prefieren usar el número de

20 MAQ. CAP. 17(F0694).indd 698 8/10/07 1:22:48 AM


17.5 Algoritmos de planificación distribuida 699

procesos en un nodo o la longitud de la cola de procesos listos como medidas de cargas compu-
tacionales. Éstas poseen una buena correlación con el tiempo de respuesta promedio en un nodo
y su uso causa una baja carga general.
La migración de un proceso puede llevarse a cabo de dos maneras. La migración priorizante
involucra suspender un proceso, registrar su estado, transferirlo a otro nodo (véase la figura 17.8)
y reanudar la operación del proceso en el nuevo nodo; esto requiere el extenso soporte del kernel.
En la migración no priorizante se toma la decisión de equilibrio de carga mientras se crea un
nuevo proceso. Si el nodo en el cual se realiza una llamada de “crear proceso” está severamente
cargado, se crea el proceso sencillamente en un nodo remoto. La migración no priorizante no
requiere ningún soporte especial en el kernel.
La estabilidad es un asunto importante en el diseño de un algoritmo de planificación distri-
buida. Un algoritmo es inestable si, bajo ciertas condiciones de carga, su carga general no está
acotada. Considere un algoritmo de planificación distribuida que transfiere un proceso desde un
nodo severamente cargado a uno arbitrariamente seleccionado. Si el nodo al que se envía el pro-
ceso también está severamente cargado, el proceso tendrá que migrar nuevamente. Bajo condi-
ciones de carga severa, este algoritmo llevará a una situación que se parece a la hiperpaginación:
la carga general de planificación será alta porque la migración de procesos es frecuente, pero los
procesos que se transfieren no presentarán gran progreso.
Un algoritmo iniciado por un transmisor normalmente transfiere un proceso en forma
no priorizante, es decir, si la longitud de la cola del CPU excede un umbral especificado en la
creación de un nuevo proceso. Un nodo transmisor interroga a otros nodos en el sistema para
encontrar un nodo cuya cola de CPU sea más pequeña que un valor umbral, o para encontrar
el nodo con la carga más ligera que satisfaga esta condición. Un algoritmo iniciado por un
transmisor podrá estar inestable en caso de altas cargas del sistema porque un transmisor que
no puede encontrar un nodo de carga ligera hará interrogaciones continuas y desperdiciará
una fracción considerable del tiempo de su CPU. Puede impedirse la inestabilidad limitando
el número de intentos que se permite a un transmisor para encontrar un receptor. Si se excede
este número, el transmisor abandonará el intento de migración de procesos y creará el nuevo
proceso en el nivel local. También puede presentarse una inestabilidad si se envían varios pro-
cesos al mismo nodo receptor, que entonces se convierte en nodo transmisor y tiene que migrar
algunos de los procesos que ha recibido. Esta situación puede evitarse usando un protocolo por
el cual el nodo sólo acepta un proceso si sigue siendo un nodo receptor (véase el problema 14
del ejercicio 17).
Un algoritmo iniciado por un receptor verifica cada vez que termina un proceso en el nodo
si un nodo es receptor. Entonces interroga a otros nodos en el sistema para encontrar uno que
no se hará nodo receptor incluso si un proceso sale transferido de él, y transfiere un proceso de
uno de estos nodos al nodo receptor. De este modo, la migración de procesos es necesariamente
priorizante. En situaciones de cargas severas del sistema, la carga general de interrogación es-
tará acotada porque el receptor será capaz de encontrar un transmisor. En situaciones de bajas
cargas del sistema, la interrogación continua por parte de un receptor no será perjudicial porque
existirán tiempos de CPU inactivos en el sistema. Puede prevenirse la carga general de equilibrio
de carga no acotada abandonando un intento de equilibrio de carga si no puede encontrarse un
transmisor dentro de un número fijo de interrogaciones; sin embargo, un receptor debe repetir
los intentos de equilibrio de carga en intervalos de tiempo fijos para proveer la propiedad de
vivacidad.

20 MAQ. CAP. 17(F0694).indd 699 8/10/07 1:22:48 AM


700 CAPÍTULO 17 Algoritmos de control distribuido

Analizaremos un algoritmo simétricamente iniciado que contiene características tanto del


algoritmo iniciado por un transmisor como del iniciado por un receptor. Se comporta como
un algoritmo iniciado por un transmisor en situaciones de bajas cargas del sistema y como uno
iniciado por un receptor en situaciones de altas cargas del sistema. Cada nodo mantiene una
bandera de estatus para indicar si es actualmente un nodo transmisor, receptor o un nodo OK,
es decir, ni transmisor ni receptor. También lleva tres listas que se llaman de transmisores, de
receptores y de OK, que contienen las id de nodos que se conocen como nodos transmisores, re-
ceptores o nodos OK, respectivamente.

Algoritmo 17.5 (Algoritmo simétricamente iniciado de equilibrio de carga)


1. Cuando un nodo se vuelve transmisor debido a la creación de un proceso: Si la lista de
receptores no está vacía, interrogar los nodos incluidos en él, sujetos al límite sobre el
número de nodos que pueden ser interrogados.
a) Si el nodo interrogado responde que es un nodo receptor, transferir un proceso a él.
b) Mover el nodo interrogado a la lista correspondiente, basado en su respuesta.
2. Cuando un nodo se vuelve receptor debido a la finalización de un proceso: Interrogar los
nodos incluidos en la lista de transmisores, seguido por los de la lista de receptores y la
lista OK, sujeto al límite del número de nodos que pueden ser interrogados.
a) Si el nodo interrogado responde que es un nodo transmisor, transferir un proceso
desde él.
b) Mover el nodo interrogado a la lista correspondiente, basado en su respuesta.
3. Cuando un nodo es interrogado por un nodo receptor: Mover el nodo interrogador a la
lista de receptores. Enviar una respuesta que contiene su propio estado actual.
4. Cuando un nodo es interrogado por un nodo transmisor: Mover el nodo interrogador a
la lista de transmisores. Enviar una respuesta que contiene su propio estado actual.

↑ Iniciado por
el transmisor
Tiempo de
respuesta

Iniciado
por el receptor

0.5 0.9
Carga del sistema →
Figura 17.9 Desempeño de algoritmos de planificación distribuida.

La figura 17.9 representa el desempeño comparativo de algoritmos de planificación distri-


buida. Un algoritmo iniciado por un transmisor causa una baja carga general en situaciones de
bajas cargas del sistema porque pocos transmisores existen en el sistema. Por tanto, el sistema
puede proveer buenos tiempos de respuesta para procesos. Conforme incrementa la carga, au-
menta también el número de transmisores y la carga general del algoritmo. En situaciones de
altas cargas del sistema, el algoritmo es inestable porque en el sistema existe un gran número
de transmisores, pero pocos receptores, si acaso existe uno. Por consiguiente, el tiempo de res-

20 MAQ. CAP. 17(F0694).indd 700 8/10/07 1:22:48 AM


17.6 Detección de terminación distribuida 701

puesta aumenta en forma aguda. Un algoritmo iniciado por un receptor provoca una mayor carga
general en situaciones de baja carga del sistema que un algoritmo iniciado por un transmisor,
porque en situaciones de baja carga del sistema existe un gran número de receptores. Por esta
razón, el tiempo de respuesta no es tan bueno como en el caso de usar un algoritmo iniciado por
un transmisor. En situaciones de alta carga del sistema existen pocos receptores en el sistema,
por lo que un algoritmo iniciado por un receptor trabaja claramente mejor que un algoritmo ini-
ciado por un transmisor. El desempeño de un algoritmo simétricamente iniciado se parecerá al
desempeño de un algoritmo iniciado por un transmisor en situaciones de baja carga del sistema o
al desempeño de un algoritmo iniciado por un receptor en situaciones de alta carga del sistema.

17.6 DETECCIÓN DE TERMINACIÓN DISTRIBUIDA


Un proceso inmoviliza recursos del sistema tales como estructuras de datos del kernel y de
memoria. El kernel libera estos recursos cuando el proceso hace una llamada de “termíname” al
sistema al final de su operación o cuando es matado por otro proceso. Este método no es adecua-
do para procesos de una computación distribuida porque éstos posiblemente no serán aptos para
decidir cuándo se deberán terminar a sí mismos o cuándo deberán matar a otros procesos. Por
ejemplo, considere una computación distribuida cuyos procesos tienen una relación cliente/ser-
vidor. Un servidor no sabrá si se le harán más solicitudes porque no sabrá quiénes son sus clien-
tes y si todos ellos ya completaron sus operaciones. En estos casos el kernel emplea métodos
de detección de terminación distribuida para verificar si ya terminó la computación distribuida
completa. Si éste es el caso, el kernel libera los recursos asignados a todos sus procesos.
Dos estados de procesos están definidos para facilitar la terminación. Un proceso está en el
estado pasivo cuando no tiene trabajo que realizar; está latente y espera que otro proceso le en-
víe trabajo por medio de un mensaje interproceso. Un proceso está en el estado activo cuando
está ocupado con la realización de trabajo. Puede estar realizando acciones de E/S, esperan-
do un recurso, esperando a que se le asigne el CPU o ejecutando instrucciones. El estado de un
proceso cambia varias veces durante su ejecución. Un proceso pasivo se vuelve inmediatamente
activo cuando recibe un mensaje, envía una confirmación al transmisor del mensaje y empieza a
procesarlo. Un proceso activo confirma un mensaje en forma inmediata, aunque podrá demorar
su procesamiento hasta un momento conveniente. Un proceso activo se vuelve pasivo cuando
termina su trabajo actual y ya no tiene que realizar otros trabajos. Se supone que tanto los mensa-
jes de control como los mensajes básicos viajan a lo largo de los mismos canales interprocesos.
Se dice que una computación distribuida ha terminado si cumple con la condición de termi-
nación distribuida (DTC). La DTC consiste en dos partes:
1. Todos los procesos de una computación distribuida son pasivos.
(17.1)
2. No hay mensajes básicos en tránsito.
La segunda parte es necesaria porque un mensaje en tránsito hará que su proceso destinatario se
vuelva activo cuando se entrega. Analizaremos dos enfoques para determinar si la DTC es válida
para una computación distribuida.
Detección de terminación con base en la distribución de crédito En este planteamiento
hecho por Mattern [1989], se asigna a cada actividad o actividad potencial en una computación
distribuida un coeficiente de ponderación numérico denominado crédito. Se inicia una compu-
tación distribuida con una conocida cantidad finita de crédito C. Éste se distribuye entre los
procesos. La forma de su distribución es irrelevante mientras cada proceso Pi reciba un crédito
no cero ci. Cuando un proceso envía un mensaje básico a otro, pone una parte de este crédito en

20 MAQ. CAP. 17(F0694).indd 701 8/10/07 1:22:49 AM


702 CAPÍTULO 17 Algoritmos de control distribuido

el mensaje; nuevamente es irrelevante qué cantidad de crédito pone en un mensaje, mientras no


sea cero ni el crédito entero. Un proceso que recibe un mensaje extrae el crédito del mensaje y lo
agrega a su propio crédito antes de procesar el mensaje. Cuando un proceso se vuelve pasivo, en-
vía su crédito entero a un proceso especial del sistema que se denomina proceso colector, el cual
acumula todo el crédito que recibe. Se sabe que la computación distribuida ha terminado cuando
el crédito acumulado por el proceso colector es igual a C. Este algoritmo es sencillo y elegante;
sin embargo, puede ser que el crédito se distribuya en forma indefinida, por lo que deberá usarse
una representación conveniente del crédito en su implementación.
Detección de terminación con base en la computación por difusión Cada proceso que se
vuelve pasivo inicia una computación por difusión para determinar si la DTC es válida. De este
modo, cada proceso tiene la capacidad de detectar la terminación. Analizaremos la detección de
la DTC en un escenario simplificado donde sean válidas las siguientes tres reglas:
1. Los procesos no son creados o destruidos en forma dinámica durante la ejecución de
la computación; o sea, todos los procesos son creados cuando se inicia la computación
distribuida, y permanecen en existencia hasta que termine la computación.
2. Los canales de comunicación interproceso son FIFO.
3. Los procesos se comunican entre sí por medio de la comunicación síncrona; es decir,
que el transmisor de un mensaje es bloqueado hasta que recibe una confirmación para el
mensaje.
La regla 3 simplifica la prueba para confirmar la DTC del siguiente modo: el transmisor de
un mensaje básico es bloqueado y reanuda su operación después de recibir la confirmación. Sólo
podrá entrar en el estado pasivo tras haber terminado su trabajo. El mensaje básico enviado por
un proceso entonces no puede estar en tránsito cuando se vuelve pasivo, y el sistema no puede
tener mensaje básico alguno en tránsito cuando todos los procesos están pasivos. Por tanto es
suficiente revisar sólo la primera parte de la condición de la DTC, o sea si todos los procesos
están pasivos. El algoritmo 17.6 realiza su chequeo por medio de una computación de difusión
cuyas consultas viajan a través de los bordes que representan la comunicación interproceso. El
ejemplo 17.4 ilustra la operación del algoritmo 17.6.

Algoritmo 17.6 (Detección de terminación distribuida)


1. Cuando un proceso se vuelve pasivo: El proceso inicia una computación por difusión por
medio de las siguientes acciones:
a) Enviar consultas de “¿Debo declarar la terminación distribuida?” a lo largo de todos
los bordes conectados a él.
b) Recordar el número de consultas enviadas y esperar las respuestas.
c) Después de recibir las respuestas a todas sus consultas, declarar la terminación distri-
buida si todas las respuestas son sí.
2. Cuando un proceso recibe una consulta demandante: Si el proceso está en el estado ac-
tivo, envía una respuesta no; de lo contrario realiza las siguientes acciones:
a) Enviar consultas a lo largo de todos los bordes conectados a él con excepción del
borde por el cual recibió la consulta demandante.
b) Recordar el número de consultas enviadas y esperar las respuestas.
c) Después de recibir las respuestas a todas sus consultas: Si todas las respuestas son
sí, enviar una respuesta sí al proceso de donde recibió la consulta demandante; de lo
contrario, enviar una respuesta no.

20 MAQ. CAP. 17(F0694).indd 702 8/10/07 1:22:49 AM


17.7 Algoritmos de elección 703

3. Cuando un proceso recibe una consulta no demandante: El proceso inmediatamente en-


vía una respuesta sí al proceso de donde recibió la consulta.

P7 P6

P2 P1 P5

P3 P4
Figura 17.10 Ilustración de la DTC.

Ejemplo 17.4 La figura 17.10 muestra una computación distribuida. Sólo los procesos P1 y P2 son
activos; todos los demás son pasivos. Entonces ocurren los siguientes eventos:
1. El proceso P2 se vuelve pasivo, inicia la detección de terminación y envía una consulta al
proceso P1.
2. El proceso P1 envía un mensaje básico al proceso P5 a lo largo del borde (P1, P5) y se vuel-
ve pasivo en la primera oportunidad.
El evento de recepción en P5 para el mensaje básico de P1 y los eventos concernientes al en-
vío/recepción de consultas y sus respuestas por los procesos podrán suceder en varias secuencias
distintas. Dos secuencias de interés son las siguientes: si el proceso P1 recibió la solicitud de P2
antes de volverse pasivo, enviará una respuesta no a P2, por lo que P2 no declarará la terminación.
Si el proceso P1 recibió la solicitud de P2 después de volverse pasivo, según la regla 3 ya habrá
recibido una confirmación del mensaje básico que había enviado al proceso P5 en el paso 2, por lo
que el proceso P5 debe haberse vuelto activo después de recibir el mensaje de P1 antes de que P1 se
volviera pasivo. Ahora bien, cuando P1 recibe la consulta de P2, enviará una consulta a cada uno de
los procesos de P3 a P7. P5 enviará una respuesta no a P1, que enviará una respuesta no a P2, por lo
que P2 no declarará la terminación. Si se eliminan las reglas 2 y 3, el algoritmo sufrirá problemas
de seguridad en algunas situaciones.

Los algoritmos de detección de terminación distribuida se vuelven complejos cuando tratan


de eliminar las reglas 1-3. Algunos estudios que se citan en la bibliografía analizan detalles de
estos algoritmos.

17.7 ALGORITMOS DE ELECCIÓN

Una función crítica, como reemplazar el token perdido en un algoritmo basado en tokens, se
asigna a un proceso individual denominado coordinador para la función. Normalmente, las prio-
ridades están asociadas a procesos y el proceso de mayor prioridad entre un grupo de procesos
se elige como coordinador para una función. Si el coordinador falla, se emplea un algoritmo de
elección para elegir al proceso no fallado de mayor prioridad como nuevo coordinador y su id se
anuncia a todos los procesos no fallados.
Algoritmos de elección para topologías de anillo Un anillo unidireccional es formado por
la conexión de procesos contiguos a través de canales FIFO. Se supone que la parte de control de

20 MAQ. CAP. 17(F0694).indd 703 8/10/07 1:22:49 AM


704 CAPÍTULO 17 Algoritmos de control distribuido

un proceso fallado continúa funcionando y simplemente reenvía cada mensaje recibido a lo largo
de su borde saliente. La elección se lleva a cabo consiguiendo las id de todos los procesos no fa-
llados en el sistema y eligiendo el proceso de mayor prioridad. Esto puede lograrse de la siguiente
manera: supongamos que un proceso Pi que inicia una elección envíe un mensaje (“elígeme”, Pi)
a lo largo de su borde saliente. Un proceso Pj que recibe este mensaje realiza dos acciones: envía
un mensaje (“elígeme”, Pj) por su parte y también reenvía el mensaje (“elígeme”, Pi) inmedia-
tamente después de su propio mensaje. Estos mensajes llegan al proceso Pi de tal forma que el
mensaje (“elígeme”, Pi) sigue a todos los demás mensajes. El proceso Pi examina las id de proce-
sos contenidas en todos estos mensajes y elige el de mayor prioridad, digamos Phigh, como nuevo
coordinador. Entonces envía un mensaje (“nuevo coordinador”, Phigh) a lo largo del anillo para
informar a todos los procesos el resultado de la elección. Se supone que no ocurren fracasos du-
rante una elección. Esta suposición asegura resultados idénticos aun si dos o más procesos inician
elecciones en forma paralela. El algoritmo requiere un orden de n2 mensajes por elección.
Puede reducirse el número de mensajes por elección del siguiente modo: un proceso Pj que
recibe un mensaje (“elígeme”, Pi) envía un solo mensaje (“elígeme”, Pj) para iniciar una nueva
elección si su propia prioridad es mayor a la de Pi; de no ser así, simplemente reenvía el mensaje
(“elígeme”, Pi). De este modo, sólo el proceso no fallado de mayor prioridad Phigh recibirá de
regreso su propio mensaje de “elígeme”. Enviará un mensaje (“nuevo coordinador”, Phigh) para
anunciar su elección. Todos los demás procesos abandonan sus elecciones, si acaso existían,
cuando reciben el mensaje (“nuevo coordinador”, Phigh). Cuando se usa este refinamiento, el
número de mensajes por elección puede ser un máximo de 3n ⫺ 1 de la siguiente forma: el men-
saje (“elígeme”, Pi) enviado por el proceso que inicia una elección necesita un máximo de n ⫺ 1
mensajes para llegar al proceso de mayor prioridad. La elección iniciada por el proceso de mayor
prioridad requiere n mensajes para finalizar, e informar a cada proceso sobre el resultado de la
elección requiere otros n mensajes. El tiempo consumido por la elección podrá ser tan alto como
(3n ⫺ 1) × twc, donde twc es el tiempo de entrega de mensajes de peor caso a través de una liga.

Algoritmo bravucón Un proceso Pi que inicia una elección envía un mensaje (“elígeme”,
Pi) a todos los procesos de mayor prioridad y empieza un intervalo de tiempo T1. Si no tiene no-
ticias de ninguno de ellos antes de que ocurra el intervalo de tiempo, supone que todos ellos han
fracasado, envía un mensaje (“nuevo coordinador”, Pi) a todos los procesos de menor prioridad y
se convierte en el nuevo coordinador. Si recibe un mensaje “¡Ni te atrevas!” de un proceso de ma-
yor prioridad Pj, abandona su reclamo de ser el nuevo coordinador. Entonces inicia otro intervalo
de tiempo T2 y espera un mensaje de Pj o de otro proceso anunciándose como nuevo coordinador.
Si no recibe un mensaje de esta índole, supone que un proceso de mayor prioridad, que debería
haber sido coordinador, fracasó durante el intervalo. En ese momento inicia una nueva elección,
enviando nuevamente mensajes de (“elígeme”, Pi). Un proceso Pj que recibe un mensaje “elíge-
me” de un proceso de menor prioridad responde enviando un mensaje “¡Ni te atrevas!” al proceso
de menor prioridad. Inmediatamente después, Pj inicia una elección por su parte, a menos que ya
la hubiese iniciado, enviando mensajes (“elígeme”, Pj) a todos los procesos de mayor prioridad.
El número total de mensajes por elección es un orden de n2. Si la gráfica del sistema está
completamente conectada y ningún nodo falla o se recupera durante una elección, el tiempo con-
sumido por la elección podrá ser tan alto como T1 ⫹ T2, donde T1, T2 son los dos intervalos de
tiempo. T1 ⱖ 2 ⫻ twc, donde twc es el tiempo de entrega de mensajes del peor caso a través de una
liga, y T2 ⱖ 3 × twc (podrá ser ⱖ 2 × twc, puesto que la transmisión del mensaje “elígeme” enviado
por un proceso de mayor prioridad se traslapará con la transmisión del mensaje “ni te atrevas”
enviado por él). Por tanto, el tiempo consumido por el algoritmo no es mayor que 5 ⫻ twc.

20 MAQ. CAP. 17(F0694).indd 704 8/10/07 1:22:49 AM


17.8 Asuntos prácticos en el uso de algoritmos de control distribuido 705

Ejemplo 17.5 Un sistema contiene 10 procesos P1, P2 . . . P10, con las prioridades 1 . . . 10, donde
10 es la prioridad más alta. El proceso P10 es el proceso coordinador. Su fracaso es detectado por
el proceso P2. P2 envía mensajes “elígeme” a P3-P10. Cada uno de los procesos de P3-P9 responde
enviando un mensaje “ni te atrevas” a P2, y estos procesos empiezan sus propias elecciones en-
viando mensajes “elígeme” a procesos de mayor prioridad. Finalmente los procesos P2-P8 reciben
mensajes “ni te atrevas” de todos los procesos de mayor prioridad excepto de P10, que fracasó.
El proceso P9 no recibe ningún mensaje “ni te atrevas” y, por tanto, se elige a sí mismo como
coordinador y envía un mensaje (“nuevo coordinador”, P9) a P1-P8. Durante la elección se envían
36 mensajes “elígeme”, 28 mensajes “ni te atrevas” y 8 mensajes “nuevo coordinador”. El número
total de mensajes para esta elección es entonces 72.
Si el sistema se hubiese organizado como un anillo unidireccional con los bordes (Pi, Pi+1)
∀i ⬍ 10 y el borde (P10, P1), se hubiese necesitado un total de 27 mensajes para llevar a cabo la
elección.

17.8 ASUNTOS PRÁCTICOS EN EL USO DE ALGORITMOS


DE CONTROL DISTRIBUIDO

17.8.1 Manejo de recursos


Cuando un proceso solicita acceso a un recurso, el asignador de recursos debe encontrar la ubi-
cación de recurso(s) coincidente(s) en el sistema, determinar su disponibilidad y asignar uno de
los recursos. La figura 17.11 contiene un esquema de la asignación de recursos. En cada nodo
del sistema existe un administrador de recursos que consiste en un servidor de nombres y un
asignador de recursos. Los números en círculos corresponden a los pasos en el subsiguiente pro-
cedimiento de asignación de recursos:

Administrador de recursos

Servidor Asignador Nj
de nombres 2 de recursos

1 ,5 3 3 ,5

Pi Pk rk Nk
4

Figura 17.11 Asignación de recursos en un sistema distribuido.

1. Cuando el proceso Pi desea usar un recurso llamado resj, construye un par (resj, Pi) y lo
remite al administrador de recursos. Éste recibe la solicitud y la entrega al servidor de
nombres.
2. El servidor de nombres localiza a resj mediante su nombre y sus atributos, y construye el
triple (rk, Nk, Pi) donde resj es el recurso rk en el nodo Nk. El triple se entrega al asignador
de recursos.
3. El asignador de recursos busca si el recurso rk del nodo Nk está disponible. De ser así, le
pasa Pk —la id del proceso controlador de recursos para el recurso— a Pi. También envía

20 MAQ. CAP. 17(F0694).indd 705 8/10/07 1:22:50 AM


706 CAPÍTULO 17 Algoritmos de control distribuido

un mensaje de asignación que contiene la id de Pi a Pk. Si el recurso no está disponible,


almacena la solicitud en una cola de solicitudes pendientes. La solicitud se cumplirá en
algún momento futuro cuando el recurso esté disponible.
4. El proceso Pk interactúa con el proceso Pi para cumplir la solicitud de servicio de P’i.
5. Después de finalizar el uso del recurso, el proceso Pi hace una solicitud de liberación. El
administrador de recursos envía un mensaje de liberación a Pk y asigna el recurso a una
solicitud pendiente, si existe.
El punto importante en el paso 3 es asegurar la no interferencia de asignadores de recursos
de diferentes nodos. Esto se puede lograr mediante un algoritmo de exclusión mutua distribuida
o de un algoritmo de elección para elegir un coordinador que realizará todas las asignaciones
en el sistema. Ambos planteamientos causarán una alta carga general. El uso de un algoritmo
de exclusión mutua provocará una carga general en cada asignación. Sin embargo, se requerirá
un protocolo para asegurar que la información del estado de recursos estará accesible para un
nuevo coordinador si el presente coordinador fracasa. Un argumento más sencillo es confiar
la asignación de recursos en un nodo al asignador de recursos de ese nodo. Este método evita la
carga general de la exclusión mutua, así como la elección y tolerancia de fallas. También es más
robusto porque puede asignarse un recurso a un proceso mientras que los nodos que contienen el
proceso y el recurso así como una ruta de la red entre los dos son funcionales. Tiene que actua-
lizarse el servidor de nombres en cada nodo cuando se agregan recursos. Este problema puede
resolverse por medio de un arreglo de servidores de nombres, como en el servicio de nombres
de dominio (DNS) (véase la sección 15.5.1).

17.8.2 Migración de procesos

El mecanismo de migración de procesos se usa para transferir un proceso entre nodos en un sis-
tema distribuido. Se emplea para lograr el equilibrio de carga o para reducir el tráfico en la red
involucrado en la utilización de un recurso remoto. También puede usarse para proveer la dispo-
nibilidad de servicios cuando debe apagarse un nodo por motivos de mantenimiento. El esquema
de la figura 17.8 dejó ver la migración de procesos engañosamente sencillo; sin embargo, en
realidad es bastante complejo debido a varias razones. El estado de un proceso comprende lo
siguiente:

• Identificador de procesos e id de sus procesos hijos.


• Señales y mensajes pendientes.
• Directorio de trabajo, descriptores de archivos y buffers de archivos actuales.
Se enfrentan dos tipos de problemas en la transferencia de un estado de proceso: a menudo
el estado de un proceso está difundido a través de muchas estructuras de datos en el kernel, por
lo que es difícil identificar y extraerlo de estas estructuras de datos. Las id de proceso y descrip-
tores de archivos tienen que ser únicos en el nodo donde opera un proceso; estas informaciones
deberán cambiarse cuando se migra un proceso. Este requerimiento crea dificultades en la sin-
cronización de procesos y en E/S. Lo importante en este contexto es proveer id de proceso glo-
balmente únicas como en el cluster Sun (véase la sección 15.4) y en la transparencia de recursos
y servicios (véase la sección 15.9).
Cuando se envía un mensaje a un proceso, el DNS convierte el nombre del proceso (<host_
name>, <process_id>) en el par (dirección IP, <process_id>). Este tipo de mensaje puede

20 MAQ. CAP. 17(F0694).indd 706 8/10/07 1:22:50 AM


Ejercicio 17 707

estar en tránsito cuando su proceso destinatario es migrado, por lo que deben tomarse medidas
para entregar el mensaje al proceso en su nueva ubicación. Cada nodo puede mantener el es-
tado residual de un proceso que fue migrado hacia fuera. Este estado contendrá la id del nodo
hacia donde fue migrado. Si un mensaje intentado para uno de estos procesos llega a este
nodo, simplemente reexpedirá el mensaje a su nueva ubicación. Si el proceso hubiera sido mi-
grado fuera de este nodo en el ínterin, el nodo reexpedirá del mismo modo el mensaje usando el
estado residual que mantiene. De esta manera, un mensaje llegará al proceso independientemente
de su migración. Sin embargo, el estado residual causa poca confiabilidad porque puede ser que
un mensaje no se entregue si el estado residual de su proceso destinatario fue perdido o se hizo
inaccesible debido a una falla del nodo. Esta situación justificaría el comentario sarcástico de que
“un sistema distribuido es un sistema que yo no puedo usar porque una máquina que desconozco
ha fracasado”. Un método alternativo será informar a todos los demás procesos que comunican
con él acerca del cambio de ubicación de un proceso (igual que un cambio de la id de proceso, de
ser aplicable). De este modo, un mensaje puede enviarse al proceso en forma directa en su nueva
ubicación. Si un mensaje que estuvo en tránsito cuando un proceso fue migrado llegase al nodo
viejo donde el proceso existía alguna vez, el nodo devolverá una respuesta “ya no está aquí” al
transmisor. Entonces éste reexpedirá el mensaje al proceso en su nueva ubicación.

EJERCICIO 17
1. Indique y compare las propiedades de vivacidad de a) un algoritmo de exclusión mutua distribuida y b)
un algoritmo de elección.
2. Demuestre que el algoritmo de Ricart-Agrawala es FCFS y libre de bloqueos mutuos.
3. El paso 2b) del algoritmo de Ricart-Agrawala se modifica de tal modo que un proceso que desea entrar
en una SC no envía una respuesta de “adelante” a ningún otro proceso hasta que haya usado su SC.
Demuestre que este algoritmo modificado no está libre de bloqueos mutuos.
4. Demuestre√ la propiedad de seguridad del algoritmo de Maekawa que usa conjuntos de solicitudes del
tamaño 苵n.
5. Construya un ejemplo donde el algoritmo de Raymond no exhibe el comportamiento FCFS para la
entrada en una SC. (Sugerencia: Considere la siguiente situación en el ejemplo 17.2: el proceso P2 hace
una solicitud para entrada en una SC mientras P5 aún se encuentra en la SC.)
6. Muestre acciones de las partes básica y de control de un proceso para implementar el algoritmo de
Raymond.
7. Identifique las consultas demandantes y no demandantes en el algoritmo Chandy-Lamport para el re-
gistro de estados consistente (algoritmo 16.2). Extienda el algoritmo para recabar la información del
estado registrado en el sitio del nodo que inició el registro de estado.
8. Analice la influencia de los métodos “esperar o morir” y “herir o esperar” sobre tiempos de respuesta
y plazos límite para procesos.
9. Demuestre que un asignador de recursos que usa el método “esperar o morir” y “herir o esperar” para
la detección de bloqueos mutuos no posee la propiedad de vivacidad si se da un nuevo sello de tiempo
a un proceso matado cuando se reinicia.
10. Se propone usar un algoritmo distribuido de sondeo para la detección de bloqueos mutuos que surgen
en la comunicación interproceso. Cuando un problema es bloqueado en una solicitud de “mensaje de
recepción”, se envía una consulta al proceso de donde espera el mensaje. Si este proceso es bloquea-
do en una solicitud de “mensaje de recepción”, el proceso remite la consulta al proceso al que está

20 MAQ. CAP. 17(F0694).indd 707 8/10/07 1:22:50 AM


708 CAPÍTULO 17 Algoritmos de control distribuido

esperando, y así sucesivamente. Un proceso declara un bloqueo mutuo si recibe su propia consulta.
Comente acerca de la conveniencia de este algoritmo para
a) la comunicación simétrica;
b) la comunicación asimétrica.
11. Demuestre que un algoritmo de detección de bloqueos mutuos distribuidos detectará bloqueos mutuos
fantasmas si se permite que los procesos retiren sus solicitudes de recursos cuando ocurre un intervalo
de tiempo.
12. Si el uso de la función inc en la regla bloquear es omitido del algoritmo de Mitchell-Merritt, muestre
que el algoritmo modificado viola el requerimiento de vivacidad.
13. Demuestre la corrección del algoritmo de detección de terminación distribuida basado en la distribu-
ción de crédito.
14. Un algoritmo de planificación distribuida iniciado por un transmisor usa el siguiente protocolo para
transferir un proceso de un nodo a otro:
a) Un transmisor interroga a todos los demás nodos en el sistema en busca de un nodo receptor.
b) Selecciona un nodo como receptor potencial y le envía un mensaje “bloquéate a ti mismo para una
transferencia de procesos”.
c) El receptor del mensaje envía una respuesta no si ya no es receptor. De lo contrario, incrementa la
longitud de su cola de CPU en 1 y envía una respuesta sí.
d) El transmisor transfiere un proceso cuando recibe una respuesta sí.
e) Si recibe una respuesta no, selecciona otro nodo y repite los pasos 14b)-14c).
¿Evita este protocolo la inestabilidad en situaciones de altas cargas del sistema?
15. Defina las propiedades de vivacidad y seguridad de un algoritmo de planificación distribuida. (Suge-
rencia: ¿Surgirán desequilibrios de carga computacional en un sistema si su algoritmo de planificación
posee propiedades de vivacidad y seguridad?)

BIBLIOGRAFÍA
Dijkstra y Scholten (1980) y Chang (1982) analizan el modelo de computación por difusión de algoritmos
distribuidos. Andrews (1991) estudia los algoritmos de difusión y paso de token.
Raymond (1989), así como Ricart y Agrawala (1981) abordan los algoritmos de exclusión mutua
distribuida. Dhamdhere y Kulkarni (1994) analizan un algoritmo de exclusión mutua tolerante a las fallas.
El algoritmo de detección de bloqueos mutuos basado en la computación por difusión (algoritmo 17.4) es
adaptado de Chandy et al. (1983). Knapp (1987) estudia varios algoritmos de detección de bloqueos mu-
tuos distribuidos. Sinha y Natarajan (1984) analizan un algoritmo distribuido de sondeo para la detección
de bloqueos mutuos distribuidos. Wu et al. (2002) describen algoritmos de detección de bloqueos mutuos
distribuidos para el modelo AND.
La detección de terminación distribuida se analiza en Dijkstra y Scholten (1980) y en Dhamdhere et al.
(1997). El algoritmo de bravucón para elecciones distribuidas se estudia en Garcia-Molina (1982). Smith
(1988) analiza técnicas de migración de procesos.
Singhal y Shivaratri (1994) y Lynch (1996) describen muchos algoritmos de control distribuido en de-
talle. Tel (2000) y Garg (2002) analizan algoritmos de detección de elección y terminación. Attiya y Welch
(2004) estudian algoritmos para el problema de elección.

1. Attiya, H. y J. Welch (2004): Distributed Computing: Fundamentals, Simulations and Advanced


Topics, John Wiley, New Jersey.

20 MAQ. CAP. 17(F0694).indd 708 8/10/07 1:22:50 AM


Bibliografía 709

2. Andrews, G.R. (1991): “Paradigms for process interaction in distributed programs”, Computing
Surveys, 23, 1, 49-40.
3. Chandy, K.M., J. Misra y L.M. Haas (1983): “Distributed deadlock detection”, ACM Transactions
on Computer Systems, 1 (2), 144-152.
4. Chang, E. (1982): “Echo algorithms: depth parallel operations on general graphs”, IEEE Transac-
tions on Software Engineering, 8 (4), 391-401.
5. Dhamdhere, D.M. y S.S. Kulkarni (1994): “A token based k-resilient mutual exclusion algorithm
for distributed systems”, Information Processing Letters, 50 (1994), 151-157.
6. Dhamdhere, D.M., S.R. Iyer y E.K.K. Reddy (1997): “Distributed termination detection of dyna-
mic systems”, Parallel Computing, 22 (14), 2025-2045.
7. Dijkstra, E.W. y C.S. Scholten (1980): “Termination detection for diffusing computations”, Infor-
mation Processing Letters, 11 (1).
8. Garg, V.K. (2002): Elements of Distributed Computing, Wiley-IEEE.
9. Garcia-Molina, H. (1982): “Elections in distributed computing systems”, IEEE Transactions on
Computers, 31 (1).
10. Knapp, E. (1987): “Deadlock detection in distributed databases”. Computing Surveys, 19, (4),
303-328.
11. Lynch, N. (1996): Distributed Algorithms, Morgan Kaufmann.
12. Mitchell, D.P. y M.J. Merritt (1982): “A distributed algorithm for deadlock detection and reso-
lution”, Proceedings of the ACM Conference on Principles of Distributed Computing, agosto de
1984, 282-284.
13. Obermarck, R. (1982): “Distributed deadlock detection algorithm”, ACM Transactions on Data-
base Systems, 7 (2), 187-202.
14. Raymond, K. (1989): “A tree-based algorithm for distributed mutual exclusion”, ACM Transac-
tions on Computer Systems, 7, 61-77.
15. Ricart, G. y A.K. Agrawala (1981): “An optimal algorithm for mutual exclusion in computer net-
works”, Communications of the ACM, 24 (1), 9-17.
16. Singhal, M. y N. G. Shivaratri (1994): Advanced Concepts in Operating Systems, McGraw-Hill,
Nueva York.
17. Sinha, M.K. y N. Natarajan (1984): “A priority based distributed deadlock detection algorithm”,
IEEE Transactions on Software Engineering, 11 (1), 67-80.
18. Smith, J.M. (1988): “A survey of process migration mechanisms”, Operating Systems Review, 22
(3), 28-40.
19. Tel, G. (2000): Introduction to Distributed Algorithms, 2a. edición, Cambridge University Press,
Cambridge.
20. Wu, H., W. Chin y J. Jaffer (2002): “An efficient distributed deadlock avoidance algorithm for the
AND model”, IEEE Transactions on Software Engineering, 28, 1, 18-29.

20 MAQ. CAP. 17(F0694).indd 709 8/10/07 1:22:51 AM


Capítulo
18
Recuperación y
tolerancia de fallas

Una falla podrá dañar el estado de datos o procesos. Varias cosas podrán salir mal si una falla
ocurre durante la operación de un sistema: se podrá perder la consistencia de datos, un servidor
podrá averiarse, recursos y servicios podrán volverse indisponibles o el sistema podrá dejar de
funcionar. A fin de proveer la operación confiable, un SO evita estas consecuencias o fallas usan-
do tres planteamientos que se llaman recuperación, tolerancia de fallas y resiliencia.
La recuperación en un sistema distribuido es análoga a la que se efectúa en un sistema de
archivos como se ha analizado en el capítulo 7. Cuando ocurre una falla, algunos datos o pro-
cesos serán regresados a estados que fueron registrados antes de la ocurrencia de la falla, por
lo que los resultantes estados de computaciones y el SO serán consistentes. Debido a la natu-
raleza distribuida de computaciones, un roll-back (volver a un estado previo) de un proceso
podrá requerir roll-backs de otros. Este requerimiento se denomina efecto dominó. Se reanudará
la operación normal de una computación después de que finalice la recuperación; sin embargo,
es posible que la computación tenga que reejecutar algunas acciones que había realizado antes
de que ocurriera la falla.
La tolerancia de fallas provee la operación ininterrumpida de un sistema mediante la re-
paración de estados de datos o procesos afectados por una falla en lugar de regresarlos a esta-
dos que se habían registrado antes de la ocurrencia de la falla. El planteamiento de resiliencia
trata de minimizar el costo de la reejecución cuando ocurren fallas. La resiliencia se logra por
medio de técnicas especiales para 1) recordar resultados útiles calculados en una subcompu-
tación y usarlos en forma directa, es decir, sin reejecución, después de una falla, y 2) reejecutar
una subcomputación, en lugar de una computación completa, cuando ocurre una falla.
Empezaremos este capítulo con un resumen de las diferentes clases de fallas y varias ma-
neras de enfrentarlas. Las secciones posteriores analizarán la recuperación, tolerancia de fallas
y resiliencia.

21 MAQ. CAP. 18(F0694).indd 710 8/10/07 1:24:11 AM


18.1 Fallas, averías y recuperación 711

18.1 FALLAS, AVERÍAS Y RECUPERACIÓN

Una falla, como un apagón o un error de lectura de memoria, podrá dañar el estado del sistema.
Para la operación confiable, el sistema deberá restaurarse a un estado consistente, y su operación
deberá reanudarse. Recuperación es el nombre genérico para todos los planteamientos que se
usan para ese propósito.
Fallas como los apagones se notan fácilmente, mientras que un error de lectura de memoria
sólo se hace notar cuando el daño sufrido por el estado del sistema causa un comportamiento
inesperado del sistema o una situación inusual en él. A este comportamiento o situación inusual
se le denomina avería. La figura 18.1 ilustra cómo surge una avería. El ejemplo 18.1 analiza una
falla, un error y una avería en un sistema bancario.

Sistema Comportamiento
Estado
Antes Comportamiento
de la falla esperado

falla

error
Estado
Después Comportamiento
de la falla inesperado,
es decir, avería

Figura 18.1 Falla, error y avería en un sistema.

Ejemplo 18.1 Las cuentas bancarias A y B contienen 1 000 y 250 dólares, respectivamente. Una
aplicación bancaria transfiere 100 dólares de la cuenta A a la cuenta B. Un apagón ocurre después
de deducir 100 dólares del saldo en la cuenta A, pero antes de agregar 100 dólares al saldo de la
cuenta B. El apagón es una falla. El error es que 100 dólares fueron deducidos de la cuenta A, pero
no fueron agregados a la cuenta B. ¡La avería es que 100 dólares desaparecieron!

Una recuperación se lleva a cabo cuando se detecta una falla. La figura 18.2 ilustra el estado
de un sistema durante la operación normal, después de una falla y después de la recuperación.
Todos los tiempos son tiempos lógicos en el sistema. El sistema es iniciado en un estado consis-
tente S0 a la hora 0. Una falla ocurre a la hora t1. La falla, o la subsiguiente avería, es detectada
a la hora ti. El sistema hubiese estado en el estado Si a la hora ti si la falla no hubiese ocurrido;
sin embargo, en realidad está en el estado Si. El procedimiento de recuperación aplica una co-
rrección S al estado y alista el sistema para reanudar su operación. Supongamos que el estado
resultante se llame Snew. El esfuerzo gastado en aplicar S determina el costo de recuperación.
Será ideal si Snew  Si; sin embargo, la naturaleza de una falla y la avería causada por ella deter-
minan si esto podrá ser así.

21 MAQ. CAP. 18(F0694).indd 711 8/10/07 1:24:11 AM


712 CAPÍTULO 18 Recuperación y tolerancia de fallas

Si
∆S
Snew

S0 S1 Si

0 t1 ti
tiempo →

Figura 18.2 Recuperación después de una falla.

18.1.1 Clases de fallas

Una falla podrá afectar a un sistema de cómputo, a sólo un proceso del sistema o a componentes
de hardware tales como la memoria o el hardware de comunicación. Por consiguiente las fallas
se clasifican en: de sistema, de proceso, de almacenamiento y de comunicación. Dentro de una
clase de fallas, un modelo de fallas describe las propiedades de una falla que determinan los tipos
de errores y averías que puedan resultar de ella.
Una falla de sistema es una caída del sistema causada por un apagón o por fallas de com-
ponentes. Las fallas de sistema se clasifican en de amnesia y de semiamnesia, dependiendo
de cuánta información de estado se pierde cuando ocurre. En una falla de amnesia, el sis-
tema “olvida” por completo el estado en el que estuvo cuando sucedió la falla. En una de
semiamnesia, algunos componentes del estado del sistema existentes en el momento de la falla
sobreviven. Una falla de sistema fail-stop (falla parada) paraliza un sistema. Los servidores
de archivos normalmente sufren fallas de semiamnesia porque pierden una parte de su estado
que corresponde a los datos que estuvieron almacenados en la memoria o en un disco fallado.
La característica fail-stop de una falla de sistema es conveniente porque un sistema detiene su
operación cada vez que ocurre una falla. Le permite a un observador externo —una persona o
un sistema de cómputo— verificar si ha ocurrido una falla al observar si la operación del sis-
tema se detuvo. También le da oportunidad al sistema para recuperarse de una falla, reparando
el estado del sistema.
Un proceso que sufre una falla bizantina podrá realizar acciones maliciosas o arbitrarias.
No es posible deshacer estas acciones cuando se nota una falla. Por tanto, las fallas bizantinas
se manejan usando procesos redundantes y protocolos de acuerdos. En este planteamiento,
un conjunto de procesos realiza la misma computación. Si sus resultados no coinciden, el
sistema usa un protocolo de acuerdo para decidir cuál de ellos es el correcto. Procesos que
producen resultados incorrectos son identificados y cancelados antes de que realicen alguna
actualización de datos; a los demás se les permite realizar actualizaciones y continuar con su
operación.
Una típica falla de almacenamiento ocurre debido a un mal bloque en un medio de alma-
cenamiento. Esto hace que algunos datos sean ilegibles. La ocurrencia de una falla de almace-
namiento podrá detectarse usando técnicas de búsqueda de errores (véase la sección 14.3), o
notarse cuando se acceden datos. Fallas de almacenamiento son básicamente de amnesia; sin

21 MAQ. CAP. 18(F0694).indd 712 8/10/07 1:24:12 AM


18.1 Fallas, averías y recuperación 713

embargo, podrán convertirse en fallas de no amnesia usando técnicas de software. Fallas de


comunicación son causadas por fallas de ligas o transmisiones. Éstas son fallas de no amnesia
porque el software de la red incluye la suficiente capacidad de almacenamiento intermedio y
manejo de errores para asegurar que no se pierden mensajes.
A continuación analizaremos cómo se manejan las fallas bizantinas en la práctica. El resto
del capítulo supone que las fallas son no bizantinas.

18.1.2 Vista general de las técnicas de recuperación

Para las fallas no bizantinas, la recuperación implica restaurar un sistema o una aplicación a
un estado consistente; no implica deshacer acciones equivocadas. Las técnicas de recuperación
pueden ser clasificadas en recuperación de datos, recuperación de procesos, tolerancia de fallas
y resiliencia. Estas técnicas tienen diferentes implicaciones para la confiabilidad, tiempos de
respuesta a computaciones y costo de recuperación. La tabla 18.1 resume sus características.

Tabla 18.1 Técnicas de recuperación

Técnica Descripción
Recuperación Un respaldo es un registro del estado de un archivo. Cuando ocurre una falla, el
de datos estado del archivo se fija al estado que se encontró en su respaldo más reciente
(véase la sección 13.11).
Recuperación Un punto de control es un registro del estado de un proceso y sus actividades de
de procesos procesamiento de archivos. Se recupera un proceso fijando su estado al mismo
que se encontró en un punto de control que fue tomado antes de que ocurriera
una falla. Esta acción se llama roll-back.
Tolerancia de fallas El error en el estado causado por una falla se corrige sin interrumpir la opera-
ción del sistema.
Resiliencia Se realiza la tolerancia de fallas y algunos resultados que se produjeron en una
computación antes de que ocurriera una falla son usados después de ella en
la computación.

Las técnicas de recuperación de datos para protegerse contra la pérdida de datos en un


archivo por medio de respaldos. Los respaldos se realizan periódicamente. Cuando ocurre una
falla, se restaura un archivo al estado encontrado en su más reciente respaldo (véase la sección
13.11). Por tanto, las técnicas de recuperación provocarán considerables costos de reejecución
si los respaldos se producen con intervalos grandes. Sin embargo, tomar respaldos con más
frecuencia causará una mayor carga general durante la operación normal. La decisión sobre
la frecuencia de respaldos involucra un sacrificio. Los tiempos de respuesta de aplicaciones se
degradarán considerablemente si los costos de reejecución son altos.
Las técnicas de recuperación de procesos emplean puntos de control para registrar el estado
de un proceso y sus actividades de procesamiento de archivos. Esta operación se llama check-
pointing. Cuando ocurre una falla, el procedimiento de recuperación fija el estado en el estado
que se encontró en un punto de control guardado antes de la falla. Esta operación se llama el roll-
back del proceso. Provoca el costo de la reejecución de computaciones que fueron procesados

21 MAQ. CAP. 18(F0694).indd 713 8/10/07 1:24:12 AM


714 CAPÍTULO 18 Recuperación y tolerancia de fallas

después de que se guardara el último punto de control. Las concesiones mutuas entre el costo de
un roll-back y la carga general del checkpointing durante la operación normal del sistema son
análogas a las de las técnicas de recuperación de datos.
Las técnicas de tolerancia de fallas permiten que un sistema o una aplicación continúen su
operación a pesar de la ocurrencia de una falla. Una técnica de tolerancia de fallas recupera el
sistema o la aplicación a un estado consistente que difiere sólo marginalmente, si acaso, de su
estado en el momento de la ocurrencia de la falla. Posiblemente se pierdan los resultados de algu-
nas computaciones que estuvieron en ejecución en el momento de la falla. Estas computaciones
tendrán que reejecutarse.
Las técnicas de resiliencia aseguran que algunos de los resultados que fueron producidos
por una computación que estuvo en operación cuando ocurrió una falla se usarán en la compu-
tación después de la falla. Esto reduce los costos de reejecución y la degradación de tiempos de
respuesta debidos a una falla.

Recuperación hacia atrás y hacia delante Los enfoques de recuperación se dividen en


dos clases amplias. Recuperación hacia atrás implica restaurar el estado de una entidad o una
aplicación afectada por una falla a algún estado anterior y reanudar su operación a partir de ese
estado. Implica la reejecución de algunas acciones que fueron realizadas antes de una falla. La
recuperación hacia delante se basa en la reparación del estado erróneo de un sistema a fin
de restaurar la normalidad. El costo de la reparación depende de la naturaleza de la computación
y puede involucrar una determinada cantidad de reejecuciones.
La recuperación hacia atrás es más fácil de implementar que la recuperación hacia delante.
Sin embargo, esto supone que el registro de estados sea tanto factible como práctico. Este as-
pecto presenta unas dificultades obvias en un sistema distribuido. Otro punto débil de la técnica
de recuperación hacia atrás es que una aplicación posiblemente no progrese mucho si ocurren
fallas frecuentemente. Una ventaja principal de la recuperación hacia delante es que la operación
de un sistema o una aplicación continúe a partir del estado reparado en lugar de en algún estado
previo, como es el caso en la recuperación hacia atrás. Esta característica garantiza el progreso
hacia delante de una computación con tiempo para ciertas clases de fallas.

18.2 FALLAS BIZANTINAS Y PROTOCOLOS


DE ACUERDO

Debido a la dificultad para deshacer acciones equivocadas, la recuperación de fallas bizantinas


se ha estudiado solamente en el contexto limitado de acuerdos entre procesos. El problema del
acuerdo es motivado por el problema de los generales bizantinos donde un grupo de generales
tiene que decidir atacar al enemigo. Los generales y sus ejércitos están ubicados en diferen-
tes posiciones geográficas y, por ende, los generales tienen que depender en el intercambio de
mensajes para llegar a una decisión. Las posibles fallas son que se pueden perder mensajes o
que algunos generales podrán ser traidores que deliberadamente envían mensajes confusos. Un
protocolo de acuerdo se diseña para llegar a un acuerdo a pesar de estas fallas.
En la literatura sobre tolerancia de fallas se han definido tres problemas de acuerdos. En
el problema de acuerdo bizantino, un proceso inicia el protocolo de acuerdo anunciando un
solo valor a todos los demás procesos. Un proceso que recibe el valor lo anuncia a otros. Un

21 MAQ. CAP. 18(F0694).indd 714 8/10/07 1:24:12 AM


18.3 Recuperación 715

proceso sin falla anuncia el mismo valor que recibe. Un proceso defectuoso podrá anunciar
un valor arbitrario, e incluso enviar diferentes valores a diferentes procesos. Los procesos
posiblemente tendrán que ejecutar muchas vueltas de anuncios hasta que pueda llegarse a un
acuerdo. El problema requiere que todos los procesos sin falla se pongan de acuerdo sobre
el mismo valor. Ése deberá ser igual al valor anunciado por el iniciador si éste es un proceso
sin falla; de no ser así, podrá ser cualquier valor. En el problema de consenso, cada pro-
ceso tiene su propio valor inicial y todos los procesos sin falla tienen que ponerse de acuer-
do sobre un valor común. En el problema de consistencia interactiva, los procesos sin falla
deben ponerse de acuerdo sobre un conjunto de valores. Analizaremos sólo el problema de
acuerdo bizantino.
Lamport et al. (1982) desarrollaron un protocolo de acuerdo para casos donde los procesos
podrán fallar, pero los mensajes se entregan sin falta. El protocolo involucra m  1 vueltas de
intercambio de informaciones, donde el número de procesos defectuosos es  m. Sin embar-
go, hay algunas restricciones acerca del valor de m. Un acuerdo sólo es posible si el número
total de procesos excede tres veces el de procesos defectuosos. Un resultado de imposibilidad
declara que un grupo de tres procesos que incluye un proceso defectuoso no puede llegar a un
acuerdo.
El resultado de imposibilidad es fácil de demostrar si el iniciador es un proceso defectuoso.
Supongamos que el proceso P1, el iniciador, envía los valores 0 y 1 a los procesos P2 y P3. El
proceso P2 enviará 0 al proceso P3. Entonces el proceso P3 ha recibido dos valores distintos de
dos procesos. No puede decidir cuál de los dos es el correcto. Una situación parecida se presenta
si P1 es un iniciador sin falla y envía 1 a P2 y P3, pero el proceso P2 es defectuoso y envía 0 al
proceso P3. Un acuerdo habría sido posible si el sistema contenía n procesos, n  4, y se usará
el siguiente algoritmo:

1. El iniciador envía su valor a cada dos procesos.


2. Un proceso que recibe el valor del iniciador lo envía a todos los demás procesos excepto
a sí mismo y al iniciador.
3. Cada proceso forma una colección de n  1 valores que contiene un valor recibido del
iniciador en el paso 1 y n  2 valores recibidos de otros procesos en el paso 2. Si no
recibió un valor del iniciador o de algún otro proceso, supondrá un valor arbitrario 0. El
proceso usa el valor que aparece la mayoría de las veces en esta colección.

Éste es el algoritmo que se va a seguir para una falla bizantina única, es decir, para m  1. El
algoritmo para m  1 es bastante complejo; por tanto, no lo discutiremos aquí.

18.3 RECUPERACIÓN

Un método de recuperación consiste en dos componentes. El algoritmo del punto de control


decide cuándo y cómo crear puntos de control de procesos. Usaremos la notación Cij para de-
notar el j-ésimo punto de control tomado por el proceso Pi. El algoritmo de recuperación usa
los puntos de control para regresar procesos, de tal modo que los nuevos estados de procesos

21 MAQ. CAP. 18(F0694).indd 715 8/10/07 1:24:12 AM


716 CAPÍTULO 18 Recuperación y tolerancia de fallas

son mutuamente consistentes. El ejemplo 18.2 ilustra el problema fundamental en el diseño de


algoritmos de puntos de control y recuperación.

C11 C12 C13


P1
m1
C21 C22 C23
P2
m2 m3
C31 C32
P3
tf

Figura 18.3 Puntos de control de procesos en un sistema distribuido.

Ejemplo 18.2 La figura 18.3 muestra el diagrama de tiempos de una computación distribuida. C11,
C12 y C13 son los puntos de control tomados por el proceso P1. Del mismo modo, C21, C22 y C23
y C31, C32 son los puntos de control tomados por los procesos P2 y P3, respectivamente. Denotamos
el estado registrado en <checkpoint> como state(<checkpoint>). Supongamos que los procesos P1,
P2 y P3 estén en los estados s1, s2 y s3, respectivamente, en el instante de tiempo tf. Por tanto, la
computación distribuida está en el estado S ⬅ {s1, s2 s3}. Supongamos que una falla ocurre en el
nodo N3 en el instante de tiempo tf. Un algoritmo de recuperación ingenuo simplemente regresará
el proceso P3 a su último punto de control, es decir, C32. Sin embargo, el nuevo estado de la compu-
tación, a saber {s1, s2, state(C32)}, no es un estado consistente porque P2 ha recibido el mensaje m3
en el estado s2, pero P3 no ha enviado m3 en state(C32) (véase la definición 17.1).

El ejemplo 18.2 deja claro que el estado de un proceso no puede ser recuperado en aisla-
miento. Por ende, un algoritmo de recuperación deberá restaurar el estado de la computación a
un estado S, en el cual los estados de todos los pares de procesos son mutuamente consistentes
según la definición 17.1. Por tanto, el objetivo de un algoritmo de recuperación es tomar las
siguientes decisiones para cada proceso Pi en una computación distribuida:
1. Decidir si el proceso Pi deberá ser regresado.
2. De ser así, identificar un punto de control Cij al que Pi deberá ser regresado.
En el ejemplo 18.2, la computación distribuida se podía recuperar al estado {s1, state(C22),
state(C32)}. A continuación analizaremos una base para tal recuperación.

Definición 18.1 (Mensaje huérfano) Un mensaje mk que es enviado por el proceso Pi al


proceso Pj es un mensaje huérfano en el nuevo estado S ⬅ {s1, . . . si, . . . sj. . . sk} de un sis-
tema durante la recuperación si sj, el nuevo estado del proceso Pj registra mk como recibido,
pero si, el nuevo estado del proceso Pi no lo registra como enviado.

Un mensaje huérfano es un mensaje que ha sido recibido por el proceso destinatario, pero
es rechazado por su transmisor debido a la recuperación. Por tanto, los estados de sus procesos
transmisor y destinatario son inconsistentes. Esta inconsistencia se elimina regresando su proce-
so destinatario al mismo estado en el que no había recibido el mensaje huérfano. Lo anterior se

21 MAQ. CAP. 18(F0694).indd 716 8/10/07 1:24:12 AM


18.4 Técnicas de tolerancia de fallas 717

llama efecto dominó. En el ejemplo 18.2, m3 se convierte en un mensaje huérfano cuando P3 es


regresado al estado en C32. Por ende, P2 se deberá regresar a un punto de control que fue tomado
antes de que P2 recibió el mensaje m3, por ejemplo, al punto de control C22. Si el proceso P2
envía un mensaje m4 a P1 después de que C22 y el proceso P1 hubieran recibido este mensaje en
el estado s3, el efecto dominó forzará también un roll-back del proceso P1.
Usando estas ideas, checkpointing y recuperación pueden llevarse a cabo en una de dos
formas. El algoritmo de checkpointing permitirá que procesos tomen puntos de control a vo-
luntad. Este método se denomina checkpointing asíncrono. En caso de una falla, el algoritmo
de recuperación regresará procesos uno por uno de acuerdo con el efecto dominó. En forma
alternativa, el algoritmo de checkpointing coordinará las acciones de checkpointing de proce-
sos para asegurar que los estados de procesos en los puntos de control sean mutuamente con-
sistentes. Este método se llama checkpointing síncrono y la colección de puntos de control de
procesos que esto produce se denomina punto de control síncrono. Cuando se aplica al sistema
de la figura 18.3, un algoritmo de checkpointing síncrono producirá el punto de control síncro-
no {C11, C21, C31} o el punto de control síncrono {C12, C22, C32}. El algoritmo simplemente
regresará a cada proceso a su punto de control individual en el más reciente punto de control
síncrono.

18.4 TÉCNICAS DE TOLERANCIA DE FALLAS

El principio básico en la tolerancia de fallas es asegurar que una falla no provoque un error,
o que el error pueda eliminarse fácilmente. En algunos de los anteriores capítulos y secciones
vimos cómo las técnicas de tolerancia de fallas aseguran que no se produzca un error en el
estado debido a fallas de proceso, almacenamiento o comunicación: la sección 18.2 describió
cómo las fallas de naturaleza bizantina pueden tolerarse, la sección 13.11.2.2 analiza cómo la
técnica de almacenamiento estable tolera fallas de almacenamiento y la sección 16.5 estudia
un arreglo que involucra la confirmación y retransmisión de mensajes para tolerar fallas de
comunicación.
En esta sección analizaremos dos facetas de tolerancia de fallas de sistema que siguen el
modelo de fail-stop.

• Tolerancia de fallas para datos replicados: Pese a una falla, los datos deberán estar dis-
ponibles y las aplicaciones deberán ver valores que resultan de la más reciente operación
de actualización.
• Tolerancia de fallas para datos distribuidos: Pese a una falla, la consistencia mutua de
diferentes partes de los datos no deberá verse afectada.

18.4.1 Bitácoras, recuperación hacia delante


y recuperación hacia atrás
Una bitácora es un registro de acciones o actividades en un proceso. En la práctica se usan dos
tipos de bitácoras:
• Bitácoras de hacer: Una bitácora de hacer registra aquellas acciones que deberán llevar-
se a cabo para asegurar la corrección del estado de una entidad o sistema. Una bitácora de
hacer también se llama bitácora de rehacer porque las acciones que se registran en ella

21 MAQ. CAP. 18(F0694).indd 717 8/10/07 1:24:13 AM


718 CAPÍTULO 18 Recuperación y tolerancia de fallas

pueden realizarse más de una vez si una falla ocurre. Las bitácoras de hacer se usan para
implementar la recuperación hacia delante.
• Bitácoras de deshacer: Una bitácora de deshacer contiene un registro de aquellas accio-
nes que deberán deshacerse para eliminar un error de estado causado por la ocurrencia
de una falla. Las bitácoras de deshacerse usan la recuperación hacia atrás para imple-
mentar.

Un principio de write-ahead logging (registro antes de la escritura) se usa para construir una
bitácora: un proceso escribe una acción que va a ser realizada o una imagen de datos que va a
ser usada en la bitácora antes de ejecutar acciones relevantes. De este modo, la bitácora conten-
drá todas las informaciones necesarias para lograr el estado correcto si ocurre una falla. Cada
bitácora podrá ser un registro de operaciones, que contiene una lista de acciones, o un registro
de valores, que contiene una lista de valores o imágenes de datos. El método de implementación
para una acción atómica que se analizó en la sección 13.11.2.2 usaba una lista de intenciones. La
lista de intenciones es un registro de valores que se emplea como una bitácora de rehacer. Provee
la idempotencia, la cual se necesita porque las entradas en la bitácora serán procesadas varias
veces si ocurre más de una falla durante el procesamiento de la transacción. Si las subacciones en
una acción atómica actualizaron datos en forma directa, deberá llevarse una bitácora de deshacer
para que puedan deshacerse las acciones si ocurriese una falla antes de que la acción atómica
pueda dividirse. La bitácora de deshacer contendrá imágenes de datos tomadas antes de que se
realizaran actualizaciones.
La idea de una ejecución atómica de una secuencia de operaciones en un archivo puede
extenderse a operaciones que involucran varios archivos. Un lenguaje de programación o un len-
guaje de consulta de bases de datos provee una característica denominada transacción atómica
para este propósito. Tiene la siguiente sintaxis:

begin transaction <transacción id>


{Acceder y modificar archivos}
if <condición>
then abort transaction;
{Acceder y modificar archivos}
end transaction <transacción id>

Una transacción atómica tiene una propiedad de todo o nada, igual que una acción ató-
mica. Su ejecución comienza cuando un proceso ejecuta el enunciado begin transaction. Se
dice que la transacción atómica se comisiona si el proceso ejecutó el enunciado end transac-
tion. En ese momento se actualizarán en forma consistente todos los archivos modificados por
la transacción atómica. Si el proceso ejecutara el enunciado abort transaction, o si una falla
ocurriese antes de que se comisione la transacción, la ejecución de ésta será cancelada y no
se realizarán actualizaciones de archivos. En este caso, todos los archivos se quedarán en sus
estados originales.

18.4.2 Manejo de datos reproducidos

La disponibilidad de los datos D puede proveerse por medio de la reproducción. Podemos hacer
n copias de D, n  1 y colocarlas estratégicamente en el sistema, de tal forma que por lo menos
una copia de D será accesible desde cualquier nodo a pesar de las fallas anticipadas en el siste-

21 MAQ. CAP. 18(F0694).indd 718 8/10/07 1:24:13 AM


18.4 Técnicas de tolerancia de fallas 719

ma. Si los datos D pueden ser modificados, es esencial usar reglas que aseguren la corrección
del acceso y realizaciones de datos. Usaremos las siguientes:

1. Muchos procesos pueden leer D en forma concurrente.


2. Sólo uno puede escribir nuevo(s) valor(es) en D en un momento dado.
3. La lectura y escritura no pueden realizarse en forma concurrente.
4. Un proceso que lee D debe ver su último valor.

Las reglas 1 a 3 son análogas a las del problema de lectores y escritores de la sección 6.7.2. La
regla 4 aborda un problema especial en la reproducción de datos.

Algoritmos de quórum Un quórum es el número de copias de D que deben ser accedidos


para realizar una operación específica en D. Los algoritmos de quórum aseguran el cumplimiento
de las reglas 1 a 4 mediante la especificación de un quórum de lectura Qr y un quórum de escritu-
ra Qw. Se usan dos tipos de candados en D. Un candado de lectura es compartido, y un candado
de escritura es exclusivo. Un proceso que solicita un candado de lectura obtiene el candado si D
está actualmente desbloqueado o si ya se encuentra bajo un candado. Sólo se concede la solicitud
para un candado de escritura si D está actualmente desbloqueado. Procesos usan quórums de
lectura y escritura mientras acceden a D, por lo que un proceso puede leer D después de colocar
un candado de lectura en las copias Qr de D, y puede escribir D después de colocar un candado
de escritura en las copias Qw de D.
Puesto que un candado de lectura es compartido, cualquier valor de Qr cumplirá con la regla
1. Para implementar las reglas 2 y 3 elegiremos a Qr y Qw, de tal modo que

2 Qw  n (18.1)
Qr  Q w  n (18.2)

La ecuación 18.2 también asegura que un lector siempre bloqueará por lo menos una copia que
participó en la última operación de escritura. Esta copia contiene el valor más reciente de D, por
lo que esa ecuación también cumple con la regla 4.
Una selección de valores que satisfaga las ecuaciones (18.1)-(18.2) es Qr  1 y Qw  n.
Con estos quórums una operación de lectura es mucho más rápida que una de escritura. Esto será
apropiado si operaciones de lectura fuesen más frecuentes que operaciones de escritura. También
son posibles muchos otros valores de quórum. Si las operaciones de escritura son más frecuentes
podremos seleccionar valores de Qr y Qw de tal forma que se cumpla con las ecuaciones (18.1)-
(18.2) y que Qw sea lo más pequeño posible. Si Qw
n, un escritor no actualizará todas las copias
de D, por lo que un lector accederá a algunas copias de D que contienen sus valores más recien-
tes y a otras que contienen sus valores viejos. Para ser capaz de identificar el valor más reciente,
podemos asociar un sello de tiempo con cada copia de D para indicar cuándo fue modificada por
última vez.
La selección de Qr  1 y Qw  1 no es tolerante a fallas. Qw  n implica que un proceso
tendrá que poner candados en todas las n copias de D a fin de realizar una operación de escritura.
Por tanto, un escritor será incapaz de escribir si tan sólo un nodo que contiene una copia de D
fallara o estuviese inaccesible para él. Si se requiere que un sistema tolere fallas en un total de
hasta k nodos, podemos elegir

21 MAQ. CAP. 18(F0694).indd 719 8/10/07 1:24:13 AM


720 CAPÍTULO 18 Recuperación y tolerancia de fallas

Qr  k  1
Qw  n  k, y
n 2 k.

Estos tamaños de quórums son grandes, pero es inevitable porque la ecuación (18.1) es esencial
para asegurar la consistencia de datos y la ecuación (18.2) lo es para asegurar que las operacio-
nes de lectura y escritura no se realicen en forma concurrente.

18.4.3 Manejo de datos distribuidos

Una transacción distribuida (que también se denomina transacción multisitio) es una facili-
dad para manipular archivos ubicados en diferentes nodos de un sistema distribuido en forma
mutuamente consistente. Cada nodo que participa en la transacción contiene un administrador
de transacciones. Este administrador lleva informaciones sobre actualizaciones de datos que
van a realizarse por parte de la transacción, que puede ser parecido a la lista de intenciones
de transacciones atómicas (véase la sección 13.11.2.2). Además, también lleva una bitácora
que es local para él. El nodo donde la transacción fue iniciada contiene un coordinador de
transacciones. El coordinador implementa la propiedad de todo o nada de transacciones por
medio del protocolo de comisión en dos fases, que también se conoce como protocolo 2PC.
Inicia este protocolo cuando la aplicación ejecuta el enunciado end transaction Ti. En la prime-
ra fase, el protocolo verifica si cada nodo participante puede comisionar las actualizaciones
de la transacción. Basándose en las respuestas de los nodos participantes, decide si va a co-
misionar o a abandonar la transacción. En la segunda fase comunica su decisión a cada nodo
participante, por lo que pudiera comisionar o abandonar como corresponde. El protocolo 2PC
se presenta como el algoritmo 18.1.

Algoritmo 18.1 (Protocolo de transacción de dos fases)

Fase 1:
1. Acciones del coordinador de transacciones: Escribe el registro prepare Ti en la bitácora.
Fija un intervalo de tiempo y envía un mensaje prepare Ti a cada nodo participante. Es-
pera hasta que cada nodo participante responda o hasta ocurra un intervalo de tiempo.
2. Acciones de un nodo participante: Al recibir un mensaje prepare Ti, el nodo participante
decide si está listo para comisionar. De ser así, escribe informaciones sobre actualiza-
ciones de datos a realizar, seguido por el registro prepared Ti en su bitácora y envía un
mensaje prepared Ti al coordinador. De lo contrario escribe el registro abandoned Ti en
su bitácora y envía una respuesta abandoned Ti al coordinador.
Fase 2:
1. Acciones del coordinador de transacciones: Si cada nodo participante envió una res-
puesta prepared Ti, escribe el registro commit Ti en su bitácora y envía un mensaje
commit Ti a cada nodo participante. De lo contrario escribe el registro abort Ti en su
bitácora y envía un mensaje abort Ti a cada nodo participante. En todo caso espera hasta
recibir una confirmación de cada nodo participante, y escribe un registro complete en su
bitácora.

21 MAQ. CAP. 18(F0694).indd 720 8/10/07 1:24:14 AM


18.5 Resiliencia 721

2. Acciones de un nodo participante: Escribe el registro commit Ti o abort Ti en la bitácora


de acuerdo con el mensaje del coordinador, y envía una confirmación al coordinador.
Según el mensaje del coordinador, realiza el procesamiento de comisión o cancela el
procesamiento y suelta los candados sobre los datos.

El protocolo 2PC maneja la avería de un nodo participante de la siguiente forma: si un


nodo participante fallara antes de que el protocolo 2PC fuera iniciado por el coordinador, no
hubiese enviado una respuesta prepared al coordinador en la primera fase del protocolo. Por con-
siguiente, el coordinador cancelará la transacción. Cuando el nodo participante se recupera, no
encontrará un registro prepared o abandoned para la transacción en su bitácora. Supondrá que
la primera fase del protocolo 2PC habrá agotado su tiempo de espera y el coordinador habrá
cancelado la transacción. Por tanto cancelará la transacción. Esta transacción es segura porque
un nodo participante puede retirarse unilateralmente de una transacción en cualquier momento
antes de enviar una respuesta prepared en la primera fase. Si el nodo participante falla después
de enviar una respuesta prepared o abandoned al coordinador, encontrará un registro prepa-
red o abandoned en su bitácora cuando se recupera. Ahora tendrá que consultar al coordinador
para saber si la transacción fue comisionada o cancelada, y en consecuencia debe realizar el
procesamiento de comisión o cancelación. Si el nodo falla mientras estuvo ejecutando el pro-
cesamiento de comisión, encontrará un registro de comisión en su bitácora cuando se recupera.
Por ende repetirá el procesamiento de comisión. Recuerde que en la sección 13.11.2.2 dijimos
que el procesamiento de comisión repetido no causará problemas de consistencia de datos si las
operaciones de actualización de datos realizadas durante el procesamiento de comisión fueren
idempotentes.
Si el coordinador falla después de escribir el registro commit en su bitácora, pero antes de
escribir el registro complete en ella, verá en su bitácora cuando se recupera el registro commit.
Ahora reenviará mensajes commit Ti a todos los nodos participantes porque no sabrá si había en-
viado estos tipos de mensajes antes de su avería. Sin embargo, este requerimiento representa un
punto débil en el protocolo 2PC. Si el coordinador hubiera fallado antes de enviar los mensajes
commit Ti, los nodos participantes no sabrían si el coordinador decidió comisionar o cancelar
la transacción. Cualquier nodo participante que haya enviado una respuesta abandoned Ti en la
primera fase sabrá que la decisión no podrá ser comisionar la transacción; sin embargo, un nodo
que haya enviado un mensaje commit Ti o abort Ti será bloqueado hasta que el coordinador se
recupere y envíe un mensaje commit Ti o abort Ti. Puede usarse un protocolo de comisión de tres
fases para evitar esta situación de bloqueo.

18.5 RESILIENCIA

Las técnicas de resiliencia se enfocan en minimizar el costo de reejecución cuando ocurren fa-
llas. La base de la resiliencia es la propiedad por la cual las averías en un sistema distribuido son
parciales, no totales, por lo que algunas partes de una programación distribuida, o los resultados
computados por ellas, podrán sobrevivir a una avería. El uso de tales resultados podrá reducir, e
incluso evitar, la reejecución. Considere una transacción distribuida que es iniciada en el nodo
Ni e involucra computaciones en los nodos Ni y Nj. La transacción será cancelada si el adminis-
trador de transacciones en el nodo Nj no responde al mensaje prepare del coordinador en el nodo

21 MAQ. CAP. 18(F0694).indd 721 8/10/07 1:24:14 AM


722 CAPÍTULO 18 Recuperación y tolerancia de fallas

Ni por la avería del nodo Nj o la liga (Ni, Nj). La transacción cancelada tendrá que reejecutarse
en algún otro momento. Gran parte de la reejecución será un derroche si el nodo Nj ya hubie-
ra completado la transacción pero simplemente era incapaz de participar en el procesamiento
de comisión debido a una avería.
Una transacción anidada Tik es una transacción atómica que forma parte de otra transacción
Ti. Las transacciones Ti y Tik tienen una relación padre/hijo. La transacción anidada puede comi-
sionar o cancelar igual que una transacción atómica, con una diferencia: cuando llega al punto de
comisión, se realiza una comisión tentativa para ella. Una comisión tentativa es un estado inter-
medio entre no comisionado y comisionado. La bitácora de la transacción tentativa queda escrita
en almacenamiento estable; sin embargo, no se procesa en ese momento. La verdadera comisión
de la transacción anidada, que involucra el procesamiento de la bitácora, se mantiene en desuso
hasta que se comisiona la transacción del padre. Cuando una transacción del padre llega a su
punto de comisión, se comisiona usando un protocolo de comisión en dos fases para asegurar
que todas sus transacciones hijas pueden comisionar. Se asignan id únicas de transacción a las
transacciones anidadas para facilitar este paso.
La resiliencia que usa transacciones anidadas se implementa de la manera siguiente: consi-
dere una transacción Ti que ejecuta en el nodo Ni e inicia una transacción anidada Tik en el nodo
Nj. Supongamos que Nj se bloquee y se recupere inmediatamente. El coordinador de transaccio-
nes en el nodo Ni podrá darse cuenta que la transacción anidada Tik tarda demasiado tiempo en
finalizar o que el administrador de transacciones en el nodo Nj no está respondiendo a su mensaje
prepare, por lo que podrá decidir iniciar nuevamente a Tik, en el mismo nodo Nj o en otro. Si
reinicia a Tik en el nodo Nj, el administrador de transacciones verificará si Tik fue iniciado allí en
el pasado y si había realizado una comisión tentativa. De ser así, no iniciará Tik porque ya tiene
los resultados de Tik en la bitácora; de lo contrario iniciará a Tik como fue deseado. En todo caso,
Tik comisionará cuando comisiona la transacción paterna Ti.
Si Ti hubiera reiniciado la transacción anidada en otro nodo, la transacción Tik del nodo Nj
se hubiera vuelto huérfana. Deberá impedirse que realice una comisión tentativa, puesto que su
transacción paterna ya no está interesada en ella. A fin de llevar esto a cabo, el coordinador lleva
una lista de id de transacciones anidadas para cada transacción. Cuando el coordinador inicia la
transacción anidada Tik, agregará la id de Tik a la lista para la transacción Ti, y cuando reinicia
la transacción anidada en otro nodo, borrará a Tik de su lista y agregará la id de la nueva transac-
ción anidada. Cuando Tik desea ejecutar una comisión tentativa, su administrador de transaccio-
nes revisará con el coordinador si la id de Tik está presente en la lista para la transacción Ti. Sólo
permitirá que se lleve a cabo una comisión tentativa si éste es el caso.

EJERCICIO 18
1. Se dice que un punto de control está fuertemente consistente i) si los estados de todos los pares de
procesos están mutuamente consistentes y ii) si cada mensaje registrado como enviado por un proceso
transmisor se registra como recibido por un proceso receptor. Analice si un punto de control síncrono
es tanto consistente como fuertemente consistente.
2. Los procesos en una computación distribuida realizan las revisiones asíncronas en puntos de control
de la siguiente forma: cada proceso toma un punto de control inmediatamente después de enviar un
mensaje. Demuestre que se puede realizar la recuperación por medio de estos puntos de control sin
enfrentarse al efecto dominó.

21 MAQ. CAP. 18(F0694).indd 722 8/10/07 1:24:14 AM


Bibliografía 723

3. ¿Pueden surgir mensajes huérfanos si un proceso toma un punto de control antes de recibir cada men-
saje?
4. ¿Puede el uso de quórums de lectura y escritura determinados por la ecuación (18.2) llevar a bloqueos
mutuos? De ser así, desarrolle un método para evitar bloqueos mutuos.
5. Debido a grandes tamaños de quórums en el manejo de datos reproducidos, se propone usar un plantea-
miento basado en la noción de conjuntos de solicitudes de Maekawa (véase la sección 18.3.1). Discuta
si se cumplirán las 4 reglas de la sección 18.4.2 mediante este planteamiento.
6. Cuando se usan puntos de control asíncronos, varios puntos de control para cada proceso necesitan ser
conservados para roll-backs en caso de presencia de mensajes huérfanos. A fin de conservar espacio
en disco es útil saber cuándo (si acaso) se puede borrar un punto de control específico sin afectar la
recuperación. Comente sobre las siguientes propuestas:
a) Borrar un punto de control Cij cuando se toma otro punto de control para el proceso Pi.
b) Borrar un punto de control Cij si se toma otro punto de control Cij1 para el proceso Pi y ningún
mensaje fue enviado por Pi entre los dos puntos de control.
c) Borrar un punto de control Cij si se toma otro punto de control Cij1 para el proceso Pi y ningún
mensaje fue recibido por Pi entre los dos puntos de control.
d) Borrar todos los puntos de control para el proceso Pi tomados previo al punto de control Cij si para
cada mensaje mk registrado como recibido en Cij, el proceso que envió el mensaje mk ha tomado un
punto de control después de enviarlo.

BIBLIOGRAFÍA
Lamport et al. (1982) analizan el problema de los generales bizantinos. Barborak et al. (1993) estudian
enfoques que pueden usarse para obtener acuerdos sobre un estado de sistema mediante el segmento libre
de fallas de la población de procesadores. Lynch (1996), Tel (2000) y Garg (2002) hablan del consenso en
sistemas síncronos y asíncronos.
El protocolo de comisión en dos fases se estudia en Gray (1981). El protocolo de comisión en tres
fases evita el problema de bloqueo del protocolo de comisión en dos fases cuando falla el coordinador. Esto
permite que los nodos participantes avancen este tipo de transacciones hacia la finalización o las regresan
hacia la cancelación. El protocolo de comisión en tres fases se analiza en Skeen (1983). Svoboda (1984)
aborda el tema de resiliencia en la computación distribuida.
Venkatesh et al. (1987) estudia el checkpointing óptimo y la recuperación libre del efecto dominó. Has-
ta la fecha, este tema es objeto de muchas investigaciones. Tel (2000) habla de la tolerancia a fallas en siste-
mas distribuidos. Garg (2002) analiza la recuperación basada en checkpointing y el registro de mensajes.

1. Barborak, M., M. Malek y A. Dahbura (1993): “The consensus problem in fault tolerant compu-
ting”, Computing Surveys, 25, 2, 171-220.
2. Garg, V.K. (2002): Elements of Distributed Computing, Wiley-IEEE.
3. Gray, J.N. (1981): “The transaction concept: virtues and limitations”, Proceedings of the Interna-
tional Conference on Very Large Data Bases, 144-154.
4. Lamport, L., R. Shostak y M. Pease (1982): “The Byzantine generals problem”, ACM Transac-
tions on Programming Languages and Systems, 4 (3), 382-401.
5. Lynch, N. (1996): Distributed Algorithms, Morgan Kaufmann.
6. Skeen, D. (1983): “A formal model of crash recovery in a distributed system”, IEEE Transactions
on Software Engineering, 9 (3), 219-228.

21 MAQ. CAP. 18(F0694).indd 723 8/10/07 1:24:14 AM


724 CAPÍTULO 18 Recuperación y tolerancia de fallas

7. Svobodova, L. (1984): “Resilient Distributed computing”, IEEE Transactions on Software Engi-


neering, 10 (3), 257-267.
8. Tel, G. (2000): Introduction to Distributed Algorithms, 2a. ed., Cambridge University Press, Cam-
bridge.
9. Venkatesh, K., T. Radhakrishnan y H.F. Li (1987): “Optimal checkpointing and local recording for
domino-free rollback recovery”, Information Processing Letters, 25 (5), 295-304.

21 MAQ. CAP. 18(F0694).indd 724 8/10/07 1:24:14 AM


Capítulo
19
Sistemas de archivos
distribuidos

Los usuarios de un sistema de archivos distribuidos (DFS) esperan la conveniencia, confiabilidad


y desempeño que proveen los sistemas de archivos convencionales. La conveniencia de usar un
sistema de archivos distribuidos depende de dos asuntos clave. La transparencia de un sistema
de archivos distribuidos hace que los usuarios no se den cuenta de la ubicación de sus archivos
en los nodos y discos del sistema. La semántica de compartición de archivos especifica las reglas
de compartición de archivos, es decir, si las modificaciones de un archivo hechas por un proceso
serán visibles para otros procesos que usan el archivo en forma concurrente y cómo.
Un proceso y un archivo al que accede pueden existir en diferentes nodos de un sistema
distribuido, por lo que una falla en el nodo o en una liga de comunicación entre los dos puede
afectar una actividad de procesamiento del archivo. Los sistemas de archivos distribuidos asegu-
ran una alta confiabilidad mediante la copia de archivos y por medio de un diseño de servidor de
archivos sin estado a fin de minimizar el impacto de caídas de servidores de archivos en activida-
des continuas de procesamiento de archivos. Otro aspecto del desempeño es la escalabilidad: los
tiempos de respuesta no deberán degradar el funcionamiento cuando se agregan nuevos nodos al
sistema distribuido. Esto se resuelve por medio de técnicas que dirigen la transferencia de datos
a secciones de un sistema distribuido que se denominan clústers y que tienen un LAN de alta
velocidad.
Este capítulo analiza técnicas de DFS para la conveniencia del usuario, la confiabilidad y el
alto desempeño. Estudios de casos reales de sistemas de archivos distribuidos ilustran su opera-
ción en la práctica.

19.1 ASUNTOS DE DISEÑO EN SISTEMAS


DE ARCHIVOS DISTRIBUIDOS
Un sistema de archivos distribuidos usa archivos en varios nodos de un sistema distribuido, por
lo que un proceso y un archivo accedido por él a menudo existen en diferentes nodos del sistema
distribuido. Esta situación tiene tres consecuencias probables:

22 MAQ. CAP. 19(F0694).indd 725 8/10/07 1:24:50 AM


726 CAPÍTULO 19 Sistemas de archivos distribuidos

• Puede ser que un usuario tenga que conocer la topología del sistema distribuido para
abrir y acceder a archivos ubicados en varios nodos del sistema.
• Una actividad de procesamiento de archivos en un proceso podrá ser trastornada si ocurre
una falla en el nodo que contiene al proceso, en el nodo al que se accede o en una liga de
comunicación que conecta a los dos.
• Puede ser que el desempeño del sistema de archivos sea bajo debido al tráfico de la red
que está involucrado en el acceso a un archivo.
La necesidad de evitar estas tres consecuencias motiva los tres diseños que se resumen en la
tabla 19.1 y que se analizarán a continuación.

Tabla 19.1 Asuntos de diseño en sistemas de archivos distribuidos

Asuntos de Descripción
diseño
Transparencia La alta transparencia de un sistema de archivos implica que un usuario no tenga
de un sistema de que saber mucho sobre la ubicación de archivos en un sistema. Tiene dos aspectos.
archivos La transparencia de ubicación implica que el nombre del archivo no deberá reve-
lar su ubicación en el sistema de archivos. La independencia de ubicación implica
que deberá ser posible cambiar la ubicación de un archivo sin tener que cambiar
su nombre.
Tolerancia Una falla en un sistema de cómputo o una liga de comunicación podrá trastornar
a fallas las actividades continuas de procesamiento de archivos. Esto afecta la disponi-
bilidad del sistema de archivos y también perjudica la consistencia de datos de
archivos y metadatos, es decir, datos de control del sistema de archivos. Un DFS
deberá emplear técnicas especiales para evitar estas consecuencias de fallas.
Desempeño La latencia de la red es un factor dominante de tiempos de acceso a archivos
en un DFS; esto afecta tanto la eficiencia como la escalabilidad de un DFS. Por
tanto, un DFS usa técnicas para reducir el tráfico de la red generado por accesos
a archivos.

Transparencia de un sistema de archivos Un sistema de archivos encuentra la ubicación


de un archivo durante la resolución de nombres de rutas (véase la sección 7.8.1). Dos temas rele-
vantes en un sistema de archivos distribuidos son: ¿cuántas informaciones acerca de la ubicación
de un archivo deberá reflejarse en su nombre de ruta? y ¿puede un DFS cambiar la ubicación de
un archivo para optimizar el desempeño de acceso a archivos? La noción de transparencia tiene
dos facetas que responden estas cuestiones.
• Transparencia de ubicación: El nombre de un archivo no deberá revelar su ubicación.
• Independencia de ubicación: El sistema de archivos deberá ser capaz de cambiar la ubi-
cación de un archivo sin tener que cambiar su nombre.
La transparencia de ubicación ofrece conveniencia al usuario, puesto que el usuario de una
computación no necesita conocer la ubicación de un archivo. La independencia de ubicación
permite que un sistema de archivos optimice su propio desempeño. Por ejemplo, si los acce-
sos a archivos almacenados en un nodo causan una congestión de la red y esto resulta en un
bajo desempeño, el DFS podrá mover unos archivos a otros nodos. Esta operación se denomina
migración de archivos. La independencia de ubicación también podrá usarse para mejorar la

22 MAQ. CAP. 19(F0694).indd 726 8/10/07 1:24:50 AM


19.1 Asuntos de diseño en sistemas de archivos distribuidos 727

utilización de medios de almacenamiento en el sistema. Analizaremos estas dos facetas de trans-


parencia en la sección 19.2.

Tolerancia a fallas Una falla trastorna una actividad continua de procesamiento de archi-
vos y, por tanto, amenaza la consistencia de datos de archivos y metadatos (datos de control)
del sistema de archivos. Un DFS podrá emplear una técnica de journaling (registros en diarios)
como en un sistema de archivos convencional para proteger la consistencia de metadatos, o bien
un diseño de servidor de archivos sin estados que hace innecesaria la protección de la consisten-
cia de metadatos cuando ocurre una falla. Para proteger datos de archivos podrá echar mano de la
semántica de transacciones que es útil en la implementación de transacciones atómicas (véase
la sección 18.4.1), de tal modo que una aplicación podrá realizar ella misma la tolerancia de
fallas si así lo desea. Analizaremos las cuestiones de tolerancia de fallas en la sección 19.4.

Desempeño El desempeño de un DFS tiene dos facetas: eficiencia y escalabilidad. En un


sistema distribuido, la latencia de la red es el factor dominante que influye en la eficiencia de una
actividad de procesamiento de archivos. La latencia de la red normalmente excede el tiempo de
procesamiento para un registro de archivo y, por tanto, a diferencia de la latencia de dispositi-
vos de E/S, no puede ser ocultada por medio del bloqueo o almacenamiento temporal de regis-
tros. Un DFS emplea la técnica de formación de cachés de archivos, que mantiene una copia de
un archivo remoto en el nodo de un proceso que accede al archivo. De este modo los accesos al
archivo no causan tráfico de la red, aunque deberá impedirse el deterioro de datos en la caché de
un archivo por medio de técnicas de coherencia de la caché. La escalabilidad del desempeño
de DFS requiere que los tiempos de respuesta no se degraden cuando crece el tamaño del siste-
ma debido a la adición de nodos o usuarios. Un sistema distribuido está compuesto de clústers
de sistemas de cómputo que están conectados por LAN de alta velocidad (véase la sección 15.2),
por lo que el caching de una sola copia de un archivo en un clúster es suficiente para reducir el
tráfico de la red entre clústers y para proveer la escalabilidad del desempeño del DFS. Cuando
varios procesos acceden al mismo archivo en paralelo, se emplean técnicas de bloqueo distri-
buido a fin de asegurar que la sincronización de las actividades de procesamiento de archivos
escale bien con un incremento de tamaño del sistema. Analizaremos las técnicas de mejora del
desempeño de DFS en la sección 19.5.

19.1.1 Vista general de la operación DFS


La figura 19.1 muestra lo esencial del procesamiento de archivos en un DFS; el esquema no
muestra ninguna técnica de DFS especial porque no están en discusión aquí. Un proceso en el
nodo N1 abre un archivo con el nombre de ruta ...alpha. A este proceso lo llamamos proceso
cliente de este archivo, o simplemente un cliente de este archivo, y al nodo N1 lo llamamos
nodo cliente. Por medio de la resolución de nombres de rutas, el DFS se da cuenta de que este
archivo existe en el nodo N2, por lo que prepara el arreglo que vemos en la figura 19.1. El com-
ponente del sistema de archivos en el nodo N2 se denomina servidor de archivos y el nodo N2
se denomina nodo servidor. Otros nodos que pudieran estar involucrados en la resolución de
nombres de rutas o en la transferencia de los datos del archivo entre los nodos N1 y N2 se llaman
nodos intermedios.
Nos referimos a este modelo como modelo de procesamiento de archivos remotos. Un arre-
glo análogo a RPC se usa para implementar accesos a archivos por medio de procesos de talón
denominados agente de servidor de archivos y agente del cliente. Cuando el cliente abre el

22 MAQ. CAP. 19(F0694).indd 727 8/10/07 1:24:50 AM


728 CAPÍTULO 19 Sistemas de archivos distribuidos

Nodo N1 Nodo N2
Tabla de archivos activos
fmt
fcbalpha

Agente del Servidor


Proceso Agente servidor de
cliente del cliente cliente archivos

Figura 19.1 Lo esencial del procesamiento de archivos en un DFS.

archivo, la solicitud se entrega al agente del cliente. Éste comunica la solicitud al agente del
servidor de archivos en el nodo N2, quien entrega la solicitud al servidor de archivos. Éste a su
vez abre alpha y construye fbcalpha. Cada vez que el cliente ejecuta una operación de lectura o
escritura sobre alpha, la operación es implementada a través de un mensaje entre el agente del
cliente y el agente del servidor de archivos. En el nodo N2 existen buffers de E/S para el archivo
y sólo un registro a la vez se pasa al cliente.

19.2 TRANSPARENCIA

En un sistema de archivos convencional un usuario identifica un archivo por medio del nombre
de ruta. El usuario está consciente de que el archivo pertenece a un directorio específico; sin em-
bargo, no lo está con respecto a su ubicación en el sistema. El campo de info de ubicación de la
entrada en el directorio del archivo indica la ubicación del archivo en el disco. Este arreglo tam-
bién será adecuado para proveer la transparencia de ubicación en un DFS: un usuario usará un
nombre de ruta para acceder al archivo, y el DFS obtendrá la ubicación del archivo de su entrada
en el directorio. El DFS podrá optar por mantener todos los archivos de un directorio en el mismo
nodo del sistema distribuido o dispersarlos en diferentes nodos. En el primer caso, sus metadatos
serán idénticos a los de un sistema de archivos convencional. En el segundo, el campo de info de
ubicación de la entrada en el directorio de un archivo contendrá un par (id del nodo, ubicación).
Proveer la independencia de ubicación requerirá que la información en el campo de info
de ubicación de la entrada en el directorio de un archivo varíe en forma dinámica. Entonces el
DFS podrá cambiar libremente la ubicación de un archivo, siempre y cuando ponga informa-
ción sobre la nueva ubicación en el campo de info de ubicación de la entrada en el directorio.
Del mismo modo, deberá cambiar la información en todas las ligas al archivo (véase la sección
7.4.1). Para simplificar estos cambios, un DFS podrá usar el siguiente arreglo: a cada archivo se
le asigna una id de archivo globalmente única. La entrada en el directorio del archivo contiene
esta id de archivo. El DFS mantiene una estructura de datos separada para contener los pares
de id/ubicación de archivos. De este modo, el DFS sólo debe cambiar un par en esta estructura de
datos cuando se cambie la ubicación de un archivo.
La mayoría de los sistemas de archivos distribuidos ofrecen la transparencia de ubicación,
pero no la independencia de ubicación. Por tanto, los archivos no pueden migrarse a otros nodos.
Esta restricción impide al DFS optimizar el desempeño de acceso a archivos.

22 MAQ. CAP. 19(F0694).indd 728 8/10/07 1:24:51 AM


19.3 Semántica de compartición de archivos 729

19.3 SEMÁNTICA DE COMPARTICIÓN DE ARCHIVOS

La semántica de la compartición de archivos determina la manera como las manipulaciones


de archivos realizadas por usuarios concurrentes de un archivo serán visibles entre ellos. Re-
cuerde del análisis en la sección 7.9 que todos los clientes que procesan en forma concurrente
un archivo mutable de imagen única tienen la misma vista de sus contenidos, por lo que modi-
ficaciones hechas por un cliente son inmediatamente visibles para otros clientes que procesen
el archivo. Clientes que procesan un archivo mutable de imagen única pueden tener diferentes
vistas de sus contenidos. Cuando terminan sus actividades de procesamiento del archivo, el
sistema de archivos puede conciliar de alguna manera estas vistas para crear una sola imagen o
admitir la existencia de muchas versiones del archivo. En el último caso, tiene que asegurarse
que todo cliente que posteriormente abra el archivo obtendrá acceso a su versión correcta. La
tabla 19.2 resume las características clave de la semántica de Unix, la semántica de sesiones y
la semántica de transacciones.

Tabla 19.2 Características de las semánticas de compartición de archivos

Semántica Descripción
Semántica Unix Se implementa un archivo mutable de imagen única. El efecto de una operación de
escritura en un archivo por parte de un cliente es inmediatamente visible para los
demás clientes del archivo. En forma opcional, los clientes podrán compartir el des-
fase del archivo, es decir, el apuntador hacia el siguiente registro en un archivo.
Semántica de Se implementa un archivo mutable de imagen múltiple. Sólo los clientes en una
sesiones sesión comparten la misma imagen de un archivo. Actualizaciones hechas por
un cliente son visibles para otros en la misma sesión; sólo serán visibles para otros
clientes después de que se cierre el archivo.
Semántica de El procesamiento de archivos realizado por un cliente se implementa como una
transacciones transacción atómica, por lo que se realizan todas las operaciones de un archivo o no
se realiza ninguna. Esta propiedad simplifica la tolerancia a fallas.

Semántica de Unix Cada archivo es un archivo mutable de una sola imagen. Por ello,
actualizaciones hechas por un proceso cliente son visibles para otros procesos clientes. Los pro-
cesos clientes podrán en forma opcional compartir el desfase de un archivo. Esta herramienta
es útil si los clientes comparten el procesamiento de un archivo. La semántica de Unix es fácil
y eficiente de implementar en un sistema de archivos convencional (véase la sección 7.9); sin
embargo, como se analizará en la sección 19.5.2, no son tan fáciles de implementar en un DFS
que usa cachés para archivos.

Semántica de sesiones Una sesión consiste en algunos procesos clientes de un archivo


que se ubican en el mismo nodo de un sistema. Los clientes en una sesión comparten una sola
imagen mutable del archivo. Por ende, el resultado de una operación de escritura realizada por
un proceso cliente es inmediatamente visible para otros clientes en la misma sesión, pero no para
los que están en otras sesiones.
La formación de sesiones y la visibilidad de las imágenes de archivos es gobernada por las
siguientes reglas: supongamos que SFi sea una sesión que involucra un conjunto de clientes

22 MAQ. CAP. 19(F0694).indd 729 8/10/07 1:24:51 AM


730 CAPÍTULO 19 Sistemas de archivos distribuidos

Nodo F F F
Nodo
N1 N2

C C C C C C C C
SF 1 SF 2 SF 3

Figura 19.2 Tres sesiones en un DFS usando la semántica de sesiones.

que procesan el archivo F. Cuando otro cliente ubicado en el mismo nodo abre este archivo,
el DFS permitirá que se una a la sesión SFi si ninguno de los clientes en SFi hubiera cerrado a
F después de realizar una operación de escritura; de lo contrario, el DFS empezará una nueva
sesión. Cuando un cliente ubicado en otro nodo abre el archivo F, el DFS siempre empieza una
nueva sesión. La figura 19.2 ilustra 3 sesiones SF1, SF2 y SF3 en un archivo F. Dos están en el
nodo N1 debido a las razones antes mencionadas. Se creará una nueva versión del archivo cada
vez que un cliente cierre un archivo después de modificarlo. Sin embargo, las reglas para decidir
qué versión de un archivo debe abrirse cuando se inicia una nueva sesión no se especifican en
la semántica de sesiones. Esta característica podrá afectar a la portabilidad de programas que se
usan en un SO que emplea la semántica de sesiones. Ésta es fácil de implementar en un DFS
cuando se usan cachés para archivos porque los cambios hechos en un archivo no son visibles
para clientes en otros nodos.

Semántica de transacciones La actividad de procesamiento de archivos de cada proceso


cliente se realiza en forma de una transacción atómica. La semántica de transacciones puede
implementarse tratando las operaciones open y close en un archivo como el inicio y fin de una
transacción, proveyendo un acceso mutuamente exclusivo a un archivo mediante la colocación
de un candado en el archivo y realizando actualizaciones del archivo como se analiza en la
sección 18.4.1. De este modo, sólo un proceso cliente puede acceder a un archivo en cualquier
momento, y se reflejan en el archivo todas las actualizaciones hechas por él o ninguna de ellas.
La propiedad de todo o nada de la semántica de transacciones siempre mantiene un archivo
en estado consistente. Por consiguiente, un proceso cliente puede simplemente reejecutar una
actividad de procesamiento de archivo que fue trastornada por una falla. El bloqueo de un ar-
chivo también implica que el DFS no tiene que manejar accesos concurrentes de clientes a un
archivo.

19.4 TOLERANCIA DE FALLAS

La confiabilidad de sistemas de archivos tiene varias facetas. Un archivo debe ser robusto, es
decir, capaz de sobrevivir a fallas en forma garantizada. Debe ser recuperable a un estado ante-
rior cuando ocurre una falla. También tiene que ser disponible a pesar de fallas en el sistema, es
decir, una copia del archivo debe ser accesible en todo momento y un proceso cliente debe ser
capaz de abrirlo para fines de procesamiento. La robustez y recuperabilidad dependen, respecti-
vamente, de cómo sean almacenados y respaldados los archivos, mientras que la disponibilidad
depende de cómo se abran y acceda a ellos. Todas estas facetas son independientes entre sí. Por

22 MAQ. CAP. 19(F0694).indd 730 8/10/07 1:24:51 AM


19.4 Tolerancia de fallas 731

tanto, un archivo puede ser recuperable sin ser robusto ni disponible, recuperable y robusto sin
ser disponible, disponible sin ser recuperable ni robusto. La robustez se logra aplicando las téc-
nicas del almacenamiento confiable de datos, por ejemplo, la técnica de generación de imágenes
del disco que se usa en RAID nivel 1 (véase la sección 12.3.3). La recuperabilidad y disponibili-
dad se logran por medio de técnicas especiales que se estudiarán en esta sección.
Para fallas que surgen durante una operación abierta y para las que ocurren después de abrir
un archivo se emplean diferentes técnicas de tolerancia de fallas. Las que ocurren en el servidor
o en los nodos intermedios durante una operación open trastornan la resolución de nombres
de rutas. Estas fallas se toleran mediante técnicas de disponibilidad. El DFS mantiene muchas
copias de las informaciones requeridas para la resolución de nombres de rutas y muchas co-
pias de un archivo. Si una copia es inaccesible debido a una falla, el DFS usa otra. Sin embargo,
las técnicas de disponibilidad se hacen muy complejas y caras si se han de tolerar las fallas que
ocurren durante el procesamiento de archivos (véase la sección 18.4.2 para las técnicas de tole-
rancia a fallas basadas en el quórum con el objeto de manejar datos copiados). Por tanto, son
pocos, si acaso existen, los sistemas de archivos distribuidos que manejan estas fallas.
Fallas que ocurren durante el procesamiento de archivos podrán dar como resultado la pér-
dida de estado, ya sea en el servidor de archivos o en el cliente. Puede diseñarse un servidor de
archivos de tal modo que no se trastorne su operación si se pierde la información del estado debi-
do a una falla. Sin embargo, puede ser que los clientes no usen técnicas de diseño especiales para
protegerse contra la pérdida de estado, por lo que caídas de nodos de clientes pueden resultar
muy desagradables. La única defensa contra caídas de nodos de clientes es el uso de la semántica
de transacciones en el servidor de archivos, con lo que se restablecerá el archivo al estado que
guardó antes de que el cliente que falló hubiera empezado su procesamiento. Una falla en un
nodo intermedio no afecta al procesamiento del archivo si el sistema de comunicación tiene la
resistencia suficiente, es decir, si puede tolerar unas cuantas fallas de ligas y nodos. Por tanto, los
sistemas de archivos no se preocupan de estas fallas.
La tabla 19.3 resume las técnicas de tolerancia a fallas que se usan en sistemas de archivos
distribuidos. La copia de archivos y directorios en cachés se ocupan de fallas en un servidor de
archivos y nodos intermedios durante una operación open. El diseño del servidor de archivos sin
estado se ocupa de fallas en un servidor de archivos durante el procesamiento de archivos. Las
secciones siguientes describen estas técnicas.

19.4.1 Disponibilidad

Se dice que un archivo es disponible si un cliente puede abrir y acceder a una copia del archivo.
La capacidad para abrir un archivo depende de si puede completarse la resolución del nombre de
ruta, es decir, si el nodo del servidor y todos los nodos involucrados en la resolución del nombre
de ruta son funcionales. La capacidad para acceder a un archivo sólo requiere que los nodos de
cliente y servidor estén funcionales porque una ruta entre los dos está garantizada por la resis-
tencia de la red.
Considere un nombre de ruta a/b/c/d, donde los archivos de directorio a, b, c y el archivo
d existen en los nodos A, B, C y D, respectivamente. Pueden emplearse dos enfoques para re-
solver esta ruta. Cuando el DFS se da cuenta de que el archivo b existe en el nodo B, enviará el
sufijo del nombre de ruta b/c/d al nodo B. En el nodo B buscará c en el directorio b y se dará
cuenta de que éste existe en el nodo C, por lo que enviará c/d al nodo C, y así sucesivamente.
En un enfoque alternativo, el DFS realizará la resolución de todos los componentes de ruta en el

22 MAQ. CAP. 19(F0694).indd 731 8/10/07 1:24:52 AM


732 CAPÍTULO 19 Sistemas de archivos distribuidos

Tabla 19.3 Técnicas de tolerancia de fallas de sistemas de archivos distribuidos

Técnica Descripción
Directorios Un directorio en caché es una copia de un directorio que
en caché existe en un sitio remoto. Le ayuda al DFS a tolerar fa-
llas en nodos intermedios involucrados en la resolución de
nombres de ruta.
Replicación En aras de la disponibilidad se mantienen varias copias
de archivos de un archivo. Se emplean técnicas especiales para evitar
inconsistencias entre las copias. La técnica de copia pri-
maria permite el acceso de lectura para programas cliente
de un archivo, pero limita las actualizaciones del archivo a
una sola copia que se denomina copia primaria. Los cam-
bios se propagan a otras copias. Este método simplifica el
control de la concurrencia.
Servidor de Un servidor de archivos convencional mantiene informa-
archivos sin ciones acerca del estado de una actividad de procesamien-
estado to de archivos en los metadatos, por ejemplo, en bloques
de control de archivos y buffers de archivos. Un servi-
dor de archivos sin estado no mantiene estas informacio-
nes, por lo que es inmune a fallas que llevan a la pérdida
de informaciones de estado.

mismo nodo cliente. Cuando se da cuenta de que un componente de nombre de ruta es el nombre de
un directorio en un nodo remoto, copiará el directorio del nodo remoto y continuará usándolo la re-
solución del nombre de ruta. De este modo, se copiarán todos los directorios al nodo cliente durante
la resolución del nombre de ruta. Como veremos más adelante, estos enfoques tienen diferentes
implicaciones para la disponibilidad. En ambos enfoques, un acceso a datos de un archivo no invo-
lucra a los nodos intermedios implicados en la resolución de nombres de rutas. El procesamiento de
archivos no se verá afectado si uno de estos nodos fallase después de que se abrió el archivo.

Directorios en caché Una situación anómala podrá surgir cuando nombres de rutas abarcan
muchos nodos. En el ejemplo anterior, supongamos que el nodo c falla después de que se abrió el
archivo d usando el nombre de ruta a/b/c/d y su proceso estuvo en proceso. Si otro cliente en
el nodo A realiza la operación open a/b/c/z, donde el archivo z también existe en el nodo D,
fallará porque el nodo c ha fallado. Por lo que el archivo z no puede ser procesado a pesar de que
su procesamiento involucra los mismos nodos de cliente y servidor que se registraron.
La única forma de evitar esta anomalía es poner en caché a los directorios remotos accedidos
durante la resolución de nombres de rutas en el nodo cliente. Para el nombre de ruta a/b/c/d
esto implica que el DFS pondrá en caché los directorios a/b y a/b/c en el nodo A. Mientras
resuelve nombres de rutas involucrando los prefijos a/b y a/b/c, el DFS usará directamente
los directorios en caché. De esta forma será capaz de resolver el nombre de ruta b/c/z sin tener
que acceder a los nodos B o C. Sin embargo, puede ser que la información en los directorios
en caché esté anticuada debido a la creación o eliminación de archivos en algunos de los nodos
intermedios, por lo que tendrá que usarse un protocolo de actualización de cachés. Analizaremos
un asunto relacionado con ello en la siguiente sección.

22 MAQ. CAP. 19(F0694).indd 732 8/10/07 1:24:52 AM


19.4 Tolerancia de fallas 733

Replicación de archivos El DFS realiza la réplica de tal manera que sea transparente para
los clientes. La réplica de un archivo que probablemente será actualizado involucra un compro-
miso entre costo y complejidad del protocolo para la actualización y sus implicaciones para el
uso eficiente del archivo. Un protocolo de comisión en dos fases actualizará todas las copias
de un archivo al mismo tiempo. Posiblemente se retrasen las actualizaciones si otros procesos
están usando algunas copias o si son inaccesibles debido a fallas. Sin embargo, no coexistirán
copias deterioradas y actualizadas de un archivo, por lo que un cliente solamente necesitará
una copia del archivo para implementar un acceso de lectura. Las alternativas a este plantea-
miento se enfocan en la aceleración de la operación de actualización, reduciendo el número de
copias que necesiten ser actualizadas.
En el enfoque de la copia primaria, las actualizaciones se dirigen a una sola copia: la copia
primaria. Otras son invalidadas cuando se actualiza la copia primaria; ellas se copiarán de
nuevo cuando son referenciadas. De modo alternativo, el DFS puede usar un protocolo similar
al protocolo de lectores y escritores para datos copiados (véase la sección 18.4.2). A fin de
proveer eficiencia y tolerancia de fallas, esto hará los quórums de lectura y escritura lo más
pequeño posibles. Con cada copia se asociará un sello de tiempo para indicar cuándo fue su
última actualización. Estos sellos de tiempo se compararán para identificar la copia más reciente
de datos en un quórum de lectura.
La réplica de archivos funciona mejor si el uso de una copia deteriorada también tiene
sentido porque los cambios no se necesiten propagar a todas o a unas pocas copias de manera
inmediata. Los directorios pueden ser replicados de esta manera. Todas las actualizaciones se
harán en la copia primaria. El deterioro de un directorio puede causar dos tipos de averías: un
archivo no tiene una entrada en el directorio aunque ha sido creado o una entrada para un archivo
existe en el directorio aunque el archivo fue eliminado. En caso de una avería puede accederse
a la copia primaria del directorio para verificar si el archivo solicitado fue creado o borrado des-
pués de que el directorio fue copiado.

19.4.2 Averías de nodos de clientes y servidores

Como se describe en la sección 7.6, un sistema de archivos convencional almacena informacio-


nes acerca del estado de una actividad de procesamiento de archivos en metadatos tales como el
bloque de control de archivos (FCB) del archivo. Esta información de estado provee un contexto
implícito entre el sistema de archivos y el proceso cliente, lo que simplifica las operaciones que
van a ser realizadas en la implementación de una operación de lectura o escritura. Por ejemplo,
para leer el siguiente registro o byte de un archivo secuencial, el sistema de archivos sencilla-
mente accede a su FCB para obtener la id del siguiente registro o byte que va a ser leído, y accede
a la tabla de mapas de archivos (FMT) por medio del FCB para obtener la dirección del disco del
siguiente registro o byte. Nos referimos a este diseño de un sistema de archivos como un diseño
con estado.
En un sistema de archivos distribuidos, el uso de un diseño con estado implica el uso de
un circuito virtual entre el nodo del cliente y el nodo del servidor (véase la sección 15.7.5).
Este último puede mantener FCB y la AFT en la memoria, igual que en un sistema de archivos
convencional. Tal arreglo provee un buen desempeño. Sin embargo, el uso de un diseño DFS con
estado plantea problemas en el evento de caídas de clientes y servidores.
Cuando cae un cliente, la actividad de procesamiento de archivos tendrá que abandonarse
y el archivo tendrá que restaurarse a su estado anterior para que el cliente pueda reiniciar su

22 MAQ. CAP. 19(F0694).indd 733 8/10/07 1:24:52 AM


734 CAPÍTULO 19 Sistemas de archivos distribuidos

actividad de procesamiento de archivos. El servidor habrá comisionado recursos como los bu-
ffers de FCB y E/S para dar servicio a la actividad de procesamiento de archivos. Estos recursos
tendrán que liberarse; de lo contrario se quedarán comisionados en la actividad de procesa-
miento de archivos de manera indefinida. Estos problemas pueden enfrentarse de la siguien-
te manera: el servidor de cliente y servidor comparten un circuito virtual. El circuito virtual
“posee” las acciones y recursos de procesamiento de archivos, tales como los metadatos del
servidor. Estas acciones y recursos se vuelven huérfanos cuando una caída de cliente o servidor
rompe el circuito virtual, por lo que las acciones tendrán que regresarse y los metadatos tendrán
que destruirse. Podrá usarse un protocolo de cliente/servidor que implementa la semántica de
transacciones para asegurar esto. Si un DFS no provee la semántica de transacciones, un proce-
so cliente tendrá que hacer sus propios arreglos para restaurar el archivo a un estado consistente
anterior.
Cuando se cae un servidor de archivos, se pierde la información de estado almacenada en
los metadatos del servidor, por lo que deberá abandonarse una actividad de procesamiento de
archivos en curso y el archivo tendrá que restaurarse a su estado anterior. Puede usarse el diseño
del servidor de archivos sin estado que se describe en la siguiente sección para evitar ambos
problemas.

19.4.3 Servidores de archivos sin estado

Un servidor de archivos sin estado no mantiene ninguna información de estado concerniente a


una actividad de procesamiento de archivos, por lo que no existe un contexto implícito entre un
cliente y el servidor de archivos. Por consiguiente, un cliente debe mantener la información de
estado concerniente a una actividad de procesamiento de archivos y proveer todas las informa-
ciones relevantes en una llamada al sistema de archivos. Por ejemplo, un cliente que lee de un
archivo secuencial tendrá que mantenerse al tanto de la id del siguiente registro o byte que va a
ser leído del archivo para que pueda usar la siguiente llamada:

read ("alpha", <record/byte id>, <io area address>);

Con esta llamada, el servidor de archivos abre el archivo alpha, localiza su tabla de mapas de
archivos y la usa para convertir <record/byte id> en el par (disk block id, byte offset) (véase
la sección 7.8.2). Luego lee el bloque de disco y provee al cliente el registro o byte solicita-
do. De este modo, muchas acciones que tradicionalmente se realizan sólo en el momento de
abrir el archivo se repiten en cada operación de archivos. Cuando el cliente recibe la respuesta
del servidor de archivos, supone que la operación de lectura/escritura solicitada por él ha sido
exitosamente completada. Si un servidor de archivos cae, en el cliente ocurren intervalos de
tiempo y retransmisiones. El servidor de archivos procesa una solicitud retransmitida cuando
la recibe, y provee una respuesta al cliente. El proceso cliente percibe entonces una respuesta
retrasada a una solicitud y no está consciente de una caída del servidor de archivos.
Un servidor de archivos sin estado no puede detectar y descartar solicitudes duplicadas
porque estas acciones requieren informaciones del estado, por lo que es posible que dé servicio a
una solicitud en más de una ocasión. Como se analizó en la sección 15.5, las solicitudes de clien-
tes deben ser idempotentes de naturaleza para evitar todo efecto dañino del reprocesamiento.
Por su naturaleza, solicitudes de lectura/escritura son idempotentes; sin embargo, las solicitudes

22 MAQ. CAP. 19(F0694).indd 734 8/10/07 1:24:52 AM


19.5 Desempeño de DFS 735

relacionadas con directorios, por ejemplo, la creación y eliminación de archivos, no son idem-
potentes. Por consiguiente, puede ser que un cliente reciba advertencias ambiguas o confusas si
un servidor de archivos sin estado cae y se recupera durante una actividad de procesamiento de
archivos.
El uso de un servidor de archivos sin estado ofrece la tolerancia a fallas, pero también causa
una penalización sustancial por dos razones. Primero, el servidor de archivos abre un archivo
en cada operación de archivos y pasa informaciones de estado al cliente. Segundo, cuando un
cliente realiza una operación de escritura, las consideraciones de confiabilidad requieren que los
datos se escriban en la copia del disco de un archivo en forma inmediata. Por consiguiente, el
servidor de archivos no puede emplear el almacenamiento temporal en buffers, cachés de archi-
vos (véase la sección 19.5.2) ni cachés de disco (véase la sección 12.9) para acelerar su propia
operación. En la sección 19.5.1 analizaremos un diseño híbrido de servidores de archivos que
evita repetidas operaciones de open para archivos.
Un servidor de archivos sin estado es inconsciente de las averías de clientes porque no posee
ninguna información de estado para un cliente o su actividad de procesamiento. Si un cliente
falla, se recupera y reenvía solicitudes al servidor de archivos, el servidor de archivos simple-
mente los reprocesará. A pesar de que una operación individual de lectura o escritura es idempo-
tente, no lo tiene que ser una secuencia de operaciones que incluye una lectura o escritura. Por
ejemplo, una secuencia de operaciones que involucra la lectura de un registro de un archivo al
buscar una cadena xyz en el registro, insertar una cadena S antes de la cadena xyz en el registro
y reescribir el registro modificado en el archivo no es idempotente. Si un cliente fallado ha reali-
zado tal secuencia no idempotente, debe restaurar el archivo a un estado anterior antes de volver
a emitir la secuencia de operaciones.

19.5 DESEMPEÑO DE DFS

La eficiencia inherente de mecanismos de acceso a archivos determina el desempeño pico de un


DFS, medido como el tiempo de respuesta promedio a solicitudes de clientes o como capacidad
de procesamiento de solicitudes de clientes. El DFS puede lograr el desempeño pico cuando to-
dos los accesos a datos son locales para nodos clientes, es decir, cuando los servidores de clientes
y archivos están ubicados en el mismo nodo. El verdadero desempeño de un DFS depende del
volumen de tráfico de la red generado por accesos a archivos remotos. De hecho, las latencias
de redes pueden deslucir completamente la eficiencia de los mecanismos de acceso, aun cuando
sólo una fracción pequeña de accesos a datos sea no local. Este hecho motiva a medidas para
reducir el tráfico de la red por medio de la reducción del número de transferencias de datos a
través de la red durante una actividad de procesamientos de datos.
Un diseño de DFS es escalable si el desempeño del DFS no degrada con un aumento del
tamaño de un sistema distribuido. La escalabilidad es importante para evitar una situación en
la que un DFS que solía trabajar bien en la organización de un cliente se convierta en un cuello
de botella cuando crece el tamaño de la organización. La escalabilidad se logra por medio de
técnicas especiales que aseguran que el tráfico de la red no crezca con el tamaño del sistema
distribuido.
La tabla 19.4 resume las técnicas para lograr un alto desempeño del DFS. Éstas se analiza-
rán en las sesiones siguientes.

22 MAQ. CAP. 19(F0694).indd 735 8/10/07 1:24:52 AM


736 CAPÍTULO 19 Sistemas de archivos distribuidos

Tabla 19.4 Técnicas de desempeño de sistemas de archivos distribuidos

Técnica Descripción
Diseño de múltiples Cada hilo en el servidor maneja una solicitud de cliente. El procesamiento de
hilos de servidores archivos es una actividad acotada por E/S, y por tanto varios hilos pueden
de archivos progresar en forma paralela, contribuyendo de esta manera a una mayor capa-
cidad de procesamiento.
Diseño de servi- Un consejo es una información relacionada con una actividad de procesamiento
dores de archivos continua que puede ser mantenida por un servidor de archivos. Cuando un
basado en consejos consejo conveniente está disponible, el servidor de archivos se comporta como
un servidor de archivos con estado, por lo que puede realizar una operación
en forma eficiente; de lo contrario, se comporta como un servidor de archivos
sin estado.
Archivo caché Una parte del archivo localizada en el nodo remoto se copia al archivo caché
en el nodo del cliente. El archivo caché reduce el tráfico de la red durante el
procesamiento de archivos al convertir la transferencia de datos que son loca-
les al nodo del cliente.
Clústers de nodos Un clúster de nodos es una sección del sistema distribuido que contiene
semiindependientes suficientes recursos de hardware y software para que la operación de
procesamiento en un clúster rara vez necesite recursos ubicados en otras partes
del sistema.

19.5.1 Acceso eficiente a archivos

La inherente eficiencia del acceso a archivos depende de cómo está estructurada la operación
de un servidor de archivos. Hablaremos de dos estructuras de servidores que proveen un acceso
eficiente a archivos.

Servidor de archivos de múltiples hilos El servidor de archivos tiene varios hilos; cada
uno es capaz de dar servicio a una solicitud de cliente. La operación de varios de estos hilos
puede ser en forma traslapada porque el procesamiento de archivos es una actividad acotada
por E/S. Este arreglo provee una respuesta rápida a solicitudes de clientes y una alta capacidad
de procesamiento. El número de hilos puede variar de acuerdo con el número de solicitudes de
clientes que están activas en un momento dado y con la disponibilidad de recursos del SO, tales
como bloques de control de hilos.

Servidor de archivos basado en consejos Un servidor de archivos basado en consejos es


un diseño híbrido porque tiene características tanto del servidor de archivos con estado como del
servidor sin estado. En aras de la eficiencia, este servidor opera de manera con estado toda vez
que sea posible. En otros momentos opera de manera sin estado. Un consejo es una información
con respecto a una actividad continua de procesamiento de archivos, por ejemplo, la id del si-
guiente registro en un archivo secuencial que será accedido por una actividad de procesamiento
de archivos (véase la sección 7.6). El servidor mantiene una colección de consejos en su memo-
ria volátil. Cuando un cliente solicita una operación de archivos, el servidor de archivos verifica
si existe un consejo que le podrá ayudar en su procesamiento. Si hay un consejo disponible,

22 MAQ. CAP. 19(F0694).indd 736 8/10/07 1:24:53 AM


19.5 Desempeño de DFS 737

lo usa para acelerar la operación de archivos; de lo contrario, el servidor de archivos opera en


forma sin estado: abre el archivo y usa la id de registros/bytes proporcionada por el cliente para
acceder al registro o byte solicitado. En todo caso inserta, después de completar la operación de
archivos, una parte del estado de la actividad de procesamiento en su memoria volátil como con-
sejo y también la devuelve al cliente como en un servidor de archivos sin estado. La eficiencia
general del servidor de archivos depende del número de operaciones de archivos asistidas por la
presencia de consejos.
La operación de un servidor de archivos basado en consejos es tolerante a fallas porque no
será trastornado aun si todos los consejos en la memoria volátil del servidor se pierden debido
a una caída. Los usuarios notarán sólo una degradación de tiempos de respuesta hasta que el
servidor de archivos se recupere y construya un conjunto de consejos útiles.

19.5.2 Formación de cachés de archivos

La técnica de formación de cachés de archivos acelera la operación del DFS mediante la


reducción del tráfico de la red. Retiene datos de un archivo remoto en un buffer en un nodo
cliente denominado caché de archivos. La caché de archivos y la copia del archivo en un disco
en el nodo del servidor forman una jerarquía de memoria (véase la sección 2.1.1), por lo que
la operación de la caché de archivos y sus beneficios son análogos a los de una caché de CPU
o una memoria virtual. Se cargan pedazos de datos de archivos desde el servidor de archivos a
la caché de archivos. A fin de aprovechar la localidad espacial, cada pedazo es suficientemente
grande para dar servicio a unos cuantos accesos a archivos hechos por un cliente. Los estudios
de distribuciones de tamaños de archivos indican un pequeño tamaño promedio de archivos, por
lo que incluso la colocación de archivos enteros en cachés es factible. Estudios de Tanenbaum
y otros reportan que 79 por ciento de los archivos en su sistema tenían un tamaño menor a 4 K
bytes, y 94 por ciento fue más pequeño que 16 K bytes. En el sistema de archivos de Andrews,
donde el tamaño de pedazos fue variado por cliente, el tamaño de pedazos fue a menudo de 8 K
bytes e incluía archivos completos, y la proporción de aciertos de caché de archivos excedió
0.98. (Un DFS podrá usar una caché de atributos separada para guardar informaciones en rela-
ción con atributos de archivos.)
La figura 19.3 contiene un diagrama esquemático de la formación de cachés de archivos.
El administrador de cachés existe en una ruta entre un cliente y un servidor de archivos. Este
administrador carga pedazos de datos de archivos al caché de archivos, suministra datos de la
caché a procesos clientes, mantiene la caché de archivos usando un algoritmo LRU para realizar
el reemplazo de pedazos y escribe pedazos modificados a la copia del archivo en el nodo del
servidor. Los asuntos clave en el diseño de una caché de archivos son los siguientes:
• Ubicación de la caché de archivos
• Política de actualización de archivos
• Validación de cachés
• Tamaño de pedazos
La caché de archivos puede mantenerse en la memoria de un nodo cliente o en un disco ad-
junto al nodo cliente. La organización de la caché de archivos en la memoria proveerá el acceso
más rápido a datos de archivos; sin embargo, esto resultará en baja confiabilidad porque la caída
del nodo cliente llevará a la pérdida de la caché de archivos, incluidos todos los datos de archivos
modificados que aún van a escribirse en la copia del archivo en el servidor. Ubicar la caché en el

22 MAQ. CAP. 19(F0694).indd 737 8/10/07 1:24:53 AM


738 CAPÍTULO 19 Sistemas de archivos distribuidos

Nodo
servidor Servidor
de archivos
Tráfico de
datos y validación
de caché

Administrador Administrador
Nodo de la caché de la caché Nodo
Caché de Caché de
cliente archivos archivos cliente
Cliente1 Cliente 2

Figura 19.3 Un esquema de formación de cachés de archivos.

disco aminorará la velocidad de acceso a los datos del archivo, pero proveerá confiabilidad, pues-
to que la caché de archivos y los datos modificados contenidos en él sobrevivirán a las caídas del
nodo cliente. Podrán usarse técnicas basadas en redundancia, como imágenes de espejo del disco,
para mejorar aún más la confiabilidad de la caché de archivos organizada en un disco.
Cuando un cliente realiza una operación de escritura en un disco, los datos del archivo
modificados tendrán que escribirse en la copia del archivo que está en el servidor. La decisión
sobre si la copia del archivo debe actualizarse de inmediato o en un momento posterior involucra
una solución intermedia entre el retraso en el cliente proceso y la confiabilidad del DFS. Lo más
sencillo es usar la política de escritura inmediata, que actualiza la caché de archivos en el nodo
cliente y la copia del archivo en el nodo del servidor al mismo tiempo. Este método es confiable
porque la escritura inmediata podrá implementarse como una transacción para asegurar que fi-
nalice; sin embargo, retrasa al cliente que realizó la operación de escritura. Para evitar el retraso
del cliente, la actualización de la copia del archivo podrá realizarse en un momento posterior,
siempre y cuando se hagan los arreglos para asegurar que mientras tanto los datos modificados
no se pierdan si el nodo cliente fallara. Esta política se llama política de escritura retardada. Sus
variaciones realizan la escritura en diferentes momentos: cuando el pedazo modificado se borra
de la caché de archivos debido a un reemplazo o cuando el cliente cierra un archivo.
Cuando un archivo es procesado por muchos clientes en paralelo, copias de sus datos
existirán en varias cachés de archivos al mismo tiempo. Si un cliente realiza una operación de
escritura, las copias en las cachés de otros clientes se hacen inválidas, es decir, deterioradas.
La función validación de cachés identifica datos inválidos y se ocupa de ellos de acuerdo
con la semántica de compartición de datos del DFS. Por ejemplo, cuando se usa la semántica
Unix, las actualizaciones de archivos hechas por un cliente deberán ser inmediatamente visibles
para otros, por lo que la función de validación de cachés refresca los datos inválidos o impide su
uso por parte de un cliente.

22 MAQ. CAP. 19(F0694).indd 738 8/10/07 1:24:53 AM


19.5 Desempeño de DFS 739

El tamaño de los pedazos en la caché de archivos deberá ser grande, de tal modo que la
ubicación espacial de los datos de archivos contribuya a una alta proporción de aciertos en
la caché del servidor. Sin embargo, el uso de un tamaño grande de pedazos implica una más alta
probabilidad de invalidación de datos debido a modificaciones realizadas por otros clientes y, por
ende, más retrasos y mayor carga general de validación de cachés, que cuando se usa un tamaño
pequeño de pedazos. De este modo, el tamaño de pedazos usado en un DFS es una concesión
entre estas dos consideraciones. Puesto que un tamaño fijo de pedazos posiblemente no satisfaga
a todos los clientes de un DFS, algunos sistemas de archivos distribuidos, en particular AFS,
ajustan el tamaño de pedazos a cada cliente individual.

Validación de cachés Un método sencillo para identificar datos inválidos es por medio de
sellos de tiempo. Un sello de tiempo está asociado a un archivo y cada uno de sus pedazos en
cachés. El sello de tiempo de un archivo indica cuándo se modificó este archivo por última vez.
Cuando un pedazo del archivo se copia a una caché, el sello de tiempo del archivo también se
copia como el sello de tiempo del pedazo. En cualquier momento el pedazo en caché es inválido
si su sello de tiempo es más pequeño que el del archivo. De este modo, una operación de escri-
tura en alguna parte x de un archivo que realiza un cliente invalida todas las copias de x en las
cachés de otros clientes. Estos datos se refrescan, es decir, se vuelven a cargar, en el momento
de su siguiente referencia.
Dos planteamientos básicos de la validación de cachés son la validación iniciada por el
cliente y la validación iniciada por el servidor. La validación iniciada por el cliente es realiza-
da por parte del administrador de cachés en un nodo cliente. En cada acceso de un cliente a un
archivo, el administrador verifica si los datos solicitados ya se encuentran en la caché. De ser
así, verifica si los datos son válidos. Si la verificación es exitosa, el administrador de cachés
provee los datos de la caché al cliente; en caso contrario, refresca los datos en la caché antes
de proveerlos al cliente. Este planteamiento produce tráfico de validación de cachés a través de
la red en cada ocasión de acceso al archivo. Este tráfico puede reducirse mediante la validación
periódica en lugar de en cada acceso al archivo, siempre que esta validación no sea inconsistente
con la semántica de compartición de archivos del DFS. Sun NFS usa este planteamiento (véase
la sección 19.6.1).
En el planteamiento iniciado por el servidor, el servidor de archivos se mantiene al tanto
de qué nodos clientes contienen qué datos de archivos en sus cachés y usa esta información de
la siguiente manera: cuando un cliente actualiza datos en alguna parte x de un archivo, el servidor
de archivos busca los nodos clientes que tienen x en su caché de archivos e informa a sus admi-
nistradores de cachés que sus copias de x se han hecho inválidas. Entonces cada administrador
de caché tiene la opción de borrar la copia de x de su caché o de volver a meterla en una caché,
ya sea inmediatamente o en el momento de la primera referencia a ella.
La validación de cachés es una operación cara. Por tanto, algunas semánticas, por ejem-
plo, la semántica de sesiones, no requieren que las actualizaciones hechas por un cliente deban
ser visibles para clientes en otros nodos. Esta característica evita por completo la necesidad de
la validación. Otra forma de evitar la carga general por validación de cachés es deshabilitar la
formación de cachés de archivos si un cliente abre un archivo en el modo de actualización. To-
dos los accesos a un archivo de ese tipo se implementan directamente en el nodo del servidor.
Entonces todos los clientes que desean usar el archivo tienen que acceder a él como en el proce-
samiento de archivos remotos.

22 MAQ. CAP. 19(F0694).indd 739 8/10/07 1:24:53 AM


740 CAPÍTULO 19 Sistemas de archivos distribuidos

19.5.3 Escalabilidad

La escalabilidad de DFS se logra por medio de técnicas que localizan la mayoría del tráfico de
datos generado por actividades de procesamiento de archivos en el interior de secciones peque-
ñas de un sistema distribuido denominado clústers de nodos o, sencillamente, clústers (véase la
sección 15.2). Hay dos razones por las que este enfoque es efectivo. En primer lugar, los clústers
normalmente representan subredes como LAN de alta velocidad, que proveen altos índices de
transferencia de datos, por lo que tanto los tiempos de respuesta como la capacidad de procesa-
miento mejoran cuando el tráfico de datos está limitado a un clúster. En segundo lugar, un au-
mento del número de clústers no lleva a la degradación del desempeño porque no agrega mucho
tráfico en la red. Cuando un cliente de un DFS que posee tanto transparencia de ubicación como
independencia de ubicación accede a un archivo remoto, el archivo podrá simplemente moverse
al clúster donde el cliente está ubicado. Si el DFS no posee independencia de ubicación, puede
lograrse un efecto análogo para archivos de solo lectura por medio de la copia de archivos o for-
mación de cachés. Para archivos que son actualizados, el uso de la semántica de sesiones elimina
el tráfico de validación de archivos, por lo que localizar una versión de archivo en el nodo cliente
será suficiente para reducir el tráfico en la red.

19.6 ESTUDIOS DE CASOS REALES

19.6.1 El sistema de archivos de red de Sun

El sistema de archivos de red (NFS) de Sun provee la compartición de sistemas de archivos


en nodos que operan bajo el sistema operativo SunOS, que es una versión del protocolo Unix
(XDR). La figura 19.4 muestra un diagrama esquemático del NFS. Este sistema usa una arqui-
tectura de dos niveles que consiste en la capa del sistema de archivos virtuales (VFS) (véase la
sección 7.11) y la capa NFS. La capa VFS implementa el protocolo de montaje y crea un desig-
nador único en todo el sistema para cada archivo, que se llama nodoV. Si el archivo en el cual se
va a realizar una operación está ubicado en uno de los sistemas de archivo locales, el VFS invoca
a este sistema de archivos; de lo contrario, invoca a la capa NFS. La capa NFS interactúa por
medio del protocolo NFS con el nodo remoto que contiene el archivo. Esta arquitectura permite
que un nodo sea tanto cliente como servidor al mismo tiempo.

Protocolo de montaje Cada nodo en el sistema incluye una lista de exportación que contie-
ne pares de la forma (<directory>,<list_of_nodes>). Cada par indica que <directory>, que existe
en uno de los sistemas de archivos locales, puede ser montado en forma remota solamente en
los nodos contenidos en <list_of_nodes>. Cuando el superusuario de un nodo hace una solicitud
para montar un directorio remoto, el NFS verifica la validez de la solicitud, monta el directorio
y regresa un file handle (nombre temporal de archivo) que contiene el identificador del sistema
de archivos del directorio remoto y el inodo del directorio en este sistema de archivos. Los
usuarios en el nodo ven una jerarquía de directorios construida por medio de estos comandos de
montaje.
NFS permite el montaje en cascada de sistemas de archivos, es decir, un sistema de archivos
podrá estar montado en un punto de montaje en otro sistema de archivos, que a su vez está mon-
tado dentro de otro sistema de archivos, y así sucesivamente. Sin embargo, el diseño NFS evita

22 MAQ. CAP. 19(F0694).indd 740 8/10/07 1:24:53 AM


19.6 Estudios de casos reales 741

Cliente Servidor
Interfaz de llamadas
al sistema

Interfaz VFS Interfaz VFS


Capa NFS
Otros sistemas Sistema de Sistema de
de archivos archivos Unix 4.2 Cliente NFS Servidor NFS archivos Unix 4.2

RPC/XDR RPC/XDR

Red

Figura 19.4 Arquitectura del sistema de archivos de red (NFS) de Sun.

cuidadosamente la transitividad del mecanismo de montaje. Por ejemplo, considere la siguiente


situación:

1. El superusuario en el nodo N1 del sistema monta el sistema de archivos C del nodo N3 en


el punto de montaje y en el sistema de archivos locales B.
2. El superusuario en el nodo N1 monta el sistema de archivos B del nodo N1 en el punto de
montaje x en el sistema de archivos locales A.

El NFS no permite que los usuarios en el nodo N2 accedan al sistema de archivos C, que fue
montado sobre una parte del sistema de archivos B. De este modo, la visión que tiene cada
host de la jerarquía de directorios es el resultado de los montajes realizados sólo por su propio
superusuario, que habilita al servidor de archivos para que opere en forma sin estado. Si no se
impone esta restricción, cada servidor de archivos tendrá que saber acerca de todos los montajes
realizados por todos los clientes sobre su sistema de archivos, lo que requerirá que el servidor de
archivos esté con estado.

Protocolo NFS El protocolo NFS usa el paradigma de servicio remoto (es decir, el proce-
samiento de archivos remotos; véase la sección 19.1.1) por medio de un modelo cliente/servidor
que emplea llamadas al procedimiento remoto (RPC). Un servidor de archivos está sin estados,
por lo que cada RPC tiene parámetros que identifican el archivo, el directorio que contiene el ar-
chivo y los datos a leer o escribir. El NFS provee llamadas para la búsqueda de un archivo dentro
de un directorio, lectura de entradas en directorios, manipulación de ligas y directorios, acceso
a atributos de archivos, es decir, informaciones tipo ínodo, y la realización de una operación de
lectura/escritura.
Puesto que un servidor de archivos está sin estado, realiza un abrir y cerrar implícito para
cada operación en un archivo y no usa la caché de buffer de Unix (véase la sección 12.10.2
para una descripción de la caché de buffer de Unix). Un NFS no provee el bloqueo de archivos o
registros; los usuarios tienen que usar sus propios medios para el control de concurrencia.

22 MAQ. CAP. 19(F0694).indd 741 8/10/07 1:24:54 AM


742 CAPÍTULO 19 Sistemas de archivos distribuidos

Resolución de nombres de rutas Supongamos que un usuario U1 ubicado en el nodo N1


usa un nombre de ruta x/y/z/w, donde y es el directorio raíz de un sistema de archivos monta-
dos. Para empezar, el nodo host N1 crea vnodex, el nodoV para x. El NFS usa la tabla de montaje
de N1 mientras está buscando el siguiente componente del nombre de ruta, y así sabe que y es
un directorio montado. El NFS crea vnodey a partir de la información de la tabla de montaje. Su-
pongamos que vnodey sirva para un archivo en el nodo N2, por lo que el NFS hace una copia del
directorio y en el nodo N1. Mientras busca z en esta copia y, el NFS nuevamente usa la tabla de
montaje de N1. Esta acción resolverá a z correctamente aun si z fuese un sistema de archivos
que montado por el superusuario del nodo N1 sobre algún punto en el sistema de archivos re-
motos y. El servidor de archivos en el nodo N2, que contiene y, no necesita tener conocimiento
alguno de este montaje. En lugar de usar este procedimiento, si el nombre de ruta y/z/w tuviese
que entregarse al servidor de archivos en el nodo N2, tendrá que saber acerca de todos los monta-
jes realizados por todos los clientes sobre su sistema de archivos. Esto requerirá que el servidor
de archivos esté con estado.
Se usa una caché de nombres de directorios en cada nodo cliente para acelerar la resolu-
ción de nombres de rutas. Esta caché contiene nombres de directorios remotos y sus nodos V. Se
añaden nuevas entradas a la caché cuando se resuelve un nuevo prefijo de un nombre de ruta y
se borran entradas cuando una búsqueda falla debido a una falta de coincidencia entre atributos
devueltos al servidor de archivos y los de los nodosV en caché.

Operaciones en archivos y semántica de compartición de archivos El NFS emplea el


paradigma del servicio remoto, lo que significa que cada operación en un archivo deberá causar
una solicitud al servidor. Sin embargo, el NFS también emplea la formación de cachés para ob-
tener mejor desempeño. Este arreglo híbrido complica la semántica de compartición de archivos
que ofrece.
El NFS usa dos cachés para acelerar operaciones en archivos. Una caché de atributos de
archivos coloca en una caché informaciones de ínodo. Esta caché se usa porque resulta que un
gran porcentaje de solicitudes hechas a un servidor de archivos estaban relacionadas con atri-
butos de archivos. Los atributos en caché se descartan después de tres segundos para archivos y
después de 30 segundos para directorios. La caché de bloques de archivos es la caché de archi-
vos convencional. Esta caché contiene bloques de datos del archivo. El servidor de archivos usa
grandes bloques de datos (8 K bytes), así como técnicas de la precarga de archivos y la escritura
retardada (es decir, técnicas de almacenamiento intermedio, véase la sección 12.6) para mejorar
el desempeño de acceso a archivos. Un bloque modificado se envía al servidor de archivos para
su escritura en el archivo en un momento no especificado. Esta política se usa incluso cuando
los clientes acceden en forma concurrente al mismo bloque de archivos en modos conflictivos,
por lo que una modificación hecha por uno no está inmediatamente visible para otros clientes
que acceden al archivo. Un bloque modificado también se envía al servidor de archivos cuando
el archivo se cierra.
La validación de cachés se realiza por medio de sellos de tiempo asociados con cada archivo
y cada bloque de cachés. Se supone que los contenidos de un bloque en caché son válidos du-
rante un determinado periodo de tiempo. Para cada acceso después de este tiempo, el bloque en
caché sólo se usa si su sello de tiempo es mayor que el del archivo.

22 MAQ. CAP. 19(F0694).indd 742 8/10/07 1:24:54 AM


19.6 Estudios de casos reales 743

19.6.2 Sistemas de archivos Andrew y Coda

Andrew, el ambiente de computación distribuida desarrollado en la Universidad de Carnegie-


Mellon, es destinado a sistemas distribuidos gigantescos con más de 5 000 estaciones de trabajo.
Cada una tiene un disco local que se usa para organizar el espacio de nombre local. Este espacio
de nombre contiene programas del sistema para la iniciación y operación de la estación de traba-
jo, así como archivos temporales que están acomodados allí por motivos de desempeño. Todos
los clientes tienen un idéntico espacio de nombre compartido que es transparente de ubicación
por naturaleza. Se implementa por medio de servidores dedicados que se llaman en forma co-
lectiva Vice.
El desempeño escalable se obtiene por medio de dos métodos. Clústers localizan actividades
de procesamiento de archivos en la medida de lo posible, de tal forma que el acceso a archivos
no cause tráfico en la red troncal del sistema. El tráfico dentro de un clúster se reduce metiendo
en caché un archivo entero en el disco local de una estación de trabajo cuando se abre para el
procesamiento. Estas dos técnicas aseguran que el tráfico de la red en el sistema no crezca mien-
tras lo hace el tamaño del sistema.

Espacio de nombre compartido Andrew usa el concepto de un volumen. Un volumen nor-


malmente contiene archivos de un solo usuario. En un disco pueden existir muchos volúmenes.
Andrew trata al volumen casi igual que Unix lo hace con una partición de disco, aunque un vo-
lumen puede ser considerablemente más pequeño que una partición de disco. Un volumen puede
ser montado. Este hecho provee una granularidad mucho más fina que en Unix. El identificador
de archivos que usa Vice contiene el número de volumen del volumen que contiene un archivo,
y un índice en un array de ínodos contenidos en el volumen.
Una base de datos de ubicación de volúmenes (VLDB) contiene informaciones sobre cada
volumen en el sistema. Esta base es copiada en cada servidor. Se migran volúmenes de un disco
a otro a fin de equilibrar la utilización de discos en el sistema. El servidor que anteriormente con-
tenía un volumen migrado mantiene una información de remisión hasta que todos los servidores
actualizan sus bases de datos de ubicación de volúmenes. Este arreglo simplifica la migración
de volúmenes porque elimina la necesidad de actualizar todas las bases de datos de ubicación de
volúmenes al mismo tiempo. La propia migración de un volumen se realiza con un mínimo
de alteración de las actividades de procesamiento de archivos mediante el siguiente procedi-
miento: se produce una copia de un volumen en el nuevo servidor. Mientras se está realizando
esta operación, su servidor original continúa dando servicio a solicitudes. Una vez que el co-
piado está completo, el volumen se hace off-line, se hacen actualizaciones recientes realizadas
después de que iniciara la operación de copiado en la copia del nuevo servidor, y la nueva copia
se hace operacional.

Operaciones en archivos y la semántica de compartición de archivos Cuando un cliente


abre un archivo, Andrew lo coloca en una caché en el disco local de la estación de trabajo del
cliente usando pedazos de 64 K bytes. Sin embargo, el sistema ajusta el tamaño del pedazo
por cliente individual para adecuarlo al patrón de acceso a archivos del cliente. Como se mencio-
nó en la sección 19.5.2, estudios realizados a mediados de los noventa reportaron que pedazos
de un tamaño de 8 K bytes fueron ampliamente usados, y el índice de aciertos en la caché de ar-
chivos normalmente excedió 0.98. Las llamadas de abrir/cerrar archivos se dirigen a un proceso

22 MAQ. CAP. 19(F0694).indd 743 8/10/07 1:24:54 AM


744 CAPÍTULO 19 Sistemas de archivos distribuidos

del nivel del usuario llamado Venus, que coloca un archivo en una caché cuando un usuario lo
abre, y actualiza la copia del servidor cuando el cliente cierra el archivo. Operaciones de lectura
y escritura de archivos se realizan en la copia en caché sin involucrar a Venus. Por consiguiente,
los cambios hechos en un archivo no se reflejan en forma inmediata en la copia del servidor y no
son visibles para otros clientes que acceden al archivo. Esta semántica de compartición de archi-
vos tiene algunas características de la semántica de sesiones; sin embargo, Andrew no mantiene
múltiples versiones de un archivo.
La copia del archivo puesto en caché por el proceso Venus en un nodo es considerada válida
a menos que se le diga al proceso Venus lo contrario. De este modo, una copia de un archivo en
caché podrá persistir en el archivo a lo largo de la operación de cierre así como de la siguiente
operación de abrir el archivo en la misma estación de trabajo. Se realiza la validación de caché
en la forma iniciada por el servidor, usando un mecanismo que se llama llamada automática.
Cuando un archivo F se pone en caché en el nodo cliente N1 debido a una operación de abrir, el
servidor anota este hecho en su tabla. Mientras esta entrada permanece en la tabla, se dice que
el nodo N1 tiene una llamada automática en F. Cuando la copia de F en el servidor es actualizada
porque un cliente cerró F, el servidor elimina la entrada de N1 de su tabla y avisa al proceso Ve-
nus en el nodo N1 que su llamada automática en F ha sido rota. Si un cliente en N1 tratara de abrir
F en el futuro, Venus sabrá que N1 no tiene una llamada automática en F, por lo que pondrá el
archivo F nuevamente en caché. Venus mantiene dos cachés: una caché de datos y una caché de
estatus. Esta última se usa para llamadas al sistema de servicio que consultan información sobre
el estatus del archivo. Ambas cachés se manejan con base en LRU.
La resolución de nombres de ruta se realiza en la forma de componente a componente.
Venus mantiene una caché de mapeo que contiene informaciones referentes a volúmenes que
fueron accedidos recientemente. Puesto que los volúmenes pueden ser migrados, Venus trata
esta información como un consejo y la descarta si resulta equivocada. Durante la resolución de
nombres de ruta, Venus también copia en su caché cada directorio involucrado en el nombre
de ruta. La presencia de estas copias en caché puede acelerar la resolución de nombres de rutas
en el futuro.
Servidores de archivos son de múltiples hilos para impedir que se conviertan en un cuello
de botella. Se usa un paquete de procesos ligeros a fin de generar nuevos procesos ligeros para
manejar solicitudes de archivos. La comunicación cliente/servidor se organiza por medio de
RPC.

Características de Coda Coda, que es un sucesor de la versión 2 del sistema de archivos


Andrew, añadió dos características complementarias para lograr la alta disponibilidad: la copia
y la operación desconectada. Coda admite la copia de volúmenes. La colección de servido-
res que tienen una copia de un volumen es conocida como grupo de almacenamiento de volúme-
nes (VSG). Coda controla el uso de archivos copiados por medio de la política de leer y escribir
todo: sólo una de las copias necesita estar disponible para la lectura, pero todas tienen que ser
actualizadas al mismo tiempo. Para este propósito se usa un RPC de transmisión múltiple deno-
minado multiRPC.
Un nodo entra en el nodo desconectado de la operación cuando el subconjunto de VSG
accesible para él es cero. Andrew todavía admite cachés de archivos enteros en el nodo de un
cliente, por lo que un cliente en el modo desconectado de la operación podrá operar en un ar-
chivo en aislamiento. Las actualizaciones de archivos hechas por este cliente se reflejarán en el
archivo cuando el nodo del cliente es capaz de conectarse al servidor. Cualquier conflicto con
versiones de archivos que mientras tanto son creados por otras actividades de procesamiento

22 MAQ. CAP. 19(F0694).indd 744 8/10/07 1:24:54 AM


19.6 Estudios de casos reales 745

tendrán que haberse resuelto en ese momento. Este paso puede ser automatizado en una forma
específica de la aplicación; sin embargo, en algunos casos la intervención humana puede ser
necesaria.
Tener un solo archivo en caché posiblemente no será adecuado para la operación desconec-
tada, por lo que Coda provee el acopio de archivos. Un usuario puede proveer a Coda una base
de datos de acopio, que contiene los nombres de rutas de archivos importantes. Durante una
sesión iniciada por el usuario, Coda usa una política de administración de cachés priorizadas
para mantener unos archivos recientemente accedidos y archivos nombrados en la base de da-
tos acopiados en la caché del nodo del usuario. Este conjunto de archivos se refina mediante la
recomputación periódica de sus prioridades. De este modo, la caché en el nodo podrá contener
un conjunto adecuado de archivos cuando el nodo se vuelve desconectado, lo que permitirá una
operación desconectada significativa.

19.6.3 GPFS

El sistema general de sistemas de archivos paralelos es un sistema de archivos de alto rendimien-


to para grandes clústers de computadoras que operan bajo Linux. GPFS usa el rayado de datos
(véase la sección 12.3.3) a través de todos los discos disponibles en un clúster. De este modo,
los datos de un archivo se escriben en varios discos que pueden leerse o escribirse en paralelo.
Un bloque de gran tamaño, es decir, una tira, se usa para minimizar la carga general de búsqueda
durante una lectura/escritura de un archivo; sin embargo, un gran bloque de disco posiblemente
no pueda proveer una alta velocidad de transferencia de datos para archivos pequeños que pue-
dan caber en un pequeño número de tiras, por lo que se usa un subbloque más pequeño que puede
ser tan pequeño como 1/32 de un bloque.
El bloqueo se usa para mantener la consistencia de datos de archivos cuando procesos en
varios nodos del clúster acceden a un archivo común. Un paralelismo alto en el acceso a un
archivo común requiere una granularidad fina de bloqueo, mientras la baja carga general de
bloqueo requiere una granularidad gruesa. GPFS usa entonces un planteamiento compuesto
que funciona de la siguiente manera: al primer proceso que realiza una operación de escritura
en un archivo se le da un candado cuyo rango de bytes cubre el archivo completo. Si ningún
otro proceso accede al mismo archivo, este proceso no tendrá que colocar y volver a colocar
candados mientras procesa el archivo. Si otro proceso desea escribir en el mismo archivo, a este
proceso se le da un candado con un rango de bytes que cubre los bytes que desea escribir, y el
rango de bytes en el candado que ya posee el primer proceso es reducido para excluir estos bytes.
De este modo, la granularidad del candado es tan gruesa como sea posible, pero tan fina como
sea necesario, sujeta a la restricción debida a que el rango de bytes en un candado no puede ser
más pequeño que un bloque de datos en un disco. Cada vez que se reduce el rango de bytes en
un candado, las actualizaciones hechas en los bytes que no están cubiertos por el nuevo rango de
bytes en el candado son arrastradas al archivo, por lo que un proceso que adquiere un candado
para estos bytes verá sus valores más recientes.
El esquema de bloqueo del GPFS involucra un administrador de candados centralizado
y unos cuantos administradores distribuidos, y emplea la noción de tokens de bloqueo para
reducir la latencia y carga general del bloqueo. La primera vez que un proceso en un nodo
accede a un archivo, el administrador de candados centralizados entrega un token de bloqueo a
ese nodo. Este token autoriza al nodo a expedir en forma local candados en el archivo a otros
procesos en este nodo hasta que se le quite el token de bloqueo. Este arreglo evita el tráfico

22 MAQ. CAP. 19(F0694).indd 745 8/10/07 1:24:55 AM


746 CAPÍTULO 19 Sistemas de archivos distribuidos

repetido entre un nodo y el administrador de candados centralizados por adquirir candados en


un archivo. Cuando un proceso en algún otro nodo desea acceder al mismo archivo, el admi-
nistrador de candados centralizados le quita el token de bloqueo al primer nodo y lo entrega al
segundo nodo. Ahora éste puede expedir nodos para este archivo en forma local. Los bytes de
datos cubiertos por rangos de bytes en los candados expedidos por un nodo pueden meterse en
caché localmente en este nodo; no se generará tráfico de coherencia de cachés cuando se ac-
ceden o actualizan estos bytes porque no se permitirá el acceso a estos bytes a ningún proceso
en cualquier otro nodo.
Es posible que los metadatos de un archivo, tales como los apuntadores directos e indirectos
en el FMT, se vuelvan inconsistentes cuando varios nodos actualizan los metadatos en forma pa-
ralela. Por ejemplo, cuando dos nodos agregan un apuntador cada uno al mismo bloque indirecto
en el FMT, la actualización de un cliente será sobrescrita por la del otro cliente. Por tanto, se
perderá uno de los apuntadores. Para impedir estas inconsistencias, se designa a uno de los nodos
como metanodo para el archivo, y todos los accesos y actualizaciones a los metadatos del ar-
chivo son realizados únicamente por el metanodo. Otros nodos que actualizan el archivo envían
sus metadatos al metanodo, y el metanodo los comisiona al disco. No pueden surgir conflictos
durante la actualización de las entradas FMT porque los rangos de bytes en candados admiti-
dos en diferentes nodos no se traslapan.
La lista del espacio libre en disco puede llegar a ser un cuello de botella de desempeño
debido a la asignación de espacio en disco durante las actividades de procesamiento de archivos
en diferentes nodos. Para evitar eso, se divide el mapa de espacios libres en particiones, y un
administrador de asignación central le entrega una partición del mapa a cada nodo. El nodo rea-
liza todas las asignaciones de espacio en disco por medio de esta partición del mapa. Cuando el
espacio libre en esta partición está agotado, le solicita al administrador de asignación el acceso
a otra partición.
Cada nodo escribe un diario separado para la recuperación. Éste se encuentra ubicado en el
sistema de archivos al que pertenece el archivo en procesamiento. Cuando un nodo falla, otros
pueden acceder a este diario y llevar a cabo las actualizaciones pendientes. La consistencia de
los bytes de datos que están siendo actualizados es implícita porque el nodo fallado habrá blo-
queado los bytes de datos; estos candados sólo se liberan después de que se procesa el diario del
nodo fallado.
Averías de comunicación pueden dividir el sistema en particiones. Sin embargo, no se afec-
tan necesariamente las actividades de procesamiento de archivos en nodos individuales porque
un nodo puede ser capaz de acceder a algunos de los discos. Esto puede conducir a inconsisten-
cias en los metadatos. Para impedir estas inconsistencias, sólo nodos en una partición deberán
continuar con el procesamiento de archivos, mientras que todos los demás nodos lo suspenden.
GPFS logra esto del siguiente modo: sólo se permite que los nodos en la partición mayoritaria,
es decir, la partición que contiene la mayoría de los nodos, realicen el procesamiento de archivos
en un momento dado. GPFS contiene una capa de servicios grupales que usa mensajes de pulso
de vida para detectar averías de nodos; esta capa avisa a un nodo cuando el nodo salió de la parti-
ción mayoritaria o cuando forma nuevamente parte de ella. Sin embargo, esta misma notificación
puede retrasarse en forma indefinida debido a averías de comunicación, por lo que el GPFS usa
características en el subsistema de E/S para impedir que aquellos nodos que no están incluidos en
la partición mayoritaria accedan a discos. El GPFS usa una política de copiado para protegerse
contra averías de discos.

22 MAQ. CAP. 19(F0694).indd 746 8/10/07 1:24:55 AM


Ejercicio 19 747

19.6.4 Windows

El sistema de archivos de Windows Server 2003 provee dos herramientas para el copiado de
datos y distribución de datos:

• La compresión diferencial remota (RDC) es un protocolo para el copiado de archivos que


reduce el tráfico de copiado de archivos y la coherencia de archivos entre servidores.
• Espacio de nombre DFS es un método para formar un árbol virtual de carpetas ubicadas
en diferentes servidores, por lo que un cliente ubicado en un nodo puede acceder a es-
tas carpetas.

El copiado se organiza por medio de la noción de un grupo copiado, que es un grupo de


servidores de un grupo de carpetas. Este arreglo de copiado es conveniente, ya que se accederán
varias carpetas del grupo de carpetas a partir del mismo servidor cuando ocurren fallas. El pro-
tocolo RDC se usa para sincronizar copias de una carpeta copiada a través de los servidores en
su grupo de copiado. Este protocolo transmite sólo los cambios hechos en un archivo, o sólo las
diferencias entre las copias de un archivo, entre diferentes miembros de un grupo de copiado,
conservando de este modo el ancho de banda entre servidores. Las copias de un archivo son
periódicamente sincronizadas. Cuando se crea un nuevo archivo, la RDC cruzada de archivos
identifica archivos existentes que son parecidos al nuevo archivo, y transmite sólo las diferencias
entre el nuevo archivo y uno de estos archivos a los miembros del grupo de copiado. Este proto-
colo reduce el ancho de banda consumido por la operación de copiado.
El espacio de nombre DFS es creado por un administrador del sistema. Para cada carpeta en
el espacio de nombres, el administrador especifica una lista de servidores que contienen una co-
pia de la carpeta. Cuando un cliente se refiere a una carpeta compartida que aparece en el espacio
de nombre, se contacta al servidor de espacio de nombres para que resuelva el nombre en el árbol
virtual. El servidor devuelve una remisión al cliente, la cual contiene una copia de la carpeta.
El cliente contacta al primer servidor en esta lista para acceder a la carpeta. Si este servidor no
responde y se habilita el failback (recuperación) del cliente, se le notifica al cliente de esta falla
y procede a contactar al siguiente servidor de la lista. Si la lista de servidores contiene entonces
dos servidores, el segundo servidor actúa como un hot standby para el primer servidor.

EJERCICIO 19
1. Escriba una breve nota sobre la influencia del diseño de servidores de archivos con estado y sin estado
sobre la tolerancia a fallas en los nodos de cliente y servidor.
2. Analice cómo puede implementarse la semántica de sesiones.
3. ¿Deberá un DFS mantener buffers de archivos en un nodo de servidor o en un nodo de cliente? ¿Cuál es
la influencia de esta decisión sobre la semántica de compartición de archivos de Unix (véase la sección
7.9) y sobre la semántica de sesiones?
4. Analice cómo deberá protegerse un cliente contra averías en un sistema de archivos distribuidos que
usa a) un diseño de servidor con estados, b) un diseño de servidor sin estados.
5. Un servidor de archivos genera múltiples hilos a fin de proveer una respuesta veloz a solicitudes de
clientes. Describa los requerimientos de sincronización de estos hilos.

22 MAQ. CAP. 19(F0694).indd 747 8/10/07 1:24:55 AM


748 CAPÍTULO 19 Sistemas de archivos distribuidos

6. Analice los problemas importantes que tienen que manejarse durante la recuperación de un nodo falla-
do en un sistema que usa el copiado de archivos para proveer confiabilidad.
7. Comente acerca de la validez y los aspectos de implementación del siguiente enunciado: “En un servidor
de archivos sin estado que usa la formación de cachés, la validación de cachés debe ser iniciada por el
cliente.”
8. Justifique el siguiente enunciado: “La formación de cachés se integra bien con la semántica de sesiones,
pero no con la semántica de Unix.”

BIBLIOGRAFÍA
Svoboda (1986) y Levy y Silberschatz (1990) hicieron estudios generales sobre sistemas de archivos distri-
buidos. Comer y Peterson (1986) analizan conceptos de nombrado y mecanismos de resolución de nom-
bres en muchos sistemas.
Lampson (1983) y Terry (1987) analizan el uso de consejos para mejorar el desempeño de un sistema
de archivos distribuidos, Makaroff y Eager (1990) hablan del efecto del tamaño de cachés sobre el desem-
peño de sistemas de archivos.
Brownbridge et al. (1982) estudian el sistema Unix United, que es un sistema temprano de archivado
en redes. Sandberg (1987) y Callaghan (2000) analizan el sistema Sun NFS, Satyanarayanan (1990) analiza
el sistema de archivos distribuidos Andrew, mientras que Kistler y Satyanarayanan (1992) describen el
sistema de archivos Coda. Braam y Nelson (1990) hablan de los cuellos de botella de desempeño en Coda e
Intermezzo, que es una secuela de Coda que incorpora el registro por diario. Russinovich y Solomon (2005)
estudian el copiado y servidores de archivos distribuidos en Windows.
Es posible que procesos de aplicación que operan en diferentes nodos de un clúster de sistemas de
cómputo hagan accesos paralelos a archivos. Thekkath et al. (1997) analizan un sistema de archivos dis-
tribuidos para clústers de sistemas de cómputo. Preslan et al. (2000) describen la tolerancia a fallas en un
sistema de archivos por clústers por medio del registro por diario. Carns et al. (2000) estudian un sistema
de archivos paralelos que provee un gran ancho de banda para accesos de archivos paralelos a datos en
archivos comunes. Schmuck y Haskin (2002) analizan el uso de discos compartidos en sistemas de archivos
paralelos y describen la sincronización distribuida y técnicas de tolerancia a fallas.

1. Brownbridge, D.R., L.F. Marshall y B. Randell (1982): “The Newcastle Connection or UNIXes of
the World Unite!”, Software—Practice and Experience, 12 (12), 1147-1162.
2. Braam, P.J. y P.A. Nelson (1999): “Removing bottlenecks in distributed file systems: Coda and
InterMezzo as examples”, Proceedings of Linux Expo, 1999.
3. Callaghan, B. (2000): NFS Illustrated, Addison Wesley.
4. Carns, P.H., W.B. Ligon III, R.B. Ross y R. Thakur (2000): “PVFS: A parallel file system for Linux
Clusters”, 2000 Extreme Linux Workshop.
5. Comer, D. y L.L. Peterson (1986): “A model of name resolution in distributed mechanisms”,
Proceedings of the 6th International Conference on Distributed Computing Systems, 509-514.
6. Ghemawat, S., H. Gobioff y S.T. Leung (2003): “The Google file system”, Proceedings of the 19th
ACM Symposium on Operating System Principles, 29-43.
7. Gray, C.G. y D.R. Cheriton (1989): “Leases: an efficient fault-tolerant mechanism for distributed
file cache consistency”, Proceedings of the 12th ACM Symposium on Operating Systems Princi-
ples, 202-210.
8. Kistler, J.J. y M. Satyanarayanan (1992): “Disconnected operation in the Coda file system”, ACM
Transactions on Computer Systems, 10, 1, 3-25.

22 MAQ. CAP. 19(F0694).indd 748 8/10/07 1:24:55 AM


Bibliografía 749

9. Lampson, B.W. (1983): “Hints for computer system designers”, Proceedings of the 9th Symposium
of Operating Systems Principles, 33-48.
10. Levy, E. y A. Silberschatz (1990): “Distributed File Systems: Concepts and Examples”, Computing
Surveys, 22 (4), 321-374.
11. Melamed, A.S. (1987): “Performance analysis of Unix-based network file systems”, IEEE Micro,
25-38.
12. Makaroff, D.J. y D.L. Eager (1990): “Disk cache performance for distributed systems”, Proceedings
of the 10th International Conference on Distributed Computing Systems, 212-219.
13. Preslan, K.W., A.P. Barry, J. Brassow, R. Cattelan, A. Manthei, E. Nygaard, S.V. Oort, D. Teigland,
M. Tilstra, M. O’Keefe, G. Erickson y M. Agarwal (2000): “Implementing journaling in a Linux
shared disk file system”, Proceedings of the Seventh IEEE Symposium on Mass Storage Systems,
351-378.
14. Russinovich, M.E. y D.A. Solomon (2005): Microsoft Windows Internals, 4a. ed., Microsoft Press,
Redmond.
15. Sandberg, R. (1987): The Sun Network File System: Design, Implementation, and experience, Sun
Microsystems, Mountain View.
16. Schmuck, F. y R. Haskin (2002): “GPFS: A shared-disk file system for large computing clusters”,
Proceedings of the First USENIX Conference on File and Storage Technologies, 231-244.
17. Satyanarayanan, M. (1990): “Scalable, secure, and highly available distributed file access”,
Computer, 23 (5), 9-21.
18. Svobodova, L. (1986): “File servers for network-based distributed systems”, Computing Surveys,
16 (4), 353-398.
19. Thekkath, C.A., T. Mann y E.K. Lee (1997): “Frangipani: A scalable DFS”. Proceedings of the
16th ACM symposium on Operating System Principles, 224-237.
20. Terry, D.B. (1987): “Caching hints in distributed systems”, IEEE Transactions on Software
Engineering, 13 (1), 48-54.

22 MAQ. CAP. 19(F0694).indd 749 8/10/07 1:24:55 AM


Capítulo
20
Seguridad de archivos
distribuidos

Un SO distribuido enfrenta amenazas a la seguridad porque los procesos que hay en él usan la
red para acceder a recursos distantes y para comunicar con otros procesos. Es posible que
la red incluya canales de comunicación públicos o procesos de comunicación que no estén bajo
el control del SO distribuido. Por tanto, un intruso ubicado en un procesador de comunicación
puede corromper mensajes interproceso o usar un ataque de mascarada para engañar a nodos
distantes o usar sus recursos sin autorización.
Un SO distribuido emplea técnicas de seguridad de mensajes para impedir que los intru-
sos puedan manipular mensajes interproceso. Estas técnicas realizan el cifrado por medio de
llaves públicas o llaves de sesión, que están distribuidas de manera segura en los procesos
de comunicación por medio de centros de distribución de llaves. Para impedir mascaradas,
los procesos de comunicación se autentifican unos a otros a través de medios de autentificación
de terceros de confianza que están disponibles en el SO distribuido.
En este capítulo analizaremos técnicas de seguridad de mensajes y autentificación de sis-
temas distribuidos. También estudiaremos cómo se asegura la integridad y la autenticidad de
datos mediante códigos de autentificación de mensajes y firmas digitales, respectivamente.

20.1 PROBLEMAS DE SEGURIDAD EN SISTEMAS DISTRIBUIDOS

Los recursos y servicios en un SO distribuido están ubicados en nodos seguros, es decir, en


nodos que están directamente bajo el control del SO distribuido. Como se muestra en la figura
20.1, un proceso usuario accede a un recurso remoto por medio de un mensaje enviado al pro-
ceso del coordinador de recursos. Este tipo de mensaje podrá viajar a través de redes públicas y
pasar a través de procesadores de comunicación que operan bajo sistemas operativos locales.
Los procesadores de comunicación emplean la técnica de almacenar y remitir para el enru-
tamiento de un mensaje hacia su destino. Por esta razón, los mensajes están expuestos a la obser-
vación e interferencia de entidades externas, por lo que plantean nuevas amenazas de seguridad
que no surgen en un sistema convencional. Éstas pueden clasificarse como sigue:

23 MAQ. CAP. 20(F0694).indd 750 8/10/07 1:25:28 AM


20.1 Problemas de seguridad en sistemas distribuidos 751

N1 N2

Proceso Proceso de
de usuario ·· CP ·· coordinador
remoto Pi Pj de recursos

Nodo seguro Nodo seguro

Figura 20.1 Amenazas a la seguridad en una red.

1. Fugas: Liberación del contenido de mensajes a usuario(s) no autorizado(s).


2. Manipulaciones: Modificación del contenido de mensajes.
3. Robos: Uso de recursos del sistema sin autorización.
4. Denegación de servicio a usuarios autorizados: Destrucción deliberada de recursos del
sistema que no alcanza a ser robo, es decir, destrucción sin ningún beneficio para el autor
o trastorno del acceso a recursos.

Las fugas y manipulaciones se califican como amenazas a la seguridad de mensajes. Po-


drán emplearse para modificar el texto de un mensaje, que es una amenaza a su integridad, o la
identidad de su transmisor, que es una amenaza a su autenticidad. Además de estas amenazas,
un intruso también podrá presentarse como usuario autorizado, falsificando e insertando mensa-
jes. Del mismo modo, un usuario podrá engañar a un coordinador de recursos que está ubicado
en un nodo remoto como otro usuario. Estas amenazas a la seguridad se abordan mediante dos
métodos:

• Técnicas de seguridad de mensajes: Se emplean técnicas especiales para frustrar ataques


a mensajes.
• Autentificación de usuarios remotos: Se proveen medios de confianza para autentificar
usuarios remotos.

Los ataques a la integridad y a la autenticidad se enfrentan por medio de una combinación de


estos dos medios.

20.1.1 Mecanismos y políticas de seguridad

La figura 20.2 muestra un arreglo de mecanismos y políticas de seguridad. La autentificación en


sistemas convencionales se describió en el capítulo 8. La que se requiere en sistemas distribui-
dos tiene dos nuevas facetas: el servicio de autentificación debe ser confiable y disponible para
todos los nodos en un sistema. Se usa el cifrado para asegurar la confidencialidad e integridad
de las bases de datos de autentificación y autorización. También se emplea para implementar la
seguridad de mensajes, codificando el texto de cada uno. Este tipo de cifrado es un mecanismo
de nivel inferior denominado distribución de llave para generar y distribuir llaves de cifrado para
su uso por parte de procesos de comunicación. Analizaremos la distribución de llaves de cifrado
en la sección 20.2.1.

23 MAQ. CAP. 20(F0694).indd 751 8/10/07 1:25:28 AM


752 CAPÍTULO 20 Seguridad de archivos distribuidos

Políticas

Cifrado

Autentifi- Distribución
cación de llave

Figura 20.2 Mecanismos y políticas para la seguridad en sistemas distribuidos.

20.1.2 Ataques a la seguridad en sistemas distribuidos

Los ataques a la seguridad en sistemas distribuidos, que normalmente se lanzan por medio de
mensajes, pueden clasificarse en las cuatro categorías resumidas en la tabla 20.1. La escucha ile-
gal puede presentarse en varias formas, como obtener el contenido de un mensaje, informaciones
estadísticas sobre mensajes que pasan a través de una liga y sobre mensajes intercambiados por
nodos específicos en el sistema. En un sistema informativo policiaco o militar, ese último tipo de
análisis puede usarse para revelar o adivinar las identidades de entidades en comunicación. La
manipulación de mensajes puede usarse para confundir el receptor de un mensaje. Este tipo de
ataque es factible en una red que se usa para almacenar y remitir.

Tabla 20.1 Clases de ataques a la seguridad en sistemas distribuidos

Ataque Descripción
Escucha clandestina Un intruso escucha mensajes interproceso a través de la red a fin de obtener
informaciones con respecto al contenido de mensajes o características estadís-
ticas de mensajes.
Manipulación de Un intruso intercepta mensajes, altera su contenido y los vuelve a insertar en
mensajes el flujo de comunicación.
Repetición de Un intruso hace copias de mensajes intercambiados por procesos comunicantes
mensajes e inserta las copias en el flujo de comunicación en un momento posterior,
como si fueran mensajes genuinos que se estén enviando en este momento.
Mascarada Un intruso es capaz de hacerse pasar por un usuario autorizado del sistema
mientras consume recursos y envía y recibe mensajes.

La repetición de mensajes puede usarse para lograr una variedad de objetivos infames.
El receptor de un mensaje repetido puede pensar que los mensajes se están intercambiando en
tiempo real. Si el receptor es un proceso usuario, puede engañársele para que tome acciones
que son innecesarias, absurdas o que representan un derroche de recursos. También podrá
revelar informaciones confidenciales sin desearlo o sin saber que lo está haciendo frente a un
intruso. Si el receptor es un proceso servidor, un mensaje repetido podrá conducir a la autenti-
ficación equivocada, lo que abre oportunidades para la suplantación de personalidad o el robo
de recursos.

23 MAQ. CAP. 20(F0694).indd 752 8/10/07 1:25:28 AM


20.2 Seguridad de mensajes 753

En la mascarada, un intruso es capaz de hacerse pasar por un usuario autorizado del sistema
para corromper o destruir informaciones que pertenecen al usuario por el que se hace pasar, o
podrá comunicarse con otros procesos y hacerles creer que están comunicándose con el usuario
al que imita.

Ataques pasivos y activos Los ataques a la seguridad pueden clasificarse en pasivos y


activos. Un ataque pasivo no interfiere de ninguna manera con el funcionamiento del sistema, ni
falsifica mensajes, ni destruye los genuinos. La escucha clandestina es un ejemplo de un ataque
pasivo. Un ataque activo sí interfiere con el funcionamiento de un sistema. La repetición, falsifi-
cación y destrucción de mensajes son ejemplos de este tipo de ataques. Los ataques pasivos son
más difíciles de detectar o de frustrar que los activos.

20.2 SEGURIDAD DE MENSAJES

Los planteamientos para la seguridad de mensajes pueden clasificarse en planteamientos orienta-


dos a ligas y planteamientos de punto a punto. En un planteamiento orientado a ligas se aplican
las medidas de seguridad en cada liga de una ruta de comunicación. Este planteamiento tiende a
ser caro, puesto que su costo depende del número de ligas a través de las cuales viaja el mensaje.
Por ejemplo, si un mensaje entre el proceso Pi, ubicado en el nodo N1, y el proceso Pj, ubicado en
el nodo N3, pasa a lo largo de la ruta N1-N2-N3, tiene que causar una carga general de seguridad
para las ligas N1-N2 y N2-N3. En el planteamiento de punto a punto, pueden emplearse medidas
de seguridad en forma selectiva por nodos o procesos en el sistema. Esta característica permite
que el usuario emplee medidas de seguridad con diversos grados de costo y sofisticación. En el
siguiente análisis vamos a suponer que se usan medidas de punta a cabo.
Se describen tres aproximaciones a la seguridad de mensajes. Éstas involucran encriptación
mediante llaves públicas, llaves privadas y llaves de sesión, respectivamente. La tabla 20.2 re-
sume sus características.

Cifrado de llave privada El cifrado de llave privada (que también se llama cifrado de
llave secreta) es el enfoque clásico con base en llaves simétricas. Cada proceso Pi tiene una llave
privada Vi, conocida por él mismo y por unos pocos procesos más en el sistema. Un proceso
que envía un mensaje a Pi debe codificarlo por medio de Vi. La ventaja principal del cifrado por
llaves privadas es que el número de llaves de cifrado en el sistema está limitado a n, donde n
es el número de entidades comunicantes en el sistema. Puesto que todos los mensajes enviados
para el proceso Pi son codificados con la misma llave, Pi no necesita conocer la identidad de un
transmisor de un mensaje a fin de leer éste.
El cifrado por llave privada sufre de algunas desventajas. Cada proceso transmisor nece-
sita conocer la llave privada de Pi. Por tanto, muchos procesos conocen la llave privada de un
proceso y un intruso podrá descubrirla debido a la negligencia de alguien. La llave privada está
expuesta a ataques de intrusos durante un largo periodo, por lo que las oportunidades de un
ataque exitoso a la llave privada aumentan con el tiempo; sin embargo, no es posible cambiar la
llave privada de un proceso porque la conocen muchos otros en el sistema.

23 MAQ. CAP. 20(F0694).indd 753 8/10/07 1:25:29 AM


754 CAPÍTULO 20 Seguridad de archivos distribuidos

Tabla 20.2 Técnicas de cifrado para la seguridad de mensajes

Técnica Descripción
Cifrado por llave Emplea el cifrado simétrico. Un proceso Pi en el sistema tiene
privada una llave única de cifrado que se denomina llave privada. Todos
los mensajes que se envían a Pi deben estar cifrados mediante
Vi. El proceso Pi los descifra mediante Vi. La llave privada de un
proceso queda expuesta a ataques de intrusos a lo largo de toda
la vida útil de un proceso.
Cifrado por llave Emplea el cifrado asimétrico. Un proceso Pi en el sistema tiene
pública un par de llaves únicas (Ui, Vi). Ui es la llave pública que se da
a conocer a todos los procesos en el sistema, mientras que Vi
es la llave privada, que se mantiene secreta. Los mensajes a
Pi son cifrados por medio de Ui, pero Pi los descifra mediante
Vi. Principalmente se usa el algoritmo de Rivest-Shamir-Adel-
man (RSA) para generar el par de llaves para un proceso. La
llave privada de un proceso no queda expuesta a ataques de
intrusos.
Cifrado por llave A un par de procesos en comunicación (Pi, Pj) se asigna una
de sesión llave de sesión SKij cuando los dos inician una sesión de comu-
nicación. La llave de sesión se usa para el cifrado simétrico de
todos los mensajes intercambiados durante la sesión. La llave
de sesión tiene una vida más corta que una llave privada o pú-
blica, por lo que sufre menos exposición a ataques de intrusos.

Los procesos de usuarios no conocen las llaves privadas de otros procesos de usuarios, por
lo que el cifrado por llave privada no es útil para la seguridad de mensajes interproceso en ge-
neral. Los procesos del SO conocen las llaves privadas de los procesos de usuarios, por lo que
usan el cifrado por llave privada mientras se comunican con procesos de usuarios. Como se verá
en la sección 20.2.1, esta herramienta se usa en la implementación de centros de distribución de
llaves. Los procesos de usuarios tienen que usar otro método de cifrado para la comunicación
entre sí.

Cifrado por llave pública Cada proceso Pi tiene un par de llaves (Ui, Vi). Ui es la llave pú-
blica de Pi, lo que puede darse a conocer a todos los procesos en el sistema. Vi es la llave privada,
que solamente conoce Pi. Ui y Vi se seleccionan de tal manera que

• Vi no puede ser adivinado por Ui; y


• para todos los mensajes m
Dvi (EUi (Pm)) ⫽ Pm ∀i (20.1)

donde Pm es la forma de texto claro del mensaje m (véase la sección 8.5) y E, D son las
funciones de cifrado y descifrado, respectivamente.

Tres pasos se encuentran involucrados en la transmisión de un mensaje m del proceso Pj al


proceso Pi.

23 MAQ. CAP. 20(F0694).indd 754 8/10/07 1:25:29 AM


20.2 Seguridad de mensajes 755

1. El proceso Pj cifra el mensaje mediante la llave pública del proceso destinatario Pi, es
decir, mediante Ui..
2. El mensaje cifrado, es decir, EUi (Pm), se transmite a través de la red y es recibido por el
proceso Pi.
3. El proceso Pi descifra el mensaje recibido por medio de su propia llave privada, es decir,
mediante Vi. Por tanto, realiza Dvi (EUi (Pm)), lo que produce Pm.

Cuando se usa el cifrado por llave pública, el SO puede publicar directorios de llaves pú-
blicas para todos los procesos existentes en el sistema. Un proceso puede consultar el directorio
para obtener la llave pública de un proceso con el cual desea comunicarse.
El algoritmo de cifrado RSA se usa para generar pares de llaves (Ui, Vi) que satisfacen la
ecuación (20.1). Supongamos que (u, v) sea un par de llaves generado por el algoritmo RSA.
Dados dos números x y y, ambos menores que un número entero seleccionado n, el cifrado y
descifrado usando u y v, respectivamente, se lleva a cabo de la siguiente manera:

Eu (x) ⫽ xu mod n
Dv (y) ⫽ yv mod n

Para cifrar y descifrar un mensaje m, se usa el algoritmo RSA como una cifra de bloque con un
tamaño de bloque s, que se elige de tal modo que n ⬎ 2s. x es entonces el número formado por la
cadena de bits que se encuentra en un bloque de Pm —la forma de texto claro del mensaje m— y
y es el número formado por la cadena de bits en el bloque correspondiente de Cm —la forma de
texto cifrado del mensaje m—. De esta manera, x ⬍ 2s y y ⬍ 2s, por lo que cada uno de ellos es
menor que n, como corresponde.
El algoritmo RSA elige n como producto de dos grandes números primos p y q. Normalmen-
te p y q tienen 100 dígitos cada uno, lo que hace que n sea un número de 200 dígitos. Suponiendo
que u y v sean las llaves públicas y privadas, para satisfacer la relación 20.1, v deberá ser rela-
tivamente primo a (p ⫺ 1) ⫻ (q ⫺ 1) (es decir, v y (p ⫺ 1) ⫻ (q ⫺ 1) no deberán tener ningún
factor común excepto 1, y u deberá satisfacer la relación

u ⫻ v mod [(p ⫺ 1) ⫻ (q ⫺ 1)] ⫽ 1.

La selección de u y v como llaves públicas y privadas implica que se usa un valor estándar
de n en el sistema. En forma alternativa, el par (u, n) puede usarse como llave pública y el par
(v, n) puede usarse como llave privada de un proceso. Esto permitirá que puedan usarse diferen-
tes valores de n para diferentes pares de procesos.
Un ataque cifrado de RSA puede ser exitoso si n puede incluirse en p y q. Sin embargo, se
estima que la factorización de un número de 200 dígitos, que es lo que se necesitará para romper
el cifrado, requerirá cuatro mil millones de años en una computadora que puede ejecutar un mi-
llón de operaciones por segundo.
El cifrado por llave pública sufre de algunos inconvenientes cuando se compara con el
cifrado por llave privada. Las llaves que se usan en el cifrado por llave pública son aproxima-
damente de magnitud mayor en tamaño que las llaves privadas. Esto es inevitable, puesto que
las llaves públicas tienen que ser grandes para que la factorización sea de un precio prohibitivo.

23 MAQ. CAP. 20(F0694).indd 755 8/10/07 1:25:29 AM


756 CAPÍTULO 20 Seguridad de archivos distribuidos

Las operaciones de cifrado y descifrado también son muy caras en comparación con el cifrado
simétrico; en muchas situaciones, estas operaciones son hasta 1 000 veces más lentas. Por ende,
no es práctico usar el cifrado por llave pública para mensajes interproceso. En lugar de esto, para
comunicar con seguridad se usa una llave de sesión a un par de procesos que tienen la intención
de iniciar una sesión de comunicación. Este aspecto se analizará en la sección 20.2.1.

Llaves de sesión Los procesos Pi y Pj obtienen una llave de sesión, también conocida como
llave de conversación, para una sesión de comunicación. Esta llave se usa para el cifrado simé-
trico durante la sesión y se descarta al final de ella. Si los procesos desean entrar en otra sesión
en algún momento futuro, obtienen una llave nueva. Este planteamiento limita la exposición de
una llave de cifrado a un intruso, reduciendo de esta manera el riesgo de un ataque exitoso al
sistema criptográfico.

20.2.1 Distribución de llaves de cifrado

Un proceso necesita saber qué llave de cifrado debe usar para la comunicación con otro proce-
so. El SO contiene un servicio interactivo llamado centro de distribución de llaves (KDC) para
proveer estas informaciones. La figura 20.3 muestra el esquema de un centro de distribución de
llaves. Un proceso Pi hace una solicitud al KDC para una llave de cifrado a fin de comunicar
con un proceso Pj. El KDC regresa una llave k. Pi usa esta llave para cifrar un mensaje m para
su envío al proceso Pj. Si los procesos usan llaves públicas para comunicarse entre sí, el KDC
lleva un directorio que contiene todas las llaves públicas de todas las entidades existentes en el
sistema. Si lo que usan son llaves de sesiones, el KDC no lleva un directorio, sino que genera
cada nueva llave de sesión cada vez que se lo solicitan.

KDC
Solicitar llave
(Pi , Pj ) llave k

Ek (m) Pj
Pi

Figura 20.3 Centro de distribución de llaves (KDC) en un SO distribuido.

Un tema importante en el esquema del KDC es el protocolo que se usa para pasar las llaves
con seguridad. Si se solicita una llave pública, sólo tiene que pasarse al solicitante. Cuando un
proceso Pi solicita una llave de sesión para comunicarse con el proceso Pj, la llave tiene que pa-
sarse tanto a Pi como a Pj. Sin embargo, Pj es inconsciente de que Pi está interesado en establecer
una sesión con él, por lo que el KDC no envía la llave de sesión directamente a Pj. En su lugar, Pi
puede enviar la llave de sesión a Pj junto con su primer mensaje. Estos protocolos de transmisión
de llaves se describen a continuación.

23 MAQ. CAP. 20(F0694).indd 756 8/10/07 1:25:29 AM


20.2 Seguridad de mensajes 757

Distribución de llaves públicas Los siguientes mensajes se intercambian entre Pi, el pro-
ceso solicitante y el KDC:

1. Pi → KDC : EUkdc (Pi , Pj )


2. KDC → Pi : EUi (Pj , Uj ) (20.2)

Pi envía su propia id y Pj la id del proceso destinatario deseado por el KDC. Este mensaje
está cifrado por medio de Ukdc, la llave pública del KDC. El KDC responde enviando Uj, la
llave pública de Pj, cifrada mediante la llave pública de Pi. El objetivo del cifrado no es
la protección de la confidencialidad de la llave de Pj, porque un intruso puede obtener esta
llave en forma legítima haciendo una solicitud al KDC; el propósito es más bien prevenir que
un intruso pueda manipular los mensajes entre Pi y el KDC a fin de perpetrar un ataque de
denegación de servicio. En ausencia del cifrado, un intruso podrá haber manipulado el men-
saje de Pi, cambiando Pj a algún Pk, por lo que Pi no podrá obtener la llave de Pj, o el intruso
podrá haber manipulado el mensaje del KDC, cambiando la llave de Pj, que se está pasando
a Pi. Cuando se usa el cifrado, tanto el KDC como Pi reconocerán los mensajes manipulados
y los descartarán.

KDC
1
Solicitar
llave 2
de sesión Enviar
llave
de sesión
Pi Pj
Pasar llave
de sesión
3

Figura 20.4 Distribución de llaves de sesión.

Distribución de llaves de sesión Cuando Pi desea obtener una llave de sesión para comu-
nicar con Pj, ésta deberá darse a conocer tanto a Pi como a Pj. La figura 20.4 ilustra cómo se
logra esto en tres pasos. En el primero, Pi envía un mensaje de solicitud al KDC que contiene
su propia id y la id de Pj. El KDC asigna una llave de sesión SKi,j para la sesión entre Pi y Pj y
envía una unidad cifrada a Pi que contiene SKi,j en su respuesta. La unidad cifrada está formada
de tal modo que sólo Pj la puede descifrar. Pi pasa esta unidad cifrada a Pj en su primer mensaje
o en un mensaje especial para este propósito. Cuando Pj recibe esta unidad de Pi, extrae SKi,j y
se queda con ella durante la sesión con Pi.
En un sistema de llaves privadas, este intercambio puede implementarse de la siguiente
forma:

23 MAQ. CAP. 20(F0694).indd 757 8/10/07 1:25:30 AM


758 CAPÍTULO 20 Seguridad de archivos distribuidos

1. Pi → KDC : Pi , Pj
2. KDC → Pi : EVi (Pj , SK i, j , EVj (Pi , SK i, j )) (20.3)
3. Pi → Pj : EVj (Pi , SK i, j ), ESK i, j (<message>)

En el segundo paso, el KDC envía una respuesta a Pi que está cifrada por medio de la llave
privada de Pi. Esta respuesta contiene la llave de sesión SKi,j y Evj (Pi, SKi,j), que es la llave de
sesión cifrada mediante la llave privada de Pj. Pi descifra el mensaje del KDC por medio de su
propia llave privada para obtener la llave de sesión SKi,j. El descifrado también produce Evj (Pi,
SKi,j). Pi copia esta unidad en el primer mensaje que envía a Pj. Cuando Pj descifra este mensaje,
obtiene SKi,j, que usa para descifrar todos los mensajes posteriores de Pi.
En un sistema de llaves públicas, no es necesario que las llaves de sesión sean distribui-
das por el KDC; un proceso transmisor puede elegir una llave de sesión. Este planteamiento
es posible porque los procesos pueden comunicarse entre sí por medio de llaves públicas. Por
tanto, un proceso Pi puede emplear el siguiente protocolo para transmitir una llave de sesión al
proceso Pj:

1. Pi → KDC : EUkdc (Pi , Pj )


2. KDC → Pi : EUi (Pj , Uj ) (20.4)
3. Pi → Pj : EUj (Pi , SK i, j ), ESK i, j (<message>)

Los primeros dos pasos de este protocolo son idénticos a los primeros dos pasos del protocolo
(20.2), es decir, proveen a Pi la llave pública de Pj. Entonces el propio Pi genera una llave de
sesión SKi,j y pasa la llave de sesión y su primer mensaje a Pj usando el paso 3.

20.2.2 Prevención de ataques de repetición de mensajes

En un ataque de repetición de mensajes, un intruso simplemente copia mensajes que pasan a


través de la red y los “repite” en el futuro. Un mensaje repetido podrá falsamente llevar a su re-
ceptor a tomar acciones equivocadas o duplicadas que podrán afectar la consistencia de datos o
a revelar informaciones confidenciales. Por ejemplo, en un sistema que usa llaves de sesión, un
intruso podrá repetir el mensaje del paso 3 en el protocolo (20.3) o en el protocolo (20.4). Cuando
Pj recibe el mensaje repetido, se engañará al pensar que Pi está comunicando con él por medio
de la llave de sesión SKi,j. Usando el proceso Pj responde a este mensaje; el intruso repetirá el
siguiente mensaje copiado. De esta manera podrá repetir una sesión completa.
El receptor de un mensaje puede emplear el protocolo de desafío-respuesta para verificar si
el intercambio de mensajes se está llevando a cabo en tiempo real. Los pasos del protocolo de
desafío-respuesta son los siguientes:

• Desafío: Cuando el proceso Pj recibe un mensaje originado por un proceso Pi, lanza un
desafío a Pi para comprobar que está ocupado con un intercambio de mensajes en tiempo
real. Este desafío tiene la forma de un mensaje que contiene una cadena de desafío, que
está cifrada de tal modo que sólo el proceso Pi la pueda descifrar.

23 MAQ. CAP. 20(F0694).indd 758 8/10/07 1:25:30 AM


20.2 Seguridad de mensajes 759

• Respuesta: Al recibir el mensaje de desafío, el proceso Pi deberá descifrarlo, obtener la


cadena de desafío, transformarla de una manera esperada por Pj, cifrar el resultado de tal
modo que sólo Pj lo pueda descifrar y mandarlo de vuelta a Pj.
• Detectar: Al recibir un mensaje de respuesta, el proceso Pj descifra el mensaje y verifica
si el contenido descifrado coincide con sus expectativas. La falta de coincidencia indi-
ca que está sujeto a un ataque de repetición.

Un desafiador podrá enviar un número como cadena de desafío y esperar una respuesta,
que es el resultado de alguna transacción sencilla de este número, por ejemplo, sumar 1; sin
embargo, el desafiador deberá usar un número distinto en cada desafío, de tal forma que la repe-
tición de una conversación vieja no proveerá la respuesta esperada. Dos opciones para una cade-
na de desafío son un número al azar o la hora actual del día. El verdadero valor de una cadena de
desafío es irrelevante, por lo que se llama nonce (valor que sólo se usa una vez).
El protocolo de desafío-respuesta deberá usarse en cada situación donde un ataque de repe-
tición de mensajes sea significativo. Por ejemplo, considere la distribución de llaves de sesiones
a través del protocolo (20.3). Un intruso podrá salvar el mensaje del paso 3 y repetirlo en algún
momento futuro para engañar al proceso Pj y hacerlo que inicie una conversación con él usando
SKi,j. Por tanto, antes de usar la llave de sesión obtenida en el paso 3, el proceso Pj usará el
protocolo de desafío-respuesta para asegurarse que la conversación se está llevando a cabo en
tiempo real:

4. Pj → Pi : ESK i, j (n)
5. Pi → Pj : ESK i, j (n 1)

Aquí n es un nonce. Se espera que Pi obtenga n por medio del descifrado, usando SKi,j, le sume 1,
cifre el resultado por medio de la llave de sesión y lo devuelva a Pj. Un intruso no será capaz de
realizar estas acciones en forma correcta, puesto que no conoce SKi,j.

20.2.3 Autentificación mutua

A fin de derrotar ataques de mascarada, los procesos involucrados en una sesión de comunica-
ción deberán validar mutuamente sus identidades al inicio de la sesión. El protocolo de desafío-
respuesta implícitamente verifica la identidad del proceso que responde a un desafío, por lo que
puede emplearse para este propósito. Considere el protocolo (20.4) que se usa para seleccionar
llaves de sesiones en un sistema de llaves públicas. En el paso 3, Pi envía la llave de la sesión
a Pj en un mensaje que está cifrado mediante la llave pública de Pj. En principio, cualquier pro-
ceso podrá enviar un mensaje de este tipo y engañar a Pj para que piense que está involucrado
en una sesión con el proceso Pi. Por esta razón, Pj debe autentificar a Pi antes de iniciar una sesión
con él. Esto puede lograrse como lo muestra el siguiente protocolo, cuyos primeros tres pasos
son idénticos al protocolo (20.4):

1. Pi → KDC : EUkdc (Pi , Pj )


2. KDC → Pi : EUi (Pj , Uj )
3. Pi → Pj : EU j (Pi , SK i, j )
4. Pj → Pi : EUi (Pj , n)

23 MAQ. CAP. 20(F0694).indd 759 8/10/07 1:25:30 AM


760 CAPÍTULO 20 Seguridad de archivos distribuidos

5. Pi → Pj : EU j (n 1)
6. Pi → Pj : ESK i, j (<message>)

En el paso 4, Pj envía un nonce n cifrado por medio de la llave pública de Pi. La identidad de
Pi es verificada por su capacidad de descifrar este mensaje, extraer el nonce y transformarlo en
la forma esperada. ¡Observe que en el paso 4 Pj no debe cifrar su mensaje por medio de la llave
de sesión SKi,j, puesto que el intruso será capaz de descifrar un mensaje de este tipo si hubiese
falsificado el mensaje en el paso 3!

20.3 AUTENTIFICACIÓN DE DATOS Y MENSAJES

La autenticidad de datos requiere que un proceso sea capaz de verificar que éstos proceden o
fueron enviados por una persona o proceso reclamado y que no haya sido manipulado por un
intruso. Ese último aspecto implica la integridad de los datos.
La integridad de datos se asegura del siguiente modo: cuando el dato d se genera o va a
ser transmitido, se usa una función especial hash de un solo sentido para computar un valor
hash v. Este valor hash, también conocido como compendio de mensajes, tiene una longitud
fija independientemente del tamaño de los datos. Aparte de las propiedades de funciones de
sentido único que se describieron en la sección 8.5.1, esta función hash de un solo sentido tiene
la propiedad de que un ataque de cumpleaños no es factible, es decir, el valor hash v del dato d
es impráctico para construir otro dato d⬘ cuyo valor hash también sea v. El dato y el valor hash
se guardan y transmiten como un par <d, v>. Para verificar la autenticidad de d, se calcula su
valor hash de nuevo, por medio de h, y se compara con v. De la propiedad especial de h que se
menciona antes, se deduce que el dato d está en su forma original si los dos coinciden; de lo
contrario, d ha sido manipulado. Para que este método funcione, el valor v también deberá estar
protegido contra la manipulación o sustitución por parte de un intruso; de no ser así, éste podrá
sustituir un par <d, v> por otro par <d⬘, v⬘>, engañando a otros procesos para hacerles pensar
que el dato d⬘ es genuino. Así, la persona o proceso que origina o transmite d cifra v o el par
<d, v> de tal forma que puede detectarse la manipulación o sustitución de v. Observe que es
más barato cifrar v que <d, v>.
La autenticidad requiere una verificación más. El cifrado de v o <d, v> deberá realizarse de
tal modo que su descifrado exitoso establecerá la identidad de la persona o proceso que origina
o transmite d. Este requerimiento se satisface estableciendo autoridades de certificación que
proveen un método seguro para distribuir información respecto de las llaves de cifrado usadas
por personas o procesos.

20.3.1 Autoridades de certificación y certificados digitales

Una autoridad de certificación (AC) asigna llaves públicas y privadas a una entidad, se trate de
una persona o de un proceso, después de precisar su identidad por medio de algún medio de ve-
rificación física. Las llaves son válidas durante un periodo específico de tiempo. La autoridad de
certificación también actúa como un centro de distribución de llaves como lo hemos analizado
en la sección 20.2.1: lleva un registro de todas las llaves asignadas por él, y cuando un proceso

23 MAQ. CAP. 20(F0694).indd 760 8/10/07 1:25:31 AM


20.3 Autentificación de datos y mensajes 761

lo requiere para la llave pública de una persona o proceso, emite un certificado de llave pública
que incluye las siguientes informaciones:

• Número de serie del certificado.


• Nombre distinguido del dueño (DN).
• Información de identificación del dueño, como la dirección.
• Llave pública del dueño.
• Fecha de emisión y fecha de vencimiento, así como el nombre distinguido del emisor.
• Firma digital con la información antes mencionada por la autoridad de certificación.

Varias autoridades de certificación pueden operar en paralelo. Un servidor obtendrá un cer-


tificado de una de ellas. Si un cliente sabe con qué autoridad de certificación está registrado un
servidor, podrá solicitar el certificado de llave pública del servidor a la autoridad de certificación.
En forma alternativa, si conoce la dirección IP del servidor, podrá solicitar que el servidor remita
su propio certificado de llave pública.
El objeto de información más importante en el certificado de una entidad es la llave pública
de la entidad. Sin embargo, antes de que el receptor del certificado la use para comunicarse con
la entidad, deberá asegurarse de que el certificado es genuino y de que pertenece a la entidad
con la que desea comunicarse, es decir, que no está sujeto a un ataque a la seguridad denomi-
nada el hombre en medio. En este ataque un intruso se hace pasar por un servidor. Cuando un
cliente solicita del servidor un certificado digital, el intruso intercepta el mensaje y le envía
al cliente un certificado falsificado que contiene la llave pública del intruso. Ahora bien, si pue-
de interceptar mensajes subsiguientes del cliente dirigidos al servidor, podrá leer estos mensa-
jes. Si así lo desea, puede iniciar una conversación con el servidor genuino, esta vez haciéndose
pasar por el cliente, y pasar los mensajes del cliente al servidor después de leerlos. Ni el cliente
ni el servidor serán capaces de descubrir que están sujetos a un ataque exitoso del hombre en
medio.
El certificado de llave pública contiene muchos objetos de información que se usan para
impedir estos ataques. El certificado está digitalmente firmado por la autoridad de certificación.
El cliente puede usar esta firma digital para asegurar que el certificado no ha sido falsificado.
Para ello necesita la llave pública de la autoridad de certificación que emitió el certificado. Si
aún no la conoce, podrá solicitar un certificado de una autoridad de certificación de orden mayor
para esta autoridad de certificación. Una vez establecida la autenticidad del certificado, puede
verificar si el certificado es válido, revisando si la fecha actual cae dentro del periodo de validez
del certificado. Si conoce la dirección IP del servidor, puede verificarla mediante una compara-
ción con la información de la dirección IP que se menciona en el certificado. Sólo si todas estas
revisiones son exitosas, comienza el intercambio de mensajes con el servidor.

20.3.2 Autentificación de mensajes y firma digital

Se usa un código de autentificación de mensajes (MAC) para verificar la integridad de datos.


Un proceso que origina o transmite el dato d obtiene MACd, el código de autentificación de

23 MAQ. CAP. 20(F0694).indd 761 8/10/07 1:25:31 AM


762 CAPÍTULO 20 Seguridad de archivos distribuidos

mensajes, de la siguiente manera: genera un compendio de mensajes v para d por medio de una
función de hash de un solo sentido. Cifra v mediante una llave de cifrado que sólo es conocida
por él y el receptor de destino de d. Entonces almacena o transmite el par < d, MACd >. Sólo el
receptor de destino de d puede revisar y verificar la integridad de d.
Se usa una firma digital para asegurar la autenticidad de datos. Una persona o proceso que
origina o transmite el dato d obtiene v de d como se mencionó antes. En ese momento obtiene
DSd, la firma digital de d, cifrando v y, en forma opcional, un sello de tiempo, usando su propia
llave privada. El par ⬍ d, DSd ⬎ entonces se guarda o se transmite. Cualquier proceso que desea
verificar la autenticidad de d descifra DSd mediante la llave pública del originador de d. El des-
cifrado exitoso da validez a la integridad de d y también identifica su originador o transmisor en
forma no repudiable, es decir, el originador o transmisor identificado no puede negarse a crear
o enviar los datos. La no repudiabilidad se desprende del hecho de que los datos fueron cifrados
por medio de la llave privada del originador o transmisor, que sólo es conocida por él mismo. La
firma digital también puede usarse para detectar cualquier modificación de datos después de que
éstos fueron creados o enviados por un proceso.
La figura 20.5 ilustra los pasos que se deben seguir en el uso de una firma digital. El
transmisor aplica una función hash de un solo sentido al texto de un mensaje para obtener un
compendio de mensajes. Lo firma con su propia llave y mediante el cifrado. Esta firma digital
se añade al final del texto del mensaje antes de enviarlo. El receptor aplica la misma función
hash de un solo sentido al texto del mensaje que recibe a fin de obtener su compendio de men-
sajes. Entonces obtiene un certificado de llave pública del transmisor del mensaje y usa la llave
pública que contiene el mensaje para descifrar la firma digital. Este paso produce el compendio
de mensajes que fue computado por el transmisor. El receptor compara este compendio de men-
sajes con su propio compendio de mensajes. El mensaje sólo es auténtico si los dos coinciden
y si el sello de tiempo en la firma digital está dentro del periodo de validez del certificado de
llave pública.

20.4 AUTENTIFICACIÓN POR TERCEROS

Un sistema abierto usa interfaces estándar y bien especificadas para otros sistemas. Un proceso
en cualquier nodo con interfaces coincidentes puede solicitar el acceso a recursos y servicios de
un sistema abierto. Este hecho plantea un problema obvio en la autentificación: ¿cómo sabe un
servidor si un proceso que desea actuar como su cliente fue creado por un usuario autorizado?
Una solución es requerir que cada servidor autentifique a cada usuario por medio de una con-
traseña. Este enfoque es inconveniente, puesto que cada servidor tendrá que poseer una base de
datos de autentificación que abarca a todo el sistema, y cada usuario será autentificado varias ve-
ces mientras usa el sistema. Una alternativa es usar un tercer autentificador y un arreglo seguro
mediante el cual el autentificador pueda introducir un usuario autorizado a un servidor. De este
modo se evita que cada servidor tenga que autentificar a cada usuario.
Analizaremos dos protocolos para la autentificación por terceros en un sistema distribuido.
El protocolo Kerberos emplea una base de datos de autentificación, mientras que el protocolo de
capa de sockets de seguridad (SSL) realiza la autentificación en forma descentralizada.

23 MAQ. CAP. 20(F0694).indd 762 8/10/07 1:25:31 AM


20.4 Autentificación por terceros 763

Texto del Texto del


4
mensaje mensaje
1 5
Hash de un Hash de un
solo sentido solo sentido
Compendio Compendio
2 de mensajes 7 de mensajes
3 Firma Firma 6 No
Cifrado
digital digital
Cifrado =? N
auténtico

Mensaje Mensaje Y
Mensaje
enviado recibido
Llave privada Llave pública auténtico
del transmisor del transmisor

Acciones del lado del transmisor Acciones del lado del receptor

Paso Descripción
1. Compendio de mensajes Se aplica una función hash de un solo sentido al texto del
del texto del mensaje mensaje para producir un compendio de mensajes, que es
una cadena de bits de longitud estándar.
2. Crear firma digital El resultado de la función hash y un sello de tiempo son
cifrados por medio de la llave privada del transmisor. El
resultado del cifrado es la firma digital.
3. Estampar la firma Se añade la firma digital al final del texto del mensaje.
4. Transmisión El mensaje que consiste en el texto del mensaje y la firma
digital se transmite a su destino.
5. Compendio de mensajes Se aplica al texto del mensaje la misma función hash de
del texto recibido un solo sentido que se usa en el transmisor para producir
una cadena de bits de longitud estándar.
6. Descifrado de la La firma digital al final del mensaje es extraída y desci-
firma digital frada por medio de la llave pública del transmisor.
7. Verificación de Se comparan el compendio de mensajes producido en el
autenticidad paso 5 y el resultado del descifrado en el paso 6. El men-
saje es auténtico si los dos son idénticos.

Figura 20.5 Autenticidad del mensaje por medio de la firma digital.

23 MAQ. CAP. 20(F0694).indd 763 8/10/07 1:25:31 AM


764 CAPÍTULO 20 Seguridad de archivos distribuidos

20.4.1 Kerberos

Kerberos es un tercer autentificador desarrollado como parte del proyecto Athena del MIT para
su uso en un ambiente de sistemas abiertos. Habilita a un usuario para comprobar su identidad
ante los servidores en un sistema abierto sin estar sujeto a repetidas autentificaciones. Se auten-
tifica al usuario por medio de una contraseña en el momento de abrir la sesión. El servicio de
autentificación emite boletos a un usuario autentificado; cada boleto es una capacidad que con-
cede el privilegio de acceso a un servidor. El usuario presenta un boleto a un servidor cada vez
que desea usar su servicio. El servidor provee el servicio si el boleto es válido. A cada usuario
y servidor existentes en el sistema se les asigna una llave privada. Se usan llaves de sesión para
asegurar la seguridad de los mensajes. Las llaves son generadas por medio de un esquema pare-
cido a la figura 20.4. Para limitar la exposición de una llave de sesión a intrusos, sólo es válida
durante un periodo de tiempo limitado. Se usan sellos de tiempo para implementar este aspecto
y para frustrar ataques de repetición de mensajes. Por tanto, los nodos del sistema deben contener
relojes aproximadamente sincronizados.
Un cliente es un proceso que opera en la computadora de un usuario y solicita servicios
remotos en su nombre. Cuando un cliente C quiere usar los servicios de un servidor Sj, crea un
nuevo autentificador y presenta un boleto para Sj y para el autentificador para Sj. El boleto se
usa para comunicar la llave de sesión al servidor en forma segura y contiene las id de cliente
y servidor —es decir, C y Sj —, un sello de tiempo que indica cuándo fue creado el boleto, así
como su tiempo de vida, es decir, de vencimiento. El boleto sólo es válido durante el periodo de
tiempo que inicia con el sello de tiempo y que termina con el tiempo de vida. Normalmente este
periodo dura aproximadamente 8 horas. Este arreglo limita la exposición de la llave de sesión a
ataques de intrusos. El autentificador presentado por C contiene la id y dirección de C, así como
un sello de tiempo cifrado por medio de la llave de sesión.
El servidor descifra el boleto mediante su propia llave, y verifica el sello de tiempo y el
tiempo de vida del boleto para asegurar que el boleto es válido. Entonces extrae la llave de
sesión y la usa para descifrar el autentificador. Después verifica el sello de tiempo en el au-
tentificador para asegurar que la solicitud fue generada en tiempo real y dentro del periodo de
validez del boleto. Sólo ejecuta el servicio solicitado por el cliente si todas estas revisiones son
exitosas. De este modo, un intruso no puede repetir autentificadores y boletos para obtener un
servicio.

Funcionamiento de Kerberos El sistema Kerberos tiene dos componentes principales: el


servidor de autentificación Kerberos (KAS) y el servidor de otorgamiento de boletos (TGS).
KAS autentifica a un usuario por medio de una base de datos en el momento de iniciar la sesión
de autentificación y le provee un boleto para el TGS. Éste habilita a un cliente para obtener
boletos de otros servidores en el sistema. Un usuario logra el uso de servidores por medio de
un protocolo de tres fases. La figura 20.6 ilustra varios pasos en el protocolo. n1, n2 y n3 son
nonces.
1. Autentificación inicial: El usuario es autentificado de la siguiente manera en el momento de
iniciar la sesión:

1.1 User → C : U, password


1.2 C → KAS : U, TGS, n1
1.3 KAS → C : EVU (n1 , SK U , T GS , TT GS )

23 MAQ. CAP. 20(F0694).indd 764 8/10/07 1:25:32 AM


20.4 Autentificación por terceros 765

Base de datos
de autentificación

Kerberos
KAS TGS

1.3 2.1
1.2 2.2

3.1
Cliente Servi-
3.2
dor

1.1

Usua-
rio

Figura 20.6 Kerberos.

El usuario presenta su id y contraseña al cliente en el paso 1.1. En el 1.2 el cliente remite la id


del usuario a KAS. También incluye un nonce n1 para autentificar a KAS. Este mensaje es una
solicitud de un boleto dirigida al TGS. Observe que la contraseña del usuario no se pasa a KAS.
Este hecho evita su exposición a través de la red y también implica que la autentificación no es
realizada por KAS; realmente se lleva a cabo en C de una manera interesante que se describirá
más adelante. En el paso 1.3, KAS usa la id del usuario U para recuperar a VU —la llave privada
de U— de la base de datos de autentificación y la usa para cifrar su respuesta a C. SKU,TGS es una
llave de sesión para la sesión entre el usuario y el TSG, y TTGS es un boleto para el TGS cifrado
por medio de la llave de éste.
C tiene que descifrar la respuesta de KAS mediante la llave VU para obtener SKU,TGS y TTGS.
Este paso autentifica al usuario de la siguiente forma: VU, la llave privada del usuario, satisface
la relación VU ⫽ f (contraseña), donde f es una función de un solo sentido conocida por C. C
obtiene VU aplicando f a contraseña. Entonces cifra la respuesta recibida de KAS por medio de
esta llave. El descifrado será fallido si la contraseña proporcionada por el usuario es inválida.
En este caso, C no puede extraer TTGS de la respuesta enviada por KAS, por lo que el usuario no
puede usar ningún servicio o recurso en el sistema.

2. Obtener un boleto para un servidor: Cuando un usuario desea usar un servidor, C obtiene un
boleto para el servidor empleando el siguiente protocolo:

2.1 C → TGS : <Server id>, TT GS , AU, n2


2.2 TGS → C : ESKU,T GS (n2 , T<Server id> , SKU ,<Server id> ,
<Server id>)

23 MAQ. CAP. 20(F0694).indd 765 8/10/07 1:25:32 AM


766 CAPÍTULO 20 Seguridad de archivos distribuidos

donde <Server_id> es el nombre del servidor que C quiere usar, AU es un autentificador,


SKU, Server_id es una llave de sesión para la sesión entre el cliente y el servidor deseado y TServer_id
es el boleto para el servidor deseado, cifrado por medio de la llave del servidor. Antes de respon-
der al cliente, el TGS verifica que el boleto presentado por el cliente es válido y que la solicitud
se ha originada en tiempo real y dentro del periodo de validez del boleto.
3. Obtener un servicio: Cuando el usuario U hace una solicitud de servicio, C genera un auten-
tificador y un nonce, e intercambia los siguientes mensajes con el servidor:

3.1 C → Server : T<Server id> , AU, ESKU,<Server (<service request>, n3 )


id >
3.2 Server → C : ESKU,<Server id>(n3 )

El servidor ejecuta este servicio si se da cuenta de que el boleto es válido y que la solicitud
se ha originado en tiempo real y dentro del periodo de validez del boleto. Devuelve el nonce n3
al cliente, por lo que el cliente lo puede autentificar, si así lo desea.

20.4.2 Capa de sockets de seguridad (SSL)

SSL es un protocolo de seguridad de mensajes que provee autentificación y privacidad de co-


municación. Funciona encima de un protocolo de transporte confiable, tal como el TCP/IP. Su
sucesor, el protocolo de seguridad de capa de transporte (TLS), está basado en SSL 3.0; aquí
analizaremos características que son comunes a los dos. Cuando un cliente desea comunicarse
con un servidor, se usa el protocolo de acuse de conexión SSL antes de que el intercambio de
mensajes pueda empezar. Esto emplea el cifrado de llave pública RSA para autentificar al ser-
vidor y, en forma opcional, también al cliente, y genera llaves de sesiones simétricas para el
intercambio de mensajes entre el cliente y el servidor. El verdadero intercambio de mensajes se
lleva a cabo mediante el protocolo de registro SSL, que realiza el cifrado simétrico de mensajes
y los transmite a través de la red. De este modo, la comunicación de mensajes entre el cliente y
el servidor es confiable debido al protocolo de transporte, es segura debido a la autentificación
realizada por el protocolo de acuse de conexión y es privada debido al cifrado realizado por el
protocolo de registro. La autenticidad de datos es asegurada mediante una firma digital en un
mensaje. Si únicamente se desea una verificación de integridad, ésta se provee por medio de
un código de autentificación de mensajes (MAC). Protocolos de aplicación de niveles mayores,
tales como http y FTP, pueden implementarse encima del SSL.
El protocolo de acuse de conexión SSL realiza las siguientes funciones:

1. La autentificación del servidor.


2. Permite que el cliente y el servidor seleccionen los algoritmos criptográficos que se van
a usar durante la sesión entre los algoritmos RC2, RC4, DES, triple DES y unos cuantos
más, así como los algoritmos de firma digital y hash entre DSA, MD5 y SHA-1.
3. En forma opcional realiza la autentificación del cliente.
4. Habilita al cliente y al servidor para generar un secreto compartido que se usará para
generar las llaves de sesión.

23 MAQ. CAP. 20(F0694).indd 766 8/10/07 1:25:32 AM


20.4 Autentificación por terceros 767

Un resumen simplificado del protocolo de acuse de conexión SSL es el siguiente: el cliente


envía un mensaje client_hello al servidor. Este mensaje contiene una especificación de las opcio-
nes criptográficas y de compresión, así como un número aleatorio de 28 bytes que llamaremos
nclient. El servidor responde con un mensaje server_hello que contiene otro número aleatorio
nserver. Inmediatamente después del mensaje server_hello, el servidor envía su certificado. SSL
tiene una lista de autoridades de certificación (CAS) del lado de clientes, cuyo uso asegura que
el certificado del servidor proviene de una de las CAS de la lista, y verifica la autenticidad del
servidor por medio de la criptografía de llaves públicas. Si así lo desea, el servidor pide el cer-
tificado del cliente y verifica su identidad de manera parecida. Posteriormente, el cliente envía
el mensaje encrypted premaster secret, que contiene una cadena premaster secret de 48 bytes,
cifrada mediante la llave pública del servidor.
Tanto el cliente como el servidor generan entonces una cadena master secret de 48 bytes a
partir de nclient, nserver y premaster secret, usando una función estándar de un solo sentido. El uso
de nclient y nserver, que son valores seleccionados al azar, asegura que el secreto master será dis-
tinto para diferentes sesiones entre el mismo par de cliente-servidor. Se usa la cadena de master
secret para obtener cuatro llaves de sesión simétrica por medio de un algoritmo estándar. Éstas
crypt crypt
se usan de la siguiente manera: las llaves kc→s y ks→c se usan para el cifrado y descifrado de
mensajes enviados por el cliente al servidor y por el servidor al cliente, respectivamente, y las
mac y kmac se usan para generar códigos de autentificación de mensajes para los mensajes
llaves kc→s s→c
enviados por el cliente y por el servidor, respectivamente. Después de la generación de llaves,
tanto el cliente como el servidor se envían mensajes de terminado uno al otro. En este momento
el protocolo de acuse de conexión SSL está completo.
El intercambio de mensajes es realizado por el protocolo de registro SSL por medio de las
llaves de sesión generadas durante el saludo. Los pasos para enviar un mensaje m del cliente al
servidor son los siguientes:

1. El cliente genera MACm, que es un código de autentificación de mensajes para el mensaje


mac .
m, por medio de la llave kc→s
crypt
2. El par ⬍m, MACm⬎ se cifra por medio de la llave kc→s y la cadena cifrada se envía al
servidor.
crypt
3. Cuando el servidor recibe la cadena cifrada, la descifra por medio de la llave k c→s E para
obtener el par ⬍m, MACm⬎. Acepta a m si su MAC, computado por medio de la llave
mac , coincide con MAC .
kc→s m

El protocolo SSL podrá ser subvertido por un ataque del hombre en medio, donde un intruso
intercepta los mensajes de un cliente enviados a un servidor en el protocolo de acuse de conexión
SSL y se hace pasar por el servidor en todos los intercambios de mensajes posteriores. En forma
análoga podrá hacerse pasar como el cliente y establecer con el servidor una conexión SSL ga-
rantizada. Los procesos de cliente y servidor deben extremar precauciones para derrotar el ata-
que del hombre en medio durante el saludo inicial. Cuando el servidor presenta su certificado al
cliente en el protocolo de acuse de conexión, el cliente debe verificar que el nombre distinguido
y la dirección IP que se mencionan en el certificado del servidor coincidan con los del servidor
con el cual está tratando de establecer una conexión SSL. La falta de coincidencia indicará que
está sujeto a un ataque del hombre en medio, por lo que en este caso deberá cancelar el protocolo
de acuse de conexión.

23 MAQ. CAP. 20(F0694).indd 767 8/10/07 1:25:32 AM


768 CAPÍTULO 20 Seguridad de archivos distribuidos

El servidor no conoce la dirección IP donde reside un cliente, por lo que tiene que usar un
planteamiento distinto para autentificarlo. Si el servidor requiere autentificación del cliente en
el protocolo de acuse de conexión SSL, el cliente queda obligado a presentar un certificado y
también una pieza de datos aleatorios que conoce el servidor y que debe firmar en forma digital
por medio de su llave privada para autentificarse a sí mismo. El servidor obtiene la llave pública
del cliente desde el certificado del cliente y valida su firma digital. Una falla en este paso indicará
que está sujeto a un ataque del hombre en medio, por lo que cancela el protocolo del saludo. Este
paso es análogo al de desafío-respuesta que se describió en la sección 20.2.2.

EJERCICIO 20
1. Elabore una cifra de llave pública para n ⫽ 77 por medio del planteamiento RSA.
2. Comente acerca del siguiente enunciado: “No existe el peligro de suplantación de personalidad si el
mensaje enviado por un cliente a un centro de distribución de llaves que solicita una llave de sesión
para un servidor se expone a un intruso.”
3. Se propone distribuir llaves de sesiones en un sistema de llaves públicas de la siguiente manera:

1. Pi → KDC : EUkdc (Pi , Pj )


2. KDC → Pi : EUi (Pj , SK i, j , EU j (Pi , SK i, j ))
3. Pi → Pj : EU j (Pi , SK i, j )
4. Pj → Pi : ESK i, j (n)
5. Pi → Pj : ESK i, j (n+1)
6. Pi → Pj : ESK i, j (<message>)

¿Sufre este protocolo de algún punto débil? De ser así, sugiera maneras de superarlo.
4. ¿La manipulación de mensajes puede llevar a la denegación de servicios? (Sugerencia: Piense en los
centros de distribución de llaves y en Kerberos.)
5. Explique cómo evita Kerberos la transmisión de informaciones sobre la contraseña a través de la red
cuando un usuario inicia la sesión. ¿Qué acciones deberán tomarse cuando un usuario cambia su con-
traseña?
6. Describa el uso del campo de tiempo de vida en un boleto de Kerberos. ¿Cómo se adivina el tiempo de
vida? Comente acerca de las ventajas y desventajas de usar el campo del tiempo de vida.
7. Comente acerca de la validez del siguiente enunciado: “Ataques de repetición de mensajes son posibles
en Kerberos hasta que venza un boleto.”
8. El protocolo de desafío-respuesta para detectar ataques de repetición de mensajes que se describe en la
sección 20.2.2 consiste en los siguientes pasos:

Pj → Pi : ESK i, j (n)
Pi → Pj : ESK i, j (n+1)

Sin embargo, en el paso 3.2 del protocolo de Kerberos el servidor regresa el nonce n3 al cliente sin
realizar una operación en él. Explique por qué es adecuado esto.
9. El protocolo de desafío-respuesta que se menciona en el problema 8 supone que un intruso no será
capaz de adivinar u obtener un SKi,j. El protocolo falla si esta suposición no es válida. Un intruso puede

23 MAQ. CAP. 20(F0694).indd 768 8/10/07 1:25:33 AM


Bibliografía 769

usar este hecho para subvertir la seguridad de la distribución de llaves de sesión en un sistema de llaves
privadas de la siguiente forma: el intruso obtiene por algún medio un SKi,j. Entonces repite el mensaje
en el paso 3 de (20.3), a saber

3. Pi → Pj : EVj (Pi , SK i, j ), ESK i, j (<message>)

De esta manera, será capaz de establecer una asociación fingida con Pj, es decir, una asociación en la
que Pj cree que está interactuando con Pi. Gozará esta capacidad de establecer asociaciones fingidas
para siempre.
Diseñe un protocolo para impedir esta amenaza. (Sugerencia: ¿Será útil si, en vez de usar el pro-
tocolo de desafío-respuesta, Pj trata de iniciar una sesión nueva con Pi mediante la obtención de una
llave de sesión del KDC?)

BIBLIOGRAFÍA
Rivest (1978) y Pfleeger y Pfleeger (2003) describen la teoría detrás del cifrado RSA. Woo y Lam (1992)
analizan protocolos de autentificación en sistemas distribuidos. Steiner et al. (1988) describen el protocolo
Kerberos.
Denning y Denning (1998) producen una colección de artículos sobre ataques del ciberespacio y la se-
guridad de Internet. Khare (1997) trabaja una colección similar de artículos que cubre asuntos de confianza
en la web, incluidas firmas digitales e infraestructuras de llaves públicas. Cheswick et al. (2003) analizan
ataques a la seguridad, cortafuegos y autentificación.

1. Cheswick, W.R., S. M. Bellovin y A.D. Rubin (2003): Firewalls and Internet Security, 2a. ed.,
Addison-Wesley Professional.
2. Denning, D.E. y P.J. Denning (eds) (1998): Internet Besieged: Countering Cyberspace Scofflaws,
Addison-Wesley.
3. Khare, R. (ed) (1997): Web Security: A Matter of Trust, O’Reilly & Associates.
4. Lampson, B., M. Abadi, M. Burrows y E. Wobbler (1992): “Authentication in distributed systems:
theory and practice”, ACM Transactions on Computers, 10, 4, 265-310.
5. Pfleeger, C.P. y S. Pfleeger (2003): Security in computing, Prentice Hall, N.J.
6. Rivest, R.L., A. Shamir y L. Adelman (1978): “On digital signatures and public key cryptosys-
tems”, Communications of the ACM, 21, 2, 120-126.
7. Steiner, J.G., C. Newman y J.I. Schiller (1988): “Kerberos: an authentication service for open
network system”, Proceedings of the Winter USENIX conference.
8. Woo, T.Y.C. y S.S. Lam (1992): Authentication for distributed systems, IEEE Computer.

23 MAQ. CAP. 20(F0694).indd 769 8/10/07 1:25:33 AM


Índice analítico

Acceso Algoritmo de Raymond, 183-184


descriptor, 375 Algoritmo de Ricart-Agrawala, 688-689
privilegio, 357, 359, 375 Algoritmo de selección, 703-705
privilegios, 381 algoritmo bravucón, 704-705
tiempo, 526 para topologías de anillo,703-704
Acceso remoto de datos, 637 Algoritmo de siguiente ajuste, 203
Acción atómica, 339-341 Algoritmo del banquero, 501-506
ejemplo, 341 estado de asignación segura, 502
implementación, 340 solicitud factible, 501
Acciones atómicas solicitud segura, 501
sistema de archivos virtuales, 341-343 Algoritmo del elevador, 551
Unix, 343-347 Algoritmo del panadero, 430-431
Windows, 348-350 Algoritmo del peor ajuste, 233
Acciones de desbloqueo, 560 Algoritmo del quórum, 719-720
Aceleración de la computación, 87, 91 Algoritmo Mitchell-Merritt, 696-697
Administración de archivos, 599 Almacenaje y hacia delante, 652, 657
Administración de E/S, 599 Almacenamiento estable, 337-338
Administración de energía, 167-168 Almacenamiento temporal de visión lateral de tra-
Administración de la memoria, 191-235, 599 ducción, 250-253
Administración de las comunicaciones, 599 Ambiente del proceso, 93-94
Administración de procesos, 599 Amenazas a la seguridad
Adversario, 362 filtración, 751
AES, 372-373 interferencia, 751
Algoritmo de Chandy-Lamport, 677-680 negación del servicio, 751
ejemplo, 678 robo, 751
propiedades del estado registrado, 678 Análisis de desempeño, 181-186
Algoritmo de control distribuido, 684-708 modelación matemática, 182
acción de control, 684 programación de relación de respuesta, 185
prontitud, 686 programación FCFS, 185
seguridad, 686 programación round-robin, 185
criterios de corrección, 686-688 programación SRN, 185
datos de control, 684 simulación, 182
de seguimiento del borde, 696-697 teoría de colas, 182
exclusión mutua distribuida, 688-693 Ancho de banda de la red, 657
operación de, 684-686 Andrew, 743-745
Algoritmo de Dekker, 426-427 escalabilidad, 743
Algoritmo de mejor ajuste, 203 espacio de nombre compartido, 743
Algoritmo de Peterson, 427-428 resolución del nombre de la trayectoria, 744
Algoritmo de primer ajuste, 203 semántica para compartir archivos, 743-745

24 MAQ. INDICE(F0694).indd 770 8/10/07 1:26:05 AM


Índice analítico 771

Anomalía de Belady, 272 asignación contigua, 211-213


Aplicación en tiempo real, 70-73 asignación de memoria de kernel, 221-226
definición, 70 asignación dinámica, 194, 195
ejemplo, 71, 86 asignación estática, 194, 195
fecha límite, 71 asignación no contigua, 213-220
requerimiento de respuesta, 71 como una unión, 193
Árbol B+, 350 lista libre, 202-206, 208, 209, 221-223, 225
Archivo, 19, 306, 514 Asignación de memoria (de C), 196, 199
abierto, 327, 326-329 Asignación de memoria contigua, 211-213
acceso, 326-331 Asignación de memoria no contigua, 213-218
atributo, 306 Asignación de recursos, 484-489
bloque de control, 319-322 eventos, 484
borrado, 307 Asignación estática, 193, 195
cerrado, 307, 330-331 Asignación indexada, 324-325
compartir, 331-333 Asignación ligada, 323-324
copia primaria, 732 Asignadores de memoria
creación, 307 asignador acompañante perezoso, 223-224
disponibilidad, 730 asignador de losa, 224-226
duplicación, 732-733 asignador de potencias de dos, 209-210
formación del caché, 726, 736-739 asignador de sistema acompañante, 208-209
validación del caché, 739 asignador McKusick-Karells, 222-223
identificación interna, 326 Ataque a la seguridad, 362-364
lectura/escritura, 307 enmascaramiento, 362
mapeo de la memoria, 282-284 negación del servicio, 362
operaciones, 306 suplantación, 362
organización, 307-311 Ataque del cumpleaños, 760
protección, 318-319, 375-382, 390-391 Ataques a la seguridad, 752-753
recuperabilidad, 730 ataque del hombre en el medio, 761
robustez, 730 espionaje telefónico, 752
semántica para compartir, 331-333, 729-730 interferencia con el mensaje, 752
tabla de mapas, 324 suplantación, 752
volver a nombrar, 307 volver a mandar el mensaje, 752, 758-759
Archivo compartido inmutable, 331 Ataques a los sistemas criptográficos, 367, 369
Archivo de acceso directo, 309-310 Autenticidad de la información, 360, 750
Archivo secuencial, 308-309 Autentificación, 15, 358, 360, 365, 661, 751
Archivo secuencial con índice, 310-311 base de datos, 359
Archivos mapeados en la memoria, 282-284 en un sistema distribuido, 762-768
Archivos mutables por conocimiento, 358
imagen individual, 332 por posesión, 358, 373
imagen múltiple, 332 por símbolo, 358
Área de memoria intermedia (buffer), 415 usando contraseñas, 373
Área del sistema, 32 Autentificación mutua, 759-760
Área del usuario, 32 Autoridad de certificación, 760
Asignación de espacio de disco, 322-325 Autorización, 358
asignación enlazada, 323-324 base de datos, 359
asignación indexada, 324-325
tabla de mapa de archivos, 324 Balance de cargas, 698
Asignación de memoria, 13-14, véase también Al- Bandeja, 529
goritmo del primer ajuste, Algoritmo Bandera de comisión, 340
de mejor ajuste, Memoria virtual Basura, 248-249
a un proceso, 198-200 definición, 248

24 MAQ. INDICE(F0694).indd 771 8/10/07 1:26:05 AM


772 Índice analítico

Biblioteca de hilos, 110-113 en un modelo de sistema distribuido, 657-


Biblioteca enlazada en forma dinámica (BED), 659
195 Brecha entre registros, 529
Bit de modificación, 273, 288 Brecha semántica, 604, 605
Bit de paridad, 527-529 BUS, 36
Bit de referencia, 259, 272-274 Buzón, 474-476
Bit setuid, 381, 391
Bitácora, 717 Caballo de Troya, 15, 363
Bitácora de deshacer, 718 Cabeza de lectura-escritura, 529
Bitácora de volver a hacer, 717 Caché
Bizantino nivel, 36
fallo, 714-715 Caché de disco, 565
problema del acuerdo, 714 unificada, 564-565
problema del consenso, 715 Caché de nombres del directorio, 742
Bloque, véase Registro lógico Caché de página, 565
Bloque de control, 514 Cadena de referencia de página, 267
Bloque de control de archivos (BCA), 319-322, Cálculo básico, 685-686
326-331 ejemplo, 686
Bloque de control de eventos (BCE), 104-105, Calloc (de C), 196, 199
175 Campo, 306
Canal
Bloque de control de hilos (BCH), 106, 109
comunicación del interproceso, 666
Bloque de control de procesos (BCP), 93, 94,
Capa de aplicación, 655
99-100, 102, 104, 111, 115, 125, 138,
Capa de enlace de datos, 654
139, 160-162, 165, 221
Capa de presentación, 655
Bloque de índice, 325
Capa de sesión, 655
Bloqueo, 21
Capa de sockets de seguridad (CCS), 766-768
Bloqueo de registros, 311, 559-562
Capa de transporte, 655
Bloqueo en vivo, 419, 426
Capa física, 654
Bloqueo mutuo, 20, 408, 419, véase también Mo-
Capacidad
delación del estado de los recursos compartir objetos, 385-388
condiciones de, 485-486 definición, 382
condiciones necesarias, 507-511 del subconjunto, 382
condiciones suficientes, 507-511 direccionamiento basado en, 384-385
sistema MIMR, 509-511 identificador de objeto, 383
sistema MISR, 508-509 tabla de objetos (TO), 384
sistema SIMR, 509 en “Amoeba”, 388-389
sistema SISR, 507-508 en el software, 388-390
definición, 483 estructura, 382
en la asignación de recursos, 484-489 problema de confinamiento, 390
modelo de clase de recursos, 506 protección basada en, 382-390
modelo de solicitud de recursos, 507 protección de, 386-388
procesos en, 511 arquitectura etiquetada, 386
Bloqueo mutuo del fantasma, 518, 687, 688, 693- segmento de capacidad, 386
694 protección de objetos, 385-388
Borde revocación, 390
borde AND, 512 sistema basado en computadora, 383-385
borde de asignación, 486 Capacidad del software, 388-390
borde de espera, 486 Capas de protocolo ISO, 654-655
borde de solicitud, 486 operación, 653
borde OR, 512 Característica biométrica, 358, 373

24 MAQ. INDICE(F0694).indd 772 8/10/07 1:26:05 AM


Índice analítico 773

Característica de fallo de página, 248 Compartir


Carga archivo, 331-333, 729-730
dinámica, 195 CPU, 13
Carga computacional, 698 datos, 90, 131-134
Carga general de disco, 14
programación, 42 memoria, 13
Cargado, 600 página, 255
Cargador, 226 programa, 232
absoluto, 228 recurso
de relocalización, 228 dinámico, 13
definición, 195 estático, 13
Cargador de relocalización, 200 segmento, 294
Centro de distribución de llaves Compartir de manera equitativa, 145
(KDC), 756 Compartir recursos, 76
Certificado de llave pública, 761 Compendio de mensajes, 760
Ciclo, 488, 506-510, 512 Compuerta de enlace (Gateway), 645
Cifra de flujo, 367, 370-371 Computación
Cifra de sustitución, 368 aceleración, 74
Cifra Vernam, 370 migración, 637
Cifrado, 365-373, 753-757 Computación cliente-servidor, 631, 638-640
asimétrico, 366 Computación de control, 685-686
cifrado RSA, 755 ejemplo, 686
distribución de llaves, 756-758 Computación idempotente, 637
llave, 366 Computación por difusión, 694-696
llaves de sesión, 756
consulta demandante, 694
simétrico, 366
consulta no demandante, 694
Cifrado de la llave privada, 753-754
Comunicación, véase Protocolo de comunicación,
Cifrado de llave pública, 754-756
comunicación de interproceso,
Cilindro, 530
Comunicación interprocesos, 137
Cinta magnética, 528
Unix
cinta que fluye, 529
cola de mensajes, 477
Circuito virtual, 652
socket, 478
Clúster, 627
tubería (pipe), 476
Sun, 629-630
Comunicación primitiva
Windows, 629
Coda, 744-745 envío con bloqueo, 469
Código de autentificación del mensaje (CAM), envío sin bloqueo, 469
761-762 Concurrencia, 86, 91-92, 107
Código de bloque, 367, 370 Concurrencia acotada, 434
Código de condición, 32, 33 Concurrente
Cola evento, 668, 671
E/S, 543 procesos, 86
programación, 104, 148, 152, 154, 158, programa, 86
163, 183 programación, 3, 7
Cola de comandos etiquetados, 552-554 Condición de carrera, 132-134, 404
Cola de preparado, véase Lista definición, 132
de preparado ejemplo, 132-133
Cola de solicitud, 148, 152 en la sincronización del control, 409-411
Colisión, 647 procesos que contienen la condición de
Comisión, 339, 718 carrera, 133
Compactación de memoria, 207, 212 Condición de terminación distribuida, 701

24 MAQ. INDICE(F0694).indd 773 8/10/07 1:26:06 AM


774 Índice analítico

Condición del progreso, 407 registro, 32, 93, 99-101, 106, 107, 118, 125,
Condiciones del bloqueo mutuo, 485-486 131, 138
Condiciones necesarias para el bloqueo mutuo, registro de límite inferior (RLI), 37, 201-202
507-511 registro de límite superior (RLS), 37,
sistema MIMR, 509-511 201-202
sistema MISR, 508-509 registro de relocalización, 200
sistema SIMR, 509 registro de valla, 37
sistema SISR, 507-508 Criptografía, 366
Condiciones suficientes para el bloqueo mutuo, ataque con texto plano conocido, 368
507-511 ataque con texto plano seleccionado, 369
Conexión, 650 ataque minucioso, 368
Conexión de Newcastle, 628 ataque único con texto cifrado, 368
Confiabilidad, 73-74 ataques sobre, 368
en el protocolo de comunicación, 631-632 términos de, 367
en el sistema distribuido, 626, 658, 665 CSMA/CD, 648
en el sistema operativo distribuido, 626,
658, 665 Datos
en la red, 646 distribuidos, 637
sistema de archivos, 333-337 migración, 637, 638
Confusión, 367, 369-373 replicado, 637
Conjunto de trabajo, 276-278 Datos dinámicos controlados por programa, 196,
definición, 276 199
implementación, 278-279 Datos distribuidos, 717, 720-721
ventana, 276 Datos duplicados, 717-720
Conservar y esperar, 485, 486, 498 Datos estáticos, 198
Contador del programa, 33 Declaración de control, 55
Contraseña, 373 Degradación parcial, 72
cifrado, 374 DES, 367, 371-372, 375
de seguridad, 364-365 encadenamiento de los bloques por código,
envejecimiento, 374 371
Contraseña de seguridad, 374-375 Despacho, 94, 95, 101
Control de enlace de datos de alto nivel (CE- Detección de bloqueos mutuos distribuidos, 685,
DAN), 654 694-697
Control distribuido, 75 Detección de errores, 529
Controlador de dispositivo, 33, 523 Detección de la terminación distribuida, 685, 701-
Controlador de memoria, 33, 523 703
Copia durante la escritura, 281, 291 Diagrama de asignación de tiempos, 668
Copia primaria, 337 Difusión, 367, 369-373
Copia secundaria, 337 Dijkstra, 431
CPU, 32-35 Dinámica
código de condición (CC), 32 asignación, 193, 195
contador del programa (PC), 32 asignación de memoria, 194
estado, 34 carga, 195
información de protección de la memoria, datos, 198
33 ligado, 195
instrucción privilegiada, 33 ruta, 652
interrupción, 32 unión, 194
máscara de interrupción, 33 Dirección
modo de usuario, 33 física, 215
modo privilegiado, 33, 58 ligada, 227
palabra de estado del programa (PEP), 33 lógica, 214

24 MAQ. INDICE(F0694).indd 774 8/10/07 1:26:06 AM


Índice analítico 775

tiempo de carga, 227 DMA como primera parte, 524


traducción, 214 DMA como tercera parte, 524
traducida, 227 Duplicación de archivos, 732
Dirección IP, 632
Dirección virtual, véase E/S, 37-38
Dirección lógica área de almacenamiento temporal (buffer),
Directorio 555
caché de nombres, 350 canal multicanalizado, 38
como archivo, 313 dispersar y recoger, 256
directorio actual, 314 dispositivo, 525-537
directorio raíz, 314 acceso aleatorio, 525, 529-533
estructura de multinivel, 313 controlador, 523
estructuras, 311-318 detección de errores, 527-528
jerarquía, 313-314 dirección, 523
Directorio actual, 314 modo de bloque, 525
Directorio raíz, 313, 314 modo de carácter, 525
Disco, véase también, RAID, 529-533 secuencial, 525, 528-529
caché, 351 estado, 538
cilindro, 530 información del estado, 522
datos alternados, 530-533 iniciación, 484, 538-540, 546-547
efecto de espejo, 337-338 instrucción, 523
efecto de espejo en RAID, 534-536 interrupción, 38
interpolación de sectores, 531-533 modo asíncrono, 524
interrupción de la cabeza, 531 modo de interrupción, 37, 38
mapa de estado, 324 modo DMA, 37, 38
paquete, 530 modo programado, 37, 38
pista, 529 modo sincrónico, 524
rayado, 534 organización, 523-525, 573
registro procesamiento de la terminación, 539-540
dirección, 530 programación, 538-540
rendimiento de procesamiento, 532-533 programador, 549
SCSI, 351 terminación, 547-548
cola etiquetada de comandos, tiempo, 526
552-554 volumen, 525
sector, 530 E/S programadas, 37
sesgo de la cabeza, 532 Efecto dominó, 717
sesgo del cilindro, 532 EIA-232D, 654
tiempo de acceso, 530 Ejecución del programa
tiempo de búsqueda, 530 definición, 92
Diseño por capas del SO, 604-6076 El problema de la cena de los filósofos, 419-421
Disponibilidad, 660 El problema de lectores-escritores, 417-419, 438-
Dispositivo de E/S 440, 444-446
corrección de errores, 528 con el uso de RCC, 444-446
detección de errores, 528 con el uso de semáforos, 438-440
tiempo de acceso, 526 enunciado del problema, 417-419
Dispositivo lógico, 542-543 esbozo, 419
Dispositivos de E/S, 513 Elasticidad, 713, 721-723
Dispositivos virtuales, 53, 497 Encomienda de dos fases, 720-721
Distribución de Poisson, 183 Entrelazamiento de sectores, 531-533
DMA, 37, 58, 75, 524 Envejecimiento de las solicitudes, 148
control del BUS, 525 Error, 711

24 MAQ. INDICE(F0694).indd 775 8/10/07 1:26:06 AM


776 Índice analítico

Escalabilidad, 727, 735, 736, 740 en monitores, 447-448


Espacio de direcciones, 85 enfoques algorítmicos, 408
Espacio de intercambio, 242, 256, 258-259 primitivas de software, 408
Espacio de la dirección física, 215 sección crítica, 404-4312
Espacio de la dirección lógica, 215, 217 uso de la región crítica condicionada (RCC),
Espacio de nombre, 743 443-447
Espera acotada, 407 uso del semáforo, 432-434
Espera circular, 485, 486, 498 Exokernel, 613
Espera de ocupación, 407-408, 415, 416 Extensibilidad, 603
Esperando la terminación de E/S, 541, 548
Esperar o morir, 697 Factor de bloqueo, 560-562
Estado, 23 definición, 560
del canal, 675 Factor de utilización, 183
del proceso, 95-99 Factor de utilización de la memoria,
del sistema distribuido, 665-673 210
global, 665 Falla(o), 711
local, 665 amnesia, 712
transición, 95-98 bizantino, 714-715
Estado bloqueado, 96, 491-495 fallo-paro, 712
Estado de asignación de seguridad, 502 Fecha límite, 71, 145
Estado de funcionamiento, 96, 491-495 Fijación de E/S, 256
Estado de intercambio, 98 Firma digital, 762
Estado de preparado, 96 Flujo de bits, 527
Estado del canal, 675 Formación de caché para el directorio, 732
Estado del CPU, 93 Formación de la memoria caché, 21
Estado del proceso, 92, 95 Fórmula de Little, 184
Estado suspendido, 98 Fracción del servidor, 641
Estado terminado, 96 Fragmentación de la memoria,
Estática 204, 211-212, 226
asignación de memoria, 194 definición, 204
Estimación de la fecha límite, 171 Fragmentación externa, 204, 211, 213
Estrategias de conexión, 650 Fragmentación interna, 204,
Estructura computacional, 3, 7-10 211-212
programa individual, 9 Función de control, 659
programas coejecutables, 10 Función de control distribuido, 22
secuencia de programas individuales, 9 Función de una sola vía, 367, 368
Ethernet, 647-648 Función Hash (función de búsqueda), 262
Etiqueta de frontera, 205-207 Función Hash de verificación de una sola vía,
Evaluación remota, 631, 639, 642-644 375
Evento, 17, 102-106, 666 Fusión de la memoria libre, 205
manejo, 102-106
Eventos aleatorios, 183-184 Giro ponderado, 144, 145, 148, 150
Exclusión mutua distribuida, 685, 688-693 GPFS, 745-746
algoritmo de Raymond, 691-693 Grado de multiprogramación, 64
enfoque basado en un símbolo, 689-693 Gráfica
enfoque totalmente distribuido, 688-689 RRAG, 486
para la topología de anillos, 690-691 borde de asignación, 486
Exclusión mutua, 133, véase también Sección borde de solicitud, 486
crítica WFG, 486-487
Exclusión mutua distribuida, 406, 422 Gráfica de espera (GDE), 486-487, 693-697
constructores de programación concurrente, borde AND, 512
408 borde OR, 512

24 MAQ. INDICE(F0694).indd 776 8/10/07 1:26:06 AM


Índice analítico 777

Gráfica de precedencia de procesos, 168-169 Interrupción, 17, 38, 41


Grupo de cilindros, 346 acción, 40-41
Grupo de usuarios, 376 anidado, 43
Guardar el contexto, 94, 95, 100 clases, 39
Gusano, 363, 364 código, 39, 42
cronómetro, 39
Hardware de la máquina, 603 E/S, 39, 41
Hardware de paginamiento, 250-256 externa, 41
Heap (montículo), 196-204 máscara, 33, 39-40
Hilo de control, 7, 18, 92, 106-125 prioridad, 38
procesamiento, 42-45
codificación, 108
programa, 39, 41
definición, 106
software, 39, 41, 45
estado, 107
vector, 40-41, 608
hilo de Windows, 128
Interrupción de software, 45, 137
hilos en el nivel de kernel, 109-110
Interrupción del cronómetro, 66
hilos en el nivel del usuario, 110-113
Interruptor de circuitos, 650-651
hilos híbridos, 113-114
Intruso, 15, 362, 365, 751
hilos Linux, 125-128
Inversión de prioridades, 408
hilos Solaris, 123-125
IOCS físico, 540-568
pila, 106
biblioteca, 545-546
Posix, 111
bloque de control de E/S (BCES), 543
ventajas,107-108
cola de E/S, 543
Hilos de control múltiples, 3, 7 dispositivo lógico, 542
Huésped, 626 estructuras de datos, 543-545
iniciación de E/S, 546-547
IBM 360/67, 273 mecanismos y políticas, 522
IBM 370, 286 objetivos de diseño, 540
Identificación interna, 326 optimización del desempeño del dispositivo,
Impulsor de dispositivo, 550-551 548
Unix, 565-566 organización física, 522
Inanición, 148, 150, 406, 417, 434, 552 tabla del dispositivo físico (TDF), 543
en la programación basada en prioridades, tabla del dispositivo lógico (TDL), 543
147 terminación de E/S, 547-548
Información PSW salvada, 40-43, 45
Ínodo, 343 Java, 455-456
Instantánea de un sistema concurrente, 422 invocación del método remoto, 643-644
convenciones pictóricas, 422 Jerarquía de la memoria, 35-37
ejemplo, 423, 434, 437, 450, 452
Instrucción de intercambio, 414 Kerberos, 764-766
Instrucción de prueba y puesta, 413 autentificador, 764
Instrucción indivisible, 412, 442 boleto, 764
Instrucción privilegiada, 33, 40, 43 Kernel, 2, 32, 610-612
Integridad de la información, 360, 750 asignación de memoria, 221-226
Intel 80386, 26 configuración e instalación, 614-615
Intercambio, 14, 70, 76, 213 operación impulsada por la interrupción,
esquemático, 70 601
Intercambio de paquetes, 651 soporte de sincronización, 442-443
Interfase del usuario, 8-10, 599
Interfase gráfica del usuario, 7 LAN, véase Red de servicio local (Local area net-
Internet, 7 work) (LAN)

24 MAQ. INDICE(F0694).indd 777 8/10/07 1:26:06 AM


778 Índice analítico

Latencia, 530, 657 Lista de exportaciones, 657


rotacional, 552-554 Lista de importaciones, 657
Latencia rotacional, 530 Lista de intenciones, 339
Lenguaje ensamblador, 227-228 Lista de marcos libres, 241, 257
Lesionado o espera, 698 Lista de preparado, 159, 161, 163, 165, 166
Liga, 316 Lista de programación, 66, 67, 69, 70
dura, 347 Lista libre, 202-206, 208, 209, 221-223, 225
simbólica, 347 Lista ligada, 202-203, 206, 208, 223, 225, 233
Ligador, 226 Llamada al procedimiento remoto (LLPR), 75,
definición, 195 631, 639-642
Ligamiento, 226-230 Llamada del sistema, 42, 45-46
declaración ENTRY, 229 relacionada con el programa, 46
declaración EXTRN, 229 relacionada con la comunicación, 46
definición, 229 relacionada con la información, 46
definición pública, 229 relacionada con los archivos, 46
dinámico, 195, 229-230 relacionada con los recursos, 46
estático, 229-230 Llave
referencia externa, 229 cifrado, 366
relocalización de programa, 227-228 en el registro, 306
definición, 228 Llave de conversación, véase Llave de sesión
Límite inferior del registro (LBR), 37, 201-202 Llave de sesión, 756-758
Linux, 246, 615 distribución, 757
contraseña de seguridad, 375 Llave privada, 753-755, 764-765
Llave pública, 754-757
futex, 126, 458
distribución, 757
hilo de control, 125-128
Localidad actual, 246
linux con seguridad ampliada, 392
Localidad de referencia, 246-248
lista activa, 180
Lógica de relocalización, 231
lista agotada, 180
Longitud del calendario, 145,146
llamada al sistema de clon, 126
Lote, 52
memoria virtual, 289-290
página inactiva lavada, 289
Manejador de la memoria virtual, 238, 257-260
región cero llena, 289
estructuras de datos, 257
región respaldada con archivos, 289 funciones, 258
módulos de kernel de carga, 392 protección, 259
procesamiento de archivos, 568-569 Manejo de bloqueos mutuos distribuidos, 693-
programador anticipador, 569 698
programador de fecha límite, 569 Manejo de eventos, 95, 600-601
proceso, 125-128 Manejo de la interrupción, 600
proceso hijo, 126 Manejo del bloqueo mutuo, 490-518
programación, 178-180 algoritmo de Banker, 501-506
programación O(1), 180 caracterización del bloqueo mutuo, 506-
seguridad, 391-392 513
sincronización de procesos, 457-458 con el uso de WFGs, 512-513
sistema de archivos, 348 cómo evitar el bloqueo mutuo, 490, 500-
arriendo, 348 506
bloque obligatorio, 348 detección del bloqueo mutuo, 490-493
candado de asesoramiento, 348 algoritmo, 492-495
ext2, 348 en Unix, 514-515
grupo de bloques, 348 enfoque práctico, 513-515
Lista de capacidad (lista C), 378-379 prevención del bloqueo mutuo, 490, 496-
Lista de control de acceso (ACL), 318, 377-378 500

24 MAQ. INDICE(F0694).indd 778 8/10/07 1:26:07 AM


Índice analítico 779

jerarquización de recursos, 499-500 tiempo de acceso a la memoria efectiva,


todas las solicitudes juntas, 498-499 245, 251-252
resolución del bloqueo mutuo, 495-496 Mensaje huérfano, 716
sistema MIMR, 509-511 Mensaje de interprocesos, 466-481, 514, 990,
sistema MISR, 508-509 almacenamiento temporal, 470-472
sistema SIMR, 509 asignación asimétrica del nombre, 468
sistema SISR, 507-508 asignación indirecta del nombre, 474
Mapa de memoria, 53 asignación simétrica del nombre, 468
Máquina extendida, 605 bloque de control (IMCB), 470
Máquina virtual, 15, 607 condición excepcional, 470
Marco de página, 217 entrega, 472-474
Matriz de control de acceso (MCA), 375 Mensaje, véase también Mensaje de interprocesos
Mecanismo, 601-602 cola, 477
autentificación, 373 conmutación, 651
capacidad, 382 huérfano, 716
despacho, 159 reconocimiento, 631
intercambio, 213 retransmisión, 631
manejo de eventos, 548 seguridad, 753-760
mecanismo de administración de memoria, volver a presentarlo, 758-759
611 Método de acceso, 308, 311, 562-563
mecanismo de comunicación, 611 funciones, 563
mecanismo de E/S, 611 mecanismos y políticas, 522
mecanismo de paginamiento, 266 organización física, 522
mecanismo de programación, 160, 611 Mezcla de programas, 59
mecanismo de protección, 360 Microkernel, 612-614
mecanismo de seguridad,360 Migración
mecanismo IOCS, 303, 304, 319, 522 archivo, 726, 729
migración del proceso, 706 computación, 698-701, 729
salvar el contexto, 161 proceso, 698-701
señal, 90-91, 119-120, 137-139 volumen, 743
Memoria, 513 Migración de procesos, 638, 698-701, 706-707
asignación Migración de volumen, 743
no contigua, 18 Migración en la computación, 638
fragmentación, 18 Modelación del estado de los recursos, 483-518
reúso, 202-207 Modelo de referencia ISO, 653-654
Memoria caché, 35-36 Modo de transferencia asíncrona (ATM), 648-650
bloque de caché, 36 interruptor, 649
localidad espacial, 36 Módulo objeto, 196, 199, 226, 231
localidad temporal, 36 Monitor, 447-454
relación de impacto, 36 caso de estudio de un programador de
Memoria intermedia (buffer), 21 discos, 452-455
Memoria intermedia (buffer) para los registros, condición variable, 447-452
311, 350, 555-559 declaración signal, 448
requerimiento pico, 559 declaración wait, 448
Memoria virtual, 18, 195, 237-240, véase también ejemplo de uso
Paginamiento, Segmentación, Conjun- productores-consumidores, 450, 451
to de trabajo semáforo, 448,449
carga de la demanda, 239 en Java, 455-456
definición, 238 exclusión mutua, 447-448
ejemplo de operación, 239-240 Monitor de lotes, 53
relación de impacto, 252 Motorola 68030, 266

24 MAQ. INDICE(F0694).indd 779 8/10/07 1:26:07 AM


780 Índice analítico

MS-DOS, 235 fallo, 242-250, 252, 263


MULTICS, 343 característica, 249
dominio de la protección, 381-382 marco, 240
segmentación, 293 reemplazo, 245, 246, 255-256
Multiprogramación, 50, 52, 56-65 tabla, 241, 257
clasificación de programas, 59-60 bit modificado, 242, 257, 259
esquemática, 57 bit válido, 242
funciones de kernel, 56, 58-65 información de protección, 242, 257
grado de multiprogramación, 59, 64 información de referencia, 242, 257, 259
mezcla de programas, 59-60 información miscelánea, 242, 257
prioridad de programas, 60-64 tamaño óptimo de página, 249
programación, 59-64 tráfico, 245
sistema, 49
Página sucia, 255, 256, 287, 288
soporte arquitectónico, 557
Paginamiento, 215, 217-219, 239, véase también
Mutex, véase también Semáforo binario
Paginamiento por demanda, Políticas
de reemplazo de página
Negación del servicio, 362, 751
New (de Pascal), 200 cadena de referencia de página, 267
Nodo, 508, 626 fijación de páginas de E/S, 256-257
Nodo de servidor, 727 lista de marcos libres, 257
Nodo del cliente, 727 localidad actual, 246
NodoV, 342 memoria temporal para la traducción de
Nombrado direcciones, 250-253
de procesos, véase Proceso(s), identifica- operaciones de E/S, 256-257
ción de separación y unión en E/S, 256
en el pase de mensajes, 468-469 paginamiento por demanda, 241-266
en el sistema de archivos, 312-313, 728 páginas compartidas, 255, 279-281
en la comunicación, 632-633 panorama general, 240-241
libertad, 311 protección de memoria, 254-255
Nombre de la trayectoria, 314-315 en el espacio de la dirección lógica, 255
nombre absoluto de la trayectoria, 315 tabla de página de dos niveles, 263-265
nombre relativo de la trayectoria, 315 Intel 80386, 265
resolución, 327-329, 731, 732, 742, 744 tabla de página de multinivel, 265-266
tabla de página invertida, 260-263
Operación de página adentro, 244 tabla de página, 257
Operación de página afuera, 244 traducción de dirección, 217-219, 241-246,
Operación de recepción, 137, 466-481 250-254
Operación idempotente, 340 Paginamiento por demanda, 241-266
Operación indivisible, 431 Páginas compartidas, 279-281
definición, 411
Palabra de estado del programa (PEP), 32-37, 99-
implementación, 411-414
101
Operación send, 137, 466-481
Paradigma de la computación distribuida, 637-
Operación signal, 431
644
Operación wait, 431
Orden parcial, 667 computación cliente-servidor, 638-640
Orden total, 667 evaluación remota, 642-644
Organización física, 4-5, 214, 522 llamada de procedimiento remoto, 640-642
Organización lógica, 4-5, 214 Paralelismo, 91-92
Origen Parbegin-Parend, 424
especificación, 226 Partición, 12
Pase de mensajes, 20, 90, 137, 466-481
Página, 215, 239 aspectos, 468
cadena de referencia, 267 Unix, 476

24 MAQ. INDICE(F0694).indd 780 8/10/07 1:26:07 AM


Índice analítico 781

Patrón de llegada, 183 Proceso(s), 18, 46, 47, 84-125


Patrón de servicio, 183 ambiente, 93-94
Pila, 92, 93, 106, 112, 196-198, 200 árbol, 86
Pista, 529 comunicación de interprocesos, 466-481
Planeación de la capacidad, 186 comunicación, 90
Política, 601-602 creación, 87-91, 102
Política CSCAN, 552 datos compartidos, 90
Política de programación, 18 definición, 93
Política SSTF, 552 demonio, 115
Políticas de reemplazo de página, 266-274 estado, 87-91, 92, 95-99
algoritmo de reloj Unix, 286 definición, 95
algoritmo de segunda oportunidad, 273-275 estado bloqueado, 96
algoritmo del reloj, 273 estado de funcionamiento, 96
aproximación FIFO, 273-274 estado de suspensión, 98
aproximación LRU, 272-273 estado preparado, 96
propiedad de pila, 270-271 estado terminado, 96
reemplazo FIFO, 268 fallo, 712
reemplazo LRU, 268-270 identificación, 93
reemplazo óptimo, 268 intercambio, 101
Portabilidad, 21, 602, 612 mensaje de interprocesos, 90
Precedencia de eventos, 667-668, 670, 671 panorama del programador, 87-91
orden parcial, 667 panorama del SO, 92-106
precedencia transitiva, 667 pila, 93
relación causal, 667 precedencia, 168
Prevención de los bloqueos mutuos distribuidos, proceso Linux, 125-128
697-698 proceso principal, 86
Prioridad, 87, 145, 147-148 procesos concurrentes, 86
definición, 60 procesos independientes, 131
dinámica, 147 procesos interactivos, 90-91, 130-137
estática, 147 definición, 131
variación de, 147, 176-177, 181 resumen de interacciones, 90
Priorización, 13, 61, 145, 146, 498 sincronización del acceso a los datos,
Privacidad, 360, 750 131-134
Problema de confinamiento, 389 sincronización del control, 134-136
Problema de consenso, 715 programación, 94-95, 101, 160-168
Problema de los productores-consumidores, 415- recuperación, 713
417, 435-437, 445 señal, 90-91
con el uso de RCC, 445 sincronización, 90
con el uso de semáforo, 435, 437 terminación, 87-91, 102-103
con el uso del monitor, 450-452 transición del estado, 95-98
enunciado del problema, 415, 417 Unix, 115-123
esbozo, 416, 417 ventajas de los procesos hijos, 87
operaciones indivisibles, 417 Windows, 128-130
Procesador de comandos, 55-56 y el programa, 84-86
Procesador de comunicación (PC), 645 Proceso hijo, 86, 138
Procesamiento de archivos, 305 Proceso ligero (PL), 123-125
Procesamiento de comisión, 340 Proceso padre, 138
Procesamiento por lotes, 52, 76 Programa, 46, 47
procesador de comandos, 55-56 cargado, 200-201
sistema, 49, 50, 52-56 contador, 32, 40
tiempo reprocesable, 54 de segmentos múltiples, 220, 221

24 MAQ. INDICE(F0694).indd 781 8/10/07 1:26:07 AM


782 Índice analítico

dirección de inicio, 227 programación en tiempo real, 168-174


espacio de direcciones, 85 programación FCFS, 148-149
mezcla, 59-60 programación HRN, 150,151
prioridad, 49, 60-64 programación LCN, 151, 155-156
priorización, 43, 49 programación monotónica de tasas, 173-174
definición, 61 programación para compartir de manera
programa kernel, 2 equitativa, 166-167, 177-178
programa sin kernel, 2 programación round-robin, 151-154
relocalización, 200-201 programación SRN, 149-150
Programa binario, 226, 231 programación STG, 151, 156
Programa de autoubicación, 231-232 solicitud, 144
Programa estructurado con traslape, 195 términos, 145
Programa ligado a E/S, 59 tiempo real, 49
Programa limitado por el CPU, 59 uso de la información de consumo de
Programa reentrante, 231-233 recursos, 154-156
Programación, 13,41, 43, 59, 65-68, 94, 95, 101, Programación a corto plazo, 157-159, 160
143-188, 600 Programación a largo plazo, 157-158, 160
análisis de rendimiento, 181-186 Programación a mediano plazo, 157-158, 160
cola, 104, 148, 152, 154, 158, 163, 183 Programación basada en prioridades, 59,161-166
conceptos, 145 Programación de discos, 21, 548, 551-554
CTSS, 165-166 CSCAN, 552
disco, 548, 551-554 en disco SCSI, 552-554
en el proceso por lotes, 159 FCFS, 551
en la multiprogramación, 59-65, 159 resumen, 552
en tiempo compartido, 65-68, 159 SCAN, 551
evento SSTF, 551
completado, 144 vista circular (vista C), 551
llegada, 144 vista, 551
priorización, 144 Programación de E/S
programación, 144 programación avanzada de E/S, 554-562
fundamentos, 143-148 almacenamiento temporal, 555-559
Linux, 178-180 bloqueo, 559-562
no priorizante, 148-150 Programación de multinivel, 163-166
priorizante, 151-156 CTSS, 165-166
programación a corto plazo, 158-168 Programación de procesos
programación a largo plazo, 158 Linux, 178-180
programación a mediano plazo, 158 Windows, 181
programación adaptativa de multinivel, Programación de relación de respuesta, 150
165-166 análisis del desempeño, 185
programación de la relación de respuesta, Programación de visión, 551
150 Programación de vista circular (vista C), 551
programación de loterías, 167 Programación del CPU, 13
programación de procesos, 160-168 Programación dinámica, 170
multiprogramación, 161-162 Programación distribuida, 685, 698-701
programación de multinivel,163-166 algoritmo iniciado en forma simétrica,
programación en tiempo real, 168-174 699-701
tiempo compartido, 163 algoritmo iniciado por el emisor, 699
Unix, 175-178 algoritmo iniciado por el receptor, 699
Windows, 181 estabilidad, 699
programación de tareas, 158 Programación en tiempo real, 49, 168-174
programación EDF, 172-173 calendario factible, 169

24 MAQ. INDICE(F0694).indd 782 8/10/07 1:26:07 AM


Índice analítico 783

precedencia de procesos, 168-169 protocolo RR, 636-637


programación basada en prioridades, 170 protocolo RRA, 634-636
programación dinámica, 170 protocolo síncrono, 634
programación EDF, 172-173 semántica de cuando más una vez, 633
programación estática, 169 semántica de cuando menos una vez, 633
programación monotónica de las tasas, semántica de exactamente una vez, 633, 635
173-174 Protocolo de comunicación
Programación estática, 169 HDLC, 654
Programación FCFS, 148-149 TCP, 655
análisis del desempeño, 185 UDP, 654, 655
Programación no priorizante, 148-150 Protocolo de control del transporte (TCP), 655
Programación priorizante, 76, 151-156 Protocolo de desafío-respuesta, 758-760
Programación round-robin, 49, 66, 151-154, 163 Protocolo de herencia de prioridades, 408
análisis de desempeño, 185 Protocolo de internet (IP), 654
Programación SRN, 149-150 Protocolo de red, 653
análisis de desempeño, 185 modelo de referencia ISO, 653-654
Programación STG, 156 Protocolo de transferencia de archivos (FTP),
Programador, 43 638, 655
Prontitud, 687 Protocolo del diagrama de datos del usuario
Propiedad de la pila, 270-271 (PDDU), 655
Propiedad estable, 680 Protocolo TCP/IP, 655-657
Propiedad sin memoria, 183 PSW, 93
Puente, 647
Protección, 15-16, 358, véase también Archivo,
Puerto, 643
Capacidad, Protección de la memoria
Puntero de archivos FCB, 327
anillo, 381
Puntero FCB del directorio, 327
dominio, 379-382, 391
Punto de montaje, 317
cambio de, 380-382, 391
MULTICS, 381-382
RAID, 533-536, 731
Unix, 380-381, 390-391
nivel 0 (rayado de disco), 534
estructura, 377-382, 390-391
nivel 1 (efecto de espejo del disco), 534-536
granularidad, 376
nivel 2, 536
información, 313
nivel 3 (entrelazamiento de bits), 536
lista de capacidades, 377-379 nivel 4 (entrelazamiento de bloques), 536
lista de control del acceso, 377-378 Rebanada de tiempo, 49, 66
matriz de control del acceso, 375 variación, 147
mecanismo, 360 Rebanadas de tiempo, 66-69, 76
objetivos, 360 Rebase de la fecha límite, 144,145
política, 360 Recolección de basura, 389
privilegio de acceso, 357, 359, 375 Recuperación, 23, 710-722
privilegios de acceso, 381 definición, 711
Protección de la memoria, 37, 58, 201-202, 216, recuperación hacia atrás, 714
254-255 recuperación hacia delante, 714
registros acotados, 201-202 Recuperación de datos, 713
Protocolo, véase Protocolo de comunicación Recurso
Protocolo de acuerdo, 715 asignación, 11-15
Protocolo de comunicación interprocesos, 631- asignación basada en los recursos en
637 común, 11-13
protocolo asíncrono, 634 dinámica, 11
protocolo de bloqueo, 634 estático, 11
protocolo de no bloqueo, 634 particionamiento, 11-13

24 MAQ. INDICE(F0694).indd 783 8/10/07 1:26:08 AM


784 Índice analítico

compartir, 73 registro físico, 560


jerarquización, 499-500 registro lógico, 560
modelación del estado, 486-487 Registro acotado por la memoria, 37
modelo matricial, 489 Registro de control, 32
RRAG, 486 Registro de direcciones de la tabla de segmentos
WFG, 486 (RDTS), 292
nudo, 510 Registro de la dirección de la tabla de página
priorización, 13 (RDTP), 254
Recurso de instancia múltiple, 507 Registro de límite superior (UBR) (RLS), 37, 201-
Recurso de una instancia simple, 507 202
Recurso no compartible, 486 Registro de valla, 37
Recurso virtual, 14-15 Registro del tamaño de la tabla de página, 255
Recursos en común Registro físico, 560
asignación basada en, 12-13, 216 Registro lógico, 560
de memorias temporales (buffer), 415 Regla del cincuenta por ciento, 206-207
Recursos no compartibles, 496 Regreso, 713
Red, 599, 644 Relación de impactos
anillo, 647 en la memoria, 245
capa, 654 en el TLB, 252
conexión, 645 Relación de respuesta, 145, 150
de área amplia (WAN), 644 Relocalización
de área local (LAN), 644-646 definición, 228
estrella, 647 del programa, 200
parcialmente conectada, 647 registro, 200
partición, 647 Reloj global, 666-667
protocolo, 645 Reloj local, 666
ruta, 645 Reloj lógico, 669-671
sistema de archivos, 740-742 sincronización, 669
sistema operativo, 627-628 Reloj vector, 671-672
tipo, 645 Remoto
topología, 645-647 acceso de datos, 638
totalmente conectada, 647 procesamiento de archivos, 727
Red de anillo, 647 Rendimiento, 48, 59,145, 146, 149, 150
Red de área ampliada (WAN), 644 Representación de datos externos (RDE), 643,
Red de servicio local (LAN), 644-646 655
Red estrella, 647 Resolución de un bloqueo mutuo, 495-496
Red parcialmente conectada, 647 Respaldo, 23, 336
Red totalmente conectada, 647 por incrementos, 336
Reemplazo de la página FIFO, 268, 273-274 Respaldo incrementativo, 336
Reemplazo de página LRU, 268-270, 272-273 Reúso de la memoria, 212
Reemplazo óptimo de página, 268 Robo de ciclo, 524
Región crítica condicionada (RCC), 443-447 RS-232C, 654
declaración await, 444 Ruta, 652-653
ejemplo de uso
lectura-escritura, 446 SCES, 21, 302, véase Método de acceso
memoria intermedia (buffer) acotada, Sección crítica (SC), 404-431
445 definición, 405
implementación, 446-447 ejemplo, 405
Región de proximidad, 246 implementación, 411-414
Registro, 306 implementación del algoritmo, 423-431
CPU, 99-101, 106, 107, 118, 125, 131, 138 algoritmo de Bakery, 430-431

24 MAQ. INDICE(F0694).indd 784 8/10/07 1:26:08 AM


Índice analítico 785

algoritmo de Dekker, 426-427 Semántica para compartir archivos, 331-333, 729-


algoritmo de Peterson, 427-428 730
implementación usando semáforo, 433-434 semántica de sesión, 729-730
propiedades de la implementación, 406-407 semántica de transacciones, 730
Sector, 530 semántica Unix, 729
Segmentación, 215, 219-220, 239, 291-295 Semántica de la sesión, 729-730
con paginamiento, 220-221 Semántica de las transacciones, 729, 730
fragmentación, 294 Semántica IPC, 633, 661, véase también Protoco-
MULTICS, 293 lo de comunicación interprocesos
Segmentación con paginamiento, 294-295 Semántica Unix, 729
fragmentación, 294 Señalamiento, 409,435
Segmento, 216
Señales, 90, 119-120, 137-139
Seguridad, 15-16, 358, 687, 750-769
Servicio del usuario, 54, 65
ataque de cumpleaños, 760
en el procesamiento por lotes, 54
autenticidad, 360, 750
en el tiempo compartido, 65
autentificación, 358
símbolo, 358 en la multiprogramación, 58-59
autorización, 358 Servidor, 638
cifrado, 359 Servidor de archivo fuera de estado, 732, 734-
contraseña, 359 735
en sistemas distribuidos, 750-769 Servidor de archivos, 727
integridad, 360, 750 Servidor de impresora, 15
mecanismo, 360, 364, 751 Servidor de nombre, 632, 641, 657, 705-706
objetivos, 360, 361 Servidor no priorizable, 148
política, 360, 364, 751 Sesgo de la cabeza, 532
privacidad, 360, 750 Sesgo del cilindro, 532
sigilo, 360, 750 Sigilo, 360, 750
sistema distribuido, 23 Simulación, 182, 491
Seguridad de un sistema distribuido, 23 Sincronización
Seguridad del mensaje, 661 de los procesos, véase Sincronización de
Selección distribuida, 685 procesos
Semáforo, 431-443 de los relojes, 669, 671
definición, 431 sincronización del acceso de datos, 133
ejemplo de uso Sincronización de control, 134, 404
exclusión mutua, 432-434 definición, 134
lectores-escritores, 438-441 Sincronización de procesos, 20, 403-463, véase
productores-consumidores, 435-437
también Condición de carrera, Sec-
implementación, 440-443
ción crítica, Semáforo, Región crítica
ayuda arquitectónica, 443
condicionada, Monitor
híbrido, 443
problemas clásicos, 414-421
nivel de kernel, 443
cena de los filósofos, 419-421
nivel de usuario, 443
pseudocódigo, 420, 442 lectores-escritores, 417-419
variable de bloqueo, 443 productores-consumidores, 415-417
semáforo binario, 432 sincronización del acceso de datos, 131-134,
Unix, 456-457 404
uso para el señalamiento, 435 sincronización del control, 134-136, 404
uso para la concurrencia acotada, 434-435 Sincronización de tiempos, 668-671, 764
uso para la exclusión mutua, 432 Sincronización del acceso de datos, 131-134, 404
Windows, 459 Sistema abierto, 725, 762
Semáforo binario, 432 Sistema acompañante, 289

24 MAQ. INDICE(F0694).indd 785 8/10/07 1:26:08 AM


786 Índice analítico

Sistema concurrente, 421-423 validación de la caché, 737


Sistema de archivos, 302-347, véase también Ar- iniciado por el cliente, 739
chivo, acceso, Compartir archivo, Pro- iniciado por el servidor, 739
tección de archivos, Acción atómica, Windows, 747
Asignación de espacio de disco, Dis- Sistema de archivos estructurado como bitácora,
co, efecto de espejo 351-352
acciones en el cierre de archivos, 330-331 Sistema de archivos virtuales, 341-343, 740
acciones en la abertura de archivos, 326-329 Sistema de cómputo, 32-41
archivos mapeados en la memoria, 282-284 Sistema de control de entrada salida (SCES), 302-
archivos montados, 328-329 305
confiabilidad, 333-337, véase también Biblioteca, 303
Recuperación, Tolerancia de fallos, Diferencia con el sistema de archivos, 304
desempeño, 350-352 Operaciones, 320
estructuración de bitácora, 351-352 Organización física, 520
integridad, 334-336 Sistema de control de entrada salida (SCES), 520-
interfase con IOCS, 319-322 522
mecanismos y políticas, 522 Sistema de nombre del dominio (DNS), 632, 644
metadatos, 342 Sistema de tiempo compartido, 49
montaje, 317-318 Sistema distribuido, véase también Precedencia
operaciones, 320 de eventos, Algoritmo de control dis-
organización lógica, 304 tribuido
recuperación, 336-337 aceleración de la computación, 626
carga general, 336 autentificación, 762-768
respaldo, 336 compartir recursos, 626
tolerancia de fallos, 337-341 comunicación, 626
Sistema de archivos distribuidos, 23, 725-745, véa- confiabilidad, 626
se también Formación de caché para corte de un sistema, 674-676
el directorio, Escalabilidad, Transpa- crecimiento incrementado, 626
rencia definición, 74
administrador del caché, 737 estado, 665-673
Andrew, 743-745 estado global, 665
aspectos de diseño, 725-728 estado local, 665
Coda, 744-745 grabado del estado, 673-680
desempeño, 727, 735-737 modelo, 657-659
disponibilidad, 731-733 modelo físico, 657
estructura del servidor de archivos, 736 modelo lógico, 657
formación de caché para los archivos, 737- modelo de nodos, 627
739 recuperación, 710-722
GPFS, 745-746 seguridad, 750-769
migración de archivos, 726 tolerancia de fallos, 717-721
montaje remoto, 744 Sistema en tiempo real
resolución del nombre de la trayectoria, duro, 71
731, 732 suave, 71
semántica para compartir archivos, 729-730 Sistema MIMR, 509-511
semántica de sesión, 729 Sistema MISR, 508-509
semántica de transacciones, 729 Sistema operativo
semántica de Unix, 729 administración de recursos, 11-15
servidor de archivos sin estado, 734-735 carga general, 6
sugerencia, 736 clases de, 49-52
Sun NFS, 740-742 distribuido, 51
tolerancia a los fallos, 727, 730-735 en tiempo real, 51

24 MAQ. INDICE(F0694).indd 786 8/10/07 1:26:08 AM


Índice analítico 787

multiprogramación, 50 Sobrecarga, 6, 42, 72


procesamiento por lotes, 50 programación, 239
tiempo compartido, 51 Socket, 478-480
comodidad del usuario Software de paginamiento, 257-281
buen servicio, 50 Solaris
necesidad, 50 hilo de control, 123-125
recursos compartidos, 50 hilo de control del usuario, 123
estructura, 21 hilo de kernel, 123
basada en kernel, 604 proceso ligero (PL), 123-125
basada en microkernel, 604 Solicitud, 144
estratificada, 4, 604-607 reordenamiento, 146
monolítica, 603-604 Solicitud de recursos y gráfica de asignaciones
SO basado en kernel, 610-612 (SRGA), 486
SO basado en microkernel, 612-614 Solicitud de seguridad, 501
SO de máquina virtual, 607-608 Solicitud duplicada, 635
funciones, 599 Solicitud factible, 169
manejo de eventos, 95 Solicitud individual, 507
mecanismo, 601-602 Solicitud múltiple, 507
objetivos, 5-7 Spooling, 49, 514
operación de, 7-10 Subsolicitud, 475, 144
parte residente, 601 Sugerencia, 736
parte transitoria, 601 Suma verificadora de la redundancia cíclica
política, 601-602 (CRC), 527-529
SUN
y utilización efectiva, 5-7
grupo, 629-630
Sistema operativo “Amoeba”, 613, 630-631
SUN NFS, 740-742
capacidades, 388-389
arquitectura, 741
Sistema operativo de multiprocesador, 21
manejo de archivos, 740
Sistema operativo distribuido, 22-23, 49, 51-52,
protocolo de montaje, 740-741
73-75, 628-661, véase también Siste-
resolución del nombre de la trayectoria, 742
ma de archivos distribuidos
semántica del manejo de archivos, 742
asignación de recursos, 705-706
SUN RPC, 643
aspectos de diseño, 659-661
puerto, 643
balance de carga, 660 SUN Sparc, 266
confiabilidad, 660-661, 717-723 Superpágina, 253-254
escalabilidad, 626, 639, 645 degradación, 254
recuperación, 660-661 promoción, 254
seguridad, 661, 750-769 Supervisor, véase también Kernel
ventajas, 73 Suplantación, 362
Sistema operativo en tiempo real, 49, 51, 52, 70-
73 Tabla de archivos activos (AFT), 326
degradación elegante, 72 Tabla de asignación de archivos (FAT), 323-324
tolerancia a los fallos, 72 Tabla de enlaces de segmentos (TES), 292
Sistema operativo Mach Tabla de página, 218, 242, 243
microkernel, 612-613, 616 tabla de página de dos niveles, 263-265
Sistema operativo moderno, 75-76 tabla de página de multinivel, 265-266
Sistema operativo THE, 606-607 tabla de página invertida, 260-263
Sistema SIMR, 509 Tabla de segmentos, 219, 292
Sistema SISR, 507-508, 693 Tabla del mapa de archivos (TMA), 324
Sitio, 626 Tabla Hash (tabla de búsqueda), 262-263, 350,
SO de la máquina virtual, 607-608 566-567
SO invitado, 607 Talón del cliente, 641

24 MAQ. INDICE(F0694).indd 787 8/10/07 1:26:08 AM


788 Índice analítico

Tarea, 47 Unión
paso, 47 dinámica, 194, 280
programación, 158 estática, 194
Teoría de colas, 182 memoria, 193-194
Texto cifrado, 366, 367 recurso, 11
Texto plano, 366, 367 Unix
Tiempo, 665 algoritmo del reloj, 286
Tiempo compartido, 51, 52, 65-70 arquitectura, 615-616
administración de memoria, 70 asignación de archivos, 345-346
programación, 65-68 asignación de memoria de kernel, 222-226
rebanadas de tiempo, 66 caché del almacenamiento temporal
operación, 67 (buffer), 566-568
Tiempo de búsqueda, 530 cola de mensajes, 477
Tiempo de giro, 48, 144, 145, 148 contraseña de seguridad, 375
Tiempo de llegada, 144, 145, 183 copia durante la escritura, 285
Tiempo de respuesta, 48,49, 144, 145 cuota de disco, 344
variación con rebanada de tiempo, 153-154 demonio, 115
Tiempo de salida, 631 demonio del paginamiento, 286-288
Tiempo de servicio, 144, 145, 184 descriptor de archivos, 343
Tiempo de terminación, 144 dirección del evento, 175
Tiempo de transferencia, 526 dominio de protección, 380-381, 391
Tiempo promedio de respuesta, 145 espacio de intercambio, 284-285
Tipo de archivo estructura de archivos, 343
archivo de flujo de bytes, 305 estructura proc, 115
archivo estructurado, 305 exec, 116, 285, 380, 391
Token ring, 648 fijación de páginas, 287
Tolerancia de fallos, 223, 72, 337-341, 713, 717- fork, 116, 285
721 ínodo, 343
Traducción de la dirección, 218-219, 243 intercambio, 288
resumen, 252, 255 liga simbólica, 347
Transacción anidada, 722 lista libre, 346
Transacción atómica, 718 llamada del sistema, 118
aborto, 718 manejador del dispositivo, 565,566
Transacción distribuida, 720-721 manejo de los bloqueos mutuos, 514-515
Transacción multisitio, véase Transacción distri- memoria virtual, 284-288
buida mensaje de interprocesos, 476-478
Transparencia, 49, 75, 659, 726-729 montaje del directorio, 346-347
independencia de ubicación, 726 procesamiento de archivos, 566-568
transparencia de ubicación, 659, 726 procesamiento de interrupciones, 118
Traslape, 239 proceso, 115-123
Traslape CPU-E/S creación, 116
en un proceso, 555 estado de ejecución de kernel, 122
Trayectoria estado de ejecución del usuario, 122
en RRAG, 488 modo de usuario, 175
en WFG, 487-488 modo interruptible de kernel, 175
Tubería, 476 modo no interruptible de kernel, 175
prioridad, 175
Unidad de administración de la memoria (MMU), terminación, 117
18, 33, 35, 219, 238, 244, 250, 254, proceso de kernel, 116
255, 291 proceso del usuario, 115
Unidad de traducción de la dirección (ATU), 523 proceso principal, 116

24 MAQ. INDICE(F0694).indd 788 8/10/07 1:26:09 AM


Índice analítico 789

proceso zombie, 117 descriptor de seguridad, 393


programación de procesos, 175-178 DLL, 619
valor conveniente, 176 ejecutivo, 618
semáforo, 456-463 espacios de nombres DFS, 747
semántica de archivos compartidos, 345 evento, 459
semget, 456 eventos por pares, 481
semop, 456 hilo de control
señales, 119-120 transiciones de estado, 129-130
setuid, 365, 380-381, 391 hilo de Windows, 128
sistema de archivos, 343-347 hilos de prioridad de variable, 181
socket, 478-480 hilos en tiempo real, 181
superbloque, 346 identificador de seguridad, 392
tabla de asignación de archivos, 345 kernel, 618
transiciones de estado del proceso, 121-123 lista de control del acceso discrecional, 393
tubería, 476 LPC, 480-481
u area, 115 memoria virtual, 290-291
Utilización del CPU, 48 páginas compartidas, 291
Utilización efectiva, 5-7, 31-52 mutex, 459
objetos de la sincronización, 458-459
Valor momentáneo, 759 pase de mensajes, 480-481
Variable de candado, 412-413, 442, 443 procesamiento de archivos, 570-571
Variable de condición, 447-452 proceso, 128-130
Virus, 16, 363 creación, 128-129
Visión abstracta del SO, 2-5 programación, 181
VM/370, 608 puerto, 480
Volumen, 349, 743 seguridad, 392-394
semáforo, 459
WAN, véase Red de área amplia (WAN) servidor de clúster (grupo), 629
Windows símbolo de acceso, 393
administrador de VM, 570 sincronización de procesos, 458-459
administrador de la caché, 570 sistema de archivos, 348-350
arquitectura, 618-619 tabla de archivos maestros, 349
capa de abstracción de hardware (CAH), Subsistemas del ambiente, 619
618 suplantación, 393
copia durante la escritura, 291 Windows NT, 246

24 MAQ. INDICE(F0694).indd 789 8/10/07 1:26:09 AM


24 MAQ. INDICE(F0694).indd 790 8/10/07 1:26:09 AM

También podría gustarte