SOISK - SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE
Tomasz Puchała

materialyPSR

SYSTEMY ROZPROSZONE

 

SYSTEMY ROZPROSZONE

1. Procesy i wątki.

1.1 Procesy.

 

Procesem nazywamy program sekwencyjny, który jest wykonywany (jest w trakcie wykonywania). Proces jest sekwencją zmian systemu komputerowego, które zachodzą zgodnie z algorytmem zapisanym w programie. Aby zaistniała możliwość wykonywania procesu, niezbędne są dwa urządzenia, tj. procesor, którego zadaniem jest wykonywanie operacji zgodnych z algorytmem oraz pamięć operacyjna, w której przechowywany jest kod (algorytm) programu. Przykładem procesu skończonego może być np. rozwiązanie równania matematycznego, a zakończenie procesu następuje w chwili uzyskania wyniku (zgodnie z algorytmem). Natomiast przykładem procesu nieskończonego może być system operacyjny, którego podstawową cechą jest praca ciągła i nie może dojść do sytuacji, kiedy nagle system operacyjny przestanie działać i zaprzestanie przyjmowania komend od użytkownika. W przypadku, kiedy jeden proces jest wykonywany przed rozpoczęciem drugiego, mówimy o procesach współbieżnych. Doskonałym przykładem jest właśnie system operacyjny, w którym procesy składające się na działanie systemu operacyjnego wykonywane są współbieżnie z procesami inicjowanymi przez użytkownika. Procesy mogą ze sobą współpracować lub być niezależne. Aby działanie wielu procesów możliwe było na maszynie posiadającej jeden procesor, konieczny jest przydział czasu, w jakim może być dany proces wykonywany. Dzieje się tak dlatego, że w danej chwili procesor jest w stanie wykonywać jeden proces. Przydzielanie czasu umożliwia wykonywanie procesów sekwencyjnie, niejako po kawałku procesu, w ustalonych przedziałach czasu przypadających na dany proces. W ten sposób możliwa jest praca wieloprocesowa na maszynie jednoprocesowej. Działanie współbieżne bezpośrednio wiąże się ze wzrostem wydajności. Na stacjach wieloprocesorowych każdy proces wykonywany jest na innym procesorze i jeśli ilość procesów nie przekracza ilości procesorów, wówczas nie ma potrzeby stosowania przydziału czasu.

Stan procesu określa się następująco:

ü  running - wykorzystywany jest kod procesu, proces jest w trakcie wykonywania

ü  waiting – oczekiwanie (zablokowanie), proces czeka na wystąpienie ustalonego zdarzenia

ü  ready – proces czeka na przydział procesora, resztę zasobów ma przydzielone

W danym momencie tylko jeden proces może być aktywny, natomiast może istnieć wiele procesów oczekujących lub gotowych. Możliwość wykonywania współbieżnego procesów pociąga za sobą konieczność zbudowania jednostki odpowiedzialnej za tworzenie i kończenie procesów. Proces może utworzyć nowy proces. Jest to możliwe za pomocą funkcji systemowej create. Proces taki nazywa się procesem macierzystym, natomiast proces przez niego utworzony nazywamy procesem potomnym. Proces macierzysty może pracować równocześnie ze swymi procesami potomnymi (które zresztą również mogą tworzyć swoje procesy potomne) lub oczekiwać na wykonanie wszystkich czynności, które miały wykonać podprocesy i dalej kontynuować działanie. Tworzenie procesów potomnych wiąże się jednak z koniecznością przydzielania nowych zasobów, które może otrzymać od systemu operacyjnego lub od procesu macierzystego. Ilość zasobów jest więc ograniczona. Ponadto ilość procesów ograniczona zostaje poprzez rozmiar tablicy rozkazów. Proces potomny nie może zostać zakończony dopóki, dopóty nie wykona wszystkich zaprogramowanych czynności. Następnie proces potomny przekazuje swoje informacje swojemu „przodkowi” poprzez wywołanie funkcji exit. Ten z kolei wywołując funkcję abort powoduje zakończenie procesu potomnego. Istnieją również inne możliwości zakończenia działania procesu potomnego. Ma to miejsce w przypadku, kiedy podproces nadużył przydzielonych zasobów, bądź stwierdzono, że jego działanie jest już zbędne. Współczesne systemy operacyjne zapewniają ponadto automatyczne zakończenie procesów potomnych, jeśli nie działa już proces macierzysty (zakończenie kaskadowe).

Wspomniany wcześniej proces niezależny charakteryzuje się tym, że wyniki działania innych procesów nie wpływają w żaden sposób na jego działanie. W takim przypadku stan procesu nie jest w żaden sposób współdzielony z innymi procesami. Wynik działania takiego procesu jest zależny wyłącznie od jego danych początkowych, czyli wielokrotne działanie procesu z identycznymi danymi wejściowymi spowoduje uzyskanie zawsze takich samych danych wynikowych. Ponadto zatrzymywanie i ponowne uruchamianie procesu nie powoduje żadnych zmian.

Proces współpracujący charakteryzuje się tym, iż może wpływać na działanie innych procesów, bądź sam jest zależny od innych procesów. Stan takiego procesu może być współdzielony i innymi procesami. Nie można przewidzieć wyniku działania takiego procesu, ponieważ jest on zależny od innych procesów, ponadto nawet przy tych samych danych wejściowych można uzyskać różne wyniki (nie można przewidzieć działanie innych procesów, z którymi dzielone są zasoby).

1.2 Wątki.

 

Wątek to podstawowa jednostka wykorzystująca procesor (inaczej nazywany lekkim procesem). Wątkami nazywa się takie procesy, które są wykonywane we wspólnej przestrzeni adresowej. Jest dynamiczną częścią procesu, która zawiera licznik rozkazów, rejestry oraz stos. Wątki współdzielą pomiędzy sobą przestrzeń adresową, kod i zasoby systemu operacyjnego. W systemach wieloprocesorowych wątki umożliwiają wykorzystanie przez proces wszystkich procesorów. Stosowanie wątków w programach owocuje zwiększona efektywnością działania a także pozwala na uproszczenie struktury programu. Używanie wątków przyśpiesza działanie programu, ponieważ przełączanie pomiędzy wątkami jest szybsze niż pomiędzy procesami wykorzystującymi jeden wątek, co wiąże się z obniżeniem kosztów.

Wątki charakteryzują się następującymi cechami:

ü  wykonywane są sekwencyjnie

ü  każdy wątek posiada własny licznik rozkazów i stos

ü  w systemach jednoprocesorowych podobnie jak procesy dzielą pomiędzy sobą czas przydziału do procesora

ü  w systemach wieloprocesorowych wykonywane są równolegle (jeden wątek na jednym procesorze)

ü  podobnie jak procesy mogą tworzyć wątki pochodne

ü  posiada dostęp do dowolnego adresu w zakresie procesu, więc może pracować na stosie innego wątku

ü  informacja o stanie wątku zajmuje niewielką ilość pamięci

ü  wątki mogą znajdować się w jednym z trzech stanów: zawieszony, wykonywany, zakończony

ü  wątki nie współzawodniczą między sobą

 

1.3 Wątki a zdalne wywoływanie procedur.

