Implementacja, komunikaty w linux.
Implementacja ma na celu przeprowadzenie wdrożenia i integracji systemu z procesami zachodzącymi w przedsiębiorstwie, aby zminimalizować ewentualne zakłócenia w funkcjonowaniu firmy.
A także jest procesem pisania programu (kodu źródłowego), czyli programowanie lub efekt takiego procesu, czyli program.
1.1 IMPLEMENTACJA BIBLIOTEK WĄTKÓW
Sposób implementacji biblioteki zależy od sposobu wspierania wielowątkowości na poziomie jądra. Wiele pakietów zaimplementowano, korzystając z tradycyjnego jądra, które w ogóle niewspiera wątków. W takich sytuacjach biblioteka wątków działa jako miniaturowe jądro, utrzymujące informacje związane z wątkami i obsługujące operacje na wątkach na poziomie użytkownika. Chociaż takie rozwiązanie prowadzi tak naprawdę do sekwencyjnego wykonania wątków, pewien poziom współbieżności jest osiągany dzięki zastosowaniu asynchronicznych operacji wejścia –wyjścia.
W wielu nowoczesnych systemach jądro wspiera wielowątkowość, udostępniając procesy lekkie. Bibliotekę wątków można wówczas implementować na wiele sposobów.
• Związać każdy wątek w odrębnym procesie lekkim. Takie rozwiązanie jest łatwiejsze do zaimplementowania, ale zużywa więcej zasobów jądra, a niewiele daje w zamian. Wymaga zaangażowania jądra we wszystkie operacje synchronizacji i szeregowania wątków.
• Przeplatać wykonanie wątków w małej liczbie procesów lekkich. Jest to efektywniejsze, gdyż zużywa mniej zasobów jądra. Metoda ta działa dobrze, jeśli wszystkie wątki w procesie są w przybliżeniu równoważne. Nie gwarantuje jednak dostępności zasobów dla konkretnego wątku.
• Tworzyć w ramach tego samego procesu wątki związane i niezwiązane. Umożliwia to aplikacjom pełne wykorzystywanie współbieżności i równoległości w systemie. Pozwala także na preferencyjną obsługę wątku związanego przez zwiększenie priorytetu szeregowania procesu lekkiego, w obrębie, którego wykonuje się wątek, lub przez zapewnienie mu wyłącznego dostępu do procesora.
Biblioteka wątków implementuje algorytm szeregowania decydujący o tym, który wątek użytkownika wybrać do wykonania. Utrzymuje ona informacje o stanie i priorytecie każdego wątku. Stan i priorytet wątku niema jednak żadnego związku ze stanem i priorytetem procesu lekkiego, w obrębie którego wykonuje się wątek. Rozważmy przykład z rys. poniżej:
Przedstawia on 6 wątków użytkownika przeplatanych przeplatanych dwóch procesach lekkich. Biblioteka wybiera do wykonania jeden wątek w każdym procesie lekkim. Te wątki(u5, u6) są w sanie wykonywany, chociaż proces lekki, który je zawiera, może oczekiwac wewnątrz funkcji systemowej lub być wywłaszczony i oczekiwać na uszeregowanie.
Wątek (u1 lub u2) zmienia stan na wstrzymany, gdy próbuje uzyskać dostęp do obiektu, do którego dostęp zablokował inny wątek. Po zniesieniu blokady biblioteka wznawia wątek i mieszcza go w kolejce bibliotecznego podprogramu szeregującego. Wątek (u3 i u4) jest w stanie gotowy do wykonania i czeka na uszeregowanie do wykonania. Podprogram szeregujący wątki wybiera do wykonania wątki z kolejki na podstawie ich priorytetu i przynależności do konkretnego procesu lekkiego. Algorytmy oczekiwania na zasoby oraz algorytmy szeregujące z poziomu jądra i poziomu użytkownika są od siebie niezależne. Jak wspomniano poprzednio, biblioteka wątkowa dziła jak miniaturowe jądro dla każdego obsługiwanego wątku.
1.2. IMPLEMENTACJA MODUŁU SZEREGOWANIA
Moduł szeregowania dysponuje tablicą qs zawierającą 32 kolejki procesów gotowych (rys. 5.2) każda kolejka odpowiada czterem kolejnym priorytetom. Zatem kolejka zerowa jest stosowana dla priorytetów 0-3, kolejka pierwsza dla priorytetów 4-7 itd. Każda kolejka zawiera nagłówek dwukierunkowej listy struktur proc. Zmienna globalna whichqs Zawiera maskę bitową z jednym bitem dla każdej kolejki. Bit ten jest ustawiony, jeśli kolejka jest pusta. W kolejkach modułu szeregującego umieszcza się tylko procesy gotowe do wykonania.
Taka architektura upraszcza zadanie wyboru procesu do wykonania. Podprogram swych(), wykonujący przełączenie kontekstu, sprawdza whichgs w poszukiwaniu pozycji pierwszego ustawionego bitu. Pozycja ta identyfikuje kolejkę szeregowania zawierającą gotowy do wykonania proces o najwyższym w danej chwili priorytecie. Podprogram swtch() usuwa ten proces z początku kolejki i przełącza do niego kontekst. Po powrocie z wykonania programu swtch()nowo wybrany proces wznawia działanie.
Przełączenie kontekstu wymaga zachowania kontekstu rejestrów procesu bieżącego. W jego bloku sterującym PCB, który jest częścią u-obszaru, obszaru następnie wypełnienia rejestrów sprzętowych zachowanym uprzednio kontekstem nowego procesu. Pole p_addr struktury proc wskazuje na pozycje w tablicy stron odpowiadające u-obszarowi. Tę informacje wykorzystuje podprogram swych() do znalezienia nowego PCB.
2.1 KOMUNIKATY I KOLEJKI
Jedyną formą komunikacji w strumieniu są komunikaty. U umożliwiają one przesyłanie danych miedzy aplikacjami a urządzeniem. Przenoszą także informacje sterujące do podprogramu obsługi lub do modułu. Podprogramy obsługi i moduły za pomocą komunikatów informują użytkowników jub siebie nawzajem błędach lub niespodziewanych zdarzeniach. Kolejka może obsłużyć nadchodzący komunikat na wiele sposobów:
- może przekazać go do następnej kolejki, bez zmian lub po wstępnym przetworzeniu.
- może przeznaczyć komunikat do opóźnionej obsługi.
- może też przekazać go do kolejki siostrzanej, odsyłając go tym samym powrotem.
- kolejka mże nawet wyrzucić komunikat.
2.2 KOMUNIKATY
Najprostszy komunikat składa się z trzech obiektów: struct msb (lub typu mblk_t), struct data (typu dblk_t) i bufora danych. Komunikat wieloczęściowy konstruuje się przez połączenie takich trujek(rys.). Pola b_next i b_prev struktury msgb służą do przechowywania komunikatu w kolejce, a b_cont do łączenia różnych części tego samego komunikatu w listę. Pole b_datap wskazuje na związaną strukturę data.
Obie struktury msgb i datab przechowują informacje o właściwym buforze danych. Pola db_base i db_lim struktury datab wskazują na początek i koniec bufora. Może się zdarzyć, że tylko część bufora zawiera tylko przydatne dane, więc pola b_rptr i b_wptr struktury msgb wskazują na początek i koniec aktywnego obszaru danych w buforze. Podprogram sllocb() przydziela bufor i inicjuje wskaźniki b_rptr i b_wptr tak, aby wskazywały na początek bufora (db_base). Gdy moduł zapisuje dane do bufora, przesuwa wskaźnik b_wptr, usuwając w ten sposób dane z bufora.
2.3 TYPY KOMUNIKATÓW
Podsystem strumieni definiuje pewien zestaw typów komunikatów. Każdy komunikat musi mieć jeden z tych typów. Pole db_type w strukturze datab określa typ komunikatu, który ma związek z jego przeznaczeniem i priorytetem kolejkowania. Na podstawie typu komunikaty można podzelic na normalne i z wysokim priorytetem.
Komunikaty z wysokim priorytetem są kolejkowane i przetwarzane przed komunikatami normalnymi.
Zdefiniowano następujące komunikat:
M_BREAK wysyłany w dół strumienia; prosi podprogram o wysłanie polecenia break do urządzenia;
M_CTL międzymodułowe zlecenie sterujące;
M_DATA zwykłe dane przesłane lub odebrane za pomocą funkcji systemowych;
M_DELAY zlecenie opóźnienia wyjścia;
M_IOCTL komunikat sterujący; generowany przez polecenia funkcji systemowej ioctl, dotyczące strumienia;
M_PASSFP przekazuje wskaźnik pliku;
M_PROTO komunikat sterujący protokołu;
M_RSE zarezerwowany;
M_SETOPTS wysyłany w górę strumienia przez moduły lub podprogram obsługi, żeby ustawić opcje w nagłówku strumienia;
M_SIG wysyłany w górę strumienia przez moduły lub podprogram obsługi; prosi nagłówek strumienia o wysłanie sygnału do użytkownika.
Typy komunikatów z wysokim priorytetem:
M_COPYIN wysyłany w górę strumienia; prosi nagłówek strumienia o skopiowanie do komunikatu danych dla funkcji systemowej ioctl;
M_COPYOUT wysyłany w górę strumienia; prosi nagłówek strumienia o skopiowanie z komunikatu danych dla funkcji systemowej ioctl;
M_ERROR wysyłany w górę strumienia; zawiadamia o błędzie;
M_FLUSH prosi moduł o opóźnienie kolejki;
M_HANGUP wysyłany w górę strumienia; ustawia informacje o zerwanym połączeniu w nagłówku strumienia;
M_IOCACK potwierdzenie wykonania funkcji systemowej ioctl; wysyłany w górę strumienia;
M_IOCNACK niemożność wykonania funkcji systemowej ioctl; wysyłany w górę strumienia;
M_IOCDATA wysyła dane ioctl w dół strumienia;
M_PCPROTO wysokopriorytetowa wersja M_PROTO;
M_PCSIG wysokoprioryetowa wersja M_SIG;
M_PSRSE zarezerwowane;
M_READ zawiadomienie o odczycie; wysyłane w duł strumienia;
M_START wznowienie zatrzymanego wyjścia do urządzenia;
M_STARTI wznowienie zatrzymanego wyjścia z urządzenia;
M_STOP wstrzymanie wyjścia;
M_STOP wstrzymanie wejścia;
Typy komunikatów pozwalają modułom na rozpoznanie konieczności specjalnej obsługi komunikatu bez konieczności zrozumienia jego zawartości. W raze komunikatów wieloczęściowych pierwsza struktura datab zawiera typ całego komunikatu. Jest jeden wyjątek od tej reguły. Jeśli aplikacja wykorzystuje wysokopoziomowy interfejs usługowy(np. TPI), to jego komunikaty z danymi składają się z pojedynczego bloku M_PROTO, w którym następuje jeden lub kilka bloków M_DATA w obrębie tego samego komunikatu.
2.4 PRZEKAZYWANIE KOMUNIKATÓW:
Przekazanie pojedynczego komunikatu wymaga wykonania kilku czynności.
- Nadawca tworzy komunikat w swojej przestrzeni adresowej.
- Nadawca wywołuje funkcję systemową msg_send, Żeby wysłać komunikat. Nagłówek komunikatu zawiera port docelowy.
- Jądro kopiuje komunikat do wewnętrznej struktury danych (kern_msg_t) za pomocą podprogramu msg_copyin(). W wyniku tego prawa dostępu do portu są przekształcone na wskaźniki do obiektów reprezentujących port w jądrze, a dane pośrednie są kopiowane do tymczasowej mapy adresów.
- Jeśli jakiś wątek oczekuje na odbiór komunikatu (wątek znajduje się w kolejce wstrzymanych odbiorców w tym porcie), to jest budzony, a komunikat jest przekazywany bezpośrednio do niego.
• W przeciwnym razie jeśli kolejka portu jest pełna, to nadawca jest wstrzymywany aż do usunięcia jakiegoś komunikatu z kolejki.
• W przeciwnym razie komunikat jest umieszczony w kolejce portu, w której pozostanie do momentu wykonania przez jakiś wątek w zadaniu odbiorcy funkcji msg_rcv.
- Jądro kończy wykonanie funkcji msg_send po umieszczenu komunikatu w kolejce lub przekazaniu go odbiorcy.
- Gdy odbiorca wykonuje funkcję msg_rcv, jądro wywołuje msg_degueue(), aby usunąć komunikat z kolejki. Jeśli kolejka jest pusta, to odbiorca jest wstrzymywany do przybycia jakiegoś komunikatu.
- Jądro kopiuje komunikat do przestrzeni sdresowej odbiorcy za pomocą funkcji msg_cpyout(), która dokonuje dalszej translacji praw dostępu do portu i danych pośrednich.
- Często nadawca spodziewa się odpowiedzi. Aby mogło to nastąpić, odbiorca musi mieć prawo wysyłania do portu, którego właścicielem jest nadawca.
Nadawca przesyła zatem odbiorcy te prawa, korzystając z pola port odpowiedzi w nagłówku komunikatu.
Zazwyczaj stosuje wówczas funkcje msg_rpc do optymalizacji wymiany komunikatów. Funkcja ta jest znaczeniowo równoważna wywołaniu funkcji msg_send, a następnie funkcji msg_rcv.
Na rys. przedstawiono przekształcenia dokonywane na różnych częściach komunikatu w czasie jego przesyłania.
2.5 PRZEKAZYWANIE PRAW DO PORTU
jest kilka przyczyn przekazywania praw do portów w komunikatach. Najczęstsza dotyczy portu odpowiedzi (jak na rys.). Wątek w zadaniu Z1 wysyła komunikat do portu P2, którego właścicielem jest zadanie Z2. Zadanie Z1 przekazuje w komunikacie prawa wysyłania do portu P1, do którego zadanie Z1 ma prawa odbioru. W rezultacie zadanie Z2 może wysłać komunikat z odpowiedzią do portu P1, a wątek nadawcy będzie na niego oczekiwać. Taka sytuacja jest na tyle powszechna, że nagłówek komunikatu zawiera pole do przechowywania praw do portu odpowiedzi.
Inną częstą przyczyną przekazywania praw do portu jest współdziałanie programu serwera, klienta i serwera nazw.Serwer nazw jest właścicielem praw wysyłania do serwerów w systemie. Zazwyczaj programy serwera rejestrują się w serwerze nazw przed rozpoczęciem wykonania – krok(a). Wszystkie zadania w chwili tworzenia dziedziczą prawa wysyłania do serwera nazw.