记录锁

作用

记录锁与读写锁很相似, 记录锁也分读和写两种操作, 但它们的作用对象分别是进程和线程.
多个进程对同一文件进行访问时,记录锁可以锁定文件的某一个区间,以读操作锁定时允许其它进程进行继续加读锁, 以写操作锁定时不允许其它进程添加读锁或写锁.
记录锁只对加锁的函数fcntl进行检测, 如果其它进程不按先加锁后读写的顺序进行访问则记录锁不起作用.
在一些系统上将组权限位打开, 同时关闭组执行位可强制所有读写函数进行锁检查.

基本函数

#include <fcntl.h>
int fcntl(int fd, int cmd, struct flock *lock);
cmd = F_GETLK //获取文件当前锁的状态,第三个参数作为输出
cmd = F_SETLK //设置锁,第三个参数作为输入
cmd = F_SETLKW //阻塞设置一把锁,第三个参数作为输入
 
struct flock {
      short l_type;    /* 锁的类型: F_RDLCK, F_WRLCK, F_UNLCK */
      short l_whence;  /* 加锁的起始位置:SEEK_SET, SEEK_CUR, SEEK_END */
      off_t l_start;   /* 加锁的起始偏移,相对于l_whence */
      off_t l_len;     /* 上锁的字节数*/
      pid_t l_pid;     /* 已经占用锁的PID(只对F_GETLK 命令有效) */
      /*...*/
};

例子

#include "unpipc.h"
 
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));
}
 
pid_t lock_test(int fd,int type,off_t offset,int whence,off_t len){
    struct flock lock;
 
    lock.l_len=len;
    lock.l_type=type;
    lock.l_whence=whence;
    lock.l_len=len;
 
    if(fcntl(fd,F_GETLK,&lock) == -1)
        return(-1);
 
    if(lock.l_type == F_UNLCK)
        return(0);
    return(lock.l_pid);
}
 
#define read_lock(fd,offset,whence,len) 
    lock_reg(fd,F_SETLK,F_RDLCK,offset,whence,len)
#define readw_lock(fd,offset,whence,len) 
    lock_reg(fd,F_SETLKW,F_RDLCK,offset,whence,len)
#define write_lock(fd,offset,whence,len) 
    lock_reg(fd,F_SETLK,F_WRLCK,offset,whence,len)
#define writew_lock(fd,offset,whence,len) 
    lock_reg(fd,F_SETLKW,F_WRLCK,offset,whence,len)
#define un_lock(fd,offset,whence,len) 
    lock_reg(fd,F_SETLK,F_UNLCK,offset,whence,len)
#define is_read_lockable(fd,offset,whence,len) 
    !lock_test(fd,F_RDLCK,offset,whence,len)
#define is_write_lockable(fd,offset,whence,len) 
    !lock_test(fd,F_WRLCK,offset,whence,len)
 
int main(int argc, char *argv[]){
    pid_t pid;
    int fd=Open("./lock.c",O_RDWR,0777);
    if((pid=Fork())==0){
        if(read_lock(fd,0,SEEK_SET,1) == -1)
            err_quit("child read_lock error");
       puts("child read_lock file");
       sleep(3);
       puts("child un_lock file");
       un_lock(fd,0,SEEK_SET,1);
    }else{
        sleep(1);
       if(write_lock(fd,0,SEEK_SET,1) == -1)
           puts("father write_lock failed, waiting for child un_lock");
       if(writew_lock(fd,0,SEEK_SET,1) == -1)
           puts("father writew_lock error");
       puts("father got write lock");
       un_lock(fd,0,SEEK_SET,1);
       waitpid(pid,NULL);
    }
    exit(0);
}
原文地址:https://www.cnblogs.com/cfans1993/p/5800603.html