记录锁的功能是:当一个进程正在读或修改文件的某个部分时,它可以阻止其它进程修改同一文件区。fcntl函数可以实现这一功能。
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
对于记录锁,cmd是F_GETLK、F_SETLK或F_SETLKW,第三个参数是一个指向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
(F_GETLK only) */
...
};
使用记录锁的规则是:多个进程在一个给定的字节上可以有一把共享的读锁,但是在一个给定字节上只能有一个进程独用的一把写锁。如果在一个给定的字节上已经有一把或多把读锁,则不能在该字节上再加写锁;如果在一个字节上已经有一把独占性的写锁,则不能再对它加任何读锁。
记录锁可以自动继承,也会自动释放,规则如下:
(1)当一个进程终止时,它所建立的锁全部释放。
(2)任何时候关闭一个描述符时,则该进程通过这个描述符可以引用的文件上的任何一把锁都被释放。
(3)由fork产生的子进程不继承父进程所设置的锁。
(4)在执行exec后,新程序可以继承原执行程序的锁。但是如果一个文件描述符设置了close-on-exec标志,那么当作为exec的一部分关闭该文件描述符时,对相应文件的所有锁都被释放了。
记录锁有建议性锁和强制性锁两种机制,它们并不是真正的锁,而是一种能对记录锁效果产生影响的机制。
建议性锁:每个使用文件的进程都要主动检查该文件是否有锁存在,当然都是通过具体锁的API,比如fcntl记录锁F_GETTLK来主动检查是否有锁存在。如果有锁存在并被排斥,那么就主动保证不再进行接下来的IO操作。如果每一个进程都主动进行检查,并主动保证,那么就说这些进程都以一致性的方法处理锁。但是,不主动判断这个文件有没有加上记录锁,就直接对这个文件进行IO操作,会怎么样呢?这种有破坏性的IO操作会不会成功呢?如果是在建议性锁的机制下,这种破坏性的IO就会成功。因为锁只是建议性存在的,并不强制执行。
强制性锁:文件记录锁功能由内核执行。上述提到的破坏性IO操作会被内核禁止。当文件被加锁来进行读写操作时,在锁定该文件的进程释放该锁之前,内核会强制阻止任何对该文件的读或写违规访问,每次读或写访问都得检查锁是否存在。也就是强制性锁机制,让锁变得名副其实,真正达到了锁的效果。
Linux默认为建议性锁,开启强制性锁时,要对一个特定文件打开其设置组ID位并关闭其组执行位,如下:
$chmod g+s <FileName>
$chmod g-x <FileName>
版权声明:本文为博主原创文章,未经博主允许不得转载。