zoukankan      html  css  js  c++  java
  • [Linux]fcntl函数文件锁概述

    概述

    fcntl函数文件锁有几个比较容易忽视的地方:

    1.文件锁是真的进程之间而言的,调用进程绝对不会被自己创建的锁锁住,因为F_SETLK和F_SETLKW命令总是替换调用进程现有的锁(若已存在),所以调用进程决不会阻塞在自己持有的锁上,于是,F_GETLK命令决不会报告调用进程自己持有的锁。

    2.struct flock结构指针中的l_type成员3个short值分别是:

    常量
    F_RDLCK 0
    F_WRLCK 1
    F_UNLCK 2

     

    3.如果两个锁之间的文件区域有交集,就会阻塞,无论交集的大小。

     

    如图中section 1持有1到10字节区间的读锁,倘若此时需要创建section 2写锁,那么需要等待section 1区域释放才行。

    示例代码:

    进程A

    #include <error.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <fcntl.h>
    
    extern int *__errno_location(void);
    #define errno (*__errno_location())
    
    void report_err(int re);
    
    struct flock section_1 = {
        F_RDLCK,
        SEEK_SET,
        0,
        10
    };
    struct flock section_1_1 = {
        F_RDLCK,
        SEEK_SET,
        0,
        10
    };
    
    int main(void)
    {
        int re;
        int file = open("/documents/test/test_2", O_RDWR);
        printf("open file fd: %d
    ", file);
        //struct flock section_1_1 = section_1;
        re = fcntl(file, F_GETLK, &section_1);
        printf("section_1 l_type: %d
    ", (&section_1)->l_type);
        re = fcntl(file, F_SETLK, &section_1_1);
        report_err(re);
        printf("section_1_1 l_type: %d
    ", (&section_1_1)->l_type);
    
        sleep(10);
        return 0;
    }
    
    void report_err(int re)
    {
        if(re == -1){
            perror("file error");
        }
    }

    进程B

    #include <error.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <fcntl.h>
    
    extern int *__errno_location(void);
    #define errno (*__errno_location())
    
    void report_err(int re);
    
    
    struct flock section_2 = {
        F_WRLCK,
        SEEK_SET,
        5,
        10
    };
    struct flock section_2_1 = {
        F_WRLCK,
        SEEK_SET,
        5,
        10
    };
    
    int main(void)
    {
        int re;
        int file = open("/documents/test/test_2", O_RDWR);
        printf("open file fd: %d
    ", file);
    
        re = fcntl(file, F_GETLK, &section_2);
        report_err(re);
        printf("section_2 l_type: %d
    ", (&section_2)->l_type);
        re = fcntl(file, F_SETLKW, &section_2_1);
        report_err(re);
        printf("section_2_1 l_type: %d
    ", (&section_2_1)->l_type);
        return 0;
    }
    
    void report_err(int re)
    {
        if(re == -1){
            perror("file error");
        }
    }

    进程A在创建section 1后阻塞10秒,期间启动进程B创建section 2,此时进程B阻塞等待进程A释放section 1。

    4.锁与进程和文件关联。这里有两重含义:第一重很明显,当一个进程终止时,它所有建立的锁全部释放;第二重则不太明显,无论一个描述符何时关闭,该进程通过这一描述符引用的文件上的任何一把锁都会释放(这些锁都是该进程设置的),详情参见《Unix高级环境编程》396页。

  • 相关阅读:
    UDP案例_在线咨询
    MFC对话框水平和垂直滚动条功能
    对话框中滚动条
    ON_COMMAND_RANGE 多个按钮响应一个函数
    char**赋值
    MFC如何使dialog对话框置顶
    如何让CListBox控件滚动条自动向下滚动?
    不带,以及带参数,带返回值的Lambda表达式
    JAVA学习_多线程技术
    最烦有些技术帖上来就放代码
  • 原文地址:https://www.cnblogs.com/yiyide266/p/10629624.html
Copyright © 2011-2022 走看看