Jedną z najpopularniejszych form usługi zdalnej jest wzorzec postępowania określany jako RPC, czyli zdalne wywoływanie procedury. Wywołanie RPC zaprojektowano jako sposób uogólnienia mechanizmu wywołania procedury na użytek systemów połączonych siecią. Pod wieloma względami jest ono podobne do mechanizmu komunikacji międzyprocesowej. W przeciwieństwie do komunikacji międzyprocesowej komunikaty wymieniane w trybie RPC mają ściśle określoną budowę i nie są już zwykłymi pakietami danych. Są one adresowane do demona RPC, który prowadzi nasłuch portu RPC w odległym systemie i zawierają identyfikator funkcji do wykonania, jak również parametry, które należy jej przekazać. Funkcja taka zostanie następnie wykonana zgodnie z życzeniem, a wszystkie wyniki będą odesłane do zamawiającego w oddzielnym komunikacie. System zazwyczaj posiada tylko jeden adres sieciowy, ale może pod tym adresem udostępniać wiele portów (port jest numerem umieszczonym na początku pakietu z komunikatem), aby rozróżniać swoje liczne usługi sieciowe. Jeśli proces zdalny potrzebuje obsługi, to adresuje komunikat do właściwego portu. Mechanizm RPC jest powszechnie stosowany w systemach sieciowych. Jednym z istotnych związanych z nim zagadnień jest semantyka wywołania. Procedura lokalna ulega awarii jedynie w wyjątkowych sytuacjach, natomiast wywołania RPC mogą zawodzić albo być podwajane i wykonywane więcej niż jednokrotnie z powodu typowych niedomagań sieci. Ponieważ często mamy do czynienia z przesyłaniem komunikatów przez zawodne łącza komunikacyjne, więc z tego powodu łatwiej jest zapewniać w systemie operacyjnym co najwyżej jednokrotne wystąpienie danego komunikatu, niż gwarantować, że komunikat pojawi się dokładnie jeden raz. Inne ważne zagadnienie dotyczy komunikacji między serwerem a klientem. W standardowych wywołaniach procedur dochodzi do wiązań podczas konsolidacji, ładowania lub wykonywania, co powoduje, że nazwa wywołania procedury jest zastępowana przez adres wywołania danej procedury w pamięci.

W systemach rozproszonych równie częste zastosowanie jak zdalne wywołania procedur znajdują wątki. Nadają się one do wysyłania i przyjmowania komunikatów w sposób umożliwiający asynchroniczne wykonywanie innych operacji w zadaniu. Ułatwiają one zaprogramowanie i zwiększenie wydajności docelowego procesu, co z kolei pozwala na obsługiwanie zamówienia od początku do końca w jednym wątku i jednoczesne wykonywanie przez jego sąsiadów tych samych czynności w odniesieniu do innych zamówień.   

 

1.4 Szeregowanie procesów, podstawowe algorytmy szeregowania
i ich własności.

 

Właściwe przydzielanie procesorów i decydowanie o kolejności wykonywania procesów należy do podstawowych zadań systemu operacyjnego. System operacyjny posiada odpowiednie moduły rozwiązujące ten problem. Procesy, których status jest określony jako gotowy umieszczane są w kolejce. Z reguły to procesy systemowe obsługiwane są niejako „poza kolejnością”, natomiast konkurujące między sobą procesy użytkowników obsługiwane zostają zgodnie z pewnymi regułami.

Istnieją trzy podstawowe etapy szeregowania:

ü  wysoki – określa kolejkę zadań, które chcą skorzystać z zasobów systemu

ü  pośredni – obsługa procesów, które posiadają status gotowy lub zawieszony

ü  niski – decyduje któremu procesowi będącemu w stanie gotowości zostaje przydzielony procesor

Podstawą procesu szeregowania są tzw. kolejki zadań, do których trafiają zadania lub procesy. Proces po wprowadzeniu do systemu trafia do kolejki zadań. Kolejka zawiera wszystkie procesy oczekujące na przydział pamięci. Jest on następnie w odpowiedni sposób porządkowana. Kolejka ta związana jest wysokim poziomem szeregowania.
W kolejnym kroku tworzona jest kolejka procesów gotowych (poziom niski). W tej kolejce zapada decyzja, któremu z gotowych procesów przydzielony zostanie procesor.

Algorytmy szeregowania dzielą się pod względem cech ich działania:

ü  efektywność – utrzymywanie pełnego obciążenia procesora

ü  przepustowość – polega na wymuszeniu wykonania jak największej ilości obliczenie w jednostce czasu

ü  czas oczekiwania – minimalizowanie czasu oczekiwania użytkownika na wyniki działania ich zadań

ü  czas odpowiedzi – minimalizacja czasu odpowiedzi dla użytkowników interakcyjnych

Algorytmy przydziału procesora podzielić można również na algorytmy z wywłaszczaniem i bez wywłaszczania. Pierwszy z nich charakteryzuje się tym, iż procesor może zostać odebrany procesowi nawet w trakcie jego wykonywania, natomiast w drugim przypadku proces utrzymuje procesor aż do jego zakończenia

Algorytm FCFS (First Come First Served).

Jak wskazuje nazwa obsługuje najpierw te procesy, które zostały w pierwszej kolejności wprowadzone do kolejki. Nie jest dobrym algorytmem, ponieważ w przypadku, kiedy w kolejce znajduje się jakiś duży proces, który będzie wymagał długiego czasu na jego zrealizowanie, powstanie blokada na czas wykonywania tego procesu, więc inne procesy w kolejce będą musiały długo czekać. Jest nieprzydatny w systemach interakcyjnych z podziałem czasu, natomiast jest często stosowany w systemach, w których procesy posiadają taki sam priorytet. Jest algorytmem bez wywłaszczania.

Algorytm SJF (Shortest Job First) - szereguje zadania zgodnie z porządkiem określonym przez czasy ich wykonywania - najpierw wykonywane jest zadanie najkrótsze. Algorytm więc faworyzuje zadania krótkie. Udowodniono, że jest to algorytm optymalny ze względu na średni czas przebywania procesów w systemie. Wadą tego algorytmu jest to, iż zadanie wymagające długiego obsługiwania przez procesor długo czekają na swoje wykonanie.

Algorytmy priorytetowe - każdemu procesowi przydziela się pewien priorytet, po czym procesor przydziela się temu procesowi, którego priorytet jest najwyższy. Procesy o równych priorytetach są porządkowane na ogól według algorytmu FCFS. Priorytety mogą być definiowane w sposób statyczny lub dynamiczny oraz mogą być przydzielane dynamicznie po to, aby osiągnąć określone cele systemowe, np. jeśli specjalny proces zażąda przydziału procesora, powinien go otrzymać natychmiast. Planowanie priorytetowe może być wywłaszczające lub niewywłaszczające. Podstawowym problemem w planowaniu priorytetowym jest stałe blokowanie (ang. indefinite blocking, starvation, livelock).

Algorytm rotacyjny - procesor jest przydzielany zadaniom kolejno na określony odcinek czasu (kwant). Kwant czasu przydziału procesora jest najczęściej rzędu 10 do 100 msek. Kolejka procesów gotowych jest traktowana jak kolejka cykliczna - nowe procesy są dołączane na koniec kolejki procesów gotowych. W przypadku, kiedy proces ma fazę procesora krótszą niż przydzielony kwant czasu, to wówczas z własnej inicjatywy zwalnia procesor. Jeśli faza procesora procesu jest dłuższa niż przydzielony kwant czasu, to nastąpi przerwanie zegarowe i przełączenie kontekstu, a proces przerwany trafia na koniec kolejki. Podstawowym problemem przy konstrukcji algorytmu RR jest określenie długości kwantu czasu. (jeśli kwant czasu jest bardzo mały to algorytm RR nazywa się dzieleniem procesora).

Algorytm wielopoziomowego planowania

Kolejkę procesów gotowych rozdziela się na kilka kolejek, z reguły w zależności od procesu. Procesy zostają na stałe przydzielone są do tych kolejek. Każda kolejka ma własny alg. planowania. Najczęściej jest to implementowane jako dwie kolejki: procesy pierwszoplanowe (alg. rotacyjny) i drugoplanowe (alg. FCFS). Musi istnieć alg. planowania między kolejkami. Stałopriorytetowe planowanie wywłaszczające: każda kolejka ma bezwzględne pierwszeństwo przed kolejkami o niższych priorytetach tzn., że żaden z procesów z kolejki o danym priorytecie nie może pracować dopóki kolejki znajdujące się nad tą kolejką nie są puste. Jeśli podczas wykonywania procesu do systemu zostanie wprowadzony nowy proces o wyższym priorytecie, to aktualnie wykonywany proces zostanie wywłaszczony; Planowanie ze sprzężeniem zwrotnym: pomiędzy kolejki rozdziela się procesy o różnych fazach procesora. Jeśli proces używa zbyt dużo czasu procesora, to zostaje przesunięty do kolejki o niższym priorytecie. Proces zbyt długo oczekujący w kolejce i niskim priorytecie może zostać przeniesiony do kolejki o wyższym priorytecie. Rozwiązuje to problem głodzenia procesów.

