VERSIONE ALTERNATIVA
//
/* LIBRERIE */
//
#include <time.h>
//
/* TIPI E STRUTTURE */
//
typedef struct train{
unsigned int id;
unsigned int local;
unsigned int counter;
unsigned int start;
char *nome[12];
} train;
//
/* VARIABILI GLOBALI */
//
#define N 4 /* La costante N rappresenta il numero di stazioni */
#define SOSTA_IN_STAZIONE 1000
#define PERCORRE_BINARIO 3000
HANDLE mut_binario[N],
sem_stazione[N];
int continua = 1; /* variabile controllo pass_fine */
char binario[N][14]={" NORD -> EST ",
" EST -> SUD ",
" SUD -> OVEST",
"OVEST -> NORD "};
char station[N][6]={"NORD "," EST "," SUD ","OVEST"};
train treno[3]=Unknown action; the action name must not contain special characters.;
//
/* FORWARD DECLARATIONS */
//
DWORD si_parteee (LPDWORD lpdwParam);
DWORD fine_corse (LPDWORD lpdwParam);
//
/* MAIN */
//
main(){
/* THREADS */
HANDLE thr_end, /* thread che controlla la fine corse */
thr_treno[3]; /* threads treno */
/* INIZIALIZZAZIONE MUTEX BINARI */
for(i=0;i<4;i
)
mut_binario[i] = CreateMutex(NULL, FALSE, NULL);
/* INIZIALIZZAZIONE SEMAFORI STAZIONI */
sem_stazione[0] = CreateSemaphore(NULL,0,2,NULL); /* Loc. ed Espr. N/S */
sem_stazione[1] = CreateSemaphore(NULL,1,2,NULL); /* Espr. E/O */
sem_stazione[2] = CreateSemaphore(NULL,2,2,NULL); /* nessun treno */
sem_stazione[3] = CreateSemaphore(NULL,2,2,NULL); /* nessun treno */
/* CREAZIONE THREAD CONTROLLO */
thr_end = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) fine_corse, (LPVOID) &continua, 0, NULL);
/* INIZIALIZZAZIONE THREAD TRENI */
for(i=0;i<3;i)
thr_treno[i] =
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) si_parteee, (LPVOID) &treno[i], 0, NULL);
/* ATTESA INTERRUPT DA TASTIERA */
while(continua);
/* TERMINAZIONE THREADS */
for(i=0;i<3;i
)
TerminateThread(thr_treno[i],0);
/* STAMPA STATISTICHE*/
printf("\n\n FINE CORSE\n");
for(i=0;i<3;i)
printf("\n Il treno %s ha compiuto %d giri completi\n",*treno[i].nome,treno[i].counter);
//
/* FINE CORSE */
//
DWORD fine_corse (LPDWORD lpdwParam){
int *continua;
continua = (int *) lpdwParam;
*continua = 0;
//
/* PARTE IL TRENO */
//
DWORD si_parteee (LPDWORD lpdwParam){
unsigned int giro; /* memorizziamo la stazione di partenza */
train *treno;
treno = (train *) lpdwParam;
giro = treno->start;
while(continua){
/* il treno sosta nelle stazioni rispettive */
if( ( (treno->start
giro)||(treno->start
(giro+2) ) )||(treno->local) )
Sleep(SOSTA_IN_STAZIONE);
/* controlli per dare la priorità ai treni espressi */
if(treno->local)
{
/* controllo il binario precedente */
WaitForSingleObject(mut_binario[(treno->start
0)?(N-1):(treno->start-1)],INFINITE);
/* controllo semaforo della stessa stazione non sia occupato (sorpasso) */
WaitForSingleObject(sem_stazione[treno->start],INFINITE);
}
/* controllo il mutex del binario che deve percorrere */
WaitForSingleObject(mut_binario[treno->start],INFINITE);
/* rilascio il mutex del binario precedente */
if(treno->local)
ReleaseMutex(mut_binario[(treno->start
0)?(N-1):(treno->start-1)]);
/* partendo, il treno rilascia il semaforo stazione dove si trovava */
/* rilascio 2 posti nel semaforo se si tratta di treno locale */
ReleaseSemaphore(sem_stazione[treno->start],2 - (1 - treno->local),NULL);
/* il treno percorre un binario */
printf("\t\t%s percorre il binario %s\n",*treno->nome,binario[treno->start]);
Sleep(PERCORRE_BINARIO);
/* il treno sta per entrare nella stazione successiva */
treno->start = (treno->start + 1)%4;
/* per entrare in stazione si deve prendere un semaforo di questa */
WaitForSingleObject(sem_stazione[treno->start],INFINITE);
printf("\t\t%s entra in stazione %s\n",*treno->nome,station[treno->start]);
/* entrati in stazione rilasciamo il binario percorso */
ReleaseMutex(mut_binario[(treno->start0)?(N-1):(treno->start-1)]);
if(treno->start
giro){
treno->counter;
printf("\t\t\t%s ha compiuto un giro completo!!!\n",*treno->nome);
}
Sleep(500);
La versione più vecchia di questa pagina è stata modificata il 2006-06-04 20:54:18 da AntarellO []
Vista della pagina:
LA FERROVIA DI MONOPOLI
La città di Monopoli ha quattro stazioni ferroviarie chiamate Nord, Sud, Est, Ovest (per brevità da ora in poi le chiameremo N,S,E,W).
La linea ferroviaria è circolare a binario semplice e solo alle stazioni esiste un secondo binario per
consentire sorpassi o incroci tra treni. Per motivi di sicurezza anche se due treni procedono nella
stessa direzione uno solo di essi può occupare la tratta ferroviaria fra due stazioni, l'altro deve
aspettare che il primo abbia raggiunto la stazione successiva per poter entrare nella tratta.
A monopoli esistono tre treni: il locale che ferma in tutte le stazioni, il treno espresso N/S
e in treno espresso E/W.
Tutti i treni viaggiano nella direzione N->E->S->W (senso orario).
I treni espresso hanno la precedenza sul locale:
se il locale è fermo in stazione e un espresso o è fermo nella stessa stazione o è sulla tratta
ferroviaria immediatamente precedente allora il locale deve attendere che l'espresso abbia
superato la stazione prima di poter ripartire.
I treni espresso si possono superare nelle stazioni (a patto che il treno locale non occupi già un binario della stazione).
/*Per giustificare l'assenza di deadlock basta osservare che prima di partire ogni treno chiede tutte le risorse che
gli saranno necessarie per percorrere la tratta fino alla prossima fermata, che è la stazione successiva nel caso
del treno locale e la stazione agli antipodi nel caso dei treni espressi.
Quindi una volta che ha ottenuto le risorse necessarie ad un viaggio non può richiederne altre
ed è negata la condizione di hold & wait.
Sono sicuro che prima o poi il treno otterrà le risorse richieste perché tutti i thread rilasciano le risorse
acquisite dopo un tempo standard.
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <stddef.h>
#include <windows.h>
#include <ctype.h>
#define N 4 //La costante N rappresenta il numero di stazioni
#define TIME 500 /*TIME è la costante di tempo che un treno, espresso o locale che sia, impiega
a percorrere un binario che collega due stazioni
*/
HANDLE binario[N], stazione[N];
int corse[3]; //La variabile 'corse' tiene il conto delle corse effettuate da un treno
void T1(LPDWORD param);
void T2(LPDWORD param);
void T3(LPDWORD param);
int main() {
HANDLE hTreno1,hTreno2,hTreno3;
DWORD dwTreno1,dwTreno2,dwTreno3;
int i;
for (i=0;i<3;i++)
corse[i]=0;
//Creo i mutex relativi ai 4 binari
binario[0]=CreateMutex(NULL,FALSE, "binario 0");
binario[1]=CreateMutex(NULL,FALSE, "binario 1");
binario[2]=CreateMutex(NULL,FALSE, "binario 2");
binario[3]=CreateMutex(NULL,FALSE, "binario 3");
/*Dato che le stazioni hanno due binari per gestire i sorpassi, creo i semafori che rappresentano i binari
delle stazioni
*/
/*Imposto lInitialCount=0 per la stazione nord e =1 per la stazione est perché all'inizio
dell'esecuzione dei miei thread ci sono due treni che partono dalla stazione nord
(il locale e l'espresso N/S) e l'espresso E/O che parte dalla stazione est
*/
stazione[0]=CreateSemaphore(NULL,0,2,"stazione 0");
stazione[1]=CreateSemaphore(NULL,1,2,"stazione 1");
stazione[2]=CreateSemaphore(NULL,2,2,"stazione 2");
stazione[3]=CreateSemaphore(NULL,2,2,"stazione 3");
//Adesso creo e faccio partire i thread
hTreno1=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)T1,NULL,0,&dwTreno1);
hTreno2=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)T2,NULL,0,&dwTreno2);
hTreno3=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)T3,NULL,0,&dwTreno3);
//L'esequzione termina finché l'utente non batte un tasto qualsiasi
getch();
TerminateThread(hTreno1,0);
TerminateThread(hTreno2,0);
TerminateThread(hTreno3,0);
for (i=0;i<3;i++)
printf("Il treno %d ha effettuato %d corse complete\n", i+1, corse[i]);
return 0;
}
/******TRENO LOCALE******/
void T1(LPDWORD param) {
while(1){
/*Mi assicuro che il binario da percorrere sia libero
e che alla stazione successiva ci sia un binario per sostare*/
WaitForSingleObject(binario[0],INFINITE);
WaitForSingleObject(stazione[1],INFINITE);
printf("Il treno locale parte dalla stazione nord\n");
//Partendo rilascio il semaforo della stazione di partenza
ReleaseSemaphore(stazione[0],1,NULL);
//Viaggia...
Sleep(TIME);
printf("Il treno locale arriva alla stazione est\n");
//Arrivati alla stazione rilascio il mutex corrispondente al binario appena attraversato
ReleaseMutex(binario[0]);
printf("Il treno locale attende di partire dalla stazione est\n");
WaitForSingleObject(binario[1],INFINITE);
WaitForSingleObject(stazione[2],INFINITE);
printf("Il treno locale parte dalla stazione est\n");
ReleaseSemaphore(stazione[1],1,NULL);
Sleep(TIME);
printf("Il treno locale arriva alla stazione sud\n");
ReleaseMutex(binario[1]);
printf("Il treno locale attende di partire dalla stazione sud\n");
WaitForSingleObject(binario[2],INFINITE);
WaitForSingleObject(stazione[3],INFINITE);
printf("Il treno locale parte dalla stazione sud\n");
ReleaseSemaphore(stazione[2],1,NULL);
Sleep(TIME);
printf("Il treno locale arriva alla stazione ovest\n");
ReleaseMutex(binario[2]);
printf("Il treno locale attende di partire dalla stazione ovest\n");
WaitForSingleObject(binario[3],INFINITE);
WaitForSingleObject(stazione[0],INFINITE);
printf("Il treno locale parte dalla stazione ovest\n");
ReleaseSemaphore(stazione[3],1,NULL);
Sleep(TIME);
printf("Il treno locale arriva alla stazione nord\n");
ReleaseMutex(binario[3]);
//Essendo ritornato al punto di partenza incremento il vettore delle corse
corse[0]++;
printf("Il treno locale attende di partire dalla stazione nord\n");
}
}
/******ESPRESSO NORD-SUD******/
void T2(LPDWORD param) {
while(1) {
/*Mi assicuro che i binari che percorrerò lungo l'intera corsa siano liberi,
anche i binari della stazione di passaggio.
Divido il viaggio in due parti che durano un tempo uguale a TIME, in questo modo quando
l'espresso supera una stazione di passaggio posso rilasciare il binario appena pecorso e
la stazione appena superata
*/
WaitForSingleObject(binario[0],INFINITE);
WaitForSingleObject(stazione[1],INFINITE);
WaitForSingleObject(binario[1],INFINITE);
WaitForSingleObject(stazione[2],INFINITE);
printf("L'espresso NORD-SUD parte dalla stazione nord\n");
//Rilascio il semaforo che rappresenta il binario della stazione di partenza
ReleaseSemaphore(stazione[0],1,NULL);
//Prima parte del viaggio
Sleep(TIME);
printf("L'espresso NORD-SUD supera la stazione est\n");
//Superata la prima stazione rilascio il binario percorso e la stazione superata
ReleaseMutex(binario[0]);
ReleaseSemaphore(stazione[1],1,NULL);
Sleep(TIME);
printf("L'espresso NORD-SUD arriva alla stazione sud\n");
ReleaseMutex(binario[1]);
printf("L'espresso NORD-SUD attende di partire dalla stazione sud\n");
WaitForSingleObject(binario[2],INFINITE);
WaitForSingleObject(stazione[3],INFINITE);
WaitForSingleObject(binario[3],INFINITE);
WaitForSingleObject(stazione[0],INFINITE);
printf("L'espresso NORD-SUD parte dalla stazione sud\n");
ReleaseSemaphore(stazione[2],1,NULL);
Sleep(TIME);
printf("L'espresso NORD-SUD supera la stazione ovest\n");
ReleaseMutex(binario[2]);
ReleaseSemaphore(stazione[3],1,NULL);
Sleep(TIME);
printf("L'espresso NORD-SUD arriva alla stazione nord\n");
ReleaseMutex(binario[3]);
//Essendo ritornato al punto di partenza incremento il vettore delle corse
corse[1]++;
printf("L'espresso NORD-SUD attende di partire dalla stazione nord\n");
}
}
/******ESPRESSO EST-OVEST******/
void T3(LPDWORD param) {
while(1) {
/*Mi assicuro che i binari che percorrerò lungo l'intera corsa siano liberi,
anche i binari della stazione di passaggio.
Divido il viaggio in due parti che durano un tempo uguale a TIME, in questo modo quando
l'espresso supera una stazione di passaggio posso rilasciare il binario appena pecorso e
la stazione appena superata
*/
WaitForSingleObject(binario[1],INFINITE);
WaitForSingleObject(stazione[2],INFINITE);
WaitForSingleObject(binario[2],INFINITE);
WaitForSingleObject(stazione[3],INFINITE);
printf("L'espresso EST-OVEST parte dalla stazione est\n");
ReleaseSemaphore(stazione[1],1,NULL);
Sleep(TIME);
printf("L'espresso EST-OVEST supera la stazione sud\n");
ReleaseMutex(binario[1]);
ReleaseSemaphore(stazione[2],1,NULL);
Sleep(TIME);
printf("L'espresso EST-OVEST arriva alla stazione ovest\n");
ReleaseMutex(binario[2]);
printf("L'espresso EST-OVEST attende di partire dalla stazione ovest\n");
WaitForSingleObject(binario[3],INFINITE);
WaitForSingleObject(stazione[0],INFINITE);
WaitForSingleObject(binario[0],INFINITE);
WaitForSingleObject(stazione[1],INFINITE);
printf("L'espresso EST-OVEST parte dalla stazione ovest\n");
ReleaseSemaphore(stazione[3],1,NULL);
Sleep(TIME);
printf("L'espresso EST-OVEST supera la stazione nord\n");
ReleaseMutex(binario[3]);
ReleaseSemaphore(stazione[0],1,NULL);
Sleep(TIME);
printf("L'espresso EST-OVEST arriva alla stazione est\n");
ReleaseMutex(binario[0]);
corse[2]++;
printf("L'espresso EST-OVEST attende di partire dalla stazione est\n");
}
}
Torna a Lab Sistemi Operativi