Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <string.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #define klawiatura 1
- #define plikNo 2
- #define kluczQueue1 9000
- #define kluczQueue2 9001
- //Deklaracja nazw kolejek
- char* KK1 = "KK1"; //Nazwa koleki z PP1 do PP2
- char* KK2 = "KK2"; //Nazwa koleki z PP2 do PP3
- //Deklaracja intow pod PIDY procesow
- //NextProcess przekazuje informacje o PID nastepnego procesu
- int PP1,PP2,PP3,PM,NextProcess = 0;
- //Deklaracja intow sterujacych procesami
- //work - czy program ma dzialac
- //end - czy program konczy dzialanie
- //stop - czy program ma sie zatrzymac
- int work = 1, end = 0, stop = 0;
- int menu = 1; //Do sprawdzania w jakim stanie znajduje sie PP1. Jak jest w menu to odrazu mozna go zakonczyc
- int kolejkaP1_P2, kolejkaP2_P3; //ID kolejek komunikatow tak jak nazwy
- int fifo; //ID kolejki komunikatow
- //Struktura danych przekazywana do kolejki z PP1 do PP2
- typedef struct msgPP1toPP2 {
- long typ; //Czy cos z tym robic
- char text[64]; //Co przekazuje z PP1 do PP2
- } wiadomosc;
- //Struktura danych przekazywana do kolejki z PP2 do PP3
- typedef struct msgPP2toPP3 {
- long typ;
- int wartosc; // Dlugosc string
- } wiadomosc2;
- void sendtoPP2(char * text); //Deklaracja naglowka funkcji wysylajacej wiadomosc do PP2
- void sendtoPP3(int wartosc); //Deklaracja naglowka funkcji wysylajacej wiadomosc do PP3
- void sendtoPM(int sygnal, siginfo_t *siginfo, void *context); //wyslanie sygnalu do PM
- void sendtoPPS(int sygnal, siginfo_t *siginfo, void *context) ;//Wysylanie sygnalow do PP przez PM
- void readsignal(int sygnal, siginfo_t *siginfo, void *context); //Proces dostal sygnal by odczytal swoja kolejke
- void odbierzSygnalNorm();
- void odbierzSygnalSpecjalny()
- {
- struct sigaction todo; //Struktura sygnalu
- memset (&todo, 0, sizeof (todo)); //ZAalokuj pamiec
- todo.sa_sigaction = &readsignal; //Wywolaj funkcje readsignal
- todo.sa_flags = SA_RESTART; //Jak proces cos grzebal gdy dostal sygnal, to ma powtorzyc dzialanie
- sigaction(12, &todo, NULL); //Wywolaj jak otrzymasz sygnal -12 - 12
- //P2 jak otrzyma sig TERM & TSTP & CONT ma je wysylac do glownego
- struct sigaction todo2;
- memset (&todo2, 0, sizeof (todo2));
- todo2.sa_sigaction = &sendtoPM;
- todo2.sa_flags = SA_RESTART;
- sigaction(SIGTSTP, &todo2, NULL);
- sigaction(SIGCONT, &todo2, NULL);
- sigaction(SIGTERM, &todo2, NULL);
- sigset_t maska;
- sigfillset(&maska); //Tworze pusta maske
- sigdelset(&maska, SIGUSR2); // Dodaje do maski sygnaly
- sigdelset(&maska, SIGCONT); // Dodaje do maski sygnaly
- sigdelset(&maska, SIGTERM); // Dodaje do maski sygnaly
- sigdelset(&maska, SIGTSTP); // Dodaje do maski sygnaly
- sigprocmask(SIG_BLOCK, &maska, NULL); //Blokuj sygnaly z maski
- }
- void mainSygnaly()
- {
- //Rozszerzona struktura do sygnalow - pozwala na pobranie pidu wysylajacego
- //Trzeba to tak zrobic, poniewaz nie da sie jednoczesnie zablokowac sygnal dla konsoli i odblokowac dla P2
- struct sigaction todo;
- memset (&todo, 0, sizeof (todo));
- todo.sa_sigaction = &sendtoPPS;
- todo.sa_flags = SA_RESTART | SA_SIGINFO;
- sigaction(SIGTSTP, &todo, NULL);
- sigaction(SIGCONT, &todo, NULL);
- sigaction(SIGTERM, &todo, NULL);
- sigset_t maska;
- sigfillset(&maska);
- sigdelset(&maska, SIGCONT);
- sigdelset(&maska, SIGTERM);
- sigdelset(&maska, SIGTSTP);
- sigprocmask(SIG_BLOCK, &maska, NULL);
- }
- int main(void)
- {
- //Tworzenie kolejek
- mkfifo(KK1, 0666);
- mkfifo(KK2, 0666);
- kolejkaP1_P2 = open(KK1, O_RDWR);
- kolejkaP2_P3 = open(KK2, O_RDWR);
- mkfifo("fifo", 0666);
- PM = getpid(); //PID PM
- //Tworzymy procesy
- if((PP3 = fork()) == 0)
- {
- odbierzSygnalNorm();
- fifo = open("fifo", O_RDONLY); //Otwieramy KS dla PP3
- wiadomosc2 wiad;
- while(1)
- {
- work = 1;
- while(work){
- if(read(kolejkaP2_P3, &wiad, sizeof(wiad) + 1) != -1){
- menu = 0;
- while(stop); //Czy w czasie dzialania nie dostalismy TSTP i czeka az dostanie CONT
- if(wiad.wartosc == -1){ //Koniec wczytywania
- work = 0;
- if(end) //Jak oflagowalismy koniec programu to konczymy dzialanie PP3
- exit(0);
- }
- if(wiad.wartosc != 0 && wiad.wartosc != -1){
- printf("%d\n", wiad.wartosc); //Wypisuje wartosc > 0
- }
- }
- }
- menu = 1;
- }
- return 0;
- }
- NextProcess = PP3;
- if((PP2 = fork()) == 0){
- odbierzSygnalSpecjalny();
- fifo = open("fifo", O_RDONLY); //Otwieramy KS dla PP2
- wiadomosc wiad;
- while(1){
- work = 1;
- while(work){
- if(read(kolejkaP1_P2, &wiad, sizeof(wiad) + 1) != -1){ //Poprawnie odebrany sygnal
- menu = 0;
- while(stop);
- if(wiad.text[0] == -1 && wiad.text[1] == -1 && wiad.text[2] == -1){
- //Dostalismy info ze PP1 zakonczyc wczytywanie
- sendtoPP3(-1); //Informacja do PP3 o koncu
- work = 0;
- if(end)
- exit(0);
- }else{
- sendtoPP3(strlen(wiad.text) - 1); //Wysyla dlugosc tekstu
- }
- }
- }
- menu = 1;
- }
- return 0;
- }
- NextProcess = PP2;
- if((PP1 = fork()) == 0){
- fifo = open("fifo", O_RDONLY); //Otwieramy KS dla PP2
- odbierzSygnalNorm();
- while(1){
- work = 1; // Oznaczamy ze jestesmy w menu
- int tryb = 0; //Zapisze tu tryb dzialania
- while(tryb != '1' && tryb != '2'){
- printf("Menu:\n1.stdin\n2.plik\n");
- tryb = getc(stdin);
- }
- if(tryb == '2'){ // Bedziemy czytac z pliku
- char plik[60] = {0};
- fgets (plik, sizeof(plik), stdin); //Pobierz linijke z wejscia
- printf("Podaj nazwe:\n");
- memset(plik, 0, sizeof(plik));
- fgets (plik, sizeof(plik), stdin); //Pobierz linijke z wejscia
- plik[strlen(plik) - 1] = '\0'; //Usuwamy enter z nazwy
- stdin = fopen(plik, "r"); // otworz plik jako wejscie
- if(stdin == NULL){ // Jak nie ma takiego pliku
- printf("Plik: %s nie istnieje, przelaczam na klawiature\n", plik);
- stdin = fopen("/dev/tty", "r"); // Zamień wejscie z powrotem na konsole
- tryb = klawiatura;
- } else{
- printf("Czytam plik: %s\n", plik);
- tryb = plikNo;
- }
- } else{
- tryb = klawiatura;
- }
- char buforWejsciowy[64]; // buforWejsciowy do zapisu danych z stdin
- while(work){
- fgets(buforWejsciowy, sizeof(buforWejsciowy), stdin); //Czytaj linijke z wejscia
- menu = 0;
- while(stop); //Jak dostalismy stopa to tutaj czekamy
- //Jak tryb == 1 i user posłał . lub tryb == 2 i plik sie skonczyl
- if( (tryb == klawiatura && buforWejsciowy[0] == '.' &&
- buforWejsciowy[1] == '\n' && buforWejsciowy[2] == '\0')
- || (tryb == plikNo && feof(stdin))
- ) { // jak dostalismy kropka enter lub jak dostalismy eof
- //Wyslij info do P2 ze koniec
- buforWejsciowy[0] = -1;
- buforWejsciowy[1] = -1;
- buforWejsciowy[2] = -1;
- sendtoPP2(buforWejsciowy); //Przesylam informacje do PP2
- work = 0; //Oznacz ze przejscie do menu
- stdin = fopen("/dev/tty", "r"); //Jak czytalismy z pliku, zamienmy wejscie na konsole
- if(end) //Jak dostalismy koniec to wyjdz
- exit(0);
- }else if(!stop) // - powtorka bo proces moze dostac stop-a w oczekiwaniu w fgets
- sendtoPP2(buforWejsciowy);
- }
- menu = 1;
- }
- return 0;
- }
- NextProcess = PP1;
- mainSygnaly();
- fifo = open("fifo", O_RDWR); //OTwieramy Fifo na zapis
- wait(NULL);
- wait(NULL);
- wait(NULL);
- //Usun kolejke
- close(kolejkaP1_P2);
- close(kolejkaP2_P3);
- //Odlacz Fifo
- unlink("fifo");
- unlink(KK1);
- unlink(KK2);
- return 0;
- }
- //Wysylanie textu do PP2
- void sendtoPP2(char* text){
- wiadomosc wiad;
- wiad.typ = 1; //Poprawna wiadomosc
- strcpy(wiad.text, text); //Ustawienie w wiad textu ktory przesylamy
- write(kolejkaP1_P2,&wiad,sizeof(wiad)+1); //Zapisanie do kolejki z PP1 do PP2
- }
- //Wysylanie dlugosci textu do PP3
- void sendtoPP3(int wartosc){
- wiadomosc2 wiad;
- wiad.wartosc = wartosc;
- wiad.typ = 1; //Poprawna wiadomosc
- write(kolejkaP2_P3, &wiad, sizeof(wiad) + 1); //Zapisanie do kolejki z PP2 do PP3
- }
- //Wysyla sygnal do PM
- void sendtoPM(int sygnal, siginfo_t *siginfo, void *context) {
- kill(PM, sygnal);
- }
- //PM prosi o odczytanie kolejki PP1 i zapisuje do fifo 3xsygnal
- void sendtoPPS(int sygnal, siginfo_t *siginfo, void *context){
- if((int)siginfo->si_pid == PP2) //Sprawdzamy czy wysylajacy pid to PP2
- {
- char sig = (char) sygnal;
- kill(NextProcess, SIGUSR2); //wyslijWiadomosc sygnal do P1 o odczytaniu fifo
- int i;
- for(i = 0; i < 3; i++)
- write(fifo, &sig, sizeof(char)); //Zapisuje numer signalu do kolejki sygnalow 3 razy bo trzy PP
- }
- }
- //Proces odczytuje swoje fifo i wykonuje dana operacje
- void readsignal(int sygnal, siginfo_t *siginfo, void *context) {
- char sig;
- read(fifo, &sig, sizeof(char)); //Odczytuje swoja kolejke sygnalow
- if(NextProcess != 0) //Zeby PP3 nie przesylal sygnalu
- kill(NextProcess, SIGUSR2); //Wysyla SIGUSR2 do nastepnego
- switch(sig)
- {
- case SIGTERM:
- end = 1; //Zakonaczamy prace
- if(menu) //Jak PP1 nic nie robi to mozna konczyc odrazu
- exit(0);
- break;
- case SIGTSTP:
- stop = 1; //Zatrzymuje dzialanie PPs
- break;
- case SIGCONT:
- stop = 0; //Wznawia dzialanie PPs
- break;
- }
- }
- void odbierzSygnalNorm(){
- struct sigaction todo; //
- memset (&todo, 0, sizeof (todo)); //ZAalokuj pamiec
- todo.sa_sigaction = &readsignal; //Wywolaj funkcje readsignal
- todo.sa_flags = SA_RESTART; //Proces byl w trakcie wykonywania operacji wiec powtarzamy operacje
- sigaction(SIGUSR2, &todo, NULL); //Dla SIGUSR2
- sigset_t maska;
- sigfillset(&maska); //Tworzy maske ze wszystkimi sygnalami
- sigdelset(&maska, SIGUSR2); // Usuwa z maski SIGUSR2
- sigprocmask(SIG_BLOCK, &maska, NULL); //Blokuje pozostale sygnaly
- //Pawel pamietaj o tym, ze nie wszystkie da sie zablokowac na przykal SIGKILL
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement