nfs 锁机制demo

下面我将提供几个不同的 C++ 示例,分别测试以下场景:

  1. 单个机器多个进程读取共享文件,锁是否有效
  2. 一个机器写入共享文件,另一个机器同时读取共享文件,锁是否有效
  3. 多个机器同时读取共享文件,锁是否有效
  4. 一个机器同时多个接口写入共享文件,锁是否有效
    每个场景都依赖于 POSIX 文件锁(fcntl())来管理文件的读写锁。锁在 NFS 文件系统上通常能确保数据的正确同步,但多个机器访问时,网络延迟和 NFS 配置可能会影响锁的行为,因此要注意环境配置。

1. 单个机器多个进程读取共享文件,锁是否有效

这个代码验证了在同一台机器上,多个进程是否能正确地读取文件并获得锁。

cpp 复制代码
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <cstring>
#include <errno.h>

#define FILE_PATH "/mnt/nfs/myfile.txt"

void acquire_read_lock(int fd) {
    struct flock lock;
    lock.l_type = F_RDLCK;  // 读锁
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;  // 锁定整个文件

    if (fcntl(fd, F_SETLK, &lock) == -1) {
        std::cerr << "读锁加锁失败: " << strerror(errno) << std::endl;
        exit(1);
    }
    std::cout << "获得读锁" << std::endl;
}

void release_lock(int fd) {
    struct flock lock;
    lock.l_type = F_UNLCK;  // 释放锁
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;

    if (fcntl(fd, F_SETLK, &lock) == -1) {
        std::cerr << "释放锁失败: " << strerror(errno) << std::endl;
    }
    std::cout << "锁已释放" << std::endl;
}

int main() {
    int fd = open(FILE_PATH, O_RDWR | O_CREAT, 0666);
    if (fd == -1) {
        std::cerr << "文件打开失败: " << strerror(errno) << std::endl;
        return 1;
    }

    // 创建多个进程来模拟并发读取
    pid_t pid = fork();
    if (pid == 0) {
        acquire_read_lock(fd);
        std::cout << "子进程 1 正在读取文件..." << std::endl;
        sleep(5);
        release_lock(fd);
        exit(0);
    }

    pid = fork();
    if (pid == 0) {
        acquire_read_lock(fd);
        std::cout << "子进程 2 正在读取文件..." << std::endl;
        sleep(5);
        release_lock(fd);
        exit(0);
    }

    wait(NULL);
    wait(NULL);

    close(fd);
    return 0;
}

2. 一个机器写入共享文件,另一个机器同时读取共享文件,锁是否有效

在这个场景中,模拟一台机器进行写入,另一台机器进行读取。需要在不同机器上运行这个代码。
写入机器

cpp 复制代码
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <errno.h>

#define FILE_PATH "/mnt/nfs/myfile.txt"

void acquire_write_lock(int fd) {
    struct flock lock;
    lock.l_type = F_WRLCK;  // 写锁
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;

    if (fcntl(fd, F_SETLK, &lock) == -1) {
        std::cerr << "写锁加锁失败: " << strerror(errno) << std::endl;
        exit(1);
    }
    std::cout << "获得写锁" << std::endl;
}

void release_lock(int fd) {
    struct flock lock;
    lock.l_type = F_UNLCK;  // 释放锁
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;

    if (fcntl(fd, F_SETLK, &lock) == -1) {
        std::cerr << "释放锁失败: " << strerror(errno) << std::endl;
    }
    std::cout << "锁已释放" << std::endl;
}

int main() {
    int fd = open(FILE_PATH, O_RDWR | O_CREAT, 0666);
    if (fd == -1) {
        std::cerr << "文件打开失败: " << strerror(errno) << std::endl;
        return 1;
    }

    acquire_write_lock(fd);
    std::cout << "写入操作进行中..." << std::endl;
    sleep(5);  // 模拟写入操作
    release_lock(fd);

    close(fd);
    return 0;
}

读取机器(同上,使用第一个示例)。

3. 多个机器同时读取共享文件,锁是否有效

在这个场景中,多个机器同时进行读取文件的操作,可以在不同机器上运行第一个示例。NFS 文件系统通常允许多个进程同时读取文件,只要它们持有读锁时不会相互干扰。

4. 一个机器同时多个接口写入共享文件,锁是否有效

这个场景模拟了在同一台机器上,通过多个进程进行写入操作,并验证锁是否有效。使用与第二个场景类似的代码,但通过多个进程进行并发写入。

cpp 复制代码
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <cstring>
#include <errno.h>
#include <sys/wait.h>

#define FILE_PATH "/mnt/nfs/myfile.txt"

void acquire_write_lock(int fd) {
    struct flock lock;
    lock.l_type = F_WRLCK;  // 写锁
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;

    if (fcntl(fd, F_SETLK, &lock) == -1) {
        std::cerr << "写锁加锁失败: " << strerror(errno) << std::endl;
        exit(1);
    }
    std::cout << "获得写锁" << std::endl;
}

void release_lock(int fd) {
    struct flock lock;
    lock.l_type = F_UNLCK;  // 释放锁
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;

    if (fcntl(fd, F_SETLK, &lock) == -1) {
        std::cerr << "释放锁失败: " << strerror(errno) << std::endl;
    }
    std::cout << "锁已释放" << std::endl;
}

int main() {
    int fd = open(FILE_PATH, O_RDWR | O_CREAT, 0666);
    if (fd == -1) {
        std::cerr << "文件打开失败: " << strerror(errno) << std::endl;
        return 1;
    }

    pid_t pid1 = fork();
    if (pid1 == 0) {
        acquire_write_lock(fd);
        std::cout << "子进程 1 正在写入文件..." << std::endl;
        sleep(5);
        release_lock(fd);
        exit(0);
    }

    pid_t pid2 = fork();
    if (pid2 == 0) {
        acquire_write_lock(fd);
        std::cout << "子进程 2 正在写入文件..." << std::endl;
        sleep(5);
        release_lock(fd);
        exit(0);
    }

    wait(NULL);
    wait(NULL);

    close(fd);
    return 0;
}


g++ -o file_lock_demo file_lock_demo.cpp
./file_lock_demo

注意事项:

  • 需要在 NFS 配置中确保锁机制开启,并且文件系统配置正确。
  • 测试时,建议在不同的机器上执行这些进程,尤其是在写入和读取操作之间的锁竞争。
  • 为了确保锁机制的有效性,确保使用的 NFS 服务器支持锁定(如 lockd 服务必须启动)。
    这些代码分别模拟了不同机器和进程间的锁竞争,通过加锁机制保证了文件的并发访问正确性。运行这些代码时,确保在 NFS 环境中进行测试。
相关推荐
Lhan.zzZ1 分钟前
嵌入式Qt接收串口数据错乱问题分析:缓冲区残留数据的陷阱
开发语言·c++·qt
CCPC不拿奖不改名8 分钟前
Python基础:python语言中的文件操作+面试题目
开发语言·数据结构·人工智能·python·学习·面试·职场和发展
superman超哥9 分钟前
Rust 借用分割技巧:突破借用限制的精确访问
开发语言·后端·rust·编程语言·借用分割技巧·借用限制·精准访问
程序炼丹师10 分钟前
C++ 中的 std::tuple (元组)的使用
开发语言·c++
程序员佳佳15 分钟前
【万字硬核】从GPT-5.2到Sora2:深度解构多模态大模型的“物理直觉”与Python全栈落地指南(内含Banana2实测)
开发语言·python·gpt·chatgpt·ai作画·aigc·api
不绝19121 分钟前
C#进阶——内存
开发语言·c#
风送雨21 分钟前
Go 语言进阶学习:第 1 周 —— 并发编程深度掌握
开发语言·学习·golang
小北方城市网24 分钟前
第 5 课:服务网格(Istio)实战|大规模微服务的流量与安全治理体系
大数据·开发语言·人工智能·python·安全·微服务·istio
jghhh0124 分钟前
自适应信号时频处理方法MATLAB实现(适用于非线性非平稳信号)
开发语言·算法·matlab
AC赳赳老秦25 分钟前
Go语言微服务文档自动化生成:基于DeepSeek的智能解析实践
大数据·开发语言·人工智能·微服务·golang·自动化·deepseek