/* Programma di esempio di memoria condivisa ... * In questo caso si tratta di due task che "giocano" * a tris. La strategia e' abbastanza a "caso", nel senso * che ogni task mette il suo simbolo a caso in una delle * caselle libere. * Dovrebbe risultare abbastanza semplice estenderlo in modo * da avere delle modalita' di gioco piu' complesse. * La sincronizzazione in questo caso viene ottenuta per * mezzo di un polling. */ #include #include #define __USE_POSIX #include #include #include #include #include #include #include #include #include #include #include "myutils.h" #define CAMPO "./campo" /* Nome del file usato per la condivisione */ #define LIBERO '+' /* indica che la corispondente casella e' libera */ #define PADRE 0 /* indicano chi ha il turno per giocare ... */ #define FIGLIO 1 /* Defizione e istanziazione di una struttura usata * dai due task per giocare. */ struct tris { char campo[9]; int libere; /* Numero di caselle libere */ int turno; } tris; /* Funzione che serve per stampare a video la schermata * con l'attuale situazione del gioco. */ void stampaCampo(char *campo) { int i; printf("------"); for (i=0; i<9; i++) { if ((i%3) == 0) printf("\n|"); printf("%c|", campo[i]); } printf("\n------\n"); } int main(void) { int memd, i, mossa; pid_t child; struct tris *mioCampo; /* Ottengo la zona di memoria condivsa */ memd = shmget(IPC_PRIVATE, sizeof(struct tris), SHM_R | SHM_W | IPC_CREAT | IPC_EXCL); if (memd == -1) sys_err("Non sono riuscito a creare la memoria condivisa\n"); /* "attacco" la zona di memoria condivisa al mio spazio * di indirizzamento */ mioCampo = shmat(memd, 0, SHM_R | SHM_W); if (mioCampo == -1) sys_err("Non sono riuscito ad agganciare la memoria condivisa\n"); /* Inizializzo la zona di memoria condivisa */ for (i=0;i<9;i++) mioCampo->campo[i] = LIBERO; mioCampo->libere = 9; /* Ci sono 9 caselle libere... */ mioCampo ->turno = PADRE; /* Il padre inizia a giocare per primo */ if ((child = fork()) < 0) sys_err("Errore nella fork"); else if (child == 0) { /* Processo figlio .... */ while(mioCampo->libere > 0) { /* Aspetto in polling che il turno passi al figlio */ while(mioCampo->turno == PADRE); /* Estraggo a caso una casella libera */ mossa = (rand()%mioCampo->libere)+1; /* Riempio la casella estratta prima con il simbolo "giusto". */ for (i=0; i<9; i++) { if (mioCampo->campo[i] == LIBERO) { mossa--; if (mossa == 0) { mioCampo->campo[i] = 'o'; break; } } } system("clear"); /* "Pulisco" lo schermo */ stampaCampo(mioCampo->campo); /* Stampo a video il "campo" di tris */ mioCampo->libere--; /* Aggiorno il valore delle caselle libere */ mioCampo->turno = PADRE; /* Cedo il turno all'altro task */ sleep(1); /* Fermo il task per 1 secondo */ } mioCampo->turno = PADRE; /* In ogni caso prima di uscire cambio turno */ return 0; } else { /* Processo Padre .... */ while(mioCampo->libere > 0) { /* Aspetto in polling che il turno passi al padre */ while(mioCampo->turno == FIGLIO); /* Estraggo caso una delle caselle libere */ mossa = (rand()%mioCampo->libere)+1; /* Riempio la casella estratta prima con il simbolo "giusto". */ for (i=0; i<9; i++) { if (mioCampo->campo[i] == LIBERO) { mossa--; if (mossa == 0) { mioCampo->campo[i] = 'x'; break; } } } system("clear"); /* "Pulisco" lo schermo */ stampaCampo(mioCampo->campo); /* Stampo a video il "campo" di tris */ mioCampo->libere--; /* Aggiorno il valore delle caselle libere */ mioCampo->turno = FIGLIO; /* Cedo il turno all'altro task */ sleep(1); /* Fermo il task per 1 secondo */ } mioCampo->turno = FIGLIO; /* In ogni caso prima di uscire cambio turno */ return 0; } return 0; }