====== Projekt 2 ====== ===== Makefile ===== CXX = gcc RM = rm -f #CFLAGS = -pedantic -Wall -ansi -g0 -s -O3 CFLAGS = -std=gnu99 -Wall #-g0 -s -O3 .PHONY : all all : proj2a proj2b proj2a: proj2a.o $(CXX) $(CFLAGS) -o $@ proj2a.o proj2b: proj2b.o $(CXX) $(CFLAGS) -o $@ proj2b.o %.o : %.c $(CXX) $(CFLAGS) -c $< -o $@ ### Zavislosti modulu proj2a.o : proj2a.c proj2b.o : proj2b.c clean: $(RM) *.o core proj2a proj2b ===== proj2a.c ===== #include #include #include #include #include #include #include #define MAX_CUSTOMERS 99 volatile sig_atomic_t customer_cut = 0, customer_sit = 0; // SIGUSR1 signal handler void sig_usr1_func(int signal) { customer_sit = 1; } // SIGUSR2 signal handler void sig_usr2_func(int signal) { customer_cut = 1; } // Customer function void customer(unsigned int num) { sigset_t block_mask, old_mask; // Wait for calling by barber sigemptyset (&block_mask); sigaddset (&block_mask, SIGUSR1); sigprocmask (SIG_BLOCK, &block_mask, &old_mask); kill(getppid(), SIGUSR2); while (!customer_sit) { sigsuspend(&old_mask); } sigprocmask (SIG_UNBLOCK, &block_mask, NULL); customer_sit = 0; printf("customer %d is taking a chair\n", num); // Sitted kill(getppid(), SIGUSR2); // Wait for cutting sigemptyset (&block_mask); sigaddset (&block_mask, SIGUSR1); sigprocmask (SIG_BLOCK, &block_mask, &old_mask); while (!customer_sit) { sigsuspend(&old_mask); } sigprocmask (SIG_UNBLOCK, &block_mask, NULL); printf("customer %d is leaving\n", num); // Leaves exit(0); } // Barber function void barber(pid_t pid, unsigned int num) { sigset_t block_mask, old_mask; // Wait for sitting sigemptyset (&block_mask); sigaddset (&block_mask, SIGUSR1); sigprocmask (SIG_BLOCK, &block_mask, &old_mask); while (!customer_cut) { sigsuspend(&old_mask); } sigprocmask (SIG_UNBLOCK, &block_mask, NULL); printf("barber cuts a customer number %u\n", num); // Cuts done kill(pid, SIGUSR1); int status; // Waits for customer leaves waitpid(pid, &status, 0); } // Main function int main(int argc, char *argv[]) { pid_t pid; sigset_t block_mask, old_mask; setbuf(stdout, NULL); // Handle input params if (argc != 2) { fprintf(stderr, "Spatne vstupni parametry, zadejte pocet zakazniku!\n"); return -1; } int count = atoi(argv[1]); if (count < 0 || count > MAX_CUSTOMERS) { fprintf(stderr, "Pocet zakazniku musi byt v rozsahu 0 az %d\n", MAX_CUSTOMERS); return -2; } // SIGUSR1+2 handlers sigset_t block_set; struct sigaction usr_action; sigfillset (&block_set); usr_action.sa_handler = sig_usr1_func; usr_action.sa_mask = block_set; usr_action.sa_flags = 0; sigaction (SIGUSR1, &usr_action, NULL); sigfillset (&block_set); usr_action.sa_handler = sig_usr2_func; usr_action.sa_mask = block_set; usr_action.sa_flags = 0; sigaction (SIGUSR2, &usr_action, NULL); // Fork customers processes int i=0; pid_t customers[MAX_CUSTOMERS]; while (i < count) { if ((pid = fork()) == 0) { customer_sit = 0; customer_cut=0; customer(i); // Wait for customer thread is ready sigemptyset (&block_mask); sigaddset (&block_mask, SIGUSR1); sigprocmask (SIG_BLOCK, &block_mask, &old_mask); while (!customer_cut) { sigsuspend(&old_mask); } customer_cut = 0; sigprocmask (SIG_UNBLOCK, &block_mask, NULL); } else { customers[i] = pid; } i++; } // Cuts customers by barber i = 0; while (i < count) { customer_cut = 0; kill(customers[i], SIGUSR1); barber(customers[i], i); i++; } printf("barber finished\n"); return 0; } ===== proj2b.c ===== #include #include #include #include #include #include #include #define MSGID 1004 //id zprav... 1000 + cislo skupiny typedef struct msgbuf { //pro zakaznika mtype = 1 //pro holice, ze je zakaznik ready mtype = 2 //pro oholeneho zakaznika mtype = 3 //signal, ze holic ma volnou sedacku mtype = 4 long mtype; int mtext; //predava se cislo zakaznika }TMSGBUF; void customer(int cid, int msqid); void barber(int argc, char* argv[], int msqid); //Vytvoreni procesu int ProcCreate(int argc, char *argv[], int msqid); //Vytvoreni fronty - vraci hodnotu fronty int MsgCreate(void); //Zniceni fronty void MsgDestroy(int msqid); /* * Hlavni program */ int main(int argc, char *argv[]) { setbuf(stdout,NULL); int msqid = 0; if(argc == 1) { fprintf(stderr, "proj2b: Chyba, predano malo parametru!\n"); exit(EXIT_FAILURE); } if(argc > 2) { fprintf(stderr, "proj2b: Chyba, predano prilis mnoho parametru!\n"); exit(EXIT_FAILURE); } //vytvoreni msg fronty msqid = MsgCreate(); if((ProcCreate(argc, argv, msqid)) != 0) { fprintf(stderr, "proj2b: Nastala neznama chyba pri vytvareni potomku.\n"); MsgDestroy(msqid); exit(EXIT_FAILURE); } MsgDestroy(msqid); return EXIT_SUCCESS; } //vytvoreni procesu int ProcCreate(int argc, char* argv[], int msqid) { int procs = 0, i = 0, pid = 0; //Prevos parametru na cislo. if((procs = atoi(argv[1])) <= 0) //Musi byt kladny. { fprintf(stderr, "proj2b: Chybny parametr '%s'.\n", argv[1]); MsgDestroy(msqid); exit(EXIT_FAILURE); } //vytvoreni potomku for(i = 0; i < procs; i++) { pid = fork(); if (pid == -1) { fprintf(stderr, "proj2b: Nastala chyba pri vytvareni potomka.\n"); MsgDestroy(msqid); exit(EXIT_FAILURE); } else if(pid == 0) { customer(i, msqid); exit(EXIT_SUCCESS); } } barber(argc, argv, msqid); return 0; } //Vytvoreni fronty int MsgCreate(void) { int msqid = 0; if((msqid = msgget(MSGID, 0666 | IPC_CREAT)) == -1) { //chyba pri vytvoreni fronty fprintf(stderr, "proj2b: Chyba pri vytvareni fronty.\n"); exit(EXIT_FAILURE); } return msqid; } //Zniceni fronty void MsgDestroy(int msqid) { msgctl(msqid, IPC_RMID, NULL); return; } /* * Zakzanik */ void customer(int cid, int msqid) { TMSGBUF msg; if(msgrcv(msqid, &msg, sizeof(msg), 1, 0) < 0) //cekam na zidli { fprintf(stderr, "proj2b: Chyba pri prijmu zpravy.\n"); MsgDestroy(msqid); exit(EXIT_FAILURE); } printf("customer %d is taking a chair\n", cid); msg.mtype = 2; //zakaznik sedi msg.mtext = cid; if(msgsnd(msqid, &msg, sizeof(msg), 0) < 0) { fprintf(stderr, "proj2b: Chyna pri odesilani zpravy.\n"); MsgDestroy(msqid); exit(EXIT_FAILURE); } if(msgrcv(msqid, &msg, sizeof(msg), 3, 0) < 0) { fprintf(stderr, "Chyba pri prijmu zpravy.\n"); MsgDestroy(msqid); exit(EXIT_FAILURE); } printf("customer %d is leaving\n", cid); msg.mtype = 4; if(msgsnd(msqid, &msg, sizeof(msg), 0) < 0) { fprintf(stderr,"proj2b: Chyba pri odesilani zpravy.\n"); MsgDestroy(msqid); exit(EXIT_FAILURE); } } /* * Holic */ void barber(int argc, char* argv[], int msqid) { TMSGBUF msg; int procs = 0, i = 0, custid = -1; if((procs = atoi(argv[1])) <= 0) { fprintf(stderr, "proj2b: Chybny parametr '%s'.\n", argv[1]); MsgDestroy(msqid); exit(EXIT_FAILURE); } for(i = 0; i < procs; i++) { msg.mtype = 1; //je volna zidle if(msgsnd(msqid, &msg, sizeof(msg), 0) < 0) { fprintf(stderr, "proj2b: Doslo k chybe pri zasilani zpravy.\n"); MsgDestroy(msqid); exit(EXIT_FAILURE); } //zakaznik si sedl if(msgrcv(msqid, &msg, sizeof(msg), 2, 0) < 0) { fprintf(stderr, "proj2b: Doslo k chybe pri prijmu zpravy.\n"); MsgDestroy(msqid); exit(EXIT_FAILURE); } else { custid = msg.mtext; printf("barber cuts a customer number %d\n", custid); msg.mtype = 3; //slez ze zidle, chci dalsiho //vystrel ze zidle if(msgsnd(msqid, &msg, sizeof(msg), 0) < 0) { fprintf(stderr, "proj2b: Doslo k chybe pri zasilani zpravy.\n"); MsgDestroy(msqid); exit(EXIT_FAILURE); } } //zidle je volna, muzu zavolat dalsiho if(msgrcv(msqid, &msg, sizeof(msg), 4, 0) < 0) { fprintf(stderr, "proj2b: Chyba pri prijmu zpravy.\n"); MsgDestroy(msqid); exit(EXIT_FAILURE); } } printf("barber finished\n"); return; }