Laboratorium 3
Tworzenie i komunikacja za pomocą łączyPIPE
Łącza PIPE
To laboratorium ma na celu zapoznanie się z zasadą tworzenia łącz nie nazwanych, oraz zasady komunikacji pomiędzy dwoma spokrewnionymi procesami.
- Wstęp
- Łącza komunikacyjne nie nazwane (PIPE) możemy użyć jedynie pomiędzy dwoma spokrewnionymi procesami.
- tworzymy za pomocą funkcji:
int pipe(int *filedes);
- filedes - tablica dwuelementowa
- filedes[0] - jest deskryptorem pliku otwartym do czytania
- filedes[1] - jest deskryptorem pliku otwartym do pisania
- łącza komunikacyjne zwykle używamy do komunikowania się dwóch procesów, ale poniższy przykład będzie na jednym:
main() { int pipefd[2],n; char buff[100]; if (pipe(pipefd) <0) perror("blad pipe\n"); printf("read fd = %d, write fd = %d\n",pipefd[0],pipefd[1]); if (write(pipefd[1],"hello world\n",12) !=12) perror("blad zapisu\n"); if ((n = read(pipefd[0],buff,sizeof(buff))) <=0) perror("blad odczytu\n"); write(1, buff, n); /* deskryptor pliku=1 wyjscie standardowe */ exit(0); }
- Cel
Napisać program typu klient-serwer który:- pobiera od użytkownika nazwę pliku 0,5pkt
- tworzy łącze nienazwane PIPE 0,5pkt
- tworzy nowy proces za pomocą funkcji fork (nie popen!) 0,5pkt
- przesyła do procesu potomnego nazwę pliku. 0,5pkt
- proces potomny odczytuje plik o podanej nazwie a zawartość (tekst) lub informację o możliwych błędach (np. brak pliku), przesyła do procesu rodzicielskiego (komunikaty o błędzie 0,5pkt)
- proces rodzicielski wyświetla na standardowym wyjściu co otrzymał od potomka (poprawne przesłanie pliku do 2pkt).
- Pomocne funkcje:
- gets lub fgets
- perror, strerror
- read, write
- fork, wait
- pipe, close
- strcat, strlen, strcpy
- Uwaga końcowa
Pamiętać należy o przydziale pamięci na przesyłane komunikaty. Ważny jest też fakt że łącze pipe służy jedynie do przekazywania danych w jedną stronę. Jeżeli chcemy mieć komunikację dwukierunkową trzeba stworzyć 2 łącza. 1 zamknąć u potomka do odczytu a u przodka do zapisu a drugie u potomka do zapisu a u przodka do odczytu. Plik może być dowolnej długości odczytywanie jak i przesyłanie zrealizować w pętli (nie jednokrotny odczyt). Nie używać bezmyślnie memset, nie stosować odczytu po jednym znaku ani kombinacji w stylu przesłania specjalnych znaczków kończących transmisje. Funkcja read jest funkcją synchroniczną. - Sprawozdanie
Oczywiście nie zapomnijcie o sprawozdaniu.