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 环境中进行测试。
相关推荐
源代码•宸39 分钟前
C++高频知识点(十三)
开发语言·c++·经验分享·面经
wa的一声哭了1 小时前
python基础知识pip配置pip.conf文件
java·服务器·开发语言·python·pip·risc-v·os
Kay_Liang1 小时前
MySQL SQL语句精要:DDL、DML与DCL的深度探究
开发语言·数据库·sql·mysql·database
流形填表1 小时前
AI 助力:如何批量提取 Word 表格字段并导出至 Excel
开发语言·人工智能·word·excel·办公自动化
每天吃饭的羊2 小时前
箭头函数(Arrow Functions)和普通函数(Regular Functions)
开发语言·javascript·ecmascript
寻觅~流光2 小时前
封装---统一封装处理页面标题
开发语言·前端·javascript·vue.js·typescript·前端框架·vue
geovindu2 小时前
Java: OracleHelper
java·开发语言·oracle
Q_Q19632884752 小时前
python的平安驾校管理系统
开发语言·spring boot·python·django·flask·node.js·php
遇见尚硅谷3 小时前
C语言:游戏代码分享
c语言·开发语言·算法·游戏
小刘|4 小时前
单例模式详解
java·开发语言·单例模式