Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4562235
  • 博文数量: 1214
  • 博客积分: 13195
  • 博客等级: 上将
  • 技术积分: 9105
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-19 14:41
个人简介

C++,python,热爱算法和机器学习

文章分类

全部博文(1214)

文章存档

2021年(13)

2020年(49)

2019年(14)

2018年(27)

2017年(69)

2016年(100)

2015年(106)

2014年(240)

2013年(5)

2012年(193)

2011年(155)

2010年(93)

2009年(62)

2008年(51)

2007年(37)

分类: LINUX

2010-09-15 09:39:33

             UNIX网络编程卷2进程间通信—记录锁

1.记录锁的功能

       当一个进程正在读或修改文件的某个部分时,它可以阻止其他进程修改同一文件区。我们不应该从字面上去理解记录锁,实际上它应该叫“区域锁”,因为它锁定的只是文件的一个(也可能是整个文件)。这个区域用来存放多用户的共享区。

2.记录锁的分类

       记录锁分为共享读锁和独占写锁,前者也叫做共享锁后者也叫做排他锁。

3.加锁规则

      如果一个进程对共享区加了共享读锁,其他进程只能加共享读锁。如果一个进程加了独占写锁,其他进程就不能加任何锁。

4.死锁

       如果两个相互等待对方持有并且不释放(已被锁定)的资源是时,则这两个进程就处于死锁状态。如果一个进程已经控制了文件的一个加锁区域,然后它又试图对另一个进程控制的区域加锁,则它就会睡眠,在这种情况下,有发生死锁的可能性。

5.锁的隐含继承和释放

1)锁与进程和文件两方面有关系,它和前者关系是:当一个进程结束后,他对文件加的锁也就消失了。它和后者的关系是:当进程close文件描述符,切断文件和进程的联系进程所创建的锁也会消失。

2)由fork产生的子进程不继承父进程所设置的锁。这意味着,若一个进程得到一把锁,然后调用fork,那么对于父进程创建的锁而言,子进程被视为另一个进程,不会拥有该锁。

3)在执行exec后,新进程可以继承原执行的锁。因为执行exec前后还是一个进程。我们只是改变进程执行的程序,并没有创建新的进程。

不让exec继承原来锁的方法/* set close-on-exec flag for descriptor */:
加锁后,
val = fcntl(fd, F_GETFD, 0);
val |= FD_CLOEXEC;
fcntl(fd, F_SETFD, val);

6.要注意的问题

    记录锁只是提供竞争进入某段代码区的功能,不会导致对文件操作失败。也就是说,我们对文件进行加锁后,我们还是可以对文件进行操作。

下面是给一个文件加锁和测试锁的程序。

/*12_1.c加锁程序*/
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
 
int main(int argc,char *argv[])
{
    int fd;
    struct flock lock;
 
    if((fd=open(argv[1],O_WRONLY))<0)
        perror(argv[1]);
    lock.l_type=F_WRLCK; /*设置flock结构*/
    lock.l_start=0;
    lock.l_whence=0;
    lock.l_len=0;
 
    if(fcntl(fd,F_SETLK,&lock)<0) /*加锁整个文件*/
    {
        perror(argv[1]);
        exit(1);
    }
    sleep(10);
    close(fd);
    exit(0);
}



/*12_2.c测试锁程序*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
 
int main(int argc,char *argv[])
{
    int fd;
    struct flock lock;
    char buf[]="123456";
 
    if((fd=open(argv[1],O_WRONLY))<0)
        perror(argv[1]);
    lock.l_type=F_WRLCK; /*设置flock结构*/
    lock.l_start=0;
    lock.l_whence=0;
    lock.l_len=0;
 
    if(fcntl(fd,F_GETLK,&lock)<0)/*测试共享资源是否加锁*/
    {
        perror(argv[1]);
        exit(1);
    }
    if(lock.l_type==F_UNLCK)
        printf("Is not clocked!\n");
    else
        printf("Is clocked!\n");
    if(write(fd,buf,sizeof(buf))<0)
        perror("wrire error");
    close(fd);
    exit(0);
}


先在后台运行加锁程序

#./12_1 12_1.c&

然后在十秒之内运行测试锁的程序

#./12_2 12_1.c

在屏幕上会打印:Is clocked!

如果等待1012_1.c运行完

再次运行测试锁的程序则会打印:Is not clocked!

12_1 把文件锁住,所以12_1.c文件的资源暂时不可获得,可12_2 程序仍然可以往12_1.c 里面写入"123456"。12_2 10秒后再运行,这时文件12_1.c 未被加锁,并且12_2 程序往12_1.c 里面写入了"123456"。

参考资料:

UNIX高级环境编程》第2 人民邮电出版社

UNIX网络编程》第2 清华大学出版社

POSIX多线程程序设计》 中国电力出版社

Linux网络编程教程》 北京希望电子出版社

还有网上的一些资料

特别感谢CU论坛的上的朋友们。


建议性锁(advisory)与强制性锁(mandatory):
建议性锁是这样规定的:每个使用上锁文件的进程都要检查是否有锁存在,当然还得尊重已有的锁。内核和系统总体上都坚持不使用建议性锁,它们依靠程序员遵守这个规定。  也就是说:如果进程不尊重锁,则进程在没有获得锁的情况下也可以对一个已经被别的进程加写锁的文件进行读写。尊重该锁的所有进程被称为合作进程 (cooperating process)。所以只有在文件只在合作进程间存取时才是安全的。

fcntl(fd, F_SETLK, &lock);。lockf 也是。
Linux not support mandaroty lock, 如果要加,得配合mount ,chomod 等,具体查看手册。
You can use open (, O_CREATE | O_EXCL) open a file, and other process would fail to open this file.

The most important thing about these locking mechanisms is that any application that could be accessing the files in question must also use the same locking mechanism.And this is unfortunately a problem when you don't control all the software in question.


参考链接:

阅读(2022) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~