多进程/多线程并发编程,系统编程基础

文件锁技术详解:flock与fcntl系统调用

文件锁技术详解:flock与fcntl系统调用


一、flock系统调用

1.1 功能描述

flock()提供文件级全局锁机制,可对整个文件施加共享锁或互斥锁。该锁为建议性锁(需主动检查),常用于进程间同步文件访问,但不保证强制排他性。

1.2 函数声明

#include <sys/file.h>
int flock(int fd, int operation);

1.3 参数详解

参数类型说明
fdint文件描述符,需通过open()fileno(FILE*)获取
operationint锁操作类型,支持以下宏组合:
- LOCK_SH:共享锁(允许多进程并发读)
- LOCK_EX:互斥锁(仅允许单进程读写)
- LOCK_UN:释放锁
- LOCK_NB:非阻塞模式(与上述宏用 `` 组合,锁冲突时立即返回)

1.4 返回值

成功:返回0
失败:返回-1,错误码存于errno,常见错误:
EAGAIN:非阻塞模式下锁冲突
EBADF:无效文件描述符
EINTR:被信号中断


二、fcntl系统调用

2.1 功能描述

fcntl()支持记录级细粒度锁,可对文件指定区域加锁。提供强制锁建议锁两种模式(依赖文件系统支持),具备更精细的控制能力。

2.2 函数声明

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, struct flock *lock);

2.3 参数详解

参数类型说明
fdint文件描述符
cmdint锁操作命令:
- F_GETLK:检测锁状态(不实际加锁)
- F_SETLK:非阻塞式设置/释放锁
- F_SETLKW:阻塞式设置锁(等待锁释放)
lockstruct flock*描述锁类型与范围的指针,结构体成员如下:
struct flock {                                                      
   short l_type;   // 锁类型:F_RDLCK/F_WRLCK/F_UNLCK              
   short l_whence; // 基准位置:SEEK_SET/SEEK_CUR/SEEK_END         
   off_t l_start;  // 偏移量(相对于l_whence)                     
   off_t l_len;    // 锁定字节数(0表示至文件尾)                  
   pid_t l_pid;    // 持有锁的进程ID(F_GETLK时填充)             
};                                                                  

2.4 返回值

成功:根据cmd不同返回不同:
F_GETLK:非负值(锁信息存于lock结构)
F_SETLK/F_SETLKW0
失败:返回-1,常见错误:
EACCES/EAGAIN:锁冲突(非阻塞模式)
EDEADLK:死锁风险(仅限F_SETLKW
EINVAL:无效参数


三、关键特性对比

特性flockfcntl
锁粒度整个文件文件区域(字节级)
锁类型共享/互斥共享/互斥/释放
阻塞控制支持LOCK_NB非阻塞通过F_SETLK/F_SETLKW区分
锁继承子进程不继承锁子进程继承锁
锁检测需显式调用检查内置锁状态查询(F_GETLK
跨进程兼容性fcntl锁互斥flock锁互斥
自动放锁关闭一个文件的所有文件描述符关闭一个文件的任意文件描述符

四、应用场景建议

简单同步:优先使用flock,代码简洁且适用于全文件锁定
高性能并发:选择fcntl,利用区域锁减少竞争
强制锁需求:需结合文件系统配置(如mount -o mand
单实例daemon:在/var/run下创建“进程号.pid”文件,并持有该文件的POSIX写锁。一旦有另一个进程运行同一个程序,发现取得不了锁后就知道已经有一个实例在运行了。一般该文件先用truncate或fturncate截断为长度0,然后写入进程的pid,最后在程序结束的时候删除(remove或unlink)该文件防止占用文件系统资源。

回复

This is just a placeholder img.