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 环境中进行测试。
相关推荐
灰子学技术5 小时前
go response.Body.close()导致连接异常处理
开发语言·后端·golang
二十雨辰6 小时前
[python]-AI大模型
开发语言·人工智能·python
Yvonne爱编码6 小时前
JAVA数据结构 DAY6-栈和队列
java·开发语言·数据结构·python
Re.不晚6 小时前
JAVA进阶之路——无奖问答挑战1
java·开发语言
你这个代码我看不懂6 小时前
@ConditionalOnProperty不直接使用松绑定规则
java·开发语言
pas1366 小时前
41-parse的实现原理&有限状态机
开发语言·前端·javascript
琹箐6 小时前
最大堆和最小堆 实现思路
java·开发语言·算法
Monly217 小时前
Java:修改打包配置文件
java·开发语言
我命由我123457 小时前
Android 广播 - 静态注册与动态注册对广播接收器实例创建的影响
android·java·开发语言·java-ee·android studio·android-studio·android runtime
island13147 小时前
CANN ops-nn 算子库深度解析:核心算子(如激活函数、归一化)的数值精度控制与内存高效实现
开发语言·人工智能·神经网络