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;

}

相關文章
相關標籤/搜索