Kiedy należy używać mmap do dostępu do plików?

Środowiska POSIX zapewniają co najmniej dwa sposoby dostępu do plików. Są standardowe wywołania systemoweopen(), read(), write(), i znajomych, ale jest też opcja użycia mmap() do mapowania pliku do pamięci wirtualnej.

Kiedy lepiej jest używać jednego nad drugim? Jakie są ich indywidualne zalety, które zasługują w tym dwa interfejsy?

Author: Peter Burns, 2008-11-03

6 answers

mmap jest świetny, jeśli masz wiele procesów, które uzyskują dostęp do danych w trybie tylko do odczytu z tego samego pliku, co jest powszechne w systemach serwerowych, które piszę. mmap pozwala wszystkim tym procesom na współdzielenie tych samych stron pamięci fizycznej, oszczędzając dużo pamięci.

mmap umożliwia również systemowi operacyjnemu optymalizację operacji stronicowania. Na przykład rozważmy dwa programy; program A, który odczytuje plik 1MB do bufora tworzonego za pomocą malloc, oraz program B, który mmaps plik 1MB do pamięci. Jeśli system operacyjny musi zamienić część pamięci A Na Zewnątrz, musi zapisać zawartość bufora do wymiany, zanim będzie mógł ponownie użyć pamięci. W przypadku B wszystkie niezmodyfikowane strony mmap'd mogą być natychmiast ponownie użyte, ponieważ system operacyjny wie, jak przywrócić je z istniejącego pliku, z którego były mmap'D. (System Operacyjny może wykryć, które strony nie są modyfikowane, początkowo oznaczając zapisywalne strony mmap ' D jako Tylko do odczytu i wychwytywając błędy segmentu , podobne do Copy on Write strategy).

mmap jest również przydatny do komunikacji między procesami . Możesz mmap plik jako odczyt / zapis w procesach, które muszą się komunikować, a następnie użyć prymitywów synchronizacji w regionie mmap'd (do tego służy znacznik MAP_HASSEMAPHORE).

Jedno miejsce mmap może być niezręczne, jeśli potrzebujesz pracować z bardzo dużymi plikami na 32-bitowej maszynie. To dlatego, że mmap musi znaleźć sąsiadujący blok adresów w Twoim procesie przestrzeń adresowa, która jest wystarczająco duża, aby zmieścić cały zakres mapowanego pliku. Może to stanowić problem, jeśli przestrzeń adresowa ulegnie fragmentacji, gdzie może być 2 GB wolnej przestrzeni adresowej, ale żaden jej indywidualny zakres nie zmieści się w mapowaniu plików 1 GB. W takim przypadku może być konieczne zmapowanie pliku w mniejszych kawałkach, niż chcesz, aby pasował.

Kolejną potencjalną niezręcznością z mmap jako zamiennikiem odczytu / zapisu jest to, że musisz rozpocząć mapowanie na offsetach rozmiaru strony. Jeśli chcesz tylko uzyskać dane z offsetu X, musisz poprawić ten offset, aby był kompatybilny z mmap.

I wreszcie, Odczyt / Zapis to jedyny sposób, w jaki możesz pracować z niektórymi typami plików. mmap nie może być używany na rzeczach takich jak rury i ttys .

 314
Author: Don Neufeld,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-20 08:21:49

Jednym z obszarów, w którym mmap () nie jest zaletą, było czytanie małych plików (poniżej 16K). Narzut błędu strony w celu odczytania całego Pliku był bardzo wysoki w porównaniu z pojedynczym wywołaniem systemowym read (). Dzieje się tak dlatego, że jądro może czasami zaspokoić odczyt w całości w plasterku czasu, co oznacza, że kod nie przełączy się. W przypadku błędu strony wydawało się bardziej prawdopodobne, że zaplanowany zostanie inny program, co sprawi, że operacja pliku będzie miała większe opóźnienie.

 71
Author: Ben Combee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-03 22:16:38

mmap ma tę zaletę, gdy masz losowy dostęp do dużych plików. Kolejną zaletą jest to, że uzyskujesz do niego dostęp za pomocą operacji pamięci (memcpy, arytmetyka wskaźników), bez zawracania sobie głowy buforowaniem. Normalne wejścia / wyjścia mogą być czasami dość trudne przy użyciu buforów, gdy masz struktury większe niż bufor. Kod do obsługi, który często jest trudny do uzyskania, mmap jest na ogół łatwiejszy. To powiedziawszy, istnieją pewne pułapki podczas pracy z mmap. Jak już ludzie wspominali, mmap jest dość kosztowny w konfiguracji, więc warto go używać tylko dla danego rozmiaru(w zależności od maszyny).

Dla czystego dostępu sekwencyjnego do pliku, nie zawsze jest to lepsze rozwiązanie, chociaż odpowiednie wywołanie madvise może złagodzić problem.

Musisz być ostrożny z ograniczeniami wyrównania w Twojej architekturze (SPARC, itanium), przy odczycie/zapisie IO bufory są często prawidłowo wyrównane i nie zatrzymują się podczas odwoływania się do rzuconego wskaźnika.

Ty należy również uważać, aby nie uzyskać dostępu poza mapą. Może się to łatwo zdarzyć, jeśli używasz funkcji łańcuchowych na mapie, a Twój plik nie zawiera \0 na końcu. Będzie to działać przez większość czasu, gdy Rozmiar pliku nie jest wielokrotnością rozmiaru strony, ponieważ ostatnia strona jest wypełniona 0 (zmapowany obszar jest zawsze w rozmiarze wielokrotności rozmiaru strony).

 47
Author: Patrick Schlüter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-02 13:22:56

Oprócz innych ładnych odpowiedzi, cytat z programowanie systemu Linux napisany przez eksperta Google Roberta Love:

Zalety mmap( )

Manipulowanie plikami za pomocą mmap( ) mA garść zalet nad standardowe wywołania systemowe read( ) i write( ). Wśród nich są:

  • Odczyt i zapis do pliku mapowanego pamięcią pozwala uniknąć Kopia zewnętrzna, która występuje podczas korzystania z systemu read( ) lub {[3] } wywołania, gdzie dane musi być skopiowany do i z bufora przestrzeni użytkownika.

  • Oprócz potencjalnych błędów strony, odczyt i zapis do pliku mapowanego pamięcią nie powoduje wywołania systemowego ani przełącznika kontekstowego nad głową. Jest to tak proste, jak dostęp do pamięci.

  • Gdy wiele procesów mapuje ten sam obiekt do pamięci, dane są współdzielone między wszystkimi procesami. Tylko do odczytu i współdzielony zapisywalny mapowania są udostępniane w całości; prywatne mapowania zapisywalne mają ich Nie-jeszcze-krowa (copy-on-write) strony udostępnione.

  • Szukanie wokół mapowania wymaga trywialnych manipulacji wskaźnikami. Nie ma potrzeby wywołania systemowego lseek( ).

Z tych powodów, mmap( ) jest dobrym wyborem dla wielu aplikacji.

Wady mmap( )

Istnieje kilka punktów, o których należy pamiętać podczas używania mmap( ):

  • Mapowania pamięci są zawsze liczbą całkowitą stron w rozmiarze. Tak więc, różnica między rozmiarem pliku kopii zapasowej a liczba całkowita stron jest "marnowana" jako slack space. Dla małych plików, a znaczna część mapowania może zostać zmarnowana. Na przykład z Strony 4 KB, mapowanie 7 bajtów zajmuje 4089 bajtów.

  • Mapowanie pamięci musi mieścić się w przestrzeni adresowej procesu. Z 32-bitową przestrzenią adresową, bardzo dużą liczbą mapowań różnej wielkości może spowodować fragmentację przestrzeni adresowej, co utrudnia znajdź Duże wolne sąsiadujące ze sobą regiony. Ten problem, oczywiście, jest dużo mniej widoczne z 64-bitową przestrzenią adresową.

  • Tworzenie i utrzymywanie mapowań pamięci i powiązanych struktur danych wewnątrz jądra jest kosztowne. Ten napowietrzny jest generalnie wyeliminowane przez wyeliminowanie podwójnego egzemplarza wymienionego w poprzedniej sekcji, szczególnie dla większych i często dostępnych pliki.

Z tych powodów korzyści z mmap( ) są najbardziej / align = "left" / gdy zmapowany plik jest duży (a więc każda zmarnowana przestrzeń jest mała procent całkowitego mapowania), lub gdy całkowity rozmiar mapowanego plik jest równomiernie podzielny przez rozmiar strony (a więc nie ma zmarnowanego miejsce).

 34
Author: Miljen Mikic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-20 18:20:44

Mapowanie pamięci ma potencjał ogromnej przewagi prędkości w porównaniu z tradycyjnym IO. Pozwala systemowi operacyjnemu odczytać dane z pliku źródłowego podczas dotykania stron w pliku mapowanym pamięcią. Działa to poprzez tworzenie stron błędów, które System operacyjny wykrywa, a następnie automatycznie ładuje odpowiednie dane z pliku.

Działa to tak samo jak mechanizm stronicowania i jest zwykle zoptymalizowany pod kątem szybkich wejść / wyjść poprzez odczyt danych o granicach i rozmiarach stron systemu (Zwykle 4K) - rozmiar, do którego zoptymalizowana jest większość pamięci podręcznych systemu plików.

 14
Author: AndyG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-07 23:28:09

Zaletą, która nie została jeszcze wymieniona, jest zdolność mmap() do utrzymywania mapowania tylko do odczytu jakoczystych stron . Jeśli przydziela się bufor w przestrzeni adresowej procesu, to używa read() do wypełnienia bufora z pliku, strony pamięci odpowiadające temu buforowi są teraz brudne , ponieważ zostały zapisane.

Brudne strony nie mogą być wyrzucane z pamięci RAM przez jądro. Jeśli istnieje przestrzeń wymiany, mogą zostać wezwane do wymiany. Ale jest to kosztowne i na niektórych systemach, takie jak małe urządzenia wbudowane z tylko pamięcią flash, nie ma wymiany w ogóle. W takim przypadku bufor zostanie zablokowany w pamięci RAM do czasu zakończenia procesu, lub być może zwróci go za pomocą madvise().

Nie zapisane na mmap() strony są czyste. Jeśli jądro potrzebuje pamięci RAM, może je po prostu upuścić i użyć pamięci RAM, w której znajdowały się strony. Jeśli proces, który miał mapowanie, uzyska do niego dostęp ponownie, spowoduje to błąd strony, jądro ponownie ładuje strony z pliku, z którego pochodzą. Tak samo jak oni / align = "left" /

To nie wymaga więcej niż jednego procesu używającego zmapowanego pliku, aby być zaletą.

 3
Author: TrentP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-17 06:04:47