文件锁
优点
缺点
文件锁
什么是文件锁
- 英文名:file lock,在同一时刻只允许一个进程对文件进行访问
- 建议性锁:advisory locking,又称协调锁
- 内核只提供加减锁以及检测是否加锁,不提供锁的控制与协调工作
- 需要多进程相互检测确认的加锁机制
- A进程对一个操作的文件加了锁
- B进程同样对该文件进行读写操作
- 只有当B进程也对该文件加锁,文件锁才能起到同步作用
- Linux一般使用建议锁
- 强制性锁:mandatory locking
- 进程对文件进行I/O操作是,内核内部会检测该文件是否被加锁
- A进程对一个操作的文件加了锁
- 当B进程对该文件进行I/O操作时,内核若检测该文件加了强制锁,B进程的操作则会失败
文件锁使用接口
系统调用:flock
- 函数原型:int flock(int fd, int operation);
- 函数功能:给整个文件添加或解除一个建议锁
- 函数参数:operation
- LOCK_SH:共享锁
- LOCK_EX:独占锁、排他锁
- LOCK_UN:移除锁
- TIPS
- flock只提供加锁、解锁机制、并不提供锁检查
- 需要用户自己检测,达到多进程同步操作
- 用户若不自己检测,同样可以对一个已经加锁的文件进行读写操作
int main(int argc, char *argv[])
{
int fd, i;
char filename[] = "data.log";
extern int errno;
fd = open(filename, O_WRONLY | O_CREAT, 0666);
if (fd != -1)
{
printf("open file %s success \n", filename);
printf("please input a num to lock the file.");
scanf("%d", &i);
printf("try to lock the file...\n");
if (flock(fd, LOCK_EX) == 0)
printf("lock file success\n");
else
printf("lock file failed\n");
write(fd, "hello", 5);
printf("input a num to Unlink the file.\n");
scanf("%d", &i);
if (flock(fd, LOCK_UN) == 0)
printf("file unlock success\n");
else
printf("file unlock failed\n");
while(1);
}
else
{
perror("open");
exit(EXIT_FAILURE);
}
return 0;
}
系统调用:fcntl
- 函数原型:int fcntl(int fd, int cmd, .../* arg */);
- 函数功能:给文件(部分文件)进行加锁、解锁操作
- 函数参数:cmd
- F_SETLK:非阻塞式申请锁
- F_SETLKW:阻塞式申请锁
- F_GETLK:获取锁的相关信息
- 记录锁
- 读锁F_RDLCK,写锁F_WRLCK,释放锁F_UNLCK
int main(int argc, char *argv[])
{
if (argc > 1)
{
int fd = open(argv[1], O_WRONLY | O_CREAT, 0777);
if (fd == -1)
{
perror("open");
exit(EXIT_FAILURE);
}
static struct flock lock;
lock.l_type = F_WRLCK;
lock.l_start = 0;
lock.l_whence= SEEK_SET;
lock.l_len = 0;
lock.l_pid = getpid();
printf("trying lock %s ...\n", argv[1]);
int ret = fcntl(fd, F_SETLKW, &lock);
if (ret == 0)
{
printf("lock %s success\n", argv[1]);
while(1);
}
}
return 0;
}
系统调用:lockf
- 函数原型:int lockf(int fd, int cmd, off_t len);
- 函数功能:
- 可以更细粒度地对文件进行加锁、解锁操作
- 库函数lockf是对系统调用fcntl的封装
- 函数参数:operation
- F_LOCK:对文件某一区域添加独占锁
- F_TLOCK:非阻塞式申请锁
- F_ULOCK:对文件某一区域解锁
int main(int argc, char *argv[])
{
int fd, ret;
int pid;
fd = open("tmp.txt", O_RDWR|O_CREAT, 0666);
ret = flock(fd, LOCK_EX);
printf("flock return ret:%d\n", ret);
ret = lockf(fd, F_LOCK, 0);
printf("lockf return ret:%d\n", ret);
sleep(30);
return 0;
}
|