Programowanie współbieżne i rozproszone/PWR Ćwiczenia shm: Różnice pomiędzy wersjami
Nie podano opisu zmian |
Nie podano opisu zmian |
||
Linia 6: | Linia 6: | ||
== Scenariusz == | == Scenariusz == | ||
=== Wstęp === | |||
Segmenty pamięci dzielonej to trzeci, ostatni już mechanizm z pakietu IPC. Jak zwykle do segmentów pamięci dzielonej stosują się wszystkie uwagi dotyczące mechanizmów IPC, omówione przy okazji kolejek komunikatów. Dotychczas wszystkie programy, które pisaliśmy w środowisku Unix składały się z procesów, z których każdy korzystał z własnych zmiennych. Zmienne współdzielone, dostępne dla wielu procesów nie występowały, a synchronizacja odbywała się poprzez wymianę komunikatów bądź to za pomocą łączy bądź kolejek komunikatów. Pewne odstępstwo od tej zasady nastąpiło z chwilą wprowadzenia semaforów, ale ponieważ to system dba o zarządzanie nimi i przydzielenie im miejsca w pamięci, więc programista nie musiał się tym zajmować. Dziś chcemy korzystać ze wspólnej pamięci w postaci zmiennych dostępnych dla wielu procesów. | |||
Choć procesy uniksowe uruchamiane na tym samym komputerze wykonują się we wspólnej pamięci, to jednak z logicznego punktu widzenia przestrzenie adresowe różnych procesów są rozłączne. Aby umożliwić korzystanie na przykład ze wspólnych zmiennych wprowadzono, początkowo do Uniksa Systemu V, a później już do wszystkich wersji systemu, mechanizm segmentow pamieci dzielonej. | |||
Segment pamięci dzielonej jest fragmentem pamięci, który może być ''podpinany'' do przestrzeni adresowych różnych procesów. Zarządzaniem segmentami pamięci dzielonej zajmuje się system, ale to programista jest odpowiedzialny za utworzenie segmentu o potrzebnej mu wielkości oraz jego podpięcie pod pewien adres przestrzeni adresowej (najczęściej wybrany przez system operacyjny). Jeśli ten sam segment zostanie przyłączony do przestrzeni adresowych różnych procesów, to wszelkie dane (a więc zmienne) w nim przechowywanie stają się widoczne i dostępne dla tych procesów. Oczywiście dostęp do nich wymaga wówczas synchronizacji, ale mamy już do tego odpowiednie mechanizmy --- na przykład semafory. | |||
adresowych to | |||
Operacje zapisu i odczytu z segmentu pamięci wirtualnej do zwykłe operacje dostępu do pamięci. Dzięki temu są one realizowane szybko i wydajnie, znacznie szybciej niż na przykład wysłanie komunikatu za pomocą kolejki komunikatów, które wymaga kopiowania komunikatu między przestrzenią adresową nadawcy, jądra oraz odbiorcy. Tutaj występuje zapis po stronie nadawcy i odczyt po stronie odbiorcy. | |||
Ponieważ segment pamięci jest zasobem IPC, trzeba go najpierw utworzyć lub uzyskać dostęp do segmentu już istniejącego. Identyfikacja segmentów odbywa się jak zwykle za pomocą ustalonego klucza, a następnie identyfikatora przekazywanego przez funkcję <tt>get</tt>, która w przypadku segmentów pamięci dzielonej nazywa się <tt>shmget</tt>. Ale to jeszcze nie koniec. Aby proces mógł coś zapisać do segmentu lub z niego odczytać, segment musi zostać podpięty do przestrzeni adresowej. Podobnie, gdy segment staje się niepotrzebny w danym procesie należy go odłączyc od przestrzeni adresowej. Dopóki jednak segment jest przyłączony do jakiekolwiek procesu, dane w nim zapisywane są utrzymywane. Segment, który jest już niepotrzebny w żadnym procesie należy usunąć, jak każdy zasób IPC. | |||
dzielonej to | |||
Tak wygląda typowy scenariusz pracy z segmentami pamięci dzielonej. Do jego realizacji służą następujące funkcje systemowe: | |||
* shmget --- tworząca segment pamięci dzielonej | |||
* shmat --- przyłączająca segmentu pamięci dzielonej do przestrzeni adresowej procesu | |||
* shmdt --- odlączająca segmentu pamięci dzielonej od przestrzeni adresowej procesu | |||
* shmctl --- realizująca operacje sterujące na segmencie pamięci dzielonej | |||
Program w C wykorzystujący mechanizm pamięci dzielonej musi wykorzystać następujące pliki nagłówkowe: | |||
<Source> | |||
#include <sys/types.h> | #include <sys/types.h> | ||
#include <sys/ipc.h> | #include <sys/ipc.h> | ||
#include <sys/shm.h> | #include <sys/shm.h> | ||
</Source> | |||
=== Tworzenie (uzyskanie dostępu do) segmentu pamięci dzielonej === | |||
Do utworzenia segmentu pamięci dzielonej służy funkcja systemowa <tt>shmget</tt>: | |||
<Source> | |||
int shmget (key_t klucz, int rozmiar, int flagi) | int shmget (key_t klucz, int rozmiar, int flagi) | ||
</Source> | |||
* Pierwszym parametrem tej funkcji jest jak zwykle klucz zasobu | |||
* Trzecim parametrem są opcje, które jak zwykle określają prawa dostępu do pamięci oraz ewentualne opcje <tt>IPC_CREAT</tt>, <tt>IPC_EXCL</tt> lub <tt>IPC_PRIVATE</tt> | |||
* Wynikiem funkcji <tt>shmget</tt> jest identyfikator segmentu pamięci dzielonej lub -1 w przypadku błędu | |||
Parametrem specyficznym dla segmentów pamięci dzielonej jest <tt>rozmiar</tt>, który określa rozmiar tworzonego segmentu pamięci dzielonej. Ma on znaczenie jedynie wtedy, gdy segment jest faktycznie tworzony. Jeśli funkcja powoduje jedynie uzyskanie dostępu do już istniejącego segmentu, to parametr ten jest ignorowany. Tak naprawdę, utworzony segment będzie miał będzie składał się z pewnej (odpowiednio dużej) liczby stron, więc jego rozmiar jest zawsze wielokrotnością rozmiaru strony. | |||
=== Przyłączanie segmentu pamięci dzielonej === | |||
<!-- | |||
Aby proces mogl skorzystac z segmentu pamieci dzielonej musi: | Aby proces mogl skorzystac z segmentu pamieci dzielonej musi: |
Wersja z 12:05, 17 paź 2006
Tematyka zajęć
Segmenty pamięci dzielonej
Literatura
Scenariusz
Wstęp
Segmenty pamięci dzielonej to trzeci, ostatni już mechanizm z pakietu IPC. Jak zwykle do segmentów pamięci dzielonej stosują się wszystkie uwagi dotyczące mechanizmów IPC, omówione przy okazji kolejek komunikatów. Dotychczas wszystkie programy, które pisaliśmy w środowisku Unix składały się z procesów, z których każdy korzystał z własnych zmiennych. Zmienne współdzielone, dostępne dla wielu procesów nie występowały, a synchronizacja odbywała się poprzez wymianę komunikatów bądź to za pomocą łączy bądź kolejek komunikatów. Pewne odstępstwo od tej zasady nastąpiło z chwilą wprowadzenia semaforów, ale ponieważ to system dba o zarządzanie nimi i przydzielenie im miejsca w pamięci, więc programista nie musiał się tym zajmować. Dziś chcemy korzystać ze wspólnej pamięci w postaci zmiennych dostępnych dla wielu procesów.
Choć procesy uniksowe uruchamiane na tym samym komputerze wykonują się we wspólnej pamięci, to jednak z logicznego punktu widzenia przestrzenie adresowe różnych procesów są rozłączne. Aby umożliwić korzystanie na przykład ze wspólnych zmiennych wprowadzono, początkowo do Uniksa Systemu V, a później już do wszystkich wersji systemu, mechanizm segmentow pamieci dzielonej.
Segment pamięci dzielonej jest fragmentem pamięci, który może być podpinany do przestrzeni adresowych różnych procesów. Zarządzaniem segmentami pamięci dzielonej zajmuje się system, ale to programista jest odpowiedzialny za utworzenie segmentu o potrzebnej mu wielkości oraz jego podpięcie pod pewien adres przestrzeni adresowej (najczęściej wybrany przez system operacyjny). Jeśli ten sam segment zostanie przyłączony do przestrzeni adresowych różnych procesów, to wszelkie dane (a więc zmienne) w nim przechowywanie stają się widoczne i dostępne dla tych procesów. Oczywiście dostęp do nich wymaga wówczas synchronizacji, ale mamy już do tego odpowiednie mechanizmy --- na przykład semafory.
Operacje zapisu i odczytu z segmentu pamięci wirtualnej do zwykłe operacje dostępu do pamięci. Dzięki temu są one realizowane szybko i wydajnie, znacznie szybciej niż na przykład wysłanie komunikatu za pomocą kolejki komunikatów, które wymaga kopiowania komunikatu między przestrzenią adresową nadawcy, jądra oraz odbiorcy. Tutaj występuje zapis po stronie nadawcy i odczyt po stronie odbiorcy.
Ponieważ segment pamięci jest zasobem IPC, trzeba go najpierw utworzyć lub uzyskać dostęp do segmentu już istniejącego. Identyfikacja segmentów odbywa się jak zwykle za pomocą ustalonego klucza, a następnie identyfikatora przekazywanego przez funkcję get, która w przypadku segmentów pamięci dzielonej nazywa się shmget. Ale to jeszcze nie koniec. Aby proces mógł coś zapisać do segmentu lub z niego odczytać, segment musi zostać podpięty do przestrzeni adresowej. Podobnie, gdy segment staje się niepotrzebny w danym procesie należy go odłączyc od przestrzeni adresowej. Dopóki jednak segment jest przyłączony do jakiekolwiek procesu, dane w nim zapisywane są utrzymywane. Segment, który jest już niepotrzebny w żadnym procesie należy usunąć, jak każdy zasób IPC.
Tak wygląda typowy scenariusz pracy z segmentami pamięci dzielonej. Do jego realizacji służą następujące funkcje systemowe:
- shmget --- tworząca segment pamięci dzielonej
- shmat --- przyłączająca segmentu pamięci dzielonej do przestrzeni adresowej procesu
- shmdt --- odlączająca segmentu pamięci dzielonej od przestrzeni adresowej procesu
- shmctl --- realizująca operacje sterujące na segmencie pamięci dzielonej
Program w C wykorzystujący mechanizm pamięci dzielonej musi wykorzystać następujące pliki nagłówkowe:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
Tworzenie (uzyskanie dostępu do) segmentu pamięci dzielonej
Do utworzenia segmentu pamięci dzielonej służy funkcja systemowa shmget:
int shmget (key_t klucz, int rozmiar, int flagi)
- Pierwszym parametrem tej funkcji jest jak zwykle klucz zasobu
- Trzecim parametrem są opcje, które jak zwykle określają prawa dostępu do pamięci oraz ewentualne opcje IPC_CREAT, IPC_EXCL lub IPC_PRIVATE
- Wynikiem funkcji shmget jest identyfikator segmentu pamięci dzielonej lub -1 w przypadku błędu
Parametrem specyficznym dla segmentów pamięci dzielonej jest rozmiar, który określa rozmiar tworzonego segmentu pamięci dzielonej. Ma on znaczenie jedynie wtedy, gdy segment jest faktycznie tworzony. Jeśli funkcja powoduje jedynie uzyskanie dostępu do już istniejącego segmentu, to parametr ten jest ignorowany. Tak naprawdę, utworzony segment będzie miał będzie składał się z pewnej (odpowiednio dużej) liczby stron, więc jego rozmiar jest zawsze wielokrotnością rozmiaru strony.