文件级建议性锁函数flock

extern int flock (int __fd, int __operation) __THROW;

这个函数是 Linux 下进程间文件同步的基础工具,尤其适用于日志写入、配置文件修改等需要避免并发冲突的场景。
函数核心含义:

flock() 是 Unix/Linux 系统提供的文件级建议性锁函数(注意:不是强制性锁),用于对整个文件加锁 / 解锁,避免多进程 / 多线程同时操作文件导致数据错乱。

extern:表示函数声明来自外部(通常是系统库)

int __fd:文件描述符(通过 open() 或 dup() 等函数获取)

int __operation:锁操作指令(加锁 / 解锁 / 非阻塞加锁等)

__THROW:是 GCC 的宏,标识函数不会抛出 C++ 异常(仅编译提示)

返回值:成功返回 0,失败返回 - 1(并设置 errno)

关键参数:__operation(锁操作指令)

__operation 支持以下核心取值(需包含 <sys/file.h> 头文件):

LOCK_SH 共享锁(读锁):多个进程可同时加共享锁,适用于只读操作

LOCK_EX 排他锁(写锁):同一时间仅一个进程能加排他锁,适用于写操作

LOCK_UN 解锁:释放已持有的文件锁

LOCK_NB 非阻塞模式:和 LOCK_SH/LOCK_EX 按位或使用,加锁失败不阻塞

  1. 基础示例:排他锁(写文件时加锁)
cpp 复制代码
#include <iostream>
#include <fcntl.h>    // open()
#include <sys/file.h> // flock()
#include <unistd.h>   // write(), close()
#include <cstring>    // strerror()
#include <cerrno>     // errno
using namespace std;

int main() {
    // 1. 打开文件(读写模式,不存在则创建,权限0644)
    int fd = open("test.txt", O_RDWR | O_CREAT, 0644);
    if (fd == -1) {
        cerr << "打开文件失败:" << strerror(errno) << endl;
        return 1;
    }

    // 2. 加排他锁(阻塞模式:锁被占用时等待)
    if (flock(fd, LOCK_EX) == -1) {
        cerr << "加排他锁失败:" << strerror(errno) << endl;
        close(fd);
        return 1;
    }
    cout << "成功获取排他锁,开始写文件..." << endl;

    // 3. 写文件(临界区:确保只有当前进程操作)
    const char* content = "Hello, flock()!\n";
    write(fd, content, strlen(content));

    // 4. 模拟业务处理(比如睡眠5秒,验证锁的阻塞效果)
    sleep(5);

    // 5. 解锁
    if (flock(fd, LOCK_UN) == -1) {
        cerr << "解锁失败:" << strerror(errno) << endl;
        close(fd);
        return 1;
    }
    cout << "已释放锁" << endl;

    // 6. 关闭文件描述符
    close(fd);
    return 0;
}
  1. 非阻塞加锁(避免进程阻塞)
cpp 复制代码
#include <iostream>
#include <fcntl.h>
#include <sys/file.h>
#include <unistd.h>
#include <cstring>
#include <cerrno>
using namespace std;

int main() {
    int fd = open("test.txt", O_RDWR);
    if (fd == -1) {
        cerr << "打开文件失败:" << strerror(errno) << endl;
        return 1;
    }

    // 非阻塞排他锁:LOCK_EX | LOCK_NB
    if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
        if (errno == EWOULDBLOCK) { // 锁被占用
            cerr << "文件已被锁定,无法获取锁(非阻塞模式)" << endl;
        } else { // 其他错误
            cerr << "加锁失败:" << strerror(errno) << endl;
        }
        close(fd);
        return 1;
    }

    cout << "非阻塞模式获取锁成功" << endl;
    // 业务操作...
    flock(fd, LOCK_UN);
    close(fd);
    return 0;
}
  1. 共享锁(读文件时加锁)
cpp 复制代码
#include <iostream>
#include <fcntl.h>
#include <sys/file.h>
#include <unistd.h>
#include <cstring>
#include <cerrno>
using namespace std;

int main() {
    int fd = open("test.txt", O_RDONLY);
    if (fd == -1) {
        cerr << "打开文件失败:" << strerror(errno) << endl;
        return 1;
    }

    // 加共享锁(多个进程可同时获取)
    if (flock(fd, LOCK_SH) == -1) {
        cerr << "加共享锁失败:" << strerror(errno) << endl;
        close(fd);
        return 1;
    }

    cout << "获取共享锁,开始读文件..." << endl;
    // 读文件操作...
    
    flock(fd, LOCK_UN); // 解锁
    close(fd);
    return 0;
}

重要注意事项
建议性锁特性 :flock() 是 "建议性锁",即只有所有进程都遵守加锁规则时才有效;如果某个进程不调用 flock() 直接操作文件,锁会失效。
文件描述符生命周期 :锁和文件描述符绑定,关闭文件描述符(close())或进程退出时,内核会自动释放锁。
跨平台注意:flock() 是 Unix/Linux 特有,Windows 系统需用 LockFile() 等替代。

相关推荐
不想写代码的星星17 小时前
std::function 详解:用法、原理与现代 C++ 最佳实践
c++
樱木Plus3 天前
深拷贝(Deep Copy)和浅拷贝(Shallow Copy)
c++
RuoZoe4 天前
重塑WPF辉煌?基于DirectX 12的现代.NET UI框架Jalium
c语言
blasit4 天前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
肆忆_6 天前
# 用 5 个问题学懂 C++ 虚函数(入门级)
c++
不想写代码的星星6 天前
虚函数表:C++ 多态背后的那个男人
c++
端平入洛7 天前
delete又未完全delete
c++
祈安_8 天前
C语言内存函数
c语言·后端
端平入洛8 天前
auto有时不auto
c++
norlan_jame9 天前
C-PHY与D-PHY差异
c语言·开发语言