fcntl()函数在前面系列内容中已经多次用到了,它是一个多功能文件描述符管理工具箱,通过配合不同的 cmd 操作命令来实现不同的功能。为了方便述说,这里再重申一次:
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* struct flock *flockptr */ );
与锁相关的 cmd 为 F_SETLK、F_SETLKW、F_GETLK,第三个参数 flockptr 是一个 struct flock 结构体指针。使用 fcntl()实现文件锁功能与 flock()有两个比较大的区别:
- flock()仅支持对整个文件进行加锁/解锁;而 fcntl()可以对文件的某个区域(某部分内容)进行加锁 /解锁,可以精确到某一个字节数据。
- flock()仅支持建议性锁类型;而 fcntl()可支持建议性锁和强制性锁两种类型。
我们先来看看 struct flock 结构体,如下所示:
struct flock {
...
short l_type; /* Type of lock: F_RDLCK,F_WRLCK, F_UNLCK */
short l_whence; /* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */
off_t l_start; /* Starting offset for lock */
off_t l_len; /* Number of bytes to lock */
pid_t l_pid; /* PID of process blocking our lock(set by F_GETLK and F_OFD_GETLK) */
...
};
对 struct flock 结构体说明如下:
- l_type:所希望的锁类型,可以设置为 F_RDLCK、F_WRLCK 和 F_UNLCK 三种类型之一,F_RDLCK 表示共享性质的读锁,F_WRLCK 表示独占性质的写锁,F_UNLCK 表示解锁一个区域。
- l_whence 和 l_start:这两个变量用于指定要加锁或解锁区域的起始字节偏移量,与lseek()函数中的 offset 和 whence 参数相同,这里不再重述。
- l_len:需要加锁或解锁区域的字节长度。
- l_pid:一个 pid,指向一个进程,表示该进程持有的锁能阻塞当前进程,当 cmd=F_GETLK 时有效。
以上便是对 struct flock 结构体各成员变量的简单介绍,对于加锁和解锁区域的说明,还需要注意以下几项规则:
- 锁区域可以在当前文件末尾处开始或者越过末尾处开始,但是不能在文件起始位置之前开始。
- 若参数 l_len 设置为 0,表示将锁区域扩大到最大范围,也就是说从锁区域的起始位置开始,到文 件的最大偏移量处(也就是