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