plucky (2) mmap.2.gz

Provided by: manpages-pl-dev_4.25.1-1_all bug

NAZWA

       mmap, munmap - mapuje lub usuwa mapowanie plików lub urządzeń w pamięci

BIBLIOTEKA

       Standardowa biblioteka C (libc, -lc)

SKŁADNIA

       #include <sys/mman.h>

       void *mmap(void addr[.length], size_t length, int prot, int flags,
                  int fd, off_t offset);
       int munmap(void addr[.length], size_t length);

       Informacje o wymaganych makrach sprawdzania cech znajdują się w rozdziale UWAGI.

OPIS

       mmap()  tworzy  nowe  mapowanie w wirtualnej przestrzeni adresowej procesu wywołującego. Początkowy adres
       nowego mapowania podaje się w addr. Argument length określa długość mapowania (musi być ono  większe  niż
       0).

       Jeśli  addr  wynosi NULL, to jądro wybiera (wyrównany do strony) adres, na którym utworzy mapowanie; jest
       to najbardziej przenośna metoda tworzenia nowych mapowań. Jeśli addr nie wynosi NULL, to  jądro  traktuje
       go  jako wskazówkę na temat miejsca umieszczenia mapowania; w Linuksie, jądro wybierze najbliższą granicę
       strony (jednak będzie ona zawsze równa lub większa wartości określonej  w  /proc/sys/vm/mmap_min_addr)  i
       spróbuje  utworzyć  tu  nowe  mapowanie. Jeśli inne mapowanie już tu istnieje, jądro wybierze nowy adres,
       który może, lecz nie musi, zależeć  od  wskazówki.  Adres  nowego  mapowania  jest  zwracany  jako  wynik
       wywołania.

       Zawartość  mapowania  pliku (w przeciwieństwie do mapowania anonimowego; zob. MAP_ANONYMOUS poniżej) jest
       inicjowana za pomocą length bajtów zaczynających się w przesunięciu offset w pliku (lub innym  obiekcie),
       do  którego  odnosi się deskryptor pliku fd. offset musi być wielokrotnością rozmiaru strony, jaki zwraca
       sysconf(_SC_PAGE_SIZE).

       Po powrocie wywołania mmap(), deskryptor pliku fd może  być  niezwłocznie  zamknięty,  nie  unieważniając
       mapowania.

       Argument  prot  opisuje  oczekiwany  sposób  ochrony pamięci mapowania (i nie może być sprzeczny z trybem
       otwarcia pliku). Może on być równy PROT_NONE lub może być sumą bitową (OR)  jednego  lub  więcej  spośród
       innych znaczników PROT_*.

       PROT_EXEC  Strony mogą być wykonywane.

       PROT_READ  Strony mogą być odczytywane.

       PROT_WRITE Strony mogą być zapisywane.

       PROT_NONE  Strony mogą nie być dostępne.

   Argument flags
       Argument  flags  określa,  czy  aktualizacje mapowania są widoczne dla innych procesów mapowanych do tego
       samego miejsca i czy aktualizacje są przenoszone na sam plik. To zachowanie zależy od podanej,  dokładnie
       jednej z poniższych wartości flags:

       MAP_SHARED
              Dzieli zadane mapowanie. Aktualizacje mapowania są widoczne dla innych procesów mapowanych do tego
              samego miejsca i (w przypadku mapowań opartych na pliku)  są  przenoszone  do  samego  pliku  (aby
              kontrolować  dokładnie,  kiedy  aktualizacje  są  przenoszone  na  sam plik, konieczne jest użycie
              msync(2)).

       MAP_SHARED_VALIDATE (od Linuksa 4.15)
              Znacznik zapewnia takie same zachowanie jak MAP_SHARED  z  tą  różnicą,  że  mapowania  MAP_SHARED
              ignorują  nieznane znaczniki we flags. Przy tworzeniu mapowań z użyciem MAP_SHARED_VALIDATE, jądro
              sprawdza natomiast, czy wszystkie przekazane znaczniki są  znane  i  odmawia  mapowania  z  błędem
              EOPNOTSUPP,  jeśli  wystąpią  nieznane znaczniki. Ten typ mapowania jest również wymagany, aby móc
              korzystać z niektórych znaczników mapowań (np. MAP_SYNC).

       MAP_PRIVATE
              Tworzy prywatne mapowanie,  typu  „kopiowanie  podczas  zapisu”.  Aktualizacje  mapowania  nie  są
              widoczne  dla  innych  procesów mapujących ten sam plik i nie są przenoszone na sam plik. Nie jest
              określone, czy zmiany zawartości pliku wykonane po wywołaniu mmap() będą uwidocznione w  mapowanym
              obszarze.

       MAP_SHARED   i   MAP_PRIVATE   są  opisane  w  POSIX.1-2001  i  POSIX.1-2008.   MAP_SHARED_VALIDATE  jest
       rozszerzeniem Linuksa.

       Ponadto, zero lub więcej poniższych wartości można zsumować bitowo (OR) we flags:

       MAP_32BIT (od Linuksa 2.4.20, 2.6)
              Umieszcza mapowanie w pierwszych  2  gigabajtach  przestrzeni  adresowej  procesu.  Znacznik  jest
              obsługiwany tylko na architekturze x86-64, w przypadku programów 64-bitowych. Znacznik dodano, aby
              pozwolić stosom wątków na  zaalokowanie  w  pierwszych  2 GB  pamięci,  co  usprawniało  wydajność
              przełączania kontekstów na pewnych wczesnych procesorach 64-bitowych. Współczesne procesory x86-64
              nie mają takiego problemu z wydajnością, zatem znacznik ten nie jest wymagany na  tych  systemach.
              Znacznik MAP_32BIT jest ignorowany, gdy ustawiony jest MAP_FIXED.

       MAP_ANON
              Równoważne MAP_ANONYMOUS; istnieje dla kompatybilności z innymi implementacjami.

       MAP_ANONYMOUS
              Mapowanie  nie  jest  oparte  na pliku; jego zawartość jest inicjowana jako zero. Argument fd jest
              ignorowany, jednak niektóre implementacje wymagają, aby fd wynosiło -1 jeśli podano  MAP_ANONYMOUS
              (lub  MAP_ANON), dlatego przenośne aplikacje powinny używać tej wartości. Argument offset powinien
              wynosić zero. Obsługę MAP_ANONYMOUS w połączeniu z MAP_SHARED dodano w Linuksie 2.4.

       MAP_DENYWRITE
              Ten znacznik jest ignorowany (dawno temu — Linux 2.0 i wcześniejsze — sygnalizował  on,  że  próba
              zapisu  to  mapowanego  pliku powinna zawieść z ETXTBSY; było to jednak źródłem ataków blokujących
              usługę (DoS)).

       MAP_EXECUTABLE
              Ten znacznik jest ignorowany.

       MAP_FILE
              Znacznik służący zgodności. Ignorowany.

       MAP_FIXED
              Nie interpretuje addr jako wskazówki: umieszcza mapowanie dokładnie na podanym adresie. addr  musi
              być  właściwie  wyrównany:  w  przypadku  większości architektur, wystarczająca jest wielokrotność
              rozmiaru strony; jednak niektóre architektury mogą narzucać dodatkowe ograniczenia.  Jeśli  obszar
              pamięci  podany  w  addr  i  length  nachodzi  na  strony  jakiegoś  istniejącego mapowania, to te
              nachodzące części istniejącego mapowania zostaną odrzucone. Jeśli podany adres nie może być użyty,
              wywołanie mmap() zawiedzie.

              Oprogramowanie,  które  ma  zamiar  być przenośne, powinno bardzo ostrożnie korzystać ze znacznika
              MAP_FIXED, mając na względzie, że dokładny schemat  mapowań  pamięci  procesu  może  się  znacznie
              zmieniać pomiędzy wersjami Linuksa, wersjami biblioteki C i wydaniami systemu operacyjnego. Proszę
              dokładnie przeczytać omówienie tego znacznika w UWAGACH!

       MAP_FIXED_NOREPLACE (od Linuksa 4.17)
              Znacznik zapewnia zachowanie podobne do MAP_FIXED, jeśli chodzi o wymuszenie adresu addr,  lecz  z
              tą  różnicą,  że  MAP_FIXED_NOREPLACE  nigdy  nie  narusza wcześniejszego zakresu mapowania. Jeśli
              żądany zakres kolidowałby z istniejącym  mapowaniem,  to  wywołanie  zawiedzie  z  błędem  EEXIST.
              Znacznik  ten może zatem posłużyć do niepodzielnej (z uwzględnieniem innym wątków) próby mapowania
              zakresu adresowego: u jednego wątku powiedzie się to, wszystkie inne zawiodą.

              Proszę zauważyć, że starsze jądra, które nie rozpoznają znacznika MAP_FIXED_NOREPLACE, zwykle  (po
              wykryciu  kolizji  z wcześniejszym mapowaniem) awaryjnie zachowają się jak „nie-MAP_FIXED”: zwrócą
              adres, który  jest  odmienny  od  adresu  żądanego.  Oprogramowanie,  które  ma  być  kompatybilne
              wstecznie, powinno zatem sprawdzać zwracany adres z adresem żądanym.

       MAP_GROWSDOWN
              Znacznik  jest  używany  do  stosów.  Wskazuje systemowi pamięci wirtualnej jądra, że mapowanie ma
              kontynuować się w dół pamięci. Zwracany adres jest o jedną stronę niżej, niż obszar pamięci, który
              jest  w  rzeczywistości  tworzony  w wirtualnej przestrzeni adresowej procesu. Dotknięcie adresu w
              „strzeżonej” stronie (guard page)  poniżej  mapowania  spowoduje  zwiększenie  mapowania  o  jedną
              stronę.  Ten  wzrost  można  powtarzać  do  momentu,  gdy  mapowanie osiągnie wysoki koniec strony
              następnego niższego mapowania; wówczas dotknięcie „strzeżonej” strony spowoduje sygnał SIGSEGV.

       MAP_HUGETLB (od Linuksa 2.6.32)
              Przydziela  mapowanie   za   pomocą   dużych   („huge”)   stron.   Więcej   informacji   w   pliku
              Documentation/admin-guide/mm/hugetlbpage.rst w źródłach jądra Linux oraz w UWAGACH poniżej.

       MAP_HUGE_2MB
       MAP_HUGE_1GB (od Linuksa 3.8)
              Używane   w  połączeniu  z  MAP_HUGETLB,  do  wybrania  alternatywnych  rozmiarów  strony  hugetlb
              (odpowiednio, 2 MB i 1 GB) w systemach, które obsługują wiele rozmiarów stron hugetlb.

              Ogólniej, żądany rozmiar dużych  stron  można  skonfigurować,  podając  logarytm  o  podstawie  2,
              żądanego rozmiaru strony, w sześciu bitach na przesunięciu MAP_HUGE_SHIFT (wartość zero w tym polu
              bitowym oznacza domyślny rozmiar dużej strony; można go  sprawdzić  za  pomocą  pola  Hugepagesize
              ujawnianego w /proc/meminfo). Zatem, powyższe dwie stałe są zdefiniowane jako:

                  #define MAP_HUGE_2MB    (21 << MAP_HUGE_SHIFT)
                  #define MAP_HUGE_1GB    (30 << MAP_HUGE_SHIFT)

              Zakres  obsługiwanych  rozmiarów  dużych stron w systemie można sprawdzić, wypisując podkatalogi w
              katalogu /sys/kernel/mm/hugepages.

       MAP_LOCKED (od Linuksa 2.5.37)
              Oznacza mapowany obszar jako zablokowany w ten sam sposób, jak robi to mlock(2). Ta  implementacja
              postara się wypełnić (prefault) cały zakres, lecz wywołanie mmap() nie zawodzi z błędem ENOMEM gdy
              się to nie powiedzie. Z tego względu później mogą wystąpić główne chybienia stron (ang. major page
              fault).  Semantyka  ta nie jest zatem tak mocna jak mlock(2). Jeśli po zainicjowaniu mapowania nie
              są później dopuszczalne główne chybienia  stron,  należy  korzystać  w  zamian  z  mmap()  wraz  z
              mlock(2). Znacznik MAP_LOCKED jest ignorowany przez starsze jądra.

       MAP_NONBLOCK (od Linuksa 2.5.46)
              Znacznik  ten  ma  znaczenie  tylko w połączeniu z MAP_POPULATE. Nie przeprowadza odczytu naprzód:
              wpisy tablicy stron są tworzone tylko w przypadku stron, które są już obecne  w  RAM.  Od  Linuksa
              2.6.23,  znacznik  ten  nie  ma  wpływu  na MAP_POPULATE. W przyszłości, połączenie MAP_POPULATE z
              MAP_NONBLOCK może zostać na nowo zaimplementowane.

       MAP_NORESERVE
              Poleca nie rezerwować  przestrzeni  wymiany  dla  tego  mapowania.  Gdy  przestrzeń  wymiany  jest
              zarezerwowana,  ma  się  gwarancję,  że  istnieje  możliwość modyfikacji mapowania. Gdy przestrzeń
              wymiany nie jest zarezerwowana, można otrzymać  SIGSEGV  podczas  zapisu,  jeśli  braknie  pamięci
              fizycznej.  Proszę  zapoznać  się również z opisem pliku /proc/sys/vm/overcommit_memory w proc(5).
              Przed Linuksem 2.6, znacznik ten działał tylko dla prywatnych, zapisywalnych mapowań.

       MAP_POPULATE (od Linuksa 2.5.46)
              Wypełnia (prefault) tablice strony dla mapowania. W przypadku mapowania pliku, powoduje to  odczyt
              z  wyprzedzeniem  pliku. W ten sposób redukuje się blokowanie, przy późniejszych chybieniach stron
              (ang. page fault). Wywołanie mmap() nie zawodzi, jeśli nie  da  się  wypełnić  mapowania  (np.  ze
              względu  na  ograniczenie  liczby  mapowanych dużych (huge) stron, za pomocą MAP_HUGETLB). Obsługę
              MAP_POPULATE w połączeniu z mapowaniami prywatnymi dodano w Linuksie 2.6.23.

       MAP_STACK (od Linuksa 2.6.27)
              Przydziela mapowanie na adresie odpowiednim dla stosu: procesu lub wątku.

              Znacznik ten jest w Linuksie  instrukcją  pustą.  Jednak  podając  go,  przenośne  aplikacje  mogą
              zapewnić  zyskanie  obsługi  znacznika,  gdy  zostanie  on  w przyszłości zaimplementowany. Z tego
              względu  jest  używany  w  implementacji  wątkowania  glibc,  aby  uwzględnić  fakt,  że  niektóre
              architektury  mogą (w przyszłości) wymagać specjalnego traktowania przy alokowaniu stosu. Kolejnym
              powodem korzystania z tego znacznika jest przenośność: MAP_STACK istnieje (i działa) na niektórych
              innych systemach (np. niektórych BSD).

       MAP_SYNC (od Linuksa 4.15)
              Znacznik  ten  jest  dostępny  jedynie  z  typem  mapowania  MAP_SHARED_VALIDATE;  mapowania  typu
              MAP_SHARED po cichu go zignorują. Znacznik ten jest obsługiwany jedynie dla  plików  obsługujących
              DAX (bezpośrednie mapowanie do pamięci trwałej). W przypadku innych plików, utworzenie mapowania z
              tym znacznikiem spowoduje wystąpienie błędu EOPNOTSUPP.

              Dzielone mapowania pliku z tym znacznikiem zapewniają  gwarancję,  że  choć  pewna  część  pamięci
              będzie zmapowana jako zapisywalna w przestrzeni adresowej procesu, będzie ona widoczna w tym samym
              pliku, na tym samym przesunięciu, nawet po załamaniu lub przeładowaniu  systemu.  W  połączeniu  z
              odpowiednimi  instrukcjami  procesora,  użytkownicy  takich  mapowań  mają  zapewnioną lepszy tryb
              czynienia modyfikacji danych trwałymi.

       MAP_UNINITIALIZED (od Linuksa 2.6.33)
              Nie czyści stron anonimowych. Znacznik ten ma polepszyć  wydajność  na  urządzeniach  wbudowanych.
              Znacznik     jest     przestrzegany     tylko,     gdy     jądro     skonfigurowano     z    opcją
              CONFIG_MMAP_ALLOW_UNINITIALIZED. Ze względu na skutki w zakresie  bezpieczeństwa,  opcja  ta  jest
              zwykle  włączana  wyłącznie  na  urządzeniach  wbudowanych  (tj.  mających  całkowitą kontrolę nad
              zawartością pamięci użytkownika).

       Z powyższych znaczników, jedynie MAP_FIXED jest określony przez POSIX.1-2001  i  POSIX.1-2008.  Większość
       systemów obsługuje jednak także MAP_ANONYMOUS (lub jego synonim MAP_ANON).

   munmap()
       Wywołanie  systemowe  munmap() usuwa mapowanie z podanego zakresu adresów i powoduje, że dalsze odwołania
       do adresów z tego zakresu będą generować nieprawidłowe  odwołania  do  pamięci.  Mapowanie  obszaru  jest
       również  automatycznie  usuwane,  gdy proces się zakończy. Z drugiej strony, zamknięcie deskryptora pliku
       nie usuwa mapowania obszaru.

       Adres addr musi być wielokrotnością rozmiaru strony (ale length już nie  musi).  Usuwane  jest  mapowanie
       wszystkich  stron  zawierających  fragmenty ze wskazanego zakresu, wszystkie późniejsze odwołania do tych
       stron wygenerują SIGSEGV. Nie jest błędem, gdy brak w podanym zakresie zamapowanych stron.

