› Foros › PC › Software libre
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
// Practica final I.
// Sistemas Operativos.
// *************************
// * INSTRUCCIONES DE USO! *
// *************************
// Para compilar este programa escribir:
//
// gcc hotelMascotas.c -lpthread -o hotelMascotas
// Para ejecutar el programa hacer:
//
// ./hotelMascotas &
//
// El numero que sale en la consola es el PID del proceso que se utilizara para enviar senyales al mismo!
// (ver abajo)
// *******************
// * Para subir nota *
// *******************
// Es posible pasar dos parametros al programa (se pueden pasar ambos, uno solo, o ninguno, y en cualquier orden!):
// -e NUMERO -> numero de empleados que atenderan llamadas
// -c NUMERO -> numero maximo de clientes en la cola (capacidad de la cola de clientes en espera)
// Esto corresponde al punto 3 (Asignación estática de recursos) para subir nota.
// Ejemplos:
//
// ./hotelMascotas -e 5 &
//
// ./hotelMascotas -c 12 -e 5 &
//
// Al comenzar a ejecutarse, el programa queda a la espera de senyales:
// - Para poder enviar una senyal al mismo, necesitamos su PID, lo sacamos con el comando:
//
// ps (y miramos el PID del proceso "hotelMascotas")
//
// ... o mas directo, ejecutamos el comando:
//
// ps | grep hotelMascotas | cut -d'p' -f1
//
// - Una vez se tiene el PID, se envia la senyal que queramos al programa con kill -NUMERO_SEGNYAL PID
// El programa reconoce las siguientes senyales:
//
// - SIGUSR1 (10) : simula la llegada de una llamada de un cliente con perro
// - SIGUSR2 (11) : simula la llegada de una llamada de un cliente con gato
//
// Ejemplos de como enviar llamadas con un solo comando:
//
// pid=`ps | grep hotelMascotas | cut -d'p' -f1`; kill -10 $pid
// *****************************************************
// * Definicion de constantes y declaraciones globales *
// *****************************************************
// Valores por defecto (ver pdf)
const int NUMERO_CLIENTES_POR_DEFECTO = 6;
const int NUMERO_EMPLEADOS_POR_DEFECTO = 3;
// Semaforos:
// - mutexCola sera el semaforo para la cola de clientes
// - mutexLog sera el semaforo para evitar que dos procesos intenten escribir una linea de log a la vez
pthread_mutex_t mutexCola;
pthread_mutex_t mutexLog;
// Numero de clientes del hotel de mascotas en un momento dado
int numeroClientes;
// Numero de clientes que han llamado al hotel de mascotas hasta el momento
int numeroClientesQueHanLlamado;
// Maximo numero de clientes que puede atender el hotel de mascotas (podra ser modificado)
int maximoNumeroClientes;
typedef struct {
// Identificador de usuario
int id;
// Flag que indica si un cliente esta siendo atendido o no
int atendido;
// Tiempo en segundos que el cliente ha sido atendido por un empleado
int segundosAtendido;
// Tiempo en segundos que el cliente tuvo que esperar antes de ser atendido por un empleado
int segundosEsperados;
// Hilo que ejecuta las acciones (esperar a que le atiendan) de un cliente
pthread_t hilo;
} informacionCliente;
// Lista de los Clientes en espera en el hotel (inicialmente habra espacio para 10 clientes, pero podra ser modificado).
informacionCliente *listaClientes;
// Numero de empleados que trabajan en el hotel de mascotas
int numeroEmpleados;
typedef struct {
// Identificador de empleado
int id;
// Hilo que ejecuta las acciones de un empleado
pthread_t hilo;
} informacionEmpleado;
// Lista de los empleados del hotel (inicialmente habra espacio para 3 clientes, pero podra ser modificado).
informacionEmpleado *listaEmpleados;
// Fichero de log
FILE *ficheroLog;
// Nombre del fichero de log
const char *NOMBRE_FICHERO_LOG = "hotelMascotas.log";
// *****************************************************
// * Funciones y procedimientos *
// *****************************************************
// Escribe una nueva linea de log con el mensaje e identificador
// recibidos como parametros.
void escribirNuevaLineaLog(char *identificador, char *mensaje) {
// Protegemos mediante el semaforo de log
pthread_mutex_lock(&mutexLog);
// Calculamos la hora actual
time_t now = time(0);
struct tm *tlocal = localtime(&now);
char stnow[19];
strftime(stnow, 19, "%d/%m/%y %H:%M:%S", tlocal);
// Escribimos en el log
ficheroLog = fopen(NOMBRE_FICHERO_LOG, "a");
fprintf(ficheroLog, "[%s] %s: %s\n", stnow, identificador, mensaje);
fclose(ficheroLog);
// Desbloqueamos el semaforo
pthread_mutex_unlock(&mutexLog);
}
// Elimina de listaClientes el cliente en el indice indicado. Si no existiera, no se hace nada
void eliminarClienteDeLaLista(int indice) {
// Quien llame a esta parte del codigo debera protegerse tambien para evitar que se intenten eliminar o incluir clientes al mismo tiempo
int i = 0;
// Para borrar, asignamos a la posicion "i" los datos de la posicion "i+1","i+1" los de la posicion "i+2" y asi hasta el final.
for (i=indice; i<numeroClientes-1;i++)
listaClientes[i] = listaClientes[i+1];
// El ultimo elemento de la lista pasa a estar vacio
listaClientes[numeroClientes-1].id = 0;
listaClientes[numeroClientes-1].hilo = 0;
// Se reduce en 1 el numero de clientes, y tambien el valor del indice 'i'
// ya que acabamos de eliminar el elemento al que apuntabda
numeroClientes--;
}
// Funcion que obtiene el indice que ocupa un cliente en la cola dado su identificador (llamada protegida por un semaforo).
int obtenerIndiceEnLaCola (int idCliente) {
int i = 0;
for (i = 0; i < numeroClientes; i++)
if (listaClientes[i].id == idCliente)
return i;
// Si llegamos aqui el cliente no esta en la lista: devolvemos -1
return -1;
}
// Funcion que devuelve el numero de cliente desatendidos
int obtenerNumeroClientesDesatendidos() {
int numeroDesatendidos = 0;
int i = 0;
pthread_mutex_lock(&mutexCola);
for (i = 0; i < numeroClientes; i++)
//El cliente que este desatendido debe de tener flag "atendido" y segundosAtendido = 0 para evitar que cuando un cliente deja de ser atendido
//(su flag "atendido" seria 0 en ese momento) sea atendido por otro empleado.
if ((listaClientes[i].atendido == 0) && (listaClientes[i].segundosAtendido == 0))
numeroDesatendidos++;
pthread_mutex_unlock(&mutexCola);
return numeroDesatendidos;
}
// Funcion que ejecuta cada uno de los empleados (que seran a su vez hilos)
void *accionesEmpleado(void *idEmpleado) {
// Variable para poder combinar caracteres y numeros antes de incluir la linea en el log
char mensajeLog[200];
// Variable para saber si un empleado tiene un cliente al que atender
int tengoCliente = 0;
// Datos del cliente al que se atendera (sera una copia del cliente en la cola)
informacionCliente infoCliente;
// En el parametro idCliente recibimos el identificador del empleado, pero hay que hacer un cast
int identificador = (int) idEmpleado;
// El identificador del empleado completo sera (ver especificacion) la palabra "empleado_" seguida de este numero
char identificadorCompleto[9];
sprintf(identificadorCompleto,"Empleado_%d", identificador);
// El empleado queda en un bucle infinito esperando llamadas entrante y atendiendolas en orden de antiguedad cuando se produzcan.
while (1) {
sprintf(mensajeLog, "Permanece a la espera para atender una llamada");
escribirNuevaLineaLog(identificadorCompleto, mensajeLog);
// Buscamos el cliente que lleva mas tiempo esperando (que sera el de menor valor del campo .id de la listaClientes).
while (obtenerNumeroClientesDesatendidos() <= 0) {
sleep(1);
}
// Protegemos esta zona del codigo para evitar que varios empleados "se lancen" sobre el mismo cliente
pthread_mutex_lock(&mutexCola);
// Sabemos que hay al menos un cliente desatendido en la lista.
// Cogemos el que lleva mas tiempo en la cola (ya que es una cola FIFO):
// Empezamos a buscar en el indice 0
int indice = 0;
// El cliente a atender no puede estar siendo atendido (atendido == 1) ni tampoco puede acabar de ser atendido (segundosAtendido > 0)
while ((indice < numeroClientes) && ((listaClientes[indice].atendido == 1) || (listaClientes[indice].segundosAtendido > 0))) {
indice++;
}
// Si encontramos algun cliente sin atender, lo atendemos
if (listaClientes[indice].atendido == 0) {
// Indicamos que hemos encontrado un cliente que atender!
tengoCliente = 1;
// Un empleado atiende a un cliente un tiempo aleatorio entre 30 y 50 segundos (ver pdf)
// Con rand()%21 generamos un numero aleatorio entre 0 y 20, y le sumamos 30 para que quede entre 30 y 50 segundos
listaClientes[indice].segundosAtendido = rand()%21 + 30;
// Registramos la hora de inicio de la conversacion
sprintf(mensajeLog, "Comienza a atender la llamada de Cliente_%d", listaClientes[indice].id);
escribirNuevaLineaLog(identificadorCompleto, mensajeLog);
// Cambiamos el flag
listaClientes[indice].atendido = 1;
// Guardamos estos datos de cliente en la variable local infoCliente
infoCliente = listaClientes[indice];
}
// ya paso el peligro de concurrencia, desbloqueamos el mutex
pthread_mutex_unlock(&mutexCola);
if (tengoCliente) {
sleep(infoCliente.segundosAtendido);
// Registramos la hora de finalizacion de la conversacion
sprintf(mensajeLog, "La llamada de Cliente_%d ha finalizado tras %d segundos siendo atendido", infoCliente.id, infoCliente.segundosAtendido);
escribirNuevaLineaLog(identificadorCompleto, mensajeLog);
// Una vez se termina de atender al cliente, volvemos a poner el flag de atendido a false para que el hilo del cliente pueda terminar
pthread_mutex_lock(&mutexCola);
// Hay que volver a buscar el indice del cliente, no sea que haya cambiado de posicion en la cola
// en caso de que otros clientes hayan salido ya de esta
indice = obtenerIndiceEnLaCola (infoCliente.id);
listaClientes[indice].atendido = 0;
pthread_mutex_unlock(&mutexCola);
}
// Una vez se termina de atender al cliente, el empleado queda sin cliente.
tengoCliente = 0;
} // Fin del bucle infinito de atencion de llamdas
// Si alguna vez llegaramos a esta linea (que nunca sera asi), terminariamos el hilo
pthread_exit(NULL);
}
// Funcion que indica si un cliente (dado su identificador) esta atendido o no
int estaAtendido (int identificador) {
int atendido = 0;
// Busca en la lista el cliente con ese identificador y comprueba si esta atendido.
// Como todo lo que busque en la cola requiere semaforo
pthread_mutex_lock(&mutexCola);
int i = 0;
for (i = 0; i < numeroClientes; i++)
if ((listaClientes[i].id == identificador) && (listaClientes[i].atendido == 1))
atendido = 1;
pthread_mutex_unlock(&mutexCola);
return atendido;
}
// Funcion que indica el numero de segundos que el cliente ha sido atendido
int obtenerSegundosAtendido (int identificador) {
int segundosAtendido = 0;
pthread_mutex_lock(&mutexCola);
int i = 0;
for (i = 0; i < numeroClientes; i++)
if (listaClientes[i].id == identificador)
segundosAtendido = listaClientes[i].segundosAtendido;
pthread_mutex_unlock(&mutexCola);
return segundosAtendido;
}
void *accionesCliente(void *idCliente) {
// Variable para poder combinar caracteres y numeros antes de incluir la linea en el log
char mensajeLog[200];
// En el parametro idCliente recibimos el identificador del clinte, pero hay que hacer un cast
int identificador = (int) idCliente;
// El identificador del cliente completo sera (ver pdf) la palabra "cliente_" seguida de este numero
char identificadorCompleto[9];
sprintf(identificadorCompleto,"Cliente_%d", identificador);
sprintf(mensajeLog, "Esta a la espera de ser antendido");
escribirNuevaLineaLog(identificadorCompleto, mensajeLog);
// Segundos de duracion de la llamada (si es que llegan a atenderle)
int numeroSegundosConversacion = 0;
// Calculamos tiempo de espera (tiempo que el cliente esperara antes de colgar)
// (ver pdf)
int numeroSegundosEsperados = 0;
int maximoSegundosAEsperar;
//- El 20% de los usuarios cuelgan transcurridos 2 minutos.
//- El 30% de los usuarios cuelgan transcurridos 3 minutos.
//- El resto de los usuarios cuelgan transcurridos 5 minutos.
int numeroDel0al100 = rand()%100;
if (numeroDel0al100 < 20)
maximoSegundosAEsperar = 120;
else if ((numeroDel0al100 >= 20) && (numeroDel0al100 < 30))
maximoSegundosAEsperar = 180;
else
maximoSegundosAEsperar = 300;
// Esperamos segundo a segundo hasta que lleguemos al maximo de segundos a esperar
// o hasta que un empleado nos atienda
while ((numeroSegundosEsperados < maximoSegundosAEsperar)&&(!estaAtendido(identificador))) {
sleep(1);
numeroSegundosEsperados++;
}
// Si se llega hasta aqui, es porque ha colgado o porque le han atendido:
// Si numeroSegundosEsperados < maximoSegundosAEsperar = cliente atendido.
// Primero almacenamos el tiempo que se ha esperado realmente.
// hay que volver a buscar el indice que ocupamos en la cola por si esta ha cambiado
pthread_mutex_lock(&mutexCola);
int indice = obtenerIndiceEnLaCola (identificador);
listaClientes[indice].segundosEsperados = numeroSegundosEsperados;
pthread_mutex_unlock(&mutexCola);
if (numeroSegundosEsperados >= maximoSegundosAEsperar) {
sprintf(mensajeLog, "Ha colgado tras esperar %d segundos.",numeroSegundosEsperados);
}
else {
// Un empleado esta atendiendo al hilo: esperamos a que termine de atendernos
while (estaAtendido(identificador))
sleep (1);
// Indicamos que el tiempo total de llamada para el hilo
sprintf(mensajeLog, "La duracion total de la llamada ha sido %d segundos de espera y %d segundos siendo atendido.", numeroSegundosEsperados, obtenerSegundosAtendido(identificador));
}
// Imprimimos el mensaje de log que corresponda y terminamos
escribirNuevaLineaLog(identificadorCompleto, mensajeLog);
pthread_mutex_lock(&mutexCola);
// Hay que volver a buscar el indice del cliente, no sea que haya cambiado de posicion en la cola
// en caso de que otros clientes hayan salido ya de esta
indice = obtenerIndiceEnLaCola (identificador);
eliminarClienteDeLaLista(indice);
pthread_mutex_unlock(&mutexCola);
pthread_exit(NULL);
}
void perro() {
// Todo este procedimiento debe protegerse mediantes semaforo.
pthread_mutex_lock(&mutexCola);
// Comprobamos si hay espacio en la lista de clientes (si no lo hay, se pone en espera)
if (numeroClientes < maximoNumeroClientes) {
// El identificador del cliente coincide con el numero de clientes + 1 (evitar que el primer cliente tenga id = 0).
listaClientes[numeroClientes].id = numeroClientesQueHanLlamado + 1;
listaClientes[numeroClientes].atendido = 0;
listaClientes[numeroClientes].segundosAtendido = 0;
listaClientes[numeroClientes].segundosEsperados = 0;
// Creamos un hilo cliente (en el que permanecera a la espera y puede llegar a colgar)
pthread_create(&listaClientes[numeroClientes].hilo, NULL, accionesCliente, (void *)listaClientes[numeroClientes].id);
// Incrementamos numero de clientes
numeroClientes++;
// y el numero de clientes que han llamado
numeroClientesQueHanLlamado++;
}
else {
// No habia espacio!!
// por lo demas, la llamada se ingnora
}
// Se debloquea el semaforo
pthread_mutex_unlock(&mutexCola);
}
void gato() {
// Todo este procedimiento debe protegerse mediantes semaforo.
pthread_mutex_lock(&mutexCola);
// Comprobamos si hay espacio en la lista de clientes (si no lo hay, se pone en espera)
if (numeroClientes < maximoNumeroClientes) {
// El identificador del cliente coincide con el numero de clientes + 1 (evitar que el primer cliente tenga id = 0).
listaClientes[numeroClientes].id = numeroClientesQueHanLlamado + 1;
listaClientes[numeroClientes].atendido = 0;
listaClientes[numeroClientes].segundosAtendido = 0;
listaClientes[numeroClientes].segundosEsperados = 0;
// Creamos un hilo cliente (en el que permanecera a la espera y puede llegar a colgar)
pthread_create(&listaClientes[numeroClientes].hilo, NULL, accionesCliente, (void *)listaClientes[numeroClientes].id);
// Incrementamos numero de clientes
numeroClientes++;
// y el numero de clientes que han llamado
numeroClientesQueHanLlamado++;
}
else {
// No habia espacio!!
// por lo demas, la llamada se ingnora
}
// Se debloquea el semaforo
pthread_mutex_unlock(&mutexCola);
}
void crearHilosEmpleados() {
// Creamos un hilo para cada empleado
int i = 0;
for (i = 0; i < numeroEmpleados; i++)
pthread_create(&listaEmpleados[i].hilo, NULL, accionesEmpleado, (void *)listaEmpleados[i].id);
}
void inicializarListaClientes() {
// Reserva dinamica de memoria para la lista de clientes por si cambia su tamanio en el futuro
listaClientes = (informacionCliente *)malloc(maximoNumeroClientes*sizeof(informacionCliente));
int i = 0;
for (i = 0; i < maximoNumeroClientes; i++){
// inicializamos el identificador a 0
listaClientes[i].id = 0;
listaClientes[i].atendido = 0;
listaClientes[i].segundosAtendido = 0;
listaClientes[i].segundosEsperados = 0;
}
}
void inicializarListaEmpleados() {
// Reserva dinamica de memoria para la lista de empleados por si cambia su tamanyo en el futuro
listaEmpleados = (informacionEmpleado *)malloc(numeroEmpleados*sizeof(informacionEmpleado));
int i = 0;
for (i = 0; i < numeroEmpleados; i++) {
// Los empleados, a diferencia de los clientes, existen desde el principio
// y nunca dejan de existir durate la duracion del programa, por lo que indicamos ya su identificador real.
listaEmpleados[i].id = i + 1;
}
}
void cambiarMaximoNumeroClientes (int nuevoMaximo) {
maximoNumeroClientes = nuevoMaximo;
// Como va a cambiar el numero de clientes de listaClientes,
// liberamos la lista anterior y la creamos de nuevo
free(listaClientes);
inicializarListaClientes();
//Indicamos que, al reiniciar la lista, se han perdido los clientes.
numeroClientes = 0;
numeroClientesQueHanLlamado = 0;
}
//Funcion nueva para cambiar el maximo numero de empleados (07/01/2013)
void cambiarMaximoNumeroEmpleados (int NuevoMaximo1) {
if(NuevoMaximo1 > 3){
int MaximoNumeroEmpleados = NuevoMaximo1;
// Como va a cambiar el numero de empleados de listaEmpleados,
// liberamos la lista anterior y la creamos de nuevo
free(listaEmpleados);
inicializarListaEmpleados();
numeroEmpleados = 0;
char mensaje[250];
sprintf(mensaje,"El numero de empleados es ahora de %d .", MaximoNumeroEmpleados);
escribirNuevaLineaLog("main", mensaje);
}
}
// Devuelve 1 si todos los caracteres de la cadena recibida son numeros
// Para comprobar si un caracter es numero o no, el codigo esta sacado de aqui:
// http://www.dreamincode.net/forums/topic/53355-c-check-if-variable-is-integer/
int esNumero (char *cadena) {
// Si atoi (ASCII to integer) da distinto de 0, es porque es un numero, y devolveriamos 1 (esNumero = true).
// Si da 0, es una letra (o el numero 0, pero ese no nos sirve), asi que devolveriamos 0.
if (atoi(cadena) != 0)
return 1;
else
return 0;
}
// Inicializa las variables.
// Implementamos la funcionalidad extra 3: asignacion estatica de recursos,
// es decir, permitimos pasar como parametros numero de llamadas y numero de empleados
// (ver instrucciones al principio del programa)
void inicializarVariables(int argc, char *argv[]) {
// Analizamos el numero de argumentos recibidos.
// Aceptariamos:
// - 1 solo argumento (que seria el propio nombre del programa: ./hotelMascotas)
// - 3 argumentos: o bien ./hotelMascotas -e NUMERO, o bien ./hotelMascotas -c NUMERO,
// donde -e indica "empleados" (numero de empleados) y -c indica "clientes" (numero maximo de clientes en la cola),
// por ejemplo al ejecutar ./hotelMascotas -e 5
// - 5 argumentos: ./hotelMascotas -e NUMERO -c OTRO_NUMERO
// Almacenamos en un flag si los argumentos recibidos son correctos
int argumentosCorrectos = 0;
if (argc == 3) {
// Si hay tres argumentos, el primero sera el nombre del programa, el segundo debera ser "-c" o "-e"
// y el tercero debera ser un numero.
// Para comparar cadenas de caracteres:
// http://www.wikihow.com/Compare-Two-Strings-in-C-Programming
if ((strncmp(argv[1],"-c",100) == 0 || strncmp (argv[1],"-e",100) == 0) && esNumero(argv[2])) {
argumentosCorrectos = 1;
if (strncmp(argv[1],"-c",100) == 0) {
// Si nos dan los clientes, ponemos los empleados al valor por defecto
maximoNumeroClientes = atoi(argv[2]);
numeroEmpleados = NUMERO_EMPLEADOS_POR_DEFECTO;
}
else {
maximoNumeroClientes = NUMERO_CLIENTES_POR_DEFECTO;
numeroEmpleados = atoi(argv[2]);
}
}
}
else if (argc == 5) {
// Cinco argumentos: el de indice 1 y 3 son -c y -d (o -d y -c) y los de indice 2 y 4 son numeros.
if (
((strncmp(argv[1],"-c",100) == 0 && strncmp (argv[3],"-e",100) == 0) || (strncmp(argv[1],"-e",100) == 0 && strncmp (argv[3],"-c",100) == 0)) &&
esNumero(argv[2]) && esNumero(argv[4])
) {
argumentosCorrectos = 1;
// Respetamos el orden en que nos pasaron los argumentos
if (strncmp(argv[1],"-c",100) == 0) {
maximoNumeroClientes = atoi(argv[2]);
numeroEmpleados = atoi(argv[4]);
}
else {
maximoNumeroClientes = atoi(argv[4]);
numeroEmpleados = atoi(argv[2]);
}
}
}
// Si los argumentos no eran correctos (o si ni siquiera habia),
// inicializamos a los valores por defecto: 6 clientes y 3 empleados
if (argumentosCorrectos == 0) {
maximoNumeroClientes = NUMERO_CLIENTES_POR_DEFECTO;
numeroEmpleados = NUMERO_EMPLEADOS_POR_DEFECTO;
}
// Creamos semaforos
pthread_mutex_init(&mutexCola,NULL);
pthread_mutex_init(&mutexLog,NULL);
// Clientes
numeroClientes = 0;
numeroClientesQueHanLlamado = 0;
inicializarListaClientes();
// Empleados
inicializarListaEmpleados();
// La inicializacion del fichero de log supone crear dicho archivo (si ya existiera, se borraria)
// y luego cerrarlo inmediatamente.
// El procedimiento escribirNuevaLineaLog se encarga de abrirlo y cerrarlo posteriormente para cada linea
// de log a escribir.
ficheroLog=fopen (NOMBRE_FICHERO_LOG, "wt");
fclose(ficheroLog);
// Indicamos que se ha inicializado todo correctamente (por consola y al log)
char mensaje[250];
sprintf(mensaje,"El hotel de mascotas ha sido inicializado con %d empleados y capacidad para %d clientes", numeroEmpleados, maximoNumeroClientes);
escribirNuevaLineaLog("main", mensaje);
printf ("\n");
printf ("%s\n",mensaje);
printf ("\n");
// Si no han pasado parametros, recordamos que pueden hacerlo!
if (argumentosCorrectos == 0) {
printf (" - Recuerda que puedes indicar al programa el numero de empleados (-e) y de clientes (-c) en cola (instrucciones disponibles en el codigo):\n");
printf (" ./hotelMascotas -c 20 -e 5 &\n");
printf ("\n");
}
printf (" - Si has arrancado el programa con '&' (./hotelMascotas &), puedes simular llamadas entrantes escribiendo en la consola: \n");
printf (" pid=`ps | grep hotelMascotas | cut -d'p' -f1`; kill -10 $pid\n");
}
// main, con la declaracion y parametros indicados en la practica 5
// Recibimos parametros, inicializamos lo que haga falta y creamos los hilos
int main (int argc, char *argv[], char *envp[]) {
// Inicializamos un generador de numeros aleatorios para poder simular cuando cuelgan los clientes
// (ver accionesCliente y explicacion en http://en.kioskea.net/faq/878-generating-random-numbers-with-rand y
// http://www.cprogramming.com/tutorial/random.html)
//randomize();
// Usamos como semilla la hora actual
srand(time(0));
// Borramos texto en la consola (esto solo funciona en linux?)
system("clear");
// Inicializamos variables.
// Implementamos la funcionalidad extra 3: asignacion estatica de recursos
inicializarVariables(argc, argv);
// Creacion de los hilos de los empleados
crearHilosEmpleados();
// El main permanece (indefinidamente) a la espera de la senial SIGUSR1 o SIGUSR2, que interpreta como una nueva llamada.
// SIGUSR1 = el cliente viene con perro.
// SIGUSR2 = el cliente viene con gato.
if (signal(SIGUSR1, perro)==SIG_ERR) {
exit(-1);
}
if (signal(SIGUSR2, gato)==SIG_ERR) {
exit(-1);
}
// Nos quedamos aqui indefinidamente para que no termine el programa
while (1) {
pause();
}
}