====== 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;
}