在多个进程同时操作同一份文件的过程中,很容易导致文件中的数据混乱,需要锁操作来保证数据的完整性,这里介绍的针对文件的锁,称之为“文件锁”-flock。
flock,建议性锁,不具备强制性。一个进程使用flock将文件锁住,另一个进程可以直接操作正在被锁的文件,修改文件中的数据,原因在于flock只是用于检测文件是否被加锁,针对文件已经被加锁,另一个进程写入数据的情况,内核不会阻止这个进程的写入操作,也就是建议性锁的内核处理策略。
flock主要四种操作类型:
- LOCK_SH,共享锁,多个进程可以使用同一把锁,常被用作读共享锁;
- LOCK_EX,排他锁,同时只允许一个进程使用,常被用作写锁;
- LOCK_UN,释放锁;
- LOCK_NB 无法建立锁定时,此操作可不被阻断,马上返回进程。通常与LOCK_SH或LOCK_EX 做OR(|)组合。
进程使用flock尝试锁文件时,如果文件已经被其他进程锁住,进程会被阻塞直到锁被释放掉,或者在调用flock的时候,采用LOCK_NB参数,在尝试锁住该文件的时候,发现已经被其他服务锁住,会返回错误,errno错误码为EWOULDBLOCK。即提供两种工作模式:阻塞与非阻塞类型。
flock只能对整个文件加锁,不能对文件的一部分进行加锁。
附加flock参数
-s,--shared:获取一个共享锁,在定向为某文件的FD上设置共享锁而未释放锁的时间内,其他进程试图在定向为此文件的FD上设置独占锁的请求失败,而其他进程试图在定向为此文件的FD上设置共享锁的请求会成功。
-x,-e,--exclusive:获取一个排它锁,或者称为写入锁,为默认项
-u,--unlock:手动释放锁,一般情况不必须,当FD关闭时,系统会自动解锁,此参数用于脚本命令一部分需要异步执行,一部分可以同步执行的情况。
-n,--nb, --nonblock:非阻塞模式,当获取锁失败时,返回1而不是等待
-w, --wait, --timeout seconds:设置阻塞超时,当超过设置的秒数时,退出阻塞模式,返回1,并继续执行后面的语句
-o, --close:表示当执行command前关闭设置锁的FD,以使command的子进程不保持锁。
-c, --command command:在shell中执行其后的语句
linux c编程
lockA.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int main()
{
int fd,i;
char path[]="/usr/local/test.txt";
extern int errno;
fd=open(path,O_WRONLY|O_CREAT);
if(fd!=-1)
{
printf("open file %s ./n",path);
printf("please input a number to lock the file./n");
scanf("%d",&i);
if(flock(fd,LOCK_EX)==0)
{
printf("the file was locked./n");
}
else
{
printf("the file was not locked./n");
}
printf("please input a number to unlock the file./n");
scanf("%d",&i);
if(flock(fd,LOCK_UN)==0)
{
printf("the file was unlocked./n");
}
else
{
printf("the file was not unlocked./n");
}
close(fd);
}
else
{
printf("cannot open file %s/n",path);
printf("errno:%d/n",errno);
printf("errMsg:%s",strerror(errno));
}
}
lockB.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
clude <sys/file.h>
int main()
{
int fd,i;
char path[]="/usr/local/test.txt";
char s[]="writing.../nwriting....../n";
extern int errno;
fd=open(path,O_WRONLY|O_CREAT|O_APPEND);
if(fd!=-1)
{
printf("open file %s ./n",path);
if(flock(fd,LOCK_EX|LOCK_NB)==0)
{
printf("the file was locked by the process./n");
if(-1!=write(fd,s,sizeof(s)))
{
printf("write %s to the file %s/n",s,path);
}
else
{
printf("cannot write the file %s/n",path);
printf("errno:%d/n",errno);
printf("errMsg:%s/n",strerror(errno));
}
}
else
{
printf("the file was locked by other process.Can't write.../n");
printf("errno:%d:",errno);
}
close(fd);
}
else
{
printf("cannot open file %s/n",path);
printf("errno:%d/n",errno);
printf("errMsg:%s",strerror(errno));
}
}