Comprender las escrituras simultáneas de archivos de múltiples procesos
⏰ 8 minutos de lectura
jitihsk
Desde aquí: ¿Es el archivo adjunto atómico en UNIX?
Considere un caso en el que múltiples procesos abren el mismo archivo y lo agregan. O_APPEND garantiza que buscar hasta el final del archivo y luego comenzar la operación de escritura es atómico. Por lo tanto, varios procesos pueden agregarse al mismo archivo y ningún proceso sobrescribirá la escritura de otros procesos en la medida en que cada tamaño de escritura sea <= PIPE_BUF.
Escribí un programa de prueba donde varios procesos se abren y escriben en el mismo archivo (write(2)). Me aseguro de que cada tamaño de escritura sea > PIPE_BUF (4k). Esperaba ver instancias en las que un proceso sobrescriba los datos de otra persona. Pero eso no sucede. Probé con diferentes tamaños de escritura. ¿Es solo suerte o hay alguna razón por la que eso no sucede? Mi objetivo final es comprender si varios procesos que se agregan al mismo archivo necesitan coordinar sus escrituras.
Aquí está el programa completo. Cada proceso crea un búfer int, llena todos los valores con su rankabre un archivo y escribe en él.
Especificaciones: OpenMPI 1.4.3 en Opensuse 11.3 de 64 bits
perror( filename ); es mucho más útil que perror( "Cant open file");
– William Pursell
17/10/2012 a las 21:26
Hice la misma prueba en una caja de Linux (centos 7 3.10.0-327.13.1.el7.x86_64), vi el comportamiento que desea. Consulte stackoverflow.com/questions/38219512/….
– aporcar
6 de julio de 2016 a las 10:26
La atomicidad de escribe menos de PIPE_BUF se aplica solo a tuberías y FIFO. Para escrituras de archivos, POSIX dice:
Este volumen de POSIX.1-2008 no especifica el comportamiento de las escrituras simultáneas en un archivo desde varios procesos. Las aplicaciones deben usar alguna forma de control de concurrencia.
… lo que significa que está solo: diferentes tipos de UNIX le darán diferentes garantías.
¿Cómo sé lo que garantiza mi Linux? ¿Está esto documentado en alguna parte para un Linux en particular?
– jitihsk
18 de octubre de 2012 a las 3:25
@KVM: Esta publicación bastante divertida de Linus Torvalds implica que un solo write() en una O_APPEND El archivo debe ser atómico en Linux, al menos en “sistemas de archivos similares a UNIX”; el ejemplo dado son los archivos de registro. Sin embargo, tenga en cuenta que NFS para uno ciertamente no se comporta de esta manera.
– café
18 de octubre de 2012 a las 4:08
@KVM: Sí, pero Linus está hablando del comportamiento tradicional de UNIX y Linux en lugar de lo que exige cualquier estándar escrito.
Tenga en cuenta que POSIX 7 write documentación dice: “Si el O_APPEND se establece la bandera de las banderas de estado del archivo, el desplazamiento del archivo se establecerá al final del archivo antes de cada escritura y no se producirá ninguna operación de modificación de archivo intermedia entre el cambio del desplazamiento del archivo y la operación de escritura.” Eso suena como una garantía de atomicidad. Tenga en cuenta, sin embargo, que no es una garantía de lo completo – write() no se garantiza que escriba todos los bytes solicitados, aunque las escrituras parciales de IME en un archivo real no ocurren.
–Andrew Henle
5 de enero de 2019 a las 13:06
niall douglas
En primer lugar, O_APPEND o el equivalente FILE_APPEND_DATA en Windows significa que los incrementos de la extensión máxima del archivo (archivo “longitud”) son atómico bajo escritores concurrentes, y eso es por cualquier cantidad, no solo PIPE_BUF. Esto está garantizado por POSIX, y Linux, FreeBSD, OS X y Windows lo implementan correctamente. Samba también lo implementa correctamente, NFS antes de v5 no lo hace, ya que carece de la capacidad de formato de cable para agregar atómicamente. Entonces, si abre su archivo con solo agregar, las escrituras simultáneas no se desgarrarán entre sí en ningún sistema operativo importante a menos que NFS esté involucrado.
Sin embargo, esto no dice nada sobre si las lecturas alguna vez verán una escritura rasgada, y sobre eso POSIX dice lo siguiente sobre la atomicidad de read() y write() en archivos normales:
Todas las siguientes funciones serán atómicas entre sí a los efectos especificados en POSIX.1-2008 cuando operen sobre archivos regulares o enlaces simbólicos… [many functions] … leer () … escribir () … Si dos subprocesos llaman a una de estas funciones, cada llamada verá todos los efectos especificados de la otra llamada, o ninguno de ellos. [Source]
y
Las escrituras se pueden serializar con respecto a otras lecturas y escrituras. Si se puede probar (por cualquier medio) que ocurre una lectura () de los datos del archivo después de una escritura () de los datos, debe reflejar esa escritura (), incluso si las llamadas son realizadas por diferentes procesos. [Source]
pero a la inversa:
Este volumen de POSIX.1-2008 no especifica el comportamiento de las escrituras simultáneas en un archivo desde varios procesos. Las aplicaciones deben usar alguna forma de control de concurrencia. [Source]
Una interpretación segura de estos tres requisitos sugeriría que todas las escrituras que superponen una extensión en el mismo archivo deben serializarse una con respecto a la otra y en lecturas de tal manera que las escrituras rotas nunca aparezcan a los lectores.
Una interpretación menos segura, pero aún permitida, podría ser que las lecturas y las escrituras solo se serialicen entre sí entre subprocesos dentro del mismo proceso, y entre procesos, las escrituras se serialicen con respecto a las lecturas únicamente (es decir, hay un orden de E/S secuencialmente consistente entre subprocesos en un proceso, pero entre procesos i/o es solo adquirir-liberar).
Por supuesto, el hecho de que el estándar requiera esta semántica no significa que las implementaciones cumplan, aunque, de hecho, FreeBSD con ZFS se comporta perfectamente, Windows muy reciente (10.0.14393) con NTFS se comporta perfectamente y Linux reciente con ext4 se comporta correctamente si O_DIRECT está activado. . Si desea obtener más detalles sobre qué tan bien los principales sistemas operativos y sistemas de archivo cumplen con el estándar, consulte esta respuesta
¿Nunca he oído hablar de NFS v5?
– ostrokach
10 de abril de 2017 a las 2:49
@ostrokach Ha estado en desarrollo durante años. Tienen una lista de correo en algún lugar donde leí lo anterior.
–Niall Douglas
10/04/2017 a las 21:31
Celada
No es suerte, en el sentido de que si profundizas en el núcleo probablemente puedas probar que en tus circunstancias particulares nunca sucederá que uno procese’ write se intercala con otro. Estoy asumiendo que:
No está alcanzando ningún límite de tamaño de archivo
No está llenando el sistema de archivos en el que crea el archivo de prueba
El archivo es un archivo normal (no un zócalo, tubería o cualquier otra cosa)
El sistema de archivos es local.
El búfer no abarca varias asignaciones de memoria virtual (se sabe que esta es cierta porque es malloc()ed, que lo pone en el montón, que es contiguo.
Los procesos no son interrumpidos, señalados o rastreados mientras write() está ocupado.
No hay errores de E/S de disco, fallas de RAM o cualquier otra condición anormal.
(Tal vez otros)
Probablemente descubra que si todas esas suposiciones son ciertas, es el caso de que el kernel del sistema operativo que está usando siempre logra una sola write() llamada al sistema con una única escritura contigua atómica en el siguiente archivo.
Eso no significa que puedas contar con que esto siempre sea cierto. Nunca se sabe cuándo podría no ser cierto cuando:
el programa se ejecuta en un sistema operativo diferente
el archivo se mueve a un sistema de archivos NFS
el proceso recibe una señal mientras el write() está en progreso y el write() devuelve un resultado parcial (menos bytes de los solicitados). No estoy seguro de si POSIX realmente permite que esto suceda, ¡pero programo a la defensiva!
etc…
Por lo tanto, su experimento no puede probar que puede contar con escrituras no intercaladas.
¿Ha sido útil esta solución?
Tu feedback nos ayuda a saber si la solución es correcta y está funcionando. De esta manera podemos revisar y corregir el contenido.
Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos.
Configurar y más información
perror( filename );
es mucho más útil queperror( "Cant open file");
– William Pursell
17/10/2012 a las 21:26
Hice la misma prueba en una caja de Linux (centos 7 3.10.0-327.13.1.el7.x86_64), vi el comportamiento que desea. Consulte stackoverflow.com/questions/38219512/….
– aporcar
6 de julio de 2016 a las 10:26