Posix fcntl记录上锁
记录上锁的Posix接口是fcntl函数
#include <fcntl.h>
int fcntl(int fd, int cmd, .../* struct flock *arg */);
成功时取决于cmd,出错时为-1
用于记录上锁的cmd参数共有三个值。这三个命令要求第三个参数arg是指向某个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;
off_t l_len;
pid_t l_pid;
};
1、F_SETLK: 获取(l_type成员为F_RDLCK或F_WRLCK)或释放(l_type成员为F_UNLCK)由arg指向的flock结构所描述的锁。如果该锁无法授予调用进程,该函数就立即返回一个EACCESS或EAGAIN错误而不阻塞
2、F_SETLKW:该命令与上一个命令类似,然而,如果所请求的锁无法授予调用进程,调用线程将阻塞到该锁能够授予为止。
3、F_GETLK:检查由arg指向的锁以确定是否有某个已存在的锁会妨碍新锁授予调用进程。如果当前没有这样的锁存在,由arg指向的flock结构的l_type成员就被置为F_UNLCK。否则,关于这个已存在锁的信息将在由arg指向的flock结构中返回,其中包括持有该锁的进程的进程ID。发出F_GETLK命令后紧接着发出F_SETLK命令不是一个原子操作。这就是说,如果我们发出F_GETLK命令,并且执行该命令的fcntl函数返回时置l_type成员为F_UNLCK,那么跟着立即发出F_SETLK命令不能保证其fcntl函数会成功返回。这两次调用 之间可能有另外一个进程运行并获取了我们想要的锁。
提供F_GETLK命令的原因在于:当执行F_SETLK命令的fcntl函数返回一个错误时,导致该错误的某个锁的信息可由F_GETLK命令返回,从而允许我们确定是哪个进程锁住了所请求的文件区,以及上锁方式(读出锁或写入锁)
l_len成员指定从该偏移开始的连续字节数。长度为0意思是从起始偏移到文件偏移的最大可能值。因此锁住整个文件表两种方式:
1、指定l_whence成员为SEEK_SET,l_start成员为0,l_len成员为0
2、使用lseek把读写指针定位到文件头,然后指定l_whence成员为SEEK_CUR,l_start成员为0,l_len成员为0