mmmapa - mmap

W computing , mmap(2)jest POSIX zgodny ze Unix wywołanie systemowe , które odwzorowuje plików lub urządzeń w pamięci. Jest to metoda operacji wejścia/wyjścia plików mapowanych w pamięci . Implementuje stronicowanie na żądanie, ponieważ zawartość pliku nie jest odczytywana bezpośrednio z dysku i początkowo w ogóle nie korzysta z fizycznej pamięci RAM. Rzeczywiste odczyty z dysku są wykonywane w sposób " leniwy ", po uzyskaniu dostępu do określonej lokalizacji. Gdy pamięć nie jest już potrzebna, ważne jest, aby munmap(2)wskaźniki do niej. Informacje o ochronie można zarządzać za pomocą mprotect(2), a specjalne traktowanie można wymusić za pomocą madvise(2).

W systemie Linux , macOS i BSD , mmapmożna tworzyć kilka typów mapowań. Inne systemy operacyjne mogą obsługiwać tylko ich część; na przykład współdzielone mapowania mogą nie być praktyczne w systemie operacyjnym bez globalnej pamięci podręcznej VFS lub we/wy.

Historia

Oryginalny projekt plików mapowanych w pamięci pochodził z systemu operacyjnego TOPS-20 . mmapi powiązane wywołania systemowe zostały zaprojektowane jako część wersji Unix Berkeley Software Distribution (BSD). Ich API zostało już opisane w Podręczniku Systemu 4.2BSD, mimo że nie zostało ani zaimplementowane w tym wydaniu, ani w 4.3BSD. Firma Sun Microsystems zaimplementowała ten sam interfejs API w swoim systemie operacyjnym SunOS . Deweloperzy BSD z UC Berkeley poprosili firmę Sun o przekazanie jej implementacji, ale rozmowy te nigdy nie doprowadziły do ​​przekazania kodu; 4.3BSD-Reno został dostarczony z implementacją opartą na systemie pamięci wirtualnej Macha .

Poparte plikami i anonimowe

Mapowanie oparte na plikach mapuje obszar pamięci wirtualnej procesu na pliki; tj. czytanie tych obszarów pamięci powoduje odczytanie pliku. Jest to domyślny typ mapowania.

Mapowanie anonimowe mapuje obszar pamięci wirtualnej procesu, który nie jest poparty żadnym plikiem. Zawartość jest inicjowana na zero. Pod tym względem mapowanie anonimowe jest podobne do malloci jest używane w niektórych malloc(3)implementacjach dla określonych alokacji. Jednak mapowania anonimowe nie są częścią standardu POSIX, chociaż są implementowane przez prawie wszystkie systemy operacyjne przez flagi MAP_ANONYMOUSi MAP_ANON.

Widoczność pamięci

Jeśli mapowanie jest współdzielone ( MAP_SHAREDflaga jest ustawiona), to jest zachowywane przez wywołanie systemowe fork(2) . Oznacza to, że zapisy w zmapowanym obszarze w jednym procesie są natychmiast widoczne we wszystkich powiązanych procesach (rodzic, dziecko lub rodzeństwie). Jeśli mapowanie jest współdzielone i wspierane przez plik (nie MAP_ANONYMOUS), na nośniku pliku bazowego jest zagwarantowane, że zostanie zapisany dopiero po wykonaniu msync(2).

Jeśli mapowanie jest prywatne ( MAP_PRIVATEflaga jest ustawiona), zmiany nie będą widoczne dla innych procesów ani zapisane w pliku.

Proces odczytujący lub zapisujący plik bazowy nie zawsze będzie widział te same dane, co proces, który zmapował plik, ponieważ segment pliku jest kopiowany do pamięci RAM i okresowo opróżniany na dysk. Synchronizację można wymusić msyncwywołaniem systemowym.

Pliki mmap(2)ing mogą znacznie zmniejszyć obciążenie pamięci dla aplikacji uzyskujących dostęp do tego samego pliku; mogą dzielić obszar pamięci, który obejmuje plik, zamiast ładować plik dla każdej aplikacji, która chce do niego uzyskać dostęp. Oznacza to, że mmap(2) jest czasami używany do komunikacji międzyprocesowej (IPC). W nowoczesnych systemach operacyjnych , mmap (2) jest zwykle korzystne z System V IPC Shared Memory obiektu.

Główną różnicą między pamięcią współdzieloną Systemu V (shmem) a mapowaniem we/wy (mmap) jest to, że pamięć współdzielona Systemu V jest trwała: jeśli nie zostanie wyraźnie usunięta przez proces, jest przechowywana w pamięci i pozostaje dostępna do momentu zamknięcia systemu . Pamięć mmap nie jest trwała między wykonaniami aplikacji (chyba że jest wspierana przez plik).

Przykład użycia w ramach języka programowania C

#include <sys/types.h>
#include <sys/mman.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/* This example shows how an mmap of /dev/zero is equivalent to
   using anonymous memory (MAP_ANON) not connected to any file.
   N.B. MAP_ANONYMOUS or MAP_ANON are supported by most UNIX
   versions, removing the original purpose of /dev/zero.
*/
/* Does not work on OS X or macOS, where you can't mmap over /dev/zero */
int main(void)
{
        const char str1[] = "string 1";
        const char str2[] = "string 2";
        pid_t parpid = getpid(), childpid;
        int fd = -1;
        char *anon, *zero;

        if ((fd = open("/dev/zero", O_RDWR, 0)) == -1)
                err(1, "open");

        anon = (char*)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
        zero = (char*)mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

        if (anon == MAP_FAILED || zero == MAP_FAILED)
                errx(1, "either mmap");

        strcpy(anon, str1);
        strcpy(zero, str1);

        printf("PID %d:\tanonymous %s, zero-backed %s\n", parpid, anon, zero);
        switch ((childpid = fork())) {
        case -1:
                err(1, "fork");
                /* NOTREACHED */
        case 0:
                childpid = getpid();
                printf("PID %d:\tanonymous %s, zero-backed %s\n", childpid, anon, zero);
                sleep(3);

                printf("PID %d:\tanonymous %s, zero-backed %s\n", childpid, anon, zero);
                munmap(anon, 4096);
                munmap(zero, 4096);
                close(fd);
                return EXIT_SUCCESS;
        }

        sleep(2);
        strcpy(anon, str2);
        strcpy(zero, str2);

        printf("PID %d:\tanonymous %s, zero-backed %s\n", parpid, anon, zero);
        munmap(anon, 4096);
        munmap(zero, 4096);
        close(fd);
        return EXIT_SUCCESS;
}

przykładowe dane wyjściowe:

PID 22475:      anonymous string 1, zero-backed string 1
PID 22476:      anonymous string 1, zero-backed string 1
PID 22475:      anonymous string 2, zero-backed string 2
PID 22476:      anonymous string 2, zero-backed string 2

Zobacz też

Bibliografia

Dalsza lektura