//Pytanie: "Linux - mechanizmy komunikacji międzyprocesowej IPC (Inter Process Communication)"//


{{:so:ipc.pdf|:so:ipc.pdf}}


====== Komunikacja międzyprocesowa ======

Środowisko systemu UNIX umożliwia procesom różnorodne sposoby wzajemnej
łączności. Komunikacja może być po prostu kwestią powiadomienia drugiego procesu
o wystąpieniu jakiegoś zdarzenia lub może obejmować przesyłanie danych od
jednego procesu do innego.

===== Synchronizacja i sygnały =====

Standardowym mechanizmem systemu UNIX służącym do powiadamiania procesu o
wystąpieniu zdarzenia jest __sygnał__. Sygnały mogą być przesyłane między dowolnymi
procesami (z ograniczeniami dotyczącymi sygnałów wysyłanych do procesów
należących do innego użytkownika), jednak liczba dostępnych sygnałów jest
skończona i nie mogą one przenosić informacji - proces staje wyłącznie wobec
faktu, że sygnał wystąpił. Sygnały nie muszą być generowane przez inne procesy.
Jądro w swoim wnętrzu również wytwarza sygnały.  Może ono na przykład wysłać
sygnał do procesu usługowego, gdy w kanale sieciowym pojawią się dane, bądź do
procesu macierzystego, gdy proces potomny zakończy działanie lub w przypadku
wyczerpania czasu odliczanego przez czasomierz.  

==== Planowanie stanów ====
Jądro systemu Linux nie korzysta wewnętrznie z sygnałów w celu komunikowania
się z procesami wykonywanymi w trybie jądra. Jeśli proces działający w trybie
jądra oczekuje na wystąpienie zdarzenia, to zazwyczaj nie posłuży się sygnałami
w celu zorientowania się o tym zdarzeniu. Zamiast tego komunikacja w jądrze
związana z pojawiającymi się asynchronicznie zdarzeniami będzie się odbywać za
pomocą **planowania stanów** i **struktur //wait_queue//**. __Mechanizmy te umożliwiają
procesom wykonywanym w trybie jądra na wzajemne informowanie się o stosownych
zdarzeniach, jak również pozwalają na generowanie zdarzeń przez moduły
sterujące urządzeń lub przez system współpracy z siecią__. 

Kiedy proces zechce poczekać na wystąpienie jakiegoś zdarzenia, włącza się do kolejki oczekujących
(wait_queue), skojarzonej z tym zdarzeniem, i informuje planistę, że odtąd nie
nadaje się do wykonania. Wystąpienie zdarzenia powoduje obudzenie wszystkich
procesów w kolejce wait_queue. Procedura taka pozwala wielu procesom oczekiwać
na jedno zdarzenie. Na przykład, jeżeli kilka procesów próbuje czytać plik z
dysku, to wszystkie one zostaną obudzone po pomyślnym wczytaniu danych do
pamięci.  

==== Semafory ====
Chociaż sygnały zawsze były głównym mechanizmem komunikowania asynchronicznych
zdarzeń między procesami, Linux ma także zaimplementowany mechanizm semafora z
systemu UNIX wydania V. Proces może czekać pod semaforem równie łatwo, jak to
czyni w związku z sygnałem, ale semafory mają tę zaletę, że można je dzielić w
dużych ilościach między wiele niezależnych procesów, a działania na licznych
semaforach mogą być wykonywane w sposób niepodzielny. Do synchronizowania
procesów komunikują­cych się za pomocą semaforów system Linux stosuje
wewnętrznie swój standardowy mechanizm kolejki wait_queue.  

===== Przekazywanie danych między procesami =====

==== Potoki ====
Linux oferuje kilka
mechanizmów przekazywania danych między procesami. Standardowy, uniksowy
mechanizm potoku (pipe) umożliwia procesowi potomnemu dziedziczenie kanału
komunikacyjnego od swojego przodka. Dane zapisane na jednym końcu potoku mogą
być czytane na drugim. Potoki w systemie Linux wyglądają jak pewien typ i-węzła z
oprogramowania wirtualnego systemu plików, a każdy potok ma dwie kolejki
wait_queue do synchronizowania czytelnika i pisarza. System UNIX zawiera także
definicje zestawu udogodnień sieciowych, których można używać do przesyłania
strumieni danych zarówno do lokalnych, jak i do odległych procesów.

==== Pamięć dzielona ====
Zastosowanie pamięci dzielonej - jest najszybszym środkiem przekazywania
wielkich lub małych ilości danych. Wszelkie dane zapisane przez proces w
obszarze pamięci dzielonej mogą być natychmiast czytane przez inny proces,
który ma ten obszar odwzorowany w swojej przestrzeni adresowej. Główna wada
pamięci dzielonej polega na tym, że sama w sobie nie daje żadnej synchronizacji.
Proces nie może spytać systemu operacyjnego, czy fragment pamięci dzielonej
został zapisany, ani nie może zawiesić swego działania do czasu wystąpienia
takiego zapisu. Pamięć dzielona nabiera szczególnej użyteczności w połączeniu z
innym mechanizmem komunikacji międzyprocesowej, który zapewni brakującą
synchronizację.  

Obszar pamięci dzielonej w systemie Linux jest obiektem trwałym, który może być
tworzony i usuwany przez procesy. Obiekt taki jest traktowany tak, jakby to była
mała, niezależna przestrzeń adresowa. Algorytmy stronicowania systemu Linux mogą
typować strony pamięci dzielonej do usuwania na dysk, zupełnie tak jak to robią
ze stronami danych procesu. Obiekt pamięci dzielonej zachowuje się jak pamięć
pomocnicza dla obszarów pamięci dzielonej, na podobieństwo pliku pełniącego
funkcję pamięci pomocniczej dla obszarów pamięci odwzorowanych w pamięci
operacyjnej. Gdy następuje odwzorowanie pliku w obszarze wirtualnej przestrzeni
adresowej, wówczas wszelkie pojawiające się braki stron powodują odwzorowanie w
pamięci wirtualnej odpowiednich stron pliku. Analogicznie, braki bezpośrednich
odwzorowań stron pamięci dzielonej powodują odwzorowanie stron z trwałego
obiektu pamięci dzielonej. Podobnie jak w przypadku plików, obiekty pamięci
dzielonej utrzymują swoją zawartość nawet wtedy, gdy aktualnie żaden proces nie
odwzorowuje ich w pamięci wirtualnej. 

//Dla tych dla których powyższy akapit wydaje się być zbyt zakręconym, to w dużym i nie ścisłym skrócie:

 
Chodzi o to że mamy  ''obiekt pamięci dzielonej'' skojarzony z fizycznym obszarem pamięci, podlegający stronnicowaniu tak jak każdy inny fragment pamięci (oraz przerzucaniu w razie potrzeby do pamięci pomocniczej, czyli tzw. swapowanie, a z drugiej strony ów ''obiekt'' jest trwały i istnieje nawet jeśli żadne procesy się aktualnie do niego nie odnoszą //

===== Podsumowanie =====


  - Sygnały
  - Potoki
  - Semafory
  - Pamieć dzielona
  - Mechanizmy sieciowe
  - Kolejki komunikatów