1.4 Projekt laboratoryjny - Budowa prostej aplikacji wielowątkowej w języku C.

 

 

 

2. Problem wzajemnego wykluczania.

2.1 Pojęcie sekcji krytycznej, protokół wstępny i protokół końcowy.

 

Procesy współbieżne mogą ze sobą współzawodniczyć o dostęp do wspólnie użytkowanych zasobów. Chodzi tu o takie zasoby, które w danej chwili mogą być wykorzystywane tylko przez jeden proces (lub ograniczoną ich liczbę, mniejszą od liczby chętnych). Jest to sytuacja dość często spotykana w życiu. Każdemu zdarzyło się, że chciał skorzystać z łazienki właśnie wtedy, gdy była ona zajęta, zadzwonić, gdy ktoś już rozmawiał przez telefon. Skądinąd wiadomo, że w każdej takiej sytuacji trzeba po prostu zaczekać (na zwolnienie łazienki, zakończenie rozmowy). Natomiast wtedy, gdy dwie osoby jednocześnie chcą wejść do pustej łazienki, zadzwonić z tego samego telefonu, trzeba zastosować zasadę uprzejmości i dobrych obyczajów. W teorii procesów współbieżnych wspólny obiekt, z którego może korzystać w sposób wyłączny wiele procesów (np. łazienka, telefon) nazywa się zasobem dzielonym, natomiast fragment procesu, w którym korzysta on z obiektu dzielonego (mycie się, telefonowanie), nazywa się sekcją krytyczną tego procesu. Ponieważ w danej chwili z obiektu dzielonego może korzystać tylko jeden proces, wykonując swoją sekcję krytyczną uniemożliwia on wykonanie sekcji krytycznych innym procesom. Problem wzajemnego wykluczania definiuje się następująco: zsynchronizować N procesów, z których każdy w nieskończonej pętli na przemian zajmuje się własnymi sprawami i wykonuje sekcję krytyczną, w taki sposób, aby wykonanie sekcji krytycznych jakichkolwiek dwóch lub więcej procesów nie pokrywało się w czasie. Aby ten problem rozwiązać, należy do treści każdego procesu wprowadzić, dodatkowe instrukcje poprzedzające sekcję krytyczną (nazywa się je protokołem wstępnym - przy wejściu do sekcji proces wykonuje protokół wejścia w którym sprawdza czy może wejść do sekcji krytycznej.) i instrukcje następujące bezpośrednio po sekcji krytycznej (protokół końcowy - po wyjściu z sekcji wykonuje protokół wyjścia aby poinformować inne procesy ze opuścił już sekcje krytyczna i inny proces może ja zająć.). Protokół wstępny i końcowy to po prostu programowa realizacja czekania i stosowanej w życiu zasady uprzejmości.

2.2 Blokada i zagłodzenie procesu.

Blokada.

Powiemy, że zbiór procesów znajduje się w stanie blokady, jeśli każdy z tych procesów jest wstrzymany w oczekiwaniu na zdarzenie, które może być spowodowane tylko przez jakiś inny proces z tego zbioru. Zjawisko blokady, zwane także zastojem, zakleszczeniem lub martwym punktem, jest przejawem braku bezpieczeństwa programu, jest to bowiem stan niepożądany. Zjawisko to może wystąpić również w systemie złożonym z procesów, które są powiązane jedynie przez to, że korzystają z tych samych zasobów komputera. Zauważmy, że jeśli w jakimś programie współbieżnym może wystąpić blokada, nie oznacza to, że wystąpi ona przy każdym wykonaniu tego programu. Dlatego testowanie nie jest dobrą metodą stwierdzania, czy dany zbiór procesów może się zablokować. Czasami unikanie blokady może być bardzo kosztowne. Jeśli jej wystąpienie jest mało prawdopodobne, lepiej godzić się na nią, ale trzeba uruchomić mechanizmy jej wykrywanie i usuwania.

 

Zagłodzenie.

Specyficznym przypadkiem nieskończonego wstrzymywania procesu jest zjawisko zagłodzenia zwane także wykluczenie. Jeśli komunikat lub sygnał synchronizacyjny może być odebrany tylko przez jeden z nań procesów, powstaje problem, który z procesów wybrać. Zjawisko zagłodzenia występuje wówczas, gdy proces nie zostaje wznowiony, mimo że zdarzenie, na które czeka, występuje dowolną liczbę razy. Za każdym razem, gdy proces ten mógłby być wznowiony, jest wybierany jakiś inny czekający proces. Zagłodzenie jest przejawem braku żywotności programu. Zależy ono od strategii wznawiania procesów. Jeśli procesy będą wznawiane zawsze w kolejności, w jakiej zostały wstrzymane (kolejka prosta), to zjawisko zagłodzenia nie wystąpi. Jeśli jednak o kolejności wznawiania decydują priorytety procesów (kolejka priorytetowa), to jest możliwe, że procesy o niższym priorytecie zostaną zagłodzone przez procesy o wyższym priorytecie. O ile istnieją algorytmy pozwalające wykrywać zjawisko blokady w trakcie wykonywania programu, o tyle wykrycie zagłodzenia jest praktycznie niemożliwe. Łatwo, co prawda zaobserwować, że pewien proces czeka bardzo długo na jakieś zdarzenie, które wystąpiło już wiele razy, ale nie wiadomo, jak system zachowa się w przyszłości. Można natomiast wykazać, że w programie współbieżnym jest możliwe zagłodzenie, przez pokazanie nieskończonego ciągu zdarzeń w tym programie, w wyniku którego jeden proces (lub więcej) pozostanie na zawsze wstrzymany.

2.3 Wzajemne wykluczanie dla dwóch procesów (N procesów) – operacje czytaj – zapisz do wspólnej pamięci.

Wzajemne wykluczanie - wymaganie aby ciąg operacji na pewnym zasobie (zwykle pamięci) był wykonany w trybie wyłącznym przez tylko jeden z potencjalnie wielu procesów. Problem wzajemnego wykluczania pojawia się w systemie w momencie gdy istnieje w nim choć jeden zasób niepodzielny; to znaczy, że zasobu tego może używać w danym czasie tylko jeden proces. Jeżeli inny proces zamawia dany zasób, to proces ten musi być opóźniany do czasu, aż zasób zostanie zwolniony. Najszybszym sposobem wymieniania danych pomiędzy procesami jest współdzielenie przez nie pewnego obszaru pamięci. W ten sposób dane umieszczone przez nadawcę są natychmiast dostępne dla odbiorcy. Jednak by zapewnić, prawidłowe odczytywanie
i zapisywanie współdzielonych danych należy wprowadzić mechanizmy, które ograniczą do nich dostęp tak by w jednym momencie operacje na danych wykonywał wyłącznie jeden proces. Jest to jeden z przykładów problemu wzajemnego wykluczania. Dany jest zbiór procesów sekwencyjnych komunikujących się przez wspólną pamięć. Każdy z procesów zawiera sekcję krytyczną , w której następuje dostęp do wspólnej pamięci. Procesy te są procesami cyklicznymi. Zakłada się ponadto:

ü  zapis i odczyt wspólnych danych jest operacją niepodzielną, a próba jednoczesnych zapisów lub odczytów realizowana jest sekwencyjnie w nieznanej kolejności

ü  sekcje krytyczne nie mają priorytetu

ü  względne prędkości wykonywania procesów są nieznane

ü  proces może zostać zawieszony poza sekcją krytyczna

ü  procesy realizujące instrukcje poza sekcją krytyczną nie mogą uniemożliwiać innym procesom wejścia do sekcji krytycznej

ü  procesy powinny uzyskać dostęp do sekcji krytycznej w skończonym czasie

 

 

2.4 Projekt laboratoryjny – Algorytm Petersona.

