fcntl函数原型如下:int fcntl(int fd, int cmd, ... /* struct flock *arg */); 包含在<fcntl.h>中。
第三个参数是指向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; /* relative starting offset in bytes */
off_t l_len; /* #bytes; 0 means until end-of-file */
pid_t l_pid; /* PID return by F_GETLK */
};
cmd参数有三个值:
F_SETLK:获取或释放由arg指向的flock结构所描述的锁,若无法获取锁,则立刻返回一个EACCES或EAGAIN错误而不阻塞。
F_SETLKW :与F_SETLK不同的是,如果无法获取的锁,将阻塞直到获取锁为止,W即wait
F_GETLK:检查由arg指向的锁以确定是否有某个已存在的锁。若不存在锁在将arg指向的l_type成员设置为F_UNLCK,若存在锁,则返回arg所指向的flock结构信息。
flock结构描述锁的类型(读出锁或写入锁)以及待锁住的字节范围。锁定整个文件的两种方法:
(1)指定l_whence成员为SEEK_SET,l_start成员为0,l_len成员为0。(最常用方法)
(2)使用lseek把读写指针定位到文件,然后指定l_whence成员为SEEK_CUR、l_start成员为0,l_len成员为0。
注意:
对于一个打开着某个文件的给定进程来说,当它关闭该文件的所有描述符或它本身终止时,与该文件关联的所有锁都被删除。
锁不能通过fork由子进程继承。
单进程时,对文件加锁,新锁会代替已有的锁。
当前区域无锁,可加读锁 或 可加写锁;
当前区域读锁,可加读锁 或 不可加写锁;
当前区域写锁,不可加读锁 或 不可加写锁;
当前区域多读一写;
#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)
#define is_read_lockable(fd,offset,whence,len) !lock_test(fd,F_RDLCK,offset,whence,len)
#define is_write_lockable(fd,offset,whence,len) !lock_test(fd,F_WRLCK,offset,whence,len)
int lock_reg(int fd,int cmd,int type,off_t offset,int whence,off_t len)
{
struct flock lock;
lock.l_type = type;
lock.l_start = offset;
lock.l_whence = whence;
lock.l_len = len;
return (fcntl(fd,cmd,&lock));
}
pid_t lock_test(int fd,int type,off_t offset,int whence,off_t len)
{ struct flock lock;
lock.l_type = type;
lock.l_start = offset;
lock.l_whence = whence;
lock.l_len = len;
if(fcntl(fd,F_GETLK,&lock) == -1)
{ return (-1); //error }
//region is not locked
if(lock.l_type == F_UNLCK)
return (0);
return (lock.l_pid);
}