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