要讲解记录锁机制,首先要介绍fcntl函数,如下给出该函数原型:
#include <fcntl.h> int fcntl(int filedes, int cmd, ... /* struct flock *flockptr */)函数返回值:若成功则依赖于cmd,若出错则返回-1。
对于记录锁,cmd是F_GETLK, F_SETLOCK, F_SETLKW。第三个参数(称其为flockptr)是一个指向flock结构的指针:
struct flock { short l_type; /* F_RDLCK, F_WRLCK, or F_UNLCK */ off_t l_start; /* offset in bytes, relative to l_whence */ short l_whence; /* SEEK_SET, SET_CUR, or SEEK_END */ off_t l_len; /* length, in bytes; 0 means lock to EOF */ pid l_pid; /* returned with F_GETLK */ };对flock结构说明如下:
F_GETLK:判断由flockptr锁描述的锁是否会被另外一把锁所排斥(阻塞)。如果存在一把锁,它阻止创建由flockptr所描述的锁,则把该现存锁的信息写到flockptr指向的结构中。如果不存在这种情况,则将l_type设置为F_UNLOCK外,flockptr所指向结构的其他信息保持不变。
F_SETLK:设置由flockptr所描述的锁。如果试图建立一把读锁(l_type设为F_RDLCK)或写锁(l_type设为F_WRLCK),而按兼容性规则不能允许的情况,fcntl立即出错返回,此时errno设置为EACCES或EAGAIN。此命令也用来清除由flockptr说明的锁(l_type为F_UNLCK)。
F_SETLKW:这是F_SETLK的阻塞版本。如果因为当前在请求区间的某个部分另一个进程已经有一把锁,因而按兼容性规则由flockptr所请求的锁不能被创建,则使调用进程休眠。如果请求创建的锁已经可用,或者休眠由信号中断,则该进程被唤醒。
实际编程中,为了避免每次分配flock结构,然后又填入各项信息,可以用如下函数两处理所有这些细节:
#include <fcntl.h> int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len) { struct flock lock; lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */ lock.l_start = offset; /* byte offset, relative to l_whence */ lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */ lock.l_len = len; /* #bytes (0 means to EOF) */ return(fcntl(fd, cmd, &lock)); }其他的加读、写或解文件锁的操作就可以定义为如下的宏:
#define read_lock(fd, offset, whence, len) lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len)) #define readw_lock(fd, offset, whence, len) lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len)) #define write_lock(fd, offset, whence, len) lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len)) #define writew_lock(fd, offset, whence, len) lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len)) #define un_lock(fd, offset, whence, len) lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))
原文:http://blog.csdn.net/tiankonguse/article/details/29403143