¿Cuál es la diferencia entre MAP_SHARED y MAP_PRIVATE en la función mmap?

3 minutos de lectura

avatar de usuario de ntl0ve
ntl0ve

jugando con mmap por diversión, tengo el siguiente código:

(.. snip ..)
fd = open("/home/me/straight_a.txt", O_RDONLY);
if (fd == -1) {
    perror("open");
    exit(1);
}

m = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0);

if (m == MAP_FAILED) {
    perror("mmap");
    exit(1);
}

printf("m is %p\n", m);

printf("*m = %c\n", *m);
printf("*(m+1) = %c\n", *(m+1));
(.. snip ..)

Esto funciona como se esperaba. Pero antes de llegar a esto, intenté…

m = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, 0);

… y mmap se equivocó con:

mmap: Permission denied

En general, ¿cuál es la diferencia entre las dos banderas (la página del manual no es demasiado generosa en este tema)? ¿Qué tipo de permiso (y dónde) me estoy perdiendo?

EDITAR

Como suele suceder… lo descubrí parcialmente.

resulta open necesitaba un O_RDWR bandera.

Entonces, ¿estoy en lo correcto al suponer que:

  • MAP_PRIVATE: ¿los cambios se realizan solo en la memoria, no se guardan en el disco?
  • MAP_SHARED: los cambios se guardarán en el disco…

… pero no estoy guardando nada en el disco en ninguna parte, pensé? Solo operando en la memoria.

  • , O_RDONLY); El archivo es de solo lectura. No se puede utilizar como almacenamiento de respaldo para un PROT_READ|PROT_WRITE área mmap()ed porque no se puede escribir. los MAP_PRIVATE el mapeo no necesita escribir en el archivo (el archivo solo se usa para leer, presumiblemente por COW) Nota: no esperaría que la expansión de tilde funcione para open(2). Me sorprendería si funciona.

    – salvaje

    1 de marzo de 2012 a las 16:12


  • Correcto, era solo una forma rápida de sacar el directorio base real de allí, ni siquiera lo pensó. Gracias, corregido en aras de la corrección.

    – ntl0ve

    1 de marzo de 2012 a las 19:42

Abrió el archivo en modo de solo lectura. Luego intentó mmmap parte de él en modo de lectura/escritura con MAP_SHARED establecido. En este contexto, MAP_SHARED implica que si escribe en la región mmap’d, sus cambios se confirmarán nuevamente en el archivo mapeado. No puede hacer esto porque abrió el archivo en modo de solo lectura.

MAP_PRIVATE funciona porque las escrituras en la región mmap’d no se confirman en el archivo original. Cuando escribe en la región, las páginas en las que se escribieron se copian en una región diferente de la memoria, posiblemente respaldada por espacio de intercambio.

Las escrituras en un segmento MAP_SHARED se transfieren al archivo subyacente. Abrió el archivo con O_RDONLY, lo que entra en conflicto con el indicador PROT_WRITE, lo que impide que MAP_SHARED pueda volver a escribir en el archivo.

MAP_PRIVATE no realiza escrituras en el archivo subyacente, por lo que el hecho de que haya abierto el archivo O_RDONLY no es un problema.

  • ¿Cuándo se confirman mis cambios en la memoria en el disco? ¿Tengo que llamar o es automático? Si es así, ¿algún almacenamiento en búfer?

    – ntl0ve

    1 de marzo de 2012 a las 16:17


  • Respuesta corta: no lo sabes. Cualquier cosa entre ahora y la eternidad. munmap() puede vaciar los búferes del disco, dependiendo de la fase de la luna.

    – salvaje

    1 de marzo de 2012 a las 16:20

  • Entiendo. También se encontró msync, que promete forzar una descarga/sincronización. Gracias.

    – ntl0ve

    1 de marzo de 2012 a las 16:23

  • @wildplasser En mi experiencia, munmap() nunca vacía los búferes. Por lo tanto, puede usar mmap/munmap para implementar ventanas de espacio de direcciones cuando la memoria física excede el espacio de direcciones de la memoria virtual.

    – Karunski

    1 de marzo de 2012 a las 18:20

  • Eso es correcto. Simplemente los deja en la cola de escritura (si están sucios) MAP_SYNC hará que munmap() se bloquee hasta que realmente se escriban (al igual que msync()). Esa es la fase de la luna parte de la historia.

    – salvaje

    1 de marzo de 2012 a las 18:50

¿Ha sido útil esta solución?