WARTOŚĆ ZWRACANA

       Po pomyślnym zakończeniu  mmap()  zwraca  wskaźnik  do  mapowanego  obszaru.  Po  błędzie  zwracane  jest
       MAP_FAILED (tj. (void *) -1) i ustawiane errno, wskazując błąd.

       Po pomyślnym zakończeniu munmap() zwraca 0. Po błędzie zwracane jest -1 i ustawiane errno, wskazując błąd
       (prawdopodobnie 1EINVAL).

BŁĘDY

       EACCES Deskryptor pliku odnosi się do pliku innego niż zwykły plik. Lub zażądano mapowania pliku, lecz fd
              nie  jest  otwarty  do  odczytu.  Lub zażądano MAP_SHARED i ustawiono PROT_WRITE, lecz fd nie jest
              otwarte w trybie do odczytu i do zapisu (O_RDWR). Lub ustawiono PROT_WRITE, lecz plik jest otwarty
              tylko do dopisywania.

       EAGAIN Plik został zablokowany lub zablokowano zbyt wiele pamięci (zob. setrlimit(2)).

       EBADF  fd nie jest prawidłowym deskryptorem pliku (a nie ustawiono MAP_ANONYMOUS).

       EEXIST We  flags  podano MAP_FIXED_NOREPLACE, a zakres który opisuje addr i length koliduje z istniejącym
              mapowaniem.

       EINVAL Niewłaściwe addr, length lub offset (np. mogą być zbyt duże lub niewyrównane do granicy strony).

       EINVAL (od Linuksa 2.6.12)  length wynosiła 0.

       EINVAL We flags nie wystąpiło żadne z: MAP_PRIVATE, MAP_SHARED lub MAP_SHARED_VALIDATE.

       ENFILE Zostało osiągnięte systemowe ograniczenie na całkowitą liczbę otwartych plików.

       ENODEV System plików, na którym znajduje się podany plik, nie obsługuje mapowania w pamięci.

       ENOMEM Brak dostępnej pamięci.

       ENOMEM Doszłoby do przekroczenia maksymalnej liczby mapowań procesu. Błąd ten może wystąpić  również  dla
              munmap(),   przy   usuwaniu   mapowania  z  obszaru  w  środku  istniejącego  mapowania,  ponieważ
              spowodowałoby to powstanie dwóch mniejszych mapowań po obu stronach niezmapowanego obszaru.

       ENOMEM (od Linuksa 4.7)  Doszłoby do przekroczenia limitu RLIMIT_DATA procesu,  opisanego  w  podręczniku
              getrlimit(2).

       ENOMEM addr przekroczyłoby wirtualną przestrzeń adresową procesora.

       EOVERFLOW
              Na  architekturze  32-bitowej z rozszerzeniem dużych plików (tj. korzystając z 64-bitowego off_t):
              liczba stron użytych dla length wraz z liczbą stron użytych dla offset przepełniłaby  liczbę  typu
              unsigned long (32-bitową).

       EPERM  Argument  prot  pyta  o  PROT_EXEC  lecz mapowany obszar należy do pliku zamontowanego na systemie
              plików z opcją no-exec (bez zezwolenia na wykonywanie).

       EPERM  Operacja zablokowana, z powodu zapieczętowania pliku (ang. file seal); zob. fcntl(2).

       EPERM  Podano znacznik  MAP_HUGETLB,  lecz  wywołujący  nie  był  uprzywilejowany  (nie  miał  przywileju
              CAP_IPC_LOCK  (ang.  capability))  i  nie jest członkiem grupy sysctl_hugetlb_shm_group; zob. opis
              /proc/sys/vm/sysctl_hugetlb_shm_group w proc_sys(5).

       ETXTBSY
              Ustawiono MAP_DENYWRITE, lecz obiekt wskazywany przez fd jest otwarty do zapisu.

       Użycie zamapowanego obszaru może spowodować wystąpienie następujących sygnałów:

       SIGSEGV
              Próba zapisu do obszaru zmapowanego tylko do odczytu.

       SIGBUS Próba dostępu do strony bufora, która leży poza końcem mapowanego pliku.  Wyjaśnienie  traktowania
              bajtów  w  stronie, która odnosi się do końca mapowanego pliku i nie jest wielokrotnością rozmiaru
              strony zamieszczono w UWAGACH.

ATRYBUTY

       Informacje o pojęciach używanych w tym rozdziale można znaleźć w podręczniku attributes(7).

       ┌───────────────────────────────────────────────────────────────┬────────────────────────┬───────────────┐
       │InterfejsAtrybutWartość       │
       ├───────────────────────────────────────────────────────────────┼────────────────────────┼───────────────┤
       │mmap(), munmap()                                               │ Bezpieczeństwo wątkowe │ MT-bezpieczne │
       └───────────────────────────────────────────────────────────────┴────────────────────────┴───────────────┘

WERSJE

       Na niektórych architekturach sprzętowych  (np.  i386),  PROT_WRITE  wymusza  PROT_READ.  Od  architektury
       zależy,  czy  PROT_READ wymusza PROT_EXEC, czy nie. Programy przenośne powinny zawsze ustawiać PROT_EXEC,
       jeśli mają zamiar wykonywać kod w nowym mapowaniu.

       Przenośnym sposobem tworzenia mapowań jest podanie addr jako 0 (NULL) i pominięcie MAP_FIXED z  flags.  W
       takim  przypadku  to  system  wybierze  adres  mapowania;  wybrany adres uniknie konfliktu z istniejącymi
       mapowaniami i nie będzie wynosił 0. Jeśli podano znacznik MAP_FIXED , a addr wynosi 0 (NULL), to mapowany
       adres będzie wynosił 0 (NULL).

       Pewne  stałe  flags  są  zdefiniowane tylko wtedy, gdy zdefiniowano określone makro sprawdzania cech (być
       może stało się to domyślnie): _DEFAULT_SOURCE z glibc 2.19 lub późniejszymi; _BSD_SOURCE lub _SVID_SOURCE
       w  glibc  2.19  i wcześniejszych (podanie _GNU_SOURCE jest również wystarczające i wymaganie właśnie tego
       makra byłoby logiczniejsze, skoro wszystkie te znaczniki są typowo linuksowe).  Chodzi  tu  o  znaczniki:
       MAP_32BIT,  MAP_ANONYMOUS  (i  synonim MAP_ANON), MAP_DENYWRITE, MAP_EXECUTABLE, MAP_FILE, MAP_GROWSDOWN,
       MAP_HUGETLB, MAP_LOCKED, MAP_NONBLOCK, MAP_NORESERVE, MAP_POPULATE oraz MAP_STACK.

   Różnice biblioteki C/jądra
       Niniejszy podręcznik opisuje interfejs zapewniany przez funkcję opakowującą mmap() z  glibc.  Pierwotnie,
       funkcja  ta  przywoływała  wywołanie  systemowe  o tej samej nazwie. Od Linuksa 2.4, to wywołanie zostało
       zastąpione wywołaniem mmap2(2), dlatego obecnie funkcja opakowująca mmap() z glibc przywołuje mmap2(2)  z
       odpowiednio dostosowanymi wartościami offset.

STANDARDY

       POSIX.1-2008.

HISTORIA

       POSIX.1-2001, SVr4, 4.4BSD.

       W  systemach  POSIX,  na  których  dostępne  są  mmap(),  msync(2)  i  munmap(), _POSIX_MAPPED_FILES jest
       zdefiniowane w <unistd.h> na wartość większą niż 0 (zob. też sysconf(3)).

UWAGI

       Pamięć mapowana za pomocą mmap() jest zachowywana poprzez fork(2) z tymi samymi atrybutami.

       Plik jest mapowany w wielokrotnościach rozmiaru  strony.  Dla  plików,  które  nie  są  wielokrotnościami
       rozmiaru strony, pozostałe bajty w częściowej stronie na końcu mapowania są zerowane podczas mapowania, a
       modyfikacje tego obszaru nie  są  zapisywane  w  pliku.  Efekt  zmiany  rozmiaru  zamapowanego  pliku  na
       zamapowane strony, które odpowiadają dodanym lub usuniętym obszarom pliku, jest nieokreślony.

       Aplikacje  mogą  sprawdzić,  które  strony  mapowania są aktualnie rezydentne w buforze/buforze strony za
       pomocą mincore(2).

   Bezpieczne korzystanie z MAP_FIXED
       Jedyne bezpieczne zastosowanie MAP_FIXED jest wtedy, gdy podany za pomocą addr i  length  zakres  adresów
       był  uprzednio  zarezerwowany  przy  użyciu  innego  mapowania;  w  przeciwnym  przypadku  MAP_FIXED jest
       niebezpieczne,  ponieważ  przymusowo  usuwa  wcześniejsze  mapowania,  przez  co  w  przypadku   procesów
       wielowątkowych, łatwe staje się uszkodzenie swojej przestrzeni adresowej.

       Przykładowo  załóżmy,  że wątek A przegląda /proc/pid/maps, aby odszukać nieużywany zakres adresów, które
       można zmapować przy użyciu MAP_FIXED, a wątek B w tym samym czasie uzyska część lub  całość  tego  samego
       zakresu  adresów.  Gdy  wątek  A  następnie  użyje  mmap(MAP_FIXED),  efektywnie naruszy mapowanie, które
       utworzył wątek B. W opisywanym scenariuszu, wątek B nie musi bezpośrednio  tworzyć  mapowania;  wystarczy
       utworzenie  wywołania bibliotecznego, które wewnętrznie korzysta z dlopen(3) do załadowania jakiejś innej
       biblioteki współdzielonej. Wywołanie dlopen(3) zmapuje bibliotekę do przestrzeni  adresowej  procesu.  Co
       więcej,  niemal  każde  wywołanie biblioteczne może być zaimplementowane w sposób, który dodaje mapowania
       pamięci do przestrzeni adresowej, albo za pomocą tej techniki, albo jedynie alokując  pamięć.  Przykładem
       mogą być brk(2), malloc(3), pthread_create(3) i biblioteki PAM ⟨http://www.linux-pam.org⟩.

       Od  Linuksa  4.17,  program  wielowątkowy  może  skorzystać ze znacznika MAP_FIXED_NOREPLACE, aby uniknąć
       niebezpieczeństwa opisanego wyżej, przy tworzeniu mapowania pod  konkretnym  adresem,  który  nie  został
       zarezerwowany wcześniejszym mapowaniem.

   Zmiany znaczników czasu w przypadku mapowań opartych na plikach
       Dla  mapowań  opartych  na plikach pole st_atime zamapowanego pliku może zostać zaktualizowane w dowolnym
       momencie pomiędzy mmap() i usunięciem odpowiedniego mapowania; pierwsze odwołanie do  zamapowanej  strony
       spowoduje zaktualizowanie tego pola, jeśli nie stało się to wcześniej.

       Pola  st_ctime i st_mtime pliku zamapowanego z PROT_WRITE i MAP_SHARED zostanie zaktualizowane po zapisie
       do mapowanego obszaru, a przed późniejszym wywołaniem msync(2) ze znacznikiem MS_SYNC lub MS_ASYNC, jeśli
       taki wywołanie wystąpi.

   Mapowania dużych stron (Huge TLB)
       W  przypadku  mapowań  korzystających  z  dużych  (huge)  stron,  wymagania dotyczące argumentów mmap() i
       munmap() różnią się nieco, od wymagań mapowań, korzystających z natywnego systemowego rozmiaru strony.

       W przypadku mmap(), offset musi być wielokrotnością używanego rozmiaru dużej strony. System automatycznie
       wyrówna length do wielokrotności używanego rozmiaru dużej strony.

       W  przypadku  munmap(),  addr  i  length muszą być wielokrotnościami używanego systemowego rozmiaru dużej
       strony.

USTERKI

       W Linuksie, gwarancje zasugerowane powyżej w opisie MAP_NORESERVE nie istnieją. Domyślnie,  każdy  proces
       może być zabity w dowolnym momencie, gdy systemowi wyczerpie się pamięć.

       Przed Linuksem 2.6.7, znacznik MAP_POPULATE działał tylko, gdy prot określono jako PROT_NONE.

       SUSv3  określa, że mmap() powinno zawieść, gdy length wynosi 0. Jednak przed Linuksem 2.6.12, mmap() było
       w takim przypadku pomyślne: nie tworzono mapowania, a wywołanie zwracało addr. Od Linuksa 2.6.12,  mmap()
       zawodzi w takim przypadku z błędem EINVAL.

       POSIX  określa,  ze system powinien zawsze wypełniać zerami wszelkie strony częściowe na końcu obiektu, a
       system nigdy nie zapisze żadnych modyfikacji obiektu poza jego końcem. W Linuksie, jeśli zapisze się dane
       do  takiej  częściowej strony, poza końcem obiektu, dane pozostają w buforze strony nawet po zamknięciu i
       odmapowaniu pliku, a choć dane nigdy nie są zapisywane do samego pliku, kolejne mapowania  mogą  zobaczyć
       zmodyfikowaną  zawartość. W niektórych przypadkach, to zachowanie można poprawić wywołując msync(2) przed
       dokonaniem odmapowania; jednak nie działa to na tmpfs(5) (np. przy użyciu  interfejsu  pamięci  dzielonej
       POSIX opisanego w podręczniku shm_overview(7)).

PRZYKŁADY

       Poniższy  program  wypisuje  część  pliku,  określonego  w  jego pierwszym argumencie wiersza poleceń, na
       standardowe wyjście. Zakres wypisywanych bajtów podaje się za pomocą wartości przesunięcia i długości,  w
       drugim  i  trzecim argumencie wiersza poleceń. Program tworzy mapowania pamięci wymaganych stron pliku, a
       następnie używa write(2) do wypisania żądanych bajtów.

   Kod źródłowy programu
       #include <fcntl.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/mman.h>
       #include <sys/stat.h>
       #include <sys/types.h>
       #include <unistd.h>

       #define handle_error(msg) \
           do { perror(msg); exit(EXIT_FAILURE); } while (0)

       int
       main(int argc, char *argv[])
       {
           int          fd;
           char         *addr;
           off_t        offset, pa_offset;
           size_t       length;
           ssize_t      s;
           struct stat  sb;

           if (argc < 3 || argc > 4) {
               fprintf(stderr, "przesunięcie pliku %s [długość]\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           fd = open(argv[1], O_RDONLY);
           if (fd == -1)
               handle_error("open");

           if (fstat(fd, &sb) == -1)           /* Do pobrania rozmiaru pliku */
               handle_error("fstat");

           offset = atoi(argv[2]);
           pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
               /* przesunięcie dla mmap() musi być wyrównane do strony */

           if (offset >= sb.st_size) {
               fprintf(stderr, "przesunięcie za końcem pliku\n");
               exit(EXIT_FAILURE);
           }

           if (argc == 4) {
               length = atoi(argv[3]);
               if (offset + length > sb.st_size)
                   length = sb.st_size - offset;
                       /* Nie można wypisać bajtów poza końcem pliku */

           } else {    /* Brak arg. długości ==> wyświetl do końca pliku */
               length = sb.st_size - offset;
           }

           addr = mmap(NULL, length + offset - pa_offset, PROT_READ,
                       MAP_PRIVATE, fd, pa_offset);
           if (addr == MAP_FAILED)
               handle_error("mmap");

           s = write(STDOUT_FILENO, addr + offset - pa_offset, length);
           if (s != length) {
               if (s == -1)
                   handle_error("write");

               fprintf(stderr, "częściowy zapis");
               exit(EXIT_FAILURE);
           }

           munmap(addr, length + offset - pa_offset);
           close(fd);

           exit(EXIT_SUCCESS);
       }

ZOBACZ TAKŻE

       ftruncate(2), getpagesize(2), memfd_create(2), mincore(2), mlock(2),  mmap2(2),  mprotect(2),  mremap(2),
       msync(2), remap_file_pages(2), setrlimit(2), shmat(2), userfaultfd(2), shm_open(3), shm_overview(7)

       Opis poniższych plików w proc(5): /proc/pid/maps, /proc/pid/map_files i /proc/pid/smaps.

       B.O. Gallmeister, POSIX.4, O'Reilly, str. 128–129 i 389–391.

TŁUMACZENIE

       Autorami  polskiego  tłumaczenia  niniejszej  strony podręcznika są: Przemek Borys <pborys@dione.ids.pl>,
       Andrzej Krzysztofowicz <ankry@green.mf.pg.gda.pl> 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 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ 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⟩.