什么是强制性记录锁?
在UNIX like 系统中提供文件的记录锁,就是可以将整个文件,或者文件中的一个字节锁起来的功能。但是在默认情况下系统使用记录锁的是建议性锁,即使你使用记录锁将某段字节锁起来,但是其他的进程仍然可以对文件文件进行自由的读写。如果你编写的程序或者你程序新创建的进程都以一致的方式处理记录锁(即,在读写前都申请一把记录锁,或者都不申请,总之要以一致的方式处理)则称你的程序的进程集为合作进程。合作进程使用建议性锁是可行的。但是如果你需要阻止非你创建的进程也按照一致的方式处理记录锁,那么就只能使用强制性记录锁了。
APUE上说 “Linux2.4.22和Solaris 9提供强制性记录锁。而FreeBSD 5.2.1和Mac OS X 10.3 则不提供。强制性记录锁不是Single UNIX Specification的组成部分。在Linux中,如果用户想要使用强制性锁,则要在各个文件系统基础上,对mount命令用_omand选项打开该机制”
“对mount命令用_omand选项打开该机制”这是一个排版错误,正确的是 “对mount命令用-o mand选项打开该机制”
为了实验强制性锁,遇到了很多问题。在两个小时的查找资料后,终于在我的CentOS5上成功的开启了强制性记录锁:
问题1:强制性锁的设置需要两个步骤:(例如:http://blog.csdn.net/yebanghua/article/details/7301904)
第一,对要加锁的文件需要设置相关权限,打开set-group-ID位,关闭group-execute位。
注:打开set-group-ID位就是对需要上锁文件执行 chmod g+s [待上锁文件]。关闭group-execute位就是对需要上锁文件执行 chmod g-x [待上锁文件]。
第二,让linux支持强制性锁,需要执行命令,挂载文件系统, mount /dev/sda1 /mnt –o mand。
但是根据APUE的描述,“在Linux中,如果用户想要使用强制性锁,则要在各个文件系统基础上,对mount命令用_omand选项打开该机制”。似乎书上的意思是Linux只需要修改mount配置,不需要执行这两步。但是后来我在CentOS上执行发现,即使是Linux系统也必须设置这两步(代码见下文)
问题2:网上很多人mount /dev/sda1 /mnt -o mand,并没有成功开启强制性记录锁。
我开始使用如下命令
1、mkdir /tmp/mount
2、mount -o mand /dev/sda1 /tmp/mount
可是仍然不行
原因如下:
###############################################
http://blog.csdn.net/yebanghua/article/details/7301904
2.4 设置强制性锁注意问题
在设置强制性锁注意的问题:几乎所有的操作都需要root权限。
1. 首先,su到root权限下,输入:mount 可以看到挂载的所有内容,如果所用磁盘存在其他挂载路径,要让mand成功,必须是:所用磁盘(sda1)被挂载的方式有mand存在。
比如存在: /dev/sda1 on /boot type ext3(rw)
/dev/sda1 on /opt/327/XXX typeext3(rw, mand)
则不成功。
需要:/dev/sda1 on /boot typeext3(rw, mand)
/dev/sda1 on /opt/327/XXX type ext3(rw,mand)
###############################################
虽然把原来的sda1挂载到一个新的目录上了,而且设置了mandatory。但是最原始的sda1却不是 mandatory 的,那么如何将 /dev/sda1 on /boot type ext3 设置成为 mandatory的呢?
###############################################
http://www.blogjava.net/qileilove/archive/2012/05/23/378903.html
# mount -o remount,mand /
###############################################
测试代码:
#include
#include
#include
#include
#include
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP | S_IROTH)
#define write_lock(fd, offset, whence, len) \
lock_reg((fd),F_SETLK,F_WRLCK,(offset),(whence),(len))
int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
{
struct flock lock;
lock.l_type = type;
lock.l_start = offset;
lock.l_whence = whence;
lock.l_len = len;
return (fcntl(fd,cmd,&lock));
}
int main()
{
int fd;
struct stat statbuf;
if( (fd = creat("templock",FILE_MODE)) < 0)
perror("create error");
if (stat("templock",&statbuf) < 0)
perror("stat error for templock");
if(chmod("templock",(statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0)
perror("chmod error for templock");
if( write(fd, "abc", 3) != 3)
perror("write error");
if ( write_lock(fd,1,SEEK_SET,1) < 0)
perror("write_lock error");
pid_t pid;
if ((pid = fork()) < 0)
{
perror("fork error");
}
else if (pid == 0)
{
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_start = 1;
lock.l_whence = SEEK_SET;
lock.l_len = 1;
if(fcntl(fd,F_GETLK,&lock) < 0)
perror("get lock error");
printf("F_RDLCK = %d, F_WRLCK = %d, F_UNLCK = %d, type = %d, pid = %d\n",F_RDLCK, F_WRLCK, F_UNLCK, lock.l_type, lock.l_pid);
int dupfd;
dupfd = open("templock",O_RDWR);
char ch[3] = {0,0,0};
if(read(dupfd,ch,3)<0)
perror("read error");
else
printf("%s\n",ch);
ch[1] = 'd';
lseek(dupfd,0,SEEK_SET);
if(write(dupfd,ch,3) < 0)
perror("write error");
return 0;
}
else
{
waitpid(pid,NULL,0);
}
}
最后,IBM developerWorks有篇文章介绍了文件锁:
http://www.ibm.com/developerworks/cn/linux/l-cn-filelock/#toggle