Jest to rozwiązanie programowe pozbawione wad i można je stosować w systemach rozproszonych. Procesy korzystają z dwóch procedur: wchodzę i wychodzę odnoszących się do sekcji krytycznej. Przed wejściem do sekcji krytycznej proces wywołuje procedurę enter_region z własnym numerem jako parametrem, pokazując w ten sposób innym procesom, że współdzielony zasób jest zajęty. Po wyjściu z sekcji krytycznej proces wywołuje procedurę leave_region z własnym numerem jako parametrem, pokazując w ten sposób innym procesom, że zasób jest wolny. Załóżmy, że proces 0 wywołuje procedurę enter_region i nadaje zmiennej interested wartość true. Proces wskazuje tym samym, że jest zainteresowany wejściem do sekcji krytycznej. Zmienna turn przyjmuje wartość 0 - identyfikator procesu wchodzącego do sekcji krytycznej. Następnie proces wchodzi w pętlę testującą możliwość wejścia do sekcji krytycznej. Testowanie polega na sprawdzeniu, czy konkurencyjny proces nie jest zainteresowany wejściem do sekcji krytycznej. Jeśli nie, to proces 0 wchodzi do sekcji krytycznej. Wychodząc z niej proces wywołuje procedurę leave_region, która ustawia odpowiadającą procesowi zmienną interested na false.

 

 

3. Synchronizacja procesów i wątków.

3.1 Pojęcie sekcji krytycznej.

 

Sekcja krytyczna (SK) to sekwencja rozkazów, której wykonanie, jeśli zostanie rozpoczęte, musi być doprowadzone do końca zanim inny proces wystąpi z żądaniem dostępu do tego wspólnego zasobu. Jeśli jesteśmy w stanie tak zorganizować wykonywanie wielu procesów, że nigdy jednocześnie nawet dwa nie znajdą się w swoich sekwencjach krytycznych, to jesteśmy w stanie ominąć problem sytuacji hazardowej. Instrukcje sekcji krytycznej muszą być ujęte w jakieś „ogrodzenie” gwarantujące spełnienie warunków wzajemnego wykluczania. Ponieważ w danej chwili z obiektu dzielonego może korzystać tylko jeden proces, wykonując swoją sekcję krytyczną uniemożliwia on wykonanie sekcji krytycznych innym procesom.

Mechanizm realizacji sekcji krytycznej powinien spełniać poniższe założenia: 

ü  wewnątrz SK może przebywać tylko jeden proces,

ü  jakikolwiek proces znajdujący się poza SK, nie może zablokować innego procesu chcącego wejść do SK,

ü  każdy proces oczekujący na wejście do SK powinien otrzymać prawo dostępu w rozsądnym czasie

3.2 Narzędzia umożliwiające synchronizację procesów i wątków.

Semafory.

Semafor jest zmienną całkowitą, która z punktu widzenia programisty przyjmuje wartości nieujemne (.0) lub — w przypadku semaforów binarnych — logiczne. Zmienna semaforowa musi mieć nadaną początkową wartość (oczywiście nieujemną). Po nadaniu początkowej wartości zmiennej semaforowej można na niej wykonywać tylko dwie operacje:

P — opuszczanie semafora (hol. proberen testować)

V — podnoszenie semafora (hol. verhogen zwiększać)

Synchronizacja za pomocą semaforów polega na blokowaniu procesu w operacji opuszczania semafora, gdy wartość zmiennej semaforowej jest 0 (false w przypadku semaforów binarnych) do czasu, aż wartość ta zostanie zwiększona.

Rodzaje semaforów:

ü  semafory binarne — zmienna semaforowa przyjmuje tylko wartości true (stan podniesienia) lub false (stan opuszczenia).

ü  semafory ogólne — zmienna semaforowa przyjmuje wartości całkowite nieujemne, a jej bieżąca wartość jest zmniejszana lub zwiększana o 1 w wyniku wykonania odpowiednio operacji opuszczenia lub podniesienia semafora.

ü  semafory uogólnione — semafory ogólne, w których zmienną semaforową można zwiększać lub zmniejszać o dowolną wartość

ü  semafory dwustronnie ograniczone — zmienna semaforowa ma górne ograniczenia po osiągnięciu którego następuje blokowanie procesu również w operacji podnoszenia.

Wady semaforów:

ü  semafor jest wysokopoziomową abstrakcją opartą na niskopoziomowych

mechanizmach elementarnych, które dostarczają niepodzielność i mechanizmy wstrzymywania

ü  wstrzymywanie i wznawianie wymaga przełączania kontekstu i zmian
w kolejkach modułu szeregowania i kolejkę wątków wstrzymanych; operacje na semaforze są
powolne

Monitory.

Monitory to konstrukcje zdefiniowane przez programistę w języku wysokiego poziomu służące do synchronizacji procesów. Z tej konstrukcji nie mogą bezpośrednio korzystać dowolne procesy. Mają one tylko dostęp do swych zmiennych lokalnych i wartości parametrów formalnych.

ü  nie wykorzystuje się funkcji systemowych;

ü  nie wykorzystuje się żadnych zmiennych;

ü  jest to technika odpowiedniego oprogramowywania procesów;

ü  podstawowa wada: większość języków wysokiego poziomu nie rozpoznaje konstrukcji monitora;

Konstrukcja monitora gwarantuje, że w jego wnętrzu może być aktywny w jednym czasie tylko jeden proces. W związku z tym programista nie musi kodować barier synchronizacyjnych w sposób jawny. Pozostaje jednak problem synchronizacji wielu monitorów. Mechanizm ich synchronizacji dostarcza konstrukcja pod nazwą warunek. Mianowicie programista może zdefiniować jedną lub kilka zmiennych tego typu. Jedynymi operacjami które mogą dotyczyć warunku są: wait(x) i signal(x). Operacja x.wait oznacza, że proces ją wywołujący zostaje zawieszony aż do chwili gdy inny proces wykona operację x.signal. Operacja x.signal wznawia jeden z zawieszonych procesów, a jeśli żaden z procesów nie jest zawieszony, to operacja ta nie ma żadnych skutków.

W implementacji monitorów konieczne jest posłużenie się wstawkami assemblerowymi i instrukcją TSL lub semaforami aby zagwarantować atomowość operacji wait i signal. Procedury te należy dołączyć do monitorów w trakcie ich kompilacji.

 

3.3 Pojęcie zakleszczenia oraz warunki konieczne, aby zjawisko zakleszczenia wystąpiło.

 

Definicja klasyczna zakleszczenia: (zakleszczenie dotyczy zasobów nieprzywłaszczalnych). Zakleszczenie jest konfliktem zasobowym, który może powstać przy rozdziale zasobów nieprzywłaszczalnych i definiowany jest jako stan rozdziału zasobów w systemie, w którym dokończenie wykonywania pewnych procesów jest niemożliwe ze względu na to, że każdy z nich żąda przydziałów zasobów nieprzywłaszczalnych przydzielonych innemu procesowi.

Definicja uniwersalna zakleszczenia: Zbiór procesów znajduje się w stanie zakleszczenia, jeżeli każdy proces z tego zbioru czeka na zdarzenie, które może być spowodowane tylko przez inny proces z tego samego zbioru procesów - zdarzeniami tymi są najczęściej zwalnianie i przydzielanie zasobów.

Martwy punkt może wystąpić wtedy i tylko wtedy gdy w systemie wystąpią jednocześnie 4 następujące warunki.

Warunki Coffmana zaistnienia stanu zakleszczenia:

1.     Wzajemne wykluczanie (mutual exclusion). W danej chwili czasu jednostka zasobu może być przydzielona tylko do jednego procesu.

2.     Przytrzymywanie w stanie zawieszenia (hold and wait). Proces oczekuje na zwolnienie potrzebnych mu jednostek zasobów, które są przydzielone do innych procesów. Podczas tego oczekiwania proces nie zwalnia dotychczas przydzielonych mu jednostek zasobów.

3.     Bez wywłaszczenia (no preemption). Jednostka zasobu przydzielona do danego procesu może być zwolniona tylko przez ten proces. Inaczej mówiąc proces nie może zostać wywłaszczony wbrew swej woli.

4.     Cykliczne oczekiwanie (circular wait). Łańcuch procesów oczekujących wzajemnie na uwolnienie przydzielonych do nich jednostek zasobów musi się zamknąć, tzn. musi istnieć zbiór {P0, P1, ... , Pn} czekających procesów takich, że Po czeka na zasób przydzielony do P1, P1 czeka na zasób przydzielony do P2, itd., Pn-1 czeka na zasób przydzielony do Pn, a Pn czeka na zasób przydzielony do P0.

 

