• Linux-进程间通信(六): 记录锁


    1. 记录锁:记录锁的功能是,当一个进程正在读或者修改文件的某个部分的时候,它可以阻止其他进程修改同一文件区;

    2. fcntl记录锁:

    #include <fcntl.h>
    
    int fcntl(int filedes, int cmd, ... /* struct flock *flockptr */);
    
    ret = 成功依赖于cmd,出错返回-1

    对于记录锁,cmd是F_GETLK, F_SETLK, F_SETLKW。

    F_GETLK-判断由flockptr描述的锁是否会被另外一把锁排斥,若存在,则把现存锁的信息写入到flockptr中,若不存在,则除了将l_type设置为F_UNLCK之外,结构中其余信息不变;

    F_SETLK-设置由flockptr描述的锁,如果按照共享读锁和独占写锁规则,不允许加锁,则立即返回错误码;

                -此命令也用于清除flockptr说明的锁,l_type=F_UNLCK

    F_SETLKW-是F_SETLK的阻塞版本,当不满足加锁规则时候,进程进入休眠,如果请求创建的锁已经可用,则休眠由信号中断,进程被唤醒;

    第三个参数flock结构如下:

    struct flock {
        short l_type;
        off_t l_start;
        short l_whence;
        off_t l_len;
        pid_t l_pid; 
    };

    结构说明:

    l_type: 所希望的锁类型,F_RDLCK(共享读锁), F_WRLCK(独占读锁), F_UNLCK(解锁一个区域);

    l_start: 相对偏移量;

    l_whence: 相对偏移量的起点;可选用的值:SEEK_SET(文件开头), SEEK_CUR(当前位置), SEEK_END(文件结尾)

    l_len: 区域字节的长度;

    l_pid: 具有阻塞当前进程的锁,其进程ID存放在l_pid;

    3. 加锁和解锁区域说明:

    (1) l_start是相对偏移量,l_whence决定了相对偏移量的起点;

    (2) 该区域可以在当前文件的尾端处开始,但是不能再文件的起始位置之前开始;

    (3) 如果l_len=0,则表示锁的区域从l_whence和l_start决定的起点开始,直至最大可能偏移量为止,不管写到该文件多少数据,他们都处于所得范围内;

    (4) 为了锁整个文件,我看设置l_start=0和l_whence=SEEK_SET,使所得起点在文件起始处,并且说明长度l_len=0.

    4.  共享读锁与独占写锁:

    多个进程在给定的字节上可以有一把共享的读锁,但是在一个给定字节上只能有一个进程独占一把写锁;

    如果在一个给定字节上已经有了一把或者多把读锁,可以继续添加读锁,但是不能在该字节上加写锁;如果在一个字节上已经有了一把独占写锁,则不能再添加任何读/写锁;

    注意:这个规则只适用于不同进程提出的锁请求,如果单个进程对一个文件区间已经有了一把锁,后来又企图对同一文件区加另一把锁,那么新锁将替换旧锁;

    5. 记录锁的隐含继承和释放:

    (1) 进程终止时,所建立的锁全部被释放;

    (2) 关闭任何一个描述符,则该进程通过该描述符可以引用的文件上的任何一把锁都被释放;

    (3) fork产生的子进程不继承父进程锁设置的锁;

    (4) 在执行了exec后,新程序可以继续执行原来程序的锁;如果对一个描述符设置了close-on-exec,则exec执行时候,文件描述符被关闭,对应锁也被释放;

    6. 在文件尾加锁:

    (1) 在加锁之前最好是对文件当前位置或者当前长度指定一把锁,因为在lseek和加锁调用之间,可能有另外一个进程在改变该文件的长度;

    (2) 下面代码第一次加锁的时候,得到一把锁,从文件尾端开始,包括以后添加的任何数据,都会加锁;解锁的时候,文件尾端已经变化了,所以并没有解锁;

    writew_lock(fd, 0, SEEK_END, 0);

    write(fd, buf, 1); //这个字节也被加锁

    un_lock(fd, 0, SEEK_END, 0); //并没有解锁前面字节,len指定为-1可解锁前面字节

    write(fd, buf, 1); //这个字节没被加锁

    7. 强制性锁和建议性锁:

    合作进程,多个进程都用一致的方式处理记录锁,完成某些任务,这些进程集合就是合作进程;

    建议性锁:建议性锁不做强制检查锁规则,需要进程自己获取,检查是否有锁存在,对于合作进程来说,建议性锁是可行的,但是对于某些非合作进程,他们不进程检查,就对文件进行改写,就会对当前文件造成影响;如建议性锁可以比如成红绿灯,只是建议性的,因为还是有人可以闯红灯;

    强制性锁:内核对每个open,read,write系统调用都进行检查,检查访问的文件是否违背了锁规则,如果违背了锁规则,则该IO调用被禁止;

    8. 锁的操作宏:

     1 int     lock_reg(int, int, int, off_t, int, off_t)
     2 {
     3     struct flock lock;
     4     
     5     lock.l_type = type;
     6     lock.l_start = offset;
     7     lock.l_whence = whence;
     8     lock.l_len = len;
     9 
    10     return (fcntl(fd, cmd, &lock));
    11 }
    12 
    13 #define read_lock(fd, offset, whence, len) 
    14             lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))
    15 #define readw_lock(fd, offset, whence, len) 
    16             lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))
    17 #define write_lock(fd, offset, whence, len) 
    18             lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))
    19 #define writew_lock(fd, offset, whence, len) 
    20             lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))
    21 #define un_lock(fd, offset, whence, len) 
    22             lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))
    23 
    24 pid_t   lock_test(int, int, off_t, int, off_t)
    25 {
    26     struct flock lock;
    27     
    28     lock.l_type = type;
    29     lock.l_start = offset;
    30     lock.l_whence = whence;
    31     lock.l_len = len;
    32 
    33     if (fcntl(fd, F_GETLK, &lock) < 0)
    34         return -1;
    35 
    36     if (lock.l_type == F_UNLCK)
    37         return 0;
    38     
    39     return (lock.l_pid);
    40 }
    41 
    42 #define is_read_lockable(fd, offset, whence, len) 
    43             (lock_test((fd), F_RDLCK, (offset), (whence), (len)) == 0)
    44 #define is_write_lockable(fd, offset, whence, len) 
    45             (lock_test((fd), F_WRLCK, (offset), (whence), (len)) == 0)
  • 相关阅读:
    自学软件测试获取学习资源途径有哪些?
    微信发红包-测试分析
    软件测试初级经验
    面试
    电商项目
    LoadRunner11的安装流程+破解+汉化+下载
    Oracle和Mysql操作上的一些区别
    Android模拟器,ADB命令
    logging
    heapq
  • 原文地址:https://www.cnblogs.com/wanpengcoder/p/5305749.html
Copyright © 2020-2023  润新知