sposób wykonywania operacji zapisu i odczytu dane odczytywane z l acza usuwane (nie można ich odczytać ponownie),

Podobne dokumenty
4.2 Sposób korzystania z l acza

Temat zajęć: Obsługa łączy komunikacyjnych

Kolejki FIFO (łącza nazwane)

Dariusz Wawrzyniak 11 maja 2001

Laboratorium Systemów Operacyjnych. Ćwiczenie 4. Operacje na plikach

Łącza nienazwane(potoki) Łącza nienazwane mogą być używane tylko pomiędzy procesami ze sobą powiązanymi.

Pliki. Funkcje tworzące pliki i operujące na nich opisane są w części 2 pomocy systemowej. Tworzenie i otwieranie plików:

Procesy. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 9 października 2011

pami eć operacyjna przechowuje dane do przetworzenia, tymczasowe dane pomocnicze,

Komunikacja za pomocą potoków. Tomasz Borzyszkowski

Plik jest poj eciem, z którym spotyka si e niemal każdy użytkownik systemu komputerowego, nawet

Łącza nienazwane(potoki)

Obsługa plików. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 25 września 2011

Dariusz Wawrzyniak 5 kwietnia 2001

Systemy Operacyjne - Operacje na plikach

Instrukcja do laboratorium Systemów Operacyjnych (semestr drugi)

Temat zajęć: Obsługa procesów w systemie.

Obsługa plików Procesy

Temat zajęć: Obsługa systemu plików.

Laboratorium z systemów operacyjnych. System plików - funkcje systemowe. Anna Wojak

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

aodczytywać zniegoza pomoc afunkcjiread, (niebuforowane funkcje wejścia/wyjścia). e sukcesem, to zwróci liczb, erzeczywiściezapisanychbajtów.

Funkcje systemu Unix

systemu operacyjnego UNIX Funkcje jadra Spis treści Dariusz Wawrzyniak 20 października Wst ep 5

System plików warstwa logiczna

Systemy Operacyjne 1 Laboratorium 3 Potoki i łącza nazwane w Linuksie (jeden tydzień) dr inż. Arkadiusz Chrobot

Funkcje jadra systemu operacyjnego UNIX

Funkcje jadra systemu operacyjnego UNIX

4. Komunikacja pomiędzy procesami przez łącza nienazwane i nazwane

Poniższe funkcje opisane są w 2 i 3 części pomocy systemowej.

J. Ułasiewicz Łącza nienazwane, nazwane, select 1

Programowanie proceduralne INP001210WL rok akademicki 2015/16 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

Instytut Teleinformatyki

Rozdzia l 3. Laboratorium 3. danych zawierajac

Wskaźniki. Informatyka

Systemy Operacyjne Ćwiczenia

Functionalization. Funkcje w C. Marcin Makowski. 30 listopada Zak lad Chemii Teoretycznej UJ

Functionalization. Jeszcze o funkcjach i strukturze projektu. Marcin Makowski. 3 grudnia Zak lad Chemii Teoretycznej UJ

Powłoka I. Popularne implementacje. W stylu sh (powłoki zdefiniowanej w POSIX) W stylu csh. bash (najpopularniejsza) zsh ksh mksh.

Jak wiemy, wszystkich danych nie zmieścimy w pamięci. A nawet jeśli zmieścimy, to pozostaną tam tylko do najbliższego wyłączenia zasilania.

Ghost in the machine

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

Procesy i wątki. Blok kontrolny procesu. Proces. Proces - elementy. Stan procesu

1. Kolejki komunikatów POSIX

Programowanie w językach

System plików. Warstwowy model systemu plików

Pobieranie argumentów wiersza polecenia

przypadków wywo lanie systemowe (funkcja systemowa) lub funkcja biblioteczna zwraca wartość 1(czasamiNULL) iprzypisujezmiennej zewn etrznej,

Przekierowanie wejścia wyjścia:

SYSTEMY OPERACYJNE I laboratorium 3 (Informatyka stacjonarne 2 rok, semestr zimowy)

Kolejki komunikatów POSIX

