Filósofos

Cómo estas necesito ayuda para resolver el problema de los 5 filósofos cenando y para ello tengo que usar messages queues podrías ayudarme con algo?

1 respuesta

Respuesta
1
Cuando un filósofo quiere comer se pone en la cola de los dos tenedores que necesita. Cuando un tenedor está libre lo toma. Cuando toma los dos tenedores, come y deja libre los tenedores.
Visto desde el otro lado, cada tenedor solo puede tener dos filósofos en cola, siempre los mismos.
Esto crea el problema comentado de que si todos quieren comer a la vez y todos empiezan tomando el tenedor de su derecha se bloquea el sistema (deadlock).
Resolución de conflictos en colas de tenedores:
Cada vez que un filósofo tiene un tenedor espera un tiempo aleatorio para conseguir el segundo tenedor. Si en ese tiempo no queda libre el segundo tenedor, suelta el que tiene y vuelve a ponerse en cola para sus dos tenedores.
Si un filósofo A suelta un tenedor (porque ha comido o porque ha esperado demasiado tiempo con el tenedor en la mano) pero todavía desea comer, vuelve a ponerse en colapara ese tenedor. Si el filósofo adyacente B está ya en esa cola de tenedor (tiene hambre) lo toma y si no vuelve a cogerlo A.
Es importante que el tiempo de espera sea aleatorio o se mantendrá el bloqueo del sistema.
Puedes ver una solucion basadas en semaforos (que son message-queues) en: http://www.uco.es/~p92gamuf/practicas/ssoo/filosofos.c
¿Entonces los message-que es son lo mismo que los semáforos?
Las colas de mensajes, junto con los semáforos y la memoria compartida son los recursos compartidos que pone unix a disposición de los programas para que puedan intercambiarse información.
Tienes que hacer una message queue y utilizarla como si fuera un semáforo.. Cuidado con los deads-lock
mira eso:
//Programa para demostraciÛn del uso de colas de mensajes
//
#include <iostream.h>
#include <sys/msg.h>
#include <errno.h>
//
// Estructura para los mensajes que se quieren enviar y/o recibir. Deben llevar
// obligatoriamente como primer campo un long para indicar un identificador
// del mensaje. 
// Los siguientes campos son la informaciÛn que se quiera transmitir en el  
// mensaje. Cuando m·s adelante, en el cÛdigo, hagamos un cast a 
// (struct msgbuf *), todos los campos de datos los ver· el sistema como
// un ?nico (char *)
//
typedef struct Mi_Tipo_Mensaje
{
long Id_Mensaje;
int Dato_Numerico;
char Mensaje[10];
};
main()
{
key_t Clave1;
int Id_Cola_Mensajes;
Mi_Tipo_Mensaje Un_Mensaje;
//
// Igual que en cualquier recurso compartido (memoria compartida, semaforos 
//  o colas) se obtien una clave a partir de un fichero existente cualquiera 
//  y de un entero cualquiera. Todos los procesos que quieran compartir este
//  semaforo, deben usar el mismo fichero y el mismo entero.
//
Clave1 = ftok ("/bin/ls", 33);
if (Clave1 == (key_t)-1)
{
cout << "Error al obtener clave para cola mensajes" << endl;
exit(-1);
}
//
//Se crea la cola de mensajes y se obtiene un identificador para ella.
// El IPC_CREAT indica que cree la cola de mensajes si no lo est· ya.
// El 0600 son permisos de lectura y escritura para el usuario que lance
// los procesos. Es importante el 0 delante para que se interprete en
// octal.
//
Id_Cola_Mensajes = msgget (Clave1, 0600 | IPC_CREAT);
if (Id_Cola_Mensajes == -1)
{
cout << "Error al obtener identificador para cola mensajes" << endl;
exit (-1);
}
//
//Se rellenan los campos del mensaje que se quiere enviar.
//El Id_Mensaje es un identificador del tipo de mensaje. Luego se podré·
//Recoger aquellos mensajes de tipo 1, de tipo 2, etc.
//Dato_Numerico es un dato que se quiera pasar al otro proceso. Se pone,
//por ejemplo 29.
//Mensaje es un texto que se quiera pasar al otro proceso.
//
Un_Mensaje.Id_Mensaje = 1;
Un_Mensaje.Dato_Numerico = 29;
strcpy (Un_Mensaje.Mensaje, "Hola");
//
//Se envia el mensaje. Los par·metros son:
//- Id de la cola de mensajes.
//- DirecciÛn al mensaje, convirtiéndola en puntero a (struct msgbuf *)
//- TamaÒo total de los campos de datos de nuestro mensaje, es decir
//de Dato_Numerico y de Mensaje
//- Unos flags. IPC_NOWAIT indica que si el mensaje no se puede enviar
//(Habitualmente porque la cola de mensajes esta llena), que no espere
//y de un error. Si no se pone este flag, el programa queda bloqueado
//hasta que se pueda enviar el mensaje.
//
msgsnd (Id_Cola_Mensajes, (struct msgbuf *)&Un_Mensaje, 
sizeof(Un_Mensaje.Dato_Numerico)+sizeof(Un_Mensaje.Mensaje), 
IPC_NOWAIT);
//
//Se recibe un mensaje del otro proceso. Los par·metros son:
//- Id de la cola de mensajes.
//- DirecciÛn del sitio en el que queremos recibir el mensaje,
//convirtiÈndolo en puntero a (struct msgbuf *).
//- TamaÒo m·ximo de nuestros campos de datos. 
//- Identificador del tipo de mensaje que queremos recibir. En este caso
//Se quiere un mensaje de tipo 2. Si ponemos tipo 1, se extrae el mensaje
//Que se acaba de enviar en la llamada anterior a msgsnd().
//- flags. En este caso se quiere que el programa quede bloqueado hasta
//Que llegue un mensaje de tipo 2. Si se pone IPC_NOWAIT, se devolvería
//Un error en caso de que no haya mensaje de tipo 2 y el programa
//continuarÌa ejecut·ndose.
//
msgrcv (Id_Cola_Mensajes, (struct msgbuf *)&Un_Mensaje,
sizeof(Un_Mensaje.Dato_Numerico) + sizeof(Un_Mensaje.Mensaje), 
2, 0);
cout << "Recibido mensaje tipo 2" << endl;
cout << "Dato_Numerico = " << Un_Mensaje.Dato_Numerico << endl;
cout << "Mensaje = " << Un_Mensaje.Mensaje << endl;
//
//Se borra y cierra la cola de mensajes.
// IPC_RMID indica que se quiere borrar. El puntero del final son datos
// que se quieran pasar para otros comandos. IPC_RMID no necesita datos,
// asÌ que se pasa un puntero a NULL.
//
msgctl (Id_Cola_Mensajes, IPC_RMID, (struct msqid_ds *)NULL);
}
//Programa para demostraciÛn del uso de colas de mensajes//#include <iostream.h>#include <sys/msg.h>#include <errno.h>
//// Estructura para los mensajes que se quieren enviar y/o recibir. Deben llevar// obligatoriamente como primer campo un long para indicar un identificador// del mensaje. // Los siguientes campos son la informaciÛn que se quiera transmitir en el  // mensaje. Cuando m·s adelante, en el cÛdigo, hagamos un cast a // (struct msgbuf *), todos los campos de datos los ver· el sistema como// un ?nico (char *)//typedef struct Mi_Tipo_Mensaje{long Id_Mensaje;int Dato_Numerico;char Mensaje[10];};
main(){key_t Clave1;int Id_Cola_Mensajes;Mi_Tipo_Mensaje Un_Mensaje;
//// Igual que en cualquier recurso compartido (memoria compartida, semaforos //  o colas) se obtien una clave a partir de un fichero existente cualquiera //  y de un entero cualquiera. Todos los procesos que quieran compartir este//  semaforo, deben usar el mismo fichero y el mismo entero.//Clave1 = ftok ("/bin/ls", 33);if (Clave1 == (key_t)-1){cout << "Error al obtener clave para cola mensajes" << endl;exit(-1);}
////Se crea la cola de mensajes y se obtiene un identificador para ella.// El IPC_CREAT indica que cree la cola de mensajes si no lo est· ya.// el 0600 son permisos de lectura y escritura para el usuario que lance// los procesos. Es importante el 0 delante para que se interprete en// octal.//Id_Cola_Mensajes = msgget (Clave1, 0600 | IPC_CREAT);if (Id_Cola_Mensajes == -1){cout << "Error al obtener identificador para cola mensajes" << endl;exit (-1);}
////Se rellenan los campos del mensaje que se quiere enviar.//El Id_Mensaje es un identificador del tipo de mensaje. Luego se podr·//recoger aquellos mensajes de tipo 1, de tipo 2, etc.//Dato_Numerico es un dato que se quiera pasar al otro proceso. Se pone, //por ejemplo 29.//Mensaje es un texto que se quiera pasar al otro proceso.//Un_Mensaje.Id_Mensaje = 1;Un_Mensaje.Dato_Numerico = 29;strcpy (Un_Mensaje.Mensaje, "Hola");
////Se envia el mensaje. Los par·metros son://- Id de la cola de mensajes.//- DirecciÛn al mensaje, convirtiÈndola en puntero a (struct msgbuf *)//- TamaÒo total de los campos de datos de nuestro mensaje, es decir//de Dato_Numerico y de Mensaje//- Unos flags. IPC_NOWAIT indica que si el mensaje no se puede enviar//(habitualmente porque la cola de mensajes esta llena), que no espere//y de un error. Si no se pone este flag, el programa queda bloqueado//hasta que se pueda enviar el mensaje.//msgsnd (Id_Cola_Mensajes, (struct msgbuf *)&Un_Mensaje, sizeof(Un_Mensaje.Dato_Numerico)+sizeof(Un_Mensaje.Mensaje), IPC_NOWAIT);
////Se recibe un mensaje del otro proceso. Los par·metros son://- Id de la cola de mensajes.//- DirecciÛn del sitio en el que queremos recibir el mensaje,//convirtiÈndolo en puntero a (struct msgbuf *).//- TamaÒo m·ximo de nuestros campos de datos. //- Identificador del tipo de mensaje que queremos recibir. En este caso//se quiere un mensaje de tipo 2. Si ponemos tipo 1, se extrae el mensaje//que se acaba de enviar en la llamada anterior a msgsnd().//- flags. En este caso se quiere que el programa quede bloqueado hasta//que llegue un mensaje de tipo 2. Si se pone IPC_NOWAIT, se devolverÌa//un error en caso de que no haya mensaje de tipo 2 y el programa//continuarÌa ejecut·ndose.//msgrcv (Id_Cola_Mensajes, (struct msgbuf *)&Un_Mensaje,sizeof(Un_Mensaje.Dato_Numerico) + sizeof(Un_Mensaje.Mensaje), 2, 0);
cout << "Recibido mensaje tipo 2" << endl;cout << "Dato_Numerico = " << Un_Mensaje.Dato_Numerico << endl;cout << "Mensaje = " << Un_Mensaje.Mensaje << endl;
////Se borra y cierra la cola de mensajes.// IPC_RMID indica que se quiere borrar. El puntero del final son datos// que se quieran pasar para otros comandos. IPC_RMID no necesita datos,// asÌ que se pasa un puntero a NULL.//msgctl (Id_Cola_Mensajes, IPC_RMID, (struct msqid_ds *)NULL);}
Ok ya leí como funcionan las colas de mensajes, ¿muchísimas gracias pero ahora como hago para usar estas colas de mensajes para la sincronización de procesos en el problema de los filósofos en el primer enlace que me diste hay una solución usando semáforos como puedo hacer para envés de semáforos usar colas de mensajes?
Realmente funcionan de la misma manera: un filosofo no hará nada hasta que no haya recibido un mensaje TENEDOR. Cada filosofo tiene que estar bloqueado en su cola de mensaje y en el la cola de mensaje del vecino.
Leete la pagina siguiente te dara un poco de informacion: "http://beej.us/guide/bgipc/output/html/multipage/mq.html"
Tienes que crear una cola de mensaje llamada Tenedores-Libres_filosofo1, Tenedores-Libres_filosofo2, Tenedores-Libres_filosofo3, Tenedores-Libres_filosofo4, Tenedores-Libres_filosofo5.
Cada filósofos se tienen que conectar a su cola y a la cola del filosofo de "al lado" (cola n+1).
Cuando un filosofo tiene tiene dos tenedores, los utiliza, y vuelve a mandar un Tenedor en la cola del vecino y en su cola.
El problema en parece sencillo pero no lo es, es complicado la sintaxis de las colas de mensajes y hacer que no se produzca situaciones de bloqueo. Por eso se recomienda: Cada vez que un filósofo tiene un tenedor espera un tiempo aleatorio para conseguir el segundo tenedor. Si en ese tiempo no queda libre el segundo tenedor, suelta el que tiene y vuelve a ponerse en cola para sus dos tenedores.
Si un filósofo A suelta un tenedor (porque ha comido o porque ha esperado demasiado tiempo con el tenedor en la mano) pero todavía desea comer, vuelve a ponerse en colapara ese tenedor. Si el filósofo adyacente B está ya en esa cola de tenedor (tiene hambre) lo toma y si no vuelve a cogerlo A.
Es importante que el tiempo de espera sea aleatorio o se mantendrá el bloqueo del sistema.
Suerte.
Creo que no voy a poder resolverlo :( intento y no me sale necesito llamar desde el argumento el numero de comidas para cada filosofo pero por más que intento no puedo
Dale por favor lo necesito :(
Para pasar argumentos a un programa:
int main(int argc, char **argv)
{
       int comidas = sscanf("%d", argv[0]);
       if ((comida < 1) || (comida > 100))
       {
              cout << "Error" << endl;
              return -1
       }
}
Ahora puedes llamar a: mi programa 30
¿Qué tal el resto de tu código? ¿Cómo vas?
No muy bien :( en eso ando pero no logro sincronizar a los filósofos con las colas de mensajes ...
Lo que pasa es que no estoy muy familiarizado con el lenguaje en C y me resulta bastante difícil poder compilar en C pues soy principiante en esto de la programación
Lo que no entiendo es que tengas que hacer un problema así siendo principiante...
Te puedo contestar a dudas punctuales, no puedo hacerte el ejercicio completo.
¿Qué hiciste? ¿Cuál es tu principal problema?
Lo que pasa es que en la universidad nos dieron el problema y estoy en segundo semestre nunca tuve experiencia con la programación y me estoy esforzando ... ya tengo a los filósofos los declar así
int main(int argc, char *argv[])
{
    key_t Clave1;
    int id_Cola_Mensaje;
    Tenedor_Mensaje Mensaje;
    Clave1 = ftok("/bin/ls", 33);
    if(Clave1 == (key_t)-1){
    printf (error)
}
    pid_t pid;
    pid_t children[10];
    int i;
    printf("I am parent, my pid: %d\n", getpid());
    for (i = 0; i < 5; i++) {
        pid = fork();
int main(int argc, char *argv[]){    key_t Clave1;    int id_Cola_Mensaje;
    Tenedor_Mensaje Mensaje;
    Clave1 = ftok("/bin/ls", 33);    if(Clave1 == (key_t)-1){    printf (error)}    pid_t pid;    pid_t children[10];    int i;
    printf("I am parent, my pid: %d\n", getpid());
    for (i = 0; i < 5; i++) {        pid = fork();
waitpid(-1, NULL, 0);
        if (pid < 0)
            perror("fork");
        else if (pid)
            children = pid;
        else {
            printf("I am child, my pid: %d\n", getpid());
            exit(EXIT_SUCCESS);
        }
    }
    printf("I am still parent with pid %d\n", getpid());
    exit(EXIT_SUCCESS);
}
 waitpid(-1, NULL, 0);        if (pid < 0)            perror("fork");        else if (pid)            children = pid;        else {            printf("I am child, my pid: %d\n", getpid());            exit(EXIT_SUCCESS);        }    }
    printf("I am still parent with pid %d\n", getpid());
    exit(EXIT_SUCCESS);}
Madre mía! Que es eso!
Bueno hay ideas buenas y copias chungas desede otros códigos...
Esta bien que creas 5 hilos/threads/hijos y que cada uno tenga 2 colas de mensajes. Eso es la base de tu programa. Aquí tienes la estructura que necesitaras para empezar:
#include <iostream>
#include <string>
// Required by for routine
#include <sys/types.h>
#include <unistd.h>
using namespace std;
main()
{
   pid_t pID = fork();
   if (pID == 0)                // hijo
   {
      // Codigo de los filosofos
      // Aquí se crean las colas de mensajes y se ponen a la espera de tenedores
    }
    else if (pID < 0)            // error 
    {
        cerr << "Failed to fork" << endl;
        exit(1);
    }
    else                                   // padre
    {
      // Codigo del programa principal donde tendrás que dar los primeros tenedores
    }
}

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas