Lösung zu Modul 6 Aufgabe 2 Parkhaus mit Race Conditions: parkhaus_race.c #include #include // sleep #include #include #include #include #include #define IN_PROCESSES 2 // Die Anzahl der Autos, die maximal erzeugt werden sollen #define IN_PRODUCE 100000 #define OUT_PROCESSES 2 #define SEGSIZE sizeof(int) #define FALSE 0 #define TRUE 1 #define PARK_CAPACITY 4 #define WAITTIME 2 int main(){ /* Variablendeklarationen */ int i, j, id, *shared_mem, returncode[4]; int produced[4]; for (i=0; i<4; i++) returncode[i] = -1; /* Reservieren des Shared Segment */ id = shmget(IPC_PRIVATE, SEGSIZE, IPC_CREAT | 0644); if (id == -1){ fprintf(stderr, "Fehler bei der Reservierung des Shared Memory Segmentes.\n"); exit(2); } printf("Shared Segment reserviert\n"); /* Das Anhaengen des Shared Segment an einen eigenen Adressraum */ i = shmat(id, 0, 0); if (i == -1){ fprintf(stderr, "Fehler beim Anhaengen Shared Memory Segmentes.\n"); exit(3); } printf("Shared Segment angehangen\n"); shared_mem = (int *) i; /* Die initialisierung des Shared Segments */ shared_mem[0] = 0; printf("Starte Prozesse\n"); /* Starten der IN-Prozesse */ if ((returncode[0] = fork())==0){ produced[0] = 0; printf("New In Child %d (%i)\n", getpid(), returncode[0]); while (produced[0] < IN_PRODUCE){ // Falls freie Parkplaetze vorhanden sind, dann einfahren if (shared_mem[0] < PARK_CAPACITY){ usleep(10); // Warten shared_mem[0]++; produced[0]++; if (produced[0]%1000 == 0) printf("%i: %i von %i\n", getpid(), shared_mem[0], PARK_CAPACITY); if (shared_mem[0]<0 || shared_mem[0]>PARK_CAPACITY){ printf("Race Condition at %i: %i von %i Plaetzen belegt!\n", produced[0], shared_mem[0], PARK_CAPACITY); exit(0); } } } printf("Dying In Child %d\n", getpid()); exit(0); } else if ((returncode[1] = fork())==0){ produced[1] = 0; printf("New In Child %d (%i)\n", getpid(), returncode[1]); while (produced[1] < IN_PRODUCE){ // Falls freie Parkplaetze vorhanden sind, dann einfahren if (shared_mem[0] < PARK_CAPACITY){ usleep(10); // Warten shared_mem[0]++; produced[1]++; if (produced[1]%1000 == 0) printf("%i: %i von %i\n", getpid(), shared_mem[0], PARK_CAPACITY); if (shared_mem[0]<0 || shared_mem[0]>PARK_CAPACITY){ printf("Race Condition at %i: %i von %i Plaetzen belegt!\n", produced[1], shared_mem[0], PARK_CAPACITY); exit(0); } } } printf("Dying In Child %d\n", getpid()); exit(0); } else if ((returncode[2] = fork())==0){ produced[2] = 0; printf("New Out Child %d (%i)\n", getpid(), returncode[2]); // outprozess while (produced[2] < IN_PRODUCE){ // Falls freie Parkplaetze vorhanden sind, dann herausfahren if (shared_mem[0] > 0){ usleep(10); // warten shared_mem[0]--; produced[2]++; if (produced[2]%1000 == 0) printf("%i: %i von %i\n", getpid(), shared_mem[0], PARK_CAPACITY); if (shared_mem[0]<0 || shared_mem[0]>PARK_CAPACITY){ printf("Race Condition at %i: %i von %i Plaetzen belegt!\n", produced[2], shared_mem[0], PARK_CAPACITY); exit(0); } } } printf("Dying Out Child %d\n", getpid()); exit(0); } else if ((returncode[3] = fork())==0){ produced[3] = 0; printf("New Out Child %d (%i)\n", getpid(), returncode[3]); // outprozess while (produced[3] < IN_PRODUCE){ // Falls freie Parkplaetze vorhanden sind, dann herausfahren if (shared_mem[0] > 0){ usleep(10); // warten shared_mem[0]--; produced[3]++; if (produced[3]%1000 == 0) printf("%i: %i von %i\n", getpid(), shared_mem[0], PARK_CAPACITY); if (shared_mem[0]<0 || shared_mem[0]>PARK_CAPACITY){ printf("Race Condition at %i: %i von %i Plaetzen belegt!\n", produced[3], shared_mem[0], PARK_CAPACITY); exit(0); } } } printf("Dying Out Child %d\n", getpid()); exit(0); } else{ if (returncode[0]>=0) wait(0); if (returncode[1]>=0) wait(0); if (returncode[2]>=0) wait(0); if (returncode[3]>=0) wait(0); /* Das Shared Segment wieder freigeben */ i = shmdt(shared_mem); if (i != 0){ fprintf(stderr, "Fehler beim Detachen des Shared Memory Segmentes.\n"); exit(4); } i = shmctl(id, IPC_RMID, 0); if (i == -1){ fprintf(stderr, "Fehler beim Kontrollieren der Freigabe des Shared Memory Segmentes.\n"); exit(5); } return 0; } } Parkhaus mit Semaphore (parkhaus_semaphore.c): #include #include // sleep #include #include #include #include // semaphoren #include #include #define IN_PROCESSES 2 // Die Anzahl der Autos, die maximal erzeugt werden sollen #define IN_PRODUCE 100000 #define OUT_PROCESSES 2 #define SEGSIZE sizeof(int) #define FALSE 0 #define TRUE 1 #define PARK_CAPACITY 120 #define WAITTIME 2 int main(){ /* Variablendeklarationen */ int i, j, id, *shared_mem, returncode[4]; int produced[4]; int semaphore_set; struct sembuf enter, leave; unsigned short marker[1]; for (i=0; i<4; i++){ returncode[i] = -1; } /* Reservieren des Shared Segment */ id = shmget(IPC_PRIVATE, SEGSIZE, IPC_CREAT | 0644); if (id == -1){ fprintf(stderr, "Fehler bei der Reservierung des Shared Memory Segmentes.\n"); exit(2); } printf("Shared Segment reserviert\n"); /* Das Anhaengen des Shared Segment an einen eigenen Adressraum */ i = shmat(id, 0, 0); if (i == -1){ fprintf(stderr, "Fehler beim Anhaengen Shared Memory Segmentes.\n"); exit(3); } printf("Shared Segment angehangen\n"); shared_mem = (int *) i; /* Die initialisierung des Shared Segments */ shared_mem[0] = 0; /* Semaphore erzeugen */ semaphore_set = semget(IPC_PRIVATE, 1, IPC_CREAT | 0644); if (semaphore_set == -1) { fprintf(stderr, "Fehler beim Erzeugen der Semaphore.\n"); exit(1); } printf("Semaphore erzeugt\n"); /* Semaphore initialisieren mit 1 */ marker[0] = 1; i = semctl(semaphore_set, 1, SETALL, marker); if (i == -1){ fprintf(stderr, "Fehler beim Initialisieren der Semaphore.\n"); exit(1); } printf("Semaphore initialisiert\n"); enter.sem_num = 0; enter.sem_op = -1; enter.sem_flg = SEM_UNDO; leave.sem_num = 0; leave.sem_op = 1; leave.sem_flg = SEM_UNDO; printf("Starte Prozesse\n"); fflush(stdout); /* Starten der IN-Prozesse */ if ((returncode[0] = fork()) == 0){ produced[0] = 0; printf("First New In Child %d (%i)\n", getpid(), returncode[0]); while (produced[0] < IN_PRODUCE){ /* Beginn des kritischen Bereichs */ i = semop(semaphore_set, &enter, 1); if (i<0){ fprintf(stderr, "Fehler beim Ausf¸hren einer Semaphoren-Operation.\n"); exit(9); } // Falls freie Parkplaetze vorhanden sind, dann einfahren if (shared_mem[0] < PARK_CAPACITY){ shared_mem[0]++; produced[0]++; printf("First %i: %i von %i\n", getpid(), shared_mem[0], PARK_CAPACITY); if (shared_mem[0]<0 || shared_mem[0]>PARK_CAPACITY){ printf("Race Condition at %i: %i von %i Plaetzen belegt!\n", produced[0], shared_mem[0], PARK_CAPACITY); exit(0); } } fflush(stdout); i = semop(semaphore_set, &leave, 1); if (i<0){ fprintf(stderr, "Fehler beim Ausfuehren einer Semaphoren-Operation.\n"); exit(9); } /* Ende des kritischen Bereichs */ } printf("Dying In Child %d\n", getpid()); exit(0); } else if ((returncode[1] = fork()) == 0){ produced[1] = 0; printf("Second New In Child %d (%i)\n", getpid(), returncode[1]); while (produced[1] < IN_PRODUCE){ /* Beginn des kritischen Bereichs */ i = semop(semaphore_set, &enter, 1); if (i<0){ fprintf(stderr, "Fehler beim Ausfuehren einer Semaphoren-Operation.\n"); exit(9); } // Falls freie Parkplaetze vorhanden sind, dann einfahren if (shared_mem[0] < PARK_CAPACITY){ shared_mem[0]++; produced[1]++; printf("Second %i: %i von %i\n", getpid(), shared_mem[0], PARK_CAPACITY); if (shared_mem[0]<0 || shared_mem[0]>PARK_CAPACITY){ printf("Race Condition at %i: %i von %i Plaetzen belegt!\n", produced[1], shared_mem[0], PARK_CAPACITY); exit(0); } } fflush(stdout); i = semop(semaphore_set, &leave, 1); if (i<0){ fprintf(stderr, "Fehler beim Ausfuehren einer Semaphoren-Operation.\n"); exit(9); } /* Ende des kritischen Bereichs */ } printf("Dying In Child %d\n", getpid()); exit(0); } else if ((returncode[2] = fork()) == 0){ produced[2] = 0; printf("Third New Out Child %d (%i)\n", getpid(), returncode[2]); // outprozess while (produced[2] < IN_PRODUCE){ /* Beginn des kritischen Bereichs */ i = semop(semaphore_set, &enter, 1); if (i<0){ fprintf(stderr, "Fehler beim Ausf¸hren einer Semaphoren-Operation.\n"); exit(9); } // Falls Parkplaetze belegt sind, dann herausfahren if (shared_mem[0] > 0){ shared_mem[0]--; produced[2]++; printf("Third %i: %i von %i\n", getpid(), shared_mem[0], PARK_CAPACITY); if (shared_mem[0]<0 || shared_mem[0]>PARK_CAPACITY){ printf("Race Condition at %i: %i von %i Plaetzen belegt!\n", produced[2], shared_mem[0], PARK_CAPACITY); exit(0); } } fflush(stdout); i = semop(semaphore_set, &leave, 1); if (i<0){ fprintf(stderr, "Fehler beim Ausfuehren einer Semaphoren-Operation.\n"); exit(9); } /* Ende des kritischen Bereichs */ } printf("Dying Out Child %d\n", getpid()); exit(0); } else if ((returncode[3] = fork()) == 0){ produced[3] = 0; printf("Fourth New Out Child %d (%i)\n", getpid(), returncode[3]); // outprozess while (produced[3] < IN_PRODUCE){ /* Beginn des kritischen Bereichs */ i = semop(semaphore_set, &enter, 1); if (i<0){ fprintf(stderr, "Fehler beim Ausfuehren einer Semaphoren-Operation.\n"); exit(9); } // Falls Parkplaetze belegt sind, dann herausfahren if (shared_mem[0] > 0){ shared_mem[0]--; produced[3]++; printf("Fourth %i: %i von %i\n", getpid(), shared_mem[0], PARK_CAPACITY); if (shared_mem[0]<0 || shared_mem[0]>PARK_CAPACITY){ printf("Race Condition at %i: %i von %i Plaetzen belegt!\n", produced[3], shared_mem[0], PARK_CAPACITY); exit(0); } } fflush(stdout); i = semop(semaphore_set, &leave, 1); if (i<0){ fprintf(stderr, "Fehler beim Ausfuehren einer Semaphoren-Operation.\n"); exit(9); } /* Ende des kritischen Bereichs */ } printf("Dying Out Child %d\n", getpid()); exit(0); } else{ if (returncode[0]>=0) wait(0); if (returncode[1]>=0) wait(0); if (returncode[2]>=0) wait(0); if (returncode[3]>=0) wait(0); /* Shared Segment wieder freigeben */ i = shmdt(shared_mem); if (i != 0){ fprintf(stderr, "Fehler beim Detachen des Shared Memory Segmentes.\n"); exit(4); } i = shmctl(id, IPC_RMID, 0); if (i == -1){ fprintf(stderr, "Fehler beim Kontrollieren der Freigabe des Shared Memory Segmentes.\n"); exit(5); } i = semctl(semaphore_set, 0, IPC_RMID, 0); if (i == -1){ fprintf(stderr, "Fehler beim Loeschen der Semaphore.\n"); exit(7); } return 0; } }