// Slave // kompilacja: g++ slave.cpp -o slave && ./slave /* Jeden proces (master) oczekuje na pojawienie się podległych mu procesów (slaves). Za pomocą dodatkowego procesu możemy startować podległe procesy. Nowy proces wysyła masterowi sygnał, że się pojawił i poprzez kolejkę komunikatów przekazuje mu namiary na siebie. Od tego momentu master zaczyna komunikować się z nowopowstałym slave’wem periodycznie, według wzorca pytanie/odpowiedź poprzez named pipes, co slave uwidacznia. */ #include #include #include #include #include #include #include #include #define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) // prosta funkcja zwracajaca czas struct timeval czas; int ret; // zmienna przyjmujaca zwracana wartosc z paru funkcji w programie char* getTime() { ret = gettimeofday(&czas, NULL); char* buffer = (char *) malloc(sizeof(char) * 18); if(ret == 0) { sprintf(buffer, "%ld.%06ld:", czas.tv_sec, czas.tv_usec); } else { strcpy(buffer, "Error:"); } return buffer; } // struktura do przesylania przez kolejke komunikatow (FIFO) struct Komunikat { // pierwszy w strukturze MUSI byc 'long int' [o dowolnej nazwie], // w nim bedzie przechowywany 'typ' komunikatu // w funkcji ktora pobieramy komunikaty: // msgrcv(kolejkaKomunikatowID, &komunikat, sizeof(struct Komunikat), 1, 0); // ta '1' to wlasnie typ komunikatu jaki chcemy otrzymac // (proces 'slave' przed wyslaniem komunikatu ustawia w strukturze typ na '1') long int typeKomunikatu; long int pid; }; int main(int argc, char *argv[]) { long int pid = (long int) getpid(); char buffer [50]; int kolejkaKomunikatowID; int pipeWysylajacy; int pipeOdbierajacy; Komunikat komunikat; // tworzymy named pipe do wysylania i odbierania sprintf(buffer, "%ld.to_master", pid); printf("Tworze named-pipe %s\n", buffer); if(mkfifo(buffer,0666) != 0) { handle_error("Nie udalo sie utworzyc named-pipe'a do wysylania."); } sprintf(buffer, "%ld.to_slave", pid); printf("Tworze named-pipe %s\n", buffer); if(mkfifo(buffer,0666) != 0) { handle_error("Nie udalo sie utworzyc named-pipe'a do odbierania."); } // wysylamy sygnal, zeby proces master zaczal czekac na nasz komunikat printf("Wysylam sygnal SIGINT do masterProcess\n"); system("killall -2 masterProcess"); // pobieramy ID kolejki komunikatow [utworzonej przez proces master] printf("Pobieram ID kolejki komunikatow\n"); if((kolejkaKomunikatowID = msgget(123, 0660)) == -1) { printf("Nie udalo sie pobrac ID kolejki o podanym kluczu.\n"); return EXIT_FAILURE; } // ustalamy typ komunikatu na 1, taki typ bedziemy pobierac w programie 'master' funkcja 'msgrcv' komunikat.typeKomunikatu = 1; // przesylamy PID aktualnego procesu, // bo utworzylismy named-pipe o nazwach zawierajacych pid 'slave' // ("tu_pid.to_master" i "tu_pid.to_slave") komunikat.pid = pid; printf("Wysylam komunikat\n"); if(msgsnd(kolejkaKomunikatowID, &komunikat, sizeof(struct Komunikat), 0) == -1) { handle_error("Nie udalo sie wyslac komunikatu."); } // komunikat wyslany, sygnal wyslany, named-pipe utworzone [ale nie otwarte] // teraz otwieramy named-pipe sprintf(buffer, "%ld.to_master", pid); printf("Otwieram named-pipe %s\n", buffer); pipeWysylajacy = open(buffer, O_WRONLY); if(pipeWysylajacy == -1) { printf("Nie udalo sie otworzyc fifo wysylajacego.\n"); return EXIT_FAILURE; } sprintf(buffer, "%ld.to_slave", pid); printf("Otwieram named-pipe %s\n", buffer); pipeOdbierajacy = open(buffer, O_RDONLY); if(pipeOdbierajacy == -1) { printf("Nie udalo sie otworzyc fifo odbierajacego.\n"); return EXIT_FAILURE; } // teraz zaczynamy w petli wysylac 'DZIALA?' i odbierac co nam master napisze while(true) { // wstawiamy do buffer wysylany tekst strcpy(buffer,"DZIALA?"); // przepisujemy tresc z buffor na wyjscie do master ret = write(pipeWysylajacy, buffer, sizeof(buffer)); if(ret == -1) { printf("Funkcja write zwrocila error.\n"); perror(NULL); return EXIT_FAILURE; } printf("Wyslano %d znakow do %ld tresc: %s\n", ret, komunikat.pid, buffer); // wypelniamy buffer trescia z wejscia od master // jesli master przestanie pisac to 'read' stanie w miejscu :( ret = read(pipeOdbierajacy, buffer, sizeof(buffer)); if(ret <= 0) { printf("Funkcja read zwrocila error.\n"); perror(NULL); return EXIT_FAILURE; } printf("Odczytano %d znakow od %ld tresc: %s\n", ret, komunikat.pid, buffer); // petla nie ma zadnego 'sleep', bo funkcja 'read' zablokuje sie do czasu, // az master wpisze odpowiedz ('DZIALA!'), wiec to master odpowiada za 'periodycznosc' } }