Problema Dei Filosofi
Cinque filosofi passano la loro vita a pensare e a mangiare (alternativamente). Per mangiare fanno uso di una tavola rotonda con 5 sedie, 5 piatti e 5 posate fra i piatti per mangiare. Un filosofo, per mangiare, ha bisogno di entrambe le posate (destra/sinistra). Per pensare, lascia le posate dove le ha prese. Dato che prediligono gli spaghetti e che gli spaghetti non si mangiano con due forchette, utilizzeranno un paio di bacchette, ma il concetto rimane lo stesso. Il problema dei filosofi mostra come gestire situazioni in cui i processi entrano in competizione per accedere ad insiemi di risorse a intersezione non nulla.
Implementazione
Ho utilizzato la libreria "semaphore.h" per gestire i semafori.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <unistd.h>
sem_t chopstick[5];
void dining(int i)
{
pid_t pid=fork();
if (pid==-1)
exit(2);
if (pid)
{
printf("Sono il %d figlio di %i!\n\n\n", i, getppid());
// while(1)
{
printf("%d sta pensando...\n", getpid());
sem_wait(&(chopstick[i]));
sem_wait(&(chopstick[(i+1)%5]));
printf("%d sta mangiando...\n", getpid());
sem_post(&(chopstick[i]));
sem_post(&(chopstick[(i+1)%5]));
}
}
else /* processo figlio */
if((i+1)!=5)
{
dining(i+1);
}
else /* Non ci sono filosofi rimanenti */
{
printf("Hanno pensato e mangiato tutti!\n");
return;
}
return;
}
int main(int argc, char* argv[])
{
pid_t pid;
int i;
/* Inizializzo i semafori
* il primo parametro e' l'indirizzo del semaforo
* il secondo e' 0 se si utilizzano i thread, altrimenti processo
* il terzo e' il valore iniziale
*/
for(i=0; i<5; i++)
sem_init(&(chopstick[i]), 1, 1);
i=1; /*i diventa 1 perche' il primo filosofo lo faccio mangiare subito */
pid=fork();
if(pid==-1)
{
exit(2);//errore
}
else
if (pid)
{
/* Per rompere la simmetria faccio mangiare per primo un filosofo
* in questo caso il filosofo 0
*/
printf("Sono %d, il padre di tutti!\\n\n\n", getpid());
// while(1)
{
printf("%d sta pensando...\n", getpid());
sem_wait(&(chopstick[1]));
sem_wait(&(chopstick[0]));
printf("%d sta mangiando...\n", getpid());
sem_post(&(chopstick[1]));
sem_post(&(chopstick[0]));
}
}
else /* Primo processo figlio */
{
printf("Padre: %d\n\n", getppid());
dining(i);
}
return 0;
}
Commenti
Ho rimosso il while(1) per evitare che il programma andasse in loop, quindi il problema viene risolto una sola volta. Ho effettivamente scritto un programma che ricorsivamente crea dei processi fratelli, e non figli, del primo processo figlio, come si puo' vedere dall'output.