linux锁定文件的命令 linux锁定文件禁止修改( 四 )


同时运行同一个程序的两个实例,运行结果为:
?
从运行的结果可以看出两个程序交叉地对对文件进行锁定 , 但是真实的操作却是,每次调用open函数去检查/tmp/LCK.test1这个文件是否存在,如果存在open调用就失败 , 显示有进程已经把这个文件锁定了 , 如果这个文件不存在,就创建这个文件,并显示许可信息 。但是这种做法有一定的缺憾,我们可以看到文件/tmp/LCK.test1被创建了很多次,也被unlink删除了很多次 , 也就是说我们不能使用已经事先有数据的文件作为这种锁文件 , 因为如果文件已经存在,则open调用总是失败 。
给我的感觉是,这更像是一种对进程工作的协调性安排 , 更像是二进制信号量的作用,文件存在为0 , 不存在为1 , 而不是真正的文件锁定 。
三、区域锁定
我们还有一个问题,就是如果同一个文件有多个进程需要对它进行读写,而一个文件同一时间只能被一个进程进行写操作 , 但是多个进程读写的区域互不相关,如果总是要等一个进程写完其他的进程才能对其进行读写,效率又太低,那么是否可以让多个进程同时对文件进行读写以提高数据读写的效率呢?
为了解决上面提到的问题,和出现在第二点中的问题 , 即不能把文件锁定到指定的已存在的数据文件上的问题,我们提出了一种新的解决方案,就是区域锁定 。
简单点来说,区域锁定就是,文件中的某个部分被锁定了,但其他程序可以访问这个文件中的其他部分 。
然而,区域锁定的创建和使用都比上面说的文件锁定复杂很多 。
1、创建区域锁定
在Linux上为实现这一功能,我们可以使用fcntl系统调用和lockf调用,但是下面以fcntl系统调用来讲解区域锁定的创建 。
fctnl的函数原理为:
int fctnl(int fildes, int command, ...);
它对一个打开的文件描述进行操作,并能根据command参数的设置完成不同的任务 , 它有三个可选的任务:F_GETLK,F_SETLK,F_SETLKW,至于这三个参数的意义下面再详述 。而当使用这些命令时,fcntl的第三个参数必须是一个指向flock结构的指针,所以在实际应用中 , fctnl的函数原型一般为:int fctnl(int fildes, int command, struct flock *flock_st);
2、flock结构
准确来说,flock结构依赖具体的实现 , 但是它至少包括下面的成员:
short l_type;文件锁的类型,对应于F_RDLCK(读锁,也叫共享锁),F_UNLCK(解锁,也叫清除锁),F_WRLCK(写锁,也叫独占锁)中的一个 。
short l_whence;从文件的哪个相对位置开始计算 , 对应于SEEK_SET(文件头),SEEK_CUR(当前位置),SEEK_END(文件尾)中的一个 。
off_t l_start;从l_whence开始的第l_start个字节开始计算 。
off_t l_len;锁定的区域的长度 。
pid_t l_pid;用来记录参持有锁的进程 。
成员l_whence、l_start和l_len定义了一个文件中的一个区域,即一个连续的字节集合,例如:
struct flock region;
region.l_whence = SEEK_SET;
region.l_start = 10;
region.l_len = 20;
则表示fcntl函数操作锁定的区域为文件头开始的第10到29个字节之间的这20个字节 。
3、文件锁的类型
从上面的flock的成员l_type的取值我们可以知道,文件锁的类型主要有三种,这里对他们进行详细的解说 。
F_RDLCK:
从它的名字我们就可以知道,它是一个读锁,也叫共享锁 。许多不同的进程可以拥有文件同一(或重叠)区域上的读(共享)锁 。而且只要任一进程拥有一把读(共享)锁,那么就没有进程可以再获得该区域上的写(独占)锁 。为了获得一把共享锁,文件必须以“读”或“读/写”方式打开 。

推荐阅读