linux文件锁笔记
来源:互联网 发布:基于mac地址的acl 编辑:程序博客网 时间:2024/05/14 09:23
一、概述
应用程序的一个常见的需求是从一个文件中读取数据,修改这些数据,然后将这些数据写回文件,当同一时刻只有一个进程使用这个文件,这么做不会出现问题,但是当多个进程同时更新一个文件时,就会出现资源竞争的问题。
文件锁是一种文件读写机制,在任何特定的时间只允许一个进程访问一个文件。利用这种机制能够使读写单个文件的过程变得更安全。
主要内容
- 文件锁的分类与原理
- 文件锁的使用
- 结束语
二、文件锁的介绍
文件锁主要分为两种:一种是劝告式的,一种是强制式的锁;但是在默认的情况下,文件锁是劝告式的。
劝告式文件锁
这种锁不会介入write和read的操作,是一种协议式的锁,在对一个文件进行读写的时候,采用如下的过程
graph LR加锁-->读写操作读写操作-->解锁
但是劝告式文件锁不会从系统层上强制应用程序遵守这个协议,其他的程序可以不检测文件的锁的状态而直接操作文件.
强制式文件锁
在程序中可以使用chmod()和fchmod()函数对文件强制加锁,强制式的锁会使read/write函数阻塞或失败.
三、文件锁的使用
文件锁有多种实现,这里将的均是劝告锁,强制锁在应用中的价值不高,并且存在很大的弊端(容易锁死).
在使用文件锁时,读写文件的接口必须使用read和write,不能使用库函数的IO操作函数,因为IO操作函数会带有缓冲,影响加锁的结果.
(好像标准库函数的IO操作函数可以选择没有缓冲,但是依旧慎重)
flock
- 功能:为一个已经打开的文件 添加或者移除一把劝告锁(advisory lock)
- 原型:int flock(int fd, int operation);
参数:
- fd 文件id
- operation 操作数
operation可以使下列的三个值
- LOCK_SH 放置一个共享锁
- LOCK_EX 放置一个排他锁
LOCK_UN 解锁
此外,LOCK_NB可以与前两个共用,通过’|’,意思是非阻塞的锁.当使用flock(fd,LOCK_SH|LOCK_NB)时,如果其他进程持有锁,则不会阻塞,而是返回错误,并记录一个错误码到error.
一个进程在一个文件上只能拥有一种类型的锁,每次调用flock会改变锁的模式.锁会在文件描述符关闭的时候自动释放.
- 不足 :
- 粒度大,只能锁整个文件
- 劝告锁,无法真正的锁定文件
- 有些NFS实现不支持flock
fcntl
这种锁通常称为”记录加锁”,fcntl可以对文件的任意部分加锁,而不影响其他部分的使用,记录加锁是针对应用程序说的,记录边界是应用程序定义的一个字节范围
- 原型:int fcntl(int fd, int cmd, … /* arg */ );
- 参数:
- fd 文件描述符
- cmd :
- F_SET_LK 设置锁状态,失败返回错误
- F_SET_LKW 设置锁状态,失败阻塞
- F_GET_LK 获取锁状态
- arg :struct flock 结构指针
fcntl的锁操作,通过下面这个结构体进行设置
struct flock { short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */#ifndef __USE_FILE_OFFSET64 __off_t l_start; /* Offset where the lock begins. */ __off_t l_len; /* Size of the locked area; zero means until EOF. */#else __off64_t l_start; /* Offset where the lock begins. */ __off64_t l_len; /* Size of the locked area; zero means until EOF. */#endif __pid_t l_pid; /* Process holding the lock. */ };
锁有三种状态,分别是读锁/写锁和无锁.
一个用于设置锁状态的函数
int pidf_set_lock(int fd,int lock_type){ struct flock flockstr; //default if(lock_type!=F_RDLCK&&lock_type!=F_WRLCK&&lock_type!=F_UNLCK) return -1; flockstr.l_type =lock_type; flockstr.l_whence =SEEK_SET; flockstr.l_start =0; flockstr.l_len =0; if(fcntl(fd,F_SETLK,&flockstr)==0) { if(flockstr.l_type==F_RDLCK) pr_pidf_debug("set a F_RDLCK,thd pid = %d; \n",getpid()); if(flockstr.l_type==F_WRLCK) pr_pidf_debug("set a F_WRLCK,thd pid = %d; \n",getpid()); if(flockstr.l_type==F_UNLCK) pr_pidf_debug("set a F_UNLCK,thd pid = %d; \n",getpid()); return flockstr.l_type; } return -1; }
获取锁状态的函数
int pidf_get_lock(int fd,pid_t *pid){ struct flock flockstr; flockstr.l_type =F_WRLCK; flockstr.l_whence =SEEK_SET; flockstr.l_start =0; flockstr.l_len =0; if(fcntl(fd,F_GETLK,&flockstr)==0) { if(pid!=NULL) *pid =flockstr.l_pid; return flockstr.l_type; } perror("fcntl F_GETLK"); return -1;}
继承和释放
- fork产生的子进程不会继承记录锁(fcntl),但是会继承flock
- 记录锁在exec()中会得到保留
- 记录锁同时和一个进程,一个inode关联,所以进程结束或者进程对文件的链接关闭,都会导致其所持有的记录锁被释放
四、结束语
参考
《Linux/UNIX系统编程手册(下)》
- linux文件锁笔记
- linux 发送文件笔记
- linux笔记----日志文件
- Linux 文件读写笔记
- 【笔记】Linux文件处理
- Linux 文件权限笔记
- linux文件权限笔记
- 【Linux】文件操作笔记
- 学习笔记:Linux日志文件
- 笔记--linux 文件查看 命令
- 笔记:linux程序设计:文件锁定
- Linux学习笔记5 :文件
- linux笔记之文件管理
- linux makefile文件心得笔记
- linux文件权限学习笔记
- Linux笔记____文件管理
- linux学习笔记-文件访问
- Linux笔记_文件编程
- 修改Linux系统用户权限
- character controller 碰撞
- 611. Valid Triangle Number
- 日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯 的一个。以下为4个嫌疑犯的供词。 A说:不是我。 B说:是C。 C说:是D。 D说:C在胡说 已知3个人说了真话,1个人说
- Win10资源管理器闪退解决办法
- linux文件锁笔记
- Java Web学习总结(40)——JSP中的Application对象和Session对象常用方法详解
- Qt Quick笔记
- 工厂方法
- python字符串转义字符
- Python namedtuple使用详解
- Java8 新特性之 Optional 类
- 函数声明和函数表达式
- 微信小程序框架wxss(二)电话列表展示demo