La versione più vecchia di questa pagina è stata modificata il 2007-05-27 00:47:13 da JacobbE [codice problema dei treni con unix]
Vista della pagina:
Questo è il problema dei 3 treni già visto nelle pagine
Problema dei treni ma fatto attraverso la libreria pthread di unix.
In questa implementazione sono stati usati un vettore di 2 puntatori, "binari[2]", che serve a memorizzare l'indirizzo ai vettori "Andata" e "Ritorno" ed evitare ripetizioni di codice per gestire l'andata e il ritorno del treno; e il vettore "percorso" e "tratta" che servono solamente a scrivere correttamente a video in che direzione sta andando il treno, ma non ha nessuna necessità ai fini del funzionamento della sincronizzazione dei processi.
Il testo del problema:
Tre treni T1 e T2 T3 collegano tre stazioni A B e C su una tratta a singolo binario.
T1 fa la spola tra A e C,T2 fa la spola tra A e B , e T3 tra B e C. I Treni possono viaggiare contemporaneamente sulla stessa linea solo se stanno andando nella stessa direzione. T1 ha priorità rispetto al treno T2 e T3 ossia se T1 non dovra mai fermarsi alla stazione B per aspettare T1 o T2.
I treni partono dopo avere atteso alla stazione un dato tempo (TIMET1 e TIMET2 e TIMET3) e percorrono le tratte alla stessa velocità , quindi T1 impegna 2*k minuti, T2 e T3 k minuti.
1. Scrivere il programma Treni in C che abbia le i seguenti processi:
T1 ();
T2();
T3()
Il programma deve soddisfare alle seguenti caratteristiche:
a) assenza di deadlock
b) assenza di scontri.
2. Spiegare come le proprietà a e b sono rispettate dal vostro algoritmo.
//Includo le librerie
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ABSX(x) x>0 ? x : -x // macro che calcola il valore assoluto di un intero x
#define t 1 //tempo di percorrenza
#define TIMET1 3 //tempo di attesa treno 1
#define TIMET2 6 //tempo di attesa treno 2
#define TIMET3 6 //tempo di attesa treno 3
pthread_mutex_t h_mutexcs;
// mutex per proteggere la modifica dei vettori andata e ritorno
pthread_mutex_t h_print;
// mutex per proteggere la scrittura a video
pthread_t h_finito,h_treni
[3];
char *percorso
[2];
char *tratta
[6];
int andata
[2], ritorno
[2], *binari
[2];
void finito
(void *end
);
void T1
(void *end
);
void T2
(void *end
);
void T3
(void *end
);
//=================================//
// MAIN
//=================================//
int main
()
{
int fine=
0,i;
pthread_mutex_init
(&h_mutexcs,
NULL);
//inizializza il mutex per la sezione critica
pthread_mutex_init
(&h_print,
NULL);
//inizializza il mutex per la stampa a video
percorso
[0]=
(char *
)malloc
(7*
sizeof(char));
percorso
[0]=
"ANDATA";
percorso
[1]=
(char *
)malloc
(8*
sizeof(char));
percorso
[1]=
"RITORNO";
tratta
[0]=
(char *
)malloc
(5*
sizeof(char));
tratta
[0]=
"A->C";
tratta
[1]=
(char *
)malloc
(5*
sizeof(char));
tratta
[1]=
"C->A";
tratta
[2]=
(char *
)malloc
(5*
sizeof(char));
tratta
[2]=
"A->B";
tratta
[3]=
(char *
)malloc
(5*
sizeof(char));
tratta
[3]=
"B->A";
tratta
[3]=
"B->A";
tratta
[4]=
(char *
)malloc
(5*
sizeof(char));
tratta
[4]=
"B->C";
tratta
[5]=
(char *
)malloc
(5*
sizeof(char));
tratta
[5]=
"C->B";
for(i=
0; i<
2; i++
)
andata
[i
]=ritorno
[i
]=
0;
// inzializza i vettori andata e ritorno
binari
[0]=andata;
//il primo elemento di binari punta al vettore andata
binari
[1]=ritorno;
//il secondo elemento di binari punta al vettore ritorno
pthread_create
(&h_finito,
NULL,finito,&fine
);
pthread_create
(&h_treni
[0],
NULL,T1,&fine
);
pthread_create
(&h_treni
[1],
NULL,T2,&fine
);
pthread_create
(&h_treni
[2],
NULL,T3,&fine
);
pthread_join
(h_finito,
NULL);
//condizione di terminazione
pthread_join
(h_treni
[0],
NULL);
//condizione di terminazione
pthread_join
(h_treni
[1],
NULL);
//condizione di terminazione
pthread_join
(h_treni
[2],
NULL);
//condizione di terminazione
return 0;
}
void finito
(void *end
)
{
int *fine;
fine=
(int*
) end;
getchar
();
*fine=
1;
}
//=================================//
// TRENO 1 (A-C)
//=================================//
void T1
(void *end
)
{
int *fine;
int ar=
0;
//0 andata, 1 ritorno
int id=
0;
//serve ad identificare il treno nei printf
int flag=
0;
fine=
(int*
) end;
//serve solo a castare FINE
while (*fine==
0)
{
pthread_mutex_lock
(&h_mutexcs
);
//binari[andata o ritorno][AB] è libero && binari[andata o ritorno][BC] è libero
if ( (binari
[ABSX
((ar-
1))][0]==
0) &&
(binari
[ABSX
((ar-
1))][1]==
0) )
{
binari
[ar
][0]++;
//blocco il binario AB (0) di andata o ritorno (ar)
binari
[ar
][1]++;
//blocco il binario BC (1) di andata o ritorno (ar)
flag=
1;
}
pthread_mutex_unlock
(&h_mutexcs
);
if (flag
)
{
pthread_mutex_lock
(&h_print
);
printf("Il treno T1 sta percorrendo la tratta %s in %s\n", tratta
[(2*id
) + ar
], percorso
[ar
]);
pthread_mutex_unlock
(&h_print
);
sleep
(2*t
);
//tempo di percorrenza
pthread_mutex_lock
(&h_print
);
printf("Il treno T1 e' arrivato a destinazione\n");
pthread_mutex_unlock
(&h_print
);
pthread_mutex_lock
(&h_mutexcs
);
binari
[ar
][0]--;
//sblocco il binario AB di andata o ritorno
binari
[ar
][1]--;
//sblocco il binario BC di andata o ritorno
ar=ABSX
((ar-
1));
//se sto andando devo tornare, e viceversa
pthread_mutex_unlock
(&h_mutexcs
);
sleep
(TIMET1
);
//resta alla stazione per un determinato periodo di tempo
flag=
0;
}
else
sleep
(0);
}
}
//=================================//
// TRENO 2 (A-B)
//=================================//
void T2
(void *end
)
{
int *fine;
int ar=
0;
//0 andata, 1 ritorno
int id=
1;
//serve ad identificare il treno nei printf
int flag=
0;
fine=
(int*
) end;
//serve solo a castare FINE
while (*fine==
0)
{
pthread_mutex_lock
(&h_mutexcs
);
if ( binari
[ABSX
((ar-
1))][0]==
0 ) //binari[andata-ritorno][AB] è libero
{
binari
[ar
][0]++;
//blocco il binario AB di andata o ritorno
flag=
1;
}
pthread_mutex_unlock
(&h_mutexcs
);
if (flag
)
{
pthread_mutex_lock
(&h_print
);
printf("Il treno T2 sta percorrendo la tratta %s in %s\n", tratta
[(2*id
) + ar
], percorso
[ar
]);
pthread_mutex_unlock
(&h_print
);
sleep
(t
);
//tempo di percorrenza
pthread_mutex_lock
(&h_print
);
printf("Il treno T2 e' arrivato a destinazione\n");
pthread_mutex_unlock
(&h_print
);
pthread_mutex_lock
(&h_mutexcs
);
binari
[ar
][0]--;
//sblocco il binario AB di andata o ritorno
ar=ABSX
((ar-
1));
//se sto andando devo tornare, e viceversa
pthread_mutex_unlock
(&h_mutexcs
);
sleep
(TIMET2
);
//resta alla stazione per un determinato periodo di tempo
flag=
0;
}
else
sleep
(0);
}
}
//=================================//
// TRENO 3
//=================================//
void T3
(void *end
)
{
int *fine;
int ar=
0;
//0 andata, 1 ritorno
int id=
2;
//serve ad identificare il treno nei printf
int flag=
0;
fine=
(int*
) end;
//serve solo a castare FINE
while (*fine==
0)
{
pthread_mutex_lock
(&h_mutexcs
);
if ( (binari
[ABSX
((ar-
1))][1]==
0)) //binari[andata-ritorno][BC] è libero
{
binari
[ar
][1]++;
//blocco il binario BC di andata o ritorno
flag=
1;
}
pthread_mutex_unlock
(&h_mutexcs
);
if (flag
)
{
pthread_mutex_lock
(&h_print
);
printf("Il treno T3 sta percorrendo la tratta %s in %s\n", tratta
[(2*id
) + ar
], percorso
[ar
]);
pthread_mutex_unlock
(&h_print
);
sleep
(t
);
//tempo di percorrenza
pthread_mutex_lock
(&h_print
);
printf("Il treno T3 e' arrivato a destinazione\n");
pthread_mutex_unlock
(&h_print
);
pthread_mutex_lock
(&h_mutexcs
);
binari
[ar
][1]--;
//sblocco il binario AB di andata o ritorno
ar=ABSX
((ar-
1));
//se sto andando devo tornare, e viceversa
pthread_mutex_unlock
(&h_mutexcs
);
sleep
(TIMET3
);
//resta alla stazione per un determinato periodo di tempo
flag=
0;
}
else
sleep
(0);
}
}
Torna a Lab Sistemi Operativi