文件锁方式
文件锁可以进行很多的分类,最常见的主要有读锁与写锁,前者也叫共享锁,后者也叫排斥锁,值得注意的是,多个读锁之间是不会相互干扰的,多个进程可以在同一时刻对同一个文件加读锁;但是,如果已经有一个进程对该文件加了写锁,那么其他进程则不能对该文件加读锁或者写锁,直到这个进程将写锁释放,因此可以总结为:对于同一个文件而言,它可以同时拥有多个读者,但是在某一时刻,他只能拥有一个写者
一、文件锁的分类
Linux的文件锁主要有两种:flock和lockf
(1)使用角度方面:
- lockf或fcntl实现了更细粒度文件锁,即:记录锁。我们可以使用lockf或fcntl对文件的部分字节上锁
- flock只能对整个文件加锁
(2)是否支持强制锁
- lockf(fcntl)系统调用可以支持强制锁,即当有进程对某个文件上锁之后,其他进程即使不在操作文件之前检查锁,也会在open、read或write等文件操作时发生错误
- flock只支持建议锁,即如果某一个进程对一个文件持有一把锁之后,其他进程仍然可以直接对文件进行各种操作的,比如open、read、write。只有当多个进程在操作文件前都去检查和对相关锁进行锁操作的时候,文件锁的规则才会生效
二、演示程序
Test7-1-1对某个特定文件新建/打开后加写锁,延时一段时间(此时启动test7-1-2)后再向文件中写入一些内容,写完后释放锁,进入死循环等待状态。Test7-1-2同样打开该文件后加读锁,此时会被阻塞,知道7-1-1释放写锁后,7-1-2才会退出阻塞状态,读取7-1-1刚才写入的内容后进入死循环等待状态。
//test7-1-1
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/file.h>//flock
#define PATH "myfile"
int main()
{
char buf[]="This text is writen by test7-1-1!";
int fd;
pid_t pid;
pid=fork();
if(pid!=0)//退出父进程,子进程成为守护进程完成下面的任务
return 0;
fd=open(PATH,O_CREAT | O_WRONLY,0666);
if(fd<0)
{
perror("[test7-1-1]Open file fail!");
exit(-1);
}
/*设置非阻塞*/
int flags = fcntl(fd, F_GETFL, 0); //获取文件的flags2值。
fcntl(fd, F_SETFL, flags | O_NONBLOCK); //设置成非阻塞模式;
//LOCK_EX建立互斥锁,0表示成功,-1表示失败
if(flock(fd,LOCK_EX)<0)
{
perror("[test7-1-1]Create lock fail!");
exit(-1);
}
printf("[test7-1-1]Create lock success!\n");
sleep(10);//延时等待test7-1-2打开
if(write(fd,buf,strlen(buf))<0)
{
perror("[test7-1-1]Write fail!");
exit(-1);
}
printf("[test7-1-1]Write data:%s\n",buf);
if(flock(fd,LOCK_UN)<0)
{
perror("[test7-1-1]Unlock fail!");
exit(-1);
}
printf("[test7-1-1]Unlock success!\n");
while(1)
sleep(1);
return 0;
}
//test7-1-2
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/file.h>//flock
#define BUFSIZE 64
#define PATH "myfile"
int main()
{
char buf[BUFSIZE];
memset(buf,0,BUFSIZE);
int fd;
pid_t pid;
pid=fork();
if(pid!=0)//退出父进程,子进程成为守护进程完成下面的任务
return 0;
fd=open(PATH,O_RDONLY,0666);
if(fd<0)
{
perror("[test7-1-2]Open file fail!");
exit(-1);
}
//LOCK_EX建立互斥锁,0表示成功,-1表示失败
//由于flock是建议锁,不会强制执行,因此需要在操作前手动检查是否上锁
while(flock(fd,LOCK_EX | LOCK_NB)<0)
{
perror("[test7-1-2]Create lock fail!");
sleep(1);
}
printf("[test7-1-2]Create lock success!\n");
sleep(2);
if(read(fd,buf,BUFSIZE)<0)
{
perror("[test7-1-2]Read fail!");
exit(-1);
}
printf("[test7-1-2]Read data:%s\n",buf);
//用完后释放读锁
if(flock(fd,LOCK_UN)<0)
{
perror("[test7-1-2]Unlock fail!");
exit(-1);
}
printf("[test7-1-2]Unlock success!\n");
while(1)
sleep(1);
return 0;
}
运行结果: