Komunikacja procesów przez pamięć dzieloną

Transkrypt

Komunikacja procesów przez pamięć dzieloną
Komunikacja procesów przez pamięć
dzieloną
Pamięć dzielona (ang. shared memory) jest najszybszą metodą komunikacji między procesami. Istotą
owego szybkiego przesyłu danych jest prosty fakt, mianowicie w przypadku ww. nie istnieje potrzeba
generalnego przesyłu danych pomiędzy procesami. Wszelakie operacje odbywać się powinny w
ramach tych samych segmentów pamięci (wirtualnej przestrzeni adresowej – adresy nie mogą być
adresami pamięci fizycznej – powodowało by niemożność wykonywania kilku procesów); Wyżej
wymienione ma zastosowanie oczywiście przy założeniu iż skupimy się tylko na architekturach
posiadających wspólną pamięć.
Mimo istnienia API mających na celu ułatwienie pracy programistycznej z opisywanym zagadnieniem,
istnieje pewien schemat, wedle którego wykonywane są wszelakie operacje. I tak, aby móc mówić o
poprawnym wykorzystaniu pamięci wspólnej należy najsamprzód zadeklarować pewien wydzielony
obszar pamięci, w wirtualnej przestrzeni adresowej, który będzie poprzez odpowiednie modyfikacje
służył jako miejsce komunikacji międzyprocesowej dla przyszłego, nazwijmy to ogólnie, rozwiązania
informatycznego. Kolejnym wymaganym etapem jest oczywiście przydzielenie utworzonego
segmentu pamięci konkretnym procesom, zależnie od zaplanowanego rozwiązania. Po wypełnieniu
owych wymogów następuje już normalna praca z pamięcią dzieloną. Po zakończeniu wszelakich prac
segment pamięci powinien zostać zwolniony.
Dla krótkiego podsumowania modelu pamięci wspólnej, warto chyba zaznajomić się następującą
tabelką, nakreślającą podstawowe cechy określające przydatność komunikacji poprzez pamięć
dzieloną lub konieczność szukania innych rozwiązań.
Zalety
Szybkość działania
Oszczędność pamięci
Wady
Konieczność stosowania technik zapewniających
poprawność przetwarzania danych (semafory,
muteksy, zmienne warunkowe, blokady,
monitory itp.)
Ograniczona możliwość wykorzystania w
systemach typowo sieciowych
Konieczność wykorzystywania konkretnych
bibliotek programistycznych
Jako, że samo przedstawienie ogólnych zasad nie wyczerpie z pewnością ciekawości komisji, można
zaprezentować odwołania do konkretnych API. W przypadku naszego programu nauczania, mieliśmy
do czynienia z IPC wywodzącym się z systemu V (_chyba_ można to utożsamić z obecnymi systemami
rodziny Unix) ; nagłówki funkcji niezbędnych do prawidłowego użycia pamięci dzielonej:
 int shmget(key_t key, int shmflg) – utworzenie nowego lub otworzenie już
istniejącego segmentu pamięci
 zwraca następujące wartości:
 identyfikator pamięci dzielonej, jeżeli sukces
 -1 jeżeli błąd, zostaje ponadto ustawione errno na:
 EINVAL ( nieprawidłowy rozmiar segmentu )
 EEXIST ( segment istnieje, nie można utworzyć )
 EIDRM ( segment czeka na usunięcie, lub usunięty )
 ENOENT ( segment nie isnieje )
 EACCES ( brak prawa dostępu )
 ENOMEM ( brak pamięci do utworzenia segmentu )
 key_t ket – klucz segmentu pamięci
 int shmflg:
 IPC_CREAT – utwórz segment pamięci, jeżeli ten nie istnieje
 IPC_EXCL – użyte z powyższym zwraca błąd, jeśli dany segment pamięci już
istnieje
 int shmctl(int shmid, int cmd, struct shmid_ds *buf) – wykonanie
operacji usunięcia obszaru pamięci wspólnej lub inne czynności
 zwraca następujące wartości
 0 – sukces
 -1 - błąd, zostaje ustawione errno na:
 EACCES ( odczyt zabroniony i cmd jest ustawiony na IPC_STAT )
 EFAULT ( adres wskazywany przez buf jest nieprawidłowy dla
komend IPC_SET i IPC_STAT )
 EIDRM ( segment został usunięty )
 EINVAL ( nieprawidłowy shmqid )
 EPERM ( podano komendy IPC_SET lub IPC_RMID, jednak proces nie
ma prawa zapisu, lub dostępu do segmentu )
 int shmid – id segmentu pamięci
 int cmd:
 IPC_STAT - pobiera strukturę shmid_ds i zachowuje ją pod adresem
wskazywanym przez buf
 IPC_SET - ustawia wartość elementu ipc_perm struktury shmid_ds, pobiera
wartość z argumentu buf (generalnie ustawić można właściciela oraz grupę,
pod warunkiem, że wywołujący proces posiada uid równy 0)
 IPC_RMID – usuwa segment pamięci wspólnej
 SHM_LOCK – blokada segmentu pamięci (ponownie proces wywołujący musi
mięc uid==0)
 SHM_UNLOCK - przeciwstawna operacja (odblokowanie segmentu)
 struct shmid_ds *buf
 void *shmat(int shmid, const void *shmaddr, int shmflg) – funkcja
przyłącza segment pamięci dzielonej
 jeśli shmaddr jest równy NULL, to przydzielony zostanie pierwszy wolny adres
znaleziony przez system – zalecane postępowanie! Podanie samemu adresu jest
wykorzystywane w przypadku świadomej próby rozwiązywania konfliktów z innymi
programami, bądź ułatwiania dostępu do konkretnego sprzętu
 flaga shmflg:
 SHM_RND – adres zostaje wyrównana w dół (zaokrąglenie do najbliższego
rozmiaru strony – tzw. Stronnicowe wyrównanie adresu <<takie bajery
powinny zadowolić dr Tadka ;-)>> )
 SHM_RDONLY – segment zostaje oznaczony jako ‘tylko do odczytu’
 int shmdt(const void *shmaddr) – funkcja odłącza od przestrzeni adresowej
procesu wskazany segment pamięci przez shmaddr
Źródła:
1. Wykład dr Surmacza z SSO –
http://infeka.wroclaw.pl/!archiwum/ssou1/Sieciowe%20systemy%20operacyjne%20UNIX/W
YKLAD.PDF
2. http://www.linuxpl.org/LPG/node1.html [10.01.2011]
3. http://en.wikipedia.org/wiki/Shared_memory
4. http://www.cs.cf.ac.uk/Dave/C/node27.html