文件锁(二)——文件锁的读锁和写锁
文件锁的读锁和写锁
对文件加锁时可以加两种锁,分别是“读文件锁”和“写文件锁”,简称读锁和写锁。
读锁、写锁之间关系
- 读锁和读锁共享:可以重复加读锁,别人加了读锁在没有解锁之前,我依然可以加读锁,这就是共享。
- 读锁和写锁互斥:别人加了读锁没解锁前,加写锁会失败,反过来也是如此。
- 加锁失败后两种处理方式:
- 阻塞,直到别人解锁然后加锁成功为止。
- 出错返回,不阻塞
- 加锁失败后两种处理方式:
- 写锁与写锁互斥:别人加了写锁在没有解锁前,不能加写锁,加写锁会失败。
加锁失败后两种处理方式:
- 阻塞,直到别人解锁然后加锁成功为止。
- 出错返回,不阻塞
文件的加锁方式
对整个文件的内容加锁
对整个文件加锁是最常用的文件加锁方式。
当你整个文件加锁时,如果文件的长度因为写入新数据或者截短而发生了变化,加锁内容长度会自动变化,保证对内容变化着的整个文件加锁。对文件某部分内容加锁
不过一般来说,对多少内容加锁,就对多少内容解锁。如果你是对整个文件加锁,就将整个文件解锁。
但是实际上加锁和实际解锁的长度不相同,比如我对1000个字节的内容加了锁,但是只对其中的100字节解锁,不过这种情况用的少,知道怎么回事即可。
怎么实现文件的整个加锁和区域解锁呢?
后面再说
再看看fcntl的函数原型
int fcntl(int fd, int cmd, ... /* struct flock *flockptr */ );
第三个参数是...,fcntl函数是一个变参函数,第三个参数用不到时就不写
- 功能
fcntl函数有多种功能,我们这里主要介绍实现文件锁的功能,当cmd被设置的是与文件锁相关的宏时,fcntl就是用来实现文件锁。 - 参数
- fd:文件描述符,指向所需要被加锁的文件
- cmd:实现文件锁时,cmd有三种设置,F_GETLK,F_SETLK和F_SETLKW含义如下:
- F_GETLK
从内核获取文件锁的信息,将其保存到第三个参数,第三个参数struct flock *flockptr,我们这里是要设置文件锁,而不是获取已有的文件锁信息,我们这里用不到这个宏。 - F_SETLK
设置第三个参数所代表的文件锁,而且设置的是非阻塞文件锁,也就是如果加锁失败不会阻塞。也就是说加锁失败后如果不想阻塞的话,就由F_SETLK宏来设置。
此时,需要用到第三个参数:struct flock *flockptr;
使用举例:- 第一步:定义一个struct flock flockptr结构体变量(这个结构体变量就是文件锁)。
- 第二步:设置flockptr的成员,表示你想设置怎样的文件锁
- 第三步:通过第三个参数,将设置好的flockptr的地址传递给fcntl,设置你想要的文件锁
- F_SETLKW
F_SETLKW一样,只不过设置的是阻塞文件锁,也就是说加锁不成功的话就阻塞,是由F_SETLKW宏来决定的。
- F_GETLK
- int fcntl(int fd, int cmd, ... /* struct flock *flockptr */ );
- 第三个参数
- 第三个参数设置为什么视情况而定,如果fcntl用于实现文件锁的话,第三个参数为struct flock *flockptr,flockptr代表的就是文件锁。
- 对flockptr的成员设置为特定的值,就可以将文件锁设置为你想要的锁。
- struct flock结构体如下:
struct flock {...short l_type; /* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */short l_whence; /* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */off_t l_start; /* Starting offset for lock */off_t l_len; /* Number of bytes to lock */pid_t l_pid; /* PID of process blocking our lock(set by F_GETLK and F_OFD_GETLK) */... };
- 第三个参数
成员说明:
l_type:锁类型
- F_RDLCK:读锁(或称共享锁)
- F_WRLCK:写锁
- F_UNLCK:解锁
l_whence:加锁位置粗定位,设置同lseek的whence
- SEEK_SET:文件开始处
- SEEK_CUR:文件当前位置处
- SEEK_END:文件末尾位置处
- l_whence这个与lseek函数的whence是一个含义
l_start:精定位,相对于l_whence的偏移,与lseek的offset的含义完全一致
通过l_whence和l_start的值,就可以用来指定从文件的什么位置开始加锁,不过一般来说,我们会将l_whence指定为SEEK_SET,l_start指定为0,表示从整个文件头上开始加锁。l_len:从l_whence和l_start所指定的起始地点算起,需要对文件多长的内容加锁。
如果 l_len被设置0,表示一直加锁到文件结尾,如果文件长度时变化的,将自动调整加锁的末尾位置。
将l_whence和l_start设置为SEEK_SET和0,然后再将l_len设置为0,就表示从文件加锁到文件末尾,其实就是对整个文件加锁。
如果只是对文件中间的某段加锁,这只是区域加锁,加区域锁时可以给文件n多个的独立区域加锁。
l_pid:当前正加锁进程的PID
代码演示
使用文件锁的互斥操作,解决父子进程向同一文件写"hello",“world\n”时,hello hello world相连的问题。
头文件,学到了封装函数的思想,尤其是使用宏来实现不同类型的文件锁
/* Too many parameters ,Different types of locks* Write dead!!!!!!!!!* */
/* Set non blocking write lock */
#define SET_WRFLCK(fd, l_whence, l_start, l_len) \set_filelock(fd, F_SETLK, F_WRLCK, l_whence, l_start, l_len)/* Set blocking write lock */
#define SET_WRFLCKW(fd, l_whence, l_start, l_len) \set_filelock(fd, F_SETLKW, F_WRLCK, l_whence, l_start, l_len)/* Set blocking read lock */
#define SET_RDFLCKW(fd, l_whence, l_start, l_len) \set_filelock(fd, F_SETLKW, F_RDLCK, l_whence, l_start, l_len)/* Set nonblocking read lock */
#define SET_RDFLCK(fd, l_whence, l_start, l_len) \set_filelock(fd, F_SETLK, F_RDLCK, l_whence, l_start, l_len)/* Unlock */
#define SET_UNFLCK(fd, l_whence, l_start, l_len) \set_filelock(fd, F_SETLK, F_UNLCK, l_whence, l_start, l_len)/*Package and set the locking function* */
static void set_filelock(int fd, int ifwait, short l_type, short l_whence, off_t l_start, short l_len)
{int ret = 0;struct flock flock;flock.l_type = l_type;flock.l_whence = l_whence;flock.l_start = l_start;flock.l_len = l_len;ret = fcntl(fd, ifwait, &flock);if (ret == -1){perror("fcntl");exit(EXIT_FAILURE);}
}
int main(int argc, char *argv[])
{int fd = 0;int ret = 0;fd = open("./hello", O_RDWR|O_CREAT|O_TRUNC, 0664);if (fd == -1) print_err("./hello", __LINE__, errno); ret = fork();if (ret > 0){while(1){SET_WRFLCKW(fd, SEEK_SET, 0, 0);write(fd, "hello ", 6);write(fd, "world\n", 6);SET_UNFLCK(fd, SEEK_SET, 0, 0);}}else if (ret == 0){while(1){SET_WRFLCKW(fd, SEEK_SET, 0, 0);write(fd, "hello ", 6);write(fd, "world\n", 6);SET_UNFLCK(fd, SEEK_SET, 0, 0);}}return 0;
}
在hello文件里面使用/hello hello没找到文本内容说明成功了。
对于fcntl的认识不仅仅可以追加改变文件标志,还可以实现文件锁的功能
文件锁(二)——文件锁的读锁和写锁相关推荐
- 文件锁(三)——文件锁的原理
文件锁的原理 理解了文件锁的原理后,就可以理解为什么文件锁可以实现互斥与共享了. 若A进程与B进程同时打开同一个文件,他们使用同一个文件表,使用同一个V节点,V节点指向hello这个文件,里面有一个锁 ...
- mysql的锁机制(读锁,写锁,表锁,行锁,悲观锁,乐观锁,间隙锁)
读锁和写锁 介绍 MyISAM表锁中的读锁和写锁 读锁(共享锁S): 对同一个数据,多个读操作可以同时进行,互不干扰.加锁的会话只能对此表进行读操作,其他会话也只能进行读操作.MyISAM的读默认是加 ...
- 理解悲观锁乐观锁、同步锁、读锁、写锁
ava 锁分类 Java 中的锁有很多,可以按照不同的功能.种类进行分类,下面是我对 Java 中一些常用锁的分类,包括一些基本的概述 从线程是否需要对资源加锁可以分为 悲观锁 和 乐观锁 从资源已被 ...
- 图文深入解析 JAVA 读写锁,为什么读锁套写锁会死锁,反过来却不会?
一.回顾基本的读写锁 我们知道读写锁 #java.util.concurrent.locks.ReentrantReadWriteLock 是一个 "读写互斥,写写互斥,读读共享" ...
- mysql locking_Mysql next-key locking,读锁,写锁
MySQL innodb的间隙锁定(next-key locking)是为了防止幻读(phantom read), 当MySQL的isolation level设为repeatable read的时候 ...
- MySQL:行锁、表锁、乐观锁、悲观锁、读锁、写锁
1.锁的分类 1.1从对数据操作的类型来分 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响. 结论1: --如果某一个会话 对A表加了read锁,则 该会话 可以对A表进行读操作 ...
- MySQL中的读锁和写锁
转载自 MySQL中的读锁和写锁 在数据库的锁机制中介绍过,数据的锁主要用来保证数据的一致性的,数据库的锁从锁定的粒度上可以分为表级锁.行级锁和页级锁.在我的博客中重点介绍过MySQL数据库的行级锁. ...
- mysql乐观锁与事务_Mysql中的读锁,写锁,乐观锁及事务隔离级别和并发问题
mysql读锁,写锁,乐观锁 读锁,也叫共享锁(shared lock) SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE 写锁,也叫排他 ...
- 读锁(共享锁)写锁(独占锁)解析
读锁(共享锁)写锁(独占锁)解析 在多线程环境下一个资源类被读是没有任何问题的,所以满足并发要求,但是,如果有一个线程去写共享资源,那么就不应该再有其他线程可以对该资源进行读或写了.也就是说,读-读可 ...
最新文章
- 茅台App首发就登顶!单日下载量43万,甚至还没开始试运行
- 通用数据库管理工具DBeaver
- 工具用的好下班走的早
- 全球及中国医用敷料市场销售前景与竞争格局研究报告2022版
- java类与对象实验_JAVA类与对象实验报告
- 一个程序如何连接到外网_如何开发制作小程序?做一个电商带直播小程序
- threejs 加载两个场景_threejs中的三维场景操作
- python发送包含html、图片、附件和链接的邮件
- 我如何将Google I / O 2018的兴奋带给尼日利亚沃里的115个人
- python 函数式编程包_python 函数支持函数式编程的包operator partial
- Oracle→简介、用户、数据字典、表空间及其文件
- paroot忘记root密码
- 405.十六进制数 (力扣leetcode) 博主可答疑该问题
- mysql数据库表中重命名语句_mysql数据库重命名sql语句
- ArcGIS小图斑根据相邻地类属性融合。
- 处理安全检查的项目代码异常解决记录
- 电脑英语Computer English
- 如何在虚拟一个USB设备
- 深入剖析JDK动态代理源码实现
- Android View部分消失效果实现
热门文章
- 电脑桌面计算机打开无响应,电脑任务栏假死点击没反应的解决方法(win7与xp)
- framemaker中遍历及判断其属性是否存在
- $wnd and $doc Calling native JavaScript with JSNI
- 【RL系列】马尔可夫决策过程——Gambler's Problem
- 基于激光雷达的室内探测系统
- C语言(经典编程题:报数游戏)
- Mac下用docker安装阿波罗Apollo
- 2022最新SCI影响因子TOP100榜单
- 会php学java入门要多久_php自学需要多久
- [日常]mov文件转换为gif