Do opisywania martwego punktu powszechnie stosuje się metodę grafów. Zakleszczenie może być opisane precyzyjnie z wykorzystaniem pojęcia grafu skierowanego nazywanego w tym przypadku grafem alokacji zasobów. Graf G = (V,E) składa się ze zbioru wierzchołków V i zbioru krawędzi E. Zbiór wierzchołków jest podzielony na dwa typy.

1.     P = {P1, P2, ... , Pn} oznacza zbiór wszystkich procesów wykonywanych aktualnie w systemie.

2.     R = {R1, R2, ... , Rm} oznacza zbiór wszystkich typów zasobów występujących w systemie.

Krawędź skierowaną Pi ® Rj będziemy nazywać krawędzią żądań. Oznacza ona, że proces Pi żąda przydziału jednostki zasobu typu Rj. Inaczej mówiąc proces ten aktualnie czeka na przydział tej jednostki. Krawędź skierowaną Ri ® Pj będziemy nazywać krawędzią przydziału. Oznacza ona, że pewna jednostka zasobu typu Ri jest przydzielona aktualnie do procesu Pj. Biorąc pod uwagę definicję grafu oraz teorię grafów można łatwo wykazać, że jeśli graf alokacji zasobów nie zawiera cykli, to wówczas żaden proces w systemie nie znajduje się w stanie zakleszczenia. Z drugiej strony, jeśli graf alokacji zasobów zawiera cykle, to martwy punkt może zaistnieć . Jeśli każdy z typów zasobów zawiera tylko po jednej jednostce danego zasobu, oraz w grafie występują cykle, to oznacza to wystąpienie martwego punktu. Cykl, zgodnie z warunkami Coffmana, jest warunkiem niezbędnym do zaistnienia martwego punktu, natomiast nie jest warunkiem wystarczającym. Jeśli bowiem cykl istnieje, a każdy typ zasobu posiada kilka jednostek, to prawdopodobieństwo wystąpienia martwego punktu gwałtownie spada.

3.4 Projekt laboratoryjny – Problem pięciu filozofów – rozwiązanie za pomocą semaforów i monitora. Analiza przypadku 2, 3 i 4 filozofów.

 

Problem jedzących filozofów jest jednym z najbardziej znanych przykładów nieustającej współbieżności. Mamy stół, wokół którego posadzono pięciu filozofów, których cykl życia składa się z myślenia i jedzenia. Pośrodku stołu stoi duży talerz z nieograniczona ilością spagetti. W połowie odległości pomiędzy dwoma talerzami leży jeden widelec. I tu powstaje problem, ponieważ żaden filozof nie może jeść spagetti jednym widelcem. Gdy zgłodnieje, podnosi widelec, jeśli jest wolny, następnie podnosi drugi. Jeżeli któryś z widelców jest zajęty, filozof czeka. Jedzenie można potraktować, jako rodzaj sekcji krytycznej, gdyż dwóch sąsiadów nie może jeść jednocześnie. W przypadku, kiedy pozwolimy filozofom samowolnie podnosić widelce może się zdarzyć, ze wszystkich pięciu podniesie jeden widelec i będą czekać w nieskończoność. Można zdecydować się na inne rozwiązanie każące filozofowi sprawdzać, czy oba widelce są wolne i dopiero wówczas je podnosić. Może się jednak zdarzyć, że będzie on miął wyjątkowo żarłocznych sąsiadów jedzących na przemian i dojdzie do zagłodzenia. Rozwiązaniem poprawnym jest zatrudnienie lokaja, który będzie pilnował, aby przy stole siedziało tylko czterech filozofów, a pozostały czekał na swoją kolej. Jak któryś z nich skończy, musi opuścić pokój, aby ponownie ustawić się w kolejce. Dowód poprawności rozwiązania opiera się na zasadzie szufladkowej Dirichleta: ponieważ mamy czterech filozofów przy stole, a jest piec widelców, to jeden z nich dostanie dwa widelce. Ponieważ proces jedzenia jest skończony, a potem najedzony filozof musi opuścić stół, jest gwarancja, że czekający w kolejce także zasiądzie do stołu.

 

4. Budowa aplikacji klient – serwer wykorzystującej protokół TCP.

4.1 Architektura systemów rozproszonych, architektura systemów sieciowych – struktura i własności.

Coraz częściej mamy do czynienia z rozdzielaniem obliczeń między wieloma fizycznymi procesorami. Możemy wyróżnić dwa podstawowe schematy budowy takich systemów. Pierwszym z nich jest system wieloprocesorowy, czyli ściśle powiązany, w którym procesory dzielą pamięć i zegar, co powoduje, że komunikacja w nim odbywa się najczęściej poprzez pamięć dzieloną. Drugim z nich jest system rozproszony. Jest to system luźno powiązany, w którym procesory nie dzielą pamięci ani zegara -  każdy procesor posiada własną pamięć lokalną, a komunikowanie między procesorami odbywa się za pomocą różnych sieci komunikacyjnych, takich jak szyny szybkiego przesyłania danych lub linie telefoniczne.   

System rozproszony jest to zbiór luźno powiązanych ze sobą procesorów połączonych za pomocą sieci komunikacyjnej. Dla danego procesora wchodzącego w skład systemu rozproszonego pozostałe procesy i ich zasoby są zdalne, natomiast jego własne zasoby są lokalne. Procesory w systemie rozproszonym mogą różnić się mocą obliczeniową i funkcjami. Mogą znajdować się wśród nich małe mikroprocesory, stacje robocze i wielkie systemy komputerowe ogólnego przeznaczenia. Takie procesory określa się za pomocą kilku różnych nazw, takich jak stanowiska, węzły, komputery, maszyny, komputery sieciowe lub macierzyste. W momencie kiedy zwracamy uwagę na położenie maszyn, wtedy najczęściej używamy terminu stanowisko, gdy odnosimy się do konkretnego systemu w danym miejscu, używamy zaś nazwy komputer (sieciowy). Pewien proces na jakimś stanowisku, który nazywamy serwerem, dysponuje zasobem, którego potrzebuje inny proces na innym stanowisku – klient. Zadanie jakie stawiamy przed systemem rozproszonym jest stworzenie wydajnego i wygodnego środowiska umożliwiającego ten sposób dzielenia zasobów. Rozproszony system operacyjny powinien umożliwić użytkownikom dostęp do różnych zasobów, nad którymi sprawuje nadzór. Poprzez  zasób należy rozumieć zarówno urządzenia sprzętowe, np. drukarki, jak i oprogramowanie – np. pliki, programy, a dostęp do tych zasobów jest nadzorowany przez system operacyjny. Możemy wyróżnić dwa zasadnicze, uzupełniające się schematy dostarczania takich usług:

Sieciowe systemy operacyjne - użytkownicy są świadomi ilości maszyn. W celu dostępu do zasobów są zmuszeni rejestrować się na zdalnych maszynach lub przesyłać dane z odległych maszyn do swoich.

Rozproszone systemy operacyjne - tym systemie użytkownicy nie muszą być świadomi ilości  maszyn, a dostęp do zasobów zdalnych uzyskują oni tak samo jak do zasobów lokalnych.

Możemy wyróżnić cztery główne powody, które przemawiają za budową systemów rozproszonych. Należą do nich: dzielenie zasobów, przyspieszenie obliczeń, niezawodność i komunikacja.  

ü  dzielenie zasobów – jest to mechanizm pozwalający na wspólne korzystanie z plików na zdalnych stanowiskach, przetwarzanie informacji w rozproszonych bazach danych, drukowanie plików na zdalnych stanowiskach, używanie zdalnych wyspecjalizowanych urządzeń oraz wykonywanie innych operacji (dla przykładu użytkownik stanowiska A może korzystać z drukarki dostępnej tylko na stanowisku B, a w tym samym czasie użytkownik stanowiska B może sięgać po plik rezydujący w A).

