shmget - tworzy segment pamięci dzielonej Systemu V
Standardowa biblioteka C (libc, -lc)
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
shmget() zwraca identyfikator segmentu pamięci
dzielonej Systemu V, skojarzonego z wartością (kluczem)
przekazaną w parametrze key. Może
służyć albo do pozyskania identyfikatora uprzednio
utworzonego segmentu pamięci dzielonej (gdy shmflg wynosi zero
i key nie ma wartości IPC_PRIVATE) lub do utworzenia
nowego.
Nowy segment, o rozmiarze równym wartości parametru
size zaokrąglonym w górę do
wielokrotności PAGE_SIZE, zostanie utworzony, jeśli
parametr key będzie mieć wartość
IPC_PRIVATE lub jeśli będzie mieć inną
wartość oraz segment skojarzony z key nie istnieje, a w
parametrze shmflg zostanie przekazany znacznik IPC_CREAT.
Jeżeli w parametrze shmflg podano zarówno
IPC_CREAT, jak i IPC_EXCL oraz już istnieje segment w
pamięci dzielonej o kluczu key, to shmget()
kończy się błędem, ustawiając
errno na wartość EEXIST. (Działa to
analogicznie do O_CREAT | O_EXCL w open(2)).
Wartość shmflg składa się
z:
- IPC_CREAT
- Tworzy nowy segment. Jeśli ten znacznik nie zostanie ustawiony, to
shmget() spróbuje znaleźć segment skojarzony z
key i sprawdzić, czy użytkownik ma uprawnienia
dostępu do segmentu.
- IPC_EXCL
- Ta flaga przekazana łącznie z IPC_CREAT zapewnia,
że to wywołanie utworzy segment. Jeśli segment
już istnieje, wywołanie zawiedzie.
- SHM_HUGETLB
(od Linuksa 2.6)
- Dołącza segment używając dużych
(„huge”) stron. Dalsze informacje można
znaleźć w pliku
Documentation/admin-guide/mm/hugetlbpage.rst w
źródłach jądra Linux.
- SHM_HUGE_2MB
- SHM_HUGE_1GB
(od Linuksa 3.8)
- Używany w połączeniu z SHM_HUGETLB do wybrania
alternatywnych rozmiarów stron hugetlb (odpowiednio, 2 MB i
1 GB) w systemach obsługujących wiele
rozmiarów stron hugetlb.
- Ogólniej, pożądany rozmiar dużej strony
można skonfigurować kodując go w sześciu
bajtach na przesunięciu SHM_HUGE_SHIFT za pomocą
logarytmu o podstawie 2. Dlatego, powyższe dwie stałe
są zdefiniowane jako:
-
#define SHM_HUGE_2MB (21 << SHM_HUGE_SHIFT)
#define SHM_HUGE_1GB (30 << SHM_HUGE_SHIFT)
- Dodatkowe informacje można odnaleźć przy
omówieniu podobnie nazwanych stałych w mmap(2).
- SHM_NORESERVE
(od Linuksa 2.6.15)
- Ten znacznik stosuje się w takim samym celu jak znacznik
MAP_NORESERVE funkcji mmap(2). Nie rezerwuje przestrzeni
wymiany dla tego segmentu. Jeśli przestrzeń wymiany zostanie
zarezerwowana, ma się gwarancję, że jest
możliwe zmodyfikowanie segmentu. Gdy przestrzeń wymiany nie
jest zarezerwowana, można otrzymać sygnał
SIGSEGV podczas próby zapisu do segmentu, gdy zabraknie
dostępnej fizycznej pamięci. Patrz także opis pliku
/proc/sys/vm/overcommit_memory w proc(5).
Oprócz powyższych flag, 9 najmniej znaczących
bitów sgmflg określa prawa dostępu do segmentu
dla jego właściciela, grupy oraz innych. Bity są w
takim samym formacie i mają takie samo znaczenie, jak parametr
mode wywołania open(2). Prawa uruchamiania nie
są obecnie używane przez system.
Jeżeli tworzona jest nowa kolejka komunikatów,
wywołanie to w następujący sposób inicjuje
strukturę danych msqid_ds (patrz msgctl(2)):
- •
- shm_perm.cuid i shm_perm.uid przyjmują
wartość efektywnego identyfikatora właściciela
procesu wywołującego.
- •
- shm_perm.cgid i shm_perm.gid przyjmują
wartość efektywnego identyfikatora grupy procesu
wywołującego.
- •
- 9 najmniej znaczących bitów pola shm_perm.mode jest
kopiowanych z 9 najmniej znaczących bitów
shmflg.
- •
- shm_segsz jest ustawiane na wartość parametru
size.
- •
- shm_lpid, shm_nattch, shm_atime i shm_dtime
są ustawiane na 0.
- •
- shm_ctime jest ustawiane na bieżący czas.
Jeśli dany segment pamięci dzielonej już
istnieje, to są weryfikowane uprawnienia i jest sprawdzane, czy
segment nie jest przeznaczony do usunięcia.
W przypadku powodzenia zwracany jest poprawny identyfikator
pamięci współdzielonej. W razie wystąpienia
błędu zwracane jest -1 i ustawiana jest errno
wskazując błąd.
- EACCES
- Użytkownik nie ma praw dostępu do żądanego
segmentu pamięci dzielonej oraz nie ma przywileju
CAP_IPC_OWNER (ang. capability) w przestrzeni nazw
użytkownika, która zarządza jego przestrzenią
nazw IPC.
- EEXIST
- IPC_CREAT i IPC_EXCL były określone w
shmflg, lecz segment pamięci dzielonej już istnieje
dla key.
- EINVAL
- Miał być utworzony nowy segment, a wartość
size jest mniejsza niż SHMMIN lub większa
niż SHMMAX.
- EINVAL
- Segment dla podanego key istnieje, lecz size jest
większy niż rozmiar tego segmentu.
- ENFILE
- Zostało osiągnięte systemowe ograniczenie na
całkowitą liczbę otwartych plików.
- ENOENT
- Segment o zadanej wartości key nie istnieje i nie ustawiono
znacznika IPC_CREAT.
- ENOMEM
- Nie udało się przydzielić pamięci dla
segmentu.
- ENOSPC
- Wszystkie możliwe identyfikatory pamięci dzielonej
zostały wykorzystane (SHMMNI) lub przydzielenie segmentu o
żądanym rozmiarze size spowodowałoby
przekroczenie systemowego ograniczenia na wielkość
pamięci dzielonej (SHMALL).
- EPERM
- Podano znacznik SHM_HUGETLB, ale proces wywołujący
nie był uprzywilejowany (nie miał przywileju
CAP_IPC_LOCK) oraz nie jest członkiem grupy
sysctl_hugetlb_shm_group; zob. opis
/proc/sys/vm/sysctl_hugetlb_shm_group w podręczniku
proc(5).
POSIX.1-2008.
SHM_HUGETLB i SHM_NORESERVE są linuksowymi
rozszerzeniami.
IPC_PRIVATE nie jest znacznikiem, ale
szczególną wartością typu key_t.
Jeśli wartość ta zostanie użyta jako parametr
key, to system uwzględni jedynie 9 najniższych
bitów parametru shmflg i utworzy nowy segment pamięci
dzielonej.
Następujące ograniczenia odnoszące się
do zasobów pamięci dzielonej dotyczą wywołania
shmget():
- SHMALL
- Systemowy limit całkowitej wielkości pamięci
dzielonej, mierzony w jednostkach systemowego rozmiaru strony.
- W Linuksie to ograniczenie można odczytać i zmienić,
używając pliku /proc/sys/kernel/shmall. Od Linuksa
3.16 domyślną wartością tego
limitu jest:
-
ULONG_MAX - 2^24
- Ta wartość (odpowiednia dla systemów 32 i
64-bitowych) skutkuje brakiem limitów dla alokacji. Ta
wartość, zamiast ULONG_MAX, została wybrana
jako domyślna, aby zapobiec przypadkom gdy pewne stare aplikacje
zwiększały istniejący limit bez sprawdzania jego
wartości bieżącej. Mogło to doprowadzić
do przepełnienia wartości, jeśli limit był
ustawiony na ULONG_MAX.
- Od Linuksa 2.4 do 3.15 domyślną wartością
limitu było:
-
SHMMAX / PAGE_SIZE * (SHMMNI / 16)
- Jeśli nie zmodyfikowano SHMMAX i SHMMNI, to
przemnożenie wyniku tego działania przez rozmiar strony (aby
otrzymać wartość w bajtach) dawało
wartość 8 GB jako limit całkowitej
pamięci używanej przez wszystkie segmenty pamięci
dzielonej.
- SHMMAX
- Maksymalny rozmiar segmentu pamięci dzielonej w bajtach.
- W Linuksie to ograniczenie można odczytać i zmienić,
używając pliku /proc/sys/kernel/shmmax. Od Linuksa
3.16 domyślną wartością tego limitu jest:
-
ULONG_MAX - 2^24
- Ta wartość (odpowiednia dla systemów 32 i
64-bitowych) skutkuje brakiem limitów dla alokacji.
Wyjaśnienie dlaczego jest to wartość domyślna
(zamiast ULONG_MAX) znajduje się w opisie
SHMALL.
- Od Linuksa 2.2 do 3.15 domyślną wartością tego
limitu było 0x2000000 (32 MB).
- Ponieważ nie da się przypisać jedynie fragmentu
segmentu pamięci dzielonej, wartość pamięci
wirtualnej nakłada kolejne ograniczenie na maksymalny rozmiar
użytecznego segmentu np. na architekturze i386 największy
segment który można zmapować ma rozmiar około
2,8 GB, a na x86_64 limit ten wynosi około
127 TB.
- SHMMIN
- Minimalny rozmiar (w bajtach) pojedynczego segmentu pamięci
dzielonej: zależny od implementacji (obecnie 1 bajt, ale efektywny
minimalny rozmiar wynosi PAGE_SIZE).
- SHMMNI
- Systemowy limit liczby segmentów pamięci dzielonej. W
Linuksie 2.2 domyślna wartość tego limitu
wynosiła 128; od Linuksa 2.4 domyślna wartość
wynosi 4096.
- W Linuksie to ograniczenie można odczytać i zmienić,
używając pliku /proc/sys/kernel/shmmni.
System Linux nie stawia ograniczeń dotyczących
liczby segmentów pamięci dzielonej dołączonych
do jednego procesu (SHMSEG).
Do Linuksa 2.3.30 Linux zwracał EIDRM dla
shmget() na segmencie pamięci dzielonej przeznaczonym do
usunięcia.
Nazwa IPC_PRIVATE prawdopodobnie nie jest
najszczęśliwsza. IPC_NEW w sposób bardziej
przejrzysty odzwierciedlałoby rolę tej wartości.
Tłumaczenie niniejszej strony podręcznika:
Rafał Lewczuk <R.Lewczuk@elka.pw.edu.p>, Andrzej Krzysztofowicz
<ankry@green.mf.pg.gda.pl>, Robert Luberda <robert@debian.org> i
Michał Kułach <michal.kulach@gmail.com>
Niniejsze tłumaczenie jest wolną
dokumentacją. Bliższe informacje o warunkach licencji
można uzyskać zapoznając się z
GNU General
Public License w wersji 3 lub nowszej. Nie przyjmuje się
ŻADNEJ ODPOWIEDZIALNOŚCI.
Błędy w tłumaczeniu strony podręcznika
prosimy zgłaszać na adres listy dyskusyjnej
manpages-pl-list@lists.sourceforge.net.