linux文件锁学习01
来源:互联网 发布:集思宝a5软件 编辑:程序博客网 时间:2024/06/05 17:43
unix下3中对文件加锁的函数:
lockf:适用于freeBSD系统
flock:适用于linux系统
fcntl:使用标准POIX ,可移植到任何标准系统上
区别:
1.flock只能加全局锁,fcntl可以加全局锁也可以加局部锁。
2.当一个进程用flock给一个文件加锁时,用另一个进程再给这个文件加锁,它会阻塞或者也可以返回加锁失败(可以自己设置)。
3.当一个进程用fcntl给一个文件加锁时,用另一个进程去读或写文件时必须先获取加锁的信息,然后在给这个文件加锁。
3.当给一个文件加fcntl的独占锁后,再给这个文件加flock的独占锁,其会进入阻塞状态。
4.当给一个文件加flock的独占锁后,用fcntl去获取这个锁信息获取不到,再用fcntl仍然可以给文件加锁。
linux通常采用的方法是文件上锁,来避免共享资源的产生竞争状态。
文件锁包括建议性锁和强制性的锁。建议性的,顾名思义,相对温柔一些,在对文件进行锁操作时,会检测是否已经有锁存在,并且尊重已有的锁。在一般的情况下,内核和系统都不使用建议锁。强制性的锁是由内核执行的锁,当一个文件被上锁进行写入操作的时候,内核将阻止其他进程对其进行读写操作。采取强制性的锁对性能的影响很大,每次进行读写操作都必须检查是否有锁存在。
--------------------------------------我是分割线------------------------------------------------
#include <unistdh.>
int lockf(fd,cmd,size)
int fd,cmd;
long size;
这个方法对只锁定文件而言是最简单的。
其中fd为文件的handle number ,
cmd 为所要使用lockf的功能指定,
size則是执行这个功能所要影响的范围大小。
cmd 这个参数要代进什么样的数值呢?其实在unistd.h中也已经有以下的定义,使用時只要依照所需代入即可:
#define F_ULOCK 0 /* Unlock a previously locked section */
#define F_LOCK 1 /* lock a section for exclusive use */
#define F_TLOCK 2 /* test and lock a section(non-blocking) */
#define F_TEST 3 /* test section for other process' locks */
其中F_TEST并没有lock的功能,其主要目的只是在测试文件是否正被其它 process
锁住而已,当已经被锁住时,lockf 返回-1,否則返回0 ;
而F_LOCK和F_TLOCK 的功能也是将文件锁住,不同之处在于如果这个文件原先已被其它process 锁上时,F_LOCK会block 住,并等候此文件直至被解除锁定为止,至于F_TLOCK 则并不会将自己 block
住,而会马上返回-1,至于F_TLOCK 等不等于下列程序呢?
while (lockf(fd,F_TEST,0L)==-1) {}
lockf(fd,F_LOCK,0L);
结果当然是不等于了!因为这就必须考虑到critical section等问题了!当然,对于一个单纯的系统而言,F_LOCK便可以达到目的,但对于大系统而言,由于许多难以预测的因素,如果某process 沒有把文件unlock,则使用F_LOCK便将因为等不到文件可以上锁而使整个系统陷入starvation,這是程序审计者必需先考虑清楚的风险!
那么lockf 的最后一个参数size又要如何使用呢?其实size的值指的就是从文件目前的读取位置开始,要往前或往后多少位置做lock或unlock的动作,而假若是要对整个文件做lock或unlock的话,则并不需要特別去量测size大小,只要直接输入0 即可,lockf 便会知道所要影响的范围为整个文件了!
#define FILE_NAME "/tmp/filelock" #include <stdio.h> #include <unistd.h> #include <sys/file.h> int main(int argc , char *agvv[]) { int fd; fd = open(FILE_NAME,O_CREAT|O_RDWR,0666); if( fd == -1) return -1; int ret = flock(fd,LOCK_EX|LOCK_NB); if(ret == 0) { printf("first run!\n"); sleep(10); }else{ printf("already run!\n"); } return 0; }
-------------------------------------------我是分割线------------------------------------------
二.fcntl()函数格式
所需头文件:
#include<sys/types.h>,
#include<unistd.h>,
include<fcntl.h>
函数原型:
int fcntl(int fd , int cmd);
int fcntl(int fd,int cmd,long arg);
int fcntl(int fd,int cmd,struct flock * lock);
函数参数:
fd:文件描述符
cmd:
lock:结构为flock,记录锁的具体状态
struct flock
{
}
Lock结构变量取值:
l_type:F_RDLCK:读取锁(共享锁)
l_start:相对位移量(字节)
l_whence:相对位移量的起点(同lseek的whence):
l_len:加锁区域长度
l_pid是加锁进程的进程id,l_pid不需要指定
返回值 成功返回依赖于cmd的值,若有错误则返回-1,错误原因存于errno.
小技巧:为了锁定整个文件,通常的做法是将l_start设置为0,l_whence设置为SEEK_SET,l_len设置为0
二.fcntl()函数使用实例
/************************************************************************* 文件名:flock.c* 文件描述:使用文件锁检测进程中是否唯一实例*原 理:每次进程启动的时候,对文件获取文件锁,下一次检测文件锁是否获取到,得不到就直接退出*创建人: SJW, 2015年10月08日* 版本号:1.0* 修改记录:************************************************************************/#define FILE_NAME "/tmp/filelock" #include <stdio.h> #include <unistd.h> #include <sys/file.h> /*================================================================ * 函 数 :is_single_f * 参 数1:需要存储文件锁的位置 * 功能描述:对指定位置文件获取文件锁,使用的是建议锁,锁定的是全部文件 * 返 回 值:成功0,失败-1 * 抛出异常: ================================================================*/int is_single_f(char * process_name){int fd; fd = open(process_name,O_CREAT|O_RDWR,0666); if( fd == -1) return -1; int ret = flock(fd,LOCK_EX|LOCK_NB); if(ret == 0) { printf("first run!\n"); sleep(10); return 0; }else{ printf("already run!\n"); return -1; } return 0;}/*================================================================ * 函 数 :Lockfile * 参 数1:需要存储文件锁的位置 * 功能描述:对指定位置文件获取文件锁,使用的是建议锁,锁定的是指定位置字符串 * 返 回 值:成功0,失败-1 * 抛出异常: ================================================================*/int Lockfile(char * process_name) { int fd; fd = open(FILE_NAME,O_CREAT|O_RDWR,0666); if( fd == -1) return -1; struct flock stLock; stLock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */ stLock.l_start = 0; /* byte offset, relative to l_whence */ stLock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */ stLock.l_len = 0; /* #bytes (0 means to EOF) */ int ret = (fcntl(fd, F_SETLK, &stLock)); if(ret == 0) { printf("first run!\n"); sleep(10); return 0; }else { printf("already run!\n"); return -1; } } int main(int argc , char *agvv[]) { //if(!is_single_f(FILE_NAME)) if(!Lockfile(FILE_NAME)) printf("\nsingle ok !\n"); else printf("\ndoule and quit !\n"); return 0; }
测试结果:
进程1:
[root@localhost 20151008]# ./flockfirst run!single ok !
进程2:
[root@localhost 20151008]# ./flockalready run!doule and quit !
- linux文件锁学习01
- Linux学习01--在xshell传输文件
- Linux学习笔记01:文件管理
- linux文件权限学习
- linux ELF文件学习
- Linux ELF文件学习
- Linux ELF文件学习
- linux文件学习1
- Linux学习---文件查找
- linux 读写文件学习
- Linux学习---文件分区
- linux文件学习4
- linux文件学习5
- linux文件学习6
- linux文件学习7
- linux文件学习8
- Linux 学习(文件)
- linux文件学习9
- ios swift开发中,使用键盘,tableview根据键盘调整高度
- 多按键事件
- iOS 真机证书设置
- 一对一主键关联关系的理解与实践
- C++学习之路---构造函数--1
- linux文件锁学习01
- SQL server 2008无法连接Local服务器的解决方法
- POJ 1080 Human Gene Functions (类似LCS)
- 剑指offer 顺时针打印矩阵
- 关于Lua中const型变量或者常量的实现
- 怎么样学习Java/ 如何学好Java
- linux内核中的基本数据结构和算法
- Linux源码中链表的声明和初始化
- 解决ScrollView嵌套ListView和GridView冲突的方法