久久婷婷香蕉热狠狠综合,精品无码国产自产拍在线观看蜜,寡妇房东在做爰3,中文字幕日本人妻久久久免费,国产成人精品三上悠亚久久


linux 文件鎖的實現及其應用

分享(xiang)到:
           

    文件鎖

    1.fcntl()函數(shu)說明

    前面講(jiang)述(shu)的(de)(de)5個基(ji)本(ben)函(han)數實(shi)現(xian)了(le)文件的(de)(de)打開、讀(du)/寫等(deng)基(ji)本(ben)操(cao)作,本(ben)節將討論(lun)在文件已經共享(xiang)的(de)(de)情(qing)況下如(ru)何操(cao)作,也就是(shi)當多個用(yong)戶共同(tong)使用(yong)、操(cao)作一(yi)個文件的(de)(de)情(qing)況。這(zhe)時,Linux通(tong)常采用(yong)的(de)(de)方法是(shi)給文件上鎖,來(lai)避免共享(xiang)的(de)(de)資源產生競爭(zheng)的(de)(de)狀態。

    文(wen)件(jian)鎖(suo)(suo)包括建(jian)議(yi)性(xing)鎖(suo)(suo)和(he)強(qiang)制性(xing)鎖(suo)(suo)。建(jian)議(yi)性(xing)鎖(suo)(suo)要求(qiu)每(mei)個上(shang)鎖(suo)(suo)文(wen)件(jian)的進程(cheng)都要檢(jian)查(cha)是(shi)(shi)否有(you)鎖(suo)(suo)存(cun)(cun)在(zai)(zai),并(bing)且尊重已有(you)的鎖(suo)(suo)。在(zai)(zai)一般(ban)情況下,內(nei)核(he)(he)和(he)系統都不使用建(jian)議(yi)性(xing)鎖(suo)(suo)。強(qiang)制性(xing)鎖(suo)(suo)是(shi)(shi)由(you)內(nei)核(he)(he)執行(xing)(xing)的鎖(suo)(suo),當一個文(wen)件(jian)被上(shang)鎖(suo)(suo)進行(xing)(xing)寫(xie)入操(cao)作(zuo)時,內(nei)核(he)(he)將(jiang)阻止其(qi)他任何文(wen)件(jian)對其(qi)進行(xing)(xing)讀寫(xie)操(cao)作(zuo)。采用強(qiang)制性(xing)鎖(suo)(suo)對性(xing)能(neng)的影響很大,每(mei)次讀寫(xie)操(cao)作(zuo)都必須(xu)檢(jian)查(cha)是(shi)(shi)否有(you)鎖(suo)(suo)存(cun)(cun)在(zai)(zai)。

    在(zai)Linux中,實(shi)現文(wen)件上鎖(suo)(suo)的函數有lockf()和fcntl(),其中lockf()用于對文(wen)件施(shi)加建議性鎖(suo)(suo),而fcntl()不僅(jin)可(ke)以施(shi)加建議性鎖(suo)(suo),還(huan)可(ke)以施(shi)加強(qiang)制性鎖(suo)(suo)。同(tong)時,fcntl()還(huan)能對文(wen)件的某一(yi)記(ji)錄上鎖(suo)(suo),也就(jiu)是(shi)記(ji)錄鎖(suo)(suo)。

    記錄鎖(suo)(suo)(suo)(suo)又(you)可分(fen)為(wei)讀(du)取(qu)鎖(suo)(suo)(suo)(suo)和(he)寫入鎖(suo)(suo)(suo)(suo),其中讀(du)取(qu)鎖(suo)(suo)(suo)(suo)又(you)稱為(wei)共享(xiang)鎖(suo)(suo)(suo)(suo),它能(neng)(neng)夠使多個(ge)(ge)進(jin)程(cheng)(cheng)都能(neng)(neng)在文(wen)(wen)件(jian)(jian)的同一(yi)(yi)部分(fen)建立讀(du)取(qu)鎖(suo)(suo)(suo)(suo)。而寫入鎖(suo)(suo)(suo)(suo)又(you)稱為(wei)排(pai)斥鎖(suo)(suo)(suo)(suo),在任何時刻只能(neng)(neng)有一(yi)(yi)個(ge)(ge)進(jin)程(cheng)(cheng)在文(wen)(wen)件(jian)(jian)的某個(ge)(ge)部分(fen)建立寫入鎖(suo)(suo)(suo)(suo)。當然(ran),在文(wen)(wen)件(jian)(jian)的同一(yi)(yi)部分(fen)不能(neng)(neng)同時建立讀(du)取(qu)鎖(suo)(suo)(suo)(suo)和(he)寫入鎖(suo)(suo)(suo)(suo)。

    fcntl()函(han)數(shu)具有(you)很(hen)豐(feng)富的(de)功(gong)能,它可以對(dui)已打開的(de)文件描述符(fu)進行各種操作,不僅包括管理(li)文件鎖(suo)(suo),還包括獲得設置(zhi)文件描述符(fu)和文件描述符(fu)標志、文件描述符(fu)的(de)復制等(deng)很(hen)多功(gong)能。本節主要介紹fcntl()函(han)數(shu)建立記錄(lu)鎖(suo)(suo)的(de)方法,關(guan)于它的(de)其(qi)他操作,感興趣的(de)讀者可以參看fcntl手冊。

    2.fcntl()函(han)數格式(shi)

    用于建立記(ji)錄鎖的fcntl()函數語法要(yao)點如表2.6所示。

表2.6 fcntl()函數語法要(yao)點

所需頭文件 #include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
函數原型 int fcntl(int fd, int cmd, struct flock *lock)
函數傳入值 fd:文件描述符
cmd F_DUPFD:復制文件描述符
F_GETFD:獲得fd的close-on-exec標志,若標志未設置,則文件經過exec()函數之后仍保持打開狀態
F_SETFD:設置close-on-exec標志,該標志由參數arg的FD_CLOEXEC位決定
F_GETFL:得到open設置的標志
F_SETFL:改變open設置的標志
F_GETLK:根據lock描述,決定是否上文件鎖
F_SETLK:設置lock描述的文件鎖
F_SETLKW:這是F_SETLK的阻塞版本(命令名中的W表示等待(wait))。
在無法獲取鎖時,會進入睡眠狀態;如果可以獲取鎖或者捕捉到信號則會返回
lock:結構為flock,設置記錄鎖的具體狀態,后面會詳細說明
函數返回值 成功:0
1:出錯

    這里,lock的結構如下所示(shi):

    struct flock
    {
        short l_type;
        off_t l_start;
        short l_whence;
        off_t l_len;
        pid_t l_pid;
    }

 &nbsp;  lock結構中(zhong)每個變(bian)量(liang)的取(qu)值含義(yi)如表2.7所示。

表(biao)2.7 lock結(jie)構變量取值

l_type F_RDLCK:讀取鎖(共享鎖)
F_WRLCK:寫入鎖(排斥鎖)
F_UNLCK:解鎖
l_start 加鎖區域在文件中的相對位移量(字節),與l_whence值一起決定加鎖區域的起始位置
l_whence:
相對位移量的起點(同lseek的whence)
SEEK_SET:當前位置為文件的開頭,新位置為偏移量的大小
SEEK_CUR:當前位置為文件指針的位置,新位置為當前位置加上偏移量
SEEK_END:當前位置為文件的結尾,新位置為文件的大小加上偏移量的大小
l_len 加鎖區域的長度

    為(wei)(wei)加鎖整個文件(jian),通常(chang)的方法是將l_start設(she)置(zhi)(zhi)為(wei)(wei)0,l_whence設(she)置(zhi)(zhi)為(wei)(wei)SEEK_SET,l_len設(she)置(zhi)(zhi)為(wei)(wei)0。

 ;   3.fcntl()使(shi)用(yong)實(shi)例

    下面首先(xian)給出了使(shi)用fcntl()函數(shu)的(de)(de)文件記(ji)錄鎖功(gong)能的(de)(de)代(dai)碼實(shi)現。在(zai)該代(dai)碼中(zhong),首先(xian)給flock結構體的(de)(de)對應位(wei)賦予相應的(de)(de)值。

    接著(zhu)調用兩次fcntl()函數。用F_GETLK命令判(pan)斷(duan)是(shi)否(fou)可以進行(xing)flock結構所描述的(de)鎖(suo)操(cao)作:若(ruo)可以進行(xing),則flock結構的(de)l_type會被設(she)置為F_UNLCK,其他域(yu)不(bu)變;若(ruo)不(bu)可進行(xing),則l_pid被設(she)置為擁有文件鎖(suo)的(de)進程號,其他域(yu)不(bu)變。

  &nbsp; 用F_SETLK和F_SETLKW命令設置flock結構所(suo)描(miao)述(shu)的(de)鎖操(cao)作(zuo),后(hou)者是前者的(de)阻塞版。

    當(dang)第(di)一次調用fcntl()時(shi),使(shi)用F_GETLK命(ming)令(ling)獲得(de)當(dang)前文件被上(shang)鎖(suo)的情況,由此可以判斷能(neng)不(bu)能(neng)進(jin)(jin)行(xing)(xing)上(shang)鎖(suo)操(cao)作(zuo);當(dang)第(di)二次調用fcntl()時(shi),使(shi)用F_SETLKW命(ming)令(ling)對(dui)指(zhi)定(ding)文件進(jin)(jin)行(xing)(xing)上(shang)鎖(suo)/解鎖(suo)操(cao)作(zuo)。因(yin)為F_SETLKW命(ming)令(ling)是(shi)阻塞(sai)式操(cao)作(zuo),所以,當(dang)不(bu)能(neng)把上(shang)鎖(suo)/解鎖(suo)操(cao)作(zuo)進(jin)(jin)行(xing)(xing)下(xia)去(qu)時(shi),運行(xing)(xing)會被阻塞(sai),直到(dao)能(neng)夠(gou)進(jin)(jin)行(xing)(xing)操(cao)作(zuo)為止。

    文件(jian)記錄鎖(suo)的功能代碼(ma)具(ju)體如(ru)下所示:

    /* lock_set.c */
    int lock_set(int fd, int type)
    {
        struct flock old_lock, lock;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        lock.l_type = type;
        lock.l_pid = -1;

        /* 判斷文件是否可以上鎖 */
        fcntl(fd, F_GETLK, &lock);
        if (lock.l_type != F_UNLCK)
        {
            /* 判斷文件不能上鎖的原因 */
            if (lock.l_type == F_RDLCK) /* 該文件已有讀取鎖 */
            {
                printf("Read lock already set by %d\n", lock.l_pid);
            }
            else if (lock.l_type == F_WRLCK) /* 該文件已有寫入鎖 */
            {
                printf("Write lock already set by %d\n", lock.l_pid);
            }
        }

        /* l_type 可能已被F_GETLK修改過 */
        lock.l_type = type;
        /* 根據不同的type值進行阻塞式上鎖或解鎖 */
        if ((fcntl(fd, F_SETLKW, &lock)) < 0)
        {
            printf("Lock failed:type = %d\n", lock.l_type);
            return 1;
        }

        switch(lock.l_type)
        {
            case F_RDLCK:
            {
                printf("Read lock set by %d\n", getpid());
            }
            break;
            case F_WRLCK:
            {
                printf("Write lock set by %d\n", getpid());
            }
            break;
            case F_UNLCK:
            {
                printf("Release lock by %d\n", getpid());
                return 1;
            }
            break;
            default:
            break;
        }/* end of switch */
        return 0;
    }

    下面(mian)的實例是文件寫入(ru)(ru)鎖的測試用(yong)例,這(zhe)里首先創建了一個hello文件,之(zhi)后(hou)(hou)對其(qi)上寫入(ru)(ru)鎖,后(hou)(hou)釋放寫入(ru)(ru)鎖。代碼如下所示(shi):

    /* write_lock.c */
    #include <unistd.h>
    #include <sys/file.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "lock_set.c"

    int main(void)
    {
        int fd;

        /* 首先打開文件 */
        fd = open("hello",O_RDWR | O_CREAT, 0644);
        if(fd < 0)
        {
            printf("Open file error\n");
            exit(1);
        }

        /* 給文件上寫入鎖 */
        lock_set(fd, F_WRLCK);
        getchar();
        /* 給文件解鎖 */
        lock_set(fd, F_UNLCK);
        getchar();
        close(fd);
        exit(0);
    }

    為(wei)了(le)能(neng)夠使(shi)用多(duo)個終(zhong)端(duan)(duan),更好地(di)顯示寫入(ru)鎖的(de)作用,本實例主要在(zai)PC上測試,讀者(zhe)可將(jiang)其交(jiao)叉編譯,下載到目標板上運(yun)行。下面是在(zai)PC上的(de)運(yun)行結(jie)果(guo)。為(wei)了(le)使(shi)程(cheng)序(xu)有較大(da)的(de)靈活性,筆者(zhe)采用文件上鎖后由(you)用戶輸(shu)入(ru)任意鍵使(shi)程(cheng)序(xu)繼續運(yun)行。建(jian)議讀者(zhe)開啟(qi)兩(liang)個終(zhong)端(duan)(duan),并(bing)且(qie)在(zai)兩(liang)個終(zhong)端(duan)(duan)上同時運(yun)行該程(cheng)序(xu),以達到多(duo)個進程(cheng)操作一(yi)個文件的(de)效果(guo)。在(zai)這里,筆者(zhe)首先(xian)運(yun)行終(zhong)端(duan)(duan)一(yi),請讀者(zhe)注意終(zhong)端(duan)(duan)二(er)中的(de)第一(yi)句。

    終(zhong)端一:

    $ ./write_lock
    write lock set by 4994
  ;  release lock by 4994

    終端二:

    $ ./write_lock
    write lock already set by 4994
    write lock set by 4997
    release lock by 4997 

