Advertisement
Guest User

Untitled

a guest
Jan 18th, 2019
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.99 KB | None | 0 0
  1.     #include <stdio.h>
  2.     #include <sys/wait.h>
  3.     #include <unistd.h>
  4.     #include <sys/types.h>
  5.    
  6.     #include <string.h>
  7.     #include <signal.h>
  8.     #include <stdlib.h>
  9.     #include <fcntl.h>
  10.      
  11.     #define klawiatura 1
  12.     #define plikNo 2
  13.     #define kluczQueue1 9000
  14.     #define kluczQueue2 9001
  15.  
  16. //Deklaracja  nazw kolejek
  17. char* KK1 = "KK1"; //Nazwa koleki z PP1 do PP2
  18. char* KK2 = "KK2"; //Nazwa koleki z PP2 do PP3
  19.  
  20. //Deklaracja intow pod PIDY procesow
  21. //NextProcess przekazuje informacje o PID nastepnego procesu
  22.  
  23. int PP1,PP2,PP3,PM,NextProcess = 0;
  24.  
  25. //Deklaracja intow sterujacych procesami
  26. //work - czy program ma dzialac
  27. //end - czy program konczy dzialanie
  28. //stop - czy program ma sie zatrzymac
  29. int work = 1, end = 0, stop = 0;
  30.  
  31. int menu = 1; //Do sprawdzania w jakim stanie znajduje sie PP1. Jak jest w menu to odrazu mozna go zakonczyc
  32.  
  33. int kolejkaP1_P2, kolejkaP2_P3; //ID kolejek komunikatow tak jak nazwy
  34. int fifo; //ID kolejki komunikatow
  35.          
  36. //Struktura danych przekazywana do kolejki z PP1 do PP2
  37. typedef struct msgPP1toPP2 {
  38.     long typ;   //Czy cos z tym robic
  39.         char text[64]; //Co przekazuje z PP1 do PP2
  40. } wiadomosc;
  41.  
  42. //Struktura danych przekazywana do kolejki z PP2 do PP3    
  43. typedef struct msgPP2toPP3 {
  44.         long typ;
  45.         int wartosc; // Dlugosc string
  46. } wiadomosc2;
  47.  
  48.  
  49. void sendtoPP2(char * text); //Deklaracja naglowka funkcji wysylajacej wiadomosc do PP2
  50. void sendtoPP3(int wartosc); //Deklaracja naglowka funkcji wysylajacej wiadomosc do PP3
  51. void sendtoPM(int sygnal, siginfo_t *siginfo, void *context); //wyslanie sygnalu do PM
  52. void sendtoPPS(int sygnal, siginfo_t *siginfo, void *context) ;//Wysylanie sygnalow do PP przez PM
  53. void readsignal(int sygnal, siginfo_t *siginfo, void *context);  //Proces dostal sygnal by odczytal swoja kolejke        
  54. void odbierzSygnalNorm();
  55.      
  56.  
  57.      
  58.    
  59.      
  60.    
  61.      
  62.  
  63.      
  64.     void odbierzSygnalSpecjalny()
  65.     {
  66.         struct sigaction todo; //Struktura sygnalu
  67.         memset (&todo, 0, sizeof (todo)); //ZAalokuj pamiec
  68.         todo.sa_sigaction = &readsignal; //Wywolaj funkcje readsignal
  69.         todo.sa_flags = SA_RESTART; //Jak proces cos grzebal gdy dostal sygnal, to ma powtorzyc dzialanie
  70.         sigaction(12, &todo, NULL);  //Wywolaj jak otrzymasz sygnal -12 - 12
  71.            
  72.         //P2 jak otrzyma sig TERM & TSTP & CONT ma je wysylac do glownego
  73.         struct sigaction todo2;
  74.         memset (&todo2, 0, sizeof (todo2));
  75.         todo2.sa_sigaction = &sendtoPM;
  76.         todo2.sa_flags = SA_RESTART;
  77.         sigaction(SIGTSTP, &todo2, NULL);
  78.         sigaction(SIGCONT, &todo2, NULL);  
  79.         sigaction(SIGTERM, &todo2, NULL);
  80.        
  81.         sigset_t maska;
  82.         sigfillset(&maska);  //Tworze pusta maske
  83.         sigdelset(&maska, SIGUSR2); // Dodaje do maski sygnaly
  84.         sigdelset(&maska, SIGCONT); // Dodaje do maski sygnaly
  85.         sigdelset(&maska, SIGTERM); // Dodaje do maski sygnaly
  86.         sigdelset(&maska, SIGTSTP); // Dodaje do maski sygnaly
  87.         sigprocmask(SIG_BLOCK, &maska, NULL); //Blokuj sygnaly z maski
  88.     }
  89.      
  90.  
  91.    
  92.      
  93.     void mainSygnaly()
  94.     {
  95.         //Rozszerzona struktura do sygnalow - pozwala na pobranie pidu wysylajacego
  96.         //Trzeba to tak zrobic, poniewaz nie da sie jednoczesnie zablokowac sygnal dla konsoli i odblokowac dla P2
  97.         struct sigaction todo;
  98.         memset (&todo, 0, sizeof (todo));
  99.         todo.sa_sigaction = &sendtoPPS;
  100.         todo.sa_flags = SA_RESTART | SA_SIGINFO;
  101.         sigaction(SIGTSTP, &todo, NULL);
  102.         sigaction(SIGCONT, &todo, NULL);
  103.         sigaction(SIGTERM, &todo, NULL);
  104.        
  105.         sigset_t maska;
  106.         sigfillset(&maska);  
  107.         sigdelset(&maska, SIGCONT);
  108.         sigdelset(&maska, SIGTERM);
  109.         sigdelset(&maska, SIGTSTP);
  110.         sigprocmask(SIG_BLOCK, &maska, NULL);  
  111.     }
  112.      
  113.  
  114.      
  115.      
  116.     int main(void)
  117.     {  
  118.     //Tworzenie kolejek
  119.         mkfifo(KK1, 0666);
  120.     mkfifo(KK2, 0666);
  121.         kolejkaP1_P2 = open(KK1, O_RDWR);
  122.         kolejkaP2_P3 = open(KK2, O_RDWR);        
  123.         mkfifo("fifo", 0666);
  124.      
  125.         PM = getpid(); //PID PM
  126.      
  127.         //Tworzymy procesy
  128.        
  129.         if((PP3 = fork()) == 0)
  130.         {
  131.             odbierzSygnalNorm();
  132.            
  133.             fifo = open("fifo", O_RDONLY); //Otwieramy KS dla PP3
  134.         wiadomosc2 wiad;
  135.         while(1)
  136.         {      
  137.             work = 1;
  138.            
  139.             while(work){
  140.              
  141.                 if(read(kolejkaP2_P3, &wiad, sizeof(wiad) + 1) != -1){  
  142.                     menu = 0;
  143.                     while(stop); //Czy w czasie dzialania nie dostalismy TSTP i czeka az dostanie CONT
  144.                     if(wiad.wartosc == -1){ //Koniec wczytywania
  145.                         work = 0;
  146.                         if(end) //Jak oflagowalismy koniec programu to konczymy dzialanie PP3
  147.                             exit(0);
  148.                     }  
  149.                    
  150.                     if(wiad.wartosc != 0 && wiad.wartosc != -1){
  151.                         printf("%d\n", wiad.wartosc);    //Wypisuje wartosc > 0
  152.                     }                      
  153.                 }      
  154.             }
  155.             menu = 1;
  156.         }
  157.             return 0;
  158.         }
  159.         NextProcess = PP3;
  160.        
  161.         if((PP2 = fork()) == 0){
  162.         odbierzSygnalSpecjalny();  
  163.         fifo = open("fifo", O_RDONLY); //Otwieramy KS dla PP2
  164.         wiadomosc wiad;
  165.            
  166.         while(1){
  167.        
  168.             work = 1;
  169.            
  170.             while(work){
  171.              
  172.                 if(read(kolejkaP1_P2, &wiad, sizeof(wiad) + 1) != -1){ //Poprawnie odebrany sygnal
  173.                  
  174.                         menu = 0;
  175.                         while(stop);
  176.                    
  177.                         if(wiad.text[0] == -1 && wiad.text[1] == -1 && wiad.text[2] == -1){
  178.                             //Dostalismy info ze PP1 zakonczyc wczytywanie
  179.                             sendtoPP3(-1); //Informacja do PP3 o koncu
  180.                             work = 0;
  181.                             if(end)
  182.                                     exit(0);
  183.                         }else{
  184.                         sendtoPP3(strlen(wiad.text) - 1); //Wysyla dlugosc tekstu
  185.                         }
  186.                 }  
  187.             }
  188.             menu = 1;
  189.         }
  190.         return 0;
  191.         }
  192.        
  193.         NextProcess = PP2;
  194.        
  195.         if((PP1 = fork()) == 0){
  196.        
  197.                 fifo = open("fifo", O_RDONLY); //Otwieramy KS dla PP2
  198.             odbierzSygnalNorm();
  199.            
  200.             while(1){
  201.                 work = 1; // Oznaczamy ze jestesmy w menu      
  202.                 int tryb = 0; //Zapisze tu tryb dzialania
  203.      
  204.                     while(tryb != '1' && tryb != '2'){
  205.                         printf("Menu:\n1.stdin\n2.plik\n");
  206.                         tryb = getc(stdin);    
  207.                     }
  208.                     if(tryb == '2'){ // Bedziemy czytac z pliku
  209.            
  210.                         char plik[60] = {0};
  211.                         fgets (plik, sizeof(plik), stdin); //Pobierz linijke z wejscia
  212.                         printf("Podaj nazwe:\n");  
  213.                         memset(plik, 0, sizeof(plik));
  214.                         fgets (plik, sizeof(plik), stdin); //Pobierz linijke z wejscia
  215.                         plik[strlen(plik) - 1] = '\0'; //Usuwamy enter z nazwy
  216.                         stdin = fopen(plik, "r"); // otworz plik jako wejscie
  217.                         if(stdin == NULL){ // Jak nie ma takiego pliku    
  218.                             printf("Plik: %s nie istnieje, przelaczam na klawiature\n", plik);
  219.                             stdin = fopen("/dev/tty", "r"); // Zamień wejscie z powrotem na konsole
  220.                             tryb = klawiatura;
  221.                         } else{
  222.                                 printf("Czytam plik: %s\n", plik);
  223.                                 tryb = plikNo;
  224.                         }  
  225.                     } else{
  226.                     tryb = klawiatura;
  227.                     }
  228.      
  229.      
  230.                     char buforWejsciowy[64]; // buforWejsciowy do zapisu danych z stdin
  231.            
  232.                     while(work){                      
  233.                         fgets(buforWejsciowy, sizeof(buforWejsciowy), stdin); //Czytaj  linijke  z wejscia
  234.                         menu = 0;
  235.                         while(stop); //Jak dostalismy stopa to tutaj czekamy
  236.                         //Jak tryb == 1 i user posłał . lub tryb == 2 i plik sie skonczyl
  237.                
  238.                         if( (tryb == klawiatura && buforWejsciowy[0] == '.' &&
  239.                      buforWejsciowy[1] == '\n' && buforWejsciowy[2] == '\0')
  240.                     || (tryb == plikNo && feof(stdin))
  241.                 ) {     // jak dostalismy kropka enter lub jak dostalismy eof
  242.                                 //Wyslij info do P2 ze koniec
  243.                             buforWejsciowy[0] = -1;
  244.                                 buforWejsciowy[1] = -1;
  245.                                 buforWejsciowy[2] = -1;            
  246.                                 sendtoPP2(buforWejsciowy); //Przesylam informacje do PP2
  247.                                 work = 0; //Oznacz ze przejscie do menu
  248.                                 stdin = fopen("/dev/tty", "r"); //Jak czytalismy z pliku, zamienmy wejscie na konsole
  249.                                 if(end) //Jak dostalismy koniec to wyjdz
  250.                                     exit(0);
  251.                             }else if(!stop) // - powtorka bo proces moze dostac stop-a w oczekiwaniu w fgets
  252.                                     sendtoPP2(buforWejsciowy);
  253.                         }
  254.            
  255.                         menu = 1;
  256.                 }
  257.             return 0;
  258.         }
  259.        
  260.         NextProcess = PP1;
  261.        
  262.         mainSygnaly();
  263.        
  264.         fifo = open("fifo", O_RDWR); //OTwieramy Fifo na zapis
  265.         wait(NULL);
  266.     wait(NULL);
  267.     wait(NULL);
  268.          //Usun kolejke
  269.         close(kolejkaP1_P2);  
  270.         close(kolejkaP2_P3);  
  271.            
  272.         //Odlacz Fifo
  273.         unlink("fifo");
  274.     unlink(KK1);
  275.     unlink(KK2);
  276.        
  277.        
  278.      
  279.         return 0;
  280.     }
  281.  
  282.  
  283.  
  284.  
  285. //Wysylanie textu do PP2
  286. void sendtoPP2(char* text){
  287.         wiadomosc wiad;
  288.     wiad.typ = 1; //Poprawna wiadomosc
  289.         strcpy(wiad.text, text); //Ustawienie w wiad textu ktory przesylamy
  290.     write(kolejkaP1_P2,&wiad,sizeof(wiad)+1); //Zapisanie do kolejki z PP1 do PP2
  291. }
  292.  
  293.  
  294. //Wysylanie dlugosci textu do PP3
  295. void sendtoPP3(int wartosc){
  296.        wiadomosc2 wiad;
  297.        wiad.wartosc = wartosc;
  298.        wiad.typ = 1; //Poprawna wiadomosc
  299.        write(kolejkaP2_P3, &wiad, sizeof(wiad) + 1); //Zapisanie do kolejki z PP2 do PP3
  300. }
  301.  
  302. //Wysyla sygnal do PM
  303. void sendtoPM(int sygnal, siginfo_t *siginfo, void *context) {
  304.         kill(PM, sygnal);
  305. }
  306.  
  307. //PM prosi o odczytanie kolejki PP1 i zapisuje do fifo 3xsygnal
  308. void sendtoPPS(int sygnal, siginfo_t *siginfo, void *context){
  309.         if((int)siginfo->si_pid == PP2)  //Sprawdzamy czy wysylajacy pid to PP2
  310.         {
  311.             char sig = (char) sygnal;
  312.                 kill(NextProcess, SIGUSR2); //wyslijWiadomosc sygnal do P1 o odczytaniu fifo
  313.             int i;
  314.                 for(i = 0; i < 3; i++)
  315.                     write(fifo, &sig, sizeof(char)); //Zapisuje numer signalu do kolejki sygnalow 3 razy bo trzy PP
  316.     }      
  317. }
  318. //Proces odczytuje swoje fifo i wykonuje dana operacje
  319. void readsignal(int sygnal, siginfo_t *siginfo, void *context) {
  320.         char sig;
  321.         read(fifo, &sig, sizeof(char)); //Odczytuje swoja kolejke sygnalow
  322.        
  323.         if(NextProcess != 0) //Zeby PP3 nie przesylal sygnalu
  324.             kill(NextProcess, SIGUSR2);  //Wysyla SIGUSR2 do nastepnego
  325.      
  326.         switch(sig)
  327.         {
  328.             case SIGTERM:
  329.                 end = 1; //Zakonaczamy prace
  330.                 if(menu) //Jak PP1 nic nie robi to mozna konczyc odrazu
  331.                     exit(0);
  332.                 break;
  333.             case SIGTSTP:
  334.                 stop = 1; //Zatrzymuje dzialanie PPs   
  335.                 break;
  336.             case SIGCONT:
  337.                 stop = 0; //Wznawia dzialanie PPs
  338.                 break;
  339.         }
  340. }
  341. void odbierzSygnalNorm(){
  342.         struct sigaction todo; //
  343.         memset (&todo, 0, sizeof (todo)); //ZAalokuj pamiec
  344.         todo.sa_sigaction = &readsignal; //Wywolaj funkcje readsignal
  345.         todo.sa_flags = SA_RESTART; //Proces byl w trakcie wykonywania operacji wiec powtarzamy operacje
  346.         sigaction(SIGUSR2, &todo, NULL); //Dla SIGUSR2
  347.         sigset_t maska;
  348.         sigfillset(&maska);  //Tworzy maske ze wszystkimi sygnalami
  349.         sigdelset(&maska, SIGUSR2); // Usuwa z maski SIGUSR2
  350.         sigprocmask(SIG_BLOCK, &maska, NULL); //Blokuje pozostale sygnaly
  351.         //Pawel pamietaj o tym, ze nie wszystkie da sie zablokowac na przykal SIGKILL        
  352. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement