Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Operativos
Curso 2004-2005
Índice general
4. Gestión de Procesos 19
4.1. Definición de Proceso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.2. Estados de un Proceso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.3. Identificación de Procesos . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.4. Creación de Procesos: fork() . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.5. Ejecución de Procesos: execl() . . . . . . . . . . . . . . . . . . . . . . . . . 23
i
ii ÍNDICE GENERAL
Sólo los alumnos que superen la parte práctica podrán optar a realizar el examen de
la parte de teoría. Una vez que un alumno supera la parte práctica, queda liberado de la
misma en las siguientes convocatorias.
En las siguientes tablas se indica: el día de inicio de cada práctica, en el que se explicará
(al inicio de cada turno) el contenido de la misma; el día límite de entrega (al finalizar
el turno correspondiente); el día de corrección (en las horas correspondientes a
cada turno).
Práctica 1
Turno
Inicio Entrega Corrección
Lunes 14 Marzo 4 Abril 11 Abril
Martes 15 Marzo 29 Marzo 5 Abril
Miércoles 16 Marzo 30 Marzo 6 Abril
Jueves 17 Marzo 31 Marzo 7 Abril
Práctica 2
Turno
Inicio Entrega Corrección
Lunes 11 Abril 25 Abril 2 Mayo
Martes 5 Abril 19 Abril 26 Abril
Miércoles 6 Abril 20 Abril 27 Abril
Jueves 7 Abril 21 Abril 28 Abril
1
2 CAPÍTULO 1. EVALUACIÓN Y CALENDARIO DE PRÁCTICAS
Práctica 3
Turno
Inicio Entrega Corrección
Lunes 2 Mayo 30 Mayo 6 Junio
Martes 26 Abril 24 Mayo 31 Mayo
Miércoles 27 Abril 25 Mayo 1 Junio
Jueves 28 Abril 26 Mayo 2 Junio
Entrega de prácticas:
2.1. Práctica 1
2.1.1. Objetivos
Entender el funcionamiento de las llamadas al sistema relacionadas con la creación
de procesos (fork, execl, wait). Se recomienda leer la parte del manual relativa a
estas llamadas y realizar los programas de ejemplo que se incluyen (ver el capítulo 4
del manual). Se recomienda también leer el manual on-line de dichas llamadas al
sistema (man fork, man execl, man -a wait (o man 2 wait)).
2.1.2. Enunciado
(a) Implementar el grafo de precedencia de la figura 2.1 utilizando las llamadas al siste-
ma fork y wait (no utilizar waitpid). El grupo de sentencias a ejecutar en cada nodo
del grafo se simularán mediante la sentencia printf(“cadena”), donde “cadena” es la
cadena de caracteres que contiene cada nodo de la figura. La frase deberá aparecer
en una única línea.
3
4 CAPÍTULO 2. ENUNCIADO DE LAS PRÁCTICAS
Hola
y usted. Hasta
malos luego
Lucas
2.2. Práctica 2
2.2.1. Objetivos
Utilizar los semáforos como una herramienta de sincronización para acceder en ex-
clusión mutua a un recurso compartido. Para ello, se proporciona una librería que
permite la utilización de semáforos de una manera sencilla y similar a la explicada
en teoría (ver detalladamente el capítulo 5 del manual).
Utilizar semáforos genéricos para controlar el acceso de N procesos a un recurso.
Utilizar el sistema de ficheros como un recurso compartido entre varios procesos,
entendiendo el funcionamiento de las llamadas al sistema fopen, fprintf, fscanf y
fclose.
2.2.2. Enunciado
Implementar, mediante la utilización de semáforos el problema clásico de Santa Claus,
que se describe como sigue. Santa Claus duerme en su taller del polo norte y sólo puede
despertarse en dos circunstancias:
Cuando los 4 renos vuelven de sus vacaciones.
El último reno en llegar debe despertar a Santa Claus. Mientras, los otros 3 renos
deben esperar en un refugio a que llegue el cuarto reno y Santa Claus esté listo para
empezar el reparto de juguetes.
Cuando algún duende tiene dificultades para hacer juguetes.
Para permitir que Santa Claus duerma, los duendes sólo pueden despertarle cuando
son tres los que tienen problemas. Además, cuando tres duendes han ido a plantear
sus problemas a Santa Claus, cualquier otro duende que desee visitar a Santa Claus
debe esperar a que éstos regresen.
Si Santa Claus despierta y encuentra tres duendes en la puerta de su taller, junto
con el último reno que vuelve de vacaciones, Santa Claus decide que los duendes pueden
esperar hasta después de Navidad, y se va a repartir juguetes.
En la solución se debe proporcionar el código de los tres tipos de procesos involucrados
santa, reno y duende; así como el código de dos dos procesos encargados de crear y des-
truir los semáforos necesarios para la sincronización: inic_santa y fin_santa. Además,
se utilizarán los ficheros “duendes.txt” y “renos.txt” para almacenar la información
mínima necesaria para la resolución del problema, teniendo en cuenta que: i) el acceso al
fichero “duendes.txt” es en lectura para santa; y en lectura/escritura para los procesos
duende (los procesos reno no pueden acceder); ii) el acceso al fichero “renos.txt” es en
lectura para santa; y en lectura/escritura para los procesos reno (los procesos duende no
pueden acceder).
En la resolución de la práctica se supondrá la existencia de un único proceso santa, un
número no determinado de procesos duende y exactamente 4 procesos reno. Cada proceso
se ejecutará en una ventana diferente. A continuación, se describe el funcionamiento de
cada uno de los tres tipos de procesos.
6 CAPÍTULO 2. ENUNCIADO DE LAS PRÁCTICAS
> santa
Durmiendo .....
Voy a repartir juguetes (pulsa ENTER o 1 para finalizar)
<se pulsa ENTER>
Durmiendo .....
>santa
Durmiendo .....
Ayudo a duende
<se pulsa ENTER>
Ayudo a duende
<se pulsa ENTER>
Ayudo a duende (pulsa ENTER o 1 para finalizar)
<se pulsa ENTER>
Durmiendo .....
> reno
Estoy de vacaciones (pulsa ENTER o 1 para finalizar)
<se pulsa ENTER>
Espero en el refugio a los demás renos .....
Voy a repartir juguetes ....
Estoy de vacaciones (pulsa ENTER o 1 para finalizar)
> reno
Estoy de vacaciones (pulsa ENTER o 1 para finalizar)
<se pulsa ENTER>
Voy a repartir juguetes ....
Estoy de vacaciones (pulsa ENTER o 1 para finalizar)
2.2. PRÁCTICA 2 7
> duende
Haciendo juguetes (pulsa ENTER si tienes problemas o 1 para finalizar)
<se pulsa ENTER>
Voy en busca de ayuda ....
Resuelto el problema
Haciendo juguetes (pulsa ENTER si tienes problemas o 1 para finalizar)
> duende
Haciendo juguetes (pulsa ENTER si tienes problemas o 1 para finalizar)
<se pulsa ENTER>
Voy en busca de ayuda ....
Soy el tercer duende y despierto a Santa Claus
Resuelto el problema
Haciendo juguetes (pulsa ENTER si tienes problemas o 1 para finalizar)
8 CAPÍTULO 2. ENUNCIADO DE LAS PRÁCTICAS
2.3. Práctica 3
2.3.1. Objetivos
Utilizar una herramienta de sincronización de alto nivel como son los monitores
condicionales. Para ello, se proporciona una librería que permite la utilización de
monitores de una manera sencilla y similar a la explicada en teoría (ver detallada-
mente el capítulo 6 del manual). Además, en el manual se incluyen dos monitores
de ejemplo cuya implementación y prueba se recomienda antes de abordar esta
práctica.
Entender las diferencias existentes entre los dos tipos de monitores vistos en teoría,
en función del proceso elegido para continuar la ejecución cuando se despierta un
proceso suspendido en una variable condition.
2.3.2. Enunciado
En este problema se deberá simular mediante la utilización de un monitor fabrica la
gestión de una fabrica en la que existen empleados de dos categorías:
a) Positivo: en ese caso los dos productos pasan a la red de distribución de ventas.
b) Negativo: este resultado se obtiene cuando uno de los dos productos (el de tipo
1 o el de tipo 2) no supera el control de calidad, por lo que dicho producto se
desecha. En ese caso, es necesario que dicho empleado retire un nuevo producto
del tipo desechado, y realice un nuevo control de calidad.
Observe que, en el caso de que ambos productos fuesen defectuosos, el control de
calidad sólo detecta uno de ellos, mientras que el otro será detectado en futuros
controles —suponga que no es posible que se generen productos defectuosos de
manera indefinida.
2.3. PRÁCTICA 3 9
Los empleados de categoría B acceden al almacén en orden FIFO. Dicho orden sólo
puede romperse si no es posible realizar ningún control de calidad manteniendo el
FIFO, pero sí rompiendo dicho orden FIFO. Es decir, el objetivo es realizar el mayor
número de controles de calidad posibles.
2. Se implementará un proceso denominado empB que, una vez retirados los dos pro-
ductos necesarios para realizar el control de calidad, mostrará un menú en pantalla
con dos opciones: “a” Positivo. “b” Negativo. En el caso de seleccionar la opción “b”,
se mostrará un nuevo menú en el que se seleccionará el tipo de producto que no
superó el control de calidad: “1” Tipo 1. “2” Tipo 2. Esta operación se repetirá hasta
obtener un control positivo.
Además, antes de mostrar el menú del control de calidad, indicará mediante un
mensaje por pantalla: i) el número de elementos de cada tipo en el almacén; ii) el
número total de controles de calidad realizados hasta el momento; y iii) el número
de empleados empA que están esperando para introducir cada uno de los dos tipos
de productos.
>emp A 1
accediendo al almacen .....
Estado del almacen despues de introducir el producto:
Tipo 1: 3 elementos
Tipo 2: 0 elementos
EmpB esperando tipo 1: 0
EmpB esperando tipo 2: 4
10 CAPÍTULO 2. ENUNCIADO DE LAS PRÁCTICAS
>emp A 2
accediendo al almacen .....
Estado del almacen despues de introducir el producto:
Tipo 1: 3 elementos
Tipo 2: 1 elementos
EmpB esperando tipo 1: 0
EmpB esperando tipo 2: 4
>emp A 1
accediendo al almacen .....
Estado del almacen despues de introducir el producto:
Tipo 1: 4 elementos
Tipo 2: 0 elementos
EmpB esperando tipo 1: 1
EmpB esperando tipo 2: 1
>empB
accediendo al almacen por los dos productos .....
Estado del almacen despues de retirar los dos productos:
Tipo 1: 2
Tipo 2: 0
EmpA esperando tipo 1: 2
EmpA esperando tipo 2: 0
Numero de controles de calidad: 0
Control de Calidad:
a. Positivo
b. Negativo
>b
Producto defectuoso:
1. Tipo 1
2. Tipo 2
>1
accediendo al almacen por un producto de tipo 1 .....
Estado del almacen despues de retirar un producto de tipo 1:
Tipo 1: 1
Tipo 2: 1
EmpA esperando tipo 1: 0
EmpA esperando tipo 2: 0
Numero de controles de calidad: 3
Control de Calidad:
a. Positivo
b. Negativo
>a
Capítulo 3
El sistema operativo UNIX se desarrolló en los laboratorios Bell desde 1969, y se puede
definir como el núcleo (kernel) de un sistema operativo de tiempo compartido, un progra-
ma que controla los recursos de una computadora y los asigna entre los usuarios. Permite
a los usuarios ejecutar programas, controla los dispositivos periféricos (discos, terminales,
impresoras...), y proporciona un sistema de archivos que administra el almacenamiento a
largo plazo de información.
Por ser un sistema operativo multiusuario, para iniciar una sesión UNIX es necesario
identificarse ante el sistema. Cada usuario tiene asignado un nombre de usuario o login y
una palabra de paso o passwd.
3.1. Archivos
> ls
file1
file2
>
El comando ls, al igual que la mayoría de los comandos, tiene opciones que pueden
se utilizadas para alterar su comportamiento. Dichas opciones se teclean a continuación
del comando y, en general, están compuestas por una letra precedida del carácter -. Por
ejemplo, ls -t permite obtener un listado de los archivos por orden de antigüedad (time),
es decir, según la fecha en la que han sido alterados por última vez, empezando por el
más reciente.
La opción -l (long) permite obtener una información más completa sobre cada uno de
los archivos listados (propietario del fichero, protección, etc.)
11
12 CAPÍTULO 3. INTRODUCCIÓN AL SISTEMA OPERATIVO UNIX
> man cp
Sobre la ayuda mostrada se avanza con las mismas teclas que en el comando more.
Como, en general, puede haber más de una entrada en el manual para un mismo comando
o función, se recomienda utilizar la opción -a. De esta manera, se muestran todas las
entradas del manual existentes, pasando de una entrada a otra mediante la tecla q:
3.1.1. Directorios
El sistema puede distinguir un archivo llamado file1 de otros que tengan el mismo nom-
bre. La distinción se realiza agrupando los archivos en directorios, de manera semejante
a como se acomodan los libros en estantes de una biblioteca, por lo que los archivos en
distintos directorios pueden tener el mismo nombre sin que se produzca ningún conflicto.
Por lo general, cada usuario tiene un directorio personal o directorio de origen, que
contiene únicamente los archivos que le pertenecen. Cuando un usuario inicia una sesión
UNIX, entra en su directorio de origen.
El comando pwd nos indica el directorio actual. Para cambiar de directorio se utiliza
el comando cd. Para crear y borrar directorios existen los comandos mkdir y rmdir.
3.2. COMPILACIÓN 13
3.1.2. Disquetera
Para acceder a la disquetera se pueden utilizar las mtools. Para ello, basta con te-
clear los comandos comunes del MS-DOS con una m delante. Por ejemplo, para listar el
contenido de un disquete: mdir.
Para copiar todos los archivos a un disquete:
mcopy ‘* a:’
.
Para cargar todos los archivos de un disquete:
mcopy ‘a:*.* .’
3.2. Compilación
gcc ejemplo.c
Sin embargo, a veces interesa compilar por separado los distintos módulos y luego
juntar todos los objetos en un ejecutable. El montaje se evita con la opción -c, que genera
los ficheros objeto con extensión .o:
gcc -c ejemplo_bis.c
gcc -c lib_1.c
gcc -c lib_2.c
gcc lib_1.o lib_2.o ejemplo_bis.o -o ejemplo_bis
14 CAPÍTULO 3. INTRODUCCIÓN AL SISTEMA OPERATIVO UNIX
En el caso de que haya que montar bibliotecas ubicadas en lugares normalizados, pero
no incluidas automáticamente por el montador, hay que montarlas con la opción -l. Por
ejemplo, una compilación y montaje utilizando la librería matemática se realizaría del
siguiente modo:
Finalmente, conviene compilar todos los programas con la opción -Wall para que nos
muestre toda la información disponible warnings de la compilación:
3.3. Depuración
Para poder depurar un programa hay que indicarle al compilador que almacene in-
formación simbólica para el depurador. En el compilador gcc hay que compilar con la
opción -g:
gdb programa
Para familiarizarse con su uso se dispone de una ayuda que puede obtenerse pulsando
el mensaje help y siguiendo las instrucciones. Todas las órdenes del depurador se pueden
abreviar hasta el mínimo que no sea ambiguo. La forma más elemental de usar el depurador
es la siguiente:
4. Se lanza la ejecución del programa con run seguido de los parámetros del programa
y las posibles redirecciones de sus entradas y salidas. El programa se parará en el
main mostrando sus parámetros.
6. Si se pulsa el retorno de carro, se repite la última orden dada. Así no hay que repetir
los n o los s para ir paso a paso.
7. Si el método resulta tedioso, se puede poner un punto de parada en otro sitio con
br, indicando el nombre de la rutina o el número de línea. Se continúa hasta dicho
punto con cont.
10. En todo momento se pueden examinar variables o parte de ellas con p expresión,
donde la expresión puede ser cualquier expresión válida en C. También se pueden
modificar con set.
12. Puede examinarse el texto fuente con l (diez líneas más), l línea o l línea, línea.
13. Puede cambiarse el módulo fuente que estamos examinado con setfile. También pue-
de hacerse referencia a líneas de ficheros distintos del actual anteponiendo el nombre
del fichero y “:” al número de línea (por ejemplo, br lib_1.c:21 o l lib_2.c:17).
SYNOPSIS
#include <stdlib.h>
DESCRIPCION
system ejecuta el comando que recibe como parámetro como si éste se hubiera tecleado
desde el terminal.
VALORES RETORNADOS
16 CAPÍTULO 3. INTRODUCCIÓN AL SISTEMA OPERATIVO UNIX
EJEMPLO
SYNOPSIS
#include <stdio.h>
DESCRIPCION
popen() ejecuta el comando que recibe como parámetro, al igual que lo hacía system,
pero además establece un pipe de comunicación entre el comando ejecutado y el proceso
que ha ejecutado el popen(). Dicho pipe se establece igual que un fichero, sobre el que se
pueden realizar operaciones de lectura y/o escritura.
VALORES RETORNADOS
EJEMPLO
#include <stdio.h>
#include <stdlib.h>
int main() {
3.4. LLAMADAS AL SISTEMA 17
if ((fich = popen("ps -ax | grep -v grep | grep \" init \" ", "r"))
== NULL) {
printf("Error al ejecutar el ps\n");
exit(1);
}
fscanf(fich, "%d", &pid);
pclose(fich);
if (pid == -1) printf("No existe el proceso init\n");
else printf("El PID del proceso init es: %d\n", pid);
return(0);
}
18 CAPÍTULO 3. INTRODUCCIÓN AL SISTEMA OPERATIVO UNIX
Capítulo 4
Gestión de Procesos
Si se realiza espera activa, cada vez que el sistema operativo le asigne la CPU a
dicho proceso, éste “mirará” el teclado a ver si se ha pulsado una tecla, y esto lo repetirá
hasta que dicho evento se produzca. Durante todo ese tiempo, el proceso está consumiendo
innecesariamente CPU. Para evitar la espera activa, los procesos se suspenden a espera
de eventos, de manera que dichos procesos no entren en el reparto de la CPU.
19
20 CAPÍTULO 4. GESTIÓN DE PROCESOS
Suspendidos (S): A dichos procesos les falta, además de la CPU, algún recurso
para poder ejecutarse, entendiéndose por recurso un dispositivo, un dato, etc. Los
procesos suspendidos están esperando a que ocurra algún evento para poder acceder
al recurso que necesitan. Estos procesos no entran en el reparto de la CPU, evitando
así la espera activa. Cuando se produce el evento esperado, dicho proceso pasará a
estar preparado.
Parados (T): Son procesos que tampoco entran en el reparto de la CPU, pero
que no están suspendidos a la espera de eventos, sino que han sido parados en su
ejecución. Para salir de dicho estado hay que mandarles continuar, volviendo así a
estar preparados.
PARADO
COLA DE PROCESOS
PREPARADOS EJECUTANDO ZOMBI
SUSPENDIDO
correspondientes a un usuario usr1: ps -aux | grep usr1. Se recomienda ver el manual (man
ps).
RSS: Kilobytes del programa en memoria. (El resto estará en disco (swapp)).
Los procesos pueden tener una estructura jerárquica, de manera que un proceso (pro-
ceso padre) puede crear un nuevo proceso (proceso hijo) y así sucesivamente. Para la
realización de aplicaciones con varios procesos, el sistema operativo unix proporciona la
llamada al sistema1 fork().
SYNOPSIS
#include <sys/types.h>
#include <unistd.h>
int fork(void);
DESCRIPCION
fork() crea un nuevo proceso exactamente igual (mismo código) al proceso que invoca
la función. Ambos procesos continúan su ejecución tras la llamada al fork().
1
Funciones que se pueden invocar desde un programa en C, y que realizan una llamada al sistema
operativo.
22 CAPÍTULO 4. GESTIÓN DE PROCESOS
VALORES RETORNADOS
En caso de error retorna -1 y no se crea el proceso hijo. En otro caso, retorna valores
diferentes al proceso padre (el que lo invocó) y al proceso hijo (el proceso creado):
Proceso Padre: Retorna el PID del proceso hijo.
Proceso Hijo: Retorna 0.
EJEMPLO
En el ejemplo que se muestra a continuación, se crea un proceso hijo que imprime en
pantalla el PID de su proceso padre, mientras que el proceso padre imprime en pantalla
su propio PID y el del proceso hijo que ha creado. Para ello, se utilizan las llamadas al
sistema getpid() y getppid(). El proceso padre, antes de finalizar se suspende hasta que el
hijo muere, para evitar que éste se quede zombi. Para ello, utiliza la llamada al sistema
wait(), que recibe en la variable status el estado en que el proceso hijo finalizó.
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
int pid = 0, status = 0, pid_hijo_finalizado = 0;
SYNOPSIS
#include <unistd.h>
DESCRIPCION
execl() sustituye la imagen del proceso actual por la del proceso cuyo código se indica
como parámetro. Comprobar que las sentencias posteriores a un execl() no se ejecutan si
dicha función ha tenido éxito (ya que se ha sustituido la imagen del proceso). Es decir,
después de una llamada a execl() sólo tiene sentido comprobar si se ha producido algún
error en la llamada.
PARAMETROS
VALORES RETORNADOS
EJEMPLO
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
24 CAPÍTULO 4. GESTIÓN DE PROCESOS
#include <stdlib.h>
int main() {
int pid = 0, status = 0;
#include <stdio.h>
Utilización de Semáforos en el
Laboratorio
#include <cipcms.h>
int main() {
semaforo_t s;
25
26 CAPÍTULO 5. UTILIZACIÓN DE SEMÁFOROS EN EL LABORATORIO
.........................
sem_destruir(s);
return(0);
}
#include <cipcms.h>
int main() {
semaforo_t s;
de cada uno de estos comandos. A partir del comando ipcs se obtienen los identificado-
res de los ipcs activos, y con el comando ipcrm [sem id] [shm id] [msg id] se eliminan los
ipcs correspondientes a semáforos (sem), memoria compartida (shm) y colas de mensajes
(msg).
Finalmente, se recomienda comprobar todos los posibles errores producidos en las lla-
madas a las funciones de manejo de semáforos. En la mayoría de los casos, éstas retornan
un valor negativo en caso de error. (Ver fichero /opt/ipcms/include/cipcms.h).
3. Si quedase algún proceso gestor, debe ser eliminado con el comando Kill pid.
>ipcs
Utilización de monitores en el
laboratorio
tipo: 1
condicionales: lleno, vacio
publicos: procedimiento_1, procedimiento_3, procedimiento_4, procedim
iento_5,
inicio: inicio
fin: fin
29
30 CAPÍTULO 6. UTILIZACIÓN DE MONITORES EN EL LABORATORIO
#include <stdio.h>
int procedimiento_1()
{
}
3. Compile dicho programa con la librería lipcmsint y la librería del sistema lpthread:
#include <cipcms.h>
#include <stdio.h>
31
int main () {
#include <stdio.h>
#include <cipcms.h>
int main() {
if (mon_destruir(mon_capturar(2000)) < 0)
printf("error al destruir\n");
else printf("monitor destruido\n");
return(0);
}
6. Para utilizar dicho monitor desde un programa en C, declarar una variable de tipo
monitor_t, capturar su descriptor a partir de la clave con la que se creó, e invocar
a los procedimientos del monitor con la función.
int monitorint(monitor_t, char *)
#include <stdio.h>
#include <cipcms.h>
int main() {
monitor_t mi_monitor;
int n = 0;
mi_monitor = mon_capturar(2000);
........
........
n = monitorint(mi_monitor, "procedimiento_1");
return(0);
}
Estos programa se compilan con la librería ipcms, al igual que los programas que
utilizan semáforos y necesitan la ejecución previa del proceso gestoripcms.
32 CAPÍTULO 6. UTILIZACIÓN DE MONITORES EN EL LABORATORIO
7. Para utilizar las variables de tipo condition declaradas en la cabecera existen las
funciones:
int mi_sem_wait() {
if (n == 0)
condm_wait(cola_sem);
else
n--;
return(0);
}
int mi_sem_signal() {
if (! condm_empty(cola_sem))
condm_signal(cola_sem);
else {
if (n == N) return(1); /* error */
n++;
}
return(0);
}
6.1. MONITOR EJEMPLO 33
void mi_inic_sem()
void mi_fin_sem()
return;
}
::::::::::::::
ej_inic.c
::::::::::::::
#include <cipcms.h>
#include <stdio.h>
int main() {
::::::::::::::
ej_fin.c
::::::::::::::
#include <cipcms.h>
#include <stdio.h>
int main() {
if (mon_destruir(mon_capturar(2004)) < 0)
printf("No se pudo destruir el monitor\n");
else
printf("Monitor finalizado\n");
return(0);
}
34 CAPÍTULO 6. UTILIZACIÓN DE MONITORES EN EL LABORATORIO
::::::::::::::
ej_proc.c
::::::::::::::
#include <cipcms.h>
#include <stdio.h>
int main() {
int resultado = 0;
monitor_t mon_sem;
} while (1);
return(0);
}
36 CAPÍTULO 6. UTILIZACIÓN DE MONITORES EN EL LABORATORIO
1. Fichero buffer.mon:
tipo: 1
condicionales: vacio, lleno
publicos: producir, consumir
inicio: iniciar
fin: finalizar
#include <stdio.h>
#include <stdlib.h>
#define N 4
void iniciar(void) {
ptr_prod = 0;
ptr_cons = 0;
num_datos = 0;
buffer[0]=0;
buffer[1]=0;
buffer[2]=0;
buffer[3]=0;
}
void finalizar(void)
{
return;
}
3. Compile dicho programa con la librería lipcms y la librería del sistema lpthread:
#include <cipcms.h>
#include <stdio.h>
int main () {
#include <stdio.h>
#include <cipcms.h>
int main() {
if (mon_destruir(mon_capturar(1234)) < 0)
printf("error al destruir\n");
else printf("monitor destruido\n");
return(0);
}
6. Para utilizar dicho monitor desde un programa en C, declarar una variable de tipo
monitor_t, capturar su descriptor a partir de la clave con la que se creó, e invocar
a los procedimientos del monitor con la función.
***********
productor.c
***********
#include <stdio.h>
#include <stdlib.h>
#include <cipcms.h>
int main() {
monitor_t m;
int dato=3;
if ((m = mon_capturar(1234))<0)
{
printf("Error al capturar el monitor\n");
exit(-1);
}
printf("Producir elemento:");
fscanf(stdin,"%d", &dato);
monitor(m, "producir", sizeof(int), 0, (void *)&dato);
return(0);
}
************
6.2. MONITORES CON PASO DE PARÁMETROS 39
consumidor.c
************
#include <stdio.h>
#include <stdlib.h>
#include <cipcms.h>
int main() {
monitor_t m;
int *dato;
if ((m = mon_capturar(1234))<0)
{
printf("Error al capturar el monitor\n");
exit(-1);
}
dato = (int *) (monitor(m,"consumir", 0, sizeof(int), NULL));
printf("Consumido %d\n",*dato);
free(dato);
return(0);
}
Estos programa se compilan con la librería ipcms, al igual que los programas que
utilizan semáforos y necesitan la ejecución previa del proceso gestoripcms.