&nbsp;   由此(ci)可見,寫入鎖(suo)為互(hu)斥鎖(suo),同一時刻只能有一個(ge)寫入鎖(suo)存在。

    接下來的(de)程序是文件讀(du)取鎖的(de)測(ce)試(shi)用例,原理與上面的(de)程序一樣。

    /* fcntl_read.c */
    #include <unistd.h>
    #include <sys/file.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "lock_set.c"

    int main(void)
    {
        int fd;
        fd = open("hello",O_RDWR | O_CREAT, 0644);
        if(fd < 0)
        {
            printf("Open file error\n");
            exit(1);
        }

        /* 給文件上讀取鎖 */
        lock_set(fd, F_RDLCK);
        getchar();
        /* 給文件解鎖 */
        lock_set(fd, F_UNLCK);
        getchar();
        close(fd);
        exit(0);
    }

 &nbsp;  同樣開啟(qi)(qi)兩(liang)個終(zhong)端,并首先啟(qi)(qi)動終(zhong)端一上的(de)程序,其(qi)運行(xing)結果如下所示。

    終端一:

    $ ./read_lock
    read lock set by 5009
    release lock by 5009

    終端二:

    $ ./read_lock
    read lock set by 5010
 &nbsp;  release lock by 5010

    讀(du)者可(ke)以將此結(jie)果與寫入(ru)鎖(suo)的運(yun)行(xing)結(jie)果相比較,可(ke)以看出,讀(du)取鎖(suo)為共(gong)享鎖(suo),當進程5009已設置(zhi)讀(du)取鎖(suo)后,進程5010仍然可(ke)以設置(zhi)讀(du)取鎖(suo)。

    本文選自華清遠見嵌入式培訓教材《從實踐中學嵌入式Linux應用程序開發》

   熱點(dian)鏈接:

   1、底層文件I/O操作的系統調用
   2、Linux中的文件及文件描述符
   3、Linux文件系統之虛擬文件系統(VFS)
   4、嵌入式文件系統構建
   5、Linux系統調用及用戶編程接口(API)

更多新聞>>