【问题标题】:Is there file locking in Rust?Rust 中是否存在文件锁定?
【发布时间】:2015-02-12 17:10:41
【问题描述】:

我找不到任何类似于文件锁定的东西,就像 Linux 中的某些程序用来防止多个实例运行一样。在 Python 中,我会使用 pylockfile

我是否忽略了 Rust 中的类似功能,还是应该从头开始实现它?

我并不懒惰,只是想尽可能少地重新发明轮子。

【问题讨论】:

  • 在 rustdoc 中有 code to start from。它确实说“这不应该在标准库中”。
  • 我认为您可能必须从头开始实施它。 IO/OS 模块仍然在不断变化,不确定这个功能是否适合它......话虽如此,Rust 从一开始就接受了包分发,尽管 Cargo 正是出于这个原因,所以创建一个专门用于此功能的小包,并通过 crates.io 与世界分享
  • 我已经有一段时间没有认真考虑文件锁定的实现了,但是那个 Python 库似乎还不够彻底。它似乎主要通过创建文件/目录并查看它们是否存在来工作,而不是依赖于操作系统设施。如果您确实重新实现文件锁定,我建议您查看其他资源以了解如何做到这一点。
  • 感谢您的回复!我的意思是创建一个外部库,而不是向标准添加东西。
  • 顺便说一句,如果你想创建一个守护进程,那么你可能需要考虑使用你的操作系统进程管理系统,比如 Linux 中的systemd 或 OS X 中的launchd。这样你就赢了不需要完全考虑锁。

标签: synchronization locking rust


【解决方案1】:

在 Linux 中你可以使用nix crate 其中wraps unix 文件锁。

这是一个例子:

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!");
}

如果您尝试运行两个实例,则只有在第一个实例解锁文件后,第二个实例才会开始倒计时。但是其他程序可以忽略这个锁:

flock(2):函数只放置咨询锁;给定文件的适当权限,a 进程可以随意忽略flock()的使用并对文件执行I/O。

【讨论】:

    【解决方案2】:

    对于当代 Rust (1.8+),您应该使用 fs2 crate。它是一个跨平台库,提供了一些标准库中没有的文件系统功能,包括文件锁定。

    fs2 的文件锁定函数在 UNIX 上内部使用 flock(2),在 Windows 上使用 LockFileEx

    例子:

    //! 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(())
    }
    

    我们可以看到这两个进程是按顺序等待文件锁的。

    $ ./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
    

    【讨论】:

      【解决方案3】:

      https://github.com/clucompany/cluFlock

      use cluFlock::ToFlock;
      use std::fs::File;
      use std::io;
      
      fn main() -> Result<(), io::Error> {
          let file_lock = File::create("/tmp/1")?.wait_exclusive_lock()?;
      
          println!("{:?}", file_lock);
          drop(file_lock); //<-- unlock file
      
          Ok( () )
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-03-16
        • 1970-01-01
        • 1970-01-01
        • 2011-11-02
        • 1970-01-01
        • 2014-01-13
        • 1970-01-01
        • 2015-08-03
        相关资源
        最近更新 更多