SHMOP(2)

NAZWA
shmop - operacje na segmentach pamięci wspólnej

SKŁADNIA
#include <sys/types.h>
#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);

int shmdt(const void *shmaddr);

OPIS
Funkcja shmat dołącza segment pamięci wspólnej o deskryptorze shmid do przestrzeni adresowej procesu, który ją wywołał. Adres, pod którym segment ma być widoczny jest przekazywany parametrem shmaddr, przy czym system może przetworzyć ten adres w następujący sposób:

Jeśli shmaddr jest równy NULL, wówczas system sam wybierze odpowiedni (nieużywany) adres, pod którym segment będzie widoczny.

Jeśli shmaddr nie jest równy NULL i w shmflg przekazany został znacznik SHM_RND, wówczas segment zostanie dołączony pod adresem shmaddr zaokrąglonym w dół do wielokrotności SHMLBA. W innym razie shmaddr musi być wyrównanym do granicy strony adresem, pod którym nastąpi dołączenie segmentu.

Jeśli w shmflg przekazany zostanie znacznik SHM_RDONLY, wówczas segment zostanie odwzorowany z zabezpieczeniem przed zapisem. Proces wywołujący shmat musi mieć prawa odczytu segmentu. W przeciwnym razie w dołączanym segmencie możliwe są zarówno odczyt, jak i zapis, przy czym proces musi mieć prawa do odczytu i zapisu segmentu. Nie istnieje pojęcie segmentu pamięci wspólnej tylko do zapisu.

Znacznik (specyficzny dla Linuksa) SHM_REMAP, który może zostać przekazany w shmflg oznacza, że odwzorowanie tego segmentu powinno zastąpić jakiekolwiek istniejące wcześniej odwzorowanie w zakresie rozpoczynającym się od shmaddr i rozciągającym na rozmiar segmentu. (Normalnie, gdy odwzorowanie w tym zakresie adresów już istnieje, powinien wystąpić błąd EINVAL.) W tym przypadku shmaddr nie może byc równe NULL.

Wartość brk procesu wywołującego funkcję nie jest zmieniana podczas dołączania segmentu. Segment zostanie automatycznie odłączony, gdy proces zakończy się. Ten sam segment może być dołączony do przestrzeni adresowej procesu jako "tylko do odczytu" lub "do odczytu i zapisu" więcej niż raz.

W wyniku pomyślnego wywołania shmat system operacyjny aktualizuje pola struktury shmid_ds opisującej segment w następujący sposób:

    shm_atime zostaje przypisany aktualny czas.

    shm_lpid zostanie przypisany identyfikator procesu wywołującego shmat.

    shm_nattch zostanie zwiększone o jeden.

Należy zwrócić uwagę, że operacja powiedzie się nawet jeśli dołączany segment pamięci wspólnej jest zaznaczony do usunięcia.

Funkcja shmdt wyłącza segment pamięci wspólnej odwzorowany pod adresem podanym w shmaddr z przestrzeni adresowej procesu wywołującego tę funkcję. Przekazany funkcji w parametrze shmaddr adres musi być równy adresowi zwróconemu wcześniej przez wywołanie shmat .

W wyniku pomyślnego wywołania shmdt pola struktury shmid_ds opisującej segment aktualizowane są w następujący sposób:

    shm_dtime przypisywany jest aktualny czas.

    shm_lpid przypisywany jest identyfikator procesu wywołującego shmdt.

    shm_nattch jest zmniejszane o jeden. Jeśli pole to osiągnie 0 i segment jest zaznaczony do usunięcia, wówczas zostanie on usunięty.

Obszar w przestrzeni adresowej procesu wywołującego funkcję jest zwalniany.

WYWOŁANIA SYSTEMOWE

fork()
    W wyniku wywołania fork() proces potomny dziedziczy dołączone segmenty pamięci wspólnej.

exec()
    Po wykonaniu exec() wszystkie odwzorowane segmenty są odłączane (nie są usuwane).

exit()
    Po wykonaniu exit() wszystkie dołączone segmenty pamięci wspólnej są odłączane (nie są usuwane).

WARTOŚĆ ZWRACANA
W przypadku wystąpienia błędu opydwie funkcje zwracają -1 przypisując zmiennej errno kod błędu. W wyniku poprawnego wykonania funkcja shmat zwraca adres początku obszaru odwzorowania segmentu, natomiast funkcja shmdt zwraca wartość 0.

BŁĘDY
Gdy shmat zakończy się niepomyślnie, zmiennej errno przypisywana jest jedna z następujących wartości:

EACCES
    Proces wywołujący funkcję nie ma uprawnień do dołączenia segmentu w zadany sposób (do odczytu lub odczytu / zapisu).

EINVAL
    Niewłaściwa wartość parametru shmid, niewyrównana do granicy strony (i nie podano SHM_RND), niepoprawna wartość shmaddr, nieudane dołączenie pod adresem brk lub został podany znacznik SHM_REMAP, podczas gdy shmaddr jest równe NULL.

ENOMEM
    Brak pamięci na deskryptor lub tablice stron.

Funkcja shmdt może zakończyć się niepomyślnie tylko w sytuacji, gdy pod adresem shmaddr nie istnieje segment pamięci wspólnej. Wowczas zmienna errno przyjmie wartość EINVAL.

UWAGI
Używanie shmat z shmaddr równym NULL jest zalecaną, przenośną motodą dołączania segmentu pamięci wspólnej. Trzeba jednak być świadomym, że ta metoda dołączania segmentu pamięci wspólnej może spowodować jego dołączenie pod różnymi adresami w różnych procesach. W związku z tym wszystkie wskaźniki obsługiwane w pamięci wspólnej muszą być względne (zazwyczaj względem adresu początkowego segmentu), nie zaś bezwzględne.

Dla wywołania shmat obowiązuje następujące ograniczenie systemowe:

SHMLBA
    Wartość, której wielokrotnością musi być adres dolnej granicy segmentu. Musi być wyrównana do granicy strony. W aktualnej implementacji SHMLBA jest równe PAGE_SIZE.

Aktualna implementacja nie ma wewnętrznego ograniczenia na ilość segmentów pamięci wspólnej dołączanych do jednego procesu (SHMSEG).

ZGODNE Z
SVr4, SVID. SVr4 dokumentuje dodatkowy kod błędu EMFILE. W SVID-v4 typ parametru shmaddr został zmieniony z char * na const void *, a typ wyniku zwracanego przez shmat() z char * na void *. (Linuksowe libc4 i libc5 zawierają prototypy char *; glibc2 zawiera void *.)

ZOBACZ TAKŻE
brk(2), ipc(5), mmap(2), shmctl(2), shmget(2).