synchronization locking rust

synchronization - ¿Hay bloqueo de archivos en Rust?



locking (2)

En Linux puede usar nix crate que envuelve el bloqueo de archivos de Unix.

Aquí hay un ejemplo:

extern crate nix; use std::fs::File; use std::os::unix::io::AsRawFd; use nix::fcntl::{flock, FlockArg}; fn main() { let file = File::open("Cargo.toml").unwrap(); let fd = file.as_raw_fd(); flock(fd, FlockArg::LockExclusive).unwrap(); for rem in (1..20).rev() { println!("Remain: {} sec.", rem); std::thread::sleep(std::time::Duration::from_secs(1)); } drop(file); println!("File unlocked!"); }

Si intenta ejecutar dos instancias, la segunda comenzará con la cuenta atrás solo después del archivo desbloqueado de la primera instancia. Pero otros programas pueden ignorar este bloqueo:

rebaño (2) : la función coloca cerraduras de aviso solamente; Si se le otorgan los permisos adecuados en un archivo, un proceso puede ignorar el uso de flock () y realizar E / S en el archivo.

Estoy aprendiendo Rust durante aproximadamente 3 horas y no encuentro nada parecido al bloqueo de archivos (ya sabes, como algunos programas usan en Linux para evitar que se ejecuten varias instancias).

Por ejemplo, en Python, usaría este módulo: https://github.com/openstack/pylockfile

¿Estoy pasando por alto una funcionalidad similar en Rust, o debería implementarla desde cero?

No es flojo, solo trata de reinventar las ruedas más pequeñas que sea posible.


Para Rust contemporáneo (1.8+) debes usar la caja fs2 . Es una biblioteca multiplataforma que proporciona algunas funciones del sistema de archivos que no se encuentran en la biblioteca estándar, incluido el bloqueo de archivos.

fs2 funciones de bloqueo de archivos de fs2 usan internamente flock(2) en UNIX y LockFileEx en Windows.

Ejemplo:

//! This program tries to lock a file, sleeps for N seconds, and then unlocks the file. // cargo-deps: fs2 extern crate fs2; use fs2::FileExt; use std::io::Result; use std::env::args; use std::fs::File; use std::time::Duration; use std::thread::sleep; fn main() { run().unwrap(); } fn run() -> Result<()> { let sleep_seconds = args().nth(1).and_then(|arg| arg.parse().ok()).unwrap_or(0); let sleep_duration = Duration::from_secs(sleep_seconds); let file = File::open("file.lock")?; println!("{}: Preparing to lock file.", sleep_seconds); file.lock_exclusive()?; // block until this process can lock the file println!("{}: Obtained lock.", sleep_seconds); sleep(sleep_duration); println!("{}: Sleep completed", sleep_seconds); file.unlock()?; println!("{}: Released lock, returning", sleep_seconds); Ok(()) }

Podemos ver que los dos procesos están secuenciados esperando en el bloqueo de archivos.

$ ./a 4 & ./a 1 [1] 14894 4: Preparing to lock file. 4: Obtained lock. 1: Preparing to lock file. 4: Sleep completed 4: Released lock, returning 1: Obtained lock. 1: Sleep completed 1: Released lock, returning [1]+ Done ./a 4