文件锁
文件锁定是一种机制,强制访问计算机文件只能由一个用户或在任何特定时间的过程。锁定的目的是要防止的恶意更新场景。调解更新的问题包括如下情况:
1.一个进程读取从一个文件包含帐户信息,包括客户的帐户余额和电话号码的客户记录。
2.进程B读取相同的文件相同的记录,所以它有它自己的拷贝。
3.进程A在其客户记录副本的帐户余额的变化,并记录写回文件。
4.进程B - 仍然有原始陈旧的价值在其客户记录副本的帐户余额 - 更新客户的电话号码,并写入客户记录文件。
5.进程B现在已经写入了其过时的帐户平衡值的文件,造成到丢失的过程中所作的更改。
文件锁定防止这个问题,任何给定的文件执行更新过程的系列化。大多数的操作系统都支持这意味着,在任何给定的的文件的个人记录可能会被锁定,所以越来越多的并发更新过程的记录锁定的概念。在数据库维护的文件锁定的用途之一是它可以序列化到整个底层数据库的物理文件的访问。虽然这可以防止任何其他进程访问文件,它实际上可以被删除每个锁的实现和释放开销比单独锁定一个文件中的地区大量更有效率。
fcntl函数
fcntl() 函数的功能很多,可以改变已打开的文件的性质,本文中只是介绍其与获取/设置文件锁有关的功能。fcntl() 的函数原型如下所示:
int fcntl (int fd, int cmd, struct flock *lock);
其中,参数 fd 表示文件描述符;参数 cmd 指定要进行的锁操作,由于 fcntl() 函数功能比较多,这里先介绍与文件锁相关的三个取值 F_GETLK、F_SETLK 以及 F_SETLKW。这三个值均与 flock 结构有关
struct flcok
{
short int l_type; /* 锁定的状态*/
//以下的三个参数用于分段对文件加锁,若对整个文件加锁,则:l_whence=SEEK_SET, l_start=0, l_len=0
short int l_whence; /*决定l_start位置*/
off_t l_start; /*锁定区域的开头位置 锁区偏移,从l_whence开始*/
off_t l_len; /*锁定区域的大小 锁区长度,0表示锁到文件尾*/
pid_t l_pid; /*锁定动作的进程 -1表示自动设置*/
};
cmd取值:
F_GETLK - 测试lock所表示的锁是否可加。
若可加则将lock.l_type置为F_UNLCK,
否则通过lock返回当前锁的信息。
F_SETLK - 设置锁定状态为lock.l_type,
成功返回0,失败返回-1。
若因其它进程持有锁而导致失败,
则errno为EACCES或EAGAIN。
F_SETLKW - 设置锁定状态为lock.l_type,
成功返回0,否则一直等待,
除非被信号打断返回-1。
写锁:独占锁 排他锁 当一个进程对一个文件写锁
其他进程不能在对该文件进行上锁
读锁:共享锁 允许多个进程对同一个文件进行上读锁
但当一个进程对文件上了读锁之后,其他进程不能 上写锁
解锁:
锁的意义在一多个进程对同一个文件进行读写过程中一定要有先后顺序
文件锁支队多个进程有效,同一个进程可以多次上读写锁
1 既可以锁定整个文件,也可以锁定特定区域。
2 读锁(共享锁)、写锁(独占锁/排它锁)、解锁。
3 文件描述符被关闭(进程结束)时,自动解锁。
4 劝谏锁(协议锁)、强制锁。
建议锁(Advisory lock)
系统默认的锁,检测两锁是否冲突的函数:
posix_locks_conflict(structfile_lock *caller_fl, struct file_lock *sys_fl)函数过程:
先判断两把锁是否属于同一进程,自己不会和自己冲突。
如果它们两是不同进程的锁,判断是否有锁定区域重合。
强制性锁(Mandatory lock)
检测强制性锁冲突的函数,满足条件则加锁,locks_mandatory_area()函数过程:
函数里调用了posix_locks_conflict()用于判断冲突锁,调用__posix_lock_file()函数用于加锁。
5 文件锁仅在不同进程间起作用。
6 通过锁同步多个进程对同一个文件的读写访问。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
//控制台读取锁的信息
void read_lock(struct flock *lock