-
-
Save stetro/2868994 to your computer and use it in GitHub Desktop.
Piss Pott Ohne Raceconditions mit Semaphoren
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <sys/types.h> | |
#include <sys/ipc.h> | |
#include <sys/shm.h> | |
#include <sys/sem.h> | |
#include <sys/wait.h> | |
#include <errno.h> | |
#include <string.h> | |
#define MAXCOUNT ((FUSS_B+FUSS_A)*17) | |
#define FUSS_B 15.51337 | |
#define FUSS_A 13.13123 | |
#define SHM_ERROR "Shared Memory konnte nicht erstellt werden!\n" | |
#define FORK_ERROR "fork() konnte keinen Kindprozess erzeugen!\n" | |
#define SEM_ERROR "Fehler bei Semaphore !\n" | |
int main(int argc, char * argv[]) | |
{ | |
/* Hilfsvariablen*/ | |
int i, sleep_time; | |
if(argc <= 1) | |
{ | |
fprintf(stderr,"Zeit in us angeben !\n"); | |
return EXIT_FAILURE; | |
} | |
sleep_time = strtol(argv[1],NULL,10); | |
/* Semaphore initialisieren*/ | |
int sem_id,sem_check; | |
unsigned short marker[1]; | |
sem_id = semget (IPC_PRIVATE, 1, IPC_CREAT|0644); /*anlegen*/ | |
if(sem_id == -1) | |
{ | |
fprintf(stderr,SEM_ERROR); | |
return EXIT_FAILURE; | |
} | |
marker[0] = 1; | |
sem_check=semctl(sem_id, 1, SETALL, marker); | |
if(sem_check < 0) | |
{ | |
fprintf(stderr,SEM_ERROR); | |
return EXIT_FAILURE; | |
} | |
/* PIDs der Kindprozesse*/ | |
int pid[2]; | |
/*Shared Memory fuer IPS*/ | |
int *sperr_fuer_kind,id_sperr,id; | |
id_sperr = shmget( IPC_PRIVATE, sizeof(int),0600); | |
if(id_sperr == -1) | |
{ | |
fprintf(stderr,SHM_ERROR); | |
return EXIT_FAILURE; | |
} | |
sperr_fuer_kind = (int*)shmat(id_sperr,0,0); | |
if(sperr_fuer_kind == NULL) | |
{ | |
fprintf(stderr,SHM_ERROR); | |
return EXIT_FAILURE; | |
} | |
/*Shared Memory fuer PissPott*/ | |
double *area; | |
id = shmget( IPC_PRIVATE, sizeof(double),0600); | |
if(id == -1) | |
{ | |
fprintf(stderr,SHM_ERROR); | |
return EXIT_FAILURE; | |
} | |
area = (double*)shmat(id,0,0); | |
if(area == NULL) | |
{ | |
fprintf(stderr,SHM_ERROR); | |
return EXIT_FAILURE; | |
} | |
/* Semaphore Strukturen zum sperren und freigeben*/ | |
struct sembuf enter, leave; | |
enter.sem_num = 0; /* Semaphor 0 in der Gruppe*/ | |
enter.sem_op = -1; /* blockieren*/ | |
enter.sem_flg = SEM_UNDO; | |
leave.sem_num = 0; /* Semaphor 0 in der Gruppe*/ | |
leave.sem_op = 1; /* freigeben*/ | |
leave.sem_flg = SEM_UNDO; | |
/* Bereich zuruecksetzen*/ | |
*area = MAXCOUNT; | |
*sperr_fuer_kind = 0; | |
/* 1 Kindprozesse erzeugen*/ | |
pid[0] = fork(); | |
if(pid[0] == -1) | |
{ | |
fprintf(stderr,FORK_ERROR); | |
return EXIT_FAILURE; | |
} | |
if(pid[0] == 0) /* KIND 1*/ | |
{ | |
while(1) | |
{ | |
/*KRITISCHER BEREICH BETRETEN*/ | |
if( semop(sem_id,&enter,1) < 0) | |
{ | |
fprintf(stderr,SEM_ERROR); | |
return EXIT_FAILURE; | |
} | |
if(*sperr_fuer_kind == 1 && *area > 0){ | |
/*KRITISCHER BEREICH VERLASSEN*/ | |
if( semop(sem_id,&leave,1) < 0) | |
{ | |
fprintf(stderr,SEM_ERROR); | |
return EXIT_FAILURE; | |
} | |
continue; | |
} | |
if(*area > 0) | |
{ | |
*area -= FUSS_A; | |
}else{break;} | |
*sperr_fuer_kind = 1; | |
/*KRITISCHER BEREICH VERLASSEN*/ | |
if( semop(sem_id,&leave,1) < 0) | |
{ | |
fprintf(stderr,SEM_ERROR); | |
return EXIT_FAILURE; | |
} | |
printf("POTT - %lf\n",*area); | |
fflush(stdout); | |
usleep(sleep_time); | |
} | |
return EXIT_SUCCESS; | |
} | |
else | |
{ | |
/* 2 Kindprozesse erzeugen*/ | |
pid[1] = fork(); | |
if(pid[1] == -1) | |
{ | |
fprintf(stderr,FORK_ERROR); | |
return EXIT_FAILURE; | |
} | |
if(pid[1] == 0) /* KIND 2*/ | |
{ | |
while(1) | |
{ | |
/*KRITISCHER BEREICH BETRETEN*/ | |
if( semop(sem_id,&enter,1) < 0) | |
{ | |
fprintf(stderr,SEM_ERROR); | |
return EXIT_FAILURE; | |
} | |
if(*sperr_fuer_kind == 2 && *area > 0){ | |
/*KRITISCHER BEREICH VERLASSEN*/ | |
if( semop(sem_id,&leave,1) < 0) | |
{ | |
fprintf(stderr,SEM_ERROR); | |
return EXIT_FAILURE; | |
} | |
continue; | |
} | |
if(*area > 0) | |
{ | |
*area -= FUSS_B; | |
}else{break;} | |
*sperr_fuer_kind = 2; | |
/*KRITISCHER BEREICH VERLASSEN*/ | |
if( semop(sem_id,&leave,1) < 0) | |
{ | |
fprintf(stderr,SEM_ERROR); | |
return EXIT_FAILURE; | |
} | |
printf("PISS - %lf\n",*area); | |
fflush(stdout); | |
usleep(sleep_time); | |
} | |
return EXIT_SUCCESS; | |
} | |
/* VATER wartet auf alle Kinder*/ | |
for(i=0;i<2;i++) | |
{ | |
waitpid(*(pid+i),NULL,0); | |
} | |
} | |
/* Semaphore freigeben*/ | |
semctl(sem_id, 0, IPC_RMID); | |
/* ENDE*/ | |
/* return EXIT_SUCCESS;*/ | |
if(*area < 0.1 && *area > -0.1) | |
{ | |
/* Shared Memory loesen*/ | |
shmdt(area); | |
shmdt(sperr_fuer_kind); | |
shmctl(id, IPC_RMID, 0); | |
shmctl(id_sperr, IPC_RMID, 0); | |
printf("OK\n"); | |
return EXIT_SUCCESS; | |
} | |
else | |
{ | |
/* Shared Memory loesen*/ | |
shmdt(area); | |
shmdt(sperr_fuer_kind); | |
shmctl(id, IPC_RMID, 0); | |
shmctl(id_sperr, IPC_RMID, 0); | |
printf("Nicht OK\n"); | |
return EXIT_FAILURE; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment