pthread_mutex_init pthread lock ejemplos c linux locking

ejemplos - pthread mutex lock



flock vs lockf en Linux (2)

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

Lo pregunto porque estoy leyendo el código que compila condicionalmente en cualquiera de estas 2 funciones basadas en la plataforma y quiero entender las posibles razones de por qué.


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

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

Si la semántica (comportamiento sobre el paso de descriptores, forking, etc.) es aceptable, debería preferir lockf() / fcntl() bloquea sobre flock() en Linux, simplemente porque la primera funciona en sistemas de archivos NFS, etc., mientras que la segunda no. (En BSDs y Mac OS X, creo que necesitas usar explícitamente fcntl() , en su lugar).

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

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

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

  1. fcntl() bloqueos fcntl() son los más confiables.

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

  2. La mayoría de las veces, lockf() se implementa como "taquigrafía" para fcntl()

    La otra alternativa, como "taquigrafía" para flock() , es posible, pero hoy en día es poco frecuente.

  3. fcntl() y flock() tienen diferentes semánticas wrt. Herencia y liberaciones automáticas.

    fcntl() bloqueos fcntl() se conservan en un exec() , pero no se heredan en un fork() . Los bloqueos se liberan cuando el proceso de propiedad cierra cualquier descriptor que haga referencia al mismo archivo.

    En Linux, FreeBSD y MAc OS X, los bloqueos de flock() se juntan con el descriptor de archivo abierto: pasar el descriptor también pasa el bloqueo. (Las páginas de manual indican que "el bloqueo está en el archivo, no en el descriptor del archivo" . Esto no es una contradicción. Simplemente significa que el bloqueo se aplica al archivo. Todavía está acoplado al descriptor, de tal manera esa duplicación del descriptor también pasa el mismo bloqueo, también.) Por lo tanto, es posible que múltiples procesos tengan el mismo bloqueo exclusivo de flock() en el mismo archivo al mismo tiempo, si obtuvieron el descriptor del originador después del flock() llamar.

El bloqueo de archivos es un tema sorprendentemente complicado. Personalmente, he obtenido mejores resultados simplemente apegándome al bloqueo fcntl() . La semántica wrt. fcntl() bloqueos fcntl() no son los más fáciles de trabajar, y en ciertos casos pueden ser francamente molestos; es solo que lo he encontrado para obtener los mejores resultados: más fiables, más portátiles y menos sorprendentes.


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