ZSO – Drugi projekt Justyny

Użyte:

– named-pipe

– sygnały

– pamięć dzielona (shared memory)

Treść:

Jeden proces (master) komunikuje się z wieloma innymi (slaves). Komunikacja jest periodyczna, ma charakter pytanie/odpowiedź, odbywa się za pomocą pamięci dzielonej. Master posiada listę podległych procesów. Wysłanie sygnału do slave’a powoduje, że ten powiadamia mastera poprzez named pipe, że kończy pracę. Master przestaje dalej zajmować się nim.

Rozwiązanie na ile poprawne nie wiem, ale chyba działa tak jak w poleceniu. Z tego co pamiętam to funkcja z obsługą sygnału powinna być 'krótka’, a tutaj w niej otwiera named-pipe, wysyła, czyta itd.:

/*Jeden proces (master) komunikuje się z wieloma innymi (slaves). Komunikacja jest periodyczna, ma charakter pytanie/odpowiedź, odbywa się za pomocą pamięci dzielonej. Master posiada listę podległych procesów. Wysłanie sygnału do slave’a powoduje, że ten powiadamia mastera poprzez named pipe, że kończy pracę. Master przestaje dalej zajmować się nim.*/
// szukanie PID slave: ps a | grep zso2 | grep S+
// kompilacja: g++ zso2.cpp -lstdc++ -o zso2

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <sys/signalfd.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>

#define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

int N = 10; // ilosc slave
static void otrzymanoSygnal(int numerSygnalu);
int rodzic = 0; // czy rodzic
int czyOtrzymanoOdpowiedz=0;
int pipeOdbierajacy;
char buffer[20];
int i=0;
long int pid;
long int* dzieci;

int main()
{
	struct sigaction akcja;
	akcja.sa_handler = otrzymanoSygnal;
	akcja.sa_flags = 0;
	sigaction(SIGINT, &akcja, NULL);
	sigaction(SIGQUIT, &akcja, NULL);
	dzieci = (long int *) malloc(sizeof(long int) * N);
	for(i=0;i<N;i++)
	{
		dzieci[i] = 0;
	}
	int sms;
	key_t key = ftok(".", 666);
	char *segptr;
	pid = getpid();
	sprintf(buffer, "%ld.namedpipe", pid);
	printf("Tworze named-pipe %s do odbierania. \n", buffer);
	if(mkfifo(buffer,0666) != 0)
	{
		handle_error("Nie udalo sie utworzyc named-pipe'a do odbierania.");
	}
	rodzic=0;
	for(i=0; i<N; i++) // robienie dzieci
	{
		printf("FORK\n");
		dzieci[i] = fork();
		if (dzieci[i] > 0)
		{
			rodzic=1;
		}
		else
		{
			rodzic=0;
			break;
		}
	}

	sms = shmget(key, sizeof(char)*25, IPC_CREAT | 0660);
	// mapowanie pamieci
	segptr = (char*)shmat(sms, NULL, 0);
	if (rodzic == 1) 
	{
		while(1)
		{
			// czas pomiedzy seriami pytan/odpowiedzi
			sleep(2);
			for(i=0; i<N;i++)
			{
				if(dzieci[i] == 500)
				{
					continue;
				}
				// czas pomiedzy pytaniami do konkretnych dzieci
				usleep(200000);
				strcpy(segptr, "Ala ma kota.");
				printf("Master wysyla informacje %s do slave %d \n", segptr, i);
				int zwrot = kill(dzieci[i], SIGINT);  
				while(czyOtrzymanoOdpowiedz==0)
				{
					pause();
				}
				czyOtrzymanoOdpowiedz=0;
				printf("Master dostal informacje %s od dziecka %d. \n", segptr, i);
			}
		}
	}
	else
	{
		printf("DZIECKO: rusza %d \n", i);
		while(1)
		{
			pause();
			printf("Dziecko %d dostalo komunikat %s \n", i, segptr);
			strcpy(segptr, "Kot ma Ale.");
			printf("Dziecko %d wysyla informacje %s do mastera \n", i, segptr);
			int zwrot = kill(pid, SIGINT);
		}
	}
}

static void otrzymanoSygnal(int numerSygnalu)
{
	if(rodzic==1)
	{
		if(numerSygnalu==SIGINT)
		{
			// przerywa pause()
			czyOtrzymanoOdpowiedz=1;
		}
		else if (numerSygnalu==SIGQUIT)
		{
			sprintf(buffer, "%ld.namedpipe", pid);
			printf("RODZIC: Otwieram named-pipe %s\n", buffer);
			pipeOdbierajacy = open(buffer, O_RDONLY);
			if(pipeOdbierajacy == -1)
			{
				printf("Nie udalo sie otworzyc fifo odbierajacego.\n");
				exit(1);
			}
			char b[10];
			int ret = read(pipeOdbierajacy, b, sizeof(b));
			if(ret <= 0)
			{
				printf("Funkcja read zwrocila error dla slave.\n");
				perror(NULL);
				exit(1);
			}
			// zamieniam ID dziecka przeslane jako char* 10 znakowy (np. "0000000003") na 'int' o wartosci '3' [funkcja 'atoi']
			int idDziecka = atoi(b);
			printf("RODZIC: Dziecko o numerze %d usuniete z listy\n", idDziecka);
			dzieci[idDziecka] = 500;
			close(pipeOdbierajacy);
		}
	}
	else
	{
		if(numerSygnalu==SIGINT)
		{
			// przerywa pause()
		}
		else if (numerSygnalu==SIGQUIT)
		{
			int zwrot = kill(pid, SIGQUIT);
			sprintf(buffer, "%ld.namedpipe", pid);
			printf("DZIECKO KAMIKAZE: Otwieram named-pipe %s\n", buffer);
			int pipeWysylajacy = open(buffer, O_WRONLY);
			if(pipeWysylajacy == -1)
			{
				printf("Nie udalo sie otworzyc fifo wysylajacego.\n");
				perror(NULL);
				exit(1);
			}
			// zamiana 'int' na 'char*' z dodaniem zer przed liczba jesli jest krotsza niz 10 znakow
			char b[10];
			sprintf(b, "%010d", i);
			// przepisujemy tresc z buffor na wyjscie do master
			int ret = write(pipeWysylajacy, b, sizeof(b));
			if(ret == -1)
			{
				printf("Funkcja write zwrocila error.\n");
				perror(NULL);
				exit(1);
			}
			close(pipeWysylajacy);
			exit(1);
		}
	}
}

 

 

Ten wpis został opublikowany w kategorii PJWSTK, PJWSTK - ZSO. Dodaj zakładkę do bezpośredniego odnośnika.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *