Provided by: manpages-pl-dev_4.23.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⟩.