一、记录锁 record locking
功能:当一个进程正在读或修改文件的某个部分时,它可以阻止其它进程修改同一文件区。
字节范围锁 byte-range locking
二、历史
flock函数,可以锁整个文件,不能锁文件中的一部分。
fcntl函数,增加了记录锁的功能。
lockf函数,在fcntl基础上构造了lockf函数,提供一个简化的接口。可以锁文件中任意字节数的区域
三、fcntl 记录锁
函数原型:
int fcntl(int fd, int cmd, struct flock *flockptr); /* cmd = F_GETLK,测试能否建立一把锁 cmd = F_SETLK,设置锁 cmd = F_SETLKW, 阻塞设置一把锁 */ //POSIX只定义fock结构中必须有以下的数据成员,具体实现可以增加 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; /* 上锁的字节数*/ pid_t l_pid; /* 已经占用锁的PID(只对F_GETLK 命令有效) */ /*...*/ };
(1)所希望的锁类型:F_RDLCK(共享读锁)、F_WRLCK(独占性写锁)、F_UNLCK(解锁一个区域)。
(2)要加锁或解锁区域的起始字节偏移量由l_start和l_whence两者决定。
(3)注意:该区域可以在当前文件尾端开始或越过其尾端处开始,但是不能在文件起始位置之前开始。
(4)如若l_len为0,则表示锁的区域从其起点(由l_start和l_whence决定)开始直至最大可能偏移量为止。
(5)为了锁住整个文件,我们设置l_start和l_whence,使锁的起点在文件起始处,并说明长度(l_len)为0。
上面提到了两种类型的锁:共享读锁(F_RDLCK)和独占写锁(F_WRLCK),基本规则是:
多个进程在一个给定的字节上可以有一把共享的读锁,但是在一个给定字节上只能有一个进程独用的一把写锁。进一步而言,如果在一个给定字节上已经有一把或多把读锁,则不能再该字节上再加写锁;如果在一个字节上已经有一把独占性的写锁,则不能再对它加任何读锁。
不同进程锁请求的读写锁规则:
------------------- 加读锁 加写锁
无锁 允许 允许
一个或多个读锁 允许 拒绝
一个写锁 拒绝 拒绝
注意:上面这个规则适用于不同进程提出的锁请求,并不适用于单个进程提出的多个锁请求。单个进程提出多个锁请求的时候,以最后一次锁作为标准,即新锁替换旧锁对于同一文件,如果一直有不同的进程连续的对其添加读锁,则其它欲对其添加阻塞写锁的进程有可能延长等待时间(这样的情况,对于添加写锁的进程会出现饿死情况)。
在读锁时,该描述符必须是读打开;加写锁时,该描述符必须是写打开。
F_GETLK: 判断由flockptr所描述的锁是否会被另外一把锁所排斥(阻塞)。如果存在一把锁,它阻止创建由flockptr所描述的锁,则把该现存锁的信息写到flockptr指向的结构中。如果不存在这种情况,则除了将l_type设置为F_UNLCK之外,flockptr所指向结构中的其他信息保持不变。
F_SETLK : 获取(l_type为F_RDLCK或F_WRLCK)或释放由flockptr指向flock结构所描述的锁,如果无法获取锁时,该函数会立即返回一个EACCESS或EAGAIN错误,而不会阻塞。
F_SETLKW: F_SETLKW和F_SETLK的区别是,无法设置锁的时候,调用线程会阻塞到该锁能够授权位置。
这里需要注意的是,用F_GETLK测试能否建立一把锁,然后接着用F_SETLK或F_SETLKW企图建立一把锁,由于这两者不是一个原子操作,所以不能保证两次fcntl之间不会有另外一个进程插入并建立一把相关的锁,从而使一开始的测试情况无效。所以一般不希望上锁时阻塞,会直接通过调用F_SETLK,并对返回结果进行测试,以判断是否成功建立所要求的锁。
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索文件
, 函数
, 阻塞
, 进程
, 字节
, 文件锁
, fcntl
, 锁记录
, 记录锁
, 读锁
, 一个
, flock命令
, lockf
fcntl函数
,以便于您获取更多的相关知识。