SHMGET(2) | Podręcznik programisty Linuksa | SHMGET(2) |
shmget - utworzenie segmentu pamięci dzielonej Systemu V
#include <sys/ipc.h>
#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. 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:
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).
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)):
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.
W przypadku wystąpienia błędu, zmiennej errno przypisywana jest jedna z następujących wartości:
POSIX.1-2001, POSIX.1-2008, SVr4.
SHM_HUGETLB i SHM_NORESERVE są linuksowymi rozszerzeniami.
Dołączenie <sys/types.h> i <sys/ipc.h> nie jest wymagane na Linuksie ani przez żadną z wersji POSIX. Jednak niektóre stare implementacje wymagają dołączenia tych plików nagłówkowych, SVID również dokumentuje ich dołączenie. Aplikacje które mają być przenośne na tego typu stare systemy mogą wymagać dołączenia omawianych plików nagłówkowych.
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():
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.
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.
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 wersji 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.
memfd_create(2), shmat(2), shmctl(2), shmdt(2), ftok(3), capabilities(7), shm_overview(7), svipc(7)
Angielska wersja tej strony pochodzi z wydania 4.07 projektu Linux man-pages. Opis projektu, informacje dotyczące zgłaszania błędów, oraz najnowszą wersję oryginału można znaleźć pod adresem https://www.kernel.org/doc/man-pages/.
Autorami polskiego tłumaczenia niniejszej strony podręcznika man są: Rafał Lewczuk (PTM) <R.Lewczuk@elka.pw.edu.p>, Andrzej Krzysztofowicz (PTM) <ankry@mif.pg.gda.pl>, Robert Luberda <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>.
Polskie tłumaczenie jest częścią projektu manpages-pl; uwagi, pomoc, zgłaszanie błędów na stronie http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją 4.07 oryginału.
2015-12-28 | Linux |