Advertisement
KsaneK

projekt SO

Jan 14th, 2019
189
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.61 KB | None | 0 0
  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <sys/ipc.h>
  4. #include <sys/sem.h>
  5. #include <sys/shm.h>
  6. #include <sys/msg.h>
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <fcntl.h>
  11. #include <unistd.h>
  12. #include <signal.h>
  13. #define BUFOR 200 + sizeof(ssize_t)
  14.  
  15. int process_num;
  16. int semid1;
  17. int semid2;
  18. int semid3;
  19. int semid4;
  20. char *fifo[3] = {"fifo1", "fifo2", "fifo3"};
  21. int fd[3];
  22. char *shm;
  23. int shmid;
  24. pid_t pids[3];
  25.  
  26. struct sembuf ACQUIRE = { 0, -1, 0 };
  27. struct sembuf RELEASE = { 0,  1, 0 };
  28.  
  29. void shm_usun(char **shm, int shmid){
  30.     // Odłączanie pamięci współdzielonej
  31.     shmdt(shm);
  32.     // Nullowanie wskaźnika na pamięć
  33.     shm = NULL;
  34.     // Usuwanie pamięci
  35.     shmctl(shmid, IPC_RMID, NULL);
  36. }
  37.  
  38. /* --------------------------------------- */
  39. /*            Obsługa sygnałów             */
  40. /* --------------------------------------- */
  41.  
  42. void killProcess()
  43. {
  44.     fprintf(stderr, "KILL %d\n", process_num);
  45.     close(fd[0]);
  46.     close(fd[1]);
  47.     close(fd[2]);
  48.     if(process_num == 0) {
  49.         shmdt(&shm);
  50.     } if(process_num == 1) {
  51.         shmdt(&shm);
  52.         semctl(semid1, 0, IPC_RMID);
  53.         semctl(semid2, 0, IPC_RMID);
  54.     } else if(process_num == 2) {
  55.         shm_usun(&shm, shmid);
  56.         semctl(semid3, 0, IPC_RMID);
  57.         semctl(semid4, 0, IPC_RMID);
  58.     }
  59.     exit(0);
  60. }
  61.  
  62. void stopProcess()
  63. {
  64.     fprintf(stderr, "STOP %d\n", process_num);
  65.     sigset_t mask;
  66.     sigfillset(&mask);
  67.     sigdelset(&mask, SIGCONT);
  68.     sigdelset(&mask, SIGUSR1);
  69.     sigsuspend(&mask);
  70. }
  71.  
  72. void resumeProcess()
  73. {
  74.     fprintf(stderr, "RESUME %d\n", process_num);
  75. }
  76.  
  77. void sigAction(int signum)
  78. {
  79.     switch(signum)
  80.     {
  81.         case SIGINT:
  82.         {
  83.             killProcess();
  84.             break;
  85.         }
  86.         case SIGUSR2:
  87.         {
  88.             stopProcess();
  89.             break;
  90.         }
  91.         case SIGCONT:
  92.         {
  93.             resumeProcess();
  94.             break;
  95.         }
  96.     }
  97. }
  98.  
  99. void handleSig(int signum)
  100. {
  101.     int i = 0;
  102.     printf("Handle\n");
  103.     for(i; i < 3; i++) {
  104.         if (i != process_num) {
  105.             printf("Writing signum to fd%d %d\n", i, signum);
  106.             write(fd[i], &signum, sizeof(int));
  107.         }
  108.     }
  109.  
  110.     kill(pids[0], SIGUSR1);
  111.     kill(pids[1], SIGUSR1);
  112.     sigAction(signum);
  113. }
  114.  
  115. void sigMessage(int signum)
  116. {
  117.     int received_signal;
  118.     read(fd[process_num], &received_signal, sizeof(int));
  119.     printf("Message %d %d\n", process_num, received_signal);
  120.     sigAction(received_signal);
  121. }
  122.  
  123. void wymiana_pidami(int process_num) {
  124.     int i = 0;
  125.     pid_t mypid = getpid();
  126.     if (process_num == 0) {
  127.         fd[0] = open(fifo[0], O_WRONLY);
  128.         fd[1] = open(fifo[1], O_RDONLY);
  129.         fd[2] = open(fifo[2], O_RDONLY);
  130.         write(fd[0], &mypid, sizeof(pid_t));
  131.         write(fd[0], &mypid, sizeof(pid_t));
  132.         read(fd[1], &(pids[0]), sizeof(pid_t));
  133.         read(fd[2], &(pids[1]), sizeof(pid_t));
  134.     } else if (process_num == 1) {
  135.         fd[0] = open(fifo[0], O_RDONLY);
  136.         fd[1] = open(fifo[1], O_WRONLY);
  137.         fd[2] = open(fifo[2], O_RDONLY);
  138.         write(fd[1], &mypid, sizeof(pid_t));
  139.         write(fd[1], &mypid, sizeof(pid_t));
  140.         read(fd[0], &(pids[0]), sizeof(pid_t));
  141.         read(fd[2], &(pids[1]), sizeof(pid_t));
  142.     } else if (process_num == 2) {
  143.         fd[0] = open(fifo[0], O_RDONLY);
  144.         fd[1] = open(fifo[1], O_RDONLY);
  145.         fd[2] = open(fifo[2], O_WRONLY);
  146.         write(fd[2], &mypid, sizeof(pid_t));
  147.         write(fd[2], &mypid, sizeof(pid_t));
  148.         read(fd[0], &(pids[0]), sizeof(pid_t));
  149.         read(fd[1], &(pids[1]), sizeof(pid_t));
  150.     }
  151.     for(i; i < 3; i++) {
  152.         if(process_num == i) {
  153.             close(fd[i]);
  154.             fd[i] = open(fifo[])
  155.         }
  156.     }
  157.     fd[process_num] = open(fifo[process_num], O_RDONLY);
  158.     printf("(%d %d) %d %d\n", process_num, mypid, pids[0], pids[1]);
  159. }
  160.  
  161. /* --------------------------------------- */
  162. /*                Proces 1                 */
  163. /* Odczytuje dane ze standardowego wejścia */
  164. /* i przekazuje je w niezmienionej formie  */
  165. /*          do procesu numer 2             */
  166. /* --------------------------------------- */
  167.  
  168. void proces1()
  169. {
  170.     process_num = 0;
  171.     wymiana_pidami(process_num);
  172.     // Obsługa sygnałów
  173.     signal(SIGINT, handleSig);
  174.     signal(SIGCONT, handleSig);
  175.     signal(SIGUSR2, handleSig);
  176.     signal(SIGUSR1, sigMessage);
  177.  
  178.     // Bufor dla danych
  179.     char *bufor = (char *)malloc(200*sizeof(char));
  180.     size_t bytes_to_read = (size_t) BUFOR;
  181.  
  182.     // Ilość odczytanych bajtów z stdina
  183.     ssize_t bytes_read;
  184.  
  185.     // Dopóki ze standardowego wejścia odczytujemy więcej niż 0 bajtów
  186.     while((bytes_read = getline(&bufor, &bytes_to_read, stdin)) > 0)
  187.     {
  188.         // Opuszczamy semafor 1
  189.         semop(semid1, &ACQUIRE, 1);
  190.         // W pierwszym bajcie zapisujemy ilość odczytanych bajtów z stdin
  191.         // Zapisujemy ilość bajtów i odczytane dane do pliku
  192.         memcpy(shm, bufor, BUFOR - sizeof(ssize_t));
  193.         // Podnosimy semafor 2 (pozwalamy drugiemu procesowy odczytać dane)
  194.         semop(semid2, &RELEASE, 1);
  195.     }
  196.     // Koniec danych, zapisujemy w pliku 0 jako ilość bajtów odczytanych
  197.     // Drugi proces po odczytaniu zera zakończy swoje działanie
  198.     semop(semid1, &ACQUIRE, 1);
  199.     memcpy(shm, "\0", 1);
  200.     semop(semid2, &RELEASE, 1);
  201.  
  202.     shmdt(&shm);
  203.     // Proces kończy swoje działanie
  204.     printf("EXIT 1\n");
  205.     exit(0);
  206. }
  207.  
  208. /* --------------------------------------- */
  209. /*                Proces 2                 */
  210. /*  Pobiera dane przesłane przez pierwszy  */
  211. /*  proces, wyświetla liczbę odczytanych   */
  212. /*   bajtów i przesyła dane do procesu 3   */
  213. /* --------------------------------------- */
  214.  
  215. void proces2()
  216. {
  217.     process_num = 1;
  218.     wymiana_pidami(process_num);
  219.     // Obsługa sygnałów
  220.     signal(SIGINT, handleSig);
  221.     signal(SIGCONT, handleSig);
  222.     signal(SIGUSR2, handleSig);
  223.     signal(SIGUSR1, sigMessage);
  224.  
  225.     // Bufor dla danych
  226.     char bufor[BUFOR];
  227.  
  228.     ssize_t length;
  229.  
  230.     // Podnosimy semafor 1 (proces 1 może zacząć pracę)
  231.     semop(semid1, &RELEASE, 1);
  232.     while(1)
  233.     {
  234.         // Opuszczamy semafor 2
  235.         semop(semid2, &ACQUIRE, 1);
  236.         // Czytamy 100 bajtów z pliku
  237.         memcpy(bufor, shm, BUFOR);
  238.         length = strlen(bufor);
  239.  
  240.         // Jeżeli zostało odczytane 0 bajtów to wychodzimy z pętli
  241.         if(length == 0) break;
  242.  
  243.         // (DEBUG) Wyświetlamy tekst oraz liczbę odczytanych bajtów
  244.         // fprintf(stderr, "(2) Odczytano %ld bajtow: %s", length, bufor);
  245.  
  246.         // Podnosimy semafor 1 (proces 1 zacznie zapisywać kolejne dane)
  247.         semop(semid1, &RELEASE, 1);
  248.         // Opuszczamy semafor 3
  249.         semop(semid3, &ACQUIRE, 1);
  250.         // Zapisujemy bufor do pamięci współdzielonej
  251.         memcpy(shm + 200, &length, sizeof(ssize_t));
  252.         // Podnosimy semafor 4 (proces 3 zacznie odczytywać dane z shm)
  253.         semop(semid4, &RELEASE, 1);
  254.     }
  255.  
  256.     // Zapisujemy do pamięci współdzielonej pierwszy bajt jako 0
  257.     // dzięki temu trzeci proces wie, kiedy zakończyć pracę
  258.     semop(semid3, &ACQUIRE, 1);
  259.     length = 0;
  260.     memcpy(shm + 200, &length, sizeof(ssize_t));
  261.     semop(semid4, &RELEASE, 1);
  262.  
  263.     // Odłączamy pamięć współdzieloną
  264.     shmdt(shm);
  265.  
  266.     // Usuwamy semafory, aby nie zostały w systemie
  267.     semctl(semid1, 0, IPC_RMID);
  268.     semctl(semid2, 0, IPC_RMID);
  269.  
  270.     // Kończymy pracę procesu
  271.     printf("EXIT 2\n");
  272.     exit(0);
  273. }
  274.  
  275. /* ---------------------------------------- */
  276. /*                Proces 3                  */
  277. /*    Pobiera dane przesłane przez drugi    */
  278. /*   proces i wyświetla je na standardowym  */
  279. /*                 wyjściu                  */
  280. /* ---------------------------------------- */
  281.  
  282. void proces3()
  283. {
  284.     process_num = 2;
  285.     wymiana_pidami(process_num);
  286.     // Obsługa sygnałów
  287.     signal(SIGINT, handleSig);
  288.     signal(SIGCONT, handleSig);
  289.     signal(SIGUSR2, handleSig);
  290.     signal(SIGUSR1, sigMessage);
  291.  
  292.     // Liczba odczytanych bajtów przez proces 2
  293.     ssize_t bytes;
  294.  
  295.     // Podnosimy semafor 3, aby drugi proces mógł zapisać dane
  296.     semop(semid3, &RELEASE, 1);
  297.     while(1)
  298.     {
  299.         // Opuszczamy semafor 4
  300.         semop(semid4, &ACQUIRE, 1);
  301.         // Odczytujemy ilość znaków w linii
  302.         memcpy(&bytes, shm + 200, sizeof(ssize_t));
  303.         // Jeżeli odczytano 0 bajtów wychodzimy z pętli
  304.         if(bytes == 0) break;
  305.         // Przekazujemy dane na standardowy strumień wyjściowy
  306.         printf("Dlugosc przeslanej linii: %ld\n", bytes);
  307.         // Podnosimy semafor 3
  308.         // (pozwalamy drugiemu procesowi na zapisanie kolejnych danych)
  309.         semop(semid3, &RELEASE, 1);
  310.     }
  311.  
  312.     // Usuwanie pamięci współdzielonej
  313.     shm_usun(&shm, shmid);
  314.  
  315.     // Usuwanie semaforów
  316.     semctl(semid3, 0, IPC_RMID);
  317.     semctl(semid4, 0, IPC_RMID);
  318.  
  319.     // Kończymy pracę procesu
  320.     printf("EXIT 3\n");
  321.     exit(0);
  322. }
  323.  
  324. int main()
  325. {
  326.     // Tworzenie semaforów i pamięci współdzielonej
  327.     semid1 = semget(ftok(".", 0), 1, IPC_CREAT | 0666);
  328.     semid2 = semget(ftok(".", 1), 1, IPC_CREAT | 0666);
  329.     semid3 = semget(ftok(".", 2), 1, IPC_CREAT | 0666);
  330.     semid4 = semget(ftok(".", 3), 1, IPC_CREAT | 0666);
  331.     shmid = shmget(ftok(".", 12), BUFOR, IPC_CREAT | 0666);
  332.     shm = shmat(shmid, NULL, 0);
  333.     mkfifo(fifo[0], 0666);
  334.     mkfifo(fifo[1], 0666);
  335.     mkfifo(fifo[2], 0666);
  336.  
  337.     if(fork())
  338.         proces1();
  339.     else if(fork())
  340.         proces2();
  341.     else if(fork())
  342.         proces3();
  343.     return 0;
  344. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement