我是靠谱客的博主 还单身大门,最近开发中收集的这篇文章主要介绍fcntl()记录锁,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

fcntl()函数实现记录锁,在文章http://blog.csdn.net/anonymalias/article/details/9197641讲解得十分详细。
这里我记录的是一些简单的概念及其使用,以后若用到,再回来深究。

1. fcntl()函数的4个常用功能

这里写图片描述
以上是fcntl()函数的常用功能,使用代码基本在http://blog.csdn.net/qq_29344757/article/details/71083191讲解。

2. 记录锁

2.1 函数接口

记录锁也是fcntl()常用功能,cmd取值有:

cmd = F_GETLK: 测试能否建立一把锁
cmd = F_SETLK: 设置锁
cmd = F_SETLKW: 阻塞设置一把锁

fcntl()函数的第3个参数为struct flock结构体类型变量,原型为:

struct flock {
short
l_type;
//锁的类型,取值为F_RDLCK(共享读锁)、F_WRLCK(独占写锁)、F_UNLCK
short
l_whence;
//加锁的起始位置,取值为SEEK_SET、SEEK_CUR、SEEK_END
__kernel_off_t
l_start;
//加锁的起始偏移
__kernel_off_t
l_len;
//上锁的字节数,为0表示从偏移处一直到文件末尾
__kernel_pid_t
l_pid;
//已经占用锁的PID(只对F_GETLK命令有效)
__ARCH_FLOCK_PAD
};

1) F_SETLK: 获取(l_type = F_RDLCK或者F_WRLCK)、释放(l_type = F_UNLCK)由flock结构体所描述的锁。若无法获取锁时,该函数会立即返回错误而不发生阻塞。
2) F_SETLKW: 与F_SETLKW的区别在于,无法操作锁的时候,发生阻塞
3) F_GETLK: 检测是否已经有某个锁已存在调用进程中,如果没有该锁,lock所指向的flock结构体l_type成员就会被置为F_UNLCK,否则已存在的锁的信息将会写入lock所指向的flock结构中

2.2 规则说明

记录锁相当于读写锁的一种扩展类型,在多进程中,记录锁和读写锁一样具有两种锁:共享读锁(F_RDLCK)、独占写锁(F_WRLCK)
1) 共享锁: 文件在给定字节区间,多个进程可以有一把共享读锁,那么允许多个进程以读方式访问该字节区间
2) 独占锁: 文件在给定字节区间,只能有一个进程有一把独占写锁,那么只允许有一个进程以写方式访问该字节区间。
3) 另外,文件在给定的字节区间,若有一把或多把读锁,不能在该字节区再加读写锁,同理,若有一把写锁,就不能在该字节区间再加任何读写锁

如果是在一个进程中对一个文件区间已经加了一把锁,后来该进程中又试图在同一文件区间再加一把锁,那么新锁会覆盖老锁。

测试代码: (摘自《Linux高级程序设计-第3版》P117)

进程2:

// 进程1
struct flock* file_lock(short type, short whence)
{
static struct flock ret;
ret.l_type = type;
//锁的类型: 共享读锁(F_RDLCK)、独占写锁(F_WRLCK)、不锁(F_UNLCK)
ret.l_whence = whence;
//加锁的起始位置
ret.l_start = 0;
//加锁的起始偏移
ret.l_len = 0;
//加锁的区域长度(字节),0表示一直到末尾
ret.l_pid = getpid();
return &ret;
}
int main(int argc, char *argv[])
{
int fd;
int i;
time_t now;
fd = open("./tmp.file", O_WRONLY | O_APPEND);
if (fd < 0)
{
perror("open");
return -1;
}
for (i = 0; i < 1000; i++)
{
//阻塞设置独占写锁
fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
time(&now);
printf("%st%s F_SETLKW lock file %s for 5sn", ctime(&now), argv[0], "tmp.file");
char buf[1024] = {};
sprintf(buf, "hello world %dn", i);
int len = strlen(buf);
if (write(fd, buf, len))
printf("%st%s write file sccessn", ctime(&now), argv[0], "tmp.file");
sleep(5);
//阻塞设置解锁
fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET));
sleep(1);
}
close(fd);
return 0;
}

进程2:

struct flock* file_lock(short type, short whence)
{
static struct flock ret;
ret.l_type = type;
//锁的类型: 共享读锁(F_RDLCK)、独占写锁(F_WRLCK)、不锁(F_UNLCK)
ret.l_whence = whence;
//加锁的起始位置
ret.l_start = 0;
//加锁的起始偏移
ret.l_len = 0;
//加锁的区域长度(字节),0表示一直到末尾
ret.l_pid = getpid();
return &ret;
}
int main(int argc, char *argv[])
{
int fd;
int i;
time_t now;
fd = open("./tmp.file", O_WRONLY | O_APPEND);
if (fd < 0)
{
perror("open");
return -1;
}
for (i = 0; i < 1000; i++)
{
//阻塞设置独占写锁
fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
time(&now);
printf("%st%s F_SETLKW lock file %s for 3sn", ctime(&now), argv[0], "tmp.file");
char buf[1024] = {};
sprintf(buf, "china %dn", i);
int len = strlen(buf);
if (write(fd, buf, len))
printf("%st%s write file sccessn", ctime(&now), argv[0], "tmp.file");
sleep(3);
//阻塞设置解锁
fcntl(fd, F_SETLKW, file_lock(F_UNLCK, SEEK_SET));
sleep(1);
}
close(fd);
return 0;
}

运行结果:
进程1
这里写图片描述
进程2
这里写图片描述
tmp.file的文件内容为:
这里写图片描述

最后

以上就是还单身大门为你收集整理的fcntl()记录锁的全部内容,希望文章能够帮你解决fcntl()记录锁所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(69)

评论列表共有 0 条评论

立即
投稿
返回
顶部