J. Ułasiewicz Programowanie aplikacji współbieżnych 1

Pliki wykład 2. Dorota Pylak

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Temat zajęć: Filtry, strumienie standardowe oraz przetwarzanie potokowe. stderr

Funkcje zawarte w bibliotece < io.h >

Zaawansowane programowanie w C++

ang. file) Pojęcie pliku (ang( Typy plików Atrybuty pliku Fragmentacja wewnętrzna w systemie plików Struktura pliku

Proces y i y w i ąt ą ki

Argumenty wywołania programu, operacje na plikach

Znaki globalne w Linuxie

Programowanie Współbieżne. W Linuxie/Unixie

Paradygmaty programowania

Funkcje zawarte w bibliotece < io.h >

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 26 marca kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 40

Uwagi dotyczące notacji kodu! Moduły. Struktura modułu. Procedury. Opcje modułu (niektóre)

Lekcja 10. Uprawnienia. Dołączanie plików przy pomocy funkcji include() Sprawdzanie, czy plik istnieje przy pmocy funkcji file_exists()

Wykład 3. Procesy i wątki. Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

Wykład 4. Tablice. Pliki

Przetwarzanie tekstu 2. Operacje na plikach tekstowych w systemie Linux

INFORMATYKA Studia Niestacjonarne Elektrotechnika

Bash - wprowadzenie. Bash - wprowadzenie 1/39

SYSTEMY OPERACYJNE WYKLAD 6 - procesy

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

2. Zarządzanie procesami

5 Przygotował: mgr inż. Maciej Lasota

Biblioteka standardowa - operacje wejścia/wyjścia

1 Pierwsze kroki w C++ cz.3 2 Obsługa plików

Operatory zmiany sposobu przypisania standardowych strumieni >,<,>> Jeżeli pierwsze polecenie powiodło się to wykona drugie

Pliki. Informacje ogólne. Obsługa plików w języku C

Tablice i funkcje. Marcin Makowski. 26 listopada Zak lad Chemii Teoretycznej UJ

skrypt powłoki to plik tekstowy, rozpoczynający się sekwencją: pierwsza linia określa powłokę, w której wykonywany jest skrypt; druga to komentarz

<stdio.h> <iostram> input. FILE *stdin. std::cin output. std::cout error. FILE *stdout. FILE *stderr

KOLOKWIUM PODSTAWY PROGRAMOWANIA

Programowanie w modelu przesyłania komunikatów specyfikacja MPI, cd. Krzysztof Banaś Obliczenia równoległe 1

Powłoka bash. Kurs systemu Unix 1

1. Procesy i współbieżność

Stan procesu. gotowy - czeka na przydział procesora, zakończony - zakończył działanie.

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Wykład II. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Programowanie i struktury danych

POPULARNE POLECENIA SKRYPTY. Pracownia Informatyczna 2

J. Ułasiewicz Łącza nienazwane, nazwane, select 1

Katedra Elektrotechniki Teoretycznej i Informatyki. wykład 12 - sem.iii. M. Czyżak

Pliki. Informacje ogólne. Obsługa plików w języku C

3. Identyfikacja. SKŁADNIA #include <sys/socket.h> int getpeername(int socket, struct sockaddr *addr, int *addrlen);

Metody zawarte w klasie File: boolean createnewfile() tworzy nowy, pusty plik, ale tylko jeśli on wcześniej nie istniał. boolean delete() usuwa dany

Pamięć współdzielona

Transkrypt:

27 4 L acza L acza w systemie UNIX sa plikami specjalnymi, s luż acymi do komunikacji pomiedzy procesami. L acza maja kilka cech typowych dla plików zwyk lych, czyli posiadaja swój i-weze l, posiadaja bloki z danymi (chociaż ograniczona ich liczb e), na otwartych l aczach można wykonywać operacje zapisu i odczytu. L acza od plików zwyk lych odróżniaja nastepujace cechy: ograniczona liczba bloków l acza maja rozmiar 4KB 8KB w zależności od konkretnego systemu, dostep sekwencyjny na l aczach można wykonywać tylko operacje zapisu i odczytu, nie można natomiast przemieszczać wskaźnika bieżacej pozycji (nie można wykonywać funkcji lseek), sposób wykonywania operacji zapisu i odczytu dane odczytywane z l acza sa zarazem usuwane (nie można ich odczytać ponownie), proces jest blokowany w funkcji read na pustym l aczu, jeśli jest otwarty jakiś deskryptor tego l acza do zapisu, proces jest blokowany w funkcji write, jeśli w l aczu nie ma wystarczajacej ilości wolnego miejsca, żeby zmieścić zapisywany blok 2. Jak już wspomniano przy opisie funkcji systemowejread (str. 7), zwrócenie przez nia wartości 0 jest wskazaniem osiagniecia końca pliku. Koniec odczytu danych z l acza nastepuje dopiero, gdy wszystkie dane zostana odczytane i wszystkie deskryptory do zapisu zostana zamkni ete. Pozostawienie otwartego deskryptora do zapisu jest interpretowane przez system jako możliwość dalszego przekazywania kolejnych danych, czego konsekwencja jest blokowanie procesów odczytujacych w funkcji read. Sytuacja taka może prowadzić do zakleszczenia (ang. deadlock). Istotne jest zatem zamykanie zb ednych deskryptorów, zw laszcza deskryptorów l acza do zapisu. W systemie UNIX wyróżnia sie dwa rodzaje l aczy l acza nazwane i l acza nienazwane. Zwyczajowo przyje lo sie określać l acza nazwane terminem kolejki FIFO, a l acza nienazwane terminem potoki. L acze nazwane ma dowiazanie w systemie plików, co oznacza, że jego nazwa jest widoczna w jakimś katalogu i może ona s lużyć do identyfikacji l acza. L acze nienazwane nie ma nazwy w żadnym katalogu i istnieje tak d lugo po utworzeniu, jak d lugo otwarty jest jakiś deskryptor tego l acza. 4.1 Sposób korzystania z l acza nienazwanego Ponieważ l acze nienazwane nie ma dowiazania w systemie plików, nie można go identyfikować przez nazwe. Jeśli procesy chca sie komunikować za pomoca takiego l acza, musza znać jego deskryptory. Oznacza to, że procesy musza uzyskać deskryptory tego samego l acza, nie znajac jego nazwy. Jedynym sposobem przekazania informacji o l aczu nienazwanym jest przekazanie jego deskryptorów procesom potomnym dzieki dziedziczeniu tablicy otwartych plików od swojego procesu macierzystego. Za pomoca l acza nienazwanego moga sie zatem komunikować procesy, z których jeden otworzy l l acze nienazwane, a nastepnie utworzy l pozosta le komunikujace sie procesy, które w ten sposób otrzymaja w tablicy otwartych plików deskryptory istniejacego l acza. L acze nienazwane tworzy funkcja systemowa pipe, zwracajac 2 deskryptory jeden do odczytu danych z l acza, a drugi do zapisu danych do l acza. 2 Wyjatkiem od tej zasady jest przypadek, w którym l acze funkcjonuje w trybie bez blokowania (jest ustawiona flaga O_NDELAY).

28 4 L acza int pipe(int fd[2]) utworzenie l acza nienazwanego. Funkcja zwraca 0 w przypadku poprawnego zakończenia lub 1 w przypadku b ledu. Opis parametrów: fd tablica 2 deskryptorów, która jest parametrem wyjściowym (fd[0] jest deskryptorem potoku do odczytu, a fd[1] jest deskryptorem potoku do zapisu). Listing 1 pokazuje przyk ladowe użycie l acza do przekazania napisu (ciagu znaków) Hallo! z procesu potomnego do macierzystego. 3 Listing 1: Przyk lad użycia l acza nienazwanego w komunikacji przodek-potomek main() { int pdesk[2]; if (pipe(pdesk) == -1){ perror(" Tworzenie potoku"); 6 9 switch(fork()){ case -1: // blad w tworzeniu procesu perror(" Tworzenie procesu"); 12 case 0: // proces potomny if (write(pdesk[1], "Hallo!", 7) == -1){ 15 perror("zapis do potoku"); 18 exit(0); default: { // proces macierzysty char buf[10]; 21 if (read(pdesk[0], buf, 10) == -1){ perror("odczyt z potoku"); 24 printf("odczytano z potoku: %s\n", buf); 27 Opis programu: Do utworzenia i zarazem otwarcia l acza nienazwanego s luży funkcja systemowa pipe, wywo lana przez proces macierzysty (linia 4). Nastepnie tworzony jest proces potomny przez wywo lanie funkcji systemowejfork w linii 9, który dziedziczy tablice otwartych plików swojego przodka. Warto zwrócić uwage na sposób sprawdzania poprawności wykonania funkcji systemowych zw laszcza w przypadku funkcji fork, która kończy sie w dwóch procesach macierzystym i potomnym. Proces potomny wykonuje program zawarty w liniach 14 19 i zapisuje do potoku ciag 7 bajtów spod adresu poczatkowego napisu Hallo!. Zapis tego ciagu polega na wywo laniu funkcji systemowej write na odpowiednim deskryptorze, podobnie jak w przypadku pliku zwyk lego. Proces macierzysty (linie 20 25) próbuje za pomoca funkcji read na odpowiednim deskryptorze odczytać ciag 10 bajtów i umieścić go w buforze wskazywanym przez buf (linia 21). buf jest adresem poczatkowym tablicy znaków, zadeklarowanej w linii 20. Odczytany ciag znaków może być krótszy, niż to wynika z rozmiaru bufora i wartości trzeciego parametru funkcji read (odczytane zostanie mniej niż 10 bajtów). Zawartość bufora, odczytana z potoku, wraz z odpowiednim napisem zostanie przekazana na standardowe wyjście. Listing 2 zawiera zmodyfikowana wersje przyk ladu przedstawionego na listingu 1. W poniższym przyk ladzie zak lada sie, że wszystkie funkcje systemowe wykonuja sie poprawnie, w zwiazku z czym w kodzie programu nie ma reakcji na b ledy.

4.1 Sposób korzystania z l acza nienazwanego 29 1 main() { int pdesk[2]; Listing 2: Przyk lad odczytu z pustego l acza 4 pipe(pdesk); if (fork() == 0){ // proces potomny 7 write(pdesk[1], "Hallo!", 7); exit(0); 10 else { // proces macierzysty char buf[10]; read(pdesk[0], buf, 10); 13 read(pdesk[0], buf, 10); printf("odczytano z potoku: %s\n", buf); 16 Opis programu: Podobnie, jak w przyk ladzie na listingu 1, proces potomny przekazuje macierzystemu przez potok ciag znaków Hallo!, ale proces macierzysty próbuje wykonać dwa razy odczyt zawartości tego potoku. Pierwszy odczyt (linia 12) b edzie mia l taki sam skutek jak w poprzednim przyk ladzie. Drugi odczyt (linia 13) spowoduje zawieszenie procesu, gdyż potok jest pusty, a proces macierzysty ma otwarty deskryptor do zapisu. Gdyby sie tak zdarzy lo, że proces macierzysty nie odczyta ca lego bloku zapisanego przez potomka co teoretycznie jest możliwe drugie wywo lanie funkcji read nie zablokuje procesu macierzystego, lecz zwróci kolejna porcje danych zapisanych przez potomka. Listing 3 pokazuje sposób przejecia wyniku wykonania standardowego programu systemu UNIX (w tym przypadku ls) w celu dalszego przetworzenia (w tym przypadku konwersji ma lych liter na duże). Pobranie argumentów z linii poleceń umożliwia przekazanie ich do programu wykonywanego przez proces potomny. 1 #define MAX 512 Listing 3: Konwersja wyniku polecenia ls main(int argc, char* argv[]) { 4 int pdesk[2]; if (pipe(pdesk) == -1){ 7 perror(" Tworzenie potoku"); 10 switch(fork()){ case -1: // blad w tworzeniu procesu 13 perror(" Tworzenie procesu"); case 0: // proces potomny 16 dup2(pdesk[1], 1); execvp("ls", argv); perror(" Uruchomienie programu ls"); 19 default: { // proces macierzysty char buf[max]; 22 int lb, i; close(pdesk[1]); 25 while ((lb=read(pdesk[0], buf, MAX)) > 0){

30 4 L acza for(i=0; i<lb; i++) buf[i] = toupper(buf[i]); 28 if (write(1, buf, lb) == -1){ perror (" Zapis na standardowe wyjscie"); 31 if (lb == -1){ 34 perror("odczyt z potoku"); 37 Opis programu: Program jest podobny do przyk ladu z listingu 1, przy czym w procesie potomnym nastepuje przekierowanie standardowego wyjścia do potoku (linia 16), a nastepnie uruchamiany jest program ls (linia 17). W procesie macierzystym dane z potoku sa sukcesywnie odczytywane (linia 25), ma le litery w odczytanym bloku konwertowane sa na duże (linie 26 27), a nastepnie blok jest zapisywany na standardowym wyjściu procesu macierzystego. Powyższa sekwencja powtarza sie w p etli (linie 25 32) tak d lugo, aż funkcja systemowa read zwróci wartość 0 (lub 1 w przypadku b ledu). Istotne jest zamkniecie deskryptora potoku do zapisu (linia 24) w celu unikniecia zawieszenia procesu macierzystego w funkcji read. Przyk lad na listingu 4 pokazuje realizacje programowa potoku ls tr a-z A-Z, w którym proces potomny wykonuje polecenie ls, a proces macierzysty wykonuje polecenie tr. Funkcjonalnie jest to odpowiednik programu z listingu 3. Listing 4: Programowa realizacja potoku ls tr a-z A-Z na l aczu nienazwanym main(int argc, char* argv[]) { 2 int pdesk[2]; if (pipe(pdesk) == -1){ 5 perror(" Tworzenie potoku"); 8 switch(fork()){ case -1: // blad w tworzeniu procesu 11 perror(" Tworzenie procesu"); case 0: // proces potomny 14 dup2(pdesk[1], 1); execvp("ls", argv); perror(" Uruchomienie programu ls"); 17 default: { // proces macierzysty close(pdesk[1]); 20 dup2(pdesk[0], 0); execlp("tr", "tr", "a-z", "A-Z", 0); perror(" Uruchomienie programu tr"); 23 26

4.2 Sposób korzystania z l acza nazwanego 31 Opis programu: Program procesu potomnego (linie 16 19) jest taki sam, jak w przyk ladzie na listingu 3. W procesie macierzystym nastepuje z kolei przekierowanie standardowego wejścia na pobieranie danych z potoku (linia 22), po czym nastepuje uruchomienie programu tr (linia 23). W celu zagwarantowania, że przetwarzanie zakończy sie w sposób naturalny konieczne jest zamkniecie wszystkich deskryptorów potoku do zapisu. Deskryptory w procesie potomnym zostana zamkniete wraz z jego zakończeniem, a deskryptor w procesie macierzystym zamykany jest w linii 21. 4.2 Sposób korzystania z l acza nazwanego Operacje zapisu i odczytu na l aczu nazwanym wykonuje sie tak samo, jak na l aczu nienazwanym, inaczej natomiast sie je tworzy i otwiera. L acze nazwane tworzy sie poprzez wywo lanie funkcji mkfifo w programie procesu lub przez wydanie polecenia mkfifo na terminalu. Funkcja mkfifo tworzy plik specjalny typu l acze podobnie, jak funkcja creat tworzy plik zwyk ly. Funkcja mkfifo nie otwiera jednak l acza i tym samym nie przydziela deskryptorów. L acze nazwane otwierane jest funkcjaopen podobnie jak plik zwyk ly, przy czym l acze musi zostać otwarte jednocześnie w trybie do zapisu przez jeden proces i w trybie do odczytu przez inny proces. W przypadku wywo lania funkcji open tylko w jednym z tych trybów proces zostanie zablokowany aż do momentu, gdy inny proces nie wywo la funkcji open w trybie komplementarnym. int mkfifo(const char *pathname, mode_t mode) utworzenie pliku specjalnego typu l a- cze. Funkcja zwraca 0 w przypadku poprawnego zakończenia lub 1 w przypadku b ledu. Opis parametrów: pathname nazwa pliku (w szczególności nazwa ścieżkowa), mode prawa dostepu do nowo tworzonego pliku. Program na listingu 5 pokazuje przyk ladowe tworzenie l acza i prób e jego otwarcia w trybie do odczytu. #include <fcntl.h> Listing 5: Przyk lad tworzenie i otwierania l acza nazwanego 3 main(){ mkfifo("kolfifo", 0600); open("kolfifo", O_RDONLY); 6 Opis programu: Funkcja mkfifo (linia 4) tworzy plik specjalny typu l acze o nazwie kolfifo z prawem zapisu i odczytu dla w laściciela. W linii 5 nastepuje próba otwarcia l acza w trybie do odczytu. Proces zostanie zawieszony w funkcji open do czasu, aż inny proces b edzie próbowa l otworzyć te sama kolejke w trybie do zapisu. Listing 6 pokazuje realizacje przyk ladu z listingu 1, w której wykorzystane zosta lo l acze nazwane. #include <fcntl.h> 3 main() { int pdesk; Listing 6: Przyk lad tworzenie i otwierania l acza nazwanego 6 if (mkfifo("/tmp/fifo", 0600) == -1){ perror(" Tworzenie kolejki FIFO"); 9

32 4 L acza switch(fork()){ 12 case -1: // blad w tworzeniu procesu perror(" Tworzenie procesu"); 15 case 0: pdesk = open("/tmp/fifo", O_WRONLY); if (pdesk == -1){ 18 perror("otwarcie potoku do zapisu"); 21 if (write(pdesk, "Hallo!", 7) == -1){ perror("zapis do potoku"); 24 exit(0); default: { 27 char buf[10]; pdesk = open("/tmp/fifo", O_RDONLY); 30 if (pdesk == -1){ perror("otwarcie potoku do odczytu"); 33 if (read(pdesk, buf, 10) == -1){ perror("odczyt z potoku"); 36 printf("odczytano z potoku: %s\n", buf); 39 Opis programu: L acze nazwane (kolejka FIFO) tworzona jest w wyniku wykonania funkcji mkfifo w linii 6. Nastepnie tworzony jest proces potomny (linia 11) i l acze otwierane jest przez oba procesy (potomny i macierzysty) w sposób komplementarny (odpowiednio linia 16 i linia 29). W dalszej cześci przetwarzanie przebiega tak, jak w przyk ladzie na listingu 1. Listing 7 jest programowa realizacja potoku ls tr a-z A-Z, w której wykorzystane zosta lo l acze nazwane podobnie, jak l acze nienazwane w przyk ladzie na listingu 4. 3 6 Listing 7: Programowa realizacja potoku ls tr a-z A-Z na l aczu nazwanym #include <stdio.h> #include <fcntl.h> main(int argc, char* argv[]) { int pdesk; if (mkfifo("/tmp/fifo", 0600) == -1){ perror(" Tworzenie kolejki FIFO"); 9 12 switch(fork()){ case -1: // blad w tworzeniu procesu perror(" Tworzenie procesu"); 15 case 0: // proces potomny

4.3 Przyk lady b ledów w synchronizacji procesów korzystajacych z l aczy 33 close(1); 18 pdesk = open("/tmp/fifo", O_WRONLY); if (pdesk == -1){ perror("otwarcie potoku do zapisu"); 21 else if (pdesk!= 1){ 24 fprintf(stderr, "Niewlasciwy deskryptor do zapisu\n"); 27 execvp("ls", argv); perror(" Uruchomienie programu ls"); 30 default: { // proces macierzysty close(0); pdesk = open("/tmp/fifo", O_RDONLY); 33 if (pdesk == -1){ perror("otwarcie potoku do odczytu"); 36 else if (pdesk!= 0){ fprintf(stderr, "Niewlasciwy deskryptor do odczytu\n"); 39 execlp("tr", "tr", "a-z", "A-Z", 0); 42 perror(" Uruchomienie programu tr"); 45 Opis programu: W linii 7 tworzona jest kolejka FIFO o nazwie fifo w katalogu /tmp z prawem do zapisu i odczytu dla w laściciela. Kolejka ta otwierana jest przez proces potomny i macierzysty w trybie odpowiednio do zapisu i do odczytu (linia 18 i linia 33). Nastepnie sprawdzana jest poprawność wykonania operacji otwarcia (linie 19 i 34) oraz poprawność przydzielonych deskryptorów (linie 23 i 38. Sprawdzanie poprawności deskryptorów polega na upewnieniu sie, że deskryptor l acza do zapisu ma wartość 1 ( l acze jest standardowym wyjściem procesu potomnego), a deskryptor l acza do odczytu ma wartość 0 ( l acze jest standardowym wejściem procesu macierzystego). Później nastepuje uruchomienie odpowiednio programów ls i tr podobnie, jak w przyk ladzie na listingu 4. 4.3 Przyk lady b ledów w synchronizacji procesów korzystajacych z l aczy Operacje zapisu i odczytu na l aczach realizowane sa w taki sposób, że procesy podlegaja synchronizacji zgodnie ze modelem producent-konsument. Nieodpowiednie użycie dodatkowych mechanizmów synchronizacji może spowodować konflikt z synchronizacja na l aczu i w konsekwencji prowadzić do stanów niepożadanych typu zakleszczenie (ang. deadlock). Listing 8 przedstawia przyk lad programu, w którym może nastapić zakleszczenie, gdy pojemność l acza okaże sie zbyt ma la dla pomieszczenia ca lości danych przekazywanych przez polecenie ls. 1 #define MAX 512 Listing 8: Możliwość zakleszczenia w operacji na l aczu nienazwanym main(int argc, char* argv[]) { 4 int pdesk[2];

34 4 L acza if (pipe(pdesk) == -1){ 7 perror(" Tworzenie potoku"); 10 if (fork() == 0){ // proces potomny dup2(pdesk[1], 1); 13 execvp("ls", argv); perror(" Uruchomienie programu ls"); 16 else { // proces macierzysty char buf[max]; 19 int lb, i; close(pdesk[1]); 22 wait(0); while ((lb=read(pdesk[0], buf, MAX)) > 0){ for(i=0; i<lb; i++) 25 buf[i] = toupper(buf[i]); write(1, buf, lb); 28 Opis programu: Podobnie jak w przyk ladzie na listingu 3 proces potomny przekazuje dane (wynik wykonania programu ls) do potoku (linie 12 15), a proces macierzysty przejmuje i przetwarza te dane w p etli w liniach 23 27. Przed przejściem do wykonania p etli proces macierzysty oczekuje na zakończenie potomka (linia 22). Jeśli dane generowane przez program ls w procesie potomnym nie zmieszcza sie w potoku, proces ten zostanie zablokowany gdzieś w funkcji write w programie ls. Proces potomny nie b edzie wiec zakończony i tym samym proces macierzysty nie wyjdzie z funkcji wait. Odblokowanie potomka może nastapić w wyniku zwolnienia miejsca w potoku przez odczyt znajdujacych sie w nim danych. Dane te powinny zostać odczytane przez proces macierzysty w wyniku wykonania funkcji read (linia 23), ale proces macierzysty nie przejdzie do linii 23 przed zakończeniem potomka. Proces macierzysty blokuje zatem potomka, nie zwalniajac miejsca w potoku, a proces potomny blokuje przodka w funkcji wait, nie kończac sie. Wystapi zatem zakleszczenie. Zakleszczenie nie wystapi w opisywanym programie, jeśli wszystkie dane, generowane przez program ls, zmieszcza sie w ca lości w potoku. Wówczas proces potomny b edzie móg l sie zakończyć po umieszczeniu danych w potoku, w nastepstwie czego proces macierzysty b edzie móg l wyjść z funkcji wait i przystapić do przetwarzania danych z potoku. Przyk lad na listingu 9 pokazuje zakleszczenie w wyniku nieprawid lowości w synchronizacji przy otwieraniu l acza nazwanego. 3 6 Listing 9: Możliwość zakleszczenia przy otwieraniu l acza nazwanego #include <fcntl.h> #define MAX 512 main(int argc, char* argv[]) { int pdesk; if (mkfifo("/tmp/fifo", 0600) == -1){ perror(" Tworzenie kolejki FIFO"); 9

4.4 Zadania 35 12 if (fork() == 0){ // proces potomny close(1); open("/tmp/fifo", O_WRONLY); 15 execvp("ls", argv); perror(" Uruchomienie programu ls"); 18 else { // proces macierzysty char buf[max]; 21 int lb, i; wait(0); 24 pdesk = open("/tmp/fifo", O_RDONLY); while ((lb=read(pdesk, buf, MAX)) > 0){ for(i=0; i<lb; i++) 27 buf[i] = toupper(buf[i]); write(1, buf, lb); 30 Opis programu: Proces potomny w linii 13 próbuje otworzyć kolejke FIFO do zapisu. Zostanie on zatem zablokowany do momentu, aż inny proces wywo la funkcje open w celu otwarcia kolejki do odczytu. Jeśli jedynym takim procesem jest proces macierzysty (linia 23), to przejdzie on do funkcji open dopiero po zakończeniu procesu potomnego, gdyż wcześniej zostanie zablokowany w funkcji wait. Proces potomny nie zakończy sie, gdyż b edzie zablokowany w funkcji open, wiec b edzie blokowa l proces macierzysty w funkcji wait. Proces macierzysty nie umożliwi natomiast potomkowi wyjścia z open, gdyż nie może przejść do linii 23. Nastapi zatem zakleszczenie. 4.4 Zadania 4.1. Jaki b edzie wynik wykonania programu na listingu 10? 1 main() { int pdesk[2]; char buf[20]; 4 pipe(pdesk); Listing 10: 7 if (fork() == 0){ // proces potomny read(pdesk[0], buf, 20); printf("odczytano z potoku: %s\n", buf); 10 write(pdesk[1], "Hallo od potomka!", 18); exit(0); 13 else { // proces macierzysty read(pdesk[0], buf, 20); printf("odczytano z potoku: %s\n", buf); 16 write(pdesk[1], "Hallo od przodka!", 18); 4.2. Zrealizować na l aczach nienazwanych oraz nazwanych nastepujace potoki: a) finger cut -d -f1

36 4 L acza b) ps -ef grep ^root c) cat /etc/passwd cut -f5 -d: d) ls -l grep ^d more e) ps -ef tr -s cut -f2 -d f) finger tr -s cut -f2,3 -d g) who cut -f1 -d sort uniq -c h) history cut -c7- tail -30 sort uniq i) ps -ef tr -s \ : cut -f1 -d: sort uniq -c sort -n 4.3. Napisać program do zabijania wszystkich procesów użytkownika, którego nazwa podana jako argument linii poleceń. 4.4. Napisać program do obliczania l acznej liczby znaków we wszystkich nazwach plików w katalogu podanym jako argument linii poleceń. 4.5 Pytania kontrolne 1. Ile deskryptorów tworzy funkcja systemowa pipe? 2. Czym sie różni l acze nienazwane od nazwanego? Na czym polega różnica w sposobie użycia jednego i drugiego rodzaju l acza? 3. Jakie ograniczenia na możliwość komunikacji pomiedzy procesami wprowadza potok ( l acze nienazwane)? 4. W czym sa podobne, a czym sie różnia od siebie funkcje creat i mkfifo? 5. Co sie stanie przy próbie odczytu danych z pustego l acza? 6. Czym sie różni sposób dostepu do plików zwyk lych od dostepu do l aczy komunikacyjnych? 7. Jaka operacja dostepu do pliku (zwyk lego lub specjalnego) i w jaki sposób informuje o osiagnieciu końca pliku? 8. Jakie funkcje systemowe zwracaja deskryptory plików?