Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h> //knihovna pro vstupy a výstupy
- #include <stdlib.h> //knihovna pro různé funkce
- #include <ctype.h> //knihovna pro testování a mapování znaků
- #include <string.h> //knihovna pro práci se stringy
- #include <unistd.h> //knihovna pro definici různých symbolických konstant a typů a pro různé funkce
- #include <signal.h> //knihovna pro inicializaci signálů
- #include <sys/wait.h> //knihovna deklarace pro čekání
- #include <sys/types.h> //knihovna datových typů
- #include <sys/shm.h> //knihovna pro sdílenou pamět
- #include <sys/ipc.h> //knihovna pro meziprocesovou komunikaci
- #include <sys/stat.h> //data vrácena ze stat() function
- #include <sys/sem.h> //knivna pro semafory
- #include <semaphore.h> //knihovna pro semafory
- #include <fcntl.h> //knihovna pro kontrolu souborů (nastavení)
- #include <sys/mman.h> //knihovna pro správu paměti
- #include <sched.h> //knihovna plánování
- #include <pthread.h> //knihovna pro vlákna
- #include <time.h> //knihovna pro zjištění času
- /************************************************* Definice maker *************************************************/
- #define CHYBA_PARAM 1
- #define CHYBA_POCET 2
- #define SYS_ERROR 2
- #define CHYBA_ARG1 3
- #define CHYBA_ARGS 4
- #define CHYBA_FORK 5
- /************************************************* Deklarace struktury s proměnnými *************************************************/
- typedef struct parametry{
- int O; // O = počet procesů kyslíku
- int H; //H = vodík,2x počet procesů kyslíku,
- int GH; //GH = maximální hodnota doby (v milisekundách), po které je generován nový proces pro vodík
- int GO; //GO = maximální hodnota doby (v milisekundách), po které je generován nový proces pro vodík
- int B; //B je maximální hodnota doby (v milisekundách) provádění funkce bond
- char *F; //název výstup. souboru
- }Tparam;
- /*Deklarace globálních proměnných*/
- sem_t *s_hydrogen,*s_oxygen,*s_citac_h,*s_citac_o,*s_citac,*s_zap,*s_predbeh,*s_bond;
- /************************************************** Funkční prototypy **************************************************/
- void napoveda(); //nápověda
- void oxygen(int i); //funkce kyslíku
- void hydrogen(int i); //funkce vodíku
- void boned(); //funkce na spojení atomů
- int nacteni_zdroju(void); //funkce pro načtení zdrojů
- void uklid(void); //funkce na úklid
- int chyba(int cislo); //funkce pro chyby
- int zpracovani_argumentu(int argc,char *argv[],Tparam *x); //funkce na zpracování argumentů
- /*************************************************** Funkce pro nápovědu ***************************************************/
- void napoveda(){
- printf("Autor: Jan Nosál\n"
- "Datum vytvoření: 11.4.2015\n"
- "Název úlohy: Building H20\n"
- "Popis úlohy: Implementujte v jazyce C modifikovaný synchronizační problém Building H20 (můžete se inspirovat knihou The Little Book of Semaphores). Existují dva typy procesů, kyslík a vodík. Aby se mohly spojit do molekuly vody, musí se počkat na příchod příslušných atomů, tj. jeden atom kyslíku a dva atomy vodíku. Poté se spojí do molekuly vody a proces se opakuje.\n");
- }
- /*************************************************** Funkce pro oxygen ***************************************************/
- void oxygen(int i){
- printf("O %d Child proces kysliku %d PPID: %d\n",i,getpid(),getppid());
- /* fprintf"%d: O %d: started",cislo_akce_fce(cislo_akce),i);
- fprintf(zapis,"%d: O %d: ready",cislo_akce_fce(cislo_akce),i);
- fprintf(zapis,"%d: O %d: begin bonding",cislo_akce_fce(cislo_akce),i);
- fprintf(zapis,"%d: O %d: bonded",cislo_akce_fce(cislo_akce),i);
- fprintf(zapis,"%d: O %d: finished",cislo_akce_fce(cislo_akce),i);
- */
- exit(0);
- }
- /*************************************************** Funkce pro hydrogen ***************************************************/
- void hydrogen(int i){
- printf("H %d Child proces vodiku %d PPID: %d\n",i,getpid(),getppid());
- /* fprintf(zapis,"%d: H %d: started",cislo_akce_fce(cislo_akce),i);
- fprintf(zapis,"%d: H %d: waiting",cislo_akce_fce(cislo_akce),i);
- fprintf(zapis,"%d: H %d: begin bonding",cislo_akce_fce(cislo_akce),i);
- fprintf(zapis,"%d: H %d: bonded",cislo_akce_fce(cislo_akce),i);
- fprintf(zapis,"%d: H %d: finished",cislo_akce_fce(cislo_akce),i);
- */
- exit(0);
- }
- /*************************************************** Funkce na spojení atomů ****************************************************/
- void boned(){
- exit(0);
- }
- /*************************************************** Funkce pro načtení zdrojů ***************************************************/
- int init_zdroju(void){
- /*SEMAFORY*/
- int chyba = 0;
- //s_hydrogen = semafor vodíku
- //s_oxygen = semafor kyslíku
- //s_bond = semafor pro konec spojování
- //s_citac_h = vylucný pristup k citaci vodiku
- //s_citac_o = vylucný pristup k citaci kysliku
- //s_citac = = vylucný pristup k citaci akci
- //s_predbeh = semafor na hlidani, aby se kyslik a vodik nepredbehly
- //s_zap = vylucny pristup k souboru
- if((s_hydrogen = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED){chyba = 2;}
- if((s_oxygen = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) {chyba = 2;}
- if((s_bond = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) {chyba = 2;}
- if((s_citac_h = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) {chyba = 2;}
- if((s_citac_o = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) {chyba = 2;}
- if((s_citac = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) {chyba = 2;}
- if((s_predbeh = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) {chyba = 2;}
- if((s_zap = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) {chyba = 2;}
- if(chyba == 0) {
- if(sem_init(s_hydrogen, 1, 0) == -1) {chyba = 2;}
- if(sem_init(s_oxygen, 1, 0) == -1) {chyba = 2; }
- if(sem_init(s_bond, 1, 0) == -1) {chyba = 2; }
- if(sem_init(s_citac_h, 1, 0) == -1) {chyba = 2;}
- if(sem_init(s_citac_o, 1, 0) == -1) {chyba = 2;}
- if(sem_init(s_citac, 1, 0) == -1) {chyba = 2;}
- if(sem_init(s_predbeh, 1, 0) == -1) {chyba = 2;}
- if(sem_init(s_zap, 1, 0) == -1) {chyba = 2;}
- }
- /*KONEC SEMAFORŮ*/
- /*INICIALIZACE SDÍLENÉ PAMĚTI*/
- /*KONEC SDÍLENÉ PAMĚTI*/
- return 0;
- }
- /*************************************************** Funkce na chyby ***************************************************/
- int chyba(int cislo){
- switch(cislo){
- case CHYBA_PARAM:
- fprintf(stderr,"Chyba zadani argumentu (argument není číslo nebo je zadán špatný rozsah doby generování atomů)\n");
- break;
- case CHYBA_POCET:
- fprintf(stderr,"Chyba poctu argumentu\n");
- break;
- case CHYBA_ARG1:
- fprintf(stderr,"Počet procesů musí být větší jak nula\n");
- break;
- case CHYBA_ARGS:
- fprintf(stderr,"Maximální hodnota doby generování musí být menší jak 5001\n");
- break;
- case CHYBA_FORK:
- fprintf(stderr,"Fork se nezdařil\n");
- break;
- default: fprintf(stderr,"Doslo k chybe programu\n");
- }
- return 0;
- }
- /*************************************************** Funkce na zpracovnání parametrů ***************************************************/
- int args(int argc,char *argv[],Tparam *x){
- if(argc==5){
- x->O = atoi(argv[1]);
- x->H = 2*x->O;
- x->GH = atoi(argv[2]);
- x->GO = atoi(argv[3]);
- x->B = atoi(argv[4]);
- for(int i = 1;i<5;i++){
- for(int j = 0;argv[i][j] != '\0';j++){
- if(argv[i][j] > '9' || argv[i][j] < '0'){
- chyba(CHYBA_PARAM);
- exit(1);
- }
- }
- }
- if(x->O<=0){
- chyba(CHYBA_ARG1);
- exit(1);
- }
- else if(!(x->GH >= 0 && x->GH < 5001) || !(x->GO >= 0 && x->GO < 5001) || !(x->B >= 0 && x->B < 5001)){
- chyba(CHYBA_ARGS);
- exit(1);
- }
- }
- else if((argc == 2) && (strcmp(argv[1],"--h"))){
- napoveda();
- exit(0);
- }
- else{
- chyba(CHYBA_POCET);
- exit(1);
- }
- return 0;
- }
- /*************************************************** Funkce na úklid ***************************************************/
- void uklid(void){
- int chyba = 0;
- if(chyba == 2){
- if(sem_destroy(s_hydrogen) == -1) { chyba = 2; }
- if(sem_destroy(s_oxygen) == -1) { chyba = 2; }
- if(sem_destroy(s_bond) == -1) { chyba = 2; }
- if(sem_destroy(s_citac_h) == -1) { chyba = 2; }
- if(sem_destroy(s_citac_o) == -1) { chyba = 2; }
- if(sem_destroy(s_citac) == -1) { chyba = 2; }
- if(sem_destroy(s_predbeh) == -1) { chyba = 2; }
- if(sem_destroy(s_zap) == -1) { chyba = 2; }
- }
- if(chyba == 2) { fprintf(stderr, "Semafor se nesmazal\n"); }
- //exit(0);
- }
- /*************************************************** Hlavní funkce ***************************************************/
- int main(int argc,char *argv[]){
- // signal(SIGINT,uklid);
- // signal(SIGKILL,uklid);
- Tparam param;
- args(argc,argv,¶m); //funkce na ověření argumentů
- int init = init_zdroju();
- if(init != 0){
- if(init == 2){
- fprintf(stderr,"Semafor se nevytvořil\n");
- exit(1);
- }
- uklid();
- }
- pid_t pid_hlav,pid_h,pid_o,pid_rod;
- pid_hlav = fork(); //vytvoření hlavního procesu
- if(pid_hlav == 0){ //potomek hlavního procesu
- useconds_t cekani;
- for(int i = 1;i<=param.H;i++){ //generování vodíku
- if(param.GH>0){
- cekani = random()%param.GH*1000;
- usleep(cekani); //čekání na další atom
- }
- pid_h = fork(); //vytvoření procesu pro vodík
- if(pid_h == 0){ //potomek procesu vodíku
- hydrogen(i); //funkce pro vodík
- }
- else if (pid_h > 0){ //rodič procecu vodíku
- waitpid(pid_h,NULL,0);
- }
- else if(pid_h < 0){ //pokud se fork nezdaří
- chyba(CHYBA_FORK);
- exit(SYS_ERROR);
- }
- }
- }
- else if(pid_hlav > 0){ //rodič hlavního procesu
- pid_rod = fork();
- if(pid_rod == 0){
- useconds_t cekani;
- for(int i = 1;i<=param.O;i++){ //generování kyslíku
- if(param.GO>0){
- cekani = random()%param.GO*1000;
- usleep(cekani); //čekání na další atom
- }
- pid_o = fork(); //vytvoření procesu pro kyslík
- if(pid_o == 0){ //potomek procesu pro kyslík
- oxygen(i); //funkce pro kyslík
- }
- else if (pid_o > 0){ //rodič procesu pro kyslík
- waitpid(pid_o,NULL,0);
- }
- else if(pid_o < 0){ //pokud se fork nezdaří
- chyba(CHYBA_FORK);
- exit(SYS_ERROR);
- }
- }
- }
- else if(pid_rod > 0){ //proces rodiče
- waitpid(pid_rod,NULL,0);
- }
- else if(pid_rod < 0){ //pokud se fork nezdařil
- chyba(CHYBA_FORK);
- exit(SYS_ERROR);
- }
- waitpid(pid_hlav,NULL,0);
- }
- else if(pid_hlav < 0){ //pokud se fork nezdaříl
- chyba(CHYBA_FORK);
- exit(SYS_ERROR);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement