Os arquivos mapeados na memória podem ser usados para substituir o acesso de leitura / gravação ou para oferecer suporte ao compartilhamento simultâneo. Quando você os usa para um mecanismo, obtém o outro também.
Em vez de procurar, escrever e ler um arquivo, você o mapeia na memória e simplesmente acessa os bits onde espera que estejam.
Isso pode ser muito útil e, dependendo da interface da memória virtual, pode melhorar o desempenho. A melhoria de desempenho pode ocorrer porque o sistema operacional agora consegue gerenciar esse antigo "arquivo de E / S" junto com todos os outros acessos à memória programática e pode (em teoria) aproveitar os algoritmos de paginação e assim por diante que já está usando para oferecer suporte memória virtual para o resto do programa. No entanto, depende da qualidade do seu sistema de memória virtual subjacente. Eu ouvi dizer que os sistemas de memória virtual Solaris e * BSD podem apresentar melhorias de desempenho melhores do que o sistema VM do Linux - mas não tenho dados empíricos para fazer backup disso. YMMV.
A simultaneidade entra em cena quando você considera a possibilidade de vários processos usando o mesmo "arquivo" por meio da memória mapeada. No modelo de leitura / gravação, se dois processos gravassem na mesma área do arquivo, você poderia ter quase certeza de que um dos dados do processo chegaria no arquivo, sobrescrevendo os dados do outro processo. Você conseguiria um ou outro - mas não uma mistura estranha. Tenho que admitir que não tenho certeza se esse é um comportamento exigido por algum padrão, mas é algo em que você poderia confiar. (Na verdade, é uma boa pergunta de acompanhamento!)
No mundo mapeado, em contraste, imagine dois processos, ambos "escrevendo". Eles fazem isso fazendo "armazenamentos de memória", o que resulta na paginação O / S dos dados para o disco - eventualmente. Mas, enquanto isso, podem ocorrer gravações sobrepostas.
Aqui está um exemplo. Digamos que eu tenha dois processos gravando 8 bytes no deslocamento 1024. O processo 1 está gravando '11111111' e o processo 2 está gravando '22222222'. Se eles usam I / O de arquivo, então você pode imaginar, no fundo do O / S, há um buffer cheio de 1s e um buffer cheio de 2s, ambos indo para o mesmo lugar no disco. Um deles vai chegar lá primeiro, e o outro um segundo. Nesse caso, o segundo ganha. No entanto , se estou usando a abordagem de arquivo mapeado por memória, o processo 1 vai para um armazenamento de memória de 4 bytes, seguido por outro armazenamento de memória de 4 bytes (vamos supor que esse não seja o tamanho máximo de armazenamento de memória). O processo 2 fará a mesma coisa. Com base em quando os processos são executados, você pode esperar ver qualquer um dos seguintes:
11111111
22222222
11112222
22221111
A solução para isso é usar a exclusão mútua explícita - o que provavelmente é uma boa ideia em qualquer caso. De qualquer forma, você estava confiando no O / S para fazer "a coisa certa" no caso de I / O de arquivo de leitura / gravação.
A primitiva de exclusão mútua de classificação é o mutex. Para arquivos mapeados na memória, sugiro que você olhe para um mutex mapeado na memória, disponível usando (por exemplo) pthread_mutex_init ().
Edite com uma pegadinha: Quando você está usando arquivos mapeados, existe a tentação de incorporar ponteiros para os dados no arquivo, no próprio arquivo (pense na lista vinculada armazenada no arquivo mapeado). Você não quer fazer isso, pois o arquivo pode ser mapeado em diferentes endereços absolutos em momentos diferentes ou em processos diferentes. Em vez disso, use deslocamentos dentro do arquivo mapeado.