Necesito un tamaño de copia de un archivo mmap muy grande al tiempo que permite el acceso simultáneo a los hilos del lector.Cambio de tamaño rápido de un archivo mmap
La manera simple es usar dos asignaciones MAP_SHARED (crecer el archivo, luego crear una segunda asignación que incluya la región crecida) en el mismo proceso sobre el mismo archivo y luego desasignar el mapeo antiguo una vez que todos los lectores puedan acceder estan terminados. Sin embargo, tengo curiosidad por saber si el esquema a continuación podría funcionar, y si es así, ¿hay alguna ventaja?
- mmap un archivo con MAP_PRIVATE
- do acceso de sólo lectura a esta memoria en múltiples hilos
- o bien adquirir un mutex para el archivo, escribir en la memoria (se supone esto se hace de una manera que la los lectores, que pueden estar leyendo esa memoria, no se equivocan)
- o adquieren el mutex, pero aumentan el tamaño del archivo y usan mremap para moverlo a una nueva dirección (cambiar el tamaño de la asignación sin copiar o archivo innecesario IO.)
La parte loca aparece en (4). Si mueve la memoria, las direcciones antiguas se vuelven inválidas y los lectores que todavía la están leyendo pueden tener una infracción de acceso repentinamente. ¿Qué pasa si modificamos los lectores para atrapar esta violación de acceso y luego reiniciamos la operación (es decir, no volver a leer la dirección incorrecta, volver a calcular la dirección dada la compensación y la nueva dirección base de mremap). Sí, sé que eso es malo pero, en mi opinión, los lectores solo pueden leer con éxito los datos en la dirección anterior o pueden fallar con una infracción de acceso y volver a intentarlo. Si se tiene suficiente cuidado, debe estar seguro. Como el redimensionamiento no ocurriría a menudo, los lectores eventualmente tendrían éxito y no se quedarían atrapados en un ciclo de reintento.
Puede producirse un problema si se vuelve a utilizar ese antiguo espacio de direcciones mientras el lector todavía tiene un puntero al mismo. Entonces no habrá violación de acceso, pero los datos serán incorrectos y el programa ingresará a la tierra unicornio y llena de dulces de comportamiento indefinido (donde generalmente no hay unicornios ni caramelos).
Pero si controlas las asignaciones completamente y podrías asegúrese de que las asignaciones que suceden durante este período no vuelvan a usar ese espacio de direcciones anterior, entonces esto no debería ser un problema y el comportamiento no debería estar indefinido.
¿Estoy en lo cierto? Podría esto funcionar? ¿Hay alguna ventaja en esto sobre el uso de dos asignaciones MAP_SHARED?
Puede usar un bloqueo de lectura/escritura y proteger la reasignación bajo el bloqueo de escritura, ¿no? – fge
Supongo que el cuello de botella es el disco. ¿Estás seguro de que vale la pena el problema? copiar archivos enormes del disco siempre lleva tiempo, porque los discos son dispositivos mecánicos lentos. –
fge, sí, pero el bloqueo de los hilos de lectura está fuera de cuestión en este caso – Eloff