Académique Documents
Professionnel Documents
Culture Documents
SISTEMAS
OPERATIVOS José Torres Jiménez
trillas
Digitalización con propósito academico. Sistemas operativos
CONCEPTOS DE
SISTEMAS
OPERATIVOS José Torres Jiménez
Preedición
EDITORIAL
TRILLAS
México, Argentina, España
Colombia, Puerto Rico, Venezuela
Presentación 5
2 Manejo de procesos 23
2.1 Introducción 23
2.2 Definición de proceso 23
2.3 Estados de un proceso 23
2.4 Bloque de control de un proceso (PCB) 24
2.5 Operaciones sobre procesos 24
2.6 Creación jerárquica vs creación no jerárquica 25
2.7 Procesamiento de interrupciones 25
2.8 Tipos de interrupciones 25
2.9 Funciones del núcleo (kernel) 25
2.10 Deshabilitación/habilitación de interrupciones 26
2.11 Estructura jerárquica de un sistema operativo 26
2.12 Migración del núcleo a microcódigo 26
7
Digitalización con propósito academico. Sistemas operativos
8 ÍNDICE DE CONTENIDO
B Java 177
B. 1 Introducción 177
B.2 Historia 178
A.3 Diferencias entre Java y C 179
B.3.1 Estructura del programa 179
B.3.2 Argumentos 179
B.3.3 Valor de salida en un programa 179
B.3.4 Estatuto import 179
B.3.5 Caracteres para comentarios 180
B.3.6 Constantes 180
B.3.7 Tipos de datos 180
B.3.8 Colección de basura 180
B.3.9 Apuntadores 181
B.3.10 Strings 181
B.3.l1 Arreglos 181
B.4 Programación en Java 181
B.4.l Objeto 181
B.4.2 Clase 182
B.4.3 Método 182
B.4.4 Instancia 182
B.4.5 Herencia 183
B.5 Aplicaciones y Applets 183
B.5. 1 Cómo crear o editar un programa 184
B.5.2 Cómo compilar un programa 184
B.5.3 Cómo ejecutar una aplicación 184
B.5.4 Cómo ejecutar un Applet 185
B.5.5 Métodos básicos de un Applet 185
B.5.6 Ejemplo de una aplicación 185
B.5.7 Ejemplo de un Applet 188
B.6 Hilos 190
B.6. 1 Constructores 191
B.6.2 Métodos 191
B.6.3 Ejemplo de Threads 192
C Baci 195
C. 1 Introducción 195
D JPNS 201
D. 1 Introducción 201
D.2 Instalando jPNS 201
D.2.1 Como Applet 201
D.2.2 Como aplicación 201
D.3 Los comandos de jPNS 202
D.3.1 Menú File 202
D.3.2 Menú Settings 202
D.4 Los iconos gráficos 202
D.5 Ejemplo de red de petri en Jpns 205
Bibliografía 207
• Manejo de recursos.
• Definición de interfaz usuario.
• Compartición de hardware
• Compartición de datos.
• Asignación de recursos.
• Recuperación de errores.
• Procesadores.
• Almacenamiento.
• Dispositivos de E / S.
• Datos.
15
1.2.1. Hardware
1. Registros de relocalización. Estos registros permiten que tanto los datos, el código
y el stack puedan ser relocalizados sin necesidad de modificar el código original de
un programa. Esto es realizado usando dos tipos de registros: a) Un registro de
segmento que define la dirección base a partir de donde se encuentran el código, los
datos o el espacio de stack; y b) Un registro de desplazamiento que toma como
referencia al registro de segmento. De esta manera al modificar el valor del registro
de segmento, se está cambiando la dirección que se puede accesar.
2. Interrupciones y Polling. Cuando una aplicación se queda verificando
continuamente la ocurrencia de un evento, se dice que está diseñada para usar
POLLING. Cuando la aplicación continúa realizando otras actividades y cuando se
ocurra el evento se indica con una señal (interrupción) que ya ocurrió el evento, se
dice que está diseñada para usar INTERRUPCIONES. En general es preferible no
usar POLLING dado que es muy ineficiente el estar verificando continuamente la
ocurrencia de eventos.
3. Búferes. Cuando dos elementos se comunican y existe diferencia en la velocidad de
procesamiento de ellos, la velocidad de operación total será equivalente a la
velocidad
del elemento más lento. Para compensar las diferencias de velocidad entre
elementos que se comunican, se puede agregar memoria entre ellos (esto es un
buffer) lo cual ayuda a suavizar las diferencias de velocidad entre ellos (por
ejemplo la conexión entre una computadora y una impresora puede funcionar mejor
usando un buffer, que está localizado internamente en la impresora).
4. Temporizador de Quantum. Para poder soportar que un solo procesador sea
compartido entre varias aplicaciones se hace uso de un temporizador de quantum
(similar a un reloj despenador) el cuál permite asignar “rebanaditas” de tiempo
entre los diversos procesos.
5. Estado Problema / Estado Supervisor. Cuando el procesador de un sistema
computacional está asignado a una aplicación del usuario se dice que el sistema está
en Estado Problema, cuando el procesador está asignado al sistema operativo se
dice que el sistema está en el Estado Supervisor.
6. Manejo de Memoria Virtual. A la capacidad de accesar más memoria que la
disponible físicamente se le denomina Manejo de Memoria Virtual. En este manejo
las instrucciones de un programa accesan direcciones mas allá del espacio real de
memoria.
1.2.2. Software
Para entender la operación de diversos algoritmos usados en los sistemas operativos
es necesario conocer algunos conceptos importantes de software son relacionados en
seguida:
1. Programación en Lenguajes de Máquina. Se refiere a los programas hechos en
lenguaje binario, los cuales pueden ser ejecutados directamente en el HW del
sistema computacional.
2. Ensambladores y Macroprocesadores. Usando un ensamblador y
macroprocesador es posible facilitar la generación de aplicaciones, dado que se
usan instrucciones cortas que relacionan directamente la operación de un
procesador en particular. El ensamblador genera a partir de las instrucciones codas
un programa en lenguaje maquinal.
3. Compilador. Es un programa que recibe como entrada un programa en lenguaje de
alto nivel (similar en cierto sentido a un lenguaje natural) y produce como salida un
programa en lenguaje ensamblador y/o lenguaje maquinal.
4. Intérprete. En lugar de realizar el proceso total de conversión de un programa en
lenguaje de alto nivel a lenguaje de bajo nivel, un intérprete va tomando instrucción
por instrucción del lenguaje de alto nivel y las ejecuta directamente.
Digitalización con propósito academico. Sistemas operativos
18 CAP I. INTRODUCCIÓN A LOS SISTEMAS OPERATIVOS
1.2.3. Firmware
- Simple.
- Confiable
- Eficiente.
A éste sistema de programación se le llamó “sistema operativo”.
• Los primeros sistemas operativos tipo batch (atlas y exec II) eran eficientes y
simples pero no confiables totalmente.
• El problema de deadlock no era entendido muy bien.
• Los siguientes sistemas operativos fueron muy complejos:
MULTICS (1965)—200 hombres-año.
• Debido a que los costos del hardware disminuyen y los de software aumentan surge
la idea de soportar directamente los conceptos de proceso y monitor en hardware
(microprocesador).
• Surge la idea de escribir un programa concurrente independientemente del HW en
donde correrá, probarlo y después diseñar la arquitectura más adecuada al software.
• Cada vez se tendrá HW más especializado de acuerdo a la aplicación.
• Esta etapa continúa.
- Nuevas teorías.
- Etcétera.
1.4. Referencias
Manejo de procesos
En este capítulo presentaremos los detalles relativos a la manipulación de procesos
por parte del Sistema Operativo. Usando un diagrama de estados y transiciones de los
procesos se explican todas las posibles operaciones relacionadas con procesos.
2.1.Introducción
A través de los procesos es como es posible realizar un trabajo utilizando un
sistema operativo. Los estados y transiciones de un proceso son ilustrados en la figura
2.1
2.2.Definiciones de proceso
• Un programa en ejecución.
• Una actividad asíncrona.
• El espíritu animado de un procedimiento.
• El lugar de control de un procedimiento en ejecución.
• Lo que se manifiesta por el PCB dentro de un SO.
• La entidad a la que se le asignan procesadores.
• La unidad despachable.
2.3.Estados de un proceso
• Corriendo.
• Listo.
• Bloqueado.
• Eliminado.
• Suspendido Listo.
• Suspendido Bloqueado.
23
Digitalización con propósito academico. Sistemas operativos
24 CAP 2. MANEJO DE PROCESOS
• Manejo de interrupciones.
• Creación / destrucción de procesos.
• Cambios de estado de un proceso.
• Despacho de procesos.
• Suspensión y reinicio de procesos.
• Sincronización de procesos.
• Comunicación interprocesos.
• Manejo de PCB’s.
• Soporte de actividades de 110.
• Soporte de asignación / desasignación de recursos.
• Soporte del sistema de archivos.
• Soporte del mecanismo de llamadas y regresos de procedimientos.
• Soporte de funciones de contabilidad del sistema.
• THE (DIJKSTRA).
2.13.1. Rutina
2.13.2. Corrutina
2.13.3. Proceso
2.13.4. Hilos
• Algunos sistemas como el OS/2, MVS. UNIX-SUN y MACH ven a los procesos
desde dos puntos de vista:
1. Como una unidad que posee recursos. A un proceso se le asigna una área de
memoria para poder correr y periódicamente se le asignan memoria y otros
dispositivos.
2. Como una unidad de despacho. Un proceso traslapa su ejecución con la de otros
procesos y puede pasar durante su vida por varios estados como LISTO,
CORRIENDO, BLOQUEADO, etc. y es despachado o planificado por el
sistema operativo.
• A la parte relativa a la UNIDAD QUE POSEE RECURSOS se le denomina
PROCESO o TAREA, mientras que a la parte de UNIDAD DE DESPACHO se le
denomina PROCESO LIGERO o simplemente HILO (Thread).
• El uso más sobresaliente del concepto de HILO es que se pueden tener múltiples
HILOS para el mismo PROCESO de forma que toma mucho menos tiempo crear
nuevos HILOS que crear un nuevo PROCESO. De este modo es más eficiente
diseñar una aplicación para correr como un solo proceso con múltiples hilos que
correr dicha aplicación como múltiples procesos.
• Otra característica atractiva de los hilos es que dado que sólo existe un proceso es
directa la compartición de datos entre los hilos, mientras que en un esquema con
múltiples procesos se requeriría la intervención del KERNEL para realizar la
compartición de datos lo que haría más lenta la aplicación.
• Un ejemplo práctico del uso de los hilos es el programa Aldus-PageMaker
corriendo bajo OS/2, este programa está diseñado con tres hilos que siempre están
activos:
2.14. Referencias
29
Digitalización con propósito academico. Sistemas operativos
30 CAP 3. ALGORITMOS DE ADMINISTRACIÓN DE PROCESADORES
3.5. Prioridad
• CARACTERÍSTICAS ESTÁTICAS
- Tamaño de código.
- Tiempo estimado de ejecución.
- Cantidad de Entrada / salida estimada.
• CARACTERÍSTICAS DINÁMICAS
1. Usar Round Robin pero el tamaño del quantum es particular para cada proceso y el
tamaño de él depende de la prioridad del proceso.
3.15. Referencias
Administración de
Memoria Real
4.1. Introducción
4.2. Organización
35
En los 50’s y 60’s la memoria principal estaba constituida por memorias de núcleos
magnéticos muy costosas, por lo cual era indispensable diseñar un sistema
computacional con el mínimo tamaño requerido.
Por lo tanto era necesario sólo conservar en memoria principal el código y datos
estrictamente necesario y lo demás en memoria secundaria.
La memoria secundaria era de mayor densidad, con un costo por bit menor, pero
con tiempos de acceso mayores que la memoria principal.
Teniendo la jerarquía ilustrada en la figura 4.1.
Para evitar que un programa de usuario que esté funcionando mal o “malicioso”
dañe el sistema operativo, se pueden verificar las direcciones generadas por el
programa y no permitir accesos si las direcciones corresponden al sistema operativo.
Si el usuario requiere accesar parte del sistema operativo se puede controlar a través
de un llamado al supervisor (SUPERVISOR CALL).
La protección de almacenamiento con asignación de almacenamiento contiguo a un
solo usuario es realizado a través del uso de registros límite según se ilustra en la figura
4.5.
Sistemas
operativo
Usuario
No usado
0
Sistemas
a operativo
CPU
a
Usuario
Registro limite
b
No usado
c
Figura 4.5. Esquema de protección en un sistema con un solo usuario y almacenamiento contiguo.
Aún con los sistemas tipo BATCH los sistemas de cómputo eran subutilizados
(ESTO SIN TOMAR EN CUENTA LO INJUSTO DE LOS TIEMPOS DE ESPERA)
pues un proceso que requiriera una operación de EIS forzaba al procesador a estar
ocioso hasta que estuviera completa dicha operación, según se ilustra en la figura 4.6.
En el caso de que una aplicación no realice operaciones de entrada / salida o sean muy
pocas se tienen un uso muy eficiente del CPU, esto es típico de aplicaciones “number-
crunching” o intensivas en cómputo.
Aún cuando se realice la operación de unión puede llegar a ocurrir que queden
muchos huecos no-contiguos, de forma que un proceso no quepa en ninguno de los
huecos, pero su tamaño sea menor o igual que la suma de los tamaños de los huecos.
Ante lo anterior se realiza una COMPACTACION o RECOLECCION DE
BASURA con el objeto de dejar contiguos todos los espacios ocupados y todos los
huecos, que ahora formarán un solo hueco. Este esquema es ilustrado en la figura 4.15.
Esto permitiría correr a todos los procesos posibles, pero tiene las siguientes
desventajas:
S O S O S O
P A Hueco
Hueco
Hueco Hueco
P C P C P C
Hueco Hueco Hueco
P E P E P E
P F P F P F
S O S O S O
P C P C P C
Hueco Hueco
Hueco
P E Hueco
P F P F P F
S O S O S O
Hueco Hueco
P C Hueco Hueco
Hueco Hueco
P F P F P F
S O S O
P A P A
Hueco P 2
P b
P C
Hueco
P C
Hueco
Hueco
Requerimiento
4 K
asigna
Sistema operativo
Hueco 16 K
P A
Hueco 14 K
P B
Hueco 5 K
P C
Hueco 30 K
4.20.Referencias
Memoria virtual
El termino memoria virtual está asociado a la habilidad de poder accesar un
espacio de almacenamiento mayor que el espacio de almacenamiento principal de un
sistema computacional.
Este concepto apareció por primera vez en el sistema computacional Atlas
construído en la universidad de Manchester en 1960.
Los métodos más comunes para el manejo de memoria virtual son:
• segmentación
• paginación
• segmentación con paginación
Absoluto Relocalizable
49
Almacenamiento
Mecanismo real
de mapeo de
Almacenamiento
direcciones
virtual
5.10. Segmentación
• lectura
• escritura
• ejecución
• agregado.
Los modos de control de acceso más comunes son:
R W E Comentario
0 0 0 No se permite acceso.
0 0 1 Solo ejecución.
0 1 0 No tiene sentido solo permitir escribir.
0 1 1 Ejecución si no se puede leer.???
1 0 0 Solo lectura.
1 0 1 Lectura y ejecución.
1 1 0 Lectura / escritura.
1 1 1 Acceso irrestricto.
V = (s, p, d)
s = número de segmento
p = número dentro del segmento
d = desplazamiento dentro de la página.
Este esquema se ilustra en la figura 5.9. Un esquema completo que ilustra varios
procesos bajo un esquema de paginación con segmentación es dado en la figura 5.10.
Estrategias de Búsqueda
Estrategias de Localización
Se refiere a “dónde” localizar dentro de memoria principal la página o segmento
que se trae de memoria secundaria.
Estrategias de Reemplazo
Se refiere a “cuál” segmento o página desplazar de memoria principal cuando no
haya espacio para localizar un segmento o página que es traído de memoria secundaria.
Establece que para obtener un desempeño óptimo la página que debe reemplazarse
es la que no será usada por el tiempo más largo en el futuro. Claro que esta política es
prácticamente irrealizable pues los sistemas operativos no cuentan con una “bola de
cristal” infalible.
La página a ser reemplazada es aquélla que no ha sido usada por el tiempo más
largo. La Heurística de esta política es que: “ El pasado reciente es un buen indicador
del futuro cercano ‘ .Esta política requiere que a cada página se le ponga una estampa
de tiempo
A Falta A – – Falta A – – –
B Falta B A – Falta B A – –
C Falta C B A Falta C B A –
D Falta D C D Falta D C B A
A Falta A D C No Falta D C B A
B Falta B A D No Falta D C B A
E Falta E B A Falta E D C B
A No Falta E B A Falta A E D C
B No Falta E B A Falta B A E D
C Falta C E B Falta C B A E
D Falta D C E Falta D C B A
E No Falta D C E Falta E D C B
3 No Faltas 2 No Faltas
cada vez que es referenciada, lo cual es un gran overhead; por esta razón se
implementan algunas estrategias que se aproximan a la LRU. Esta política podría
funcionar muy mal si se estuviera ejecutando un lazo donde se requieran muchas
páginas.
5.12.6. Reemplazo de Página Menos Frecuentemente Usada (LFU)
5.12.8. Localidad
Establece que los procesos tienden a referenciar el almacenamiento en forma no-
uniforme sobre patrones altamente localizados.
Localidad Temporal
Localidad Espacial
Significa que si se está accesando una localidad en particular es muy probable que
los siguientes accesos están cerca del lugar del anterior acceso. v.g.
• Recorrido de Arreglos.
• Ejecución de Código Secuencial.
• La tendencia de localizar variables relacionadas juntas.
La justificación de esto:
La idea es que los compiladores y sistemas operativos pudieran detectar cuando una
página ya no se necesita y liberarla, de esta forma los conjuntos de trabajo no
experimentarían grandes aumentos y podría mantenerse al mínimo el espacio de
memoria principal utilizado, pudiendo soportar mayor número de procesos.
5.13. Referencias
Para profundizaren el manejo de memoria virtual se recomiendan las siguientes
lecturas:
[38], [39], [18], [40], [33], [41], [26], [27], [24], [42], [35], [43], [36], [37], [44].
Sincronización y
comunicación de procesos
En este capítulo se verán diversos mecanismos de control de concurrencia, se tratan
ampliamente diversos mecanismos para realizar la sincronización y comunicación entre
procesos cooperativos y la solución de problemas de concurrencia clásicos.
Si deseamos sumar dos matrices, podemos desarrollar una versión paralela más
eficiente que una versión secuencial.
63
Los enunciados PARBEGIN y PAREND nos sirven para indicar que los estatutos
contenidos entre ellos pueden ejecutarse en forma paralela o concurrente.
También se utilizan los enunciados COBEGIN y COEND para el mismo propósito.
b 2 4ac
br
2a
PARBEGIN
TRANSACCION A;
TRANSACCION B;
PAREND.
Transacción A Transacción B
tl Saldo A = Saldo X
t2 Saldo B = Saldo X
t3 Saldo X = Saldo A - 1000
t4 Saldo X = Saldo B -1000
Si: ti < t2 < t3 < t4 y SaldoX = 2000 en tl. El valor final de SaldoX es 1000 pero
debería ser 0.
De lo anterior nos damos cuenta que no se debe permitir el acceso indiscriminado
de procesos concurrentes a variables o recursos compartidos.
3.- Dentro del ESTADO FUTURO existirán tantas columnas como posibles
cambios de estado puede haber. v.g. si se trata de dos procesos tendremos:
Digitalización con propósito academico. Sistemas operativos
66 CAP 6. SINCRONIZACIÓN Y COMUNICACIÓN DE PROCESOS
program versionone;
En este caso el estado constará de tres números, el primer número indica el número
de instrucción del proceso 1, el segundo número el número de instrucción del proceso 2
y el tercer número el valor de la variable processnumber
La gráfica que ilustra la ejecución de este programa es la figura 6.1
Program versiontwo;
var p1 inside, p2inside: boolean;
procedure processone;
begin
while true do
begin
program versionthree;
varplwantstoenter p2wantstoenter:boolean;
procedure processone;
begin
while true do
begin
p1wantstoenter:=true;
while p2wantstoenter do;
criticalsectionone;
pl wantstoenter: =false;
otherstuffone
end
end;
procedure processtwo;
begin
while true do
begin
p2wantstoenter: =true;
while plwantstoenter do;
criticalsectiontwo;
p2wantstoenter: =false;
otherstufftwo
end
end;
begin
p1wantstoenter:=false;
p2wantstoenter: =false;
parbegin
processone;
processtwo;
parend
end.
program versionfour;
var p1wantstoenter,p2wantstoenter:boolean;
procedure processone;
begin
while true do
begin
plwantstoenter:=true;
while p2wantstoenter do
begin
pl wantstoenter: =false;
delay(random, fewcycles);
plwantstoenter =true;
end;
criticalsectionone;
plwantstoenter: =false;
otherstuffone
end
end;
procedure processtwo;
begin
while true do
begin
p2wantstoenter: =true;
while plwantstoenter do
begin
p2wantstoenter: =false;
delay(random, fewcycles);
p2wantstoenter:=true;
end;
criticalsectiontwo;
p2wantstoenter: =false;
otherstufftwo
end
end;
begin
plwantstoenter: =false;
p2wantstoenter: =false;
parbegin
processone;
processtwo
parend
end.
program dekkersalgorithm
var favoredprocess:(first, second);
plwantstoenterp2wantstoenter:boolean;
procedure processone;
begin
while true do
begin
plwantstoenter:=true;
while p2wantstoenter do
if favoredprocess = second then
begin
plwantstoenter: =false;
while favoredprocess second do
p1 wanstoenter: =true;
end;
criticalsectionone;
favoredprocess: =second;
plwantstoenter: =false;
otherstuffone
end
end;
procedure processtwo;
begin
white true do
begin
p2wantstoenter:=true;
while plwantstoenter do
if favoredprocess = first then
begin
p2wantstoenter: =false;
while favoredprocess =first do
p2wanstoenter: =true;
end;
criticalsectiontwo;
favoredprocess: =first;
plwantstoenter: =false;
otherstufftwo
end
end;
begin
plwantstoenter: =false;
p2wantstoenter: =false;
favoredprocess. =first;
parbegin
processone;
processtwo
parend
end.
turn := 2;
while enter2 and turn=2 do;
criticalsectionone;
enterl:=false;
otherstuffone
end
end;
procedure p2;
begin
while true do
begin
enter2: =true;
turn:= 1;
while enterl and turn=l do;
criticatsectiontwo;
enter2:=false;
otherstufftwo;
end
end;
begin
enterl:=false;
enter2: =false;
turn: =l;
parbegin
pl;
p2;
parend
end.
6.9. Semáforos
Habilita_Interrupciones;
Fin P;
V(id_sem);
Deshabilita_Interrupciones;
id_sem.cont =id_sem.cont+1;
Si (id_sem. cont < =0) Entonces Desbloqueo _ proceso;
Habilita_Interrupciones;
Fin V;
Detalles importantes respecto a semáforos:
• El valor inicial del semáforo indica en términos generales el número de unidades
disponibles de algún recurso.
• En el caso de exclusión mutua el número de recursos es 1 y este es el valor inicial
del semáforo.
• Cuando el contador del semáforo tiene valores negativos indica el número de
procesos bloqueados en ese semáforo.
• La exclusión mutua se resuelve en forma sencilla usando semáforos.
• De acuerdo al valor máximo del semáforo se clasifican en:
— Semáforos binarios: valor máximo = 1.
— Semáforos generales: No tiene límite.
Inicialización;
Sem_mutex: =1;
Parbegin
Proceso 1;
Proceso2;
Parend;
Fin Programa Exc_Semaforo.
Y la comunicación entre procesos?
Se tienen dos procesos, uno produce unidades de información de una en una y las
deposita en un buffer; y el otro las consume del mismo buffer también de una en una.
1. Plantear un solución usando pseudocódigo y considerando:
2. El buffer es de capacidad ilimitada por lo cual no se puede dar la situación de buffer
lleno.
3. El consumidor deberá ser bloqueado si no hay unidades de información.
4. Las operaciones de manipulación del buffer deben hacerse en forma secuencial.
5. Plantee una solución usando:
• — Semáforos generales.
— Semáforos binarios.
PRODUCE_UNIDADES_DE_INFORMAClON;
P(SEM_BUFFER);
AGREGA_UNIDADES_ÁL_BUFFER;
V(SEM_BUFFER);
V(SEM_UNIDADES);
____
FIN PRODUCTOR;
CONSUMIDOR;
____
P(SEM_BUFFER);
P(SEM_UNIDADES);
TOMA_PORCION_DEL_BUFFER;
V(’SEM_BUFFER);
CONSUME_UNIDADES_DE_INFORMACIÓN;
FIN CONSUMIDOR;
INICIALIZAClON:
SEM_UNIDADES:=0;
SEM_BUFFER: =1;
PARBEGIN
PRODUCTOR;
CONSUMIDOR;
PAREND;
FIN PROGRAMA PROD_CON_SEM_GEN.
PROGRAM PROD_CON_SEM_GEN2;
VARIABLES
SEM_UNIDADES: SEMAFORO GENERAL;
SEM_BUFFER: SEMAFORO GENERAL;
PRODUCTOR;
____
PRODUCE_UNIDADES_DE_INFORMAClON;
P(SEM_BUFFER);
AGREGA_UNIDADES_ÁL_BUFFER;
V(SEM_BUFFER);
V(SEM_UNIDADES);
____
FIN PRODUCTOR;
CONSUMIDOR;
____
P(SEM_UNIDADES);
P(SEM_BUFFER);
TOMA_PORCION_DEL_BUFFER;
V(SEM_BUFFER);
CONSUME_UNIDADES_DE_INFORMACION;
____
FIN CONSUMIDOR;
INICIALIZAClON:
SEM_UNIDADES: =0;
SEM_BUFFER:=1;
PARBEGIN
PRODUCTOR;
CONSUMIDOR;
PAREND;
FIN PROGRAMA PROD_CON_SEM_GEN2.
PROGRAMA PROD_CON_SEM_BOOL;
CONSTANTES
MAX_BUFFER: =MAX;
TIPO
BUFFER=0. .MAX_BUFFER;
VARIABLES
SEM_CONSUMIDOR : SEMAFORO BINARIO;
SEM_BUFFER: SEMAFORO BINARIO;
NUM_UNIDADES: BUFFER;
PRODUCTOR;
____
PRODUCE_UNIDAD_DE_INFORMAClON;
P(SEM_BUFFER);
AGREGA_UNIDAD_ÁL_BUFFER;
NUM_UNIDADES: =NUM_UNIDADES+ 1;
SI NUM_UNIDADES=1 ENTONCES V(SEM_CONSUMIDOR);
V(SEM_BUFFER);
____
FIN PRODUCTOR;
CONSUMIDOR;
____
(SEM_CONSUMIDOR);
REPITE
P(SEM_BUFFER);
TOMA_PORCION_DEL_BUFFER;
NUM_UNIDADES: =NUM_UNIDADES-1;
V(SEM_BUFFER);
CONSUME UNIDAD_DE_INFORMAClON;
HASTA QUE NUM_UNIDADES=O;
____
FIN CONSUMIDOR;
INICIALIZAClON:
SEM_CONSUMIDOR: =0;
SEM_BUFFER: =1;
NUM_UNIDADES:=0;
PARBEGIN
PRODUCTOR;
CONSUMIDOR;
PAREND;
FIN PROGRAMA PROD_CON_SEM_BOOL.
PROGRAMA PROD_CON_SEM_BOOL2;
CONSTANTES
MAX_BUFFER: =MAX;
TIPO
BUFFER=0. .MAX_BUFFER;
VARIABLES
SEM_CONSUMIDOR : SEMAFORO BINARIO;
SEM_BUFFER: SEMAFORO BINARIO;
NUM_UNIDADES: BUFFER;
PRODUCTOR;
____
PRODUCE_UNIDAD_DE_INFORMACION;
P(SEM_BUFFER);
AGREGA_UNIDAD_AL_BUFFER;
NUM_UNIDADES: =NUM_UNIDADES+ 1;
SI NUM_UNIDADES= 1 ENTONCES V(SEM_CONSUMIDOR);
V(SEM_BUFFER);
____
FIN PRODUCTOR;
CONSUMIDOR;
VARIABLES
NUM_UNIDADES_ANT_BUFFER;
____
P(SEM_CONSUMIDOR);
REPITE
P(SEM_BUFFER);
TOMA_PORCION_DEL_BUFFER;
NUM_UNIDADES: =NUM_UNIDADES-1;
NUM_UNIDADES_ANT: =NUM_UNIDADES;
V(SEM_BUFFER);
CONSUME_UNIDAD_DE_INFORMACION;
HASTA QUE NUM_UNIDADES_ANT=0;
____
FIN CONSUMIDOR;
INICIALIZAClON:
SEM_CONSUMIDOR: =0;
SEM_BUFFER: = 1;
NUM_UNIDADES: =0;
PARBEGIN
PRODUCTOR;
CONSUMIDOR;
PAREND;
FIN PROGRAMA PROD_CON_SEM_BOOL2.
PROGRAMA PROD_CONSUMIDOR;
CONSTANTES
max=max_unidades_buffer;
VARIABLES
Sem_productor:SEMAFORO GENERAL;
Sem_consumidor:SEMAFORO GENERAL;
Sem_mutex :SEMAFORO GENERAL;
PRODUCTOR:
____
____
produce_unidades_de_información;
P(sem_productor);
P(sem_mutex);
Agrega_unidad_al_buffer;
V(sem_mutex);
V(sem_consumidor);
____
____
FIN PRODUCTOR;
CONSUMIDOR;
____
____
P(sem_consumidor);
P(sem_mutex);
toma_unidad_del_buffer;
V(sem_mutex),
V(sem_productor);
____
____
FIN CONSUMIDOR;
INICIALIZACION:
Sem_mutex: =I;
Sem_productor: =max;
Sem_consumidor: =0;
PARBEGIN
PRODUCTOR;
CONSUMIDOR;
PAREND;
FIN PROGRAMA PROD_CONSUMIDOR.
sem_buffer:= 1;
unidades: =0;
PARBEGIN
PRODUCTOR;
CONSUMIDOR;
PAREND
FIN PROGRAMA PROD_CONSUMIDOR.
Sólo lectores
Inicialización:
Cont_lec : = O;
mutex := 1;
PARBEGIN
___
Proceso Lector_i;
PAREND
FIN Programa Lectores;
Sólo Escritores
Programa Escritores;
Variables
mutex: Semáforo Binario;
Proceso Escritor_j;
___
___
P(mutex);
(*Acceso alabase de datos *)
V(mutex);
___
___
Fin Proceso Escritor_j;
Inicialización:
mutex:= 1;
PARBEGIN
___
Proceso Escritor_j;
___
PAREND
FIN Programa Escritores;
Lectores y escritores
Plantear el pseudocódigo que implemente el acceso a una base de datos por parte de
varios procesos de tipo lector y varios procesos de tipo escritor, considerando que:
Los lectores pueden accesar la base de datos en forma concurrente pero mientras
esté accesando un lector ningún escritor podrá realizar su acceso.
Los escritores deben accesar la base de datos en forma mutuamente exclusiva, y
ningún lector podrá accesar la Base de Datos mientras lo esté haciendo un escritor.
Existen dos alternativas de solución:
P(Esc);
(* acceso a la base de datos *)
V(Esc);
___
___
FIN Proceso Escrito_j;
INICIALIZAClON:
Mutex := 1;
Ese := 1;
Cont_Lec := 0;
PARBEGIN
___
Proceso Lector_i;
___
Proceso Escritor-j;
___
PAREND
FIN Programa Lectores_Prioridad;
PROGRAMA Escritores_Prioridad;
Constantes
Max_L = M;
Max_E = N;
Tipos
Lee = 0,1,2,..., Max_L;
Ese = 0,1,2,..., Max_E;
Variables
Mutexl : Semáforo Binario;
Mutex2 : Semáforo Binario;
Mutex3: Semáforo Binario;
Lectores: Lec;
Escritores: Esc;
Sem_Lec : Semáforo General;
Sem-Esc: Semáforo General;
Proceso Lector_i;
___
P(Mutex3);
P(Sem_lec);
P(Mutexl);
Lectores: =Lectores+ 1;
SI Lectores = 1 ENTONCES P(Sem_Esc);
V(Mutexl);
V(Sem_Lec);
V(Mutex3);
(* Lectura *)
P(Mutexl);
Lectores : = Lectores - 1;
SI Lectores = 0 ENTONCES V(Sem_Esc);
V(Mutexl);
___
P(Mutex2);
Escritores: =Escritores+l;
SI Escritores = 1 ENTONCES P(Sem_Lec);
V(Mutex2);
P(Sem_Esc)
(* Escritura *)
V(Sem_Esc);
P(Mutexl);
Escritores:=Escritores-1;
SI Escritores = 0 ENTONCES V(Sem_Lec);
V(Mutex_2);
___
FIN Proceso Escritor_j;
INICIALIZACION:
Mutexl := 1;
Mutex2 := 1;
Mutex3 := 1;
Lectores := 0;
Escritores : = 0;
Sem_Lec := 1;
Sem_esc := 1;
PARBEGIN
Proceso Lector_i;
Proceso Escritor_j;
PAREND
FIN Programa Escritores_Prioridad;
Constantes
Max_L = Máximo_de_Lectores;
Max_E = Máximo_de_Escritores;
Tipos
L=0,1,..., Max_L;
E=0,1,..., Max_E;
Variables
Sem_Lec: Semáforo General;
Sem_Esc: Semáforo General;
Sem_Mutex: Semáforo Binario;
Cont_Lec: L;
Cont_Esc: E;
Escribiendo: Booleano;
Lec_Acce: L;
Proceso Lector_i;
___
P(Sem_Mutex);
SI (Escribiendo) O (Cont_Es <>0)
ENTONCES
Cont_Lec:= Cont_Lec+1;
V(Sem_Mutex);
P(Sem_Lec)
Cont_Lec: = Cont_Lec-1;
FIN ENTONCES
Lec_Acce: = Lec_Acce+1;
SI (Con_Lec <> O) ENTONCES V(Sem_Lec)
SINO V(Sem_Mutex);
(* Lectura *)
P(Sem_Mutex);
Lec_Acce:=Lec_Acce-1;
SI (Lec_Ácce=O ) Y(Cont_Esc <> 0 )
ENTONCES V(Sem_Esc)
SINO V(Sem_Mutex)
___
P(Sem_Mutex);
SI (Lec_Acce <> 0) Y (Escribiendo)
ENTONCES
Cont_Esc: =Cont_Esc+1;
V(Sem_Mutex);
P(Sem_Esc);
Cont_Esc: = Con_Esc-1;
FIN ENTONCES;
Escribiendo := V;
V(Sem_Mutex);
(* Escritura *)
P(Sem_Mutex);
Escribiendo := F;
SI (Cont_Lec <> 0) ENTONCES V(Sem_Lec)
SINO
SI (Cont_Esc <> 0) ENTONCES V(Sem_Esc)
SINO V(Mutex);
FIN SINO
___
FIN Proceso Escritor_j;
INICIALIZAClON:
Sem_Lec := 0;
Sem_Esc := 0;
Cont_Lec := 0;
Cont_Esc : = 0;
Lec_Acce := 0;
Sem_Mutex := 1;
Escribiendo : =F;
PARBEGIN
Proceso Lector_i;
___
Proceso Escritor_j;
___
PAREND
FIN Programa Lectores_Escritores;
Programa filósofos;
Constantes
MarFil = 5;
Tipos
Ten = 0,1,2;
Fil = 0,1,..., Max_Fil-1;
Variables
Sem_Áux : Semáforo General;
Num_ten : Arreglo [O..Max_fil-1] DE Ten;
Fil_Bloq : Arreglo [O..Max_fil-1] DE Booleano;
Sem_Mutex: Semáforo Binario;
Sem_Fil : Arreglo [O..Max_fil-1] DE Semáforo General;
I_Fil:Fil;
Procedimiento Filosofo_i;
___
Filosofar;
Toma Tenedor(i);
Comer;
Libera Tenedor(i);
___
SINO
Num_Ten[Izq(i)] := Num_Ten[Izq(i)] - 1;
Num_Ten[Der(i)] := Num_Ten[Der(i)] - 1;
V(Sem_Mutex);
FIN SINO
FIN Procedimiento Libera_Tenedor;
Procedimiento Libera_Tenedor(i : Fil);
P(Sem_Mutex);
Num_Ten[Izq(i)]:= Num_Ten[Izq(i)] + 1;
Num_Ten[Der(i)] := Num_Ten[Der(i)] + 1;
SI (Num_Ten[Der(i)] = 2) Y (Fil_Bloq[Der(i)])
ENTONCES
V(Sem_Fil[Der(i)]);
P(Sem_Aux);
FIN ENTONCE;,
SI (Num_ten[Izq(i)] 2) Y (Fil_Bloq[Izq(i)]) ENTONCES
V(Sem_Fil[Izq(i)]);
P(Sem_Áux);
FIN ENTONCES;
V(Sem_Mutex);
FIN Procedimiento Libera_Tenedor;
INICIALIZAClON:
PARA I_Fi1 := 0 HASTA Max_Fil - 1 HAZ
Num_Ten[I_FiI] := 2;
Fil_Bloq[i] : = F;
Sem_Fil[i] = 0;
FIN PARA
Sem_Áux = O;
Sem_Mutex := 1;
PARBEGIN
___
Filosofo 1;
___
PAREND;
FIN Programa filósofos;
6.9.5 Problema de K-procesos en la sección crítica
La siguiente solución intenta resolver el problema de permitir que K de n procesos
puedan ejecutar concurrentemente su sección crítica usando para esto sólo semáforos
binarios.
1. Muestre que es posible que retardo=2 siendo que es un semáforo binario para k = 2
n = 3; k = 2 n 4. Y se podría concluir que no funciona para valores de n mayores.
Generar una gráfica que incluya todos los posibles estados y transiciones.
Programa k_de_n;
CONSTANTES
k=;
n=;
VARIABLES
Contador : Entero; Mu
Mutex: Semáforo Binario;
Retardo: Semáforo Binario;
Procedimiento Proceso_i;
___
P(Mutex);
Contador := Contador –1;
SI contador <= l
ENTONCES
V(Mutex);
P(Retardo);
V(mutex);
FIN ENTONCES
SINO V(Mutex);
(* Sección Crítica *)
Digitalización con propósito academico. Sistemas operativos
6.9. SEMÁFOROS 93
P(Mutex);
Contador := Contador+1;
SI Contador <= 0
ENTONCES V(Retardo)
SINO V(Mutex);
___
Variables
Sem_Recurso : Arreglo [1..3] DE Semáforo Binario;
Sem_Fumador: Arreglo [1..6] DE Semáforo General;
Mutex: Semáforo Binario;
Sem_Ágentes: Semáforo Binario;
Acum: Entero;
Termina_Ágente: Arreglo [1..3] DE Booleano;
Procedimiento Forza_Terminación;
Variables
i: Entero;
Acum:=0;
PARA i:=1 HASTA 3 HAZ
V(Sem_Recurso [i]);
FIN_PARA;
PARA i:=1 HASTA 6 HAZ
V(Sem_Fumador[i]);
FIN_PARA;
FIN Procedimiento Forza_Terminación;
Procedimiento Agente (Acum, Rec1, Rec2 : Entero);
Variables
I: Entero;
PARA i:=1 HASTA Viajes HAZ
P(Sem_Agentes);
V(Sem_Recurso[Recl]);
V(Sem_Recurso[Rec2]);
FIN PARA;
Termina_Agente[num]: =V;
FIN Procedimiento Agente;
Procedimiento Ayudante (Num, Incremento: Entero);
REPITE
P(Sem_Recurso[Num]);
P(Mutex);
Acum: =Acum+Incremento;
V(Sem_Fumador[Acum]);
V(Mutex);
HASTA Termina_Ágente[1] Y
Termina_Ágente[2] Y
Termina_Ágente[3];
Forza_Terminación;
FIN Procedimiento Ayudante;
Procedimiento Fumador(Num, Valor_Acum : Entero);
REPITE
P(Sem_fumador[Valor_Acum]);
Acum:=0;
V(Sem_Agentes);
HASTA Termina_Agente[Num];
FIN Procedimiento Fumador;
Inicialización:
PARA Acum:=1 HASTA 3 HAZ
Sem_Recurso[Acum]: =0;
Termina_Ágente[Acum]: =F;
FIN PARA;
PARA Acum:=1 HASTA 6 HAZ
Sem_Fumador[Acum]: =0;
FIN PARA;
Acum:=0;
Mutex:=1;
Sem_Agentes:=I;
PARBEGIN
Agente(1,2,3);
Agente(2, 1,3);
Agente(3, 1,2);
Ayudante(1, 1);
Ayudante(2,2);
Ayudante(3,4);
Fumador(I,6);
Fumador(2,5);
Fumador(3,3);
PAREND;
FIN Cigarro;
Solución:
1 Los procesos ayudante proporcionan recursos a los fumadores, de acuerdo a la
siguiente gráfica:
Concluimos que:
2 y 4 Los agentes terminan después de “viajes” veces. Los ayudantes terminan hasta
que todos los agentes hayan modificado su variable termina _ agente[] haciéndola
verdadera; si por lo menos un ayudante encuentra ésta condición, los ayudantes pueden
terminar, de otra forma no. Los fumadores terminan cuando el agente respectivo haya
modificado a verdadero la variable termina _ agente [], pero si el fumador checa dicha
variable antes de
Digitalización con propósito academico. Sistemas operativos
96 CAP 6. SINCRONIZACIÓN Y COMUNICACIÓN DE PROCESOS
que se modifique sólo podrá terminar si acaso termina por lo menos un ayudante, pero
de ésta forma ejecutará su código una vez más que su agente respectivo.
3 De no hacerse esto posiblemente algún ayudante pudiera ejecutar
V(sem_fumador[i]) para i > 6
o sea para un semáforo inexistente.
5 Que no tienen ninguna función y se van acumulando operaciones V sobre ellos, y
si el número de viajes fuera grande podría llegar el caso que se sobrepase la
representación de un entero.
6
Programa Cigarro;
Constantes
Viajes20;
Variables
Sem_Recurso : Arreglo[1. .3] DE Semáforo Binario;
Sem_Fumador Arreglo [1..3] DE Semáforo Binario;
Mutex: Semáforo Binario;
Sem_Agentes : Semáforo Binario;
Acum : Entero;
Procedimiento Agente(Num, Red, Rec2: Entero);
Variables
Entero;
PARA i:=1 HASTA Viajes HAZ
P(Sem_Agentes);
V(Sem_Recurso[Recl]);
V(Sem_Recurso[Rec2]);
FIN PARA;
FIN Procedimiento Agente;
Procedimiento Ayudante(Num: Entero);
Variables
i: entero;
PARA i:=1 HASTA Viajes HAZ
P(Sem_Recurso[Num]);
P(Mutex);
pon_bit(Acum,Num);
CASO Acum
6: V(Sem_Fumador[1]);
5: V(Sem_Fumador[2]);
3: V(Sem_Fumador[3]);
SINO no_hagas_nada;
FIN CASO;
V(Mutex);
FIN PARA;
FIN Ayudante;
6.10. Pipes
• READRECORD (pipenumber);
lectores:=lectores+1; escribiendo:= V;
end; end;
(*lectura*) (*escritura *)
región BD do región BD do
lectores: = lectores-1; escribiendo: =F;
end; end;
___ ___
Fin lector_i. Fin escritor_j.
Para definir el “que hacer” cuando ocurra una interrupción, los procesos podrían
hacer un llamado como: Handle(interruptnumber,method) Donde “method” puede
especificar:
1. Ignorar la interrupción.
2. Terminar si la interrupción ocurre.
3. Esperar a que ocurra la interrupción.
4. Si ocurre la interrupción, activar a una rutina de Servicio de Interrupción.
PROGRAMA Productores_Consumidores;
EXPORTA GETBUFFER,PUTBUFFER;
CONSTANTES
Size= 10; (* tamaño del buffer *)
TIPOS
Dato = ...; (* tipo de dato del buffer *)
VARIABLES
BUFFER : ARREGLO [O..Size-1] DE Dato;
NextIn,NextOut: 0..Size-1;
(* índice para insertar o borrar siguiente dato *)
INVARIANT PUTBUFFER;
(STARTCOUNT(PUTBUFFER) – FINISHCOUNT(GETBUFFER)) < Size;
(* No sobre producción *)
CURRENTCOUNT(PUTBUFFER) =0;
(* Previene conflictos de productores *)
INVARIANT GETBUFFER,
(STARTCOUNT(GETBUFFER) – FINISHCOUNT(PUTBUFFER)) <O;
(* No sobre consumo *)
CURRENTCOUNT(GETBUFFER) =0;
(* Previene conflictos de consumidores *)
PROCEDIMIENTO PUTBUFFER(QUE:Dato);
BUFFER[NextIn]: = QUE;
Nextln:=(Nextln+ 1) MOD Size;
FIN PUTBUFFER;
PROCEDIMIENTO GETBUFFER( VAR RESULTADO:Dato);
RESULTADO: =BUFFER[NextOut];
NextOut:=(NextOut+1) MOD Size;
FIN GETBUFFER;
FIN PROGRAMA Productores_Consumidores.
Problema de Lectores_Escritores.
INVARIANT Lectura;
(WAITCOUNT(Escritura) + CURRENTCOUNT(Escritura)) =0;
(* si no hay alguien escribiendo o esperando escribir entonces se puede leer *).
INVARIANT Escritura;
(CURRENTCOUNT(Escritura) + CURRENTCOUNT(Lectura)) = 0;
(* Si no hay ningún escritor escribiendo y ningún lector leyendo entonces se puede
escribir *)
NOTA: Al terminar un proceso se asume que el reinicio es de acuerdo al orden de
llegada, pero se debe considerar adicionalmente que cuando termine un escritor deben
reiniciarse todos los lectores esperando.
VARIABLES
SequenceNumber:ENTERO;
Valor:Dato;
PARA SequenceNumber:=1 HASTA Infinito
Produce_Valor;
AWAIT(Out reaches SequenceNumber-Size);
Buffer[SequenceNumber MOD Size]: = Valor;
ADVANCE(In);
FIN PARA;
FIN Productor;
Procedimiento Consumidor;
VARIABLES
SequenceNumber:ENTERO;
ValorDato;
PARA SequenceNumber: = 1 HASTA Infinito
AWAIT(In reaches SequenceNumber);
Valor:=Buffer[SequenceNumber MOD Size];
ADVANCE(Out);
Consume_Valor;
FIN PARA;
FIN Consumidor;
INICIALIZAClON:
(* Se inicializan los contadores de eventos *)
PARBEGIN
Productor;
Consumidor;
PAREND:
FIN Productor_Consumidor;
6.17.1 Secuenciadores
Permite asignar un orden arbitrario a eventos desordenados, este orden puede ser
usado para determinar qué proceso obtendrá primeramente un recurso.
Un secuenciador es un ADT implementado con un entero no decreciente
inicializado en cero, su única función de acceso es:
TICKET(S) Regresa el valor actual del secuenciador 5 y después incrementa 5.
Inicialmente 5 es cero. Es una operación atómica y debe garantizarse que no haya dos
llamados a TICKET que regresen el mismo valor.
v.g
Resolvemos el problema anterior de Productor-Consumidor, pero ahora con
múltiples productores y un sólo consumidor:
Programa Productor_Consumidor;
___
VARIABLES
___
Turn: Sequencer;
Procedimiento Productor_i;
VARIABLES
SequenceNumber:ENTERO;
Valor:Dato;
LAZO
Produce_Valor;
SequenceNumber: = TICKET(Turn);
AWAIT(In reaches SequenceNumber);
AWAIT(Out reaches SequenceNumber-Size+ 1);
Buffer[SequenceNumber MOD Size]: = Valor;
ADVANCE(In);
FIN LAZO;
FIN Productor_i;
6.18. Monitores
—
—
P(sem_mutex);
— (* sección crítica *)
V(sem_mutex);
—
—
Fin Proceso1;
Proceso2;
—
—
P(sem_mutex);
— (* sección crítica *)
V(sem_mutex);
—
—
Fin Proceso2;
Inicialización;
Sem_mutex:=1;
Parbegin
Proceso1;
Proceso2;
Parend;
Fin Programa Exc_Semáforo;
Usando el concepto de MONITOR el código de los procesos se vería así:
Programa Exc_Semaforo;
Proceso1;
—
—
Enter;
— (* sección crítica *)
Exit;
—
Fin Proceso1;
Proceso2;
—
Enter;
— (* sección crítica *)
Exit;
—
—
Fin Proceso2;
Inicialización;
Parbegin
Proceso1;
Proceso2;
Parend;
Fin Programa Exc_Semaforo.
Mientras el código del MONITOR se vería así:
MONITOR Exclusión;
VAR
Sem_mutex: Semáforo Binario;
Procedimiento Enter;
P(sem_mutex);
Fin Enter;
Procedimiento Exit;
V(sem_mutex);
Fin Exit;
Inicialización:
Sem_mutex:=1;
Fin Monitor Exclusión.
Algo fundamental de un monitor es que es una parte de código es PASIVA, que
solo se ejecuta cuando se manda llamar, y que su parte de inicialización es ejecutada
automáticamente antes de que se mande llamar alguno de sus procedimientos.
Existen cuatro tipos de monitores reportados en la literatura: Monitor Tipo Monitor,
Monitor Tipo Manager, Monitor Tipo Mediador y Monitor Tipo Gladiador
6.19.Referencias
Manejo de Interbloqueo
(Deadlock)
7.1. Introducción
1._ Prevención.
En este caso se requiere que cada proceso especifique de antemano la cantidad de
recursos que requerirá, y cuando se desea un recurso se analiza si el nuevo estado es un estado
seguro, de ser así se otorga el recurso, de otro modo NO. De este modo controlando la
asignación de recursos se EVITA EL DEADLOCK.
2._ Detección/recuperación.
En este caso basta que un recurso esté libre para que sea otorgado al momento de
realizar una petición. De este modo es posible que se dé el Deadlock y en forma periódica se
corre un algoritmo que lo detecta. En caso de haber DEADLOCK se corre un algoritmo que
recupera del deadlock a través del reinicio/desasignación de recursos.
3._ Nulo.
Si el deadlock es poco frecuente y además la aplicación no es crítica un enfoque es NO
HACER NADA, en estos casos si ocurre el deadlock y el sistema se para se reinicia el
sistema.
109
El estado del sistema es definido a través de las estructuras de datos (W, A, f) donde:
3URFHVRFRQWLQXD
3URFHVR
(VSHUD 3URFHVR(VSHUD
DVLJQDGRU
'HFLGLHQGR 2FLRVR
5HTXHULPLHQWR 5HTXHULPLHQWR
DYDQ]DGR
3URFHVRFRQWLQXD
3URFHVR (VSHUD
3URFHVR(VSHUD
DVLJQDGRU
'HFLGLHQGR 2FLRVR
5HTXHULPLHQWR
Proceso continua
3URFHVR (VSHUD
3URFHVR(VSHUD
DVLJQDGRU
$FWXDOL]D 2FLRVR
Teorema de Fontao
Para un estado del sistema representado por {W, A, f) y considerando que dicho estado es
seguro, si un proceso Pi requiere q unidades del recurso j el recurso puede ser otorgado en
forma segura si: Pi ǝ Hjq U Tjq
El calculo de la matriz R como se deduce de lo anterior esta basado en el calculo de los
conjuntos H y T, como podrá suponerse en la matriz R sólo se pondrá el máximo de unidades
que pueden ser otorgadas a cada proceso.
Adicionalmente se puede comentar que:
Este algoritmo representa una buena alternativa para la prevención del deadlock en
sistemas multiprocesadores con ciclos de CPU ociosos.
El cálculo de la matriz R puede ser hecho concurrentemente para cada recurso.
El vector surplus es muy útil para poder tomar medidas estadísticas del uso de los
recursos.
PROGRAMA FONTAO;
CONSTANTES
n = max de procesos;
m = max de recursos;
todos = 0,1,2,...,n;
vacio = 0;
max = máximo de unidades de cualquier recurso;
TIPOS
recurso = 0,1,..,max;
vector_recurso = ARREGLO[1..m] de recurso;
conj-proceso = CONJUNTO DE [0,l,..,n]
proceso = 1,2,...,n;
proceso_mas_cero = 0,1,2,. ..,n;
VARIABLES
A : ARREGLO [1..n] DE vector_recurso;
W : ARREGLO [1..n] DE vector_recurso;
F: vector-recurso;
R: ARREGLO [1..n] DE vector_recurso;
H: conj-proceso;
T: conj-proceso;
P : conj-proceso;
Los algoritmos de detección de deadlock representan una gran ventaja sobre los
algoritmos de prevención al no requerir que se especifique previamente el número y tipo de
recursos que requerirá cada proceso.
En aplicaciones como las de acceso a una base de datos en las que no se sabe
previamente que archivos ni que registros se van a utilizar, no es posible aplicar algoritmos de
prevención de deadlock, por lo que se aplican algoritmos como los de detección de deadlock y
técnicas de estampillas de tiempo (timestamp).
Los algoritmos de detección tienen que ser diseñados considerando las siguientes
alternativas:
x Cuándo correr.
x Cómo detectar el deadlock.
x Cómo recuperarse del deadlock.
Considerar que los procesos No-Bloqueados Terminan, de forma tal que al liberar los
recursos que tenían asignados algunos de los procesos Bloqueados podrían obtener los
recursos solicitados de forma tal que se convertirían en No-Bloqueados.
Esta es una de las partes más difíciles de resolver, puesto que el corregir el deadlock
involucra en general que parte o el total del trabajo realizado por un proceso queda invalidado,
prácticamente el proceso tiene que ser reiniciado o por lo menos regresado a un punto
ESTABLE (CONCEPTO DE TRANSACCIÓN).
Para corregir el deadlock básicamente se deben desasignar unidades de recursos a uno o a
varios procesos, puesto que no siempre ocurre que al desasignar unidades a un proceso quede
corregido el deadlock.
Seleccionar al proceso al que se le desasignarán unidades de algún recurso no es fácil
puesto que debería considerarse:
7.4. Referencia.
Para ampliar los conocimientos sobre el problema de interbloqueo se recomienda consultas las
siguientes referencias:
[57], [58], [59], [60], [61], [62], [63], [64], [65], [66], [14], [3], [16], [30], [18], [53].
Un sistema de archivos debe ser capaz de proporcionar diversas funciones accesibles por el
usuario:
Por ejemplo para llevar el control de los teléfonos de personas podría ser útil un archivo de
datos que constará de los datos de la tabla 8.1.
1RPEUH 7HO«IRQR
9DUJDV5XE«Q
'¯D]5D¼O
5XL]3HGUR
0DUW¯QH]5D¼O
119
El problema de la tabla 9.1 es que, dado que los datos no están ordenados, buscar un teléfono en
particular puede ser lento. Asumiendo que tenemos N renglones en la tabla, localizar un elemento en
particular tendría los siguientes casos:
x Mejor Caso: Sólo se busca en 1 renglón.
x Peor Caso: Se busca en los N renglones.
x Caso Promedio: Se busca en N+1
2
renglones.
Los casos Mejor y Peor son fáciles de derivar para calcular el caso promedio se ha hecho uso de
N
la fórmula: CasoPromedio = ¦ TodosCasos Y tenemos que: ¦TodosCasos= ¦ i .Para obtener
i=1
Num Casos
simbólicamente el valor de esta sumatoria sumemos dos veces de la siguiente manera:
1 2 3 ... N–1 N
N N -1 N-2 ... 2 1
________ ________ ________ ________ ________
(N + 1) (N + 1) (N + 1) ... (N + 1) (N + 1)
N (N + 1)
N __2___ (N + 1)
de donde N (N + 1) = 2 ¦i concluyendo entonces que: casoPromedio = N
= 2 . Este tipo de
i=1
búsqueda de la conoce como búsqueda secuencial y es a única alternativa de búsqueda cuando los datos
no están ordenados y se cuenta con estructuras auxiliares.
Si los datos anteriores son ordenados (lo cuál podría hacerse con un algoritmo similar al
QuickSort que tiene un orden de N log N) esto se ilustra en la tabla 8.2. Podemos utilizar una búsqueda
binaria. La ventaja de la búsqueda binaria es que en cada operación el tamaño del problema se reduce a
la mitad.
1RPEUH 7HO«IRQR
'¯D]5D¼O
0DUW¯QH]5D¼O
5XL]3HGUR
9DUJDV5XE«Q
x Mejor Caso = 1
x Peor Caso = [logm(N)].
x Caso promedio = 1+[logm(N)]
2
El inconveniente de utilizar una búsqueda binaria es que al hacer altas, bajas y cambios sobre
una tabla ordenada, tenemos que organizar los datos para que se mantengan ordenados, y esto podría
tomar mucho tiempo. Ante este problema una alternativa es la utilización de un índice (similar al de la
parte final de un libro) que contendría el nombre de la persona y un apuntador a dónde esta el elemento
dentro de la tabla. Como puede notarse, los datos en la tabla podrán estar físicamente desordenados,
pero a través del índice se ven lógicamente ordenados. El índice (normalmente) es un archivo aparte
del archivo que contiene los datos, la manera más popular de construir y mantener un índice es a través
del algoritmo de arboles balanceados B-Tree. Los casos para este tipo de búsqueda son:
x Mejor Caso = 1
x Peor Caso = [logm(N)].
x Caso promedio = 1+[log2m(N)]
Dónde m indica el número de vías que tiene el árbol. La gran ventaja de un Índice es que el
algoritmo de mantenimiento es mucho más eficiente que el algoritmo para mantener un archivo
ordenado, y por otro lado es mucho más rápido dado que m es mayor que 2.
Los platos son organizados para permitir el almacenamiento y la lectura de los datos.
Cada plato se divide en varios miles de pistas, las cuales son pequeños círculos concéntricos.
Cada pista se divide a su vez en sectores. Un sector es normalmente la unidad de
direccionamiento de información más pequeña en un disco duro, y en la mayoría de
los
3ODWR
6HFWRU
%UD]R
&DEH]D
OHFWXUD
HVFULWXUD
%UD]R
&LOLQGUR 5RWDFLµQ
)LJXUD(VWUXFWXUDGHXQGLVFRGXUR
casos puede almacenar 512 bytes de información. Cada pista, normalmente tiene entre 100 y 300
sectores. Esto se ilustra en la figura 8.1
En los sistemas de archivos FAT (File Allocation Table) los sectores se agrupan en bloques más
grandes llamados clusters. el rango de tamaño de los cluster va de 4 sectores (2,048 bytes) a 64 sectores
(32,768 bytes).
El tiempo de acceso a datos está definido por el tiempo de búsqueda, el tiempo de movimiento de
la cabeza y el retardo rotacional. El tiempo de búsqueda es el tiempo que le toma a la cabeza
posicionarse sobre el cilindro deseado. Hasta que los datos sean leídos o escritos se tiene que incluir el
tiempo de movimiento de la cabeza para encontrar la pista deseada, además de el tiempo del retardo
rotacional para encontrar el sector deseado.
7LHPSR GH
WUDQVPLVLµQ 7LHPSRGH
E¼VTXHGD &DEH]DV
OHFWRUDV
HVFULWRUDV
7LHPSRGHODWHQFLD
)LJXUD7LHPSRGHE¼VTXHGDODWHQFLD\WUDQVIHUHQFLDGHXQGLVFRGXUR
El mayor de estos tres tiempos es el tiempo de búsqueda, este tiempo es del orden de 10
veces mayor que los tiempos de latencia y transmisión.
Los diferentes algoritmos de planificación del acceso a un disco se enfocan a optimizar el
tiempo de búsqueda de manera prioritaria y en segundo término de optimizar el tiempo de latencia.
En este algoritmo las peticiones de movimiento del brazo del disco son atendidas de acuerdo al
orden de llegada de las peticiones. Cuando existe un número grande de peticiones de desplazamiento
del brazo este algoritmo tiene un pobre desempeño, puesto que se mueve a la siguiente posición (de
acuerdo al orden de llegada) sin considerar la posición actual del brazo.
Bajo este algoritmo, la siguiente petición de movimiento del brazo es la que esté localizada más
cerca de la posición actual del brazo. En general este algoritmo tiene un buen desempeño, dado que
minimiza el total de movimiento del brazo maximizando el número de peticiones atendidas. El único
inconveniente es que bajo cargas de trabajo altas, las peticiones que estén localizadas en los extremos
del disco pueden ser postergadas un tiempo grande.
Este algoritmo es muy similar al SSTF, pero la siguiente petición a atender, es aquella que
minimice el tiempo de búsqueda en la dirección actual del movimiento del brazo. Cuando ya no existan
peticiones pendientes en la dirección actual del brazo se cambia la dirección de movimiento. El único
inconveniente es que peticiones nuevas en la dirección actual de movimiento del brazo serán atendidas
antes que peticiones anteriores que están en la dirección opuesta de la dirección actual de movimiento.
Las peticiones que son atendidas son las que ya existían al cambiar la dirección de movimiento
del brazo, las nuevas peticiones se atenderán hasta que se atiendan todas las peticiones que estaban al
cambiar la dirección de movimiento del brazo.
se atiende la petición más cercana en la dirección interna y se continua hasta que no existan peticiones
pendientes hacia adentro. Se reinicia en la petición más externa.
8.8. Referencias
Para ampliar los conocimientos sobre el manejo de archivos y discos se recomienda leer las
referencias:
[ 17], [25], [39], [14], [67], [68], [69].
Tanto el sistema operativo de red como el sistema operativo distribuido requieren para
su operación de una arquitectura de comunicaciones. La arquitectura de comunicaciones más
ampliamente usada actualmente es el protocolo TCP/IP.
126
Digitalización con propósito academico. Sistemas operativos
127 CAP.9. SISTEMAS OPERATIVOS DISTRIBUIDOS
x Correo Electrónico (SMTP ó Simple Mail Transfer Protocol), da el soporte para envió y
recepción de correo electrónico.
x Transferencia de Archivos (FTP File Transfer Protocol), permite el intercambio de archivos
entre diferentes computadoras.
x TELNET, permite el acceso remoto de computadoras.
1. Balanceo de cargas. De manera tal que se utilicen al máximo los elementos de procesamiento
que estén disponibles y el tiempo de terminación de programas sea minimizado. Este balanceo
de cargas debe tomar en cuenta los costos adicionales inherentes al proceso de comunicación
necesario.
2. Mejorar el desempeño del Sistema de Comunicaciones. Si dos procesos se comunican
intensamente y están localizados en computadoras diferentes, esto incrementa la carga por
comunicaciones, si se ubican los dos procesos en la misma computadora es posiblemente
mejorar el desempeño del sistema de comunicaciones.
3. Mejorar la disponibilidad. Si se dará mantenimiento a alguna computadora y está corriendo en
ella un proceso continuo, se podría migrar dicho proceso a otra computadora y garantizar la
continuidad en la ejecución de dicho proceso mientras se da mantenimiento.
4. Uso de Dispositivos Especiales. Un proceso que requiera dispositivos especiales que solo estén
disponible en una computadora de la red, podría migrar hacía dicho nodo y aprovechar
eficientemente dichos dispositivos.
La migración de procesos es una labor muy compleja dado que pueden existir diferentes
sistemas operativos y diferentes plataformas de hardware en un sistema distribuido. Esta situación ha
cambiado drásticamente con el resurgimiento del uso extensivo del concepto de máquina virtual que ha
promovido el lenguaje de programación JAVA. Usando el lenguaje JAVA es posible realizar la
migración de applets de JAVA entre máquinas independientemente de su Hardware y de su sistema
operativo.
9.5. Referencias
Unix
Los laboratorios BELL, la compañía General Electric y el proyecto MAC del Instituto Tecnológico de
Massachussets(MIT) se unieron en 1965 para desarrollar un nuevo sistema operativo llamado
MÜLTICS. La idea de este proyecto fue permitir el acceso simultáneo de diferentes usuarios a los
servicios de un sistema computacional- El proyecto dio como resultado una versión preliminar de
MULTICS pero los laboratorios BELL decidieron terminar su participación en el proyecto.
En los laboratorios BELL, Ken Thompson escribió una versión preliminar de un KERNEL para la
computadora GE-645, además Thompson diseñó un juego denominado "Space Travel" para la
Honeyweil 635 cuya ejecución era muy ineficiente, por este motivo decidió emigrar el programa a una
computadora PDP-7. En este momento se unieron Ken Thompson, Dennis Ritchie y Brian Kemighan
escribiendo un sistema de archivos, un manejador de procesos y ciertas utilerías básicas. El nombre de
este sistema fue UNICS jugando un poco con el nombre del sistema anterior MÜLTICS. En 1970 el
nombre fue cambiado a UNIX.
El mismo grupo de desarrollo emigró el sistema operativo de la computadora PDP-7 a una
computadora PDP-11 al mismo tiempo que desarrollaron un ambiente de procesamiento de textos para
el departamento de patentes de los laboratorios BELL. La primera versión del KERNEL de UNIX
ocupó solo 16K.
Ken Thompson al tratar de desarrollar un compilador para el lenguaje FORTRAN termino
desarrollando un lenguaje denominado B basado en otro lenguaje anterior llamado BCPL. El programa
del lenguaje B era lento de forma que Dennis Ritchie se dedico a mejorarlo y surgió el lenguaje C.
129
En 1973, el sistema operativo UNIX fue reescrito en C. Por cuestiones legales, los laboratorios BELL
no pudieron comercializar el sistema operativo UNIX motivo por el cuál se distribuyo libremente a
universidades y centros interesados.
De esta forma surgieron muchas variantes de UNIX, y fue hasta 1982 cuando los laboratorios BELL
conjuntaron dichas versiones en una sola denominada UNIX System III. AT&T anuncio tiempo
después el lanzamiento de UNIX System V. En la Universidad de California en Berkeley se hicieron
modificaciones y surgió la versión UNIX 4.3 BSD (Berkeley Software Distribution).
Microsoft pidió la licencia a AT&T y produjo XENIX una versión de UNIX para microcomputadoras.
Microsoft hizo equipo con una compañía denominada Santa Cruz Operation (SCO) surgiendo el SCO-
XENIX. En la actualidad hay muchas versiones de UNIX entre ellas la versión para computadoras IBM
se denomina AIX.
El KERNEL está escrito casi completamente en lenguaje C y una pequeña parte esta en código
ensamblador- El KERNEL permite planificar el procesador para múltiples usuarios, además realiza el
manejo del disco y permite comunicamos con los dispositivos de entrada salida.
Los procesos creados por el KERNEL tienen definidos una ENTRADA ESTÁNDAR, una SALIDA
ESTÁNDAR y un ERROR ESTÁNDAR según se ilustra en la figura A.1.
Error esándar 2
(pantalla)
x Directorios
x Archivos especiales
x Archivos ordinarios
Una característica fundamental de UNIX es que los DISPOSITIVOS son tratados como
ARCHIVOS motivo por el cuál el manejo de DISPOSITIVOS es relativamente fácil.
La estructura de archivos es jerárquica teniéndose directorios que contienen archivos y
directorios donde estos tienen archivos y directorios...
Los directorios que casi siempre están presentes en cualquier sistema UNIX se ilustran en la
figura A.2.
bin
A.1.6. El Shell
x C-Shell
x Kom-SheIl
x Boume-Shell
x C
x Fortran
x Pascal
x Cobol
x Ada
x PL/I
x C++
NOTA: Estos dos formateadores utilizan comandos punto para realizar todo el formateo.
Para entrar a UNIX se debe dar el nombre del usuario a la petición de Login:, después el sistema
preguntará la contraseña del usuario con la petición de Password:
Manipulación de contraseñas
Comando ls
Permite ver los archivos de algún directorio, se puede incluir un patrón utilizando los caracteres
comodines * (Cualquier número de caracteres) y ? (Cualquier carácter).
Junto con el comando ls se pueden incluir diversas opciones precediéndolas del signo –.
23&,21 '(6&5,3&,1
D /LVWDWRGRVORVDUFKLYRVLQFOX\HQGRORVHVFRQGLGRV
G /LVWDVRORORVGLUHFWRULRV
O 3URGXFHXQDOLVWDODUJD
U /LVWDDUFKLYRVHQRUGHQLQYHUVRDOIDE«WLFDPHQWH
W /LVWD ORV DUFKLYRV GH DFXHUGR D OD IHFKD GH PRGLILFDFLµQ ORV PRGLILFDGRV ORV PRGLILFDGRV
P£VUHFLHQWHPHQWHSULPHUR
) 0DUFDORVGLUHFWRULRVFRQXQDGLDJRQDOLQYHUWLGD\ORVDUFKLYRVHMHFXWDEOHVFRQXQ
5 /LVWDGLUHFWRULRV\DUFKLYRVUHFXUVLYDPHQWH
7DEOD$,2SFLRQHVGHOFRPDQGR,V
Comando cat
El comando cat permite desplegar el contenido de archivos.
Comando wc
Permite contar el número de líneas, palabras o caracteres de un archivo. Las opciones son
indicadas en la tabla A.2.
23&,21 '(6&5,3&,1
F Cuenta sólo caracteres.
O Cuenta sólo líneas.
Z Cuenta sólo palabras.
7DEOD$7DEODGH2SFLRQHVGHOFRPDQGRZF
Muestra en el caso de no especificar ninguna opción primero en el número de: Líneas, Palabras
y Caracteres.
El comando cal permite desplegar un calendario de un mes en particular o de todos los meses de un
año. El formato es:
cal año
cal mes año
Comando who
El comando who permite saber que usuarios están en el sistema y quien es uno (???). Los
formatos son:
who
who am I
Comando man
Permite obtener ayuda del manual en línea de UNIX, el formato comando es: man Ítem
Comando mail
Permite el enviar y recibir mensajes a/de otros usuarios. Para enviar un mensaje a uno o varios usuarios
el formato es:
mail usuario1 usuario2 ...
&20$1'2 '(6&5,3&21
" 'HVSOLHJDODVRSFLRQHVGHOPDLO
Q¼PHUR $YDQ]DHOQ¼PHURGHPHQVDMHVLQGLFDGRV
G %RUUDPHQVDMHV
G
%RUUDWRGRVORVPHQVDMHV
KXVXDULRV %XVFDPHQVDMHVGHOXVXDULRLQGLFDGR
0XVXDULR 3HUPLWHSDVDUDOXOWLPRPHQVDMHGHVSOHJDGRDOXVXDULRLQGLFDGR
Q¼PHUR 5HWURFHGHHOQ¼PHURGHPHQVDMHLQGLFDGR
SQ¼PHUR 'HVSOLHJDHOQ¼PHURGHPHQVDMHLQGLFDGR
T 6DOH\GHMDPHQVDMHVHQFROD
UWH[WR&WUO' 3HUPLWHFRQWHVWDUGLUHFWDPHQWHDOWUDQVPLVRUGHOPHQVDMHDFWXDOPHQWHGHVSOHJDGR
6 $JUHJDXQDUFKLYRHOPHQVDMH
7RS 'HVSOLHJDODVSULPHUDVFLQFRO¯QHDVGHXQPHQVDMH
7RSQ¼PHURQXPHUR 'HVSOLHJDODVSULPHUDVFLQFRO¯QHDVGHORVPHQVDMHLQGLFDGRVHQOHUDQJRGDGR
XQ¼PHUR 5HFXSHUDHOPHQVDMHFX\RQ¼PHURVHLQGLFDTXHKDE¯DVLGRERUUDGR
[ 6DOHVLQDFWXDOL]DUFRODGHPHQVDMH
7DEOD$7DEODGH2SFLRQHVGHOFRPDQGRPDLO
x Su nombre.
x Su contenido.
x Información adicional de control e identificación.
x ORDINARIOS Que son archivos que no tienen un formato interno particular, v.gr. texto ó
código.
x DIRECTORIO Es una tabla de los contenidos de una colección de archivos relacionados,
contiene un nombre y un número de inodo (que es donde está almacenada la información).
x ESPECIALES Representan dispositivos lógicos ó físicos. Se encuentra en el directorio: /dev
&RPDQGR 'HVFULSFLµQ
FGWUD\HFWRULD 6HFDPELDODWUD\HFWRULDLQGLFDGD
FG 6HFDPELDDOGLUHFWRULRUD¯]
FG 6HFDPELDDOSDSDGHOQLYHODFWXDO
FG 6HFDPELDDOGLUHFWRULRGHHQWUDGDGHILQLGRFRPRKRPH
PNGLUGLUHF 3HUPLWHFUHDUHOGLUHFWRULRLQGLFDGR
SZG 'HVSOLHJDHOGLUHFWRULRDFWXDO
PYGLUOGLU &DPELDHOQRPEUHGHOGLUHFWRULRGLUODGLU
UPGLUGLUHF %RUUDHOGLUHFWRULRLQGLFDGR
7DEOD$ 7DEODGHFRPDQGRVSDUDPDQHMRGHGLUHFWRULRV
UNIX maneja los permisos de acceso a los archivos y directorios clasificando a los usuarios de
la siguiente forma:
x u Se refiere al propietario.
x g Se refiere al grupo.
x Se refiere a los otros(todos los demás).
x r De lectura
x w De escritura
x x De ejecución
De este modo surgen 9 bits (el comando Is -1 muestra 10 bits donde el primero indica el tipo de
archivo y los otros 9 indican los permisos a los que nos referimos) que definen los permisos de cada
archivo y directorio respecto a propietario, grupo y todos.
x Los DIRECTORIOS requieren el permiso de ejecución x para poder accesar los archivos y
directorios que pertenecen a ellos.
x Para que sea efectivo el permiso de escritura w se requiere que DIRECTORIO en cuestión
tenga el permiso de ejecución x.
El comando que permite modificar estos nueve bits de permisos es el comando chmod cuyas
opciones se ilustran en la tabla A.5.
&20$1'2 '(6&5,3&,1
FKPRG>TXLHQ@SHUPLVRDUFK 3HUPLWHDJUHJDUTXLWDUHOSHUPLVRLQGLFDGRVREUHORVDUFKLYRV
FKPRG>TXLHQ@SHUPLVRDUFK UHVSHFWRDORVXVXDULRVLQGLFDGRV
TXLHQSXHGHVHU
J 7RGRVORVXVXDULRVGHOPLVPRJUXSRTXHHOSURSLHWDULR
R 7RGRVORVXVXDULRV
X 3URSLHWDULR
SHUPLVRSXHGHVHU
[ (MHFXWDEOHSDUDGLUHFWRULRVVHUHILHUHDE¼VTXHGD
U OHFWXUD
Z HVFULWXUD
TXL«Q \ ORV SHUPLVRV VH SXHGHQ HVSHFLILFDU XVDQGR XQ
Q¼PHURHQRFWDOFRPRHQHOFRPDQGR
FKPRGDUFKLYR
TXHGDU£DFFHVRLUUHVWULFWRDODUFKLYRO
7DEOD$7DEODGHFRPDQGRFKPRG.
$5&+,92 '(6&5,3&,1
DUFKF &µGLJRIXHQWHGH&
DUFKK $UFKLYRLQFOXGHGHHQFDEH]DGRSDUD&
DUFKI &µGLJRIXHQWHGH)2575$1
DUFKS &µGLJRIXHQWHGH3$6&$/
DUFKV &µGLJRIXHQWHGH(16$0%/$'25
DUFKR &µGLJRREMHWR
. 'LUHFWRULRDFWXDO
.. 'LUHFWRULRSDGUH
7DEOD$&RQYHQFLRQHVGH1RPEUHGH$UFKLYRV.
Para especificar los nombres de archivos se tienen definidas convenciones, algunas de las cuales
se ilustran en la tabla A.6.
&20$1'2 '(6&5,3&,1
,V /LVWDDUFKLYRV
FDW 3HUPLWHYHUDUFKLYRVRORVSXHGHFUHDUWDPEL«Q
FS 3HUPLWHFRSLDUDUFKLYRV
PY 3HUPLWHFDPELDUHOQRPEUHDXQDUFKLYR
3J 9HUDUFKLYRVS£JLQDDS£JLQD
PRUH 9HUDUFKLYRVS£JLQDDS£JLQD
UP 3HUPLWHERUUDUDUFKLYRV
WRXFK 6LHODUFKLYRLQGLFDGRQRH[LVWHFUHDXQRGHORQJLWXGFHUR6L\DH[LVWHDFWXDOL]DOD
IHFKDGHOD¼OWLPDDFWXDOL]DFLµQFRQODIHFKDDFWXDO
FVSOLW 6HSDUDUXQDUFKLYRHQEDVHDORVDUJXPHQWRVGDGRV
,Q /LJDGRVQRPEUHVDXQDUFKLYR
6SOLW 6HSDUDXQDUFKLYRHQSHGD]RVGHQO¯QHDV
PYDUFKODUFK 3HUPLWHFDPELDUHOQRPEUHGHODUFKOSRUDUFK
7
7DEOD$&RPDQGRVSDUD0DQHMRGH$UFKLYRV
7DEOD$&RPDQGRVSDUD0DQHMRGHJUXSRV\SURSLHWDULRV
A.3. Procesos
Definición de Proceso
Un proceso es una tarea que se lleva a cabo dentro del sistema operativo UNIX.
Es un programa que se está ejecutando.
Es la forma de controlar a los múltiples usuarios para compartir los recursos del sistema.
Los procesos son el medio a través del cual un usuario invoca al shell para que este invoque al
kernel y se realice la operación indicada.
Cuando el usuario que entro al sistema ejecuta el comando cat MIÓ, se crea otro proceso con
las siguientes características:
x Identíficador de USUARIO- El identificador del usuario que entro al sistema. Esto es heredado.
x Directorio.- El directorio base(HOME) asignado al usuario. Esto es heredado.
x Programa.- El programa cat.
x Identífícador del PROCESO.- El número asignado a este nuevo proceso.
x Proceso Padre,- sh (el del proceso anterior)
x Identificador del PADRE— El asignado al proceso anterior.
x Archivos Abiertos- La terminal asignada (stdin, stdout y stderr) HEREDADA y el archivo
MIÓ.
La creación del proceso que ejecuta el comando cat se realiza a través de la operación llamada
SPAWNING (un pez desovando), esto en forma detallada involucra lo siguiente:
x El ambiente del proceso del shell(sh) es duplicado formando un proceso padre y un proceso hijo
a través de la llamada de sistema fork.
x La llamada de sistema fork regresa el valor del identificador del proceso hijo al proceso padre y
regrese el valor de cero al proceso hijo.
x El padre entra en un estado de espera a través de la llamada de sistema: wait
x El programa cat es cargado en el ambiente heredado del hijo a través de la ejecución del
llamado de sistema: exec
x El hijo solo altera su ambiente abriendo el archivo MIÓ a través de la llamada de sistema: open
x El hijo termina, señalizando al padre a través de la llamada de sistema: exit
x El padre despierta y reinicia ejecución (el shell).
Si el comando ejecutado no es cat MIÓ sino sh el efecto que se tiene es crear otra instancia del
shell(otro proceso) que a su vez podrá crear otra instancia(proceso) al ejecutar otro comando...
Listar Procesos
El comando que permite ver la información de los procesos es: ps. SÍ se desea ver toda la
información se debe usar la opción f: ps -f que muestra para cada proceso la información indicada en la
tabla A.9.
&2/801$ '(6&5,3&,1
8,' (OLGHQWLILFDGRUGHOXVXDULRSURSLHWDULRGHOSURFHVR
3,' (OLGHQWLILFDGRUGHOSURFHVR
33,' (OLGHQWLILFDGRUGHOSURFHVRSDGUH
35, 3ULRULGDGGHOSURFHVR(QWUHP£VDOWRHVHOQ¼PHURPHQRUHVODSULRULGDG
1, 9DORU1LFH8VDGRHQHOF£OFXORGHODSULRULGDG
77< /DHVWDFLµQGHWUDEDMRGHFRQWUROGHOSURFHVR
&0' (OQRPEUHGHOFRPDQGR
UPGLUGLUHF %RUUDHOGLUHFWRULRLQGLFDGR
7
7DEOD$,QIRUPDFLµQGHOFRPDQGRSV
23&,1 '(6&5,3&,1
H 'HVSOLHJDWRGRVORVSURFHVRVH[FHSWRORVGH.(51(/
I /LVWDGRFRPSOHWR
N 'HVSOLHJDLQIRUPDFLµQGHORVSURFHVRVGH.(51(/
O *HQHUDXQOLVWDGRODUJR
3 SOLVWD'HVSOLHJDLQIRUPDFLµQVµORGHORVQ¼PHURVGHSURFHVRVHVSHFLILFDGRVHQSOLVWD
XOLVWD 'HVSOLHJDLQIRUPDFLµQVµORGHORVSURFHVRVGHORVXVXDULRVHQXOLVWD
7
7DEOD$2SFLRQHVGHOFRPDQGRSV
Las opciones más utilizadas del comando ps son ilustradas en la tabla A. 10.
Unix tiene la capacidad de poder correr un proceso en segundo plano (al fondo) y seguir
trabajando sin tener que esperar a que termine cierto comando.
La forma de realizarlo es por demás simple, solo basta con que se termine el comando con el
carácter ampersand & y listo.
Sino se termina un comando con & estará corriendo en primer plano(frente) y el control se
regresará hasta que termine.
SÍ se desea dejar corriendo un proceso después de salir del sistema se debe usar el comando: nohup.
v.gr.:
nohup sort archivo&
x
logout
A.4. El Shell
A.4.1. Descripición del Shell
A.4.3. Redirección
La redirección de ]a entrada se lleva a cabo a través del signo de < v.gr. more < arch La redirección de
]a salida se realiza con el signo de > o ^> donde el primero manda la salida al lugar indicado y si existe
el archivo lo borra mientras el segundo lo agrega al final.
v.g.
cat > arch
cat >> arch
La redirección del error estándar se realiza a través del signo de > o ^> pero precediéndolo de un 2
v.g. cat arch 2 > archerror
Sino se desea ver el error, ni guardarlo se puede usar:
cat arch 2 > /dev/null
Existen diversas combinaciones del uso de los operadores de redirección que pueden ser útiles:
comando < archentrada > archsalida 2 > archerror
comando >> archsalida 2 >> archerror < archentrada
comando > archsalida 2 > & 1
Este último ejemplo manda el error al archivo definido como salida previamente. En general se puede
hacer referencia a los archivos de entrada, salida y error ya definidos usando la notación:
&0 Archivo Salida Definido.
&1 Archivo Entrada Definido.
&2 Archivo Error Definido.
v.g.
ls|sort
En algunas ocasiones se desea que la salida de algún comando vaya a dos lugares (en lugar de
un tubo requerimos una T), para esto se utiliza el comando tee
v.g.
Is l tee archl l sort
En este caso la salida del comando Is se manda al archi y al mismo tiempo se manda al comando
sort.El KORN SHELL y el BOURNE SHELL permiten la creación de PIPES con nombre, para realizar
esto se utiliza el comando /etc/mknod dando un nombre y el nombre dado sera el pipe con nombre, v.g.
/etc/mknod BITACORA p
# log < BITACORA
while TRUE
do
read line
echo ‘date +'%H%M%S't #line » /usr/ejemplo/archbita
done < BITACORA
nohup nice log&
A.4.6. Metacaracteres
El carácter ? representa cualquier carácter: v.gr. Is ro? indicará todos los archivos que tengan
como primer letra r, como segunda letra o y como tercer letra cualquier carácter.
El carácter * representa cualquier número de caracteres. Uno de los comandos favoritos a las 2
de la mañana es: rm *
Es posible también especificar una lista de posibles valores v.gr.:
Is [cd]i[lf]
Indica los archivos cuyo nombre empieza con c o d le sigue una i y teminan con 1 ó f
Is [A-Z]r
Indica los archivos cuyo nombre tiene dos letras; la primera es una letra mayúscula y la segunda
la letra r
Is *[ibc]
Indica los archivos cuyo nombre no termina con b o c
Para expander una variable del SHELL dentro de un string se encierra el nombre de la variable entre
llaves({ }) y se precede con el signo de $.
v.g.
prefijo = "re"
echo es $prefijotomado el mundo despliega: es el mundo
puesto que la variable prefijotomado no está definida. echo es ${prefijo}tomado el mundo
despliega: es retomado el mundo
Para desplegar las variables del SHELL que están definidas se usa el comando set
Algunas de las variables del shell que normalmente están definidas se indican en la tabla A.
11.
9$5,$%/( '(6&5,3&,1
/2*1$0( (OQRPEUHFRQHOTXHVHKL]RHOORJLQ
+20( (OQRPEUHGHOGLUHFWRULRFRQHOTXHVHGLRORJLQ
3$7+ 8QDOLVWDRUGHQDGDGHQRPEUHVGHWUD\HFWRULDGHGLUHFWRULRVVHSDUDGRVSRU(OVKHOO
EXVFDHQHORUGHQHVSHFLILFDGRGHQWURGHO3$7+ORVFRPDQGRVTXHVHGHVHDQ
HMHFXWDU
36, (OSURPSWSULPDULRGHVLVWHPD
36 (OSURPSWVHFXQGDULRGHOVLVWHPD
,)6 (OSURPSWVHFXQGDULRGHOVLVWHPD
7DEOD$$OJXQDVYDULDEOHVGHO6KHOO
A.4.8. Exportando variables
Las variables que se definen solo son validas dentro del proceso que realiza la definición, si se desea
que dichas variables sean visibles dentro de los procesos hijos(nietos, biznietos,...) es necesario usar el
comando export nombre-variable.
Para verificar las variables que han sido exportadas se usa el comando export sin parámetros.
Es importante destacar que las variables de un proceso hijo nunca serán vistas desde el proceso padre.
Para desplegar las variables definidas a nivel local se usa el comando set.
Para desplegar las variables que han sido heredadas se usa el comando env.
Para almacenar en una variable un comando para ser ejecutado posteriormente es necesario delimitar el
comando entre comillas invertidas (no confundir con las comillas sencillas), v.gr.;
ahora='date'
echo $ahora
Desplegará la fecha actual
Bourne Shell
Es un shell ampliamente usado desarrollado en 1975 por S.R. Boume en los laboratorios BELL,
el nombre viene del apellido de su desarrollador. La forma de localizarlo es en:/bin/bsh se invoca con
bsh y su indicador (prompt) es $.
Soporta el manejo de excepciones a través del comando trap, soporta el concepto de
pipes con nombre (named pipes), soporta variables locales y globales (se exportan con el
comando (export), soporta las estructuras de control if-then-else, case, for, while y until a
diferencia de C SHELL y KORN SHELL usa las utilerías test y expr para realizar la
evaluación de expresiones condicionales.
C Shell
Korn Shell
Este shell fue desarrollado por David Kom en AT&T, es resultado de tomar características de los dos
anteriores y agregar algunas nuevas. Este shell es el que se usa en AIX por omisión. Se localiza en:
/bin/ksh se invoca con: ksh y el indicador (prompt) es $
Incorpora lo mejor del C SHELL y del BOURNE SHELL, es un poco más rápido que el C SHELL
pero más lento que el BOURNE SHELL, adicionalmente a las construcciones del C SHELL soporta el
select similar al case para elegir las opciones de un menú.
Una de las características más importantes del ksh es el poder definir alias para los comandos usando el
comando alias.
v.g.
alias dir=“ls –1”
De este modo al dar dir se ejecutará el comando Is –1
Otra característica propia del ksh es el poder exportar todas las definiciones de variables y de alias
utilizando la variable ENV. Suponiendo que las definiciones de las variables y aliases están definidas
en el archivo varal del directorio del usuario basta con hacer lo siguiente:
ENV=$HOME/viral
export ENV
Dentro del ksh se pueden editar los comandos anteriores haciendo lo siguiente:
set -o vi
Después para editar los comandos anteriores se debe hacer con la secuencia siguiente:
ESC Entra en modo edición.
k Comando Previo
j Comando Siguiente
Este shell es idéntico al shell Boume escepto que no se pueden realizar algunos comandos como:
cambiarse de directorio (cd)
utilizar redirección (<, >, >>)
especificar los nombres de comandos empezando con diagonal (/)
definir el valor de la trayectoria de búsqueda de comandos a través de la variable (PATH)
Este shell se localiza en el directorio /bin/Rsh, para invocarlo se hace con: Rsh y el indicador (prompt)
es $
Este shell proporciona un ambiente privilegiado desde el cuál se pueden realizar operaciones
administrativas del sistema. Permite la ejecución de comandos catalogados como privilegiados
(trusted).
Este shell se localiza en /bin/tsh la forma de invocarlo es con Ctrl-X Ctrl-R, el indicador
(prompt) es tsh >
Para entraba este shell se debe estar como superusuario(su) o como raíz(root).
&20$1'2 '(6&5,3&,1
DZN /HQJXDMHGHE¼VTXHGD\SURFHVDPLHQWRGHVWULQJV
FXW 3HUPLWHVHOHFFLRQDUFROXPQDVGHXQDUFKLYR
GLII &RPSDUDGRVDUFKLYRV\VHOHFFLRQDODVGLIHUHQFLDV
JUHS 6HOHFFLRQDORVUHQJORQHVTXHFXPSOHQHOFULWHULRGDGRVµORXQFULWHULR
(JUHSH[WHQGHGJUHS 6HOHFFLRQDLRVUHQJORQHVTXHFXPSOHQORVP¼OWLSOHVFULWHULRVGDGRV
)JUHSIDVWJUHS 6HOHFFLRQDORVUHQJORQHVTXHFXPSOHQORVP¼OWLSOHVFULWHULRVGDGRV
KHDG 6HOHFFLRQDORVSULPHURVUHQJORQHVGHORVDUFKLYRV
OLQH 6HOHFFLRQDHOSULPHUUHQJOµQGHORVDUFKLYRV
VHG 3HUPLWHHGLWDUORVIOXMRVGHGDWRV
WDLO 3HUPLWHVHOHFFLRQDUODV¼OWLPDVO¯QHDVGHORVDUFKLYRV
XQLT 6HOHFFLRQDUHQJORQHVHOLPLQDQGRUHSHWLFLµQ6µORVLVREUHORTXHVHRSHUDHVW£RUGHQDGR
ZF &XHQWDFDUDFWHUHVSDODEUDV\O¯QHDVGHXQDUFKLYR
7DEOD$&RPDQGRVGHVHOHFFLµQ.
A.5 Editores
Dentro del ambiente unix se tienen disponibles diversos editores y herramientas para
manipulación de strings según se indica en la tabla D.6.
(',725 '(6&5,3&,1
Ed (VXQHGLWRUGHO¯QHDTXHVµOR SHUPLWHWUDEDMDUFRQXQDUFKLYRDXQWLHPSR
Red 9HUVLµQUHVWULQJLGDGHOHGLWRUHGSDUDXVDUVHFRQHO6+(//5(67,&7('
([ (GLWRUGHO¯QHDVLPLODUDOHGSHURSXHGHHGLWDUP¼OWLSOHVDUFKLYRVDXQWLHPSR
(GLO 9HUVLµQSDUDSULQFLSLDQWHVGHH[
Vi (GLWRUGHSDQWDOODFRPSOHWDVHSXHGHQHMHFXWDUODPD\RU¯DGHORVFRPDQGRVGHH[
9LHZ 9HUVLµQSDUDVµOROHFWXUDGHOYL
9HGLW 9HUVLµQSDUDSULQFLSLDQWHVGHOYL
7YL 9HUVLµQSULYLOHJLDGDGHOYLSDUDXVRVGHDGPLQLVWUDFLµQGHOVLVWHPD
JUHSHJUHSIJUHS +HUUDPLHQWDVSDUDE¼VTXHGDGHSDWURQHVGHQWURGHORVDUFKLYRVHJUHS\IJUHSVRQ
GRVYDULDQWHVGHOJUHSTXHVRQXQSRFRP£VHILFLHQWHV
6HG (GLWRUGHIOX-RV6WUHDPVSDUDDUFKLYRV
DZN (GLWRUGHIOXMRV6WUHDPVSDUDDUFKLYRV
7DEOD$(GLWRUHVHQ81,;.
Grep
El comando grep (Globally look for a Regular Expression and Print) permite encontrar cada
ocurrencia de una palabra o frase en algún archivo de UNIX.Las opciones de este comando se ilustran
en la tabla A. 14.
Sed
El comando sed (Stream EDitor) permite realizar edición de archivos, v.g. sed archivo.
Digitalización con propósito academico. Sistemas operativos
150 $31',&($81,;
23&,1 '(6&5,3&,1
F 0XHVWUDODFXHQWDGHODVO¯QHDVHQODVTXHKXERDSDUHDPLHQWR
L ,JQRUDPD\¼VFXODVPLQ¼VFXODVGXUDQWHODFRPSDUDFLµQ
O 0XHVWUDVµORORVQRPEUHVGHDUFKLYRVHQORVTXHKD\DSDUHDPLHQWR
Q 3UHFHGHFDGDO¯QHDHQODTXHKD\DSDUHDPLHQRFRQHQ¼PHURGHO¯QHDGHODUFKLYR
V 6XSULPHPHQVDMHVGHHUURU
9 'HVSOLHJDODVO¯QHDVHQODVTXHQRKD\DSDUHDPLHQWR
; 'HVSOLHJDVµORDSDUHDPLHQWRVH[DFWRVVµORFRQIJUHS
\ ,JQRUDPD\¼VFXODVPLQ¼VFXODV
7DEOD$2SFLRQHVGHOFRPDQGRJUHS
A.5.2. El Editor vi
Es un editor de pantalla completa, de muy amplio uso en las instalaciones UNIX. Permite
la creación y modificación de archivos texto, no tiene capacidades de formateo. Trabaja
siempre sobre una copia del archivo en un buffer de edición. Tiene básicamente dos modos de
operación:
x Modo Comando.- En el cuál todos los teclazos son interpretados como comandos. Este es el
modo con el que se entra al vi.
x Modo Edición.- En este modo todos los comandos se interpretan como texto. Para regresar al
modo comando se presiona ESC.
Tiene como característica sobresaliente el poder realizar búsqueda y reemplazo de texto pudiendo
utilizar la característica de apareamiento de patrones.
Movimiento en el Documento
Algunas teclas que se pueden usar en el modo comando para moverse en el archivo se indican
en la tabla A.15.
TECLAS MOVIMIENTO
TECLAS 029,0,(172
Kµ)OHFKDL]TXLHUGD 8QFDU£FWHUDODL]TXLHUGD
Mµ)OHFKD$EDMR 8QDO¯QHDKDGDDEDMR
Mµ)OHFKD$EDMR 8QDO¯QHDKDGDDUULED
µ)OHFKD'HUHFKD 8QFDU£FWHUDODGHUHFKD
&WUO)µ$Y3£J 8QDSDQWDOODKDGDDGHODQWH
&WUO%µ5H3£J 8QDSDQWDOODKDFLDDWU£V
&WUO' 0HGLDSDQWDOODKDFLDDEDMR
&WUO8 0HGLDSDQWDOODKDGDDUULED
6HPXHYHDODO¯QHD
6HPXHYHDOI¯QDOGHODUFKLYR
6HPXHYHDOILQDOGHOUHQJOµQ
Z 6HPXHYHXQDSDODEUDKDFLDDGHODQWH
7DEOD$&RPDQGRVGHPRYLPLHQWRHQYL
Búsqueda y Reemplazo
Para deshacer la operación anterior basta con presionar; u Para repetir el último comando
realizado se presiona:
Personalización del vi
Para ver la definición actual de las variables del editor se ejecuta: :set all
Para personalizar los valores por omisión se debe crear un archivo $HOME/.exrc que contenga
los comandos de definición del vi v.g.:
set directory=/u/juan/tmp
Permite definir el directorio donde se almacena el buffer de edición temporal. Si el
sistema se cae y se desea recuperar el archivo que se estaba editando se debe hacer: vi -r
archivo
23&,1 '(6&5,3&,1
W\SHI 6HDSOLFDDDUFKLYRVRUGLQDULRV
W\SHG 6HDSOLFDDGLUHFWRULRV
VL]HQ 6µORORVDUFKLYRVP£VJUDQGHVTXHQEORTXHV
VL]HQ 6µORORVDUFKLYRVPHQRUHVTXHQEORTXHV
PWLPH[ 6µORORVDUFKLYRVPRGLILFDGRVKDFHP£VGH[G¯DV
PWLPH[ 6µORORVDUFKLYRVPRGLILFDGRVKDFHPHQRVGH[G¯DV
³DPHSDWUµQ 6µORORVQRPEUHVTXHDSDUHFHQFRQHOSDWUµQLQGLFDGR
SHUPQXPHURRFWDO 6µORORVDUFKLYRVTXHDSDUHFHQFRQORVSHUPLVRVLQGLFDGRVSRUHOQ¼PHURRFWDOGDGR
XVHUXVXDULR 6µORSDUDORVDUFKLYRVGHOXVXDULRLQGLFDGR
7DEOD$2SFLRQHVGHOFRPDQGRILQG
&$5&7(5 6,*1,),&$'2
A 3ULQFLSLRGHOLQHD
)LQGHO¯QHD
. 8QVµORFDU£FWHU
.* 0¼OWLSOHVFDUDFWHUHV
D &XDOTXLHUFDU£FWHUHVSHFLILFDGR
[-] &XDOTXLHUFDU£FWHUGHOUDQJR 7DEOD$&DUDFWHUHVGHOFRPDQGR
JUHS
v.g.
cut -f2 -d: archivos
cut -fl,3 -d; archivos
Permite desplegar las diferencias entre dos archivos. Las líneas que son diferentes. La sintaxis
es: diff opciones arch1 arch2 las líneas de arch1que necesitan cambiarse se preceden con un signo < las
líneas de arch2 que necesitan cambiarse se preceden con un
signo >
La opción -b para tomar múltiples espacios como uno solo.
La opción -e despliega solo lo que necesita cambiarse en arch2 para que sea igual a arch1.
Además de desplegar las líneas diferentes en los archivos indica la acción que debe seguirse
para que sean iguales las líneas de los dos archivos, esta acción se indica con el formato: num1 acción
num2 donde num1 indica el número de línea del arch1, num2 indica el número de línea del arch2 y la
acción puede ser a(agregar) ó d(borrar) ó c(cambiar).
A.7 AIXwindows
Este concepto permite trabajar con multitasking de una forma gráfica y fácil de usar. De este
modo es posible tener un mejor control de los procesos que están corriendo.
Para crear una nueva terminal virtual basta hacer: open sh y para eliminarla presionar:
Ctrl-D para cambiar de terminal virtual basta hacer Alt+ActÍon(siguiente) ó Shift+Action (anterior).
AIXwindos es un sistema de manejo de ventanas que es superior al concepto de terminal virtual debido
a que se puede estar viendo directamente la evolución de múltiples procesos.
AIXwindows ofrece:
Xwindows trabaja con un modelo CLIENTE -SERVIDOR. Las diversas aplicaciones son
clientes y existe un DISPLAY SERVER (Servidor de Despliegue) que recibe las peticiones de
los clientes y las presenta en la pantalla (Hardware). Dentro de los clientes tenemos
aixterm, xclock, mwm.
El mwm (Motif Window Manager) es un cliente XI 1 que permite ser configurado por el
usuario y soporta el uso del teclado y del ratón.
Para iniciar el servidor se realiza a través del comando xinit (además corre los clientes xclock y
aixterm).
x aixterm es el emulador de terminal.
x xclock es un cliente que despliega un reloj.
x Área de Borde.- Localizado alrededor de la ventana. Usando el ratón en esta área es posible
redimensionar la ventana.
x Área de Título.- Localizado dentro de la ventana en la parte superior. Usando el ratón en esta
área es posible mover la ventana.
x Botón de Menú de Ventana.- Localizado en la esquina superior izquierda dentro de la ventana.
Desde este menú es posible mover, redimensionar, maximizar, minimizar y cerrarla ventana.
x Botón Minimizar.- Localizado a un lado del botón de Maximizar. Permite poner la ventana
como un icono.
x Botón Maximizar.- Localizado en la esquina superior derecha. Permite poner al máximo el
tamaño de la ventana.
x Área de Menú y de cliente.- Localizada dentro de la ventana. Es dependiente de la aplicación
cliente que se esté corriendo.
Algunas de las combinaciones de tecla que son útiles son ilustradas en la tabla A. 18.
T '(6&5,3&,1
$OW(VF +DFHODVLJXLHQWHYHQWDQDODYHQWDQDDFWLYD
6KLIW(VF $FWLYDHOPHQGHODYHQWDQD
DL[WHUP ,QLFLDXQQXHYRGLHQWHDL[WHUP
[FORFN ,QLFLDXQQXHYRFOLHQWH[FORFN
7DEOD$&RPDQGRVHQ;:LQGRZV
aixterm
Parámetros de configuración
Para ver las opciones de cualquier cliente basta con usar el nombre del cliente con las opciones:
-help ó -keywords. Los tipos de letras y colores que se pueden usar están en los directorios
/usr/lpp/fonts y /usr/lib/Xl Í/rgb.
UNIX usa una instalación de proceso simple pero poderosa que es muy visible para el usuario.
Todos los procesos en el sistema, excepto dos procesos básicos, los crean comandos del programa de
usuario.
El sistema operativo UNIX reconoce un total de nueve estados de proceso; estos están listados
en la tabla A-19.
El diagrama que describe esto es dado en la figura A.3.
Dentro de las características importantes tenemos:
o UNIX emplea dos estados Corriendo para indicar si el proceso se ejecuta en modo usuario o
en modo kerneL
o Se hace una distinción entre los dos estados: Listo para correr, en memoriay Adquisición
por Prioridad. En esencia, estos son el mismo estado, como lo indica la línea punteada que los
(67$'2 '(6&5,3&,1
8VXDULRFRUULHQGR (MHFXFLµQHQPRGRXVXDULR
.HUQHOFRUULHQGR (MHFXFLµQHQPRGRNHUQH/
/LVWRSDUDFRUUHUHQPHPRULD /LVWRSDUDFRUUHUWDQSURQWRFRPRHODVLJQDGRUGHO&38OHDVLJQHHO
'XUPLHQGRHQPHPRULD 1RVHHMHFXWDSRUHVWDUHVSHUDQGRDTXHRFXUUDXQHYHQWR(O
SURFHVRHVW£HQPHPRULD
/LVWRSDUDFRUUHUHQGLVFR (OSURFHVRHVWOLVWRSDUDFRUUHUSHURHOLQWHUFDPELDGRUVZDSSHU
WLHQHTXHWUDHUORSULPHURDPHPRULD
'XUPLHQGRHQGLVFR (OSURFHVRHVW£HVSHUDQGRODRFXUUHQFLDGHXQHYHQWR\
DGHP£VHVWDHQGLVFR
$GTXLVLFLµQSRUSULRULGDG (OSURFHVRHVW£OLVWRSDUDUHJUHVDUGHOPRGR.HUQHODOPRGRXVXDULR
SHURVHOHTXLWRHO&38SRUSULRULGDGSDUDSODQLILFDUDRWURSURFHVR
&UHDGR (OSURFHVRHVW£UHFLHQFUHDGR\QRHVW£OLVWRSDUDFRUUHU
=RPELH (SURFHVRWHUPLQRSHURGHMDLQIRUPDFLµQTXHSXHGHVHUFRQVXOWDGD
SRUHOSURFHVRSDGUH
7DEOD$(VWDGRVGHSURFHVRVHQ81;.
Llamada a sistema
interrupción
Adquisición
por prioridad Regreso
a modo
usuario
Replanificación
Adquisición por prioridad
de proceso
Sleep
Suficiente memoria
Despertar Listo para correr en
Duración en i
Regreso a
memoria Cread
Sale de disco
Sale de disco
)LJXUD$'LDJUDPDGH(VWDGRVGH3URFHVRVHQ81,;
une. La distinción se hace para enfatizar la manera en que se entra al estado de Adquisición
por prioridad. Cuando un proceso corre en el modo kernel (como resultado de una llamada de
supervisor, interrupción de reloj, o interrupción de E/S), llegará un momento en que el kernel
complete su trabajo y esté preparado para regresar el control al programa de usuario. En este
punto, el kernel puede decidir darle preferencia a un proceso que esté listo y es de mayor
prioridad el actual. En ese caso, el proceso en curso se mueve al estado de Adquisición
por Prioridad.
La adquisición por prioridad puede ocurrir sólo cuando un proceso esta por moverse del modo
kernel al modo usuario. Mientras un proceso corre en el modo kernel, no puede ser desplazado. Esto
hace que UNIX no sea adecuado para procesamiento en tiempo real.
Procesos de sistema
Dos procesos son únicos en UNIX. El proceso O es un proceso especial que se crea cuando el
sistema es arrancado, este proceso es el intercambiador (swapper). Además el proceso O produce el
proceso 1, llamado init. Los demás procesos del sistema tienen al proceso 1 como ancestro. Cuando un
usuario interactivo nuevo se registra en el sistema, el proceso 1 le crea un proceso de usuario. Después,
el programa de usuario puede crear procesos hijos usando fork, cualquier aplicación puede estar
formada por varios procesos.
7DEOD$,P£JHQHVGHXQSURFHVR
ITEM '(6&5,3&,1
(VWDGRGHOSURFHVR 'HILQHHHVWDGR DFWXDOGHOSURFHVR
$SXQWDGRUHV $O£UHDGHXVXDULR\ODPHPRULDGHOXVXDULRWH[WRGDWRVVWDFN
7DPD³RGHOSURFHVR 3HUPLWHGHILQLUHOHVSDFLRTXHVHGHEHDVLJQDUDOSURFHVR
LGHQWLILFDGRUGHOXVXDULR (OLGHQWLILFDGRUGHOXVXDULRTXHFUHµHOSURFHVR
,GHQWLILFDGRUHVGHSURFHVR &RQWLHQHHOLGHQWLILFDGRUGHOSURFHVRSDGUH\GHOPLVPRSURFHVR
'HVFULSWRUGHOHYHQWR 7LHQHLPSRUWDQFLDFXDQGRHOSURFHVRHVW£GXUPLHQGRHVSHUDQGRXQHYHQWRFXDQGRHO
HYHQWRRFXUUHHSURFHVRHVWUDQVIHULGRDOHVWDGROLVWRSDUDFRUUHQ
3ULRULGDG 1¼PHURXVDGRSRUHODVLJQDGRUGH&38SDUDUHDOL]DUODSODQLILFDFLµQ
6H³DOHV /LVWDODVVH³DOHVTXHKDQVLGRPDQGDGDVDOSURFHVR
7HPSRUL]DGRUHV 8VDGRSDUDPDQGDUVHDOHVHQWUHSURFHVRV\OOHYDUHOWLHPSRGHHMHFXFLµQGHOSURFHVR
/LJD33OLQN $SXQWDGRUDOVLJXLHQWHSURFHVRHQODFRODGHOLVWRSDUDFRUUHUTXHVHUHMHFXWDGRWLHQH
VHQFLGRVLHOSURFHVRHVW£OLVWRSDUDFRUUHU
(VWDGRGHODPHPRULD ,QGLFDVLHOSURFHVRHVW£HQPHPRULDSULQFLSDORHQGLVFR
7DEOD$(QWUDGDHQODWDEODGHSURFHVRV.
,7(0 '(6&5,3&,1
$SXQWDGRUDODWDEODGHOSURFHVR ,QGLFDODHQWUDGDTXHFRUUHVSRQGHDO£UHD8
,GHQWLILFDGRUHVGHXVXDULR ,GHQWLILFDGRUHVGHXVXDULRGHORVSURFHVRV
7HPSRUL]DGRUHV 3DUDOOHYDUHOWLHPSRTXHORVSURFHVRVVHKDQHMHFXWDGRHQPRGR
XVXDULR\HQPRGRNHUQHO
$UUHJORPDQHMDGRUGHVH³DOHV 3DUDFDGDWLSRGHVHDOTXHUHFLEDHOSURFHVRLQGLFDFRPRVHYDD
PDQHMDULJQRUDUWHUPLQDURHMHFXWDUXQDUXWLQD
7HUPLQDOGHFRQWURO ,QGLFDODWHUPLQDOGHHQWUDGDGHOSURFHVR
&DPSRGHHUURU 5HJLVWUDORVHUURUHVDOHMHFXWDUXQDOODPDGDDOVLVWHPD
9DORUGHUHJUHVR &RQWLHQHHOUHVXOWDGRGHODVOODPDGDVDOVLVWHPD
3DU£PHWURVGH(6 'HVFULEHODVFDUDFWHU¯VWLFDVSDUDUHDOL]DUWUDQVIHUHQFLDVFRQ
3DU£PHWURVGHDUFKLYRV /RVGLUHFWRULRVTXHGHILQHQHODPELHQWHGHOSURFHVR
7DEODGHGHVFULSWRUHVGHDUFKLYRVGHXVXDULR /OHYDHOFRQWUROGHORVDUFKLYRVTXHKDDELHUWRHOXVXDULR
&DPSRVO¯PLWH 5HVWULQJHHWDPD³RGHXQSURFHVR\HOWDPD³RGHORVDUFKLYRV
&DPSRVGHSHUPLVRV 'HILQHQORVSHUPLVRVGHORVDUFKLYRVTXHHOSURFHVRFUHD
7DEOD$,QIRUPDFLµQGHO£UHD8GHXQSURFHVR
Todo esto se realiza en el modo kernel en el proceso padre. Cuando el kernel ha completado
estas funciones, el despachador (asignador del CPU) puede hacer alguna de las opciones siguientes:
xTubos(Pipes).
xMensajes.
xMemoria compartida.
xSemáforos.
xSeñales.
Los pipes, los mensajes y la memoria compartida se usan para la comunicación entre los procesos,
mientras que los semáforos y las señales se usan para la sincronización entre procesos.
A.9.1. Pipes
Una de las características más relevantes de UNIX es el concepto de PIPE. Desarrollado a partir del
concepto de corrutinas, un pipe es un buffer circular que permite a dos procesos comunicarse usando el
modelo productor / consumidor, esto es la primer información escrita por un proceso es la primera en
ser leída por el otro(PEPS o PIFO).
Cuando se crea un pipe, se le da un tamaño fijo en bytes. Se manejan automáticamente los casos de
LLENO y VACIO, es decir si se intenta escribir cuando está lleno se BLOQUEA al proceso y si se
intenta leer cuando está vacío se BLOQUE al proceso que quiso leer. Además automáticamente maneja
el sistema operativo la exclusión mutua, es decir solo un proceso a la vez accesa el PIPE.
Existen tres tipos de pipes; con nombre(también denominados FIEOS), sin nombre y los pipes de flujo
(stream pipes). Sólo los procesos relacionados pueden compartir pipes sin nombre, mientras que los
procesos no relacionados pueden compartir sólo tubos con nombre, los stream pipes pueden ser con
nombre o sin nombre.
La forma de crear un pipe es a través de la función: int pipe (int filedes [2]) La función regresa
dos decriptores de archivos, filedes[0] está abierto para lectura y filedes[ 1] está abierto para escritura.
Desde el punto de vista de un proceso un pipe puede ser visto como un archivo al que se le escribe
usando filedes[I] y se lee de el usando filedes[OJ. Esto puede ver en la gráfica A.4.
3URFHVRGHXVXDULR
IG>@IG>@
NHUQHO
3LSH
)LJXUD$8QSLSHVLQQRPEUH
3DGUH +LMR
SS 3S
IG>@IG>@ IG>@IG>@
3LSH
3LSH
.HUQHO
)LJXUD$&RPXQLFDFLµQHQWUHXQSURFHVRSDGUH\XQSURFHVRKLMRDWUDY«VGHXQSLSH.
Con frecuencia se utilizan las funciones popen y pclose para facilitar el manejo de los pipes.
El formato de la función popen es:
FILE *popen(const char *cmdstring, const char *type)
y realiza un fork seguido de un exec para ejecutar el comando cmdstring, si type es “r” el
apuntador de archivo queda conectado a la salida estándar de cmdstring si type es “w” el apuntador de
archivo queda conectado a la entrada estándar de cmdstring.
El formato de la función pelóse es el siguiente:
int pclose(FILE *fp)
su función es cerrar la E/S estándar asociada al cmdstring.
Los pipes con nombre pueden ser usados entre procesos relacionados siempre y cuando un
ancestro común haya creado el pipe. Utilizando los pipes(fifos) es posible que procesos no relacionados
puedan intercambiar datos.
El formato para crear un pipe con nombre o fifo es el siguiente:
int mkfifo (const char *pathname, mode-t mode)
La creación de un fifo es similar a la creación de un archivo. Una vez creado el fifo se puede abrir
usando la función open (las funciones normales de manejo de archivos como:
cióse, read, write, unlink,... funcionan con los fifos).
Al abrir el fifo y no especificar la bandera de nobloqueo (0-NONBLOCK) puede ocurrir lo siguiente:
* Si se abre en modo solo lectura (read-only) se bloquea al proceso hasta que otro proceso abra el fifo
para escritura.
* Si se abre en modo solo escritura (write-only) se bloquea al proceso hasta que otro proceso abra el
fifo para lectura.
Al abrir el fifo y especificar la bandera de nobloqueo (0-NONBLOCK) puede ocurrir lo siguiente:
* Si se abre en modo solo lectura (read-only) inmediatamente continua el proceso.
* Si se abre en modo solo escritura (write-only) regresa el error ENXIO si no existe un proceso que
haya abierto el fifo para lectura.
Si se escribe sobre un fifo que no está abierto para lectura por ningún proceso se genera la señal
SIGPIPE, y cuando el último escritor cierra el FIFO se genera un FIN DE ARCHlVO(eof) para el
lector del fifo.
Es común que se tengan múltiples escritores para un fifo por lo cuál es importante conservar las
escrituras atómicas, esto se logra a través de la constante PIPE-BUF que especifica la cantidad máxima
de datos que debe ser escrita en forma atómica, si todos los escritores escriben menos que esta cantidad
se garantiza que las escrituras son atómicas.
Los fifos se utilizan principalmente para:
* Comunicar comandos sin necesidad de utilizar archivos temporales.
* Aplicaciones cliente-servidor para pasar datos entre los clientes y el servidor.
La gráfica A.6 ilustra la forma de manejar los fifos para aplicaciones cliente-servidor.
En este caso los clientes se comunican con el SERVIDOR a través del fifo conocido por todos y
pueden mandarle al servidor su identificador de proceso, el proceso SERVIDOR se comunica con un
CLIENTE específico creando un FIFO particular para ese cliente, de forma tal que a través de los fifos
específicos el SERVIDOR puede mandar mensajes que serán leídos por los clientes(que saben por su
identificador de que fifo leer).
Un stream pipe puede ser sin nombre o con nombre pero tiene la característica de ser bidireccional, esto
se ilustra en la figura A.7.
La operación para crear un stream pipe es s-pipe, una característica importante de los stream pipes es
que en general son más rápidos que el uso de colas de mensajes.
6HUYLGRU
),)2 ),)2
(63&7(, (63&7(1
),)2
&RQRFLGR
SRUWRGRV
...
...
&OLHQWH&7(, &OLHQWH&7(1
)LJXUD$),)2VSDUDLPSOHPHQWDUXQDDSOLFDFLµQFOLHQWHVHUYLGRU
3URFHVRGH
XVXDULR
IG>@IG>@
NHUQHO
6WUHDPSLSH
)LJXUD$'LDJUDPDGHOXVRGHXQ6WUHDPSLSH
Cada mecanismo tiene asociado una estructura de datos que lo define, esta estructura es creada
utilizando las llamadas msgget, shmget o semget en esta llamada se debe especificar una llave (key)
cuyo tipo de datos es key-t y está definido en < sys/types.h >, esta llave (key) es utilizada para crear su
identificador dentro del kernel.
Existen varios formas en que los procesos servidor y cliente utilicen la misma estructura IPC:
x El servidor puede crear una nueva estructura IPC especificando la llave IPC-PRIVATE y
almacenar el identificador regresado (por ejemplo en un archivo) en donde el cliente puede leer
dicho identificador. La desventaja de esto es que se debe usar el sistema de archivos para
realizar la comunicación.
x Una forma muy utilizada es que el padre realice la creación de la estructura especificando IPC-
PRIVATE y después realice un fork heredando a su hijo el identificador del IPC.
Para referirse a una estructura IPC ya creada nunca se debe especificar la llave IPC-PRIVATE, pues se
crearía una nueva estructura, en vez de esto se debe usar el identificador de la estructura IPC y utilizar
solo las operaciones de manipulación y no de creación. Para crear una nueva estructura siempre se debe
utilizar una llave con IPC-CREAT haciendo OR con IPC-EXCL.
Estructura de permisos
Con cada estructura IPC está asociada una estructura que define los permisos y el propietario:
struct ipc-perm {
uid_t uid; /* Ident del usuario propietario*/ gid-t gid; /* Ident del
grupo del propietario*/
uid-t cuid; /* Ident del usuario creador */
gid-t cgid; /* Ident del grupo del creador */
mode-t mode; /* Modo de acceso*/
u-long seq; /* Número de Secuencia del slot */
key-t key; /* Llave */
}
Todos los elementos de la estructura son imcializados cuando se crea la estructura IPC excepto seq. Se
pueden modificar después los campos de uid, gid y mode a través de las operaciones msgcti, semctl o
shmcti, para que un proceso pueda modificar esto, el proceso debe ser el creador de la estructura IPC o
el superusuario. Los valores de mode especifican los permisos de la estructura IPC se dan en la tabla
A.23.
7DEOD$3HUPLVRVGHODHVWUXFWXUD,3&
Estos valores pueden ser definidos a nivel usuario, grupo y los otros.
Un problema fundamental de las estructuras IPC es que son validos en todo el sistema y la
estructura no es borrada al terminar el proceso. A menos que se borre específicamente a través de un
llamado a ipcrm, en cambio con los pipes al terminar el último proceso que hace referencia a él se borra
el pipe.
Mensajes
Un mensaje es un bloque de texto con tipo. UNIX proporciona las operaciones msgget, msgcti,
msgsnd y msgrcv para realizar el paso de mensajes. A cada proceso, se le asocia una cola de mensajes,
la cual funciona como un buzón.
El que envía el mensaje especifica el tipo con cada mensaje enviado y el receptor puede usarlo
como un criterio de selección. El receptor puede recuperar mensajes completos de acuerdo al orden de
llegada(PEPS) o de acuerdo al tipo. Un proceso se suspenderá cuando trata de enviar un mensaje a una
cola llena. Un proceso también se suspenderá cuando trata de recibir un mensaje de una cola vacía. Si
un proceso intenta leer un mensaje de un cierto tipo y no se puede hacer, el proceso no es suspendido.
Cada cola de mensajes tiene la estructura de datos siguiente:
struct msqid-ds{
struct ipc-perm msgperm; /* Estructura de Permisos */
struct msg *msg-first; /* Apuntador al Primer mensaje */
struct msg *msgJast; /* Apuntador al Ultimo mensaje */
ulong msg-cbytes; /* Número de Bytes Actual en la cola */
ulong msg-qnum; /* Número de mensajes Actual en la cola */
ulong msg-qbytes; /* Número máximo de bytes de la cola */
pid-t msg-Jspid; /* Ident. del últ. proceso hizo msgsndQ */
pid-t msgJrpid; /* Ident. del últ. proceso hizo msgrcvQ */
time-t msg-stime; /* Hora del últ. msgsnd() */
timeJ msg-rtime; /* Hora del últ. msgrcvQ */
time-t msg-ctime; /* Hora del últ. cambio */
}
Algunas constantes que definen la operación de las colas de mensajes especificando el
tamaño en bytes y en número de mensajes son: MSGMAX, MSGMNB, MSGMNI y
MSGTQL.
9$/25GHFPG '(6&5,3&,1
,3&67$7 /HHODHVWUXFWXUDLGHQWLILFDGDSRUPVJLG\ODDOPDFHQDHQODHVWUXFWXUDDSXQWDGDSRUEXI
,3&B6(7 'HILQHORVFDPSRVPVJBSHUPXLGPVJSHUPJLGPVJSHUPXLG\PVJBTE\WHVGHODFROD
GHPHQVDMHVGHILQLGDSRUPVJLGWRPDQGRORVYDORUHVGHODHVWUXFWXUDDSXQWDGDSRUEXI
3DUDTXHXQSURFHVRSXHGDUHDOL]DUHVW£RSHUDFLµQHOLGHQWLILFDGRUGHOSURFHVRGHEHVHU
PVJBSHUPFXLGµPVJBSHUPXLGRXQSURFHVRVXSHUXVXDULR6µORHOSURFHVR
VXSHUXVXDULRSXHGHLQFUHPHQWDUHOYDORUGHPVJBTE\WHV
,3&B50' %RUUDODFRODGHPHQVDMHVGHOVLVWHPD\FXDOTXLHUPHQVDMHHQHOOD/RVSURFHVRVTXH
HVW£QXVDQGRWRGDY¯DODFRODUHFLELU£QXQHUURU(,'50HQODVLJXLHQWHRSHUDFLµQTXHVH
UHDOLFH(VWDRSHUDFLµQVµORVHSXHGHUHDOL]DUSRUXQSURFHVRFX\R,GHQWLILFDGRU
FRUUHVSRQGDDDPVJBSHUPFXLGµPVJBSHUPXLGRSRUHOSURFHVRVXSHUXVXDULR
7DEOD$&RPDQGRVGHODRSHUDFLµQPVJFWL.
int msgsnd(int msgmsqid, const void *ptr, size_t nbytes, int flag);
Regresando O si es exitoso y -1 sino.
Cada mensaje queda formado por un long integer que define el tipo del mensaje, el número que
define la longitud del mensaje(nbytes) y los datos del mensaje, ptr apunta a un long integer que
contiene un valor positivo que define el tipo del mensaje seguido del mensaje en sí, como ejemplo si
los mensajes son de tamaño 512 se tiene:
struct mensaje{
long tipo; /* Valor positivo del tipo de mensaje)*/
char conten; /* Datos del mensaje definidos por nbytes */
El valor de tipo puede ser usado por el receptor para leer los mensaje en orden diferente al de
entrada (PEPS).
Si se especifica IPC_NOWAIT y se excede el número de mensajes o el tamaño en bytes en la
cola msgsnd regresa inmediatamente indicando el error EAGAIN.
Si no se especifica IPC_NOWAIT y se excede el número de mensajes o el tamaño en bytes de
la cola se bloque al proceso hasta que:
9$/25'(W\SH '(6&5,3&,1
6HUHJUHVDHOSULPHUPHQVDMHGHODFROD
! 6HUHJUHVDHOSULPHUPHQVDMHFX\RYDORUGHOWLSRVHDLJXDODOHVSHFLILFDGR
(OSULPHUPHQVDMHFX\RYDORUGHOWLSRVHDPHQRURLJXDODOYDORUDEVROXWR
GHOHVSHFLILFDGRHVHOTXHVHUHJUHVD}
7DEOD$2SFLRQHVSDUDHVSHFLILFDUTXHPHQVDMHUHFLELU
Memoria compartida
La forma más rápida de comunicación interprocesos que proporciona UNIX es la memoria
compartida, la cual es un bloque común de memoria virtual, compartida por múltiples procesos.
Los procesos leen y escriben en la memoria compartida usando las mismas instrucciones de
máquina que usan para leer y escribir en otras partes de su espacio de memoria virtual. El permiso
para un proceso es solo leer o leer-escribir, determinado con base en cada proceso. La exclusión
mutua no es soportada directamente por la memoria compartida y debería ser soportada por otro
mecanismo por ejemplo usando semáforos.
El kernel mantiene la siguiente estructura para cada área de memoria compartida:
struct shnid ds {
struct ipc_perm shm_perm; /* Permisos */
struct anon_map *shm_map; /* Apuntador del kernel */
int shm_segsz; /* Tamaño del segmento en bytes */
ushort shm_lkcnt; /* # veces que se ha bloquedo el segmento */
pid_t shmJpid; /* Ident. del proceso de últ. shmopQ */
pid_t shm-cpid; /* Ident. del proceso creador */
ulong shm_nattch; /* # actual de enlaces a mem. compartida */
Digitalización con propósito academico. Sistemas operativos
$&2081,&$&,1'(,17(5352&(626 169
shmget La función para obtener un identificador de memoria compartida es shmget, cuya sintaxis es:
int shmctl(int shmid, int cmd, struct shmid-ds *buf) El parámetro especifica alguno de los valores
ilustrados en la tabla A.26.
9$/25 '(6&5,3&,1
,3&67$7 /HHODHVWUXFWXUDVKPLGVSDUDHOVHJPHQWRLQGLFDGRJXDUG£QGRORHQODHVWUXFWXUDDSXQWDGDSRU
EXI
,3&6(7 'HILQHORVFDPSRVVKPSHUPXLGVKPSHUPJLGVKPSHUPPRGHGHDFXHUGRDORVYDORUHV
GHILQLGRVHQODHVWUXFWXUDDSXQWDGDSRUEXI(VWHFRPDQGRVRORORSXHGHHMHFXWDUHOSURFHVRFRQ
LGHQWLILFDGRULJXDODVKPBSHUPXLGVKPSHUPFXLGRHOSURFHVRVXSHUXVXDULR
,3&50' %RUUD HO VHJPHQWR GH PHPRULD FRPSDUWLGD GHW VLVWHPD (O VHJPHQWR QR VH ERUUD KDVWD TXH HO
¼OWLPRSURFHVRHQOD]DGRDO£UHDGHPHPRULDFRPSDUWLGDVHGHVHQODFHSHURQRVHSHUPLWHQQXHYRV
HQODFHV3DUDTXHVHSXHGDUHDOL]DUHOFRPDQGRHOSURFHVRTXHORHMHFXWDGHEHWHQHULGHQWLILFDGRU
LJXDODVKPASHUPXLGVKPSHUPFXLGRHOSURFHVRVXSHUXVXDULR
6+0/2&. %ORTXHD HO VHJPHQWR GH PHPRULD FRPSDUWLGD (VWH FRPDQGR VµOR VH SXHGH HMHFXWDU SRU HO
VXSHUXVXDULR
6+0--1/2&. 'HVEORTXHDHOVHJPHQWRGHPHPRULDFRPSDUWLGD(VWHFRPDQGRVRORORSXHGHUHDOL]DUHOSURFHVR
VXSHUXVXDULR
7DEOD$9DORUHVGHFPGGHQWURGHVKPFWO.
shmat Una vez que se ha creado el segmento de memoria compartida un proceso se enlaza a él con:
x Si addr es cero el segmento al que se enlaza es la primer direción disponible seleccionada por
el kernel.(Esto es lo recomendado).
x Si addr no es cero y no se especifica SHM_RND, se enlaza al segmento de acuerdo a la
dirección especificada.
x Si addr no es cero y se especifica SHM_RND(de ROUND, redondear), se conecta al addr
redondeándolo de acuerdo a la alineación definida(normal mente múltiplo de dos, esto se
define por SHMLBA)
shmdt La operación shmdt permite desenlazarse de un área de memoria compartida (sólo se borra con
shmctl) la sintaxis de esta operación es:
Semáforos
Las llamadas al sistema de semáforos en el sistema UNIX son una generalización de las
primitivas P y V. Pues pueden realizarse varias operaciones de manera simultánea y el aumento y
decremento de las operaciones pueden ser valores mayores que uno. El kernel hace todas las
operaciones requeridas en forma atómica; ningún otro proceso puede accesar el semáforo sino hasta
que se terminan todas las operaciones.
Un semáforo consta de los siguientes elementos:
Asociadas con el semáforo, están las colas de procesos suspendidos en ese semáforo.
En realidad, los semáforos se crean en conjuntos y un conjunto consta de uno o más semáforos.
Existe una llamada de sistema semctl que permite establecer todos los valores del semáforo en el
conjunto, al mismo tiempo. Además, existe una llamada de sistema semop que toma como argumento
una lista de operaciones del semáforo, cada una definida sobre uno de los semáforos en un conjunto.
Cuando se hace esta llamada, el kernel ejecuta las operaciones indicadas una a la vez. Para cada
operación, la función real la especifica el valor sem_op.
Las posibilidades son las siguientes:
x Si sem_op es positivo, el kernel aumenta el valor del semáforo y despierta todos los procesos
esperando que el valor del semáforo aumente.
x Si sem_op es O, el kernel comprueba el valor del semáforo. Si es O continua con las otras
operaciones en la lista; de otra manera, aumenta el número de procesos esperando que este
semáforo sea O y suspende el proceso en caso de que el valor del semáforo sea igual a 0.
x Si sem_op es negativo y su valor absoluto es menor que o igual al valor del semáforo, el kernel
añade sem_op (un numero negativo) al valor del semáforo. Si el resultado es O, el kernel
despierta todos los procesos esperando que el valor del semáforo sea igual a O.
semget La operación semget permite realizar la creación del semáforo pero no su inicialización (para
ello se debe usar la operación semctl). Y se debe tomar en cuenta que el semáforo no es borrado cuando
el proceso que lo creo termina, para ello es necesario hacerlo a través de semctl.
Internamente se maneja la siguiente estructura de los semáforos:
struct semid_ds {
struct ipc_perm sem_perm; /* Definición de permisos */
struct sem *sem_base; /* Apuntador al primer semáforo del conjunto */
ushort sem_nsems; /* # de semáforos en el conjunto */
time_t sem_otime; /* Hora de última operación semop() */
time_t sem_ctime; /* Hora de última modificación */
}
sem_base es un apuntador manejado en el kernel que apunta a un arreglo de estructuras sem:
struct sem {
ushort semval; /* Valor del semáforo, siempre MAYOR O IGUAL A CERO */
pid_t sempid; /* Ident. del proceso que hizo últ. operación */
ushort semcnt; /* # de procesos esperando semval > valor actual*/
ushort semzcnt; /* # de procesos esperando que semval = O */
}
Algunas constantes que definen la operación de los semáforos respecto al número máximo de
semáforos en el conjunto y sus valores son: SEMVMX, SEMAEM, SEMMNI, SEMMNS, SEMMSL,
SEMMNU. SEMUME y SEMOPN.
La sintaxis de la operación semget es:
int semget(key_t key, int nsems, int flag);
Al crear un semáforo se inicializan los siguiente Ítems de la estructura semid_ds:
semctl La operación que permite entre otras cosas realizar la inicialización es semctl, sus sintaxis es:
int semctl (int semid, int semnum, int cmd, unión semun arg);
&20$1'2 '(6&5,3&,1
,3&B7$7 /HHODHVWUXFWXUDGHVHPLGGV\ODDOPDFHQDHQODHVWUXFWXUDDSXQWDGDSRUDUJEXI
,3&B6(7 'HILQHORVFDPSRVVHPBSHUPXLGVHPBSHUPJLG\VHPBSHUQUPRGHGHDFXHUGRDYDORUHVTXHVHWLHQHQHQOD
HVWUXFWXUDDSXQWDGDSRUDUJEXW3DUDTXHVHSXHGDUHDOL]DUHVWDRSHUDFLµQHOLGHQWLILFDGRUGHOSURFHVRGHEH
FRLQFLGLUFRQVHPBSHUPXcGVHPSHUPFLGRVHUHOVXSHUXVXDULR
,3&B50,' %RUUDHOFRQMXQWRGHVHP£IRURVGHOVLVWHPDHOERUUDGRHVLQPHGLDWR&XDOTXLHUSURFHVRTXHHVW«XVDQGRHO
VHPIRURUHFLEHXQHUURU(,'50FXDQGRLQWHQWHUHDOL]DUODVLJXLHQWHRSHUDFLµQVREUHHOFRQMXQWRGHVHPIRURV
3DUDTXHVHSXHGDUHDOL]DUHVWDRSHUDFLµQHOLGHQWLILFDGRUGHOSURFHVRGHEHFRLQFLGLUFRQVHPBSHUPXLG
VHPBSHUPGGRVHUHOVXSHUXVXDULR
*(79$/ 5HJUHVDHOYDORUGHVHPYDOSDUDHOVHPIRURHVSHFLILFDGRSRUVHPQXP
6(79$/ 'HILQHHOYDORUGHVHPYDOSDUDHOVHPIRURLQGLFDGRSRUVHPQXP(OYDORUHVHVSHFLILFDGRHQDUJYDO
*(73,' 5HJUHVHHYDORUGHVHPSLGSDUDHOVHPIRURHVSHFLILFDGRSRUVHPQXP
*(71&17 5HJUHVDHOYDORUGHVHPQFQWSDUDHOVHPIRURHVSHFLILFDGRSRUVHPQXP
*(7=&17 5HJUHVDHOYDORUGHVHP]FQWSDUDHOVHPIRURHVSHFLILFDGRSRUVHPQXP
*(7$// /HHWRGRVORVYDORUHVGHORVVHPIRURVHQHOFRQMXQWR\ORVDOPDFHQDHQHODUUHJORDSXQWDGRSRUDUJDUUD\
6(7$// 'HILQHWRGRVORVYDORUHVGHORVVHPIRURVHQHOFRQMXQWRWRPDQGRORVYDORUHVDSXQWDGRVSRUDUJDUUD\
7DEOD$2SFLRQHVGHFPGHQHOFRPDQGRVHPFWO.
semop La operación semop realiza en forma atómica un arreglo de operaciones sobre un conjunto de
semáforos, la sintaxis de esta operación es:
Si el valor de sem_op es negativo esto equivale a una operación P. Si el valor del semáforo es
MAYOR O IGUAL al valor absoluto de sem_op, el valor absoluto de sem_op es restado del valor del
semáforo. Esto garantiza que el valor resultante de el semáforo es mayor o igual a cero. Si la bandera
SEM_UNDO es especificada el valor absoluto de sem_op es sumado al valor de ajuste del proceso de
dicho semáforo. SÍ el valor de sem_op es negativo pero el valor del semáforo es menor que el valor
absoluto de sem_op puede ocurrir lo siguiente:
Si se especifico IPC_NOWAIT se regresa inmediatamente indicando el error EAGAIN.
Si no se especifico IPC_NOWAIT, e] valor de semncnt es incrementado y el proceso es
bloqueado hasta que pase algo de los siguiente:
El valor del semáforo llegue ha ser mayor o igual al valor absoluto de sem_op
(ocasionado por que otro(s) proceso(s) realizo operaciones semop con valores positivos). En
este momento el valor de semncnt es decrementado, el valor absoluto de sem_op es restado del
valor del semáforo. Si se especifico SEM-UNDO el valor absoluto de sem_op es sumado al
valor de ajuste del proceso respecto a ese semáforo.
El semáforo sea borrado del sistema con lo que se regresa el error ERMID
Se reciba una señal, con lo cuál se decrementará el valor de semncnt y se regresa el error
EINTR.
Si sem_op es cero indica que se desea esperar hasta que el valor del semáforo
sea cero. Si el valor del semáforo es cero se regresa inmediatamente. Si el valor del semáforo no
es cero puede ocurrir lo siguiente:
Java
B.l. Introducción
Este apéndice contiene un resumen general de Java con puntos básicos del lenguaje, que
facilitará el aprendizaje a aquellas personas que desean aprender o que están iniciado el camino hacia el
creciente mundo de Java.
Desde su lanzamiento en 1995, la plataforma Java ha sido la tecnología qué más ha sido
adoptada por la Industria en los últimos años. Desde un contexto mixto de Software y Hardware, la
tecnología Java puede ser concebida como un conjunto de atributos, que no son únicos de la tecnología,
pero la manera en como estos se combinan hace de Java una tecnología altamente recomendable para la
Industria y la computación dentro de las Empresas [74], véase la Figura B.1.
Desde otra perspectiva, Sun Microsystems define a Java como:
Un lenguaje simple, orientado a objetos, distribuido, interpretado, robusto, seguro, de
arquitectura neutral, portable, de alto desempeño, multi hilos y dinámico.
Un poco pretencioso de parte de Sun, aunque en realidad Java cumple con estas características.
x Orientado a Objectos: Java es un lenguaje orientado a objectos, ya que permite utilizar todas las
características de este paradigma, como clases, objectos, herencia, medularidad, reutilización de
código, etc.
x Interpretado: en lugar de generar código nativo de máquina, el compilador de Java genera byte-
code para la Máquina Virtual de Java (Java Virtual Machine).
x Portable y de Arquitectura Neutral: Los programas de Java son compilados a una arquitectura
nuetral en un formato de Byte-Code, por lo que una aplicación de Java puede ejecutarse sobre
cualquier sistema, siempre y cuando este tenga la Máquina Virtual de Java.
x Dinámico: Las clases pueden ser cargadas dinámicamente en tiempo
174
0RGHORGH
6HJXULGDG
3RUWDELOLGDG $FFHVR
DO:HE
2EMHWRV-DYD 'HVDUUROOR
5£SLGR
7HFQRORJ¯D
-DYD
Figura B.1. Tecnología Java.
x Distribuido: Básicamente por la capacidad de Java de soportar operaciones sobre red de alto
nivel. Esta característica permite a Java bajar y ejecutar código atravez de Internet.
x Simple: Ya que es fácil de aprender, y además la semejanza con C , permite que los usuarios no
tengan muchos problemas para adaptarse a Java.
x Multi Hilos: Java soporta el manejo de múltiples hilos de ejecución que pueden manejar
diferentes tareas.
B.2. Historia
del desarrollo de otra tecnología emergente de Internet, enfocada a la parte comercial y de negocios, el
Worid Wide Web. [75].
La semejanza entre Java y C es muy grande, lo cual facilita mas el aprendizaje de Java para un
programador de C. Aun así existen algunas diferencias importantes de mencionar.
Un programa en Java esta formado por una o mas clases, cada una de las cuales es compilada a
byte-code, archivo de tipo .class el cual es ejecutable para la Máquina Virtual de Java. Por lo menos
alguna de estás clases debe definir el método main () dentro de ella, convirtiéndose en la clase principal
que inicia el programa.
Todo programa o aplicación de Java debe tener una función main O construida de la siguiente
manera:
public static void main(String args)
x public: define que el método main puede ser llamado por cualquier objeto.
x static: indica que el método main es una método de la clase.
x void: muy semejante en C, indica que el método main no regresa ningún valor.
Para ejecutar un programa, primero se debe generar el byte-code, para después ejecutar el
interprete Java seguido del nombre de la clase que contiene la función main (), omitiendo la extensión
.class. Por otro lado se encuentran los applets de Java, que es importante mencionar no son
aplicaciones, que puedan ser ejecutadas de la forma mencionada anteriormente. Un applet es una clase
de Java que puede ser ejecutada por otra aplicación de Java, Navegador de Internet o con el
visualizador de applets. [76].
B.3.2. Argumentos
Debido a que el método mainO en Java debe ser declarado como void, un programa en Java no
podrá regresar valores de salida con un retum al final del método main, por lo que el programador
deberá invocar el método System. exit ().
El estatuto import es utilizado en Java para hacer accesibles los paquetes de clases que trae por
omisión, además de facilitar la escritura del código. Muy similar al include
utilizado en C. Es importante mencionar que los estatutos import deben aparecer en el tope del código y
antes de cualquier declaración de la primera clase o interface. Existen dos formas de utilizarlo:
x En primera hacer accesible una clase de un paquete en especial, para que en vez de escribir j
ava. útil. Vector cada vez que se desee utilizar la clase, agregando import java. útil. Vector, solo
se tendrá que hacer referencia a la clase como Vector.
x Hace accesible todas las clases de un paquete, para no tener que definirlas una por una, por
ejemplo import. awt. *.
B.3.6. Constantes
Para definir una constante en Java esta debe ser declarada como f inal y su valor debe ser
asignado al momento de que se defina la variable. #de£ine es el equivalente en C para definir
constantes de tipo static final en Java. Por ejemplo static final int KM = 1000;
A diferencia de C, Java define tamaños estrictos para los tipos de datos. En C un tipo de dato int
puede ser de 16, 32 o 64 bits, y un char puede ser con signo o sin signo. A menudo las variables en C
tienen basura dentro de su valor, Java tiene la característica de definir valores por omisión en la
inicialización.
7DEOD%,7LSRVGHGDWRVHQ-DYD
Para los programadores de C este terminó puede sonar algo fuera de lo común, debido a que
están acostumbrados a preocuparse por crear objetos, para después liberar la memoria
que estos ocupaban. En Java se usa la técnica de colección de basura para detectar objectos que no
están mas en uso y liberarlos. Es por eso que no existe algo equivalente al comando free O de C, la
técnica de collección de basura se encarga de ese trabajo. Para la creación de objectos en Java se utiliza
la palabra reservada new, equivalente a raalloc () de C.
B.3.9. Apuntadores
B.3.10. Strings
Los Strings en Java no son cadenas de caracteres terminados con un cracter nulo ('\0') como en C, por
lo que Java casi lo define como tipo de dato primitivo, pero en realidad son instancias de la clase java.
lang. String. Una característica curiosa de los Strings, es que no se pueden realizar operaciones de
modificación sobre ellos, por lo que se tiene que hacer uso de la clase StringBuffer para hacerlo, y
después regresarlo a tipo String.
B.3.11. Arreglos
En Java el límite de un arreglo es delimitado de forma muy estricta, debido a esta característica
cualquier intento de leer mas allá del tamaño del arreglo, resulta en un error de compilación o en
tiempo de ejecución. Por esta razón para hacer referencia a un Arreglo en Java, se debe recurrir a
referenciación implícita, no a aritmética de puntos.
Ya que Java es un lenguaje orientado a objetos, en esta sección hablaremos un poco del paradigma
orientado a objetos y de algunos conceptos básicos que es recomendable analizar antes de empezar a
programar.
La programación orientada a objetos no tiene una definición concreta, por lo que mencionaremos
conceptos, que le ayudaran a conceptualizar el paradigma orientado a objetos.
B.4.1. Objeto
Los objetos de software son modelados en base a los objetos reales, que como estos también
cuentan con estados (variables) y comportamientos (métodos). [77].
B.4.2. Clase
En la vida diaria constantemente estamos en contacto con objetos del mismo tipo que
comparten características similares. Una clase es un conjunto de datos y métodos que operan sobre los
datos y comparten características de un objeto en específico. [781].
En la Figura B.2 se muestra una clase, formada por variables y métodos de instancia.
0«WRGRV
9DULDEOHV
*UXSRV
+DFHU
GH'LVFXVLµQ
7DUHDV
&DOLILFDFLµQ
3DUWLFLSDFLµQ
5HVSRQVDELOLGDG
$VLVWLUD
(VWXGLDU &ODVHV
B.4.3. Método
B.4.4. Instancia
Considerando que la clase es una representación abstracta y general de un objeto, una instancia
es la representación concreta de la clase, véase Figura B.4.
&¯UFXOR
&ODVH &¯UFXOR
&¯UFXOR
$EVWUDFWR &¯UFXOR
&RQFUHWR
)LJXUD%,QVWDQFLDVGHXQDFODVH
&ODVH$
&ODVH% &ODVH(
)LJXUD%-HUDUTX¯DGHFODVHV
B.4.5. Herencia
Applet: Es un programa Java que se ejecuta por medio de un Visualizador Web en la máquina
del cliente. A diferencia de un apliación el applet depende de un Visualizador
Digitalización con propósito academico. Sistemas operativos
181 $31',&(%-$9$
Web que soporte Java para su ejecución. Todo applet debe de implementar por lo uno y mas de
los métodos: init, start y paint.
Como para muchos de los lenguajes existentes, un programa Java puede ser creado o editado
con un editor de texto sencillo que guarde los archivos en ASCII y sin caracteres de formato. Es
importante mencionar que el compilador de Java por convención acepta archivos con extensión .java,
por lo que cualquier programa que cree debe tener esta extensión.
Windows: NotePad o Edit de MS-DOS.
Unix: pico, vi o asedit.
Ya sea que se trate de una aplicación o de un applet, o si se encuentra en Windows o Unix, para
compilar un programa Java, solo debe estar en el subdirectorio donde se encuentra el programa Java y
teclear lo siguiente:
javac {nombre del programa}
Por Ejemplo:
javac ProgramaJava.java
Después de compilar un programa Java sin errores el resultado es un archivo. class dentro del
mismo subdirectorio que el código fuente. Lo que contiene la clase es un bytecode de Java, que es un
código de plataforma independiente, para ser interpretado por la Máquina Virtual de Java.
Tanto para la plataforma Windows o Unix, es el mismo comando. Una vez que ya se creo el
programa Java, se debe teclear lo siguiente:
java [nombre de la clase}
Por ejemplo:
java ProgramaJava
El argumento para el interprete de Java es el nombre de la clase que se desea ejecutar, no el
nombre del archivo, es decir que se debe de omitir la extensión. Es importante que escriba exactamente
el nombre de la clase, ya que el interprete de Java es sensible a mayúsculas / minúsculas.
Para ejecutar un applet, debe compilar primero el programa Java, para después cargar el archivo HTML
(página Web) que hace referencia al applet, dentro de un Visualizador Web que soporte applets de
Java, este puede ser Netscape, Explorer o Hotlava. Para esto debe indicar al Visualizador la ruta y
nombre completo donde creo el archivo HTML.
Existe la posibilidad de ejecutar un applet por medio de una aplicación llamada appletviewer, que trae
incluida el JDK (Java Development Kit), y se debe teclear lo siguiente:
appletviewer (ruta y nombre del archivo html)
Por ejemplo:
appletviewer file;/ejeiaplos/AppletJava
init; Inicializa el applet cuando se carga por primera vez. En este proceso se crean los objetos y
la configuración inicial de variables.
start: Ya inicializado un applet, el arranque e sel siguiente paso. Si un applet fue detenido, para
cambiarse a otra página, cuando se regrese al applet, este arranca de nuevo. Este proceso se puede
repetir varias veces durante el ciclo de vida de un applet, a diferencia de la inicialización que solo
sucede una vez.
stop; La detención sucede principalmente cuando se abandona la página donde se encuentra el applet,
en este momento se suspende la ejecución de los hilos, para después volverlos a arrancar cuando se
visualice el applet de nuevo.
destroy: Elimina y limpia todos los hilos de ejecución antes de que el applet sea liberado o de que el
Visualizador lo termine. Por lo general este método no es usado a menos que recursos que se hayan
utilizado necesiten ser liberados, pero es recomendable utilizarlo.
El ejemplo que se muestra a continuación es un ejemplo muy sencillo de una aplicación, que
tiene el propósito de mostrar algunos de los fundamentos de Java como:
x Instanciación de clases.
x Condicional if y switch.
x Ciclos for y while.
x Manejo de excepciones-
x Métodos
x Manejo de Argumentos.
ProgramaJava.java
El ejemplo recibe dos argumentos, el primero una cadena de caracteres (string) y el segundo un
número entero. Como resultado produce la impresión en pantalla de la cadena de caracteres, tantas
veces como el segundo argumento. Por ejemplo si se ejecuta el programa de la siguiente forma java
ProgramaJava Hola 3, deberá desplegar lo siguente:
HOLA
HOLA
HOLA
Usted mandó imprimir el mensaje un número impar de veces.
1 import java.útil. Vector;
En este ejemplo sólo utilzaremos la clase Vector(), por lo que en vez de importar todo el paquete
completo, sólo elegimos la clase Vector().
2 public class Pro grama Java { Encabezado del programa, define el nombre de la clase.
3 static String mensaje;
4 static int veces;
Declaración de variables globales, en este caso son estáticas debido a que son referenciadas por
el método main() que también es estático.
5 public Programa Java () {
6 Vector mensajes = new Vector();
Inicialización e instanciación de una clase Vector.
7 for(int i=0; i < veces; i++) {
Sintaxis: for(inicializaci6n; condición; incremento o decremento).
8mensajes.addElement(mensaje.toUpperCase());
Agrega el texto en mayúsculas que se recibió como argumento al Vector, tantas veces lo defina
el segundo argumento.
9 }
10 Imprime("Usted mando imprimir el mensaje un numero"+EsPar(veces)+"de veces");
Manda llamar el método EsPar para calcular si es par o impar el segundo argumento.
11 while(veces > 0) {
Sintaxis: while(condición)
12 Imprime((String)mensajes.elementAt(veces-1));
Imprime uno por uno todos los elementos del Vector, ejecutando un cast de valores tipo Objeto
que regresa el Vector a String.
13 eces—;
Decrementa en uno la variable;
14 }
15 }
16 public static void main(String[] args) { Implementación del método main.
17 try {
Inicia el rango del programa en donde se cacharán excepciones.
18 if(args.length==2) {
Verifica si los argumentos que esta recibiendo la clase son 2.
19 mensaje = new String(args[0] );
Almacena el primer argumento dentro de una variable de tipo String.
20 veces = Integer.parselnt(args[l]);
import java.útil.Vector;
public class ProgramaJava {
static String mensaje;
static int veces;
public PrograJiiaJava() {
Vector mensajes = new Vector();
for(int i=0; i < veces; i++) {
El applet que se muestra a continuación, implementa dos áreas de texto, la primera editable y la
segunda no editable. Todo aquel texto que se escriba dentro de la primera área
de texto, se copiará a la segunda después de oprimir el botón Copiar, El botón Limpiar borra el
contenido de las dos áreas de texto.
Programa AppletJava.java
import j ava.applet.Applet;
import java.awt.*;
import java.awt.event.*;
public class AppletJava extends Applet {
Panel Panel_ditable;
Panel Panel_oEditable;
Panel Main;
Label Etiqueta_ditable;
Label Etiqueta_NoEditable;
TextArea Texto_Editable;
TextArea Texto_NoEditable;
Button Boton_Copiar;
Button Boton_Limpiar;
public void INIT()
Construye();
}
public void Construye() {
Etiqueta-Editable = new Label("EDITABLE",Label.CENTER);
Texto_Editable = new TextArea();
Panel_Editable = new Panel (new BorderLayout()) ;
Panel_Editable. add(Etiqueta_Editable ,BorderLayout. NORTH);
Panel_Editable. add (Texto_Editable, BorderLayout. CENTER);
Etiqueta_NoEditable = new Label("NO EDITABLE",Label.CENTER);
Texto_NoEditable = new TextArea() ;
Texto_NoEditable.setEditable(false);
Panel_NoEditable = new PaneKnew BorderLayout());
Panel_NoEditable. add(Etiqueta_NoEditable ,BorderLayout. NORTH);
Panel_NoEditable. add(Texto-NoEditable, BorderLayout. CENTER) ;
Main = new Panel(new GridLayout(2,D);
Main.add(Panel_Editable) ;
Main.add(Panel-NoEditable);
Boton_Copiar = new Button("Copiar");
Boton_Copiar.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
Copia();
}
});
BotorL_Limpiar = new Button.(“Limpiar”) ;
Botón _Limpiar.addActionListener (new ActionListener () {
B.5.7Archivo AppletJava.html
<HTML>
<HEAD>
<TITLE>AppletJava</TITLE>
</HEAD>
<BODY>
<APPLET CODE=”ApletJava” WIDTH=400 HEIGHT=400>
</APPLET>
</BODY>
</HTML>
B.6. Hilos
Que estudiante sentado en la mesa del comedor, en su vida no ha tenido el deseo de hacer los
problemas de Mecánica, leer el artículo de valores en México y América Latina, ver su serie de
televisión favorita y estudiar para su examen final de Ecuaciones Diferenciales, todo al mismo tiempo.
Por imposible que parezca, este tipo de situaciones suceden en el mundo real, tal vez menos
complicadas que la anterior o porqué no, aun mas difíciles. Un ejemplo claro, es la rutina común, que
realizamos al manejar, en donde se puede llegar a la situación de dar vuelta, cambiar de velocidad,
tener cuidado de no pegarle al carro que esta mal estacionado en la esquina y observar alrededor para
verificar que ningún despistado quiera cruzar la calle, todo al mismo tiempo. En el mundo de la
computación, a menudo
las computadoras personales se enfrentan al mismo reto, de enviar un correo electrónico, imprimir un
documento, compilar un programa y bajar un programa de la Internet, al mismo tiempo. Después de tan
largo ejemplo, podemos inferir que la concurrencia es importante para nuestras vidas, a pesar de esto
muchos lenguajes de programación, no brindan la facilidad de implementar actividades concurrentes.
En este aspecto Java brinda al programador un conjunto de primitivas, donde puede especificar que sus
aplicaciones contengas hilos de ejecución (clase Thread), y la implementación de programación multi
hilos (multithreading), donde a cada hilo se le designa una parte del programa la cual es ejecutada
concurrentemente con otros hilos. La definición de un hilo entonces, puede ser una sección de código
ejecutado independientemente de otros hilos dentro de un mismo programa.
La clase Thread es un hilo de ejecución en un programa, en donde la máquina vitual de Java permite la
ejecución de hilos concurrentemente dentro de una aplicación. Cada hilo tiene una prioridad, en donde
los hilos con mayor prioridad son ejecutados preferentemente que aquellos con menor prioridad. En un
programa ejecutado por un hilo se crea una nueva instancia del objeto Thread, este hilo tiene
inicialmente la misma prioridad que aquel hilo que lo creo.
Cuando se ejecuta una aplicación, la maquina virtual crea un hilo que típicamente llama al método
main, de aqui en adelante la maquina virtual sigue ejecutando hilos hasta que:
B.6.1. Constructores
x public Thread(String NombreHilo) : que construye un hilo cuyo nombre es NombreHilo.
x public Thread() : construye un hilo cuyo nombre es "Thread"+n, donde n es un número entero,
por ejemplo Thread4,Thread5, etc.
El trabajo que un Thread debe realizar se encuentra definido dentro del método run, aunque
explícitamente no se hace una llamada a este método, cuando un programa inicializa la ejecución de un
hilo hace una llamada al método start, que a su vez hace la llamada el método run. [79]
El siguiente código crea un hilo y lo ejecuta.
B.6.2. Métodos
Los métodos que se mencionan a continuación no son todos los que posee la clase Thread, pero
si los mas importantes.
start
Inicializa la ejecución del hilo y la Máquina Virtual de Java llama al método run del hilo.
run
Si la construcción del hilo fue hecha usando un objeto ejecutable Runnable, entonces este método del
objeto Runnable es llamado; si este no es el caso, este método no hace nada.
seelp
Permite dormir al hilo, por una cantidad de milisegundos. La excepción que genera puede ser debido a
que otro hilo a interrumpido este hilo.
stop
Fuerza a un hilo a parar independientemente de lo que este ejecutando.
Interrupt
Interrumpe el hilo.
Isinterrupted
Verifica si el hilo ha sido interrumpido.
destroy
Destruye el hilo, sin desbloquear cualquiera de los monitores que este haya bloqueado.
IsAlive
Verifica si el hilo todavía esta vivo. Todo hilo se mantiene vivo mientras haya sido inicial izado y no
haya muerto.
suspend
Suspende el hilo. Si el hilo esta vivo suspende cualquier trabajo que este ejecutando hasta que sea
reiniciado.
resume
Reinicia un hilo suspendido. Si el hilo esta vivo pero suspendido, es reiniciado y permite que continué
su ejecución.
Yield
El hilo que esta siendo ejecutado es detenido temporalmente y permite a otros hilos ejecutarse.
El ejemplo que se muestra a continuación es una aplicación que muestra la forma de como
implementar hilos. Cada uno de los 5 hilos en la aplicación imprime en pantalla su nombre, después de
dormirse un tiempo dado entre O y 3 segundos. [79]
x ThreadJava: clase principal que instancia cinco clases ImprimeThread, e invoca el método
start de la clase Thread, en cada unos de los cinco objetos ImprimeThread para ponerlos listos
para ejecución.
x ImprimeThread: es una clase que es heredada de Thread, consiste de la variable de instancia
duérmete, un constructor y el método run. La variable duérmete, es inicializada con un entero
aleatorio entre O y 3000 cuando el objeto ImprimeThread
es construido, para después dormirse el tiempo especificado por duérmete y después imprime en
pantalla su nombre.
La aplicación termina hasta que el último hilo ImprimeThread despierte e imprima su nombre.
Baci
C.l. Introducción
Baci es descendiente del lenguaje Pascal secuencial (PascaI-S) propuesto por Ben Ari. Pascal-S
es una extensión al lenguaje Pascal más algunas extensiones para soportar el manejo de concurrencia,
en particular se soporta la construcción cobegin ... coend para indicar ejecución concurrente y la
construcción wait... signal para controlar que ciertas partes de un programa sean ejecutadas de manera
mutuamente exclusiva. La diferencia entre la implementación de Pascal y Baci, es que Baci utiliza un
subconjunto del lenguaje C++ en lugar de Pascal.
Baci una herramienta sencilla de utilizar y fácil de entender, para usarlo se requiere solo
entender conceptos básicos de lenguajes de programación y conocer mecanismos de manejo de
concurrencia. En particular Baci soporta la creación de procesos, semáforos generales, semáforos
binarios y monitores.
Baci está compuesto de un compilador y de un interprete. El compilador toma como entrada un
programa escrito en un subconjunto del lenguaje C++ (llamado C- -) más algunas construcciones para
creación de procesos y manejo de concurrencia y produce como salida un programa en PCODE que es
un código para una máquina virtual. El interprete toma como entrada el programa en PCODE y lo
ejecuta directamente. El proceso de utilización de Baci se describe en la figura C.l.
C.2. El Lenguaje C- -
El lenguaje C- - son un subconjunto del lenguaje C++. Algunas restricciones y nuevos tipos que
se aplican en este compilador son ;
x Las operaciones de entrada y salida se manejan solamente con: cout, cin y end1.
x Solamente se soportan los tipos de datos int, char y string. Pero si soporta el manejo de arreglos
de estos tipos de datos.
191
&RPSLODFLµQ
&UHDFLµQGH (MHFXFLµQGH
GHSURJUDPDV
SURJUDPDV SURJUDPDV
&RPSLODFLµQH[LWRVD
3&2'(SURJUDPDSFR
3URJUDPDFP EDFF EDLQWHUS
OLVWDGRSURJUDPDOVW
(GLWRU
GHWH[WR
(UURUHVGH
FRPSLODFLµQ
(MHFXFLµQQRDSURSLDGD
)LJXUD&,3URFHVRGHXWLOL]DFLµQGH%DFL
semaphore. Un semaphore es un valor no-negativo de una variable int que puede ser accesada
con algunas reestricciones. Los semáforos binarios(binarysem) , solo pueden tener los valores de O y
1. Las funciones de manejo de semáforos son:
x Creación de una variable de condición, esto se realiza con el tipo de datos: condition. En un
sentido estricto una variable de tipo condition no tiene un valor. Realmente es como una
especie de cola de bloqueo dónde los procesos que realizan un llamado a la operación waitc son
bloqueados y los procesos que realicen un llamado a la operación sígnalc pueden desbloquear a
algún proceso esperando en la variable de condición.
x void waitc (condition cond, int prio): el proceso que manda llamar esta operación es
bloqueado en la variable de condición cond y se le asigna la prioridad prio para iniciar un re-
levantamiento.Esta acción a otros procesos del monitor ejecutarse.
x void waitc (conditíon cond): es similar a la anterior sólo que la prioridad es por omisión de 10.
x void sígnalc (condition cond): despierta a algún proceso bloqueado en la variable de condición
cond que tenga la mayor prioridad (la prioridad mayor es la que tenga el menor número de
prioridad).
x int empty (condition cond): regresa un 1 si no existe por lo menos un proceso bloqueado en la
variable de condición cond y O de otra manera.
Un archivo fuente de Baci debe usar la extensión .cm . Para ejecutar un programa en BACI,
existen dos pasos a seguir :
a) Compilar el archivo “.cm” para obtener el archivo PCODE (.peo)
Usar: bacc [banderas-opcionales] nombre JirchivoFuente Banderas Opcionales:
C.8 Ejemplo
El programa siguiente ilustra como se puede realizar la creación de procesos. Cada proceso
incrementa una variable global. Pruebe correr dicho programa varias veces y observe los diferentes
resultados.
incremen.cm
const int m == 5;
int n;
void incr (char id)
{ inti;
for (i = 1; i < = m; i = i + 1)
{
n=n+l;
cout <<id << “ n =”<<n << “ i =”;
cout << i << “ ” << id << endi;
}
}
main()
{
n=0;
cobegin
{
incr( 'A'); incr( 'B'); inc( 'C');
}-
cout<< “La suma es “ << n <<; endl;
}
JPNS
D.l. Introducción
Este es un pequeño manual que muestra las posibilidades que brinda el Simulador de Redes de
Petri (JPNS). El JPNS fue desarrollado en la universidad de Stuttgart por Thomas Braunl. JPNS soporta
la metodología de especificación y modelación a través de Redes de Petri., soporta la representación de
Plazas, Transiciones y Arcos y disparar la Red de Petri de manera paralela o secuencial. JPNS puede
ser obtenido en http://www.ee.uwa.edu.au/~braunl
Desempaque los archivos y agregúelos a un folder. Una vez hecha esta operación, el programa
se puede ejecutar, ya sea como applet o aplicación.
Ejecuta el comando "java jpns" en el directorio en el cual haya instalado JPNS. Ejecutando el
programa como aplicación se tiene una completa funcionalidad del sw.
196
Las primeras dos opciones, las cuales son "Parallel" and "Sequentiell", especifican el modo que se
utilizará cuando se ejecute la red de petri sobre la cual se está trabajando. Se cuenta con las siguientes
opciones:
x Parallel Random: todas las transiciones disparan de manera paralela. Cuando hay dos
transiciones que están conectadas con el mismo nodo y este nodo sólo tiene un token, se activa
la opción ramdom, es decir, se ejecuta una transición activada aleatoriamente por el programa.
x Parallel Manual: se tiene la situación anterior , pero aquí el usuario decide que transición
activar.
x Sequentiell Random: las transiciones disparan una tras otra. Esta opción selecciona una
transición aleatoriamente para dispararla.
x SequentalH Manual: la misma situación de Sequentiell Random, pero aquí el usario tiene el
control de los disparos.
Las otras dos opciones de este menú son utilizadas para la salida gráfica. Si "Options" es
elegida, un cuadro de diálogo aparece, donde se puede seleccionar la opción "Show" , que pinta la
transición que se está disparando de la red de petri en ejecución y seleciona el retraso de tiempo entre
cada paso. La opción "Paintíng" le brinda al usuario la posibilidad de elegir una salida coloreada o en
blanco y negro (impresión).
ILJXUD',,FRQRGHODRSFLµQ5HO«DVH
)LJXUD',FRQRSDUD$GG1RGH
Reléase: A través de esta opción el usuario puede mover los componentes de la red de petri con
el botón izquierdo del mouse.
Add Node: El usuario puede colocar nodos con el botón izquierdo del mouse y con el derecho
mover los componentes de la red de petri.
)LJXUD',FRQRSDUD$GG7UDQVLWLRQ,
)LJXUD',FRQRSDUD$GG(GJH
Add Edge: Para dibujar las ligas da un click con el botón izquierdo del mouse sobre el
componente de inicial de la liga y otro click sobre el componente correspondiente o componente final
de la liga. De otra manera la liga no podrá llevarse a cabo. Dando click's sobre la superficie del editor el
usuario podrá darle curvaturas a la liga
)LJXUD',FRQRSDUD$GG7RNHQ
Add Token: Haciendo click con el botón izquierdo del mouse agrega tokens a un nodo. Con el
botón derecho del mouse elimina tokens de un nodo.
)LJXUD',FRQRSDUDRSFLµQ(GLW
)LJXUD',FRQRSDUD2HOHWH
Edit; Haciendo click con el botón izquierdo del mouse abre el correspondiente cuadro de
diálogo de edición para el elemento seleccionado. Aquí el usuario puede introducir nombres,
condiciones, pesos, etc.
Delete: Con un click en el botón izquierdo del mouse elimina el componente seleccionado con
todas sus propiedades.
)LJXUD',FRQRSDUDRSFLµQVXDYH
)LJXUD,FRQRSDUDODRSFLµQ0HPRUL]H
)LJXUD',2,FRQRSDUDODRSFLµQ'UDZ0HPRUL]HG
)LJXUD',FRQRSDUDODRSFLµQ6WHS
)LJXUD',FRQRSDUDODRSFLµQ6LQJOH6WHS
La barra de status informa cuales son las acciones que se están ejecutando, el modo en el cual
se está ejecutando y un contador de pasos.
La exclusión mutua es una regla de sincronización la cual especifica que los accesos a variables
o recursos compartidos deben hacerse de uno a la vez cuando tenemos procesos concurrentes. Cuando
un proceso está ejecutando el código relativo al acceso de recursos o variables compartidas se dice que
está en su SECCIÓN CRITICA. La exclusión mutua puede ser implementada por medio de diferentes
mecanismos.
3
0XWH[
6HFB 6HFB 3
, ,
)LJXUD'5HGGH3HWULSDUDPDQHMRGHH[FOXVLµQPXWXD
5. Agregue pesos a las diferentes ligas. Para hacerlo seleccione la opción "Editar" y haga
click con el botón izquierdo del mouse sobre alguna liga. Aumente el peso de la liga y
vea que se sucede. Ejecute el paso 3.
6. Guarde el ejemplo.
7. Construya los demás ejemplos, según las figuras dadas, y realice modificaciones para
ejecutarlas en modo paralelo y secuecial.
[1] G. M. Amdahl and Blair G- A., Architecture of the IBM System/360, IBM Journal do Researche
and Development, 1964.
[2] C. J. Bashe, IBMs Early Computers, MIT Press, 1986.
[3] H. M. Deitel, An Introduction to Operating Systems, Addison-Wesley Publinshig Company,
1990.
[4] H. R. Grosch, The way it was in 1957, Datamation, 1977.
[5] S. P. Harbison and G. L. Steele, C: A reference manual, Prentice Hall, 1995.
[6] T. G. Lewis, “Where is Computing Heading?”, Computer, págs. 59-63, 1994.
[7] M. Maekawa and R. R. Oldefoeft, Operating Systems, Advanced concepts, Benjamin-
Cummings, 1987.
[8] E. Iacobucci, OS/2 Programmers guide, Me Graw Hill, 1988.
[9] D. Cameron and B. Rosenblatt, Learning GNUEmacs, OReilly and Associates, 1991.
[10] P. H. Enslow, “Multiprocessor Organizatíon-A survey”, Computing Surveys, págs-103-129,
1977.
[11] S. R. Boume, The UNIX System, Addison-Wesley, 1983.
[12] E. G. Coffman and T. A. Ryan, Operating Systems Theory, Prentice Hall, 1973.
[13] P. B. Hansen, Operating System Principies, Prentice Hall, 1973.
[14] A. S. Tanenbaum, Operating Systems, design and implementaüon, Prentice Hall, 1997.
[15] A. S. Tanenbaum, Modern Operating system, Prentice Hall, 1992.
[16] M. Milenkovic, Sistemas Operativos, Me Graw Hill, 1994.
[17] M. Bach, The design ofthe Unix Operating system, Prentice Hall, 1984.
[18] K. A. Robbins, Unix Programación Práctica, Prentice Hall, 1997.
[19] E. W. Dijkstra, Co-operating sequencial processes in programming languages, Academic
Press, 1968.
[20] L. Dowdy and C. Lowery, P.S. to Operating systems, Prentice Hall, 1993.
[21] S. Kleiman S. and D. Shah and B. Smaalders, Programming with Threads, Prentice Hall, 1999.
[22] E. Nemeth and S. Seebass and T. R. Hein, UNIX System Administration Handbook, Prentice
Hall, 1995.
[23] B. W. Kemighan, The C Programming Language, Prentice Hall, 1988.
[24] P. B. Hansen, The Architecture of Concurrent Programs, Prentice Hall, 1977.
[25] R. A. Finkel, An Operating Systems Vade Mecum, Prentice Hall, 1988.
202