Lsung zu Modul 6 Aufgabe 2

Parkhaus mit Race Conditions: parkhaus_race.c

#include <stdio.h>
#include <stdlib.h>
// sleep
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>

#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 <stdio.h>
#include <stdlib.h>
// sleep
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
// semaphoren
#include <sys/sem.h>
#include <sys/wait.h>

#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 Ausfhren 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 Ausfhren 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;
	}
}
