文件鎖--fcntl函數

當多個用戶共同使用、操作一個文件的情況下,這時,Linux通常採用的方法是給文件上鎖,來避免共享的資源產生競爭的狀態。

文件鎖包括建議性鎖和強制性鎖。

建議性鎖要求每個上鎖文件的進程都要檢查是否有鎖存在,並且尊重已有的鎖。在一般情況下,內核和系統都不使用建議性鎖。

強制性鎖是由內核執行的鎖,當一個文件被上鎖進行寫入操作的時候,內核將阻止其它任何文件對其進行讀寫操作。採用強制性鎖對性能的影響很大,每次讀寫操作都必須檢查是否有鎖存在。

Linux中,實現文件上鎖的函數有lockfcntl,其中flock用於對文件施加建議性鎖,而fcntl不僅可以施加建議性鎖,還可以施加強制性鎖,還能對文件的某一記錄進行上鎖,也就是記錄鎖。

記錄鎖又分爲讀取鎖和寫入鎖。

讀取鎖又稱共享鎖,能使多個進程都在文件的同一部分建立讀取鎖。

寫入鎖又稱爲排斥鎖,在任何時刻只能有一個進程在文件的某個部分建立寫入鎖。

在文件的同一部分不能同時建立讀取鎖和寫入鎖。

2fcntl函數格式

Fcntl函數語法要點:

所需頭文件:#include<sys/types.h>

                    #include<unistd.h>

                    #include<fcntl.h>

函數原型:int fcntl(int fd,cmd,struct flock *lock)

函數傳入值:fd:文件描述符

                     CmdF_DUPFD:複製文件描述符

F_GETFD:獲得fdclose-on-exec標誌,若標誌未設置,則文件經過exec函數之後仍保持打開狀態。

F_SETFD:設置close-on-exec標誌,該標誌以參數argFD_CLOEXEC位決定。

F_GETFL:得到open設置的標誌

F_SETFL:改變open設置的標誌

F_GETFK:根據lock描述,決定是否上文件鎖

F_SETFK:設置lock描述的文件鎖

F_SETLKW:這是F_SETLK的阻塞版本(命令名中的W表示等待(wait))。如果存在其它鎖,則調用進程睡眠;如果捕捉到信號則睡眠中斷

F_GETOWN:檢索將收到SIGIOSIGURG信號的進程號或進程組號

F_SETOWN:設置進程號或進程組號

                     Lock:結構爲flock,設置記錄鎖的具體狀態

函數返回值:成功:0

                     -1:出錯

Lock的結構如下所示:

Struct flock{

Short l_type;

Off_t l_start;

Short l_whence;

Off_t l_len;

Pid_t l_pid;

}

Lock結構變量取值:

L_typeF_RDLCK:讀取鎖(共享鎖)

              F_WRLCK:寫入鎖(排斥鎖)

              F_UNLCK:解鎖

L_stat:相對位移量(字節)

L_whence:相對位移量的起點(同lseekwhence):SEEK_SET:當前位置爲文件開頭,新位置爲偏移量的大小

                                    SEEK_CUR:當前位置爲文件指針位置,新位置爲當前位置加上偏移量

                                    SEEK_END:當前位置爲文件的結尾,新位置爲文件的大小加上偏移量大小

L_len:加鎖區域長度

3fcntl使用實例

Lock_set函數:

void lock_set(int fd,int type)

{

       struct flock lock;

       lock.l_whence=SEEK_SET;//賦值lock結構體

       lock.l_start=0;

       lock.l_len=0;

       while(1)

       {

              lock.l_type=type;

/*根據不同的type值給文件上鎖或解鎖*/

              if((fcntl(fd,F_SETLK,&lock))==0)

              {

                     if(lock.l_type==F_RDLCK)

                            printf("read lock set by %d\n",getpid());

                     else if(lock.l_type=F_WRLCK)

                            printf("write lock set by %d\n",getpid());

                     else if(lock.l_type=F_UNLCK)

                            printf("release lock set by %d\n",getpid());

                     return;

              }

/*判斷文件是否可以上鎖*/

                     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 already lock set by %d\n", lock.l_pid ());

                            getchar();

                     }

              }

}

/*fcntl_write.c測試文件寫入鎖函數部分*/

#include<unistd.h>

#include<sys/file.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<stdio.h>

#include<stdlib.h>

int main(void)

{

       int fd;

       fd=open("hello",O_RDWR|O_CREAT,0666);

       if(fd<0)

       {

              perror("open");

              exit(1);

       }

       lock_set(fd,F_WRLCK);

       getchar();

       lock_set(fd,F_UNLCK);

       getchar();

       close(fd);

       exit(0);

}


發佈了4 篇原創文章 · 獲贊 1 · 訪問量 9581
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章