mmap - mmap

Na computação , mmap(2)é uma chamada de sistema Unix compatível com POSIX que mapeia arquivos ou dispositivos na memória. É um método de E / S de arquivo mapeado em memória . Ele implementa paginação por demanda porque o conteúdo do arquivo não é lido diretamente do disco e, inicialmente, não usa RAM física. As leituras reais do disco são realizadas de maneira " preguiçosa ", depois que um local específico é acessado. Depois que a memória não for mais necessária, é importante que os apontem. As informações de proteção podem ser gerenciadas usando e um tratamento especial pode ser aplicado usando . munmap(2)mprotect(2)madvise(2)

No Linux , macOS e BSDs , mmappode-se criar vários tipos de mapeamentos. Outros sistemas operacionais podem suportar apenas um subconjunto deles; por exemplo, mapeamentos compartilhados podem não ser práticos em um sistema operacional sem um VFS global ou cache de E / S.

História

O design original dos arquivos mapeados na memória veio do sistema operacional TOPS-20 . mmape as chamadas de sistemas associadas foram projetadas como parte da versão Berkeley Software Distribution (BSD) do Unix. A API deles já foi descrita no Manual do Sistema 4.2BSD, embora não tenha sido implementado naquela versão, nem no 4.3BSD. A Sun Microsystems implementou essa mesma API, no entanto, em seu sistema operacional SunOS . Os desenvolvedores BSD da UC Berkeley solicitaram à Sun que doasse sua implementação, mas essas conversas nunca levaram a qualquer transferência de código; O 4.3BSD-Reno foi distribuído com uma implementação baseada no sistema de memória virtual do Mach .

Apoiado em arquivos e anônimo

O mapeamento baseado em arquivo mapeia uma área da memória virtual do processo para arquivos; ou seja, a leitura dessas áreas da memória faz com que o arquivo seja lido. É o tipo de mapeamento padrão.

O mapeamento anônimo mapeia uma área da memória virtual do processo sem suporte de nenhum arquivo. O conteúdo é inicializado em zero. Nesse aspecto, um mapeamento anônimo é semelhante malloce é usado em algumas malloc(3)implementações para certas alocações. No entanto, os mapeamentos anônimos não fazem parte do padrão POSIX, embora implementados por quase todos os sistemas operacionais pelos sinalizadores MAP_ANONYMOUSe MAP_ANON.

Visibilidade da memória

Se o mapeamento for compartilhado (o MAP_SHAREDsinalizador está definido), ele será preservado em uma chamada de sistema fork (2) . Isso significa que as gravações em uma área mapeada em um processo são imediatamente visíveis em todos os processos relacionados (pai, filho ou irmão). Se o mapeamento for compartilhado e apoiado por um arquivo (não MAP_ANONYMOUS), a mídia de arquivo subjacente só será gravada após o msync (2) ser editado.

Se o mapeamento for privado (o MAP_PRIVATEsinalizador está definido), as alterações não serão vistas por outros processos nem gravadas no arquivo.

Um processo de leitura ou gravação do arquivo subjacente nem sempre verá os mesmos dados de um processo que mapeou o arquivo, uma vez que o segmento do arquivo é copiado para a RAM e periodicamente liberado para o disco. A sincronização pode ser forçada com a msyncchamada do sistema.

Os arquivos mmap (2) podem reduzir significativamente a sobrecarga de memória para aplicativos que acessam o mesmo arquivo; eles podem compartilhar a área de memória que o arquivo abrange, em vez de carregar o arquivo para cada aplicativo que deseja acessá-lo. Isso significa que o mmap (2) às vezes é usado para comunicação entre processos (IPC). Em sistemas operacionais modernos , o mmap (2) é normalmente preferido ao recurso de memória compartilhada IPC do System V.

A principal diferença entre a memória compartilhada do System V (shmem) e a memória I / O mapeada (mmap) é que a memória compartilhada do System V é persistente: a menos que explicitamente removida por um processo, ela é mantida na memória e permanece disponível até que o sistema seja desligado . A memória mmap não é persistente entre as execuções do aplicativo (a menos que seja apoiada por um arquivo).

Exemplo de uso na linguagem de programação 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;
}

saída de amostra:

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

Veja também

Referências

Leitura adicional