rust - 使用文件锁防止应用多开

本文给出了进程只能单开的方法。

安装依赖

rust 复制代码
cargo add fslock

使用方法

rust 复制代码
use fslock::LockFile;

// 打开pid文件,没有则自动创建
let mut pid_lock =
        LockFile::open(&pid_path.clone().into_os_string()).unwrap();
// 非阻塞的锁文件
if !pid_lock.try_lock_with_pid().unwrap() {
    // 如果文件已经被锁,则退出进程
    // ...
}

// 文件加锁成功,则执行业务逻辑
// ...

库支持的系统

此库支持 windowslinuxmac,通过如下代码实现

rust 复制代码
#[cfg(unix)]
mod unix;
#[cfg(unix)]
use crate::unix as sys;

mod string;
mod fmt;

#[cfg(windows)]
mod windows;
#[cfg(windows)]
use crate::windows as sys;

原理简介

1. 锁操作

linux

调用 libc.so的接口实现,目的是不使用 std 库。

rust 复制代码
pub fn try_lock(fd: FileDesc) -> Result<bool, Error> {
    let res = unsafe { libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB) };
    if res >= 0 {
        Ok(true)
    } else {
        let err = errno();
        if err == libc::EWOULDBLOCK || err == libc::EINTR {
            Ok(false)
        } else {
            Err(Error::from_raw_os_error(err as i32))
        }
    }
}

windows

rust 复制代码
pub fn try_lock(handle: FileDesc) -> Result<bool, Error> {
    let mut overlapped = make_overlapped()?;
    let drop_handle = DropHandle { handle: overlapped.hEvent };
    let res = unsafe {
        LockFileEx(
            handle,
            LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY,
            0,
            1,
            1,
            &mut overlapped as LPOVERLAPPED,
        )
    };

    let ret = if res == TRUE {
        let res = unsafe { WaitForSingleObject(overlapped.hEvent, 0) };
        if res != WAIT_FAILED {
            Ok(true)
        } else {
            Err(Error::last_os_error())
        }
    } else {
        let err = unsafe { GetLastError() };
        if err == ERROR_LOCK_VIOLATION {
            Ok(false)
        } else {
            Err(Error::from_raw_os_error(err as i32))
        }
    };

    drop(drop_handle);
    ret
}

2. 进程退出解锁清空文件内容

rust 复制代码
impl Drop for LockFile {
    fn drop(&mut self) {
        if self.locked {
            let _ = self.unlock();
        }
        sys::close(self.desc);
    }
}

    pub fn unlock(&mut self) -> Result<(), sys::Error> {
        if !self.locked {
            panic!("Attempted to unlock already unlocked lockfile");
        }
        self.locked = false;
        sys::unlock(self.desc)?;
        // 解锁后清空文件内容
        sys::truncate(self.desc)?;
        Ok(())
    }
相关推荐
小灰灰搞电子1 天前
Rust可以取代C++么?
开发语言·c++·rust
百锦再1 天前
京东云鼎入驻方案解读——通往协同的“高架桥”与“快速路”
android·java·python·rust·django·restful·京东云
异步思考者1 天前
Rust实战:一个内存消息队列的 Trait 驱动开发
rust
受之以蒙1 天前
智能目标检测:用 Rust + dora-rs + yolo 构建“机器之眼”
人工智能·笔记·rust
熬了夜的程序员1 天前
【Rust学习之路】第 0 章:理解 Rust 的核心哲学
开发语言·学习·rust
EniacCheng1 天前
【RUST】学习笔记-环境搭建
笔记·学习·rust
禅思院1 天前
在win10上配置 Rust以及修改默认位置问题
开发语言·前端·后端·rust·cargo·mingw64·cargo安装位置
shandianchengzi1 天前
【记录】Rust|Rust开发相关的7个VSCode插件的介绍和推荐指数(2025年)
开发语言·vscode·rust
JPX-NO1 天前
Rust + Rocket + Diesel构建的RESTful API示例(CRUD)
开发语言·rust·restful
林太白1 天前
Rust01-认识安装
开发语言·后端·rust