Me gustaría saber si las llamadas al sistema de lectura/escritura de Linux admiten lecturas/escrituras no sincronizadas (escrituras no adjuntas) en regiones no superpuestas de un solo archivo de disco de múltiples subprocesos o procesos. Cada subproceso buscará su propia región del archivo, y leerá/escribirá desde/hacia esta región exclusivamente, nunca superponiendo las regiones en las que están operando otros subprocesos.
POSIX especifica en XSH 2.9.7 que sustancialmente todas las funciones de E/S son atómicas entre sí con respecto a sus efectos especificados por POSIX. Se proporciona una larga lista de las funciones específicas a las que se aplica, y open()
, lseek()
, read()
, write()
y close()
están todos en eso. Por lo tanto,
Si dos subprocesos llaman a una de estas funciones, cada llamada verá todos los efectos especificados de la otra llamada, o ninguno de ellos.
Eso no depende de ninguna sincronización externa, incluso para operaciones en descriptores de archivos asociados con la misma descripción de archivo abierto.
Puede haber varias descripciones de archivos abiertos para el mismo archivo, incluso en un solo proceso (consulte, por ejemplo, la página del manual para abrir (2)). Dados varios subprocesos que realizan read()
y write()
operaciones en regiones no superpuestas del mismo archivo normal, a través de descriptores de archivo que hacen referencia a diferentes descripciones de archivos abiertos , POSIX no proporciona ninguna base para esperar que esas operaciones interfieran entre sí, independientemente de la sincronización externa de los subprocesos involucrados. En la práctica, funciona bien.
Dónde puede meterse en problemas es si los subprocesos involucrados intentan usar descriptores de archivo que se refieren a la misma descripción de archivo abierto. No es necesario que tengan el mismo valor de descriptor de archivo (por lo que dup()
ing un descriptor de archivo no ayuda aquí), ni los subprocesos tienen que pertenecer al mismo proceso para que surja la situación. Cada descripción de archivo abierto tiene una sola posición de archivo asociada, por lo que si dos subprocesos diferentes intentan realizar tareas que requieren cada uno por separado establecer el desplazamiento del archivo y transferir datos hacia o desde el archivo, y si están usando la misma descripción de archivo abierto, entonces la atomicidad de las llamadas de función individuales no es suficiente para garantizar que las lecturas y escrituras se realicen en las posiciones previstas. Se requiere sincronización en ese escenario.
Alternativamente, como @maximegorushkin observó en los comentarios y @bk2204 observó en otra respuesta, el pread()
y pwrite()
Las funciones realizan el posicionamiento y la transferencia de datos en una sola llamada. Estos también están en la lista de funciones de E/S atómicas y superan la separación del posicionamiento de la transferencia de datos por transferencia de datos. Su uso requiere un cuidado y una contabilidad adicionales, y hay escenarios en los que no sirve adecuadamente, pero, sin embargo, puede ser viable para el caso particular en cuestión.
Por lo tanto , si dos subprocesos diferentes quieren operar en el mismo archivo sin sincronización, entonces el enfoque más seguro y general es que cada uno abra el archivo de forma independiente. Entonces no interferirán entre sí siempre que sus operaciones de E/S estén restringidas a regiones inconexas del archivo. Incluso operar en regiones superpuestas del archivo no está descartado, pero eso introduce consideraciones más complejas y específicas de la aplicación.
Sí, esto es posible. El pread
y pwrite
Las funciones le permiten leer y escribir desde un archivo en un desplazamiento dado sin cambiar el desplazamiento del archivo. Están diseñados específicamente para permitir la lectura y escritura en programas multiproceso.
Debe tener en cuenta que en violación de POSIX, pwrite
en un descriptor de archivo abierto con O_APPEND
siempre escribirá al final del archivo.