Obsah

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 <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/msg.h>
#include <signal.h>
#include <unistd.h>
 
#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 <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <string.h>
 
#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;
}