SylixOS文件记录锁使用

1. 文件记录锁介绍

       文件锁锁定的是整个文件,而记录锁定还可以锁定文件的某一特定部分,即从文件的某一相对位置开始的一段连续的字节流。

       当一个进程正在读取或者修改文件的某个部分时,使用文件记录锁可以阻止其他进程修改同一文件的相同区域。它可以用来锁定文件的某个区域或者整个文件,SylixOS 支持多种文件记录锁 API。

注:SylixOS 支持多种设备驱动模型,但是目前只有 NEW_1 型设备驱动支持文件记录锁功能,此类驱动文件节点类似于UNIX 系统的 vnode。

2. 文件记录锁设置

      SylixOS可以通过fcntl 函数操作文件记录锁的功能。

2.1      fcntl原型

#include <fcntl.h>

int  fcntl (int  iFd, int  iCmd, ...)

函数fcntl原型分析:

1. 此函数成功时根据参数iCmd的不同而返回不同的值,失败返回-1并设置错误号;

2. 参数 iFd 是文件描述符;

3. 参数 iCmd 是命令;

4. 参数 ...是命令参数。

      fcntl设置文件记录锁时iCmd对应3个命令:F_GETLK、F_SETLK 和 F_SETLKW。命令解释分别是:F_GETLK表示获取文件锁;F_SETLK表示设置文件锁(非阻塞);F_SETLKW表示设置文件锁(阻塞)。第 3 个参数是一个 flock 结构体指针,结构体成员如程序清单 2‑1所示。

程序清单 2‑1  flock结构体成员

struct flock {

    short   l_type;                                            /* F_RDLCK, F_WRLCK, or F_UNLCK */

    short   l_whence;                                       /* flag to choose starting      */

                                                                       /* offset                       */

    off_t   l_start;                                              /* relative offset, in bytes    */

    off_t   l_len;                                                 /* length, in bytes; 0 means    */

                                                                       /* lock to EOF                  */                                                                               

    pid_t   l_pid;                                                 /* returned with F_GETLK        */

    long    l_xxx[4];                                           /* reserved for future use      */

};

1.   l_type表示锁的类型分别为:F_RDLOCK(共享读锁)、F_WRLOCK(独占写锁)和F_UNLCK(解锁);

2.   l_whence表示文件记录锁的起始位置,其值如图 2‑1所示。

                               图 2‑1  l_Whence值相关

iWhence

oftOffset 说明

SEEK_SET

将文件的偏移量设置为距文件开始处 oftOffset 个字节

SEEK_CUR

将文件的偏移量设置为当前值加oftOffset个字节,oftOffset可为负

SEEK_END

将文件的偏移量设置为文件长度加oftOffset个字节,oftOffset可为负

3.   l_start是相对l_whence偏移开始位置(注意不可以从文件开始的之前部分锁起);

4.   l_len是锁定区域长度,如果为0则锁定文件尾(EOF),如果向文件中追加数据也将被锁;

5.   l_pid是已占用锁的进程ID(由命令F_GETLK返回)。

2.2      文件记录锁使用规则

       文件记录锁中的F_RDLOCK(共享读锁)和F_WRLOCK(独占写锁)的基本规则是:任意多个进程在一个给定字节上可以有一把共享的读锁,但是在一个给定字节上只能有一个进程有一把独占的写锁。进一步而言,如果在一个给定字节上已经有一把或多把读锁,则不能在该字节上再加写锁;如果在一个给定字节上有一把写锁,则不能再加任何锁。基本规则如表 2‑1所示。

                                   表 2‑1  记录锁规则


      上面的规则适用于不同进程提出的锁请求,并不适用于单个进程提出的锁请求。也就是说,如果一个进程对一个文件区间已经有了一把锁,后来该进程又企图在同一个区间再加一把锁,那么也是可以的,这个时候新锁将替换已有锁。因此,如果一个进程将某个文件加了一把写锁,然后又企图给文件加一把读锁,那么将会成功执行,原来的写锁会被替换为读锁。

2.3      文件记录锁特点

