Linux-进程间通信(六): 记录锁
1. 记录锁:记录锁的功能是,当一个进程正在读或者修改文件的某个部分的时候,它可以阻止其他进程修改同一文件区;
2. fcntl记录锁:
#include <fcntl.h> int fcntl(int filedes, int cmd, ... /* struct flock *flockptr */); ret = 成功依赖于cmd,出错返回-
对于记录锁,cmd是F_GETLK, F_SETLK, F_SETLKW。
F_GETLK-判断由flockptr描述的锁是否会被另外一把锁排斥,若存在,则把现存锁的信息写入到flockptr中,若不存在,则除了将l_type设置为F_UNLCK之外,结构中其余信息不变;
F_SETLK-设置由flockptr描述的锁,如果按照共享读锁和独占写锁规则,不允许加锁,则立即返回错误码;
-此命令也用于清除flockptr说明的锁,l_type=F_UNLCK
F_SETLKW-是F_SETLK的阻塞版本,当不满足加锁规则时候,进程进入休眠,如果请求创建的锁已经可用,则休眠由信号中断,进程被唤醒;
第三个参数flock结构如下:
struct flock {
short l_type;
off_t l_start;
short l_whence;
off_t l_len;
pid_t l_pid;
};
结构说明:
l_type: 所希望的锁类型,F_RDLCK(共享读锁), F_WRLCK(独占读锁), F_UNLCK(解锁一个区域);
l_start: 相对偏移量;
l_whence: 相对偏移量的起点;可选用的值:SEEK_SET(文件开头), SEEK_CUR(当前位置), SEEK_END(文件结尾)
l_len: 区域字节的长度;
l_pid: 具有阻塞当前进程的锁,其进程ID存放在l_pid;
3. 加锁和解锁区域说明:
(1) l_start是相对偏移量,l_whence决定了相对偏移量的起点;
(2) 该区域可以在当前文件的尾端处开始,但是不能再文件的起始位置之前开始;
(3) 如果l_len=0,则表示锁的区域从l_whence和l_start决定的起点开始,直至最大可能偏移量为止,不管写到该文件多少数据,他们都处于所得范围内;
(4) 为了锁整个文件,我看设置l_start=0和l_whence=SEEK_SET,使所得起点在文件起始处,并且说明长度l_len=0.
4. 共享读锁与独占写锁:
多个进程在给定的字节上可以有一把共享的读锁,但是在一个给定字节上只能有一个进程独占一把写锁;
如果在一个给定字节上已经有了一把或者多把读锁,可以继续添加读锁,但是不能在该字节上加写锁;如果在一个字节上已经有了一把独占写锁,则不能再添加任何读/写锁;
注意:这个规则只适用于不同进程提出的锁请求,如果单个进程对一个文件区间已经有了一把锁,后来又企图对同一文件区加另一把锁,那么新锁将替换旧锁;
5. 记录锁的隐含继承和释放:
(1) 进程终止时,所建立的锁全部被释放;
(2) 关闭任何一个描述符,则该进程通过该描述符可以引用的文件上的任何一把锁都被释放;
(3) fork产生的子进程不继承父进程锁设置的锁;
(4) 在执行了exec后,新程序可以继续执行原来程序的锁;如果对一个描述符设置了close-on-exec,则exec执行时候,文件描述符被关闭,对应锁也被释放;
6. 在文件尾加锁:
(1) 在加锁之前最好是对文件当前位置或者当前长度指定一把锁,因为在lseek和加锁调用之间,可能有另外一个进程在改变该文件的长度;
(2) 下面代码第一次加锁的时候,得到一把锁,从文件尾端开始,包括以后添加的任何数据,都会加锁;解锁的时候,文件尾端已经变化了,所以并没有解锁;
writew_lock(fd, 0, SEEK_END, 0);
write(fd, buf, 1); //这个字节也被加锁
un_lock(fd, 0, SEEK_END, 0); //并没有解锁前面字节,len指定为-1可解锁前面字节
write(fd, buf, 1); //这个字节没被加锁
7. 强制性锁和建议性锁:
合作进程,多个进程都用一致的方式处理记录锁,完成某些任务,这些进程集合就是合作进程;
建议性锁:建议性锁不做强制检查锁规则,需要进程自己获取,检查是否有锁存在,对于合作进程来说,建议性锁是可行的,但是对于某些非合作进程,他们不进程检查,就对文件进行改写,就会对当前文件造成影响;如建议性锁可以比如成红绿灯,只是建议性的,因为还是有人可以闯红灯;
强制性锁:内核对每个open,read,write系统调用都进行检查,检查访问的文件是否违背了锁规则,如果违背了锁规则,则该IO调用被禁止;
8. 锁的操作宏:
int lock_reg(int, int, int, off_t, int, off_t)
{
struct flock lock; lock.l_type = type;
lock.l_start = offset;
lock.l_whence = whence;
lock.l_len = len; return (fcntl(fd, cmd, &lock));
} #define read_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))
#define readw_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))
#define write_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))
#define writew_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))
#define un_lock(fd, offset, whence, len) \
lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len)) pid_t lock_test(int, int, off_t, int, off_t)
{
struct flock lock; lock.l_type = type;
lock.l_start = offset;
lock.l_whence = whence;
lock.l_len = len; if (fcntl(fd, F_GETLK, &lock) < )
return -; if (lock.l_type == F_UNLCK)
return ; return (lock.l_pid);
} #define is_read_lockable(fd, offset, whence, len) \
(lock_test((fd), F_RDLCK, (offset), (whence), (len)) == )
#define is_write_lockable(fd, offset, whence, len) \
(lock_test((fd), F_WRLCK, (offset), (whence), (len)) == )
Linux-进程间通信(六): 记录锁的更多相关文章
- Linux进程同步之记录锁(fcntl)
记录锁相当于线程同步中读写锁的一种扩展类型,可以用来对有亲缘或无亲缘关系的进程进行文件读与写的同步,通过fcntl函数来执行上锁操作.尽管读写锁也可以通过在共享内存区来进行进程的同步,但是fcntl记 ...
- Linux进程间通信(六):共享内存 shmget()、shmat()、shmdt()、shmctl()
下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式 ...
- linux 文件记录锁详解
一: linux记录锁更恰当的称呼应该是范围锁,它是对文件某个范围的锁定. 关于记录锁的功能就是fcntl提供的第五个功能,具体使用如下: int fcntl(int fd, int cmd, str ...
- 【转载】Linux进程间通信(六):共享内存 shmget()、shmat()、shmdt()、shmctl()
来源:https://www.cnblogs.com/52php/p/5861372.html 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相 ...
- linux c编程:记录锁
记录锁相当于线程同步中读写锁的一种扩展类型,可以用来对有亲缘或无亲缘关系的进程进行文件读与写的同步,通过fcntl函数来执行上锁操作.尽管读写锁也可以通过在共享内存区来进行进程的同步,但是fcntl记 ...
- linux内核剖析(七)Linux进程间通信的几种方式总结
进程间通信概述 进程通信的目的 数据传输 一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间 共享数据 多个进程想要操作共享数据,一个进程对共享数据 通知事 一个进程需要向另 ...
- Linux进程间通信—管道
Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...
- Linux进程间通信的几种方式总结--linux内核剖析(七)
进程间通信概述 进程通信的目的 传输数据 一个进程须要将它的数据发送给还有一个进程.发送的数据量在一个字节到几M字节之间 共享数据 多个进程想要操作共享数据,一个进程对共享数据 通知事 一个进程须要向 ...
- Linux进程间通信(IPC)机制总览
Linux进程间通信 Ø 管道与消息队列 ü 匿名管道,命名管道 ü 消息队列 Ø 信号 ü 信号基础 ü 信号应用 Ø 锁与信号灯 ü 记录锁 ü 有名信号灯 ü 无名信号灯(基 ...
随机推荐
- [C/C++] C/C++错题集
1. 解析: A:在GCC下输出:0 在VC6.0下输出:1 B:在GCC下输出:段错误 (核心已转储) 在VC6.0下输出:已停止工作,出现了一个问题,导致程序停止正常工作. C:正常 ...
- jCanvaScript canvas的操作库
在jcscript.com上下载最新的jCanvaScript.1.5.18.min.js文件 里面有很多关于canvas的方法都已经是封装好了的,只需直接调用,但是要注意调用之前和调用之后都要写: ...
- P2587 [ZJOI2008]泡泡堂
题目描述 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛前,对阵双方的教练向组 ...
- 【刷题】UOJ #34 多项式乘法
这是一道模板题. 给你两个多项式,请输出乘起来后的多项式. 输入格式 第一行两个整数 \(n\) 和 \(m\) ,分别表示两个多项式的次数. 第二行 \(n+1\) 个整数,表示第一个多项式的 \( ...
- POJ3384:Feng Shui——题解
http://poj.org/problem?id=3384 题目大意:给一个顺时针序的多边形,求在里面放半径为r的两个圆使得两圆覆盖的面积最大,求出这样的圆的坐标. ———————————————— ...
- 洛谷3690:【模板】Link Cut Tree——题解
https://www.luogu.org/problemnew/show/P3690 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
- LOJ2351:[JOI2017/2018决赛]毒蛇越狱——题解
https://loj.ac/problem/2351 参考:https://www.cnblogs.com/ivorysi/p/9144676.html 但是参考博客讲解太吓人了,我们换一种通俗易懂 ...
- nodejs路径处理方法和绝对路径
1. 路径处理方法 __dirname 表示当前文件所在的目录的绝对路径__filename 表示当前文件的绝对路径module.filename ==== __filename 等价process. ...
- javascript实现deepEqual和shallowEqual
function deepEqual(x, y) { if (x === y) { return true; } if (!(typeof x == "object" && ...
- Codeforces 864E Fire(背包DP)
背包DP,决策的时候记一下 jc[i][j]=1 表示第i个物品容量为j的时候要选,输出方案的时候倒推就好了 #include<iostream> #include<cstdlib& ...