ü  przyspieszanie obliczeń – jeśli jakieś konkretne obliczenie można podzielić na pewną liczbę obliczeń cząstkowych, które mogłyby być wykonywane współbieżnie, to system rozproszony może umożliwić rozdzielenie obliczeń między różne stanowiska w celu ich współbieżnego wykonywania. Poza tym jeśli jakieś stanowisko jest w danej chwili obciążone zbyt dużą liczbą zadań, to niektóre z tych zadań mogą zostać przesunięte do mniej obciążonych stanowisk. To przemieszenie zadań nazywamy dzieleniem obciążeń.

ü  niezawodność – jeśli system składa się z pewnej liczby dużych, autonomicznych instalacji, wówczas awaria jednego z nich nie ma wpływu na resztę. Jeśli natomiast system składa się z pewnej liczby małych maszyn, z których każda odpowiada za jakąś ważną funkcje systemu, to pojedyncze uszkodzenie może spowodować zatrzymanie całego systemu. Awaria stanowiska powinna zostać wykryta przez system, przy czym należy liczyć się z podjęciem odpowiednich działań zmierzających do usunięcia jej skutków. System powinien wstrzymać korzystanie z usług uszkodzonego stanowiska, a jeśli istnieje taka możliwość to zadanie uszkodzonego stanowiska powinno zostać przejęte przez inne stanowisko.

ü  komunikacja – w przypadku gdy wiele stanowisk jest połączonych ze sobą za pomocą sieci komunikacyjnej, wtedy użytkownicy rożnych stanowisk mają możliwość wymieniania informacji (na niskim poziomie systemy przekazują między sobą komunikaty). Zaletą systemu rozproszonego jest to, że działania mogą być wykonywane na wielkie odległości, dzięki czemu nad jednym projektem może pracować wiele osób, przesyłając sobie pliki projektu, dane, czy też wymieniając pocztę.

4.2 Pojęcie protokołu sieciowego, model warstwowy protokołu sieciowego.

Protokoły sieciowe.

Zapewniają usługi łączy dla systemów komunikacyjnych, obsługują adresowanie
i informację routingu, weryfikację błędów oraz żądania retransmisji. Obejmują również procedury dostępu do sieci określone przez wykorzystywany rodzaj sieci (IP, IPX);

Protokół jest realizowany przez parę modułów programowych zlokalizowaną w komputerach nadawczych i odbiorczych. Na przykład protokół transportu służy do przesyłania dowolnej długości komunikatów od procesu nadawczego do procesu odbiorczego. Proces chcący wysłać wiadomość do innego procesu wywołuje moduł protokołu transportu, przekazując mu komunikat w określonym formacie. Odtąd obowiązek przesłania komunikatu do celu przejmuje na siebie oprogramowanie transportowe, dzieląc ten komunikat na pakiety ustalonego rozmiaru i formatu. zdalne do przesyłania do celu za pomocą protokołu sieciowego czyli innego protokołu niższego poziomu. Odpowiedni protokół transportu w komputerze odbiorczym przyjmuje pakiety i wykonuje działania odwrotne w celu odtworzenia komunikatu przed przekazaniem go do procesu odbiorczego.

Model warstwowy protokołu sieciowego.

Programowanie sieciowe ma posiać hierarchii warstw. Każda warstwa jest interfejsem dla warstw leżących ponad nią. rozszerzającym i uogólniającym pewne właściwości systemu komunikacyjnego będącego jej podłożem. W każdym komputerze przyłączonym do sieci warstwa jest reprezentowana przez moduł oprogramowania. Tak więc każda warstwa dostarcza usług warstwie leżącej ponad nią i rozszerza usługi przez warstwę leżąca, od niej niżej. Na spodzie znajduje się warstwa fizyczna, stanowią ją środki komunikacyjne (kable miedziane lub światłowodowe, łącza satelitarne lub radiowe) oraz odpowiednie układy w każdym komputerze, transmitujące sygnały przez środki komunikacji. Porcje danych są odbierane w miejscu przeznaczenia i przekazywane w górę hierarchii modułów programowych, ulegając na każdym etapie transformacjom aż przyjmą postać zdatną do przekazania docelowemu procesowi odbiorczemu

4.3 Protokół OSI oraz protokół TCP/IP.

 

Protokół OSI.

Ogólnie przyjętym modelem sieci jest model warstwowy. Wymienione wyżej funkcje dzieli się na rozłączne podzbiory i powierza poszczególnym warstwom. Najwyższa warstwa jest odpowiedzialna za konwersje protokółów użytkownika lub funkcje zarządzania urządzeniami, najniższa warstwa za sterowanie fizycznym medium transmisji danych. W modelu warstwowym pełny zbiór funkcji komunikacyjnych zostaje podzielony na podzbiory w taki sposób, by było możliwe traktowanie każdego podzbioru jako pewnej całości wykonującej autonomiczne zadanie. Wyodrębnione podzbiory funkcji są powiązane ze sobą tak, że tworzą strukturę hierarchiczna w postaci uporządkowanych warstw. Każda warstwa składa się z w obiektach rozproszonych w różnych urządzeniach sieci komputerowej. Podstawowa zasada jest to, ze komunikują się ze sobą tylko równorzędne pary obiektów jednej warstwy korzystając jedynie z usług transmisji danych oferowanych przez warstwy niższe. Każda warstwa modelu jest opisana przez protokół wymiany informacji pomiędzy równorzędnymi obiektami warstwy oraz przez zbiór usług komunikacyjnych pełnionych dla warstwy znajdującej się bezpośrednio nad nią.

Warstwy OSI.

WARSTWA FIZYCZNA

WARSTWA ŁĄCZA DANYCH

WARSTWA SIECIOWA

WARSTWA TRANSPORTOWA

WARSTWA SESJI

WARSTWA PREZENTACJI

WARSTWA APLIKACJI

 

Warstwa fizyczna: (physical layer)

Jest odpowiedzialna za transmisję strumienia bitów między węzłami sieci. Definiuje protokoły opisujące interfejsy fizyczne, to jest ich aspekty: mechaniczny, elektryczny, funkcjonalny i proceduralny. Do funkcji tej warstwy należą: sprzęgniecie z medium transmisji danych, dekodowanie sygnałów, określanie zakresu amplitudy prądu lub napięcia i określanie parametrów mechanicznych łączówek (kształtu, wymiarów i liczby styków) oraz inne kwestie związane z transmisją bitów.

Warstwa łącza danych: (data link layer)

Zapewnia niezawodne łącze pomiędzy sąsiednimi węzłami. Nadzoruje przepływ informacji przez łącze i w związku z podatnością warstwy fizycznej na zakłócenia i wynikające stąd błędy oferuje własne mechanizmy kontroli błędów w przesyłanych ramkach lub pakietach (CRC - Cyclic Redundancy Check).

 

 

Warstwa sieciowa: (network layer)

Dostarcza środków do ustanawiania, utrzymania i rozłączania połączeń sieciowych miedzy systemami otwartymi, w których rezydują komunikujące się aplikacje, i odpowiada, za obsługę błędów komunikacji. Ponadto warstwa sieciowa jest odpowiedzialna za funkcje routingu, który wyznacza optymalną pod względem liczby połączeń drogę przesyłania pakietu przez sieć.

Warstwa transportowa: (transport layer)

Zapewnia przezroczysty transfer danych między stacjami sesyjnymi, odciąża je od zajmowania się problemami niezawodnego i efektywnego pod względem kosztów transferu danych. Warstwa ta zapewnia usługi połączeniowe. Wszystkie protokoły w warstwie transportowej są typu “od końca do końca”(end-to-end). Oznacza to, że działają one tylko między końcowymi systemami otwartymi.

Warstwa sesji: (session layer)

Umożliwia aplikacjom organizację dialogu oraz wymianę danych między nimi. Do najważniejszych usług warstwy sesji należą: sterowanie wymianą danych, ustalanie punktów synchronizacji danych (dla celów retransmisji w wypadku przemijających przekłamań na łączach) oraz umożliwienie odzyskania danych (utraconych w wyniku przerwy w łączności) przez ponowne ich przesłanie.

Warstwa prezentacji: (presentation layer)

Zapewnia możliwość reprezentowania informacji, którą się posługują stacje aplikacyjne podczas komunikacji Zapewnia tłumaczenie danych, definiowanie ich formatu oraz odpowiednią składnię.

Warstwa aplikacji: (application layer)

Dostarcza procesom aplikacyjnym metod dostępu do środowiska OSI, pełni rolę okna między współdziałającymi procesami aplikacyjnymi.

 

Protokół TCP/IP.

Architektura protokołów.

Zestaw protokołów został opracowany w celu umożliwienia komunikacji miedzy różnymi typami systemów komputerowych, jak również pomiędzy różnymi sieciami. Agencja DARPA oraz Stanford University rozpoczęły pracę nad protokołem TCP
w 1973 r. Badania prowadzone w ciągu pięciu lat doprowadziły do opracowania dwóch wzajemnie uzupełniających się protokołów. Pierwszy z nich TCP jest protokołem połączeniowym, natomiast drugi protokółem bezpołączeniowy IP (stąd nazwa TCP/IP). Protokoły TCP/IP wykorzystywane są obecnie w systemach UNIX-owych, sieciach lokalnych (LAN) oraz w sieciach rozległych (WAN). Pozwalają również na łączenie oddzielnych sieci fizycznych w jedną logiczną.

Zalety protokołów TCP/IP:

ü  uniwersalność pod względem specyfikacji systemów komputerowych

ü  integracja różnych rodzajów sieci komputerowych

ü  przydzielenie unikatowego adresu każdej maszynie dzięki wspólnemu schematowi adresacji

ü  standardowe protokoły warstw wyższych

Protokół TCP/IP umożliwia realizację wielu usług, oto niektóre z nich:

ü  transfer danych (IP, TCP, UDP)

ü  kontrola poprawności połączeń (ICMP)

ü  zarządzanie siecią (SNMP)

ü  zdalne łączenie (TELNET, SSH)

ü  przesyłanie plików (FTP)

Architektura protokołu TCP/IP składa się z czterech warstw ułożonych hierarchicznie

 

WARSTWA APLIKACJI

WARSTWA TRANSPORTOWA

WARSTWA INTERNET

WARSTWA DOSTĘPU DO SIECI

 

Dane generowane przez programy aplikacyjne są przekazywane w dół stosu, jeśli maja być przesyłane w sieć i w górę stosu w przypadku odbioru. Każda warstwa stosu dodaje do danych przekazywanych z warstwy wyższej informacje sterujące w postaci nagłówków (headers). Nagłówek dodany w warstwie wyższej jest traktowany jako dane w warstwie niższej. Warstwy protokołów TCP/IP używają różnych nazw do określenia przekazywanych danych. Aplikacje stosujące w warstwie transportowej protokół TCP nazywają swoje dane strumieniem. Protokół TCP nazywa swoje dane segmentem. Aplikacje wykorzystujące w warstwie transportowej protokół UDP określają swoje dane jako wiadomości, a dane protokołu UDP to pakiety. W warstwie Internet protokół IP traktuje swoje dane jako bloki zwane inaczej datagramami. W najniższej warstwie bloki danych to ramki lub pakiety w zależności od używanego protokołu.

Warstwa dostępu do sieci.

Najniższą warstwą w hierarchii architektury TCP/IP jest warstwa dostępu do sieci. W warstwie tej do datagramów IP dodaje się nagłówki oraz zakończenie i w ten sposób otrzymuje się ramki przesyłane w sieci. Funkcje tej warstwy odpowiadają w przybliżeniu funkcjom trzech najniższych warstw modelu ISO/OSI. Do komunikacji w sieciach rozległych lub przez łącza szeregowe mogą byś stosowane takie protokoły jak X25, PPP lub SLIP. Te dwa ostatnie protokoły zostały opracowane specjalnie do przesyłania datagramów pomiędzy dwoma punktami łączem szeregowym. W sieciach rozległych stosuje się protokołu PPP, natomiast protokół SLIP używa się do prostego połączenia dwóch komputerów łączem szeregowym.

Warstwa Internet.

Zasadniczym protokołem w tej warstwie jest protokół IP. Odpowiedzialny jest on za przesyłanie pakietów zwanych datagramami, pomiędzy użytkownikami sieci. Jest to protokół bezpołączeniowy, co oznacza, że datagramy są przesyłane przez się bez kontroli poprawności i dostarczenia. W tym przypadku może dojść do sytuacji, kiedy
datagram może ulec przekłamaniu lub zostanie zagubiony w sieci. Dlatego protokół IP przeznaczony jest do używania w sieciach bardzo dobrej jakości i niezawodnych łączach transmisyjnych. Drugim protokołem tej warstwy jest ICMP, związany ściśle
z IP. Zadaniem jego jest informowanie o nieprawidłowościach w pracy sieci. Pozwala na przesyłanie komunikatów sterujących między węzłami sieci, które umożliwiają sterowanie przepływem, testowanie urządzeń, wskazywanie alternatywnych połączeń także wykrywanie niedostępnych użytkowników.

 

Warstwa transportowa.

Zapewnia bezpośrednie połączenie między końcowymi użytkownikami (systemami) wymieniającymi informacje. Do najważniejszych protokołów w tej warstwie zalicza się protokół TCP oraz UDP. Protokół TCP jest typu połączeniowego, umożliwia wykrywanie błędów na obu końcach połączenia. Ma on możliwość ustanowienia i utrzymania połączenia wirtualnego między dwoma użytkownikami w celu przesyłania danych, sterowania przepływem, przesyłania potwierdzeń oraz kontroli i korekcji błędów (CRC). Protokół UDP jest protokołem bezpołączeniowym, nie posiada mechanizmów korekcyjnych. Segmenty TCP oraz pakiety UDP w celu dalszego przesłania umieszczane są wewnątrz datagramu IP.

Warstwa aplikacji.

Warstwa ta zawiera procesy wykorzystujące protokoły TCP lub UDP. Protokoły tej warstwy dostarczają użytkownikom różnych usług. Do najbardziej znanych i rozpowszechnionych aplikacji korzystających z TCP należą:

ü  TELNET, SSH – dla usług terminalowych, pozwalają na rozpoczęcie sesji poprzez sieć

ü  TFTP – dla prostych usług transferu plików (uproszczona wersja FTP)

ü  FTP – umożliwia interakcyjne przesyłanie plików

ü  SMTP – poczta elektroniczna, działa na zasadzie „zapamiętaj i prześlij” między systemami poczty korzystającymi z serwerów pocztowych

Do bardziej znanych usług protokołu UDP należą:

ü  DNS – serwery przechowujące dane o domenach i przypadających im adresach sieciowych

ü  RIP – służy do wymiany informacji związanych z aktualizacją reguły doboru tras w węzłach sieci

ü  NFS – umożliwia współdzielenie plików przez wiele komputerów dołączonych do sieci, jest to rozproszony system plików działających według modelu „klient – serwer”

Protokoły TCP/IP wyróżniają dwa typy urządzeń sieciowych: routery (lub gatewaye) oraz hosty (komputery). Routery służą do przesyłania pakietów między sieciami a na hostach instalowane jest oprogramowanie aplikacyjne dla użytkowników

4.4 Komunikacja strumieniowa oraz komunikacja datagramowa – własności.

Możliwe są dwa rodzaje usług transportu danych:

ü  połączeniowe, w których między procesem nadawczym a odbiorczym tworzy się „połączenie wirtualne" i używa się go do przesyłania strumienia (ang. Stream) danych;

ü  bezpołączeniowe w którym do określonych miejsc przeznaczenia przesyła się indywidualne komunikaty- nazywane datagramami (ang. Datagrames)

Komunikacja datagramowa

Datagramy przesyłane za pomocą usług bezpołączeniowych są podobne do pakietów. Są one adresowane do procesów, natomiast pakiety przesyłane przez warstwę sieci są adresowane tylko do komputerów macierzystych. Usługi bezpołączeniowe mogą być zawodne, toteż wykrywanie strat lub złego porządku datagramów oraz podejmowanie działań naprawczych należy do oprogramowania warstwy zastosowań.

Komunikacja strumieniowa

Komunikacja w trybie połączeniowym jest przydatna do wdrażania usług wymagających przesyłania strumieni danych o nieograniczonej wielkości, takich jak zdalne sesje konwersacyjne lub transmisje wielkich plików. Usługi bezpołączeniowe są prostsze i wymagają mniej zachodu. Stosuje się je często do realizacji komunikacji klient-serwer w systemach rozproszonych zbudowanych z sieci lokalnych, ponieważ ustanowienie połączenia jest dość pracochłonne,

