1. 文件锁

当多个进程打开同一文件进行读写时可能会出现数据混乱的问题,原因在于进程间共享同一文件读写指针位置,也就是f_pos(关于f_pos参考:4-文件描述符与打开的文件之间的关系的第三小节file结构体)。

解决这个问题的方法有很多,比如可以使用信号量完成进程同步,但通常使用文件锁会更好一些,因为内核会将锁跟文件关联起来,这就需要借助fcntl函数来实现对一个文件进行加锁。只有拿到锁的进程可以对文件进行读写操作,而没有获得锁的进程操作文件可以打开文件,但无法执行read、write操作,以此来防止进程间对同一文件进行读写出现的数据混乱问题。

2. fcntl函数

#include <unistd.h>
#include <fcntl.h>int fcntl(int fd, int cmd, ... /* arg */ );

参数fd:指定文件描述符

参数cmd:一般用于设置文件锁,F_SETLK和F_SETLKW 用于加锁解锁, F_GETLK用于获取文件锁。

F_SETLK设置文件锁,如果另一进程已经加锁,那么fcntl将会失败并返回EAGAIN错误,不会阻塞。

F_SETLKW设置文件锁,如果另一进程已经加锁,那么该进程将会阻塞,直到文件锁被释放。

F_GETLK实际上是用于获取文件锁的相关信息,以检测能否设置F_SETLK或F_SETLKW进行加锁。

参数flock具体定义:

struct flock {...short l_type;       //锁的类型:F_RDLCK(读方式加锁) 、F_WRLCK(写方式加锁) 、F_UNLCK(解锁)short l_whence;    //参考偏移位置:SEEK_SET、SEEK_CUR、SEEK_END off_t l_start;       //具体起始偏移位置,0表示文件开头off_t l_len;       //长度:其实是表示加锁的范围(加多少个字节),如果为0表示整个文件加锁pid_t l_pid;        //持有该锁的进程ID:(只有调用F_GETLK only,才会用到这个参数)...
};

加锁范围:

1. 如果 len > 0, [whence+start  ,  whence+start+len) ,包左不包右

2. 如果 len = 0, [whence+start  , ∞),包左不包右,表示对整个文件加锁

以whence为参考位置开始,加上start就是具体的起始位置。例如:whence = SEEK_SET,start = 10,那么参考位置就是文件开头(偏移为0的位置),加上start后,具体的起始位置就是偏移为10的位置。

3. 文件锁示例

多个进程对加锁文件进行访问:

1. 首先测试两个进程间以读方式加锁

2. 然后测试两个进程间以写方式加锁

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>void sys_err(char *str){perror(str);exit(1);
}int main(int argc, char *argv[]) {int fd;struct flock f_lock;//参数不够if (argc < 2) {printf("./a.out filename\n");exit(1);}//打开文件失败if ((fd = open(argv[1] , O_RDWR)) < 0){sys_err("open");}//选用写琐f_lock.l_type = F_WRLCK;  //选用读琐      //f_lock.l_type = F_RDLCK;          //设置文件指针为文件开头f_lock.l_whence = SEEK_SET;//起始偏移,0表示文件开头f_lock.l_start = 0;// l_len表示加锁的长度,0表示整个文件加锁 f_lock.l_len = 0; //设置属性,让线程阻塞(F_SETLKW),直到加锁成功fcntl(fd, F_SETLKW, &f_lock);//如果加锁成功,打印get flockprintf("get flock\n");//为了测试效果明显,休眠10秒sleep(10);//设置锁类型为解锁f_lock.l_type = F_UNLCK;//设置属性,解锁不成功阻塞fcntl(fd, F_SETLKW, &f_lock);//解锁成功打印unflockprintf("un flock\n");close(fd);return 0;
}

测试两个进程间以写方式加锁,程序执行结果:

从图中可以看出,以写方式进行加锁的话,那么左1进程对文件以写方式加锁成功,右1进程对文件以写方式加锁会失败并阻塞,等到左1进程释放写锁后,右1进程立马获取到了写锁。

修改部分代码,测试两个进程间以读方式加锁:

//选用写琐
//f_lock.l_type = F_WRLCK;
//选用读琐
f_lock.l_type = F_RDLCK;       

以读方式进行加锁的话,那么左1进程对文件以读方式加锁成功,右1进程对文件以读方式加锁也会成功。

由此我们可以得出结论:进程间对文件进行加文件锁也遵循“读共享、写独占”特性。但!如若进程不加锁直接操作文件,依然可访问成功,但数据势必会出现混乱。

