rebaño vs lockf en Linux

5 minutos de lectura

Si lockf se utiliza con un desplazamiento de 0, ¿cuáles son las diferencias entre flock y lockf cuando se usa en modo exclusivo, si lo hay?

Lo pregunto porque estoy leyendo un código que se compila condicionalmente en cualquiera de estas 2 funciones según la plataforma y quiero entender las posibles razones por las que.

avatar de usuario
Animal Nominal

La diferencia práctica entre flock() y lockf() está en la semántica (comportamiento con respecto al cierre y paso), la aplicabilidad sobre NFS y otros sistemas de archivos compartidos, y si los bloqueos de aviso son visibles para otros procesos que usan fcntl() cerraduras o no.

La biblioteca que está utilizando simplemente tiene lógica para elegir la semántica deseada en función de la plataforma actual.

Si la semántica (comportamiento sobre el paso del descriptor, bifurcación, etc.) es aceptable, debería preferir lockf()/fcntl() se bloquea flock() se bloquea en Linux, simplemente porque el primero funciona en sistemas de archivos NFS, etc., mientras que el segundo no. (En BSD y Mac OS X, creo que debe usar explícitamente fcntl()en lugar de.)


En Linux, lockf() es solo un envoltorio fcntl()tiempo flock() los bloqueos están separados (y solo funcionarán en sistemas de archivos locales, no en, por ejemplo, montajes NFS en kernels anteriores a 2.6.12). Es decir, un proceso puede tener una exclusiva de asesoramiento flock() bloqueo en un archivo, mientras que otro proceso tiene un aviso exclusivo fcntl() bloqueo en ese mismo archivo. Ambos son bloqueos de aviso, pero no interactúan.

En Mac OS X y FreeBSD, lockf()/flock()/fcntl() todos los bloqueos interactúan, aunque se recomienda a los desarrolladores que utilicen solo una de las interfaces en una aplicación. Sin embargo, solo fcntl() las cerraduras funcionan Montajes NFS (y, obviamente, solo si tanto el cliente como el servidor NFS se han configurado para admitir bloqueos de registros, lo cual es sorprendentemente raro, por ejemplo, en entornos de alojamiento web; una gran causa de dolores de cabeza para algunos desarrolladores web (framework)).

POSIX no especifica explícitamente cómo lockf()/flock()/fcntl() las cerraduras deben interactuar, y ha habido diferencias en el pasado. Ahora, la situación se ha calmado un poco, y uno puede aproximadamente dilo

  1. fcntl() las cerraduras son las más fiables

    En todas las arquitecturas, tienen la mejor oportunidad de funcionar correctamente, por ejemplo, en sistemas de archivos compartidos: montajes NFS y CIFS, por ejemplo.

  2. Más amenudo, lockf() se implementa como “taquigrafía” para fcntl()

    La otra alternativa, como “taquigrafía” de flock()es posible, pero hoy en día es raro.

  3. fcntl() y flock() tienen diferente semántica wrt. herencia y liberaciones automáticas

    fcntl() las cerraduras se conservan a través de un exec()pero no heredado a través de un fork(). Los bloqueos se liberan cuando se cierra el proceso de propiedad. ninguna descriptor que hace referencia al mismo archivo.

    En Linux, FreeBSD y MAC OS X, flock() los bloqueos se acoplan con el descriptor de archivo abierto: pasar el descriptor también pasa el bloqueo. (Las páginas del manual indican que “el bloqueo está en el archivo, no en el descriptor del archivo”. Esto no es una contradiccion. Solo significa que la cerradura se aplica al archivo Todavía está acoplado al descriptor, de tal manera que duplicar el descriptor también pasa el mismo bloqueo). Por lo tanto, es posible que varios procesos tengan el mismo aviso exclusivo. flock() bloqueo en el mismo archivo al mismo tiempo, si obtuvieron el descriptor del creador después de la flock() llamada.

El bloqueo de archivos es un problema sorprendentemente complicado. Personalmente, obtuve mejores resultados al simplemente ceñirme a fcntl() cierre. La semántica wrt. fcntl() las cerraduras no son las más fáciles de usar y, en ciertos casos, pueden ser francamente exasperantes; es solo que descubrí que produce los mejores resultados, los más confiables, los más portátiles y los menos sorprendentes.

  • Anexo al comentario anterior: Linux 2.6.12 se lanzó el 18 de junio de 2005, por lo que incluso en el momento de la respuesta flock() funcionaba en NFS.

    – Akilán

    16 mayo 2018 a las 11:24

  • @Akilan: ¿Qué parte? No confundir flock() con lockf(); es horrible comentar así sin señalar exactamente lo que está mal. Es como decir que ha cometido un error, sin señalar el error. No solo es inútil, sino que hace que el tono sea muy presumido y antipático. Creo que usted mismo acaba de confundir lockf() y flock() en la sección NOTAS. En cuanto a NFS y flock() en kernels anteriores a 2.6.12, sí, eso justifica una nota, gracias.

    – Animal nominal

    16 mayo 2018 a las 12:50


  • Lamento que no haya sido muy claro. De hecho, estoy hablando del NFS.

    – Akilán

    17 de mayo de 2018 a las 12:18

  • @Akilan: No, eso estaba claro. Dijiste “la respuesta ya no es cierta”, pero no señalaste cómo, o qué parte. Sin más detalles, debo estar en desacuerdo, porque aparte de mencionar la versión del kernel, no veo cómo mi respuesta difiere en absoluto de la página del manual.

    – Animal nominal

    17 mayo 2018 a las 12:34

La razón más probable de la compilación condicional es que ninguna de las dos funciones está disponible en todas las plataformas.

  • Ese fue mi pensamiento inicial, la verificación reveló que ambos eran compatibles con las plataformas. Sin embargo, puede que no haya sido el caso históricamente, por lo que este parece ser el favorito.

    – Dan McGrath

    14/03/2014 a las 15:55

¿Ha sido útil esta solución?

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
Privacidad