Pregunta

Pregunta

Pregunta

Supongamos que tengo algo que no es un directorio (archivo, tubería/socket con nombre, lo que sea) en el nombre de la ruta /tmp/fooy algún otro que no es un directorio en el nombre de la ruta /tmp/bar. Luego, dos (o más) procesos comienzan a ejecutarse simultáneamente:

El proceso que uno hace:

unlink('/tmp/foo') /* or rename('/tmp/foo', '/tmp/removed') */
unlink('/tmp/bar') /* or rename('/tmp/bar', '/tmp/removed') */

El proceso dos (y así sucesivamente) hace:

link('/tmp/foo', '/tmp/bar')

Según tengo entendido, no hay forma de que el proceso dos pueda tener éxito (ya sea que se link(2)intenta mientras /tmp/footodavía está presente, en cuyo caso /tmp/bartambién está presente, por lo que debe fallar con EEXIST, o /tmp/foodesaparece, por lo que debe fallar con ENOENT).

Pero esta intuición se basa en la suposición de que las llamadas al sistema unlink(2)y/o rename(2)son inherentemente secuenciales en sus efectos de desvinculación, por lo que estoy buscando una verificación de mi comprensión: ¿Existe algún sistema tipo *nix cuyo núcleo permita las dos unlink(2)y/o rename(2)llamadas para tener éxito, pero simultáneamente causa link(2)que también tenga éxito (ya sea debido a reordenar la desvinculación /tmp/fooy /tmp/barno abstraerlo/ocultarlo del proceso que llama link(2), o a través de alguna otra condición de carrera/error peculiar)?

Comprensión actual

He leído las páginas de manual de unlink(2), rename(2)y link(2)de Linux y algunos BSD, y la especificación POSIX para estas funciones. Pero no creo que en realidad contengan nada tranquilizador sobre este asunto, tras una cuidadosa consideración. Al menos con rename(2), nos prometen que eldestinose reemplaza atómicamente si ya está presente (Dejando a un lado los errores en el propio sistema operativo.), pero nada más.

He vistoreclamosque múltiples ejecuciones simultáneas de rename(foo, qux)will de forma atómica y portátil tienen todos los cambios de nombre menos uno ENOENT, ¡así que eso es prometedor! Simplemente no estoy seguro de si eso también puede extenderse a tener una link(foo, bar)falla en las mismas circunstancias.ENOENT

Respuestas preferidas

Me doy cuenta de que esta es una de esas situaciones en las que "no se puede probar algo negativo"; en el mejor de los casos, solo podemos señalar que no hay evidencia de que link(2)exista un sistema similar a *nix que permita que el proceso dos tenga éxito.

Entonces, lo que estoy buscando son respuestas que cubran tantos sistemas similares a *nix como sea posible (al menos Linux, OS X y los distintos BSD, pero idealmente también los sistemas propietarios que todavía se utilizan en algún momento, como Solaris 10). de personas que están lo suficientemente familiarizadas con estos sistemas y este conjunto limitado de problemas (operaciones de sistemas de archivos atómicos/bien ordenados) que están seguros (tanto como uno puede serlo de manera realista) de que conocerían problemas como el Mac antes mencionado. rename(2)Error no atómico de OS X si existieran en las plataformas con las que están familiarizados. Eso me daría suficiente confianza en que esto funciona como creo que funciona de una manera lo suficientemente portátil como para confiar.

Nota final

Esta no es una pregunta de "problema X/Y"; no hay ningún problema subyacente que pueda responderse remitiéndome a los diversos mecanismos de bloqueo/IPC o algo más que solucione la incertidumbre sobre cómo interactúan estas llamadas al sistema en particular: quiero específicamente para saber si uno puede confiar en que las llamadas al sistema anteriores interactúen de forma portátil como se espera en sistemas similares a *nix en el uso práctico actual.

Respuesta1

Mire estándares comoPOSIXpara garantías de portabilidad. En la práctica, la mayoría de los sistemas compatibles con POSIX tienen pequeñas desviaciones de las especificaciones, pero en términos generales se puede confiar en las garantías dadas en las especificaciones. La mayoría de los Unices modernos cumplen con la especificación incluso si no han sido probados formalmente. Es posible que deban ejecutarse en modo POSIX, por ejemplo, configurándolos POSIXLY_CORRECT=1con bash o asegurándose de que /usr/xpg4/binesté delante /biny /usr/bindentro PATHde Solaris.

Unix único v2(una extensión anterior de POSIX) tiene esto que decir sobrelink:

La link()función creará atómicamente un nuevo enlace para el archivo existente y el recuento de enlaces del archivo se incrementa en uno.

Acerca derename:

Si el enlace nombrado por elnuevoEl argumento existe, se elimina yviejorenombrado anuevo. En este caso, un enlace llamado nuevo permanecerá visible para otros procesos durante la operación de cambio de nombre y hará referencia al archivo al que hace referencianuevooviejoantes de que comenzara la operación.

POSIX establece explícitamente que si el destino existe, su reemplazo debe ser atómico. Sin embargo, no establece que el cambio de nombre en sí deba ser atómico, es decir, que no hay un momento en el que ambosviejoynuevoreferirse al expediente de que se trate, o cuando ninguno de los dos lo haga. En la práctica, esas propiedades son ciertas en sistemas Unix, al menos con sistemas de archivos locales.

Además se garantiza el orden de las operaciones: en C, ;garantiza la ejecución secuencial; en sh, ;/newline garantiza la ejecución secuencial (como lo hace &&, etc.); Otros lenguajes de programación ofrecen garantías similares. Entonces en

unlink("/tmp/foo");
unlink("/tmp/bar");

se garantiza que no hay ningún momento en el que /tmp/fooexista pero no /tmp/bar(suponiendo que /tmp/barexista inicialmente). Por lo tanto, un proceso concurrente que se ejecuta link("/tmp/foo", "/tmp/bar")no puede tener éxito.

Tenga en cuenta que la atomicidad no garantizaresiliencia. La atomicidad se trata de un comportamiento observable en un sistema vivo. La resiliencia, en el contexto de los sistemas de archivos, se trata de lo que sucede en caso de una falla del sistema. Muchos sistemas de archivos sacrifican la resiliencia por el rendimiento, por lo que si se interrumpe la ejecución unlink("foo"); unlink("bar");(con el directorio actual en el almacenamiento en disco), es posible que barse elimine y fooquede atrás.

Algunos sistemas de archivos de red ofrecen menos garantías cuando las operaciones se realizan en diferentes clientes. Las implementaciones más antiguas de NFS eran conocidas por esto. Creo que las implementaciones modernas son mejores, pero no tengo experiencia con NFS moderno.

información relacionada