美文网首页
Linux系统编程7:读写锁

Linux系统编程7:读写锁

作者: jdzhangxin | 来源:发表于2018-04-30 09:11 被阅读129次

    1. 接口

    int fcntl(int filedes, int cmd,...)
    

    1.1 锁操作

    int fcntl(int fd, int cmd, struct flock *lock)
    
    • 参数
    No. 参数 含义
    1 fd 文件描述符
    2 cmd 命令。F_GETLK:获取锁;F_SETLK:设置锁;F_SETLKW:设置阻塞锁。
    3 struct flock 锁信息
    • 锁信息
    No. 参数 含义
    1 l_type F_RDLCK:读取锁(共享锁);F_WRLCK:写入锁(排斥锁);F_UNLCK:解锁
    2 l_whence SEEK_SET:以文件开头为锁定的起始位置;SEEK_CUR:以目前文件读写位置为锁定的起始位置;SEEK_END:以文件结尾为锁定的起始位置
    3 l_start 相对l_whence位置的偏移量
    4 l_len 锁定区域的长度。0表示到整个文件的结束
    5 l_pid 当前占用锁的PID,只对F_GETLK命令有效
    • 返回值
    No. 返回值 含义
    1 -1 失败
    2 0 SET相关命令成功
    • 给指定文件添加读锁
    #include <stdio.h>
    #include <fcntl.h>
     
    int main(int argc, char* argv[]){
        if(2!=argc){
            printf("usage:%s <pathname>\n",argv[0]);
            return 1;
        }
        int fd = open(argv[1],O_RDONLY);
        if(-1 == fd){
            perror("open error");
            return 1;
        }
        struct flock lock;
        lock.l_type = F_RDLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0; 
        if(-1 == fcntl(fd,F_SETLK,&lock)){
            perror("fcntl error");
            return 1;
        }
        pause();
        close(fd);
    }
    
    • 查看当前锁的状态
    #include <stdio.h>
    #include <fcntl.h>
    #include <string.h>
     
    int main(int argc, char* argv[]){
        if(2!=argc){
            printf("usage:%s <pathname>\n",argv[0]);
            return 1;
        }
        int fd = open(argv[1],O_RDWR);
        if(-1 == fd){
            perror("open error");
            return 1;
        }
        struct flock lock;
        bzero(&lock,sizeof(lock));
        if(-1 == fcntl(fd,F_GETLK,&lock)){
            perror("fcntl error");
            return 1;
        }
        printf("file:%s,lock type:%d,start:%d,len:%d,by %d\n",argv[1],lock.l_type,lock.l_start,lock.l_len,lock.l_pid);
     
    }
    
    • 给指定文件添加写锁
    #include <stdio.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <unistd.h>
    int fd;
     
    void handler(int sig){
        struct flock lock;
        lock.l_type = F_UNLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0; 
        if(-1 == fcntl(fd,F_SETLKW,&lock)){
            perror("fcntl error");
            exit(1);
        }
    }
     
    int main(int argc, char* argv[]){
        signal(SIGUSR1,handler);
        int c,start = 0,len = 0;
        while((c = getopt(argc,argv,"s:l:"))!=-1){
            switch(c){
            case 's':
                start = atoi(optarg);
                break;
            case 'l':
                len = atoi(optarg);
                break;
            }
        }
     
        if(optind != argc -1){
            printf("usage:%s [-s <start>] [-l <len>] <pathname>\n",argv[0]);
            return 1;
        }
        fd = open(argv[optind],O_WRONLY);
        if(-1 == fd){
            perror("open error");
            return 1;
        }
        struct flock lock;
        lock.l_type = F_WRLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = start;
        lock.l_len = len; 
        if(-1 == fcntl(fd,F_SETLKW,&lock)){
            perror("fcntl error");
            return 1;
        }
        pause();
        for(;;);
        close(fd);
    }
    
    • 给指定文件解锁
    // 本程序不能解锁,因为只有加锁进程才能执行解锁操作
    #include <stdio.h>
    #include <fcntl.h>
     
    int main(int argc, char* argv[]){
        if(2!=argc){
            printf("usage:%s <pathname>\n",argv[0]);
            return 1;
        }
        int fd = open(argv[1],O_WRONLY);
        if(-1 == fd){
            perror("open error");
            return 1;
        }
        struct flock lock;
        lock.l_type = F_UNLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0; 
        if(-1 == fcntl(fd,F_SETLKW,&lock)){
            perror("fcntl error");
            return 1;
        }
        pause();
        close(fd);
    }
    

    1.2 死锁

    交通堵塞 死锁
    #include <stdio.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <stdlib.h>
    void lock(const char* pathname){
     
        int fd = open(pathname,O_WRONLY);
        if(-1 == fd){
            perror("open error");
            exit(1);
        }
        struct flock lock;
        lock.l_type = F_WRLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0; 
        if(-1 == fcntl(fd,F_SETLKW,&lock)){
            perror("fcntl error");
            exit(1);
        }
        //close(fd);
    }
    int main(int argc, char* argv[]){
        if(3!=argc){
            printf("usage:%s <pathname1> <pathname2>\n",argv[0]);
            return 1;
        }
        printf("PID:%d lock file %s\n",getpid(),argv[1]);
        lock(argv[1]);
        printf("sleep 1s\n");
        sleep(1);
        printf("PID:%d lock file %s\n",getpid(),argv[2]);
        lock(argv[2]);
        pause();
    }
    

    1.3 记录锁

    • 作用:文件读与写的同步
    • 本质:当一个进程正在读或修改文件的某个部分时,阻止其他进程修改同一文件区。

    1.2.1 分类

    • 访问操作
      写入锁(排他锁)/读取锁(共享锁)
    • 加锁区域
      文件锁(整个文件上锁)/记录锁(文件部分内容上锁)

    1.2.2 操作

    1.2.2.1 获取
    fcntl(fd,F_GETLK)
    

    1.2.2.2 设置

    fcntl(fd,F_SETLK,arg)
    fcntl(fd,F_SETLKW,arg)
    

    辅助函数

    • lseek_append.cpp
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
     
    int main(int argc,char* argv[]){
        if(4 != argc){
            printf("usage:%s <pathname> <off> <content>\n",argv[0]);
            return 1;
        }
        int fd = open(argv[1],O_RDWR);
        if(-1 == fd){
            return 1;
        }
        off_t off = lseek(fd,atoi(argv[2]),SEEK_SET);
        if(-1 == off){
            return 1;
        }
        struct stat stat_buf;
        fstat(fd,&stat_buf);
        size_t save_size = stat_buf.st_size - off;
        //char buf[save_size];
        char *buf = malloc(save_size);
        if(-1 == read(fd,buf,save_size)){
            return 1;
        }
         
        off = lseek(fd,atoi(argv[2]),SEEK_SET);
        if(-1 == off){
            return 1;
        }
        if(-1 == write(fd,argv[3],strlen(argv[3]))){
            return 1;
        }
        if(-1 == write(fd,buf,save_size)){
            return 1;
        }
     
        free(buf);
        buf = NULL;
    }
    
    • lseek_read.cpp
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
     
    int main(int argc,char* argv[]){
        if(4 != argc){
            printf("usage:%s <pathname> <off> <len>\n",argv[0]);
            return 1;
        }
        int fd = open(argv[1],O_RDONLY);
        if(-1 == fd){
            return 1;
        }
        off_t off = lseek(fd,atoi(argv[2]),SEEK_SET);
        if(-1 == off){
            return 1;
        }
        size_t len = atoi(argv[3]);
        char buf[len+1];
        bzero(buf,len+1);
        if(-1 == read(fd,buf,len)){
            return 1;
        }
        printf("%s\n",buf);
    }
    
    • lseek_write.cpp
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
     
    int main(int argc,char* argv[]){
        if(4 != argc){
            printf("usage:%s <pathname> <off> <content>\n",argv[0]);
            return 1;
        }
        int fd = open(argv[1],O_WRONLY);
        if(-1 == fd){
            return 1;
        }
        off_t off = lseek(fd,atoi(argv[2]),SEEK_SET);
        if(-1 == off){
            return 1;
        }
        if(-1 == write(fd,argv[3],strlen(argv[3]))){
            return 1;
        }
    }
    

    相关文章

      网友评论

          本文标题:Linux系统编程7:读写锁

          本文链接:https://www.haomeiwen.com/subject/alrmhftx.html