fcntl函数中的建议性锁和强制性锁

所谓建议性锁就是假定人们都会遵守某些规则去干一件事。例如,人与车看到红灯都会停,而看到绿灯才会继续走,我们可以称红绿等为建议锁。但这只是一种规则而已,你并不防止某些人强闯红灯。而强制性锁是你想闯红灯也闯不了。

 

 

建议性锁只在cooperating processes之间才有用,对cooperating process的理解是最重要的,它指的是会影响其它进程的进程或被别的进程所影响的进程,举两个例子:(1)我们可以同时在两个窗口中运行同一个命令,对同一个文件进行操作,那么这两个进程就是cooperating processes;(2)cat file| sort,那么cat和sort产生的进程就是使用了pipe的cooperating processes。

 

 

 

fcntl使用三个参数 F_SETLK /F_SETLKW,F_UNLCK和F_GETLK,来分别要求、释放、测试record locks,record locks是对文件一部分而不是整个文件的锁,这种细致的控制使得进程更好地协作以共享文件资源。fcntl能够用于读取锁和写入锁,read lock也叫shared lock(共享锁),因为多个cooperating process能够在文件的同一部分建立读取锁;write lock被称为exclusive lock(排斥锁),因为任何时刻只能有一个cooperating process在文件的某部分上建立写入锁。如果cooperating processes对文件进行操作,那么它们可以同时对文件加read lock,在一个cooperating process加write lock之前,必须释放别的cooperating process加在该文件的read lock和wrtie lock,也就是说,对于文件只能有一个write lock存在,read lock和wrtie lock不能共存。

 

建议性锁 (针对合作进程而言的)

建议性锁,就是一种软弱的锁——必须要在参与所有共享数据操作的所有进程之间都遵守这样神圣的约定的前提,建议性的锁才发挥作用,而劝告性的建议锁对于协作进程来说已经足够了!!但是,有读写权限的进程,不遵守这个约定,就会把这一切都搞杂,约定对于他们来说,不好用。但建议性锁也有他的优势:相对与强制性锁,性能好一些。个人理解。

 

协作进程(cooperating processes):如果每个进程所使用的函数都以一致的方法处理记录锁,互斥锁等,则这些进程被称为协作进程。

 

强制性锁

前提: 

先执行这个命令

mount -o mand /dev/sda7 /mnt  //sda7对应的文件系统格式一定是ext系列才行

 

注:我的Ubuntu10.10 在挂载的文件系统里创建的文件(即下文的 touch /mnt/firo )权限是777并且无法更改 囧!!!

 

这里的原因是:因为Ubuntu桌面版用户一般是安装在windows7 下的,那么一般所有硬盘的分区就都是NTFS FAT32而不是EXT系列系统,

 

所以我mount了一个NTFS文件系统的盘符后,因为NTFSEXT很不同 ,他没有相关权限位的数据结构 所以并不支持chmod chown等操作。

 

这里给出一个解决办法:利用/dev/loop1这个设备,创建一个ext2的文件系统之后在挂载,^_^具体命令如下。

dd if=/dev/zero of=/file bs=1k count=10 //其中“/file”是在/目录下的任意文件,可以不存在 。bs是块大小1024字节。count是块数:10个。

losetup /dev/loop1 /file   

mkfs -t ext2 /dev/loop1 100 //这里最后一个参数:57是最小的可以指定的值,如果小于57将不能创建文件系统。他指定文件系统使用块数。

mount -t ext2 /dev/loop1 /mnt   //但是当只有上面的最后一个参数是100的整数倍的数(比如200)才行。关于这几个命令:大家参看man吧!!!如果mount | grep mnt输出的是如下就对了!!:-)/dev/loop1 on /mnt type ext2 (rw,mand)之后,修改要加强制锁的文件的权限:设置 SGID 位,并清除组可执行位。这种组合通常来说是毫无意义的,系统用来表示该文件被加了强制锁。例如:touch /mnt/firo

ls -l /mnt/firo

chmod g+s /mnt/firo

chmod g-x /mnt/firo