41-fcntl设置文件锁相关推荐

  1. linux fcntl 设置阻塞,Linux fcntl函数设置阻塞与非阻塞

    转自http://www.cnblogs.com/xuyh/p/3273082.html 用命令F_GETFL和F_SETFL设置文件标志,比如阻塞与非阻塞 F_SETFL     设置给arg描述符 ...

  2. fcntl设置FD_CLOEXEC

    原文地址:http://hi.baidu.com/passerryan/item/d81eac1671ce3d5cf0090e2b 这是fcntl的一个Flag标志. fcntl(fd, F_SETF ...

  3. python windows 下设置文件锁、多线程

    在python 环境的Lib文件夹下新建fcntl.py文件,在其中写入下面的内容: fcntl.py是linux平台上python自带的包,windows平台下没有,所以需要自己设计一份,让wind ...

  4. linux系统编程之文件与I/O(六):fcntl 函数与文件锁

    2013-05-14 11:26 8290人阅读 评论(2) 收藏 举报  分类: linux系统编程(19)  版权声明:本文为博主原创文章,未经博主允许不得转载. 一.fcntl函数 功能:操纵文 ...

  5. Linux 文件锁 fcntl 函数详解

    Linux 文件锁 fcntl 函数详解 #include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd); ...

  6. Linux文件锁和fcntl系统调用

    1.Linux 中的文件锁 Linux 支持的文件锁技术主要包括劝告锁(advisory lock)和强制锁(mandatory lock)这两种.此外,Linux 中还引入了两种强制锁的变种形式:共 ...

  7. 5进程间锁:进程间pthread_mutex,文件锁

     1进程间pthread_mutex A依赖的头文件 #include<pthread.h> B函数声明 int pthread_mutexattr_destroy(pthread_m ...

  8. linux操作系统之信号量、互斥量在进程间的同步、文件锁

    (1)信号量:进化版的互斥量 多个线程间对某个对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住.这样虽然达到了多线程操作数据共享的目的,却导致线程并发性下降. 信号量:相对折 ...

  9. c 如何加函数锁linux,Linux下C语言中fcntl函数用法说明

    本文最后更新于2017年8月18日,已超过 1 年没有更新,如果文章内容失效,还请反馈给我,谢谢! =Start= 缘由: 学习.提高需要 正文: 参考解答: fcntl – manipulate f ...

最新文章

  1. @NotNull-JSR-303验证
  2. 探秘重编译(Recompilations)(1/2)
  3. 图像柔光效果(SoftGlow)的原理及其实现。
  4. 使用Aspose.Cells的基础知识整理
  5. 又到校招季,来说说面试和实习
  6. ram在计算机网络中表示的是,2018年职称计算机考试题库(20)
  7. 如何简化临时内存的分配与释放
  8. 长沙黑梨路枪击抢劫案
  9. java jstl foreach用法_JSTL 中c:forEach使用
  10. sqlite3_get_table()
  11. PHP 使用GD库合成带二维码的海报步骤以及源码实现
  12. 石油工程课程设计c语言,东北石油大学-石油工程抽油设计C语言编程.doc
  13. python 解决问题的集合-No JSON object could be decoded
  14. 快看快看,这款免费的低代码平台绝绝子
  15. 利用Excel制作问卷的饼状图
  16. 《完全用Linux工作》
  17. HttpRequest 和HttpWebRequest的区别(转)
  18. LabVIEW编程LabVIEW开发 研华PCIE-1751更改DIO方向 例程与相关资料
  19. Spark 写入 MySQL 乱码问题
  20. 解决:Word 不显示 EndNote 插件(Word 插件不显示问题通用)

热门文章

  1. 垃圾小白羊的leetcode刷题记录6
  2. 等你来战 | 第五届“强网”拟态防御国际精英挑战赛报名开启!
  3. “东华春秋杯”上海大学生网络安全技能大赛决赛收官 聚焦高校人才培养
  4. Android开发新手入门总结(1)
  5. STM32CUBE+自平衡车实践篇3.4-STM32cueb配置编码器+车轮速度测量代码实现
  6. 带顶点动画的护盾效果——UnityShader学习笔记
  7. 人工智能基础——贝叶斯分类器例程(c语言实现,完整代码)
  8. 赵小楼《天道》《遥远的救世主》深度解析(9)肖亚文的“小心思和小算计”
  9. SparkSql-redis:将查询到的结果保存到redis中
  10. 中年网易,生存像是一种幸运