Nadesłany przez Tomasz Lubiński, 26 lipca 2005 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
peterson.c:
//(c)2002 Tomasz Lubinski //www.algorytm.org //algorytm Peterson'a - problem wzajemnego wykluczania #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <signal.h> int n; void usun_pamiec() { int shmid,key; for (key=1; key<=n; key++) { shmid=shmget(100+key, 4, IPC_CREAT); shmctl(shmid, IPC_RMID, NULL); } for (key=1; key<n; key++) { shmid=shmget(200+key, 4, IPC_CREAT); shmctl(shmid, IPC_RMID, NULL); } exit(0); } int main() { int* flag[100]; int* turn[99]; int shmid,key; struct shmid_ds buf; printf("Podaj dla ilu procesow chcesz przetestowac algorytm (max. 99)\n"); scanf("%d", &n); //zainicjowanie zmiennych wspoldzielonych for (key=1; key<=n; key++) { shmid=shmget(100+key, 4, IPC_CREAT); shmctl(shmid, IPC_STAT, &buf); buf.shm_perm.mode=0666; shmctl(shmid, IPC_SET, &buf); flag[key]=shmat(shmid, NULL, SHM_RND); *flag[key]=0; } for (key=1; key<n; key++) { shmid=shmget(100+key, 4, IPC_CREAT); shmctl(shmid, IPC_STAT, &buf); buf.shm_perm.mode=0666; shmctl(shmid, IPC_SET, &buf); turn[key]=shmat(shmid, NULL, SHM_RND); *turn[key]=0; } //po zakonczeniu wykonywania progamu pamiec wspoldzielona nalezy usunac. //po nacisnieciu klawiszy ctrl+c sygnal SIGINT jest przechwytywany i //uruchamiana jest funkcja usun_pamiec signal(SIGINT, usun_pamiec); printf("Program nalezy przerwac wciskajac ctrl+c\n\n"); //uruchomienie n procesow potomnych, ktore beda dzialaly wspolbieznie for (key=1; key<=n; key++) { if (fork()==0) { int k,l,other,whose,pid; pid=key; //kazdy proces potomny otrzymuje wlasny numer pid //algorytm Peterson'a while(1) { printf("P%d jest poza sekcja krytyczna\n", pid); sleep(random()%15); printf("P%d chce wejsc do sekcji krytycznej\n", pid); for (k=1; k<n; k++) { *flag[pid]=k; *turn[k]=pid; do { whose=*turn[k]; if (whose!=pid) break; for (l=1; l<=n; l++) { if (l!=pid) other=*flag[l]; if (other>=k) break; } } while(other>=k); } printf("\t\t\t\tP%d jest w sekcji krytycznej\n", pid); sleep(random()%10); *flag[pid]=0; } } } wait(NULL); }