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 环境中进行测试。
相关推荐
言乐610 小时前
Python游戏水平测试辅助系统
开发语言·python·游戏·django·pygame
WWJA王文举17 小时前
I²C通信完整流程详解:START、地址、ACK、数据、Repeated START和STOP一次讲透
c语言·开发语言
zhanghaha131418 小时前
Python进阶教程:6_JSON 数据解析 —— 新手完全指南
开发语言·python·json
qq_4480111619 小时前
C语言中的动态内存分配
c语言·开发语言·php
汉字萌萌哒20 小时前
2024CSP-J入门级C++真题详解
开发语言·c++
arbboter20 小时前
【网络工具】NetProxy网络代理用户手册
开发语言·网络·c#·网络代理·网络异常·代理工具
汉字萌萌哒21 小时前
2019CCF-CSP入门级C++试题解析
java·开发语言·c++
叠层归一研究院21 小时前
AGI 系统(十一):二阶网络 — 二阶递归 × 多主体 (元符号网络)
开发语言·人工智能·算法·php·agi
小雨笙笙21 小时前
C语言:变量三属性——存储类型
c语言·开发语言
果果燕1 天前
C++ 学习笔记(二):类与对象—— 构造函数与析构函数
开发语言·c++