SylixOS文件记录锁使用

1. 文件记录锁介绍

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

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

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

2. 文件记录锁设置

      SylixOS能够经过fcntl 函数操做文件记录锁的功能。spa

2.1      fcntl原型

#include <fcntl.h>指针

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

函数fcntl原型分析:进程

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

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

3. 参数 iCmd 是命令;it

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;

}

相关文章
相关标签/搜索