ls -l /mnt/firo

 

之后在程序中直接操作这个文件就行了^_^1.如果想要打开一个有强制性记录锁的文件,而且open函数中指定了O_TRUNC时,即便没有指定O_NONBLOCKopen调用也会立即出错返回,errno置为EAGAIN

 

2.强制性锁可以避开。但意义不大,原理是创建个新文件,并删除(unlink不受强制性影响)原有的文件。

 

3.强制性锁虽然解决非协作进程来捣乱的问题,但是,对于多个进程更新共享文件时,对共享数据仍需要某种锁。

 

lockf()

 

 

System V的锁函数 lockf()具有如下的形式

lock()用于对文件施加建议性锁
#include <unistd.h>
int lockf(int fd, int function, long size);
参数 fd 是在文件打开操作中获得的文件描述符;
参数 function 可以取如下的参数值:
F_ULOCK 为一个先前锁定的区域解锁
F_LOCK 锁定一个区域
F_TLOCK 测试并锁定一个区域
F_TEST 测试一个区域是否已经上锁。
参数 size 指明了从文件当前位置开始的一段连续锁定区域的长度,当 size 为 时,锁定记录将由当前位置一直扩展到文件尾。
函数 lockf()既可以用来上锁有可以用来测试是否已经赏了锁。 如果 lockf 的参数function为 F_LOCK 指定文件的对应区域已被其它进程锁定,那么 lockf 的调用进程将被阻塞直到该区域解锁。上述情况我们称为阻塞。如果在调用 lockf()时把参数设为 F_TLOVK,那么当被测试的区域上了锁时,lockf 便会立即返回-1,出错返回码 errno 将为 EAGAIN,它是一个非阻塞调用。

C代码 

#include <unistd.h>  

my_lock(int fd)   

{   

/*  将文件指针移回文件头 */  

lseek(fd,0L,0);   

/*  锁定整个文件 */  

if (lockf(fd,F_LOCK,0L)==-1)   

{   

perror("can't F_LOCK");   

exit(1);   

}   

}   

my_unlock(int fd)   

{   

lseek(fd,0L,0);   

if(lockf(fd,F_ULOCK,0L)==-1)   

{   

perror("can't F_UNLOCK");   

exit(1);   

}   

}  

 

 

 

flock()

BSD UNIX 操作系统提供了如下形式的调用来锁定和解锁一个文件:
#include <sys/file.h>
int flock(int fd, int operation);
调用 flock有两个参数:
参数 fd 是一个已打开文件的文件描述符;
参数 operation 可设定为下述各值:
LOCK_SH 共享锁
LOCK_EX  互斥锁
LOCK_UN 解锁
LOCK_NB 当文件已被锁定时不阻塞
BSD UNIX使用flock()来请求对指定文件的咨询式锁定和解锁。BSD的咨询锁有共享锁和互斥锁两种。在任一给定时刻,多个进程可以用于属于同一文件的共享锁,但是某共享文件不能同时具有多个互斥锁或存在共享锁和互斥锁共存的情况。如果锁定成功,flock将返回零,否则返回-1

 

C代码  

#include <sys/file.h>  

my_flock(int fd)   

{   

if (flock(fd,LOCK_EX))==-1)   

{   

perror(“ can LOCK_EX” );   

exit(1);   

}   

}   

my_unload(fd)   

{   

if (flock(fd,LOCK_UN)==-1)   

{   

perror(“ can’ t LOCK_UN” );   

exit(1);   

}   

}  

前面两种锁定方式的比较

由于 Linux 支持上面的两种锁定方式,所以可以根据不同的实际情况选用不同的锁定方式。以上的两种锁定方式有以下的不同:
1System V的锁定方式是记录锁定,可以指定锁定的范围。而 BSD 的锁定方式是文件锁定,只能指定锁定文件。
2System V的锁定是每个进程所独有的,可以用于父子进程间的共享锁定。而 BSD的锁定方式是可以继承的,父子进程间使用的是同一锁定的,所以不能用于父子进程间的文件共享锁定

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值