1、当多个用户同时访问一个文件的时候,Linux会采取给文件上锁的机制防止共享资源产生竞争状态。于是便有了文件锁的概念。
2、文件锁包括建议性锁和强制性锁。
建议锁要求每个上锁文件的进程都要检查是否有锁存在,并且尊重已有的锁。在一般情况下内核和操作系统都不使用建议性锁。
3、强制性锁是由内核执行的锁,当一个文件被上锁进行写入操作的时候,内核将阻止其他任何文件对该文件进行读写操作。但是会损耗性能,每次读写操作都会检查是否有锁存在。
4、实现上锁操作的函数由flock以及fcntl。flock主要是实现建议性锁,但是fcntl除了建议性锁还有强制性锁。同时fcntl还能实现记录锁。记录锁包括读取锁(共享锁)和写入锁(排斥锁)。
5、flock函数
功能:锁定文件或解除锁定文件,只能锁定整个文件,无法锁定文件的某一区域。
原型: int flock(int fd,int operation);
参数:operation
LOCK_SH建立共享锁定。多个进程可同时对同一个文件作共享锁定。
LOCK_EX建立互斥锁定。一个文件同时只有一个互斥锁定。
LOCK_UN解除文件锁定状态。
LOCK_NB无法建立锁定时,此操作可不被阻断,马上返回进程。通常与 LOCK_SH或LOCK_EX做OR(|)组合。
flock()根据调用时operation参数传入LOCK_UN的值来释放一个文件锁。此外,锁会在相应的文件描述符被关闭之后自动释放。同时,当一个文件描述符被复制时(dup()、dup2()、或一个fcntl() F_DUPFD操作),新的文件描述符会引用同一个文件锁。
flock(fd, LOCK_EX);
new_fd = dup(fd);
flock(new_fd, LOCK_UN);
这段代码先在fd上设置一个互斥锁,然后通过fd创建一个指向相同文件的新文件描述符new_fd,最后通过new_fd来解锁。
返回值:返回0表示成功,若有错误则返回-1,错误代码存于errno。
表头文件: #include<sys/file.h>
6、fcntl函数
功能:可以施加建议性锁,还可以施加强制锁。同时,fcntl还能对文件的某一记录进行上锁,也就是记录锁。对整个文件区域加锁
原型:int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
参数:
fd
参数fd代表欲设置的文件描述符。
cmd
参数cmd代表打算操作的指令。有以下的几种情况
F_DUPFD:用来查找大于或等于参数arg的最小且仍未使用的文件描述符,并且复制参数fd的文件描述符。
F_GETFD:取得close-on-exec旗标。若此旗标的FD_CLOEXEC位为0,代表在调用exec()相关函数时文件将不会关闭。
F_SETFD 设置close-on-exec 旗标。该旗标以参数arg的FD_CLOEXEC位决定。
F_GETFL 取得文件描述符状态旗标,此旗标为open()的参数flags。
F_SETFL 设置文件描述符状态旗标,参数arg为新旗标,但只允许O_APPEND、O_NONBLOCK和O_ASYNC位的改变,其他位的改变将不受影响。
F_GETLK 取得文件锁定的状态
F_SETLK 设置文件锁定的状态。。此时flcok 结构的l_type值必须是F_RDLCK、F_WRLCK或F_UNLCK。如果无法建立锁定,则返回-1,错误代码为EACCES或EAGAIN。
代码: r = fcntl(fd,F_SETLK,&lk);
if(r == 0) printf("枷锁成功!\n");
else printf("枷锁失败!\n");