functions filesystem unix file-io

unix - filesystem - function sh shell



¿El archivo se agrega atómico en UNIX? (4)

En general, ¿qué podemos dar por hecho cuando anexamos a un archivo en UNIX desde procesos múltiples? ¿Es posible perder datos (un proceso que sobrescribe los cambios del otro)? ¿Es posible que los datos se arruinen? (Por ejemplo, cada proceso agrega una línea por anexo a un archivo de registro, ¿es posible que dos líneas se dañen?) Si el apéndice no es atómico en el sentido anterior, ¿cuál es la mejor forma de garantizar la exclusión mutua?


Escribí un guión para probar empíricamente el tamaño máximo de apéndice atómico. El script, escrito en bash, genera múltiples procesos de trabajo que escriben firmas específicas del trabajador en el mismo archivo. A continuación, lee el archivo, buscando firmas superpuestas o corruptas. Puede ver el origen del script en esta publicación de blog .

El tamaño máximo real de apendice atómico varía no solo según el sistema operativo, sino también por el sistema de archivos.

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


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

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


Se supone que una escritura que está por debajo del tamaño de ''PIPE_BUF'' es atómica. Eso debería tener al menos 512 bytes, aunque fácilmente podría ser más grande (Linux parece tenerlo configurado en 4096).

Supongamos que está hablando de todos los componentes que cumplen completamente con POSIX. Por ejemplo, esto no es cierto en NFS.

Pero suponiendo que escribe en un archivo de registro que abrió en el modo ''O_APPEND'' y mantiene sus líneas (incluida la nueva línea) en bytes ''PIPE_BUF'', usted debe poder tener múltiples escritores en 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 de los archivos sobreviva a un reinicio, también deberá llamar a fsync(2) después de cada grabación, pero eso es terrible para el rendimiento.

Aclaración : lea los comentarios y la respuesta de Oz Solomon . No estoy seguro de que se O_APPEND que O_APPEND tenga esa atomicidad de tamaño PIPE_BUF . Es muy posible que sea solo como Linux implementó write() , o puede ser debido a los tamaños de bloque del sistema de archivos subyacente.


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

Voy a darle una respuesta con enlaces para probar el código y los resultados como el autor de Boost.AFIO propuesto, que implementa un sistema de archivos asíncrono y una biblioteca i / o C ++.

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 ("longitud" del archivo) son atómicos en los escritores simultáneos. 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, ya que carece de la capacidad de formato de cable para anexarse ​​atómicamente. Por lo tanto, si abre su archivo con solo anexar, las escrituras concurrentes no se romperán entre sí en ningún sistema operativo importante a menos que se trate de NFS.

Sin embargo, las lecturas concurrentes a anexos atómicos pueden ver escrituras rasgadas dependiendo del sistema operativo, del 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ómico. Aquí hay un resumen rápido por indicadores, sistema operativo y sistema de archivo:

No O_DIRECT / FILE_FLAG_NO_BUFFERING:

Microsoft Windows 10 con NTFS: actualice la atomicidad = 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: actualizar atomicidad = al menos 1Mb, probablemente infinito (*)

O_DIRECT / FILE_FLAG_NO_BUFFERING:

Microsoft Windows 10 con NTFS: actualizar atomicity = hasta 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 está desactivado, sino 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: atomicidad de actualización = al menos 1Mb, probablemente infinito (*). Tenga en cuenta que Linuxes anteriores con ext4 definitivamente no excedían los 4096 bytes, XFS ciertamente solía tener un bloqueo personalizado, pero parece que Linux reciente finalmente ha solucionado esto.

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

Puede ver los resultados de la prueba empírica en bruto en https://github.com/ned14/afio/tree/master/programs/fs-probe . Tenga en cuenta que probamos las desviaciones rotas solo en múltiplos de 512 bytes, por lo que no puedo decir si una actualización parcial de un sector de 512 bytes se desgarraría durante el ciclo de lectura, modificación y escritura.

Entonces, para responder la pregunta del OP, las escrituras O_APPEND no interferirán entre sí, pero las lecturas simultáneas de O_APPEND probablemente verán escrituras desgarradas en Linux con ext4 a menos que O_DIRECT esté activado, por lo que sus escrituras O_APPEND necesitarían un tamaño de sector múltiple.

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

Todas las siguientes funciones serán atómicas entre sí en los efectos especificados en POSIX.1-2008 cuando operan en archivos regulares o enlaces simbólicos ... [muchas funciones] ... leer () ... escribir ( ) ... Si cada uno de los dos hilos llama a una de estas funciones, cada llamada verá todos los efectos especificados de la otra llamada o ninguna de ellas. [Source]

y

Las escrituras se pueden serializar con respecto a otras lecturas y escrituras. Si puede demostrarse (por algún medio) que una lectura () de datos de archivo ocurre después de una escritura () de los datos, debe reflejar dicha escritura (), incluso si las llamadas se realizan mediante procesos diferentes. [Source]

pero a la inversa

Este volumen de POSIX.1-2008 no especifica el comportamiento de las escrituras simultáneas en un archivo de múltiples procesos. Las aplicaciones deben usar alguna forma de control de concurrencia. [Source]

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