Enunciado.
El programa que hay que presentar constará de un único
fichero fuente de nombre Tolkien.c
. La
correcta compilación de dicho programa, producirá un
fichero ejecutable, cuyo nombre será obligatoriamente
Tolkien
. Respetad las mayúsculas/minúsculas
de los nombres.
La ejecución del programa creará una serie de procesos
cuya vida está inspirada en los personajes de "El señor
de los anillos". Los personajes que aparecerán se describen
a continuación:
- Tolkien:
- Es el proceso que nace al ejecutar la
aplicación. A partir de él, se generarán
todos los demás.
- El proceso Tolkien crea a los procesos
Smeagol, Deagol,
Drogo, Primula, Elrond y Celebrian.
Este y otros personajes los nombraréis
en vuestro programa
tal cual están escritos aquí, sin ningún
tipo de acento y con la primera letra sólo
en mayúsculas,
para evitar problemas.
- Tolkien espera por la muerte de todos los procesos
que ha creado, sin consumir CPU.
- Además, obtendrá como código de retorno
los años que han vivido Frodo y Arwen
de sus madres y lo imprimirá por la pantalla,
del siguiente modo:
TOLKIEN: "Frodo ha muerto y vivió 101 años".
TOLKIEN: "Arwen ha muerto y vivió 678 años".
- Tolkien devuelve cero al sistema operativo
si todo se ejecuta normalmente.
- Smeagol:
- Esperará hasta recibir la señal SIGALRM.
Se enviará manualmente desde otro terminal
con la orden
kill
cuando se
ejecute la práctica.
- Debe matar a su hermano Deagol.
- Cambiará a continuación de nombre. Lo conocerán
a partir de entonces como Gollum.
- Pasará el anillo único (SIGUSR2) a Frodo.
- Esperará a recibir de vuelta el anillo
de Frodo (SIGUSR2) y morirá, devolviendo
0 a Tolkien.
Las esperas serán sin consumo de CPU.
- Deagol:
- Esperará, sin consumir CPU, a que lo mate
su hermano Gollum, por aquel entonces conocido
como Smeagol.
- Drogo:
- Es un hobbit.
- Tendrá como hijo a Frodo y, como se explica
más abajo, le matarán.
- Primula:
- Es una hobbit.
- Tendrá, junto con Drogo, como hijo a Frodo.
El proceso de procreación se explica más abajo.
- Esperará por la muerte de su hijo Frodo,
que le dirá cuántos años ha vivido y se
lo pasará como código de retorno a Tolkien.
- Frodo:
- Es un hobbit, hijo de Drogo y Primula.
- Esperará a recibir el anillo (SIGUSR2) de
Gollum y el apoyo moral (SIGALRM) de
Arwen, en cualquier orden.
- Devuelve, a continuación, el anillo único
a Gollum (SIGUSR2).
- Duerme 10 segundos (usad
sleep()
).
- Vive un número de años aleatorio entre 90 y
120. Muere, y le comunica la edad en que ha
muerto a su madre Primula como código de retorno.
- Elrond:
- Es un elfo.
- Procrea con Celebrian y tienen a Arwen.
Muere como se explica más abajo.
- Celebrian:
- Es la mujer del elfo Elrond.
- Tienen a Arwen.
- Espera a que Arwen muera, toma su edad y
se la pasa a Tolkien, al morir de pena
por la muerte de su hija.
- Arwen:
- Es hija de Elrond y Celebrian.
- Duerme 20 segundos (usad
sleep()
).
- Le da consejo (SIGALRM) a Frodo.
- Dormirá 15 segundos, acto seguido.
Usad
sleep()
.
- Debido a que se casa con el mortal Aragorn
(alias Trancos, que no aparece en la práctica),
se vuelve mortal y muere a una edad al azar
comprendida entre 601 y 730 años.
Devuelve la edad a la que ha muerto a su madre,
Celebrian.
El mecanismo de procreación, tanto para elfos como para hobbits,
consistirá en los siguientes pasos:
- La parte femenina de la pareja mostrará su disponibilidad
para la procreación enviando la señal SIGUSR1 a su
pareja.
- La parte masculina, una vez recibida la señal, responde
a su pareja enviando la señal SIGUSR1.
- La parte femenina decide cuántas veces se ha de repetir
los dos pasos anteriores al azar (entre 2 y 11, úsese
la función
rand()
).
- Una vez satisfecha, y como no necesita más de la parte
masculina, le envía la señal SIGTERM. Su pareja muere,
por consiguiente.
- La parte femenina, finalmente, tiene un proceso hijo.
La única diferencia en el proceso de procreación de hobbit y
elfos está en que los elfos lo realizan
sin consumir CPU mientras que los hobbits
(al igual que los humanos, por cierto) sí que la consumen y
realizan espera ocupada.
Los procesos tienen que aparecer bajo la orden ps
-f
con su nombre. Esto significa que será necesario
usar una llamada de la familia exec
para
reemplazar argv[0]
, aunque vayamos a ejecutar
el mismo ejecutable. Esto os servirá también para que
vuestro código diferencie qué personaje se está ejecutando
en cada momento. Se deja a vuestra libertad el añadir más
argv
s, si lo consideráis necesario.
Siempre que en el enunciado se diga que se puede usar
sleep()
, se refiere a la llamada al sistema,
no a la orden de la línea de órdenes.
Para generar números aleatorios comprendidos entre un valor
bajo
y otro alto
, ambos inclusive,
podéis usar la siguiente función:
#include <stdlib.h>
#include <sys/types.h>
#include <time.h>
[...]
int azar(int bajo,int alto)
{
static int primeraVez=(0==0);
if (primeraVez) {srand(time(NULL)); primeraVez=!primeraVez;}
return rand()/(RAND_MAX+1.0)*(1+alto-bajo)+bajo;
}