Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/shm.h>
- #include <sys/msg.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <signal.h>
- #define BUFOR 200 + sizeof(ssize_t)
- int process_num;
- int semid1;
- int semid2;
- int semid3;
- int semid4;
- char *fifo[3] = {"fifo1", "fifo2", "fifo3"};
- int fd[3];
- char *shm;
- int shmid;
- pid_t pids[3];
- struct sembuf ACQUIRE = { 0, -1, 0 };
- struct sembuf RELEASE = { 0, 1, 0 };
- void shm_usun(char **shm, int shmid){
- // Odłączanie pamięci współdzielonej
- shmdt(shm);
- // Nullowanie wskaźnika na pamięć
- shm = NULL;
- // Usuwanie pamięci
- shmctl(shmid, IPC_RMID, NULL);
- }
- /* --------------------------------------- */
- /* Obsługa sygnałów */
- /* --------------------------------------- */
- void killProcess()
- {
- fprintf(stderr, "KILL %d\n", process_num);
- close(fd[0]);
- close(fd[1]);
- close(fd[2]);
- if(process_num == 0) {
- shmdt(&shm);
- } if(process_num == 1) {
- shmdt(&shm);
- semctl(semid1, 0, IPC_RMID);
- semctl(semid2, 0, IPC_RMID);
- } else if(process_num == 2) {
- shm_usun(&shm, shmid);
- semctl(semid3, 0, IPC_RMID);
- semctl(semid4, 0, IPC_RMID);
- }
- exit(0);
- }
- void stopProcess()
- {
- fprintf(stderr, "STOP %d\n", process_num);
- sigset_t mask;
- sigfillset(&mask);
- sigdelset(&mask, SIGCONT);
- sigdelset(&mask, SIGUSR1);
- sigsuspend(&mask);
- }
- void resumeProcess()
- {
- fprintf(stderr, "RESUME %d\n", process_num);
- }
- void sigAction(int signum)
- {
- switch(signum)
- {
- case SIGINT:
- {
- killProcess();
- break;
- }
- case SIGUSR2:
- {
- stopProcess();
- break;
- }
- case SIGCONT:
- {
- resumeProcess();
- break;
- }
- }
- }
- void handleSig(int signum)
- {
- int i = 0;
- printf("Handle\n");
- for(i; i < 3; i++) {
- if (i != process_num) {
- printf("Writing signum to fd%d %d\n", i, signum);
- write(fd[i], &signum, sizeof(int));
- }
- }
- kill(pids[0], SIGUSR1);
- kill(pids[1], SIGUSR1);
- sigAction(signum);
- }
- void sigMessage(int signum)
- {
- int received_signal;
- read(fd[process_num], &received_signal, sizeof(int));
- printf("Message %d %d\n", process_num, received_signal);
- sigAction(received_signal);
- }
- void wymiana_pidami(int process_num) {
- int i = 0;
- pid_t mypid = getpid();
- if (process_num == 0) {
- fd[0] = open(fifo[0], O_WRONLY);
- fd[1] = open(fifo[1], O_RDONLY);
- fd[2] = open(fifo[2], O_RDONLY);
- write(fd[0], &mypid, sizeof(pid_t));
- write(fd[0], &mypid, sizeof(pid_t));
- read(fd[1], &(pids[0]), sizeof(pid_t));
- read(fd[2], &(pids[1]), sizeof(pid_t));
- } else if (process_num == 1) {
- fd[0] = open(fifo[0], O_RDONLY);
- fd[1] = open(fifo[1], O_WRONLY);
- fd[2] = open(fifo[2], O_RDONLY);
- write(fd[1], &mypid, sizeof(pid_t));
- write(fd[1], &mypid, sizeof(pid_t));
- read(fd[0], &(pids[0]), sizeof(pid_t));
- read(fd[2], &(pids[1]), sizeof(pid_t));
- } else if (process_num == 2) {
- fd[0] = open(fifo[0], O_RDONLY);
- fd[1] = open(fifo[1], O_RDONLY);
- fd[2] = open(fifo[2], O_WRONLY);
- write(fd[2], &mypid, sizeof(pid_t));
- write(fd[2], &mypid, sizeof(pid_t));
- read(fd[0], &(pids[0]), sizeof(pid_t));
- read(fd[1], &(pids[1]), sizeof(pid_t));
- }
- for(i; i < 3; i++) {
- if(process_num == i) {
- close(fd[i]);
- fd[i] = open(fifo[])
- }
- }
- fd[process_num] = open(fifo[process_num], O_RDONLY);
- printf("(%d %d) %d %d\n", process_num, mypid, pids[0], pids[1]);
- }
- /* --------------------------------------- */
- /* Proces 1 */
- /* Odczytuje dane ze standardowego wejścia */
- /* i przekazuje je w niezmienionej formie */
- /* do procesu numer 2 */
- /* --------------------------------------- */
- void proces1()
- {
- process_num = 0;
- wymiana_pidami(process_num);
- // Obsługa sygnałów
- signal(SIGINT, handleSig);
- signal(SIGCONT, handleSig);
- signal(SIGUSR2, handleSig);
- signal(SIGUSR1, sigMessage);
- // Bufor dla danych
- char *bufor = (char *)malloc(200*sizeof(char));
- size_t bytes_to_read = (size_t) BUFOR;
- // Ilość odczytanych bajtów z stdina
- ssize_t bytes_read;
- // Dopóki ze standardowego wejścia odczytujemy więcej niż 0 bajtów
- while((bytes_read = getline(&bufor, &bytes_to_read, stdin)) > 0)
- {
- // Opuszczamy semafor 1
- semop(semid1, &ACQUIRE, 1);
- // W pierwszym bajcie zapisujemy ilość odczytanych bajtów z stdin
- // Zapisujemy ilość bajtów i odczytane dane do pliku
- memcpy(shm, bufor, BUFOR - sizeof(ssize_t));
- // Podnosimy semafor 2 (pozwalamy drugiemu procesowy odczytać dane)
- semop(semid2, &RELEASE, 1);
- }
- // Koniec danych, zapisujemy w pliku 0 jako ilość bajtów odczytanych
- // Drugi proces po odczytaniu zera zakończy swoje działanie
- semop(semid1, &ACQUIRE, 1);
- memcpy(shm, "\0", 1);
- semop(semid2, &RELEASE, 1);
- shmdt(&shm);
- // Proces kończy swoje działanie
- printf("EXIT 1\n");
- exit(0);
- }
- /* --------------------------------------- */
- /* Proces 2 */
- /* Pobiera dane przesłane przez pierwszy */
- /* proces, wyświetla liczbę odczytanych */
- /* bajtów i przesyła dane do procesu 3 */
- /* --------------------------------------- */
- void proces2()
- {
- process_num = 1;
- wymiana_pidami(process_num);
- // Obsługa sygnałów
- signal(SIGINT, handleSig);
- signal(SIGCONT, handleSig);
- signal(SIGUSR2, handleSig);
- signal(SIGUSR1, sigMessage);
- // Bufor dla danych
- char bufor[BUFOR];
- ssize_t length;
- // Podnosimy semafor 1 (proces 1 może zacząć pracę)
- semop(semid1, &RELEASE, 1);
- while(1)
- {
- // Opuszczamy semafor 2
- semop(semid2, &ACQUIRE, 1);
- // Czytamy 100 bajtów z pliku
- memcpy(bufor, shm, BUFOR);
- length = strlen(bufor);
- // Jeżeli zostało odczytane 0 bajtów to wychodzimy z pętli
- if(length == 0) break;
- // (DEBUG) Wyświetlamy tekst oraz liczbę odczytanych bajtów
- // fprintf(stderr, "(2) Odczytano %ld bajtow: %s", length, bufor);
- // Podnosimy semafor 1 (proces 1 zacznie zapisywać kolejne dane)
- semop(semid1, &RELEASE, 1);
- // Opuszczamy semafor 3
- semop(semid3, &ACQUIRE, 1);
- // Zapisujemy bufor do pamięci współdzielonej
- memcpy(shm + 200, &length, sizeof(ssize_t));
- // Podnosimy semafor 4 (proces 3 zacznie odczytywać dane z shm)
- semop(semid4, &RELEASE, 1);
- }
- // Zapisujemy do pamięci współdzielonej pierwszy bajt jako 0
- // dzięki temu trzeci proces wie, kiedy zakończyć pracę
- semop(semid3, &ACQUIRE, 1);
- length = 0;
- memcpy(shm + 200, &length, sizeof(ssize_t));
- semop(semid4, &RELEASE, 1);
- // Odłączamy pamięć współdzieloną
- shmdt(shm);
- // Usuwamy semafory, aby nie zostały w systemie
- semctl(semid1, 0, IPC_RMID);
- semctl(semid2, 0, IPC_RMID);
- // Kończymy pracę procesu
- printf("EXIT 2\n");
- exit(0);
- }
- /* ---------------------------------------- */
- /* Proces 3 */
- /* Pobiera dane przesłane przez drugi */
- /* proces i wyświetla je na standardowym */
- /* wyjściu */
- /* ---------------------------------------- */
- void proces3()
- {
- process_num = 2;
- wymiana_pidami(process_num);
- // Obsługa sygnałów
- signal(SIGINT, handleSig);
- signal(SIGCONT, handleSig);
- signal(SIGUSR2, handleSig);
- signal(SIGUSR1, sigMessage);
- // Liczba odczytanych bajtów przez proces 2
- ssize_t bytes;
- // Podnosimy semafor 3, aby drugi proces mógł zapisać dane
- semop(semid3, &RELEASE, 1);
- while(1)
- {
- // Opuszczamy semafor 4
- semop(semid4, &ACQUIRE, 1);
- // Odczytujemy ilość znaków w linii
- memcpy(&bytes, shm + 200, sizeof(ssize_t));
- // Jeżeli odczytano 0 bajtów wychodzimy z pętli
- if(bytes == 0) break;
- // Przekazujemy dane na standardowy strumień wyjściowy
- printf("Dlugosc przeslanej linii: %ld\n", bytes);
- // Podnosimy semafor 3
- // (pozwalamy drugiemu procesowi na zapisanie kolejnych danych)
- semop(semid3, &RELEASE, 1);
- }
- // Usuwanie pamięci współdzielonej
- shm_usun(&shm, shmid);
- // Usuwanie semaforów
- semctl(semid3, 0, IPC_RMID);
- semctl(semid4, 0, IPC_RMID);
- // Kończymy pracę procesu
- printf("EXIT 3\n");
- exit(0);
- }
- int main()
- {
- // Tworzenie semaforów i pamięci współdzielonej
- semid1 = semget(ftok(".", 0), 1, IPC_CREAT | 0666);
- semid2 = semget(ftok(".", 1), 1, IPC_CREAT | 0666);
- semid3 = semget(ftok(".", 2), 1, IPC_CREAT | 0666);
- semid4 = semget(ftok(".", 3), 1, IPC_CREAT | 0666);
- shmid = shmget(ftok(".", 12), BUFOR, IPC_CREAT | 0666);
- shm = shmat(shmid, NULL, 0);
- mkfifo(fifo[0], 0666);
- mkfifo(fifo[1], 0666);
- mkfifo(fifo[2], 0666);
- if(fork())
- proces1();
- else if(fork())
- proces2();
- else if(fork())
- proces3();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement