shmget − utworzenie segmentu pamięci wspólnej
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, int size, int shmflg);
Funkcja shmget() zwraca deskryptor segmentu pamięci wspólnej, skojarzonego z wartością (kluczem) przekazaną w parametrze key. Nowy segment zostanie utworzony, Jeśli parametr key będzie mieć wartość IPC_PRIVATE lub jeśli będzie mieć inną wartość, a segment skojarzony z key nie istnieje zaś w parametrze shmflg zostanie przekazany znacznik IPC_CREAT (tj. shmflg&IPC_CREAT nie jest równe 0), to zostanie utworzony nowy segment, a jego rozmiar będzie równy parametrowi size zaokrąglonemu w górę do wielokrotności PAGE_SIZE.
Wartość shmflg skłąda się z:
|
IPC_CREAT, |
aby utworzyć nowy segment. Jeśli ten znaczniek nie zostanie ustawiony, to shmget() spróbuje znaleźć segment skojarzony z key i sprzwdzić, czy użytkownik ma uprawnienia dla dostępu do segmentu. | ||
|
IPC_EXCL |
przekazane łącznie z IPC_CREAT zapewnia sygnalizację błędu, jeśli segment już isnieje. |
mode_flags (9 najmniej znaczących bitów)
określa prawa dostępu do segmentu dla jego właściciela, grupy oraz reszty świata. Prawa uruchamiania nie są obecnie przez system używane.
W momencie tworzenia segmentu, prawa dostępu są kopiowane z parametru shmflg do pola shm_perm definiującej segment struktury shmid_ds. Budowa struktury shmid_ds:
struct shmid_ds
{
struct ipc_perm shm_perm; /* prawa dostępu */
|
shm_segsz; /* rozmiar segmentu (w bajtach) */ | |||||
|
shm_atime; /* czas ostatniego dołączenia */
| |||||
|
shm_dtime; /* czas ostatniego odłączenia */
| |||||
|
shm_ctime; /* czas ostatniej modyfikacji */ |
unsigned short shm_cpid; /* PID
twórcy segmentu */
unsigned short shm_lpid; /* PID ostatniego operującego
procesu */
|
shm_nattch; |
/* aktualna liczba dołączeń */ |
};
struct ipc_perm
{
key_t key;
ushort uid; /* euid i egid właściciela*/
ushort gid;
ushort cuid; /* euid i egid twórcy */
ushort cgid;
ushort mode; /* 9 najmniej znaczących bitów
shmflg */
ushort seq; /* numer porządkowy */
};
Podczas tworzenia segmentu pamięci wsólnej, funkcja ta inicjalizuje strukturę shmid_ds w następujący sposób:
shm_perm.cuid i shm_perm.uid przypisywany jest efektywny identyfikator użytkownika procesu, który wywołał shmget.
shm_perm.cgid i shm_perm.gid przypisywany jest efektywny identyfikator grupy procesu, który wywołał shmget.
9 najmniej znaczących bitów parametru shmflg jest kopiowanych do pola shm_perm.mode.
shm_segsz przypisywana jest wartość parametru size.
Polom shm_lpid, shm_nattch, shm_atime i shm_dtime przypisywana jest wartość 0.
Polu shm_ctime przypisywany jest aktualny czas.
Jeśli dany segment pamięci wspólnej już istnieje, wówczas system sprawdza prawa dostępu oraz bada, czy segment nie został zaznaczony do usunięcia.
|
fork() |
Po wywołaniu fork() proces potomny dziedziczy dołączone segmenty pamięci wspólnej. | ||
|
exec() |
Po wywołaniu exec() wszystkie dołączone segmenty są odłączane (nie są usuwane). | ||
|
exit() |
Podczas wywoływania exit() wszystkie dołączone segmenty są odłączane (nie są usuwane). |
Funkcja po pomyślnym zakończeniu zwraca deskryptor segmentu, a −1, jeśli wystąpi błąd.
W przypadku wystąpienia błędu, zmiennej errno przypisywana jest jedna z następujących wartości:
|
EINVAL, |
jeśli miał zostać utworzony nowy segment, a size < SHMMIN lub size > SHMMAX, lub gdy nie miał być utworzony nowy segment, a segment o podanej wartości key istnieje, lecz size jest większe niż rozmiar tego segmentu. | ||
|
EEXIST, |
jeśli przekazane zostały znaczniki IPC_CREAT | IPC_EXCL , ale segment o zadanym kluczu już istnieje. | ||
|
EIDRM |
jeśli segment został zaznaczony do usunięcia lub usunięty. | ||
|
ENOSPC |
jeśli przekroczony został limit ilości segmentów pamięci wspólnej w systemie (SHMMNI) lub sumarycznej wielkości wszystkich segmentów (SHMALL). | ||
|
ENOENT, |
jeśli segment o zadanej wartości key nie istnieje, a nie ustawiono znacznika IPC_CREAT. | ||
|
EACCES, |
jeśli użytkownik nie ma praw dostępu do zadanego segmentu pamięci wspólnej. | ||
|
ENOMEM, |
gdy nie uda się przydzielić pamięci dla segmentu. |
IPC_PRIVATE nie jest znacznikiem, lecz wartością typu key_t. Jeśli jako key zostanie użyta ta wartość specjalna, to funkcja zignoruje wszystko oprócz 9 najmniej znaczących bitów shmflg i utworzy nowy segment pamięci wspólnej nie posiadający klucza (jeśli wywołanie zakończy się pomyślnie).
Następujące ograniczenia odnoszące się do zasobów pamięci wspólnej dotyczą funkcji shmget:
|
SHMALL |
Maksymalna liczba stron pamięci użytych do stworzenia segmentów pamięci wspólnej: zależna od polityki. | ||
|
SHMMAX |
Maksymalny rozmiar (w bajtach) pojedynczego segmentu pamięci wspólnej: zależny od implementacji (aktualnie 4MB). | ||
|
SHMMIN |
Minimalny rozmiar (w bajtach) pojedynczego segmentu pamięci wspólnej: zależny od implementacji (aktualnie 1 bajt, ale efektywny minimalny rozmiar wynosi PAGE_SIZE ). | ||
|
SHMMNI |
Maksymalna liczba segmentów pamięci wspólnej w systemie: zależna od implementacji (aktualnie 4096, ale w wersjach Linuksa wcześniejszych niż 2.3.99 wynosiła 128) |
System Linux nie stawia ograniczeń dotyczących ilości segmentów dołączonych do jednego procesu (SHMSEG).
Wybrana nazwa, IPC_PRIVATE, prawdopodobnie nie jest najszczęśliwsza. IPC_NEW w sposób bardziej przejrzysty odzwierciedlało by rolę tej wartości.
SVr4, SVID. SVr4 dokumentuje dodatkowy kod błędu EEXIST. Do wersji 2.3.30 Linux zwracał EIDRM w przepadku wywołania shmget na segmencie pamięci wspólnej przeznaczonym do skasowania.
ftok(3), ipc(5), shmctl(2), shmat(2), shmdt(2)
Powyższe tłumaczenie pochodzi z nieistniejącego już Projektu Tłumaczenia Manuali i może nie być aktualne. W razie zauważenia różnic między powyższym opisem a rzeczywistym zachowaniem opisywanego programu lub funkcji, prosimy o zapoznanie się z oryginalną (angielską) wersją strony podręcznika.