Created
June 1, 2012 13:02
-
-
Save stetro/2851989 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> | |
#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!" | |
#define FORK_ERROR "fork() konnte keinen Kindprozess erzeugen!" | |
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; | |
unsigned short marker[1]; | |
sem_id = semget (IPC_PRIVATE, 1, IPC_CREAT|0644); /*anlegen*/ | |
if(sem_id == -1) | |
{ | |
fprintf(stderr,"Fehler bei Semaphore !\n"); | |
return EXIT_FAILURE; | |
} | |
marker[0] = 1; | |
semctl(sem_id, 1, SETALL, marker); | |
/* PIDs der Kindprozesse*/ | |
int pid[2]; | |
/* Shared Memorys generieren und bei Fehlern aussteigen*/ | |
double *area,id; | |
int *sperr_fuer_kind,id_sperr; | |
id = shmget( IPC_PRIVATE, 2*sizeof(double),0600); | |
if(id == -1) | |
{ | |
fprintf(stderr,SHM_ERROR); | |
return EXIT_FAILURE; | |
} | |
id_sperr = shmget( IPC_PRIVATE , sizeof(int),0600); | |
if(id_sperr == -1) | |
{ | |
fprintf(stderr,SHM_ERROR); | |
return EXIT_FAILURE; | |
} | |
area = (double*)shmat(id,0,0); | |
if(area == NULL) | |
{ | |
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; | |
} | |
/* 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) | |
{ | |
semop(sem_id,&enter,1); /* Eintritt in kritischen Bereich*/ | |
if(*sperr_fuer_kind == 1 && *area > 0){ | |
semop(sem_id,&leave,1); /* Verlassen des krit. Bereichs*/ | |
continue; | |
} | |
if(*area > 0) | |
{ | |
*area -= FUSS_A; | |
}else{break;} | |
*sperr_fuer_kind = 1; | |
semop(sem_id,&leave,1); /* Verlassen des krit. Bereichs*/ | |
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) | |
{ | |
semop(sem_id,&enter,1); /* Eintritt in kritischen Bereich*/ | |
if(*sperr_fuer_kind == 2 && *area > 0){ | |
semop(sem_id,&leave,1); /* Verlassen des krit. Bereichs*/ | |
continue; | |
} | |
if(*area > 0) | |
{ | |
*area -= FUSS_B; | |
}else{break;} | |
*sperr_fuer_kind = 2; | |
semop(sem_id,&leave,1); /* Verlassen des krit. Bereichs*/ | |
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