1.     记录锁采用(pid,start,end)三元组作为锁标识,一个文件可拥有多个记录锁,同一区域只允许有一个记录锁。

2.     当进程终止(正常/不正常),该进程拥有的所有记录锁都将释放。同一个进程中,指向同一文件(i-node)的fd都可以操作该文件上的记录锁:如释放、修改等。显式调用F_UNLCK和close(fd)都将释放锁,close将释放整个文件中该进程拥有的所有记录锁。

3.     记录锁不被spawn的子进程继承(PID不同)。

4.     记录锁的类型转换、改变锁范围等操作均为原子操作。

5.     未设置FD_CLOEXEC时,记录锁将被exec后的进程继承(PID相同)。

6.     记录锁对文件打开mode有要求:加读锁要求文件句柄fd有读权限,加写锁要求fd有写权限。

3. 文件记录锁使用

       比如进程A对文件“/apps/file”加上写锁(进程A先上锁),当A进程用户操作结束后会释放锁给进程B操作,进程A代码如程序清单 3‑1所示。

                                             程序清单 3‑1  进程A代码

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

 

#define FILE_PATH   "/apps/file"

int main(int argc, char *argv[])

{

    int           iFd     = 0;

    struct flock flck;

    short         sLockt  = F_WRLCK;

 

    iFd = open(FILE_PATH, O_RDWR);                 /*  打开文件                      */                                  

    if (iFd < 0) {

        fprintf(stderr, "open file failed.\n");

        return -1;

    }

    /*

     *  l_whence = SEEK_SET;l_start  = 0;表示从文件开始起偏移量为0开始上锁

     *  l_len    = 0;表示锁定到文件尾

     */

    flck.l_type   = sLockt;                       /*  文件记录锁类型设置为独写锁     */

    flck.l_whence = SEEK_SET;

    flck.l_start  = 0;

    flck.l_len    = 0;

 

    if (fcntl(iFd, F_SETLK, &flck) < 0) {         /*  fcntl设置文件记录锁            */

        fprintf(stderr, "add write lock failed.\n");

        close(iFd);

        return -1;

    }

    /*

     *  用户对文件被锁定区域操作

     */

sLockt        = F_UNLCK;                      /*  文件记录锁类型设置为解锁       */

    flck.l_type   = sLockt;

    flck.l_whence = SEEK_SET;

    flck.l_start  = 0;

    flck.l_len    = 0;

 

    if (fcntl(iFd, F_SETLK, &flck) < 0) {

        fprintf(stderr, "unlock failed.\n");

        close(iFd);

        return -1;

    }

    close(iFd);

    return 0;

}

      进程B也对文件“/apps/file”操作,区别是进程B设置为F_SETLKW(阻塞等待解锁)。进程B阻塞等待进程A解锁方可对文件进行操作,进程B代码如程序清单 3‑2所示。

                                           程序清单 3‑2  进程B代码

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

 

#define FILE_PATH   "/apps/file"

int main(int argc, char *argv[])

{

    int          iFd     = 0;

    struct flock flck;

    short        sLockt  = F_WRLCK;

 

    iFd = open(FILE_PATH, O_RDWR);                  /*  打开文件                      */

    if (iFd < 0) {

        fprintf(stderr, "open file failed.\n");

        return -1;

    }

    /*

     *  l_whence = SEEK_SET;l_start  = 0;表示从文件开始起偏移量为0开始上锁

     *  l_len    = 0;表示锁定到文件尾

     */

    flck.l_type   = sLockt;                          /*  文件记录锁类型设置为独写锁   */                                 

    flck.l_whence = SEEK_SET;

    flck.l_start  = 0;

    flck.l_len    = 0;

 

    if (fcntl(iFd, F_SETLKW, &flck) < 0) {          /*  fcntl设置文件记录锁          */

        fprintf(stderr, "add write lock failed.\n");

        close(iFd);

        return -1;

    }

    /*

     *  用户对文件被锁定区域进行操作

     */

    close(iFd);

    return 0;

}

 

转载于:https://my.oschina.net/u/3022273/blog/880028

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值