u konwersacja między klientem a serwerem może się sprowadzać do wymiany zaledwie pary komunikatów.

 

4.5 Pojęcie portu, pojęcie pary gniazdowej.

 

Każda aplikacja korzystająca z protokołów TCP/IP jest identyfikowana za pomocą numeru portu. Z kolei protokoły transportowe są określone za pomocą numerów protokołów. Pozwala to łączyć dane generowane przez różne aplikacje z kilkoma protokołami transportowymi i z kolei te protokoły z protokołem IP. Takie podejście daje możliwość multipleksacji danych, czyli np. umożliwia równoczesną komunikację wielu aplikacji z TCP. W Internecie niektóre numery portów są zarezerwowane i wstępnie przypisane do tzw. dobrze znanych usług (przyjmują numery 0 – 255). Zaliczyć można do nich takie protokoły sieciowe jak FTP, TELNET, SSH, HTTP, STMP.

Gniazdo to kombinacja adresu IP i numeru portu. W związki z tym gniazdo jednoznacznie określa proces w Internecie. Gniazdo to również zakończenie logicznego łącza komunikacyjnego pomiędzy dwoma aplikacjami. Jeśli aplikacje realizowane są na dwóch komputerach, to para odpowiadających im gniazd definiuje połączenie w protokole połączeniowym TCP.

4.6 Mechanizm ustanowienia połączenia – uzgadnianie trójfazowe.

ü  ustanawianie połączenia TCP przebiega według poniższego scenariusza.

ü  serwer musi być przygotowany na przyjęcie nadchodzącego połączenia. W tym celu zazwyczaj wywołuje funkcje: socket, bind i listen Nazywa się to otwarciem biernym (ang- passive open) połączenia.

ü  klient rozpoczyna otwarcie aktywne (ang. active open) połączenia, wywołując funkcję connect. To powoduje, że oprogramowanie TCP klienta wysyła segment danych SYN (nazwa tego segmentu pochodzi od słowa ang- synchronize), zawierający początkowy numer kolejny danych, które ten klient będzie przesyłać przez to połączenie. Zazwyczaj w tym segmencie SYN nie przesyła się danych; zawiera on tylko nagłówek IP, nagłówek TCP i ewentualne opcje TCP

ü  serwer musi potwierdzić przyjęcie segmentu SYN od klienta i wysłać własny segment SYN, zawierający początkowy numer kolejnych danych, które serwer będzie wysyłać przez to połączenie. Serwer wysyła w jednym segmencie SYN również potwierdzenie ACK (ang. acknowledgrnent).

ü  klient musi potwierdzić przyjęcie segmentu SYN od serwera.

4.7 Mechanizm zakończenia połączenia.

Podczas gdy do ustanowienia połączenia potrzeba trzech segmentów, to czterech segmentów używa się do jego zakończenia.

 

ü  jeden program użytkowy najpierw wywołuje funkcję close; mówimy wówczas, że ten punkt końcowy połączenia wykonuje zamknięcie aktywne (ang. active close).

ü  oprogramowanie TCP po tej stronie połączenia wysyła segment danych FIN (ang. finish), oznaczający zakończenie wysyłania danych.

 

ü  drugi punkt końcowy połączenia, który odbiera segment FIN, wykonuje zamknięcie bierne (ang. passive close). Oprogramowanie TCP potwierdza przyjęcie segmentu FIN. Informacja o otrzymaniu segmentu FIN jest również przesyłana do programu użytkowego jako znacznik końca pliku (po wszystkich danych, które mogą już oczekiwać w kolejce na pobranie przez program użytkowy), ponieważ odebranie segmentu FIN oznacza, że ten program użytkowy już nie otrzyma żadnych dodatkowych danych poprzez to połączenie.

 

ü  po pewnym czasie ten drugi program użytkowy, który odebrał znacznik końca pliku, wywołuje funkcję close, aby zamknąć swoje gniazdo. To powoduje/ że jego warstwa TCP wysyła segment FIN.

 

ü  oprogramowanie TCP w tym systemie, który odebrał ten ostatni segment FIN (w tym punkcie końcowym połączenia, który wykonuje zamknięcie aktywne), potwierdza przyjęcie segmentu FIN.

 

4.8 Architektura programu klienta i serwera funkcjonujących w oparciu o protokół TCP.

 

4.9 Budowa serwera iteracyjnego.

 

4.10 Budowa serwera współbieżnego opartego na:

ü  Procesach

ü  Watkach

 

4.11 Funkcje w języku C: socket, connect, accept, listen, bind, close, read, write.

socket - Funkcja socket tworzy internetowe gniazdo strumieniowe (SOCK_STREAM), czyli gniazdo obsługiwane przez warstwę TCP. Funkcja ta przekazuje małą liczbę całkowita, która służy jako deskryptor identyfikujący to gniazdo we wszystkich następnych wywołaniach funkcji systemowych (np. funkcji connect oraz read).

Connect - Stosując funkcję connect do gniazda TCP, powodujemy ustanowienie połączeniaTCP z serwerem określonym przez gniazdową strukturę adresową, wskazywaną poprzez drugi argument wywołanej funkcji. Musimy również jako trzeci argument tej funkcji określić rozmiar gniazdowej struktury adresowej; pozwalamy zawsze kompilatorowi obliczyć rozmiar struktury dla adresów gniazd internetowych, używając w tym celu operatora sizeof w języku C.

accept - Zazwyczaj funkcja accept powoduje, że proces serwera popada w stan uśpienia

w oczekiwaniu na nadejście i zaakceptowanie połączenia z klientem. W celu ustanowienia połączenia obsługiwanego zgodnie z protokołem TCP stosuje się tzw. uzgodnienie trójfazowe po czym następuje powrót z funkcji accept.

Wartością przekazywaną przez tę funkcję jest nowy deskryptor, cockfd, zwany deskryptorem gniazda połączonego ,który służy do komunikowania się z nowym klientem, Funkcja accept przekazuje nowy deskryptor odpowiadający każdemu klientowi, który łączy się z naszym serwerem.

listen - Wywołując funkcję listen, przekształcamy gniazdo w gniazdo nasłuchujące,

w którym przychodzące od klientów połączenia będą akceptowane przez jądro systemu.

 

bind - funkcja nadaje nazwę gniazdka, gdyż aby inny proces mógł zaadresować gniazdko musi ono mieć nazwę.

write - funkcje do czytania i przesyłania.

close - zakończenie połączenia. Serwer zamyka połączenie z klientem, wywołując funkcję close. Rozpoczyna to zwykłą sekwencję kończąca połączenie zgodnie z protokołem TCP: w każdym kierunku jest wysyłany segment FIN, a przyjęcie każdego segmentu FIN jest potwierdzane na drugim końcu połączenia.

read – funkcja służy do pobierania danych z gniazda TCP. Musimy zawsze wywołanie funkcji read umieścić w pętli., której wykonywanie zakończy się wtedy, kiedy funkcja read przekaże albo 0 (oznaczające zakończenie połączenia), albo liczbę ujemna (wskazującą na wystąpienie błędu).

4.12 Projekt laboratoryjny – Aplikacja klient – serwer w języku C.

 

 

 

 

 

Bibliografia:

 

1. Zbigniew Weiss , Tadeusz Gruźlewski - „Programowanie Współbieżne i Rozproszone” Wydawnictwo Naukowo – Techniczne – 1.1, 1,2, 3

2. http://www.astagor.net/putinf/data/SysOper/ - 1.4, 4

3. http://www.algorytm.cad.pl/Algorithms/51-60/algorithm55.html - 2.4

4. http://www.kik.pcz.czest.pl/so/mainpage/subject20/index20.htm - 1.3, 4.1

5.     www.ia.pw.edu.pl/~tkruk/edu/sop2a/w5.doc – 2.1, 2.2, 2.3

6.     Jędrzej Ulasiewicz - „Programownie aplikacji współbieżnych”

7.     Janina Mincer – „Systemy operacyjne”