¿Es file append atomic en UNIX?


En general, ¿qué podemos dar por sentado cuando agregamos a un archivo en UNIX desde múltiples procesos? ¿Es posible perder datos(un proceso sobrescribe los cambios del otro)? Es posible que los datos manejados? (Por ejemplo, cada proceso está anexando una línea por anexa a un archivo de registro, ¿es posible que dos líneas queden destrozadas? Si el anexo no es atómico en el sentido anterior, entonces ¿cuál es la mejor manera de garantizar la exclusión mutua?

Author: Peter Cordes, 2009-07-20

4 answers

Una escritura que está bajo el tamaño de 'PIPE_BUF' se supone que es atómica. Eso debería ser al menos 512 bytes, aunque podría ser fácilmente más grande (Linux parece tener establecido en 4096).

Esto supone que estás hablando de todos los componentes compatibles con POSIX. Por ejemplo, esto no es cierto en NFS.

Pero suponiendo que escriba en un archivo de registro que abrió en modo 'O_APPEND' y mantenga sus líneas (incluida la nueva línea) en bytes' PIPE_BUF ' largos, debería poder tener varios escritores para un archivo de registro sin ningún problema de corrupción. Cualquier interrupción llegará antes o después de la escritura, no en el medio. Si desea que la integridad del archivo sobreviva a un reinicio, también necesitará llamar a fsync(2) después de cada escritura, pero eso es terrible para el rendimiento.

Aclaración : lee los comentarios y La respuesta de Oz Solomon. No estoy seguro de que O_APPEND se supone que tiene ese tamaño atomicidad PIPE_BUF. Es completamente posible que sea solo la forma en que Linux implementó write(), o puede ser debido a los tamaños de bloque del sistema de archivos subyacente.

 52
Author: freiheit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:34:27

Editar: Actualizado en agosto de 2017 con los últimos resultados de Windows.

Te voy a dar una respuesta con enlaces a código de prueba y resultados como el autor de proposed Boost.AFIO que implementa un sistema de archivos asíncrono y una biblioteca C++ de e/s de archivos.

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ómicos bajo escritores concurrentes. 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 alambre para anexar atómicamente. Por lo tanto, si abre su archivo con solo anexar, las escrituras concurrentes no se rasgarán entre sí en ningún sistema operativo principal a menos que NFS esté involucrado.

Sin embargo, concurrente lee a atomic appends puede ver escrituras rasgadas dependiendo del sistema operativo, el sistema de archivo y con qué banderas abrió el archivo - el incremento de la extensión máxima del archivo es atómico, pero la visibilidad de las escrituras con respecto a las lecturas puede o no ser atómica. Aquí hay un resumen rápido por banderas, sistema operativo y sistema de archivo:


No O_DIRECT / FILE_FLAG_NO_BUFFERING:

Microsoft Windows 10 con NTFS: actualizar atomicity = 1 byte hasta e incluyendo 10.0.10240, desde 10.0.14393 al menos 1Mb, probablemente infinito (*).

Linux 4.2.6 con ext4: actualización atomicidad = 1 byte

FreeBSD 10.2 con ZFS: actualización atomicidad = al menos 1Mb, probablemente infinito ( * )

O_DIRECT / FILE_FLAG_NO_BUFFERING:

Microsoft Windows 10 con NTFS: update atomicity = until e incluyendo 10.0.10240 hasta 4096 bytes solo si la página está alineada, de lo contrario 512 bytes si FILE_FLAG_WRITE_THROUGH desactivado, de lo contrario 64 bytes. Tenga en cuenta que esta atomicidad es probablemente una característica de PCIe DMA en lugar de diseñado en. Desde 10.0.14393, al menos 1Mb, probablemente infinito (*).

Linux 4.2.6 con ext4: actualización atomicity = at mínimo 1Mb, probablemente infinito ( * ). Tenga en cuenta que los linuxes anteriores con ext4 definitivamente no superaban los 4096 bytes, XFS ciertamente solía tener bloqueo personalizado, pero parece que Linux reciente finalmente ha solucionado esto.

FreeBSD 10.2 con ZFS: actualización atomicidad = al menos 1Mb, probablemente infinita ( * )


Puedes ver los resultados de las pruebas empíricas en bruto en https://github.com/ned14/afio/tree/master/programs/fs-probe . Nota probamos para compensaciones rasgadas solo en múltiplos de 512 bytes, por lo que no se puede decir si una actualización parcial de un sector de 512 bytes se rompería durante el ciclo de lectura-modificación-escritura.

Por lo tanto, para responder a la pregunta del OP, las escrituras O_APPEND no interferirán entre sí, pero las lecturas simultáneas a las escrituras O_APPEND probablemente verán escrituras rasgadas en Linux con ext4 a menos que O_DIRECT esté activado, con lo cual sus escrituras O_APPEND tendrían que ser múltiples de tamaño de sector.


( * ) "Probablemente infinito"se deriva de estas cláusulas en la especificación POSIX:

Todos los las siguientes funciones serán atómicas con respecto a cada otros en los efectos especificados en POSIX.1-2008 cuando operan en archivos regulares o enlaces simbólicos ... [muchas funciones] ... 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. [Fuente]

Y

Las escrituras pueden ser serializadas con respecto a otras lecturas y escrituras. Si a Leer() de los datos del archivo se puede demostrar (por cualquier medio) para ocurrir después de un write () de los datos, debe reflejar ese write (), incluso si las llamadas están hechos por diferentes procesos. [Fuente]

Pero a la inversa:

Este volumen de POSIX.1-2008 no especifica el comportamiento de concurrente escribe en un archivo desde varios procesos. Las aplicaciones deben utilizar algunos forma de control de concurrencia. [Fuente]

Puedes leer más sobre el significado de estos en esta respuesta

 27
Author: Niall Douglas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-21 18:19:45

Escribí un script para probar empíricamente el tamaño máximo atómico del apéndice. El script, escrito en bash, genera múltiples procesos de trabajo que todos escriben firmas específicas de trabajo en el mismo archivo. Luego lee el archivo, buscando firmas superpuestas o corruptas. Puedes ver la fuente del script en esta entrada de blog .

El tamaño máximo atómico real del apéndice varía no solo por el sistema operativo, sino por el sistema de archivos.

En Linux + ext3 el tamaño es 4096, y en Windows + NTFS el tamaño es 1024. Vea los comentarios a continuación para más tamaños.

 18
Author: Oz Solomon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-08 20:25:54

Esto es lo que dice el estándar: http://www.opengroup.org/onlinepubs/009695399/functions/pwrite.html .

Si se establece el indicador O_APPEND de los indicadores 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 del archivo entre el cambio del desplazamiento del archivo y la operación de escritura.

 14
Author: Bastien Léonard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-20 17:06:05